use oxictl::sim::TheveninBattery;
fn main() -> Result<(), String> {
let mut bat = TheveninBattery::<f64>::default_18650().map_err(|e| e.to_string())?;
println!("# Thevenin Battery Simulation (18650 Li-ion cell)");
println!("# Phase 1: discharge at I=+2 A (steps 0–99)");
println!("# Phase 2: rest at I= 0 A (steps 100–149)");
println!("# Phase 3: charge at I=−1 A (steps 150–199)");
println!(
"{:>6} {:>10} {:>10} {:>10}",
"step", "soc", "v_term", "phase"
);
let n_steps = 200_usize;
for step in 0..n_steps {
let (current, phase) = if step < 100 {
(2.0_f64, "discharge")
} else if step < 150 {
(0.0_f64, "rest")
} else {
(-1.0_f64, "charge")
};
let v_term = match bat.step(current) {
Ok(v) => v,
Err(oxictl::sim::BatteryError::Overdischarged) => {
eprintln!("step {step}: battery overdischarged — stopping simulation.");
break;
}
Err(oxictl::sim::BatteryError::Overcharged) => {
eprintln!("step {step}: battery overcharged — stopping simulation.");
break;
}
Err(e) => return Err(e.to_string()),
};
let soc = bat.soc();
if step % 25 == 0 {
println!("{step:6} {soc:10.5} {v_term:10.5} {phase:>10}");
}
}
eprintln!("\n=== Battery Simulation Summary ===");
eprintln!("Final SOC: {:.5}", bat.soc());
eprintln!("Final OCV: {:.5} V", bat.open_circuit_voltage());
eprintln!("Final V_term (no-load): {:.5} V", bat.terminal_voltage());
eprintln!("State of health: {:.3}", bat.state_of_health());
eprintln!("Remaining energy: {:.3} J", bat.remaining_energy_joules());
Ok(())
}