Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' into simgrid-fork-changelog-plugins
authorMartin Quinson <martin.quinson@ens-rennes.fr>
Fri, 3 Nov 2023 16:55:49 +0000 (17:55 +0100)
committerMartin Quinson <martin.quinson@ens-rennes.fr>
Fri, 3 Nov 2023 16:55:49 +0000 (17:55 +0100)
ChangeLog
docs/source/Plugins.rst
docs/source/Release_Notes.rst
examples/cpp/battery-chiller-solar/s4u-battery-chiller-solar.cpp
examples/cpp/battery-connector/s4u-battery-connector.cpp
examples/cpp/chiller-simple/s4u-chiller-simple.cpp
examples/cpp/chiller-simple/s4u-chiller-simple.tesh
include/simgrid/plugins/chiller.hpp
src/plugins/chiller.cpp

index e90432e..0da01dd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,6 +9,9 @@ S4U:
  - Introduce a Mailbox::get_async() with no payload parameter. You can use the new
    Comm::get_payload() once the communication is over to retrieve the payload.
  - Implement recursive mutexes. Simply pass true to the constructor to get one.
+ - Update of the Task model. Each Task now consists of a dispatcher, a collector
+   and one or more instances. The parallelism degree of each of these can be set.
+   Several examples have been added or modified accordingly.
  - Introduce a new MessageQueue abstraction and associated Mess simulated object.
    The behavior of a MessageQueue is similar to that of a Mailbox, but intended for
    control messages that do not incur any simulated cost. Information is automagically
@@ -36,6 +39,8 @@ C API:
 Plugins:
  - Revamp the battery plugin: rewrite completely the API, for a better usability.
    The examples were updated accordingly.
+   The battery can now act as a simple connector. See battery-connector example.
+ - Revamp of the Photovoltaic plugin: now called SolarPanel and complete rewrite of the API 
  - Revamp of the Photovoltaic plugin: now called SolarPanel and complete rewrite of the API
  - Add chiller plugin: enable the management of chillers consuming electrical energy
    to compensate heat generated by hosts.
index 659e67c..c40e5e6 100644 (file)
@@ -25,6 +25,7 @@ documents some of the plugins distributed with SimGrid:
   - :ref:`WiFi Energy <plugin_link_energy_wifi>`: models the energy dissipation of wifi links.
   - :ref:`Battery <plugin_battery>`: models batteries that get discharged by the energy consumption of a given host.
   - :ref:`Solar Panel <plugin_solar_panel>`: models solar panels which energy production depends on the solar irradiance.
+  - :ref:`Chiller <plugin_chiller>`: models chillers which dissipate heat by consuming energy.
 
 You can activate these plugins with the :ref:`--cfg=plugin <cfg=plugin>` command
 line option, for example with ``--cfg=plugin:host_energy``. You can get the full
@@ -231,11 +232,11 @@ Solar Panel
 
 .. doxygengroup:: plugin_solar_panel
 
+.. _plugin_chiller:
+
 Chiller
 =======
 
 .. doxygengroup:: plugin_chiller
 
-   .. doxygentypedef:: ChillerPtr
-
 ..  LocalWords:  SimGrid
index 992a1b0..346f563 100644 (file)
@@ -626,9 +626,10 @@ reacting to every signals of a class, and then filtering on the object you want.
 completion) are now specialized by activity class. That is, callbacks registered in Exec::on_suspend_cb will not be fired for
 Comms nor Ios
 
