use std::f64::consts::PI;
use climate_indices::ClimateError;
use climate_indices::eto::thornthwaite;
use ndarray::{Array1, Array3};
const YEARS: usize = 10;
const MONTHS: usize = 12;
const CELLS: usize = 2;
fn main() -> Result<(), ClimateError> {
let temperatures_celsius = monthly_temperatures_celsius();
let latitudes_radians = Array1::from_vec(vec![33.4_f64.to_radians(), 47.6_f64.to_radians()]);
let leap_years = Array1::from_shape_fn(YEARS, |year| year % 4 == 3);
let pet_mm = thornthwaite(
temperatures_celsius.view(),
latitudes_radians.view(),
leap_years.view(),
)?;
println!("PET in mm, year 0 (cold cell, warm cell)");
println!("month cold warm");
for (month, name) in [
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
]
.iter()
.enumerate()
{
println!(
"{name:>5} {:>6.1} {:>6.1}",
pet_mm[(0, month, 0)],
pet_mm[(0, month, 1)]
);
}
for cell in 0..CELLS {
let annual_mm: f64 = (0..MONTHS).map(|month| pet_mm[(0, month, cell)]).sum();
println!("cell {cell}: {annual_mm:.1} mm in year 0");
}
assert_eq!(pet_mm.dim(), (YEARS, MONTHS, CELLS));
assert!(
pet_mm
.iter()
.all(|value| value.is_finite() && *value >= 0.0)
);
for cell in 0..CELLS {
let peak = (0..MONTHS)
.max_by(|left, right| {
pet_mm[(0, *left, cell)]
.partial_cmp(&pet_mm[(0, *right, cell)])
.expect("PET is finite")
})
.expect("twelve months");
assert_eq!(peak, 6, "cell {cell} peaks in July");
}
Ok(())
}
fn monthly_temperatures_celsius() -> Array3<f64> {
Array3::from_shape_fn((YEARS, MONTHS, CELLS), |(year, month, cell)| {
let season = 12.0 + 12.0 * ((month as f64 - 6.0) * PI / 6.0).cos();
let warming = 2.0 * cell as f64 + 0.2 * year as f64;
(season + warming - 0.5).max(0.0)
})
}