Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Various sonar cleanups
[simgrid.git] / src / plugins / battery.cpp
index 3a870f9..0cbfdbc 100644 (file)
@@ -6,10 +6,7 @@
 #include <simgrid/plugins/battery.hpp>
 #include <simgrid/plugins/energy.h>
 #include <simgrid/s4u/Engine.hpp>
 #include <simgrid/plugins/battery.hpp>
 #include <simgrid/plugins/energy.h>
 #include <simgrid/s4u/Engine.hpp>
-#include <simgrid/s4u/Host.hpp>
 #include <simgrid/simix.hpp>
 #include <simgrid/simix.hpp>
-#include <xbt/asserts.h>
-#include <xbt/log.h>
 
 #include "src/kernel/resource/CpuImpl.hpp"
 #include "src/simgrid/module.hpp"
 
 #include "src/kernel/resource/CpuImpl.hpp"
 #include "src/simgrid/module.hpp"
@@ -71,19 +68,25 @@ continuous use of the battery alternating between charge and discharge:
 The natural depletion of batteries over time is not taken into account.
 
 Loads & Hosts
 The natural depletion of batteries over time is not taken into account.
 
 Loads & Hosts
-..............
+.............
 
 You can add named loads to a battery. Those loads may be positive and consume energy from the battery, or negative and
 provide energy to the battery. You can also connect hosts to a battery. Theses hosts will consume their energy from the
 battery until the battery is empty or until the connection between the hosts and the battery is set inactive.
 
 Handlers
 
 You can add named loads to a battery. Those loads may be positive and consume energy from the battery, or negative and
 provide energy to the battery. You can also connect hosts to a battery. Theses hosts will consume their energy from the
 battery until the battery is empty or until the connection between the hosts and the battery is set inactive.
 
 Handlers
-......
+........
 
 You can schedule handlers that will happen at specific SoC of the battery and trigger a callback.
 Theses handlers may be recurrent, for instance you may want to always set all loads to zero and deactivate all hosts
 connections when the battery reaches 20% SoC.
 
 
 You can schedule handlers that will happen at specific SoC of the battery and trigger a callback.
 Theses handlers may be recurrent, for instance you may want to always set all loads to zero and deactivate all hosts
 connections when the battery reaches 20% SoC.
 
