Skip to main content

Climate Tipping Point Dynamics - A physically-motivated dynamical systems model for analyzing climate tipping points under various SSP scenarios

Project description

erucakra: A Physically-Motivated Toy Model for Climate Tipping Point Dynamics

DOI PyPI version Python 3.9+ License: MIT Code style: black

A three-variable dynamical system model exhibiting bifurcation behavior for analyzing climate tipping points under IPCC AR6 SSP scenarios.

Model Description

The model describes climate system dynamics through a coupled ordinary differential equation system:

dx/dt = y
dy/dt = x(z - z_crit - x²) - cy
dz/dt = ε(A(t)/A_scale - z - βx²)

Physical Interpretation

Variable Description Physical Analog
x Fast climate variability Interannual oscillations (ENSO-like modes)
y Rate of change of x Momentum in phase space
z Slow accumulated forcing Ocean heat content, ice sheet mass proxy
A(t) External forcing Radiative forcing (W/m²) from SSP scenarios

Bifurcation Dynamics

The system undergoes a supercritical pitchfork bifurcation when z crosses z_crit:

  • z < z_crit: Single stable equilibrium at x = 0 (stable climate)
  • z > z_crit: Bistable regime with equilibria at x = ±√(z - z_crit) (tipped state)

The effective potential governing the fast dynamics:

V(x) = -x²(z - z_crit)/2 + x⁴/4

This creates a double-well potential after tipping, representing irreversible regime shifts.

Parameters

Symbol Description Default Typical Range
c Damping coefficient 0.2 0.1 – 0.5
ε Timescale separation (slow/fast) 0.02 0.01 – 0.05
β Feedback strength (variability → accumulation) 0.8 0.5 – 1.5
z_crit Critical tipping threshold 0.55 0.3 – 0.8
A_scale Global forcing normalization 13.0 W/m²

Normalization Strategy

All scenarios use a global normalization scale (A_scale = 13.0 W/m²) based on the SSP5-8.5 peak forcing. This ensures consistent comparison across scenarios:

Scenario Peak Forcing Normalized Peak
SSP1-2.6 ~3.6 W/m² 0.28
SSP2-4.5 ~5.6 W/m² 0.43
SSP3-7.0 ~11.6 W/m² 0.89
SSP5-8.5 ~13.2 W/m² 1.02

Installation

From PyPI

pip install erucakra

From Source

git clone https://github.com/sandyherho/erucakra.git
cd erucakra
pip install poetry
poetry install

Usage

Command Line Interface

Run a single scenario:

erucakra run --scenario ssp245

Run all scenarios:

erucakra run --all-scenarios

Adjust tipping sensitivity:

# Lower z_crit = more sensitive (tips earlier)
erucakra run --scenario ssp245 --z-crit 0.4

# Higher z_crit = less sensitive (tips later)
erucakra run --scenario ssp370 --z-crit 0.7

Use custom forcing data:

erucakra run --forcing ./my_forcing.csv

Use a configuration file:

erucakra run --config ./configs/custom.yaml

List available scenarios:

erucakra list

Run sensitivity analysis:

erucakra sensitivity --scenario ssp245 --z-crit-min 0.3 --z-crit-max 0.8 --n-samples 10

Python API

from erucakra import ClimateModel, GLOBAL_A_SCALE, DEFAULT_Z_CRIT_ABSOLUTE

# Initialize model with default parameters
model = ClimateModel(
    c=0.2,           # damping
    epsilon=0.02,    # timescale separation
    beta=0.8,        # feedback strength
    z_crit=0.55,     # absolute tipping threshold
)

# Run simulation
results = model.run(
    scenario="ssp370",
    t_end=600.0,
    add_noise=True,
)

# Check results
print(f"Scenario: {results.scenario_info['name']}")
print(f"Tipped: {results.tipped}")
print(f"Max z: {results.max_z:.3f}")
print(f"z_crit: {results.z_crit:.3f}")
print(f"First crossing: Year {results.first_crossing_year}")

# Export outputs
results.to_csv("output.csv")
results.to_netcdf("output.nc")
results.to_png("timeseries.png")
results.to_gif("phase_space.gif")

Analyzing Multiple Scenarios

from erucakra import ClimateModel, SCENARIOS

model = ClimateModel()

for scenario_key in SCENARIOS:
    results = model.run(scenario=scenario_key, add_noise=False)
    summary = results.summary()
    
    print(f"{scenario_key}: "
          f"max_z={summary['max_z']:.3f}, "
          f"tipped={summary['tipped']}, "
          f"crossing={summary['first_crossing_year']}")

Custom Forcing Data

Forcing CSV format:

time,forcing
1750,0.3
1850,0.5
2000,2.5
2100,5.5
2200,4.0
from erucakra import ClimateModel
from erucakra.io import load_forcing_csv

# Load custom forcing
times, values = load_forcing_csv("my_forcing.csv")