-Two new useful plugins were added: The :ref:`battery plugin<plugin_battery>` can be used to create batteries that get discharged
-by the energy consumption of a given host, while the :ref:`solar panel plugin <plugin_solar_panel>` can be used to create
-solar panels which energy production depends on the solar irradiance. These plugins could probably be better integrated
+Three new useful plugins were added: The :ref:`battery plugin<plugin_battery>` can be used to create batteries that get discharged
+by the energy consumption of a given host, the :ref:`solar panel plugin <plugin_solar_panel>` can be used to create
+solar panels which energy production depends on the solar irradiance and the :ref:`chiller plugin <plugin_chiller>` can be used to
+create chillers and compensate the heat generated by hosts. These plugins could probably be better integrated
 in the framework, but our goal is to include in SimGrid the building blocks upon which everybody would agree, while the model
 elements that are more arguable are provided as plugins, in the hope that the users will carefully assess the plugins and adapt
 them to their specific needs before usage. Here for example, there is several models of batteries (the one provided does not
index c428b32..00fff06 100644 (file)
@@ -82,6 +82,8 @@ int main(int argc, char* argv[])
   chiller->add_host(myhost2);
   solar_panel->on_this_power_change_cb(
       [battery](sp::SolarPanel* s) { battery->set_load("Solar Panel", s->get_power() * -1); });
+
+  // These handlers connect/disconnect the solar panel and the hosts depending on the state of charge of the battery
   battery->schedule_handler(0.8, sp::Battery::CHARGE, sp::Battery::Handler::PERSISTANT,
                             [battery]() { battery->set_load("Solar Panel", false); });
   battery->schedule_handler(0.75, sp::Battery::DISCHARGE, sp::Battery::Handler::PERSISTANT,
@@ -97,10 +99,17 @@ int main(int argc, char* argv[])
                               battery->connect_host(myhost2);
                             });
 
+  /* Handlers create simulation events preventing the simulation from finishing
+     To avoid this behaviour this actor sleeps for 2 days and then delete all handlers
+  */
+  sg4::Actor::create("end_manager", myhost1, end_manager, battery);
+
+  // This actor updates the solar irradiance of the solar panel
   sg4::Actor::create("irradiance_manager", myhost1, irradiance_manager, solar_panel)->daemonize();
+
+  // These actors start a job on a host for a specific duration
   sg4::Actor::create("host_job_manager", myhost1, host_job_manager, 12 * 60 * 60, 4 * 60 * 60);
   sg4::Actor::create("host_job_manager", myhost2, host_job_manager, 12 * 60 * 60, 4 * 60 * 60);
-  sg4::Actor::create("end_manager", myhost1, end_manager, battery);
 
   e.run();
   XBT_INFO("State of charge of the battery: %0.1f%%", battery->get_state_of_charge() * 100);
index b4d9434..b3a8588 100644 (file)
@@ -4,6 +4,8 @@
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
 /* This example shows how to use the battery as a connector.
+   A connector has no capacity and only delivers as much power as it receives
+   with a transfer efficiency of 100%.
    A solar panel is connected to the connector and power a host.
 */
 
index 079d7c5..db48b65 100644 (file)
@@ -6,31 +6,44 @@
 #include "simgrid/plugins/chiller.hpp"
 #include "simgrid/plugins/energy.h"
 #include "simgrid/s4u.hpp"
-#include <xbt/log.h>
 
 XBT_LOG_NEW_DEFAULT_CATEGORY(chiller_simple, "Messages specific for this s4u example");
 namespace sg4 = simgrid::s4u;
 