+Connector
+.........
+
+A Battery can act as a connector to connect Solar Panels direcly to loads. Such Battery is created without any
+parameter, cannot store energy and has a transfer efficiency of 100%.
+
   @endrst
  */
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(Battery, kernel, "Logging specific to the battery plugin");
   @endrst
  */
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(Battery, kernel, "Logging specific to the battery plugin");
@@ -107,6 +110,11 @@ void BatteryModel::update_actions_state(double now, double delta)
 
 double BatteryModel::next_occurring_event(double now)
 {
 
 double BatteryModel::next_occurring_event(double now)
 {
+  static bool init = false;
+  if (!init) {
+    init = true;
+    return 0;
+  }
   double time_delta = -1;
   for (auto battery : batteries_) {
     double time_delta_battery = battery->next_occurring_handler();
   double time_delta = -1;
   for (auto battery : batteries_) {
     double time_delta_battery = battery->next_occurring_handler();
@@ -117,15 +125,15 @@ double BatteryModel::next_occurring_event(double now)
 
 /* Handler */
 
 
 /* Handler */
 
-Battery::Handler::Handler(double state_of_charge, Flow flow,  bool repeat, std::function<void()> callback)
-    : state_of_charge_(state_of_charge), flow_(flow), callback_(callback), repeat_(repeat)
+Battery::Handler::Handler(double state_of_charge, Flow flow, Persistancy p, std::function<void()> callback)
+    : state_of_charge_(state_of_charge), flow_(flow), callback_(callback), persistancy_(p)
 {
 }
 
 {
 }
 
-std::shared_ptr<Battery::Handler> Battery::Handler::init(double state_of_charge, Flow flow, bool repeat,
+std::shared_ptr<Battery::Handler> Battery::Handler::init(double state_of_charge, Flow flow, Persistancy p,
                                                          std::function<void()> callback)
 {
                                                          std::function<void()> callback)
 {
-  return std::make_shared<Battery::Handler>(state_of_charge, flow, repeat, callback);
+  return std::make_shared<Battery::Handler>(state_of_charge, flow, p, callback);
 }
 
 /* Battery */
 }
 
 /* Battery */
@@ -154,12 +162,15 @@ void Battery::update()
     double consumed_power_w = 0;
     for (auto const& [host, active] : host_loads_)
       provided_power_w += active ? sg_host_get_current_consumption(host) : 0;
     double consumed_power_w = 0;
     for (auto const& [host, active] : host_loads_)
       provided_power_w += active ? sg_host_get_current_consumption(host) : 0;
-    for (auto const& [name, load] : named_loads_) {
-      if (load > 0)
-        provided_power_w += load;
+    for (auto const& [name, pair] : named_loads_) {
+      if (not pair.first)
+        continue;
+      if (pair.second > 0)
+        provided_power_w += pair.second;
       else
       else
-        consumed_power_w += -load;
+        consumed_power_w += -pair.second;
     }
     }
+
     provided_power_w = std::min(provided_power_w, nominal_discharge_power_w_ * discharge_efficiency_);
     consumed_power_w = std::min(consumed_power_w, -nominal_charge_power_w_);
 
     provided_power_w = std::min(provided_power_w, nominal_discharge_power_w_ * discharge_efficiency_);
     consumed_power_w = std::min(consumed_power_w, -nominal_charge_power_w_);
 
@@ -182,6 +193,14 @@ void Battery::update()
     // Updating battery
     energy_provided_j_ += energy_lost_delta_j * discharge_efficiency_;
     energy_consumed_j_ += energy_gained_delta_j / charge_efficiency_;
     // Updating battery
     energy_provided_j_ += energy_lost_delta_j * discharge_efficiency_;
     energy_consumed_j_ += energy_gained_delta_j / charge_efficiency_;
+
+    // This battery is a simple connector, we only update energy provided and consumed
+    if (energy_budget_j_ == 0) {
+      energy_consumed_j_ = energy_provided_j_;
+      last_updated_      = now;
+      return;
+    }
+
     capacity_wh_ =
         initial_capacity_wh_ *
         (1 - (energy_provided_j_ / discharge_efficiency_ + energy_consumed_j_ * charge_efficiency_) / energy_budget_j_);
     capacity_wh_ =
         initial_capacity_wh_ *
         (1 - (energy_provided_j_ / discharge_efficiency_ + energy_consumed_j_ * charge_efficiency_) / energy_budget_j_);
@@ -189,18 +208,16 @@ void Battery::update()
     energy_stored_j_ = std::min(energy_stored_j_, 3600 * capacity_wh_);
     last_updated_    = now;
 
     energy_stored_j_ = std::min(energy_stored_j_, 3600 * capacity_wh_);
     last_updated_    = now;
 
-    std::vector<std::shared_ptr<Handler>> to_delete = {};
-    for (auto handler : handlers_) {
+    auto handlers_2 = handlers_;
+    for (auto handler : handlers_2) {
       if (abs(handler->time_delta_ - time_delta_s) < 0.000000001) {
         handler->callback_();
       if (abs(handler->time_delta_ - time_delta_s) < 0.000000001) {
         handler->callback_();
-        if (handler->repeat_)
+        if (handler->persistancy_ == Handler::Persistancy::PERSISTANT)
           handler->time_delta_ = -1;
         else
           handler->time_delta_ = -1;
         else
-          to_delete.push_back(handler);
+          delete_handler(handler);
       }
     }
       }
     }
-    for (auto handler : to_delete)
-      delete_handler(handler);
   });
 }
 
   });
 }
 
@@ -210,11 +227,13 @@ double Battery::next_occurring_handler()
   double consumed_power_w = 0;
   for (auto const& [host, active] : host_loads_)
     provided_power_w += active ? sg_host_get_current_consumption(host) : 0;
   double consumed_power_w = 0;
   for (auto const& [host, active] : host_loads_)
     provided_power_w += active ? sg_host_get_current_consumption(host) : 0;
