Localized V2 rewrite for this language is in progress. Showing English-first content for now.
Science Workflow

Climate Science

Climate modeling with uncertainty propagation for robust predictions

Back to Science Hub

Climate Science with Sounio

Sounio enables climate modeling with rigorous uncertainty quantification for policy-relevant projections.

The Uncertainty Challenge

Climate science involves multiple uncertainty sources:

  • Initial condition sensitivity
  • Model structural uncertainty
  • Parameter uncertainty
  • Scenario uncertainty
  • Observation errors

Communicating these uncertainties clearly is critical for policy decisions.

Temperature Projections with Uncertainty

use std::units::{celsius, year, W_per_m2}
use std::epistemic::{Knowledge, measure}

struct ClimateProjection {
    temperature: Knowledge<celsius>,
    forcing: Knowledge<W_per_m2>,
    year: year,
    scenario: String,
}

fn project_temperature(
    baseline: Knowledge<celsius>,
    forcing: Knowledge<W_per_m2>,
    sensitivity: Knowledge<celsius_per_doubling>
) -> Knowledge<celsius> {
    // Simple energy balance model
    let delta_t = sensitivity * ln(forcing / 280.0) / ln(2.0)

    baseline + delta_t
    // Uncertainty from all inputs propagates automatically
}

Ensemble Analysis

fn analyze_ensemble(
    models: Vec<ClimateModel>,
    scenario: EmissionScenario
) -> EnsembleResult with IO {
    var projections = vec![]

    for model in models {
        let projection = model.run(scenario)
        projections.push(Knowledge {
            value: projection.temperature,
            uncertainty: model.internal_variability,
            provenance: vec![model.name, model.version],
            confidence: model.validation_score,
        })

        perform IO::log(
            model.name + ": " +
            projection.temperature.to_string() + " K"
        )
    }

    // Multi-model mean with uncertainty
    let ensemble_mean = weighted_mean(projections, |p| p.confidence)

    // Include model spread in uncertainty
    let model_spread = projections.std_dev()
    let total_uncertainty = (
        ensemble_mean.uncertainty.pow(2) +
        model_spread.pow(2)
    ).sqrt()

    EnsembleResult {
        mean: Knowledge {
            value: ensemble_mean.value,
            uncertainty: total_uncertainty,
            confidence: ensemble_mean.confidence,
            provenance: projections.flat_map(|p| p.provenance).collect(),
        },
        range: (projections.min(), projections.max()),
        n_models: models.len(),
    }
}

Confidence-Gated Policy Advice

fn assess_risk(
    projection: Knowledge<celsius>,
    threshold: celsius
) -> RiskAssessment with IO {
    // Probability of exceeding threshold
    let exceedance_prob = 1.0 - normal_cdf(
        threshold,
        projection.value,
        projection.uncertainty
    )

    if projection.confidence > 0.90 {
        if exceedance_prob > 0.66 {
            RiskAssessment::Likely("Threshold likely to be exceeded")
        } else if exceedance_prob > 0.33 {
            RiskAssessment::Possible("Threshold may be exceeded")
        } else {
            RiskAssessment::Unlikely("Threshold unlikely to be exceeded")
        }
    } else {
        perform IO::warn("Low model confidence - assessment uncertain")
        RiskAssessment::Uncertain("Insufficient model agreement")
    }
}

Sea Level Rise Modeling

fn project_sea_level(
    thermal_expansion: Knowledge<mm>,
    ice_sheet_contribution: Knowledge<mm>,
    glacier_melt: Knowledge<mm>
) -> Knowledge<mm> {
    // Components sum with correlated uncertainties
    let total = thermal_expansion + ice_sheet_contribution + glacier_melt

    // Ice sheet has fat-tailed uncertainty
    let adjusted = total.with_distribution(
        Distribution::SkewNormal(
            location: total.value,
            scale: total.uncertainty,
            shape: 2.0  // Right-skewed for ice sheet instability
        )
    )

    adjusted
}

Regional Downscaling

fn downscale_projection(
    global: Knowledge<celsius>,
    region: Region,
    historical: Vec<Observation>
) -> Knowledge<celsius> with IO {
    // Statistical downscaling with uncertainty
    let pattern = compute_scaling_pattern(historical, region)

    let regional = global * pattern.scaling_factor

    // Add downscaling uncertainty
    let total_uncertainty = (
        regional.uncertainty.pow(2) +
        pattern.uncertainty.pow(2)
    ).sqrt()

    if pattern.confidence < 0.80 {
        perform IO::warn(
            "Limited historical data for " + region.name +
            " - downscaling uncertainty may be underestimated"
        )
    }

    Knowledge {
        value: regional.value,
        uncertainty: total_uncertainty,
        confidence: regional.confidence * pattern.confidence,
        provenance: regional.provenance.append("downscaled_" + region.name),
    }
}

Features for Climate Science

  • Ensemble handling: Combine multiple model outputs
  • IPCC-compatible: Likelihood language support
  • Uncertainty decomposition: Separate sources of uncertainty
  • Provenance tracking: Full model lineage
  • Unit safety: Prevents common unit errors

Data Format Support

  • NetCDF native support
  • CMIP6 data structures
  • BIDS-like metadata conventions

Get Started

sounio new climate-project --template climate
cd climate-project
sounio run examples/temperature_projection.sio