-static void manager(simgrid::plugins::ChillerPtr c)
+static void display_chiller(simgrid::plugins::ChillerPtr c)
 {
-  XBT_INFO("Initial state: ");
-  XBT_INFO("%s: Power: %fW T_in: %f°C Energy consumed: %fJ", c->get_cname(), c->get_power(), c->get_temp_in(),
+  XBT_INFO("%s: Power: %.2fW T_in: %.2f°C Energy consumed: %.2fJ", c->get_cname(), c->get_power(), c->get_temp_in(),
            c->get_energy_consumed());
-  XBT_INFO("The machines slowly heat up the room.");
-  simgrid::s4u::this_actor::sleep_until(1000);
-  XBT_INFO("The Chiller now compensates the heat generated by the machines.");
-  simgrid::s4u::this_actor::sleep_until(1200);
+}
+
+static void manager(simgrid::plugins::ChillerPtr c)
+{
+  display_chiller(c);
+
+  simgrid::s4u::this_actor::sleep_for(c->get_time_to_goal_temp());
+  XBT_INFO("The input temperature is now equal to the goal temperature. After this point the Chiller will compensate "
+           "heat with electrical power.");
+  display_chiller(c);
+
+  simgrid::s4u::this_actor::sleep_for(1);
+  display_chiller(c);
+
   XBT_INFO("Let's compute something.");
-  sg4::this_actor::exec_async(1e10);
-  simgrid::s4u::this_actor::sleep_until(1300);
+  sg4::this_actor::execute(1e10);
   XBT_INFO("Computation done.");
-  simgrid::s4u::this_actor::sleep_until(1400);
+  display_chiller(c);
   XBT_INFO("Now let's stress the chiller by decreasing the goal temperature to 23°C.");
   c->set_goal_temp(23);
 
-  simgrid::s4u::this_actor::sleep_until(1900);
-  simgrid::s4u::this_actor::sleep_until(2000);
-  simgrid::s4u::this_actor::sleep_until(2100);
+  simgrid::s4u::this_actor::sleep_for(1);
+  display_chiller(c);
+
+  simgrid::s4u::this_actor::sleep_for(c->get_time_to_goal_temp());
+  XBT_INFO("The input temperature is back to the goal temperature.");
+  display_chiller(c);
+
+  simgrid::s4u::this_actor::sleep_for(1);
+  display_chiller(c);
 }
 
 int main(int argc, char* argv[])
@@ -43,11 +56,7 @@ int main(int argc, char* argv[])
   chiller->add_host(e.host_by_name("MyHost1"));
   chiller->add_host(e.host_by_name("MyHost2"));
   chiller->add_host(e.host_by_name("MyHost3"));
-  sg4::Actor::create("sender", e.host_by_name("MyHost1"), manager, chiller);
-  chiller->on_power_change_cb([](simgrid::plugins::Chiller* c) {
-    XBT_INFO("%s: Power: %fW T_in: %f°C Energy consumed: %fJ", c->get_cname(), c->get_power(), c->get_temp_in(),
-             c->get_energy_consumed());
-  });
+  sg4::Actor::create("manager", e.host_by_name("MyHost1"), manager, chiller);
 
   e.run();
   return 0;
index cdad59d..33e196f 100644 (file)
@@ -1,21 +1,19 @@
 #!/usr/bin/env tesh
 
 $ ${bindir:=.}/s4u-chiller-simple ${platfdir}/energy_platform.xml
-> [MyHost1:sender:(1) 0.000000] [chiller_simple/INFO] Initial state: 
-> [MyHost1:sender:(1) 0.000000] [chiller_simple/INFO] Chiller: Power: 0.000000W T_in: 23.000000°C Energy consumed: 0.000000J
-> [MyHost1:sender:(1) 0.000000] [chiller_simple/INFO] The machines slowly heat up the room.
-> [1000.000000] [chiller_simple/INFO] Chiller: Power: 400.000000W T_in: 24.000000°C Energy consumed: 71373.333333J
-> [MyHost1:sender:(1) 1000.000000] [chiller_simple/INFO] The Chiller now compensates the heat generated by the machines.
-> [1200.000000] [chiller_simple/INFO] Chiller: Power: 400.000000W T_in: 24.000000°C Energy consumed: 151373.333333J
-> [MyHost1:sender:(1) 1200.000000] [chiller_simple/INFO] Let's compute something.
-> [1300.000000] [chiller_simple/INFO] Chiller: Power: 426.666667W T_in: 24.000000°C Energy consumed: 194040.000000J
-> [MyHost1:sender:(1) 1300.000000] [chiller_simple/INFO] Computation done.
-> [1400.000000] [chiller_simple/INFO] Chiller: Power: 400.000000W T_in: 24.000000°C Energy consumed: 234040.000000J
-> [MyHost1:sender:(1) 1400.000000] [chiller_simple/INFO] Now let's stress the chiller by decreasing the goal temperature to 23°C.
-> [1900.000000] [chiller_simple/INFO] Chiller: Power: 1000.000000W T_in: 23.087110°C Energy consumed: 734040.000000J
-> [2000.000000] [chiller_simple/INFO] Chiller: Power: 686.266667W T_in: 23.000000°C Energy consumed: 802666.666667J
-> [2100.000000] [chiller_simple/INFO] Chiller: Power: 400.000000W T_in: 23.000000°C Energy consumed: 842666.666667J
-> [2100.000000] [host_energy/INFO] Total energy consumption: 632000.000000 Joules (used hosts: 212000.000000 Joules; unused/idle hosts: 420000.000000)
-> [2100.000000] [host_energy/INFO] Energy consumption of host MyHost1: 212000.000000 Joules
-> [2100.000000] [host_energy/INFO] Energy consumption of host MyHost2: 210000.000000 Joules
-> [2100.000000] [host_energy/INFO] Energy consumption of host MyHost3: 210000.000000 Joules
\ No newline at end of file
+> [MyHost1:manager:(1) 0.000000] [chiller_simple/INFO] Chiller: Power: 0.00W T_in: 23.00°C Energy consumed: 0.00J
+> [MyHost1:manager:(1) 821.566667] [chiller_simple/INFO] The input temperature is now equal to the goal temperature. After this point the Chiller will compensate heat with electrical power.
+> [MyHost1:manager:(1) 821.566667] [chiller_simple/INFO] Chiller: Power: 0.00W T_in: 24.00°C Energy consumed: 0.00J
+> [MyHost1:manager:(1) 822.566667] [chiller_simple/INFO] Chiller: Power: 400.00W T_in: 24.00°C Energy consumed: 400.00J
+> [MyHost1:manager:(1) 822.566667] [chiller_simple/INFO] Let's compute something.
+> [MyHost1:manager:(1) 922.566667] [chiller_simple/INFO] Computation done.
+> [MyHost1:manager:(1) 922.566667] [chiller_simple/INFO] Chiller: Power: 426.67W T_in: 24.00°C Energy consumed: 43066.67J
+> [MyHost1:manager:(1) 922.566667] [chiller_simple/INFO] Now let's stress the chiller by decreasing the goal temperature to 23°C.
+> [MyHost1:manager:(1) 923.566667] [chiller_simple/INFO] Chiller: Power: 1000.00W T_in: 24.00°C Energy consumed: 44066.67J
+> [MyHost1:manager:(1) 1470.277778] [chiller_simple/INFO] The input temperature is back to the goal temperature.
+> [MyHost1:manager:(1) 1470.277778] [chiller_simple/INFO] Chiller: Power: 1000.00W T_in: 23.00°C Energy consumed: 590777.78J
+> [MyHost1:manager:(1) 1471.277778] [chiller_simple/INFO] Chiller: Power: 400.00W T_in: 23.00°C Energy consumed: 591177.78J
+> [1471.277778] [host_energy/INFO] Total energy consumption: 443383.333333 Joules (used hosts: 149127.777778 Joules; unused/idle hosts: 294255.555556)
+> [1471.277778] [host_energy/INFO] Energy consumption of host MyHost1: 149127.777778 Joules
+> [1471.277778] [host_energy/INFO] Energy consumption of host MyHost2: 147127.777778 Joules
+> [1471.277778] [host_energy/INFO] Energy consumption of host MyHost3: 147127.777778 Joules
\ No newline at end of file
index f0297fa..8f9611b 100644 (file)
@@ -96,16 +96,9 @@ public:
   double get_max_power() { return max_power_w_; }
   bool is_active() { return active_; }
   double get_temp_in() { return temp_in_c_; }
-  double get_temp_out() { return temp_out_c_; }
   double get_power() { return power_w_; }
   double get_energy_consumed() { return energy_consumed_j_; }
-  double get_next_event();
-
-  /** Add a callback fired after this chiller power changed. */
-  void on_this_power_change_cb(const std::function<void(Chiller*)>& func) { on_this_power_change.connect(func); };
-  /** Add a callback fired after a chiller power changed.
-   * Triggered after the on_this_power_change function.**/
-  static void on_power_change_cb(const std::function<void(Chiller*)>& cb) { on_power_change.connect(cb); }
+  double get_time_to_goal_temp();
 };
 
 } // namespace simgrid::plugins
