earths 0.0.4

High-fidelity Earth simulation engine — orbit, atmosphere, geology, hydrology, biosphere, terrain, lighting, rendering, satellites, and temporal systems with full scientific coupling
Documentation
use earths::atmosphere::climate::{
    CLIMATESENSITIVITYK, ClimateState, EARTHALBEDO, PREINDUSTRIALCO2PPM, co2doublingforcing,
    planck_spectral_radiance, solarzenith,
};
use earths::atmosphere::heatwaves::{HeatWave, dewpointc, saturationvaporpressurepa};
use earths::atmosphere::layers::{
    LAPSERATETROPOSPHERE, SEALEVELPRESSURE, SEALEVELTEMPERATURE, barometricpressure,
    dryairmolarmass, mesosphere, scaleheight, stratosphere, thermosphere, troposphere,
};
use earths::atmosphere::storms::{TropicalCyclone, capeintegrated, capelayer, fujitascale};
use earths::atmosphere::winds::{
    OMEGAEARTH, beauforttoms, coriolisparameter, ekmanspiraldepth, geostrophicwindspeed,
    gradientwindspeed, thermalwindshear, windchilltemperature,
};
use earths::hydrology::glaciers::{
    GLENFLOWLAWA, ICECREEPEXPONENT, antarcticicesheet, greenlandicesheet, icedensity,
    icerheologyviscosity,
};
use earths::hydrology::lakes::{baikal, superior};
use earths::hydrology::oceans::{
    MEANOCEANDEPTHM, MEANSALINITYPSU, OCEANSURFACEAREAM2, OCEANVOLUMEM3, SEAWATERDENSITY,
    deepocean, dissolvedgashenry, oceanareafromfraction, oceanheatcontentj, sealevelrisethermalm,
    surfacelongwaveradiationwm2, surfacemixedlayer, thermocline, thermohalineoverturningratesv,
    vaporpressureoverocean,
};
use earths::hydrology::rivers::{amazon, chezyvelocity, hjulstromerosionthreshold, nile};