-  for (auto const& [name, load] : named_loads_) {
-    if (load > 0)
-      provided_power_w += load;
+  for (auto const& [name, pair] : named_loads_) {
+    if (not pair.first)
+      continue;
+    if (pair.second > 0)
+      provided_power_w += pair.second;
     else
     else
-      consumed_power_w += -load;
+      consumed_power_w += -pair.second;
   }
 
   provided_power_w = std::min(provided_power_w, nominal_discharge_power_w_ * discharge_efficiency_);
   }
 
   provided_power_w = std::min(provided_power_w, nominal_discharge_power_w_ * discharge_efficiency_);
@@ -224,10 +243,11 @@ double Battery::next_occurring_handler()
   for (auto& handler : handlers_) {
     double lost_power_w   = provided_power_w / discharge_efficiency_;
     double gained_power_w = consumed_power_w * charge_efficiency_;
   for (auto& handler : handlers_) {
     double lost_power_w   = provided_power_w / discharge_efficiency_;
     double gained_power_w = consumed_power_w * charge_efficiency_;
-    // Handler cannot happen
-    if ((lost_power_w == gained_power_w) or (handler->state_of_charge_ == energy_stored_j_ / (3600 * capacity_wh_)) or
-        (lost_power_w > gained_power_w and handler->flow_ == Flow::CHARGE) or
-        (lost_power_w < gained_power_w and handler->flow_ == Flow::DISCHARGE)) {
+    if ((lost_power_w == gained_power_w) or (handler->state_of_charge_ == get_state_of_charge()) or
+        (lost_power_w > gained_power_w and
+         (handler->flow_ == Flow::CHARGE or handler->state_of_charge_ > get_state_of_charge())) or
+        (lost_power_w < gained_power_w and
+         (handler->flow_ == Flow::DISCHARGE or handler->state_of_charge_ < get_state_of_charge()))) {
       continue;
     }
     // Evaluate time until handler happen
       continue;
     }
     // Evaluate time until handler happen
@@ -263,7 +283,7 @@ Battery::Battery(const std::string& name, double state_of_charge, double nominal
     , capacity_wh_(initial_capacity_wh)
     , energy_stored_j_(state_of_charge * 3600 * initial_capacity_wh)
 {
     , capacity_wh_(initial_capacity_wh)
     , energy_stored_j_(state_of_charge * 3600 * initial_capacity_wh)
 {
-  xbt_assert(nominal_charge_power_w <= 0, " : nominal charge power must be non-negative (provided: %f)",
+  xbt_assert(nominal_charge_power_w <= 0, " : nominal charge power must be <= 0 (provided: %f)",
              nominal_charge_power_w);
   xbt_assert(nominal_discharge_power_w >= 0, " : nominal discharge power must be non-negative (provided: %f)",
              nominal_discharge_power_w);
              nominal_charge_power_w);
   xbt_assert(nominal_discharge_power_w >= 0, " : nominal discharge power must be non-negative (provided: %f)",
              nominal_discharge_power_w);
@@ -277,11 +297,29 @@ Battery::Battery(const std::string& name, double state_of_charge, double nominal
   xbt_assert(cycles > 0, " : cycles should be > 0 (provided: %d)", cycles);
 }
 
   xbt_assert(cycles > 0, " : cycles should be > 0 (provided: %d)", cycles);
 }
 
+/** @ingroup plugin_battery
+ *  @brief Init a Battery with this constructor makes it only usable as a connector.
+ *         A connector has no capacity and only delivers as much power as it receives
+           with a transfer efficiency of 100%.
+ *  @return A BatteryPtr pointing to the new Battery.
+ */
+BatteryPtr Battery::init()
+{
+  static bool plugin_inited = false;
+  if (not plugin_inited) {
+    init_plugin();
+    plugin_inited = true;
+  }
+  auto battery = BatteryPtr(new Battery());
+  battery_model_->add_battery(battery);
+  return battery;
+}
+
 /** @ingroup plugin_battery
  *  @param name The name of the Battery.
  *  @param state_of_charge The initial state of charge of the Battery [0,1].
 /** @ingroup plugin_battery
  *  @param name The name of the Battery.
  *  @param state_of_charge The initial state of charge of the Battery [0,1].
- *  @param nominal_charge_power_w The maximum power delivered by the Battery in W (<= 0).
- *  @param nominal_discharge_power_w The maximum power absorbed by the Battery in W (>= 0).
+ *  @param nominal_charge_power_w The maximum power absorbed by the Battery in W (<= 0).
+ *  @param nominal_discharge_power_w The maximum power delivered by the Battery in W (>= 0).
  *  @param charge_efficiency The charge efficiency of the Battery [0,1].
  *  @param discharge_efficiency The discharge efficiency of the Battery [0,1].
  *  @param initial_capacity_wh The initial capacity of the Battery in Wh (>0).
  *  @param charge_efficiency The charge efficiency of the Battery [0,1].
  *  @param discharge_efficiency The discharge efficiency of the Battery [0,1].
  *  @param initial_capacity_wh The initial capacity of the Battery in Wh (>0).
@@ -309,7 +347,21 @@ BatteryPtr Battery::init(const std::string& name, double state_of_charge, double
  */
 void Battery::set_load(const std::string& name, double power_w)
 {
  */
 void Battery::set_load(const std::string& name, double power_w)
 {
-  named_loads_[name] = power_w;
+  kernel::actor::simcall_answered([this, &name, &power_w] {
+    if (named_loads_.find(name) == named_loads_.end())
+      named_loads_[name] = std::make_pair(true, power_w);
+    else
+      named_loads_[name].second = power_w;
+  });
+}
+
+/** @ingroup plugin_battery
+ *  @param name The name of the load
+ *  @param active Status of the load. If false then the load is ignored by the Battery.
+ */
+void Battery::set_load(const std::string& name, bool active)
+{
+  kernel::actor::simcall_answered([this, &name, &active] { named_loads_[name].first = active; });
 }
 
 /** @ingroup plugin_battery
 }
 
 /** @ingroup plugin_battery
@@ -322,7 +374,7 @@ void Battery::set_load(const std::string& name, double power_w)
  */
 void Battery::connect_host(s4u::Host* host, bool active)
 {
  */
 void Battery::connect_host(s4u::Host* host, bool active)
 {
-  host_loads_[host] = active;
+  kernel::actor::simcall_answered([this, &host, &active] { host_loads_[host] = active; });
 }
 
 /** @ingroup plugin_battery
 }
 
 /** @ingroup plugin_battery
@@ -389,12 +441,13 @@ double Battery::get_energy_stored(std::string unit)
  *  @param state_of_charge The state of charge at which the Handler will happen.
  *  @param flow The flow in which the Handler will happen, either when the Battery is charging or discharging.
  *  @param callback The callable to trigger when the Handler happen.
  *  @param state_of_charge The state of charge at which the Handler will happen.
  *  @param flow The flow in which the Handler will happen, either when the Battery is charging or discharging.
  *  @param callback The callable to trigger when the Handler happen.
- *  @param repeat If the Handler is recurrent or unique.
+ *  @param p If the Handler is recurrent or unique.
  *  @return A shared pointer of the new Handler.
  */
  *  @return A shared pointer of the new Handler.
  */
-std::shared_ptr<Battery::Handler> Battery::schedule_handler(double state_of_charge, Flow flow, bool repeat, std::function<void()> callback)
+std::shared_ptr<Battery::Handler> Battery::schedule_handler(double state_of_charge, Flow flow, Handler::Persistancy p,
+                                                            std::function<void()> callback)
 {
 {
-  auto handler = Handler::init(state_of_charge, flow, repeat, callback);
+  auto handler = Handler::init(state_of_charge, flow, p, callback);
   handlers_.push_back(handler);
   return handler;
 }
   handlers_.push_back(handler);
   return handler;
 }