index b0c814e..3cec29d 100644 (file)
@@ -34,7 +34,7 @@ from the heat of the other devices, such as lighing, accounted using a factor :m
 
   Q_{room} = (1 + \alpha) \times Q_{machines}
 
-This energy heats the input temperature :math:`T_{in}` and gives an output temperature :math:`T_{out}` based on the the
+This energy heats the input temperature :math:`T_{in}` and gives an output temperature :math:`T_{out}` based on the
 mass of air inside the room :math:`m_{air}` and its specific heat :math:`C_{p}`:
 
 .. math::
@@ -76,18 +76,11 @@ void ChillerModel::update_actions_state(double now, double delta)
 double ChillerModel::next_occurring_event(double now)
 {
   static bool init = false;
-  if (!init) {
+  if (not init) {
     init = true;
     return 0;
-  }
-  double next_event = -1;
-  double tmp;
-  for (auto chiller : chillers_) {
-    tmp = chiller->get_next_event();
-    if (tmp != -1 and (next_event == -1 or tmp < next_event))
-      next_event = tmp;
-  }
-  return next_event;
+  } else
+    return -1;
 }
 
 /* Chiller */
@@ -111,30 +104,21 @@ void Chiller::update()
       return;
 
     double hosts_power_w = 0;
-    for (auto const& host : hosts_)
+    for (auto const& host : hosts_) {
       hosts_power_w += sg_host_get_current_consumption(host);
-    double heat_generated_j = hosts_power_w * (1 + alpha_) * time_delta_s;
-    temp_out_c_             = temp_in_c_ + heat_generated_j / (air_mass_kg_ * specific_heat_j_per_kg_per_c_);
-    double delta_temp_c     = temp_out_c_ - goal_temp_c_;
-
-    if (not active_ or delta_temp_c <= 0) {
-      temp_in_c_    = temp_out_c_;
-      power_w_      = 0;
-      last_updated_ = now;
-      return;
     }
 
-    double cooling_demand_w = delta_temp_c * air_mass_kg_ * specific_heat_j_per_kg_per_c_ / time_delta_s;
-    double previous_power_w = power_w_;
-    power_w_                = std::min(max_power_w_, cooling_demand_w / cooling_efficiency_);
+    double heat_generated_j = hosts_power_w * (1 + alpha_) * time_delta_s;
+    temp_out_c_             = temp_in_c_ + heat_generated_j / (air_mass_kg_ * specific_heat_j_per_kg_per_c_);
+    double cooling_demand_w =
+        std::max(temp_out_c_ - goal_temp_c_, 0.0) * air_mass_kg_ * specific_heat_j_per_kg_per_c_ / time_delta_s;
+    if (not active_)
+      power_w_ = 0;
+    else
+      power_w_ = std::min(max_power_w_, cooling_demand_w / cooling_efficiency_);
     temp_in_c_ =
         temp_out_c_ - (power_w_ * time_delta_s * cooling_efficiency_) / (air_mass_kg_ * specific_heat_j_per_kg_per_c_);
-
     energy_consumed_j_ += power_w_ * time_delta_s;
-    if (previous_power_w != power_w_) {
-      on_this_power_change(this);
-      on_power_change(this);
-    }
     last_updated_ = now;
   });
 }
