Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
8e3d6e4
Fix entry_points() compatibility for Python 3.9-3.12
JanStreffing Mar 30, 2026
a4f855f
fix(cmip7): Load DataRequest from CMIP7_DReq_metadata instead of cmip…
JanStreffing Mar 30, 2026
61c1e9a
docs: Improve reproduction section with actual debugging experience
JanStreffing Mar 30, 2026
f952af4
docs: Clarify what's fixed vs architectural issues that remain
JanStreffing Mar 30, 2026
edd3d82
Refactor CMIP7 to use native compound name architecture
JanStreffing Mar 30, 2026
5617a18
style: run black from project root to fix all formatting issues
JanStreffing Apr 2, 2026
0ac7a3e
Merge origin/prep-release into fix/cmip7-pipeline-fixes
JanStreffing Apr 2, 2026
936c996
fix: Remove unused json and Path imports from test file
JanStreffing Apr 2, 2026
5104773
style: reformat with black 24.8.0 for CI compatibility
JanStreffing Apr 2, 2026
27c092c
adding minimal example for awiesm3-veg-hr
JanStreffing Apr 2, 2026
822dd58
fix: namespace-prefix config dict keys so YAML pycmor section is resp…
JanStreffing Apr 2, 2026
18a10b9
fix: pipeline cluster assignment bugs and use fixed SLURM scaling
JanStreffing Apr 2, 2026
9efaa84
add CMIP7 ocean variable rules, fx pipelines, and namelist changes (u…
JanStreffing Apr 3, 2026
b28dbf2
WIP: add mass transport, zostoga pipelines and gsw density support
JanStreffing Apr 3, 2026
010090f
style: reformat custom_steps.py with black 24.8.0
JanStreffing Apr 3, 2026
e398f75
WIP: add CMIP7 sea ice variable rules, pipelines, and example config …
JanStreffing Apr 3, 2026
0ecb485
adding wip namelist.io
JanStreffing Apr 3, 2026
6cd1624
Merge remote-tracking branch 'origin/prep-release' into feat/cmip7-aw…
JanStreffing Apr 3, 2026
b90ee82
WIP: add CAP7 sea ice rules, custom steps, and restructure configs wi…
JanStreffing Apr 3, 2026
771d486
WIP: add CAP7 ocean rules, custom steps, and variable todo tracking
JanStreffing Apr 3, 2026
7e23b03
WIP: add 6 more CAP7 ocean rules (vsf, volcello, masscello_dec, volce…
JanStreffing Apr 3, 2026
2a2e318
WIP: add rules for variables needing namelist.io additions (evspsbl, …
JanStreffing Apr 3, 2026
d5b5be6
WIP: add pycmor rules and namelist.io entries for new FESOM2 tendency…
JanStreffing Apr 3, 2026
6ea0ec2
Fix namelist.io for FESOM2 single-frequency constraint and enable dai…
JanStreffing Apr 3, 2026
423c818
Enable daily ocean rules (tos_day, sos_day, zos_day) and clean up sta…
JanStreffing Apr 3, 2026
e33cc3c
Enable thkcello rule and clean up stale namelist.io comments
JanStreffing Apr 3, 2026
9cd6ed9
Add time-varying masscello rule (Omon): rho_0 * hnode via scale_pipeline
JanStreffing Apr 3, 2026
ff39366
Add complete CMIP7 atmosphere CMORization: 76 rules covering all core…
JanStreffing Apr 4, 2026
771ef9b
Add complete CMIP7 land CMORization: 11 core rules, 6 deferred to cap…
JanStreffing Apr 5, 2026
cb40985
Fix grid metadata: TCo319 interpolated to 0.25deg regular grid, 25 km
JanStreffing Apr 5, 2026
fa6dc78
co2 field output conditional
JanStreffing Apr 7, 2026
9e5036f
missing.md renamed to missing_from_namelist.io.md
JanStreffing Apr 7, 2026
ead88b3
Delete CMIP7_ARCHITECTURE_ISSUE.md
JanStreffing Apr 7, 2026
0478640
Add CMIP7 veg_atm CMORization: 27 rules for atmosphere, aerosol, and …
JanStreffing Apr 8, 2026
2e32137
Add CMIP7 veg_land CMORization: 58 rules, fix deaccumulation to 1h
JanStreffing Apr 8, 2026
00deaed
Add CMIP7 veg_seaice CMORization: daily sisnhc from m_snow/a_ice
JanStreffing Apr 8, 2026
cb24d2e
Add CMIP7 extra_land CMORization: 13 rules for PFT fractions, hydrolo…
JanStreffing Apr 8, 2026
d4c74fb
Add CMIP7 extra_atm CMORization: 21 rules for 1hr/3hr/daily/monthly a…
JanStreffing Apr 8, 2026
17447bb
Implement 3 cap7_land variables from LPJ-GUESS: evspsblsoi, evspsblve…
JanStreffing Apr 8, 2026
b02b096
Fix black formatting in custom_steps.py
JanStreffing Apr 8, 2026
ea6c846
Implement remaining 3 cap7_land fx variables from IFS static fields
JanStreffing Apr 8, 2026
21cbd68
Add annual data volume estimation script for CMIP7 AWI-ESM3-VEG-HR
JanStreffing Apr 8, 2026
84a380b
Expand top rules to 50 and add tier column to volume estimate script
JanStreffing Apr 8, 2026
3cc0e7b
Fix XIOS crash: move zg and hur fields from 2D_physical to 3D_pl group
JanStreffing Apr 8, 2026
66400b4
Rename cap7 to lrcs across all files, directories, and references
JanStreffing Apr 8, 2026
3b14cf4
Implement 58 cap7_atm variables: daily radiation/fluxes, 6hr ml+plev7…
JanStreffing Apr 8, 2026
37db4c4
Implement cap7_ocean (2 rules) and update cap7_atm for unfiltered CSVs
JanStreffing Apr 8, 2026
f2bb98b
Implement 9 cap7_seaice rules, add friver to cap7_ocean, update namel…
JanStreffing Apr 8, 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
7 changes: 7 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ Key features:

## Development Commands

### Environment Setup
```bash
# Load conda environment
source ~/loadconda.sh
conda activate pycmor_py312
```

### Installation

#### Using pip (traditional)
Expand Down
186 changes: 186 additions & 0 deletions awi-esm3-veg-hr-variables/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
# AWI-ESM3-VEG-HR CMIP7 Variable Configuration

CMIP7 CMORization configuration for AWI-ESM3-VEG-HR.

## Model Configuration

Reference runtime: `AWI-ESM3-VEG-HR-CMIP7-Spinup_cont2` (awiesm3-v3.4.1)

### OpenIFS (IFS CY48R1)
- **Resolution**: TCo319 spectral, L91 vertical levels
- **Output grid**: 0.25deg regular (1440x720), interpolated via XIOS/FullPos
- **Time step**: 900 s
- **Radiation**: ecRad, called every 3 hours
- **Land surface**: HTESSEL (4-layer soil, snow scheme, Farquhar photosynthesis)
- **Aerosol**: MACv2-SP simple plumes (no CAMS, no M7)
- **CO2**: concentration-driven (no prognostic CO2 tracer)
- **Wave model**: WAM (2-way coupled)
- **I/O**: XIOS 2.5-ece

### FESOM 2.6
- **Mesh**: DARS unstructured (~3.1M surface nodes, ~10 km nominal)
- **Vertical**: 56 z-levels (57 interfaces), linear free surface
- **Sea ice**: Built-in single-category, mEVP rheology, melt ponds enabled
- **Diagnostics**: ldiag_cmor=.true. (CMIP scalar diagnostics)

### LPJ-GUESS 4.1.2
Config from `global.ins` via `run_coupled_4_1_2.ins`:
- **Fire model**: BLAZE (uses SIMFIRE internally for burned area prediction)
- **BVOC**: disabled (ifbvoc=0)
- **Nitrogen cycle**: enabled (ifnlim=1, ifcentury=1)
- **Land cover**: natural vegetation only (run_landcover=0)
- **Methane**: disabled (ifmethane=0)
- **Vegetation mode**: cohort, npatch=15
- **PFTs**: 12 global + 8 arctic shrub/tundra (~20 active natural PFTs)
- **CO2**: concentration-driven via OASIS coupling from atmosphere
- **CMIP output**: extensive monthly + yearly .out files (166 output files defined in `lpjg_output.ins`)
- **Output format**: plain-text .out files (no XIOS)
- **Coupling to IFS**: daily via OASIS-MCT (sends LAI, veg type/fraction; receives T, precip, radiation, soil state)

### Coupling (OASIS3-MCT 5.0)
- **Atm-Ocean**: 2-hourly (7200 s)
- **Atm-Vegetation**: daily (86400 s)
- **Runoff mapping**: rnfmap v1.1

### Ice Sheet
- **No interactive ice sheet model** (no PISM, no Yelmo, no BISICLES)
- IFS prescribes glaciated areas as grid cells with 10 m water mass equivalent
- Greenland/Antarctic ice sheets are static boundary conditions

### What this model does NOT have
- No interactive ice sheet model
- No prognostic aerosol (no CAMS, no M7 -- only MACv2-SP prescribed plumes)
- No atmospheric chemistry
- No interactive ozone (O3 prescribed from climatology, not prognostic)
- No CO2 tracer (concentration-driven)
- No ice thickness distribution (single-category sea ice)
- No icebergs
- No methane cycle
- No BVOC emissions

## XIOS XML Configuration (top level)

These files configure the OpenIFS/XIOS output pipeline. XIOS expressions handle unit conversions, deaccumulation, and sign flips at output time so pycmor only needs to add metadata.

| File | Purpose |
|------|---------|
| `iodef.xml` | XIOS top-level entry point, references context files |
| `context_ifs.xml.j2` | IFS XIOS context, includes all `*_def.xml` and `file_def` |
| `field_def_cmip7.xml` | All CMIP7 field definitions: raw IFS fields + derived expressions |
| `file_def_oifs_cmip7_spinup.xml.j2` | Output file definitions: fields, frequencies, operations (average/instant/min/max) |
| `axis_def.xml` | Vertical axes: plev19, plev3 (850/500/250 hPa), model levels |
| `grid_def.xml` | Grids: regular_sfc, regular_pl, regular_pl3, regular_ml |
| `domain_def.xml.j2` | Domain definitions for reduced Gaussian to regular grid interpolation |

## FESOM Configuration (top level)

| File | Purpose |
|------|---------|
| `namelist.io` | FESOM2 I/O namelist: ocean + sea-ice output variables and frequencies |

## Per-realm Subdirectories

Each subdirectory contains:
- **CSV files** -- CMIP7 Data Request variables for that realm (from CMIP7_DReq_Software)
- **YAML file** -- pycmor rules mapping model output to CMOR-compliant files
- **TODO file** -- implementation status, blockers, research notes, and OIFS source investigation

### Core (CMIP7 mandatory variables)

| Directory | Realm | Model | Rules | Variables | Key notes |
|-----------|-------|-------|-------|-----------|-----------|
| `core_atm/` | Atmosphere | OpenIFS | 76 | 45 unique | Monthly/daily/sub-daily (3hr, 6hr, 1hr); surface, plev19, plev3, model levels |
| `core_land/` | Land | OpenIFS/HTESSEL | 11 | 11 | XIOS-derived + pipeline-computed; 6 variables deferred to lrcs_land |
| `core_ocean/` | Ocean | FESOM 2.6 | 25 | 25 | Monthly 2D/3D, daily, fx; includes mass transport and zostoga pipelines |
| `core_seaice/` | Sea Ice | FESOM 2.6 | 9 | 8 unique | Monthly + daily siconc; velocity rotation via vec_autorotate |

### LRCS (additional priority variables)

| Directory | Realm | Model | Rules | Key notes |
|-----------|-------|-------|-------|-----------|
| `lrcs_ocean/` | Ocean | FESOM 2.6 | 45 | Decadal, yearly tendencies (6 with FESOM source mods), scalar diagnostics; ~12 blocked by basin masks |
| `lrcs_seaice/` | Sea Ice | FESOM 2.6 | 40+ | Heat/salt fluxes, tendencies, melt ponds, stress, hemisphere scalars; some blocked by single-category ice |
| `lrcs_land/` | Land | OIFS/LPJ-GUESS | 6 | 6 deferred variables: 3 from LPJ-GUESS (evspsblsoi, evspsblveg, mrfso), 3 from IFS static fields (sftgif, mrsofc, rootd) |
| `veg_atm/` | Atmos/Aerosol | OpenIFS + LPJ-GUESS | 27 | 38 variables: 27 implemented (3hr rad/flux, plev6, daily snow, lwp, 7 fire emissions), 11 blocked |
| `veg_land/` | Land | OpenIFS/HTESSEL + LPJ-GUESS | 58 | 88 variables: 22 IFS (3hr/day/mon hydrology, snow), 36 LPJ-GUESS (N-cycle, fractions, Lut), 30 blocked |
| `veg_seaice/` | Sea Ice | FESOM 2.6 | 1 | 4 variables: 1 implemented (daily sisnhc from m_snow/a_ice), 3 blocked (2 ITD, 1 missing physics) |
| `extra_land/` | Land | OpenIFS/HTESSEL + LPJ-GUESS | 13 | 19 variables: 2 fx, 7 LPJ-GUESS (PFT fracs, LAI), 3 IFS hydrology, 1 hourly tas; 6 blocked (irrigation, river, root zone) |
| `extra_atm/` | Atmos/Aerosol | OpenIFS | 21 | 43 variables: 13 1hr (fluxes, rad, 30S-90S subsets), 2 3hr, 5 daily, 1 monthly gust; 22 blocked (aerosol/chem, crops, heat index, lightning) |

### CAP7 (high-priority additional variables)

| Directory | Realm | Model | Rules | Key notes |
|-----------|-------|-------|-------|-----------|
| `cap7_atm/` | Atmosphere | OpenIFS | 58 | 233 variables: 79 already in core/veg/extra/lrcs, 58 new (daily radiation/fluxes/precip, 6hr ml+plev7h, 1hr instant, monthly ml); ~96 blocked (17 COSP, 21 tendencies, 9 aerosol, 5 CO2, 4 reff, ~40 IFS source) |
| `cap7_ocean/` | Ocean | FESOM 2.6 | 3 | 43 variables: 26 already in core/lrcs, 3 new (daily tossq, monthly volcello, friver); 14 blocked (no icebergs/SF6/geothermal/bigthetao, basin masks, namelist changes for hfx/hfy/3hr stress) |
| `cap7_seaice/` | Sea Ice | FESOM 2.6 | 9 | 21 variables: 9 already in core/lrcs/veg, 9 new (daily sithick/snd/siu/siv, monthly sieqthick/snw/evspsbl/prra/prsn); 3 blocked (sisali constant, sitempsnic internal, snc single-category) |

## Custom Pipeline Steps

Complex variables that cannot be expressed as XIOS expressions are computed in `../examples/custom_steps.py`.

### Atmosphere pipelines
- **sfcWind**: sqrt(u10^2 + v10^2) from 10u + 10v
- **hurs**: Magnus formula from 2t + 2d
- **huss**: Tetens formula from 2d + sp
- **clwvi**: tclw + tciw (liquid + ice water path)

### Land pipelines
- **snc**: snow cover saturation curve from sd (threshold 15mm water equiv)
- **areacella**: spherical grid cell area from lat/lon coordinates
- **slthick**: constant HTESSEL soil layer thicknesses [0.07, 0.21, 0.72, 1.89] m

### LPJ-GUESS loaders and fire emission pipelines
- **load_lpjguess_monthly**: custom loader for LPJ-GUESS plain-text .out files (Lon/Lat/Year/Jan..Dec)
- **load_lpjguess_yearly**: loader for yearly .out files (Lon/Lat/Year/Total)
- **load_lpjguess_yearly_lut**: loader for yearly Lut .out files (Lon/Lat/Year/psl/crp/pst/urb)
- **load_lpjguess_monthly_lut**: loader for monthly Lut .out files (Lon/Lat/Year/Mth/psl/crp/pst/urb)
- **compute_fire_emission**: converts fFireAll (kgC/m2/s) to species emissions using Andreae (2019) savanna/grassland emission factors (BC, CH4, CO, DMS, OA, SO2, NMVOC)

### Land hydrology/snow custom steps
- **compute_temporal_diff**: temporal differencing for dgw, dsn, dsw, dcw, dslw (daily storage changes)
- **compute_mrtws**: terrestrial water storage summation (soil + snow + skin reservoir)
- **compute_snd**: physical snow depth from SWE and snow density (sd*1000/rsn)
- **compute_mrsow**: total soil wetness ratio (weighted mean swvl / porosity)
- **sum_lpjguess_monthly_files**: load and sum multiple LPJ-GUESS .out files (for c3PftFrac)
- **select_southern_hemisphere**: lat subset for 30S-90S regional variables (orog, tas)

### CAP7 atmosphere custom steps
- **compute_rtmt**: net downward radiative flux at model top (rsdt - rsut + rlds - rlus)
- **extract_single_plevel**: extract single pressure level from multi-level dataset (ta@700hPa, wap@500hPa)

### CAP7 sea ice custom steps
- **compute_snd_from_msnow**: snow depth on ice from m_snow/a_ice (unused after h_snow switched to daily)

### Ocean pipelines
- **zostoga**: global thermosteric sea level via gsw/TEOS-10
- **mass transport** (umo/vmo/wmo): Boussinesq approximation (velocity x rho_0 x cell area)
- **bottom/surface extract**: tob, sob from 3D fields; uos, vos from daily 3D
- **vertical integration**: scint, phcint, opottempmint, somint
- **fx pipelines**: areacello, deptho, sftof, thkcello, masscello, volcello from mesh

### Sea ice pipelines
- **siconc/simpconc**: fraction to percent conversion
- **sispeed**: sqrt(uice^2 + vice^2)
- **sihc/sisnhc**: heat content from ice/snow thickness + thermodynamic constants
- **sisnhc (daily)**: derived from daily m_snow/a_ice (h_snow not available daily)
- **sistressave/sistressmax**: stress invariants from sigma tensor components
- **sitempbot**: freezing temperature from SSS
- **sifb**: freeboard from ice/snow thickness and density ratios
- **ice mass transport**: uice/vice x m_ice
- **hemisphere integrals**: sisnmass N/S from m_snow x cell_area

### FESOM2 source code modifications
Six new diagnostic outputs added to `gen_modules_cmor_diag.F90`:
- opottemptend, opottempdiff, opottemprmadvect (temperature tendencies)
- osalttend, osaltdiff, osaltrmadvect (salinity tendencies)
- rsdoabsorb (shortwave absorption by ocean layer)

## Summary of Implementation Status

| Realm | Core done | Core total | LRCS done | LRCS total | Blocked |
|-------|-----------|------------|-----------|------------|---------|
| Atmosphere | 76 | 76 | -- | -- | 3 items need runtime verification |
| Land | 11 | 17 | 0 | 6 | 3 need OIFS source changes, 3 derivable offline |
| Ocean | 25 | 27 | 45 | ~80 | ~12 need basin masks, ~8 need online diag |
| Sea Ice | 9 | 9 | 40+ | ~70 | ITD/age/ridge tracers not enabled |
37 changes: 37 additions & 0 deletions awi-esm3-veg-hr-variables/axis_def.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<axis_definition>
<!-- Definition of model levels axes -->
<axis_group id="ml_axes" unit="-" positive="up" >
<axis id="model_levels" long_name="vertical model levels" />
<axis id="model_levels_zoom" long_name="vertical model levels zoom" axis_ref="model_levels" >
<zoom_axis index="(0,10)[0 1 2 3 4 23 24 25 26 78 79]" />
</axis>
</axis_group>

<!-- Definition of pressure levels axes -->
<axis_group id="pl_axes" unit="Pa" positive="up" >
<axis id="pressure_levels" long_name="vertical pressure levels" n_glo="19" value="(0,18)[100000.0 92500.0 85000.0 70000.0 60000.0 50000.0 40000.0 30000.0 25000.0 20000.0 15000.0 10000.0 7000.0 5000.0 3000.0 2000.0 1000.0 500.0 100.0]" /> <!--<axis id="pressure_levels" long_name="vertical pressure levels" n_glo="39" value="(0,38)[100000.0 92500.0 85000.0 70000.0 60000.0 50000.0 40000.0 30000.0 25000.0 20000.0 17000.0 15000.0 13000.0 11500.0 10000.0 9000.0 8000.0 7000.0 5000.0 3000.0 2000.0 1500.0 1000.0 700.0 500.0 300.0 200.0 150.0 100.0 70.0 50.0 40.0 30.0 20.0 15.0 10.0 7.0 5.0 3.0]" />-->
<axis id="pressure_levels_zoom" long_name="vertical pressure levels zoom" axis_ref="pressure_levels" >
<zoom_axis index="(0,2)[10 11 12]" />
</axis>
<axis id="pressure_levels_3" long_name="vertical pressure levels plev3" n_glo="3" value="(0,2)[85000.0 50000.0 25000.0]" />
<axis id="pressure_levels_6" long_name="vertical pressure levels plev6 lower troposphere" n_glo="6" value="(0,5)[95000.0 90000.0 85000.0 80000.0 75000.0 70000.0]" />
<axis id="pressure_levels_7h" long_name="vertical pressure levels plev7h" n_glo="7" value="(0,6)[100000.0 92500.0 85000.0 70000.0 50000.0 25000.0 10000.0]" />
</axis_group>

<!-- Definition of theta levels axes -->
<axis_group id="th_axes" unit="K" positive="up" >
<axis id="theta_levels" long_name="vertical theta (potential temperature) levels" n_glo="3" value="(0,2)[300 320 360]" />
<axis id="theta_levels_zoom" long_name="vertical theta (potential temperature) levels zoom" axis_ref="theta_levels" >
<zoom_axis index="(0,1)[0 2]" />
</axis>
</axis_group>

<!-- Definition of PV levels axes -->
<axis_group id="pv_axes" unit="PVU" positive="up" >
<axis id="pv_levels" long_name="vertical potential vorticity (PV) levels" n_glo="2" value="(0,1)[2.e-6 3.e-6]" />
<axis id="pv_levels_zoom" long_name="vertical potential vorticity (PV) levels zoom" axis_ref="pv_levels" >
<!-- <zoom_axis begin="1" n="1" /> -->
<zoom_axis index="(0,0)[1]" />
</axis>
</axis_group>
</axis_definition>
Loading
Loading