Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of https://framagit.org/simgrid/simgrid
authormlaurent <mathieu.laurent@ens-rennes.fr>
Fri, 31 Mar 2023 18:19:44 +0000 (20:19 +0200)
committermlaurent <mathieu.laurent@ens-rennes.fr>
Fri, 31 Mar 2023 18:19:44 +0000 (20:19 +0200)
1  2 
src/mc/api/strategy/Strategy.hpp
src/plugins/battery.cpp

@@@ -17,9 -17,12 +17,14 @@@ protected
    std::map<aid_t, ActorState> actors_to_run_;
  
  public:
 +  /** Used to store penalties computed by the strategy to each actor */
 +  std::map<aid_t, double> penalties_;
    virtual ~Strategy()                                      = default;
+   void operator=(const Strategy&)
+   { /* nothing to copy over while cloning */
+     return;
+   }
    virtual std::pair<aid_t, double> next_transition() const = 0;
    virtual void execute_next(aid_t aid, RemoteApp& app)     = 0;
    virtual void consider_best()                             = 0;
index 0000000,7e7f949..b08de11
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,598 +1,599 @@@
 -- ``battery_power``: Set the initial power of the battery in W (default=0). A negative value indicates that the battery act as a load and charge. A positive value indicates that the battery act as a generator and discharge
