Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use crate::tabs::ExplorerTab;
use super::BatteryDegradationTool;
use eframe::egui;
use egui_plot::{HLine, Line, Plot, PlotPoints};
use math_explorer::applied::battery_degradation::{Cycles, DepthOfDischarge, PowerLawModel};

pub struct BatteryDegradationTab {
pub struct CapacityFadeTool {
dod: f64,
temperature: f64,
cycles_to_simulate: f64,
}

impl Default for BatteryDegradationTab {
impl Default for CapacityFadeTool {
fn default() -> Self {
Self {
dod: 80.0,
Expand All @@ -19,12 +19,12 @@ impl Default for BatteryDegradationTab {
}
}

impl ExplorerTab for BatteryDegradationTab {
impl BatteryDegradationTool for CapacityFadeTool {
fn name(&self) -> &'static str {
"Battery Degradation"
"Capacity Fade"
}

fn show(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
fn show(&mut self, ctx: &egui::Context) {
// Enforce valid ranges for internal state before using it
self.dod = self.dod.clamp(0.0, 100.0);
self.cycles_to_simulate = self.cycles_to_simulate.max(100.0);
Expand Down
106 changes: 106 additions & 0 deletions math_explorer_gui/src/tabs/battery_degradation/lifetime_estimator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use super::BatteryDegradationTool;
use eframe::egui;
use math_explorer::applied::battery_degradation::{
Capacity, DepthOfDischarge, PowerLawModel,
};

pub struct LifetimeEstimatorTool {
target_capacity: f64,
dod: f64,
cycles_per_day: f64,
}

impl Default for LifetimeEstimatorTool {
fn default() -> Self {
Self {
target_capacity: 80.0,
dod: 50.0,
cycles_per_day: 1.0,
}
}
}

impl BatteryDegradationTool for LifetimeEstimatorTool {
fn name(&self) -> &'static str {
"Lifetime Estimator"
}

fn show(&mut self, ctx: &egui::Context) {
// Enforce valid ranges
self.target_capacity = self.target_capacity.clamp(0.1, 99.9);
self.dod = self.dod.clamp(0.1, 100.0);
self.cycles_per_day = self.cycles_per_day.max(0.1);

egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("Battery Lifetime Estimator");
ui.label("Calculate the expected battery life based on specific usage profiles.");
ui.add_space(10.0);

ui.group(|ui| {
ui.heading("Usage Profile");
egui::Grid::new("lifetime_params_grid").show(ui, |ui| {
ui.label("Depth of Discharge (DoD):");
ui.add(egui::Slider::new(&mut self.dod, 0.1..=100.0).text("%"))
.on_hover_text("Percentage of battery capacity used per cycle.");
ui.end_row();

ui.label("Target Capacity (End of Life):");
ui.add(egui::Slider::new(&mut self.target_capacity, 10.0..=99.0).text("%"))
.on_hover_text("The threshold capacity to be considered 'end of life'.");
ui.end_row();

ui.label("Cycles per Day:");
ui.add(egui::Slider::new(&mut self.cycles_per_day, 0.1..=10.0).text("cycles"))
.on_hover_text("How many charge/discharge cycles happen per day.");
ui.end_row();
});
});

ui.add_space(20.0);
ui.separator();
ui.add_space(10.0);

// Calculation
let model = PowerLawModel::standard();
let dod_val = DepthOfDischarge::new(self.dod);
let capacity_val = Capacity::new(self.target_capacity / 100.0);

let total_cycles = model.cycles_to_capacity(capacity_val, dod_val).as_f64();
let lifetime_days = total_cycles / self.cycles_per_day;
let lifetime_years = lifetime_days / 365.25;

// Results Display
ui.horizontal(|ui| {
ui.label(
egui::RichText::new("Estimated Total Cycles:")
.size(18.0)
.strong(),
);
ui.label(
egui::RichText::new(format!("{:.0}", total_cycles))
.size(24.0)
.color(egui::Color32::GREEN)
.strong(),
);
});

ui.add_space(5.0);

ui.horizontal(|ui| {
ui.label(
egui::RichText::new("Estimated Lifetime:")
.size(18.0)
.strong(),
);
ui.label(
egui::RichText::new(format!("{:.1} years", lifetime_years))
.size(24.0)
.color(egui::Color32::GREEN)
.strong(),
);
});

ui.label(format!("({:.0} days)", lifetime_days));
});
}
}
68 changes: 68 additions & 0 deletions math_explorer_gui/src/tabs/battery_degradation/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use crate::tabs::ExplorerTab;
use eframe::egui;

pub mod capacity_fade;
pub mod lifetime_estimator;

use capacity_fade::CapacityFadeTool;
use lifetime_estimator::LifetimeEstimatorTool;

/// A trait for sub-tools within the Battery Degradation tab.
pub trait BatteryDegradationTool {
/// Returns the name of the tool.
fn name(&self) -> &'static str;

/// Renders the tool's UI.
fn show(&mut self, ctx: &egui::Context);
}

pub struct BatteryDegradationTab {
tools: Vec<Box<dyn BatteryDegradationTool>>,
selected_tool_index: usize,
}

impl Default for BatteryDegradationTab {
fn default() -> Self {
Self {
tools: vec![
Box::new(CapacityFadeTool::default()),
Box::new(LifetimeEstimatorTool::default()),
],
selected_tool_index: 0,
}
}
}

impl ExplorerTab for BatteryDegradationTab {
fn name(&self) -> &'static str {
"Battery Degradation"
}

fn show(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
// Render Top Menu for Tool Selection
egui::TopBottomPanel::top("battery_degradation_tool_selector").show(ctx, |ui| {
ui.horizontal(|ui| {
ui.label("Tool:");
for (i, tool) in self.tools.iter().enumerate() {
if ui
.selectable_label(self.selected_tool_index == i, tool.name())
.clicked()
{
self.selected_tool_index = i;
}
}
});
});

// Delegate to active tool
if let Some(tool) = self.tools.get_mut(self.selected_tool_index) {
tool.show(ctx);
} else {
egui::CentralPanel::default().show(ctx, |ui| {
ui.centered_and_justified(|ui| {
ui.label("No tool selected");
});
});
}
}
}
2 changes: 1 addition & 1 deletion todo_gui.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ This document outlines the roadmap for integrating the various modules of the `m
* **Module:** `applied::battery_degradation`
* **Features:**
* [x] **Capacity Fade:** Plot capacity vs. cycle number based on depth of discharge (DoD) and temperature.
* [ ] **Lifetime Estimator:** Calculator for expected battery life under specific usage profiles.
* [x] **Lifetime Estimator:** Calculator for expected battery life under specific usage profiles.

### 4.2 Clinical Trials
* **Module:** `applied::clinical_trials`
Expand Down
Loading