Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Various sonar cleanups
[simgrid.git] / src / plugins / battery.cpp
index 73da963..0cbfdbc 100644 (file)
@@ -6,10 +6,7 @@
 #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 <xbt/asserts.h>
-#include <xbt/log.h>
 
 #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
-..............
+.............
 
 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.
 
+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");
@@ -107,6 +110,11 @@ void BatteryModel::update_actions_state(double now, double delta)
 
 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();
@@ -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;
-    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
-        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_);
 
@@ -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_;
+
+    // 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_);
@@ -189,18 +208,16 @@ void Battery::update()
     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 (handler->persistancy_ == Handler::Persistancy::PERSISTANT)
           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;
-  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
-      consumed_power_w += -load;
+      consumed_power_w += -pair.second;
   }
 
   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_;
-    // 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
@@ -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)
 {
-  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);
@@ -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);
 }
 
+/** @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].
- *  @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).
@@ -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)
 {
-  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
@@ -322,7 +374,7 @@ void Battery::set_load(const std::string& name, double power_w)
  */
 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
@@ -389,7 +441,7 @@ 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 Persistancy If the Handler is recurrent or unique.
+ *  @param p If the Handler is recurrent or unique.
  *  @return A shared pointer of the new Handler.
  */
 std::shared_ptr<Battery::Handler> Battery::schedule_handler(double state_of_charge, Flow flow, Handler::Persistancy p,