-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(battery, kernel, "Logging specific to the battery plugin");
-
-namespace simgrid::plugin {
-class Battery {
-private:
- simgrid::s4u::Host* host_ = nullptr;
-
- double state_of_charge_min_ = 0.2;
- double state_of_charge_max_ = 0.8;
- double charge_efficiency_ = 1;
- double discharge_efficiency_ = 1;
- double initial_capacity_wh_ = 0;
- double cycles_ = 1; // total complete cycles (charge + discharge) the battery can do before complete depletion.
- double depth_of_discharge_ = 0.9;
- double usable_capacity_ = 0.8;
- double energy_budget_j_ = 0;
-
- bool active_ = false;
- double power_w_ = 0; // NEGATIVE when charging (consumes power) POSITIVE when discharging (generates power)
- double state_of_charge_ = 0;
- double capacity_wh_ = 0;
- double next_event_ = -1;
- double energy_exchanged_j_ = 0;
- double last_updated_ = 0;
-
- // Calculation of costs from Bei Li thesis (link :https://tel.archives-ouvertes.fr/tel-02077668/document) (chapter 4)
- bool eval_cost_ = false;
- double cumulative_cost_ = 0;
- double investment_cost_per_wh_ = 0;
- double static_maintenance_cost_per_wh_times_h_ = 0;
- double variable_maintenance_cost_per_wh_ = 0;
-
- void init_battery_params();
- void init_cost_params();
- void update();
-
- void set_state_of_charge(double soc);
- void set_state_of_charge_min(double soc);
- void set_state_of_charge_max(double soc);
- void set_capacity(double c);
- void set_initial_capacity(double c);
- void set_cycles(int c);
- void set_depth_of_discharge(double d);
- void set_usable_capacity(double c);
- void set_charge_efficiency(double e);
- void set_discharge_efficiency(double e);
- void set_eval_cost(bool eval);
- void set_investment_cost(double c);
- void set_static_maintenance_cost(double c);
- void set_variable_maintenance_cost(double c);
-
- bool is_charging();
-
-public:
- static simgrid::xbt::Extension<simgrid::s4u::Host, Battery> EXTENSION_ID;
-
- explicit Battery(simgrid::s4u::Host* host);
- ~Battery();
-
- void set_state(bool state);
- void set_power(const double power);
-
- bool is_active() const;
- double get_power();
- double get_state_of_charge();
- double get_state_of_charge_min() const;
- double get_state_of_charge_max() const;
- double get_state_of_health();
- double get_capacity();
- double get_cumulative_cost();
- double get_next_event_date();
-};
-
-simgrid::xbt::Extension<simgrid::s4u::Host, Battery> Battery::EXTENSION_ID;
-
-void Battery::set_power(const double p)
-{
- update();
- xbt_assert(p == 0 or (p > 0 and state_of_charge_ > state_of_charge_min_) or
- (p < 0 and state_of_charge_ < state_of_charge_max_),
- "Incoherent power and state of charge. A battery cannot charge(discharge) past its maximal(minimal) state "
- "of charge.");
- xbt_assert(p == 0 or energy_exchanged_j_ < energy_budget_j_, "Cannot set power of a fully used battery.");
- simgrid::kernel::actor::simcall_answered([this, p] {
- power_w_ = p;
- if (power_w_ == 0) {
- next_event_ = -1;
- return;
- }
- double soc_shutdown;
- double soh_shutdown;
- if (power_w_ > 0) {
- soc_shutdown = capacity_wh_ * 3600 * (state_of_charge_ - state_of_charge_min_) / (power_w_ * charge_efficiency_);
- soh_shutdown = (energy_budget_j_ - energy_exchanged_j_) / (power_w_ * charge_efficiency_);
- } else { // power_w_ < 0
- soc_shutdown =
- capacity_wh_ * 3600 * (state_of_charge_max_ - state_of_charge_) / (abs(power_w_) / discharge_efficiency_);
- soh_shutdown = (energy_budget_j_ - energy_exchanged_j_) / (abs(power_w_) / discharge_efficiency_);
- }
- if (soh_shutdown <= 0)
- next_event_ = simgrid::s4u::Engine::get_clock() + soc_shutdown;
- else
- next_event_ = simgrid::s4u::Engine::get_clock() + std::min(soc_shutdown, soh_shutdown);
- });
-}
-
-void Battery::set_state(bool state)
-{
- update();
- simgrid::kernel::actor::simcall_answered([this, state] { active_ = state; });
-}
-
-void Battery::set_state_of_charge(double soc)
-{
- xbt_assert(soc > 0 and soc <= 1, " : state of charge should be in ]0,1] (provided: %f)", soc);
- simgrid::kernel::actor::simcall_answered([this, soc] { state_of_charge_ = soc; });
-}
-
-void Battery::set_state_of_charge_min(double soc)
-{
- xbt_assert(soc > 0 and soc <= 1 and soc < state_of_charge_max_,
- " : state of charge min should be in ]0,1] and below state of charge max (provided: %f)", soc);
- simgrid::kernel::actor::simcall_answered([this, soc] { state_of_charge_min_ = soc; });
-}
-
-void Battery::set_state_of_charge_max(double soc)
-{
- xbt_assert(soc > 0 and soc <= 1 and soc > state_of_charge_min_,
- " : state of charge max should be in ]0,1] and above state of charge min (provided: %f)", soc);
- simgrid::kernel::actor::simcall_answered([this, soc] { state_of_charge_max_ = soc; });
-}
-
-void Battery::set_initial_capacity(double c)
-{
- xbt_assert(c > 0, " : capacity should be > 0 (provided: %f)", c);
- simgrid::kernel::actor::simcall_answered([this, c] { initial_capacity_wh_ = c; });
-}
-
-void Battery::set_capacity(double c)
-{
- xbt_assert(c > 0, " : capacity should be > 0 (provided: %f)", c);
- simgrid::kernel::actor::simcall_answered([this, c] { capacity_wh_ = c; });
-}
-
-void Battery::set_cycles(int c)
-{
- xbt_assert(c > 0, " : cycles should be > 0 (provided: %d)", c);
- simgrid::kernel::actor::simcall_answered([this, c] { cycles_ = c; });
-}
-
-void Battery::set_depth_of_discharge(double d)
-{
- xbt_assert(d > 0 and d <= 1, " : depth of discharge should be in ]0, 1] (provided: %f)", d);
- simgrid::kernel::actor::simcall_answered([this, d] { depth_of_discharge_ = d; });
-}
-
-void Battery::set_usable_capacity(double c)
-{
- xbt_assert(c > 0 and c <= 1, " : usable capacity should be in ]0, 1] (provided: %f)", c);
- simgrid::kernel::actor::simcall_answered([this, c] { usable_capacity_ = c; });
-}
-
-void Battery::set_charge_efficiency(double e)
-{
- xbt_assert(e > 0 and e <= 1, " : charge efficiency should be in [0,1] (provided: %f)", e);
- simgrid::kernel::actor::simcall_answered([this, e] { charge_efficiency_ = e; });
-}
-
-void Battery::set_discharge_efficiency(double e)
-{
- xbt_assert(e > 0 and e <= 1, " : discharge efficiency should be in [0,1] (provided: %f)", e);
- simgrid::kernel::actor::simcall_answered([this, e] { discharge_efficiency_ = e; });
-}