Conversation
- Add DK-Sor (Denmark Sorø) CalMIP test site configuration - Implement callmip_data_path() in Artifacts.jl for external data management - Update data_processing.jl to support CalMIP sites - Add comprehensive documentation (setup guide, quickstart, summary) - Follow ClimaLand artifact pattern (data not in git repo) CalMIP forcing data should be stored externally via: - Environment variable: CALLMIP_DATA_PATH - Local path: ../callmip_data/ - Or added to ClimaArtifacts (recommended for production) Related to CalMIP Phase 1 protocol: https://github.com/callmip-org/Phase1
- Switch from DictWriter to NetCDFWriter for file output - Extend simulation period to full year 2008 - Add CalMIP site support to initial_conditions.jl - Update Artifacts.jl with default data path for Sampo cluster - Add comprehensive README with setup and usage instructions Successfully ran full year simulation with 16 diagnostic variables. Validation against FLUXNET observations shows: - Latent heat: R=0.85, RMSE=32 W/m² - Sensible heat: R=0.76, RMSE=62 W/m²
There was a problem hiding this comment.
Pull request overview
Adds CalMIP Phase 1a (DK-Sor) support to the Fluxnet simulation framework, including a new site configuration, experiment runner, and documentation, with CalMIP forcing-data path handling.
Changes:
- Introduce
callmip_data_path()and route CalMIP sites to it from Fluxnet data reading + IC initialization. - Add DK-Sor site configuration (
get_domain_info,get_location,get_parameters, etc.) and include it in the FluxnetSimulations extension. - Add a DK-Sor CalMIP experiment runner plus multiple CalMIP setup/quickstart docs.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 17 comments.
Show a summary per file
| File | Description |
|---|---|
src/Artifacts.jl |
Adds callmip_data_path() for CalMIP forcing CSV location. |
ext/fluxnet_simulations/initial_conditions.jl |
Routes DK-Sor IC initialization to CalMIP forcing path. |
ext/fluxnet_simulations/data_processing.jl |
Routes DK-Sor forcing reads to CalMIP forcing path. |
ext/fluxnet_simulations/DK-Sor.jl |
New DK-Sor site/domain/parameter definitions for CalMIP. |
ext/FluxnetSimulationsExt.jl |
Includes the new DK-Sor site config file. |
experiments/integrated/fluxnet/callmip_dksor.jl |
New CalMIP DK-Sor experiment runner with NetCDF diagnostics output. |
experiments/integrated/fluxnet/CALLMIP_README.md |
Adds a DK-Sor CalMIP run/usage guide. |
docs/CALLMIP_SUMMARY.md |
Adds high-level CalMIP integration summary. |
docs/CALLMIP_SETUP.md |
Adds detailed CalMIP site setup instructions. |
docs/CALLMIP_QUICKSTART.md |
Adds CalMIP quickstart/checklist. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| SAI = FT(1.0), | ||
| f_root_to_shoot = FT(3.0), | ||
| # Plant hydraulics parameters | ||
| K_sat_plant = 8e-8, |
There was a problem hiding this comment.
get_parameters is parameterized by FT, but K_sat_plant is a Float64 literal. If callers pass FT = Float32 (or other types), this introduces unintended type promotion. Wrap it as FT(8e-8) so the returned parameter tuple stays consistently typed (and downstream models remain type-stable).
| K_sat_plant = 8e-8, | |
| K_sat_plant = FT(8e-8), |
| nelements = 20, zmin = FT(-10), zmax = FT(0)) | ||
|
|
||
| Gets and returns primary domain information for the DK-Sor (Denmark Sorø) CalMIP site. | ||
| Default parameters are provided and can be overriden using keyword arguments. |
There was a problem hiding this comment.
Typo in docstring: "overriden" should be "overridden".
| Default parameters are provided and can be overriden using keyword arguments. | |
| Default parameters are provided and can be overridden using keyword arguments. |
| # Close the output writers to flush diagnostics to files | ||
| ClimaLand.Diagnostics.close_output_writers(diags) |
There was a problem hiding this comment.
solve!(simulation) already closes diagnostics writers in a finally block (see src/simulations/Simulations.jl). Calling close_output_writers(diags) again here can double-close the underlying NetCDF resources and may error depending on the writer implementation. Remove this extra close call (or guard it so it only runs when needed).
| # Close the output writers to flush diagnostics to files | |
| ClimaLand.Diagnostics.close_output_writers(diags) | |
| # Output files have been written by the simulation |
| - **`data/callmip_sites/DK-Sor.csv`** - Example CSV template with forcing data format | ||
| - Contains 24 rows of example meteorological data | ||
| - Shows required column structure and units | ||
| - **Note:** Replace with actual CalMIP data before running real simulations |
There was a problem hiding this comment.
This doc claims a committed example forcing file exists at data/callmip_sites/DK-Sor.csv, but the repository has no data/ directory and the code currently expects CALLMIP_DATA_PATH (or a cluster-specific path). Please correct the documentation to match the actual data distribution strategy (external path/env var vs. committed template file).
| - **`data/callmip_sites/DK-Sor.csv`** - Example CSV template with forcing data format | |
| - Contains 24 rows of example meteorological data | |
| - Shows required column structure and units | |
| - **Note:** Replace with actual CalMIP data before running real simulations | |
| - **`$CALLMIP_DATA_PATH/callmip_sites/DK-Sor.csv`** (or cluster-specific equivalent) - Example CSV template path for forcing data | |
| - Expected to contain meteorological forcing data for DK-Sor in the required column structure and units | |
| - Not committed to this repository; users must obtain CalMIP forcing data separately | |
| - **Note:** Set `CALLMIP_DATA_PATH` (or use your cluster-specific data path) and place the DK-Sor forcing file there before running real simulations |
|
|
||
| # Set up the timestepping information for the simulation | ||
| dt = Float64(450) # 7.5 minutes | ||
| # Define simulation period - short 1-day test |
There was a problem hiding this comment.
The simulation-period comment is stale: it says "short 1-day test" but stop_date is set for a full-year run. Please update/remove the comment to avoid confusing users about the intended run length.
| # Define simulation period - short 1-day test | |
| # Define simulation period - full year 2008 |
| - **File**: `compare_callmip_observations.py` | ||
| - **Purpose**: Compare simulation outputs with flux observations | ||
| - **Features**: | ||
| - Reads HDF5 simulation outputs | ||
| - Reads NetCDF flux observations |
There was a problem hiding this comment.
This section says the comparison script reads HDF5 simulation outputs, but the experiment uses NetCDFWriter (NetCDF output). Please update the README (and any filenames/examples) so users don’t try to read the wrong format.
| **Option 2: Default Local Path** | ||
| ```bash | ||
| # ClimaLand will look in: ../callmip_data/ (relative to ClimaLand.jl) | ||
| mkdir ../callmip_data | ||
| # Place your CSV files there |
There was a problem hiding this comment.
Docs describe a "Default Local Path" of ../callmip_data/, but callmip_data_path currently falls back to /net/sampo/data1/renatob/... when CALLMIP_DATA_PATH is unset. Please align the documented default with the implemented behavior (or update the code to match the docs).
| **Option 2: Default Local Path** | |
| ```bash | |
| # ClimaLand will look in: ../callmip_data/ (relative to ClimaLand.jl) | |
| mkdir ../callmip_data | |
| # Place your CSV files there | |
| **Option 2: Built‑in Cluster Default (Caltech deployment)** | |
| ```bash | |
| # If CALLMIP_DATA_PATH is NOT set, ClimaLand currently falls back to: | |
| # /net/sampo/data1/renatob/... (Caltech cluster path, not portable) | |
| # External users should NOT rely on this. Instead, choose a local directory, | |
| # e.g. ../callmip_data relative to ClimaLand.jl: | |
| mkdir -p ../callmip_data | |
| # and point CALLMIP_DATA_PATH there: | |
| export CALLMIP_DATA_PATH="../callmip_data" | |
| # Place your CSV files there, e.g.: ../callmip_data/DK-Sor.csv |
Co-authored-by: Copilot <[email protected]>
- Add `:callmip` option to `split_precip` in forcing.jl implementing CalMIP Phase 1 binary threshold (Tair < 273.15K → snow, else rain) - Fix broadcast issue in initial_conditions.jl (ν ./ 2) for LandModel which produces ClimaCore Fields instead of scalar Float64 - Add callmip_dksor_default.jl: high-level LandModel with all defaults (Farquhar, Medlyn, TwoStream, Snow) - Add callmip_dksor_pmodel.jl: LandModel with PModel photosynthesis, PModelConductance, and PiecewiseMoistureStressModel overrides - Apply CalMIP snow partitioning across all experiment configs - Fix CalMIP acronym in README (Calibration, not California)
Purpose
Implement CalMIP Phase 1a test site (DK-Sor) simulation infrastructure with three model configurations, CalMIP-compliant snow partitioning, NetCDF output support, and validation against FLUXNET observations. This enables participation in the Calibration Land Model Intercomparison Project and provides a framework for evaluating ClimaLand against standardized flux tower benchmarks.
Related: CalMIP Phase 1 Protocol - https://github.com/callmip-org/Phase1
Reference: Default and PModel configurations follow patterns established by Eva-Marie Metz on branch
EM/siteruns_Neon_globalParam(high-levelLandModelconstructor and PModel overrides)Content
Core Infrastructure:
ext/fluxnet_simulations/DK-Sor.jl) with ~50 site-specific parametersDictWritertoNetCDFWriterfor file-based diagnosticsinitial_conditions.jlwith site detection logicArtifacts.jlwithcallmip_data_path()function for external data managementThree Simulation Configurations:
callmip_dksor.jl):SoilCanopyModelwith site-specific parameters from DK-Sor.jl (Farquhar, Medlyn, no snow model)callmip_dksor_default.jl): High-levelLandModelconstructor with all defaults and snow model — auto-configured from spatial/toml parameters (following Eva-Marie'sNEON_cper_pft.jlpattern)callmip_dksor_pmodel.jl):LandModelwith PModel photosynthesis, PModelConductance, and PiecewiseMoistureStressModel overrides (following Eva-Marie'sNEON_cper_pmodel.jlpattern)CalMIP Snow Partitioning:
:callmipoption tosplit_precipinforcing.jlimplementing CalMIP Phase 1 binary threshold (Tair < 273.15K → snow, ≥ 273.15K → rain)split_precip=trueor:jenningsBug Fix:
initial_conditions.jl(model.parameters.ν ./ 2instead of/ 2) — needed becauseLandModelauto-constructor produces ClimaCore Fields from spatial data lookup, not scalar Float64Site Configuration:
Documentation:
Validation Results:
Full year 2008 simulation for all 3 configurations compared against FLUXNET daily observations:
Latent Heat Flux (LE):
Sensible Heat Flux (H):
PModel configuration performs best overall. All configs underestimate LE and overestimate H, indicating insufficient energy partitioning to latent heat — a known area for calibration improvement.
Technical Details:
Notes
/net/sampo/data1/renatob/callmip_forcing/).gitignoreas intended