+ #include <simgrid/Exception.hpp>
+ #include <simgrid/plugins/battery.hpp>
+ #include <simgrid/s4u/Actor.hpp>
+ #include <simgrid/s4u/Engine.hpp>
+ #include <simgrid/s4u/Host.hpp>
+ #include <simgrid/s4u/VirtualMachine.hpp>
+ #include <simgrid/simix.hpp>
+ #include "src/kernel/resource/CpuImpl.hpp"
+ #include "src/simgrid/module.hpp"
+ #include <boost/algorithm/string/classification.hpp>
+ #include <boost/algorithm/string/split.hpp>
+ SIMGRID_REGISTER_PLUGIN(battery, "Battery management", &sg_battery_plugin_init)
+ /** @defgroup plugin_battery plugin_battery Plugin Battery
+   @beginrst
+ This is the battery plugin, enabling management of batteries on hosts.
+ To activate this plugin, first call :cpp:func:`sg_battery_plugin_init()`.
+ We consider a constant energy exchange model.
+ Properties of batteries such as State of Charge and State of Health are lazily updated, ie., when reading values and
+ when the power is modified.
+ State of Charge (SoC)
+ .....................
+ If the power of a battery is set to a negative value then the battery will act as a load and fill over time until it
+ reaches its maximal SoC. Conversely, if the power of a battery is set to a positive value then the battery will act as a
+ generator and deplete over time until it reaches its minimal SoC. When reaching either its maximal or minimal SoC it
+ will set its power to 0.
+ The natural depletion of batteries over time is not taken into account.
+ State of Health (SoH)
+ .....................
+ A battery starts with an energy budget :math:`E` such as:
+ .. math::
+   E = C \times U \times D \times N \times 2
+ Where :math:`C` is the initial capacity, :math:`U` is the ratio of usable capacity, :math:`D` is the depth of discharge
+ and :math:`N` is the number of cycles of the battery.
+ The SoH represents the consumption of this energy budget during the lifetime of the battery.
+ Use the battery reduces its SoH and its capacity in consequence.
+ When the SoH reaches 0, the battery becomes unusable.
+ .. warning::
+   Due to the decrease of the battery capacity with the SoH, a large usable capacity leads to very tiny battery capacity
+   when reaching low SoH. This may results in charge and discharge cycles too short to be evaluated by the simulator. To
+   avoid this situation you should not try to reach a SoH of 0 with a usable capacity set to 1.
+ Plotting the output of the example "battery-degradation" highlights the linear decrease of the SoH due to a continuous
+ use of the battery and the decreasing cycle duration as its capacity reduces:
+ .. image:: /img/battery_degradation.svg
+    :align: center
+ Batteries properties
+ ....................
+ Properties of the batteries are defined as properties of hosts in the platform XML file.
+ Here is an example of XML declaration:
+ .. code-block:: xml
+    <host id="Host" speed="100.0Mf" core="1">
+        <prop id="battery_active" value="1" />
+        <prop id="battery_capacity" value="10" />
+        <prop id="battery_cycles" value="200" />
+        <prop id="battery_state_of_charge" value="0.8" />
+    </host>
+ The different properties are:
+ - ``battery_active``: Set the battery as active if set to 1 (default=0)
++- ``battery_power``: Set the initial power of the battery in W (default=0). A negative value indicates that the battery
++act as a load and charge. A positive value indicates that the battery act as a generator and discharge
+ - ``battery_state_of_charge``: Set the initial state of charge of the battery (default=0)
+ - ``battery_state_of_charge_min``: Set the minimal state of charge of the battery (default=0.2)
+ - ``battery_state_of_charge_max``: Set the maximal state of charge of the battery (default=0.8)
+ - ``battery_capacity``: Set the initial capacity of the battery in Wh (default=0)
+ - ``battery_usable_capacity``: Set the ratio of usable capacity of the battery (default=0.8)
+ - ``battery_depth_of_discharge``: Set the depth of discharge of the battery (default=0.9)
+ - ``battery_charge_efficiency``: Set the charge efficiency of the battery (default=1)
+ - ``battery_discharge_efficiency``: Set the charge efficiency of the battery (default=1)
+ - ``battery_cycles``: Set the number of cycle of the battery (default=1)
+ - ``battery_depth_of_discharge``: Set the number of cycle of the battery (default=1)
+ - ``battery_eval_cost``: Evaluate the cost of the battery during the simulation if set to 1 (defaulf=0)
+ - ``battery_investment_cost``: Set the investment cost of the battery (default=0)
+ - ``battery_static_maintenance_cost``: Set the static maintenance cost of the battery (default=0)
+ - ``battery_variable_maintenance_cost``: Set the variable maintenance cost of the battery (default=0)
+   @endrst
+  */
+ 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();
+   double get_state_of_charge_max();
+   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; });
+ }
+ void Battery::set_eval_cost(bool eval)
+ {
+   simgrid::kernel::actor::simcall_answered([this, eval] { eval_cost_ = eval; });
+ }
+ void Battery::set_investment_cost(double c)
+ {
+   xbt_assert(c >= 0, " : investment cost should be >= 0 (provided: %f)", c);
+   simgrid::kernel::actor::simcall_answered([this, c] { investment_cost_per_wh_ = c; });
+ }
+ void Battery::set_static_maintenance_cost(double c)
+ {
+   xbt_assert(c >= 0, " : static maintenance cost should be >= 0 (provided: %f)", c);
+   simgrid::kernel::actor::simcall_answered([this, c] { static_maintenance_cost_per_wh_times_h_ = c; });
+ }
+ void Battery::set_variable_maintenance_cost(double c)
+ {
+   xbt_assert(c >= 0, " : variable maintenance cost should be >= 0 (provided: %f)", c);
+   simgrid::kernel::actor::simcall_answered([this, c] { variable_maintenance_cost_per_wh_ = c; });
+ }
+ bool Battery::is_charging()
+ {
+   update();
+   return power_w_ < 0;
+ }
+ bool Battery::is_active() const
+ {
+   return active_;
+ }
+ double Battery::get_power()
+ {
+   update();
+   return power_w_;
+ }
+ double Battery::get_state_of_charge()
+ {
+   update();
+   return state_of_charge_;
+ }
+ double Battery::get_state_of_charge_min()
+ {
+   return state_of_charge_min_;
+ }
+ double Battery::get_state_of_charge_max()
+ {
+   return state_of_charge_max_;
+ }
+ double Battery::get_state_of_health()
+ {
+   update();
+   return 1 - (energy_exchanged_j_ / energy_budget_j_);
+ }
+ double Battery::get_capacity()
+ {
+   update();
+   return capacity_wh_;
+ }
+ double Battery::get_cumulative_cost()
+ {
+   update();
+   return cumulative_cost_;
+ }
+ double Battery::get_next_event_date()
+ {
+   update();
+   return next_event_;
+ }
+ void Battery::init_battery_params()
+ {
+   const char* prop_chars;
+   prop_chars = host_->get_property("battery_capacity");
+   if (prop_chars) {
+     set_capacity(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
+     set_initial_capacity(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
+   }
+   prop_chars = host_->get_property("battery_usable_capacity");
+   if (prop_chars)
+     set_usable_capacity(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
+   prop_chars = host_->get_property("battery_depth_of_discharge");
+   if (prop_chars)
+     set_depth_of_discharge(
+         xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
+   prop_chars = host_->get_property("battery_cycles");
+   if (prop_chars)
+     set_cycles(xbt_str_parse_int(prop_chars, ("cannot parse int: " + std::string(prop_chars)).c_str()));
+   simgrid::kernel::actor::simcall_answered([this] {
+     energy_budget_j_ = (initial_capacity_wh_ * usable_capacity_ * depth_of_discharge_ * 3600 * cycles_ * 2);
+   });
+   prop_chars = host_->get_property("battery_active");
+   if (prop_chars)
+     set_state(xbt_str_parse_int(prop_chars, ("cannot parse int: " + std::string(prop_chars)).c_str()));
+   prop_chars = host_->get_property("battery_state_of_charge_min");
+   if (prop_chars)
+     set_state_of_charge_min(
+         xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
+   prop_chars = host_->get_property("battery_state_of_charge_max");
+   if (prop_chars)
+     set_state_of_charge_max(
+         xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
+   prop_chars = host_->get_property("battery_charge_efficiency");
+   if (prop_chars)
+     set_charge_efficiency(
+         xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
+   prop_chars = host_->get_property("battery_discharge_efficiency");
+   if (prop_chars)
+     set_discharge_efficiency(
+         xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
+   prop_chars = host_->get_property("battery_state_of_charge");
+   if (prop_chars)
+     set_state_of_charge(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
+   prop_chars = host_->get_property("battery_eval_cost");
+   if (prop_chars)
+     set_eval_cost(xbt_str_parse_int(prop_chars, ("cannot parse int: " + std::string(prop_chars)).c_str()));
+   prop_chars = host_->get_property("battery_investment_cost");
+   if (prop_chars)
+     set_investment_cost(xbt_str_parse_int(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
+   prop_chars = host_->get_property("battery_static_maintenance_cost");
+   if (prop_chars)
+     set_static_maintenance_cost(
+         xbt_str_parse_int(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
+   prop_chars = host_->get_property("battery_variable_maintenance_cost");
+   if (prop_chars)
+     set_variable_maintenance_cost(
+         xbt_str_parse_int(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
+   prop_chars = host_->get_property("battery_power");
+   if (prop_chars)
+     set_power(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
+   simgrid::kernel::actor::simcall_answered([this] { last_updated_ = simgrid::s4u::Engine::get_clock(); });
+ }
+ void Battery::update()
+ {
+   simgrid::kernel::actor::simcall_answered([this] {
+     double now             = simgrid::s4u::Engine::get_clock();
+     double time_delta_real = now - last_updated_;
+     if (time_delta_real <= 0 or not is_active())
+       return;
+     double time_delta_until_event = next_event_ - last_updated_;
+     bool event                    = next_event_ != -1 and time_delta_until_event <= time_delta_real;
+     double power_real_w           = power_w_ < 0 ? power_w_ * charge_efficiency_ : power_w_ / discharge_efficiency_;
+     state_of_charge_ -= power_real_w * (event ? time_delta_until_event : time_delta_real) / (3600 * capacity_wh_);
+     energy_exchanged_j_ += (event ? time_delta_until_event : time_delta_real) * abs(power_real_w);
+     capacity_wh_ = initial_capacity_wh_ * usable_capacity_ * (1 - (energy_exchanged_j_ / energy_budget_j_)) +
+                    initial_capacity_wh_ * (1 - usable_capacity_);
+     capacity_wh_ = std::max(capacity_wh_, 0.0);
+     if (eval_cost_) {
+       double usage_cost_per_wh =
+           (investment_cost_per_wh_ / (depth_of_discharge_ * cycles_ * 2) + variable_maintenance_cost_per_wh_);
+       double usage_cost =
+           usage_cost_per_wh * abs(power_real_w) * (event ? time_delta_until_event : time_delta_real) / 3600;
+       double static_maintenance_cost =
+           static_maintenance_cost_per_wh_times_h_ * initial_capacity_wh_ * time_delta_real / 3600;
+       cumulative_cost_ += usage_cost + static_maintenance_cost;
+     }
+     if (event) {
+       power_w_    = 0;
+       next_event_ = -1;
+     }
+     last_updated_ = now;
+   });
+ }
+ Battery::Battery(simgrid::s4u::Host* host) : host_(host)
+ {
+   init_battery_params();
+ }
+ Battery::~Battery() = default;
+ } // namespace simgrid::plugin
+ using simgrid::plugin::Battery;
+ /* **************************** events  callback *************************** */
+ static void on_creation(simgrid::s4u::Host& host)
+ {
+   if (dynamic_cast<simgrid::s4u::VirtualMachine*>(&host)) // Ignore virtual machines
+     return;
+   host.extension_set(new Battery(&host));
+ }
+ /* **************************** Public interface *************************** */
+ static void ensure_plugin_inited()
+ {
+   if (not Battery::EXTENSION_ID.valid())
+     throw simgrid::xbt::InitializationError("The Battery plugin is not active. Please call sg_battery_plugin_init() "
+                                             "before calling any function related to that plugin.");
+ }
+ /** @ingroup plugin_battery
+  *  @brief Enable battery plugin.
+  */
+ void sg_battery_plugin_init()
+ {
+   if (Battery::EXTENSION_ID.valid())
+     return;
+   Battery::EXTENSION_ID = simgrid::s4u::Host::extension_create<Battery>();
+   simgrid::s4u::Host::on_creation_cb(&on_creation);
+ }
+ /** @ingroup plugin_battery
+  *  @param state The state to set.
+  *  @brief Set the state of the battery.
+  * A battery set to inactive (false) will neither update its state of charge nor its state of health.
+  */
+ void sg_battery_set_state(const_sg_host_t host, bool state)
+ {
+   ensure_plugin_inited();
+   host->extension<Battery>()->set_state(state);
+ }
+ /** @ingroup plugin_battery
+  *  @param power The power to set in W.
+  *  @brief Set the power of the battery.
+  *  @note A negative value makes the battery act as a load and charge.
+  * A positive value makes the battery act as a generator and discharge.
+  */
+ void sg_battery_set_power(const_sg_host_t host, double power)
+ {
+   ensure_plugin_inited();
+   host->extension<Battery>()->set_power(power);
+ }
+ /** @ingroup plugin_battery
+  *  @brief Return true if the battery is active.
+  */
+ bool sg_battery_is_active(const_sg_host_t host)
+ {
+   ensure_plugin_inited();
+   return host->extension<Battery>()->is_active();
+ }
+ /** @ingroup plugin_battery
+  *  @brief Return the power of the battery in W.
+  *  @note A negative value indicates that the battery act as a load and charge.
+  * A positive value indicates that the battery act as a generator and discharge.
+  */
+ double sg_battery_get_power(const_sg_host_t host)
+ {
+   ensure_plugin_inited();
+   return host->extension<Battery>()->get_power();
+ }
+ /** @ingroup plugin_battery
+  *  @brief Return the state of charge of the battery.
+  */
+ double sg_battery_get_state_of_charge(const_sg_host_t host)
+ {
+   ensure_plugin_inited();
+   return host->extension<Battery>()->get_state_of_charge();
+ }
+ /** @ingroup plugin_battery
+  *  @brief Return the minimal state of charge of the battery.
+  */
+ double sg_battery_get_state_of_charge_min(const_sg_host_t host)
+ {
+   ensure_plugin_inited();
+   return host->extension<Battery>()->get_state_of_charge_min();
+ }
+ /** @ingroup plugin_battery
+  *  @brief Return the maximal state of charge of the battery.
+  */
+ double sg_battery_get_state_of_charge_max(const_sg_host_t host)
+ {
+   ensure_plugin_inited();
+   return host->extension<Battery>()->get_state_of_charge_max();
+ }
+ /** @ingroup plugin_battery
+  *  @brief Return the state of health of the battery.
+  */
+ double sg_battery_get_state_of_health(const_sg_host_t host)
+ {
+   ensure_plugin_inited();
+   return host->extension<Battery>()->get_state_of_health();
+ }
+ /** @ingroup plugin_battery
+  *  @brief Return the capacity of the battery in Wh.
+  *  @note capacity is reduced by the state of health of the battery.
+  */
+ double sg_battery_get_capacity(const_sg_host_t host)
+ {
+   ensure_plugin_inited();
+   return host->extension<Battery>()->get_capacity();
+ }
+ /** @ingroup plugin_battery
+  *  @brief Return the cumulative cost of the battery.
+  */
+ double sg_battery_get_cumulative_cost(const_sg_host_t host)
+ {
+   ensure_plugin_inited();
+   return host->extension<Battery>()->get_cumulative_cost();
+ }
+ /** @ingroup plugin_battery
+  *  @brief Return the date of the next event, i.e., when the battery will be empty or full.
+  *  @note If power is null then return -1.
+  */
+ double sg_battery_get_next_event_date(const_sg_host_t host)
+ {
+   ensure_plugin_inited();
+   return host->extension<Battery>()->get_next_event_date();
+ }