# Run with custom forcing
model = ClimateModel(z_crit=0.5)
results = model.run(
    forcing=values,
    forcing_times=times,
    t_end=600.0,
)

Sensitivity Analysis

from erucakra import ClimateModel

model = ClimateModel()

# Vary z_crit to find critical threshold
results_list = model.sensitivity_analysis(
    scenario="ssp245",
    z_crit_range=(0.3, 0.6),
    n_samples=10,
    add_noise=False,
)

for z_crit, results in results_list:
    if results:
        print(f"z_crit={z_crit:.2f}: tipped={results.tipped}, max_z={results.max_z:.3f}")

Available Scenarios

Scenario Description Peak Forcing
ssp126 SSP1-2.6 Sustainability ~3.6 W/m²
ssp245 SSP2-4.5 Middle Road ~5.6 W/m²
ssp370 SSP3-7.0 Regional Rivalry ~11.6 W/m²
ssp585 SSP5-8.5 Fossil Development ~13.2 W/m²

Output Formats

Format Description
CSV Full data table with all variables and diagnostics
NetCDF CF-compliant NetCDF4 with compression and metadata
PNG Time series diagnostic plot with threshold indication
GIF Animated 3D phase space visualization

Output Variables

Variable Units Description
year year Calendar year (integer)
year_decimal year Decimal year (fractional)
x_variability Fast climate variability
y_momentum 1/time Rate of change
z_accumulated Slow accumulated state
A_forcing_Wm2 W/m² Radiative forcing
A_normalized Normalized forcing (A/A_scale)
warming_proxy_celsius °C Approximate temperature anomaly
distance_to_threshold z - z_crit
regime "tipped" or "not_tipped"

Configuration

Create a custom configuration file:

# my_config.yaml
model:
  damping: 0.2
  epsilon: 0.02
  beta: 0.8
  z_crit: 0.55  # Absolute threshold

simulation:
  t_start: 0.0
  t_end: 600.0
  n_points: 48000
  add_noise: true
  noise_level: 0.03

outputs:
  formats:
    - csv
    - netcdf
    - png
    - gif
  base_dir: ./outputs

Run with configuration:

erucakra run --config my_config.yaml --scenario ssp370

Mathematical Details

Fast Subsystem (x, y)

The (x, y) subsystem forms a damped Duffing-type oscillator:

d²x/dt² + c(dx/dt) = x(z - z_crit) - x³

The cubic term -x³ provides saturation, preventing unbounded growth.

Slow Subsystem (z)

The z equation is a forced relaxation:

dz/dt = ε(A_normalized - z - βx²)

At quasi-equilibrium: z_eq ≈ A_normalized - βx²

The βx² term creates hysteresis: oscillations reduce effective forcing, so tipping may not reverse when forcing decreases.

Fixed Points

For the full system at equilibrium:

Pre-tipping (z < z_crit):

  • Single stable fixed point: (x, y, z) = (0, 0, A_normalized)

Post-tipping (z > z_crit):

  • Unstable: (0, 0, z_eq)
  • Stable: (±√(z - z_crit), 0, z_eq)

where z_eq satisfies the implicit equation from the feedback.

Citation

If you use this model in your research, please cite:

@software{erucakra2025,
  author = {Herho, Sandy H. S.},
  title = {\texttt{erucakra}: {A} {P}hysically-{M}otivated {T}oy {M}odel for {C}limate {T}ipping {P}oint {D}ynamics},
  year = {2025},
  url = {https://github.com/sandyherho/erucakra},
  version = {0.0.1}
}

License

MIT License © 2025 Sandy H. S. Herho

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

erucakra-0.0.1.tar.gz (39.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

erucakra-0.0.1-py3-none-any.whl (45.3 kB view details)

Uploaded Python 3

File details

Details for the file erucakra-0.0.1.tar.gz.

File metadata

  • Download URL: erucakra-0.0.1.tar.gz
  • Upload date:
  • Size: 39.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.12.2 Linux/6.11.9-100.fc39.x86_64

File hashes

Hashes for erucakra-0.0.1.tar.gz
Algorithm Hash digest
SHA256 a07532dc5b9af532bce4eabeda5a913a21d4fa733dbae2ce725401d763dc4e5d
MD5 db283ff873dfa67d9d8f4db276ee2047
BLAKE2b-256 b68f42b5a2457b8cff2df3ed911fc21ed07f40287d955808e3f8d6caa10abaa3

See more details on using hashes here.

File details

Details for the file erucakra-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: erucakra-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 45.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.12.2 Linux/6.11.9-100.fc39.x86_64

File hashes

Hashes for erucakra-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f68369de2ca58388c9067a4385f8341226375394fcd166f20a35f5ba54272ee6
MD5 9e40f3ee1558c717a84258f7077f4c73
BLAKE2b-256 e21c4f7907f41e6b643d3643f094bff968fb90731eca59229896b85331ccffbd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page