Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Various sonar cleanups
[simgrid.git] / src / plugins / battery.cpp
index 412b69e..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"
@@ -84,6 +81,12 @@ You can schedule handlers that will happen at specific SoC of the battery and tr
 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