@@ -296,19 +280,25 @@ ChillerPtr Chiller::remove_host(s4u::Host* host)
 }
 
 /** @ingroup plugin_chiller
- *  @return Time of the next event, i.e.,
- when the chiller will reach the goal temp if possible, -1 otherwise.
+ *  @return The time to reach to goal temp, assuming that the system remain in the same state.
  */
-double Chiller::get_next_event()
+double Chiller::get_time_to_goal_temp()
 {
-  if (not is_active() or goal_temp_c_ <= temp_out_c_)
+  if (goal_temp_c_ == temp_in_c_)
+    return 0;
+
+  double heat_power_w = 0;
+  for (auto const& host : hosts_)
+    heat_power_w += sg_host_get_current_consumption(host);
+  heat_power_w = heat_power_w * (1 + alpha_);
+
+  if (temp_in_c_ < goal_temp_c_)
+    return air_mass_kg_ * (goal_temp_c_ - temp_in_c_) * specific_heat_j_per_kg_per_c_ / heat_power_w;
+
+  if (not active_)
     return -1;
-  else {
-    double heat_power_w = 0;
-    for (auto const& host : hosts_)
-      heat_power_w += sg_host_get_current_consumption(host);
-    heat_power_w = heat_power_w * (1 + alpha_);
-    return air_mass_kg_ * (goal_temp_c_ - temp_out_c_) * specific_heat_j_per_kg_per_c_ / heat_power_w;
-  }
+  else
+    return air_mass_kg_ * (temp_in_c_ - goal_temp_c_) * specific_heat_j_per_kg_per_c_ /
+           (power_w_ * cooling_efficiency_ - heat_power_w);
 }
 } // namespace simgrid::plugins