fn main() {
    let tropo = troposphere();
    let strato = stratosphere();
    let meso = mesosphere();
    let thermo = thermosphere();

    let altitudes = [0.0, 5000.0, 11000.0, 20000.0, 50000.0, 80000.0];
    let mut totaldensity = 0.0;
    for &alt in &altitudes {
        let layer = if alt < 12000.0 {
            &tropo
        } else if alt < 50000.0 {
            &strato
        } else if alt < 85000.0 {
            &meso
        } else {
            &thermo
        };
        let temp = layer.temperatureat(alt);
        let press = layer.pressureat(alt);
        let dens = layer.densityat(alt);
        totaldensity += dens;
        println!(
            "[{:>12}] alt={:>6.0}m  T={:.1}K  P={:.0}Pa  ρ={:.4}kg/m³",
            layer.name, alt, temp, press, dens
        );
    }

    let psea = barometricpressure(0.0);
    let pcruise = barometricpressure(10000.0);
    let hscale = scaleheight();
    println!(
        "P(sea)={:.0}Pa  P(10km)={:.0}Pa  Hscale={:.0}m  Σρ={:.4}",
        psea, pcruise, hscale, totaldensity
    );
    println!(
        "constants: P0={} T0={} Mair={} Γ={}",
        SEALEVELPRESSURE,
        SEALEVELTEMPERATURE,
        dryairmolarmass(),
        LAPSERATETROPOSPHERE
    );

    let preind = ClimateState::preindustrial();
    let current = ClimateState::current();

    let forcingpi = preind.co2radiativeforcing();
    let forcingnow = current.co2radiativeforcing();
    let warming = current.equilibriumwarming();
    let olr = current.outgoinglongwaveradiation();
    let asr = current.absorbedsolarradiation();
    let imbalance = current.energyimbalance();
    let teff = current.effectiveemissiontemperature();
    let greenhouse = current.greenhouseeffectk();

    println!(
        "CO2: pre-ind={:.0}ppm  now={:.0}ppm",
        preind.co2ppm, current.co2ppm
    );
    println!(
        "Forcing: pi={:.2} now={:.2} W/m²  warming={:.2}K",
        forcingpi, forcingnow, warming
    );
    println!(
        "OLR={:.1}  ASR={:.1}  imbalance={:.2}  Teff={:.1}K  greenhouse={:.1}K",
        olr, asr, imbalance, teff, greenhouse
    );

    let zenith = solarzenith(45.0, 23.44, 0.0);
    let radiance = planck_spectral_radiance(10e-6, 288.0);
    let doubling = co2doublingforcing();
    println!(
        "zenith={:.2}°  planck(10µm,288K)={:.4}  2xCO2={:.2}W/m²",
        zenith, radiance, doubling
    );
    println!(
        "constants: CO2PI={} sensitivity={} albedo={}",
        PREINDUSTRIALCO2PPM, CLIMATESENSITIVITYK, EARTHALBEDO
    );

    let cyclone = TropicalCyclone {
        maxsustainedwindms: 75.0,
        centralpressurehpa: 940.0,
        radiusmaxwindkm: 30.0,
        latitudedeg: 20.0,
    };
    let cat = cyclone.saffirsimpsoncategory();
    let ace = cyclone.accumulatedcycloneenergy(48.0);
    let pi = TropicalCyclone::potentialintensityms(302.0, 200.0, 1500.0);
    let rossby = cyclone.rossbydeformationradius();
    let windr = cyclone.windatradius(60.0);
    let fujita = fujitascale(90.0);
    let capesingle = capelayer(305.0, 300.0, 1000.0);
    let cape = capeintegrated(305.0, 300.0, 0.0075, 500.0, 40);
    println!(
        "Cyclone: cat={} ACE={:.1} PI={:.1}m/s Rossby={:.0}m wind@60km={:.1}m/s",
        cat, ace, pi, rossby, windr
    );
    println!(
        "Fujita(90m/s)={} CAPElayer={:.1} CAPEintegrated={:.1}J/kg",
        fujita, capesingle, cape
    );

    let f45 = coriolisparameter(45.0);
    let vg = geostrophicwindspeed(0.01, 45.0, 1.225);
    let vgr = gradientwindspeed(0.01, 500000.0, 45.0, 1.225);
    let tw = thermalwindshear(5e-6, 260.0, 45.0, 500e2, 750e2);
    let ekman = ekmanspiraldepth(0.05, 45.0);
    let b7 = beauforttoms(7);
    let wc = windchilltemperature(-10.0, 30.0);
    println!(
        "ω={:.5e}  f(45°)={:.5e}  Vg={:.1}  Vgr={:.1}  thermalwind={:.4}",
        OMEGAEARTH, f45, vg, vgr, tw
    );
    println!(
        "Ekman={:.0}m  B7={:.1}m/s  windchill(-10°,30km/h)={:.1}°C",
        ekman, b7, wc
    );

    let hw = HeatWave {
        maxtemperaturec: 45.0,
        durationdays: 5,
        relativehumiditypercent: 40.0,
    };
    let hi = hw.heatindexc();
    let wb = hw.wetbulbtemperaturec();
    let danger = hw.dangerlevel();
    let mort = hw.excessmortalityfactor();
    let svp = saturationvaporpressurepa(35.0);
    let dp = dewpointc(35.0, 60.0);
    println!(
        "Heatwave: HI={:.1}°C  Tw={:.1}°C  danger={}  mortalityfactor={:.2}",
        hi, wb, danger, mort
    );
    println!("SVP(35°C)={:.0}Pa  dewpoint(35°C,60%)={:.1}°C", svp, dp);

    let sml = surfacemixedlayer();
    let tc = thermocline();
    let deep = deepocean();
    let rhosml = sml.densitykgm3();
    let rhotc = tc.densitykgm3();
    let rhodeep = deep.densitykgm3();
    let speedsml = sml.soundspeedms();
    let pdeep = deep.pressureatdepth(3000.0);
    let thc = thermohalineoverturningratesv();
    let ohc = oceanheatcontentj(0.5, 700.0);
    let slr = sealevelrisethermalm(0.5, 700.0);
    let lw = surfacelongwaveradiationwm2(17.0, 0.97);
    let oa = oceanareafromfraction(0.71);
    let vp = vaporpressureoverocean(20.0);
    let co2dissolved = dissolvedgashenry(40.0, 15.0, 3.4e-4);
    println!(
        "Ocean: ρsml={:.1} ρtc={:.1} ρdeep={:.1}  sound={:.0}m/s  P@3km={:.0}Pa",
        rhosml, rhotc, rhodeep, speedsml, pdeep
    );
    println!(
        "THC={:.0}Sv  OHC={:.2e}J  SLR={:.4}m  LW={:.1}W/m²",
        thc, ohc, slr, lw
    );
    println!(
        "area(0.71)={:.2e}m²  VP(20°C)={:.0}Pa  CO2diss={:.6}mol/m³",
        oa, vp, co2dissolved
    );
    println!(
        "constants: A={:.2e}m²  D={:.0}m  V={:.3e}m³  S={:.0}psu  ρ={:.0}",
        OCEANSURFACEAREAM2, MEANOCEANDEPTHM, OCEANVOLUMEM3, MEANSALINITYPSU, SEAWATERDENSITY
    );

    let am = amazon();
    let ni = nile();
    let vmanning = am.manningvelocity(3.0, 0.035);
    let fr = am.froudenumber(1.5, 10.0);
    let re = ni.reynoldsnumber(1.0, 5.0);
    let sed = am.sedimenttransportcapacity(1.5, 10.0, 0.001);
    let sp = am.streampowerwperm();
    let sd = ni.specificdischargems();
    let chezy = chezyvelocity(50.0, 2.0, 0.001);
    let hjul = hjulstromerosionthreshold(0.5);
    println!(
        "Amazon: Vmanning={:.2}m/s  Fr={:.3}  sed={:.4}  SP={:.0}W/m",
        vmanning, fr, sed, sp
    );
    println!(
        "Nile: Re={:.0}  q={:.2e}m/s  Chézy={:.2}m/s  Hjul(0.5mm)={:.3}m/s",
        re, sd, chezy, hjul
    );

    let bk = baikal();
    let su = superior();
    let dbk = bk.meandepthm();
    let sdl = su.shorelinedevelopmentratio(4385.0);
    let rt = bk.residencetimeyears(330.0);
    let strat = su.thermalstratificationenergyj(18.0, 4.0);
    let evap = su.evaporationratemmday(25.0, 18.0, 3.0, 60.0);
    let lwlake = bk.longwaveradiationwm2(4.0, 0.97);
    println!(
        "Baikal: meand={:.1}m  restime={:.0}yr  LW={:.1}W/m²",
        dbk, rt, lwlake
    );
    println!(
        "Superior: SDL={:.2}  stratE={:.2e}J  evap={:.2}mm/d",
        sdl, strat, evap
    );

    let ant = antarcticicesheet();
    let grl = greenlandicesheet();
    let mbant = ant.massbalancemyr();
    let tauant = ant.basalshearstresspa();
    let velant = ant.deformationvelocitymyr();
    let ela = grl.equilibriumlinealtitude(0.0);
    let vol = grl.volumem3(800000.0);
    let sle = grl.sealevelequivalentmm(800000.0);
    let visc = icerheologyviscosity(-10.0, 100000.0);
    println!(
        "Antarctic: MB={:.3}m/yr  τ={:.0}Pa  v={:.4}m/yr",
        mbant, tauant, velant
    );
    println!(
        "Greenland: ELA={:.0}m  V={:.2e}m³  SLE={:.1}mm  visc={:.2e}Pa·s",
        ela, vol, sle, visc
    );
    println!(
        "constants: ρice={} n={} Aglen={:.2e}",
        icedensity(),
        ICECREEPEXPONENT,
        GLENFLOWLAWA
    );
}