From 05ea8b91f5cb2baace69b4373f4fab3c7465b116 Mon Sep 17 00:00:00 2001 From: Adrien Gougeon Date: Mon, 9 Oct 2023 17:51:47 +0200 Subject: [PATCH] add possibility for a battery to be a simple connector and an example. add power change callback for chiller and update example. fix some issues with batteries andchillers updates. --- MANIFEST.in | 2 + examples/cpp/CMakeLists.txt | 2 +- .../s4u-battery-chiller-solar.cpp | 13 ---- .../s4u-battery-connector.cpp | 63 +++++++++++++++++++ .../s4u-battery-connector.tesh | 13 ++++ .../cpp/chiller-simple/s4u-chiller-simple.cpp | 38 +++-------- .../chiller-simple/s4u-chiller-simple.tesh | 25 ++++---- include/simgrid/plugins/battery.hpp | 19 +++--- include/simgrid/plugins/chiller.hpp | 10 +++ src/plugins/battery.cpp | 44 ++++++++++++- src/plugins/chiller.cpp | 49 +++++++++++---- 11 files changed, 198 insertions(+), 80 deletions(-) create mode 100644 examples/cpp/battery-connector/s4u-battery-connector.cpp create mode 100644 examples/cpp/battery-connector/s4u-battery-connector.tesh diff --git a/MANIFEST.in b/MANIFEST.in index 5e93c83d5e..422f0e42c9 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -168,6 +168,8 @@ include examples/cpp/app-token-ring/s4u-app-token-ring.cpp include examples/cpp/app-token-ring/s4u-app-token-ring.tesh include examples/cpp/battery-chiller-solar/s4u-battery-chiller-solar.cpp include examples/cpp/battery-chiller-solar/s4u-battery-chiller-solar.tesh +include examples/cpp/battery-connector/s4u-battery-connector.cpp +include examples/cpp/battery-connector/s4u-battery-connector.tesh include examples/cpp/battery-degradation/plot_battery_degradation.py include examples/cpp/battery-degradation/s4u-battery-degradation.cpp include examples/cpp/battery-degradation/s4u-battery-degradation.tesh diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt index abda1093ca..a0fc73f401 100644 --- a/examples/cpp/CMakeLists.txt +++ b/examples/cpp/CMakeLists.txt @@ -157,7 +157,7 @@ foreach (example activityset-testany activityset-waitany activityset-waitall act actor-create actor-daemon actor-exiting actor-join actor-kill actor-lifetime actor-migrate actor-suspend actor-yield actor-stacksize app-bittorrent app-chainsend app-token-ring - battery-chiller-solar battery-degradation battery-simple battery-energy + battery-chiller-solar battery-connector battery-degradation battery-simple battery-energy chiller-simple comm-pingpong comm-ready comm-suspend comm-wait comm-waituntil comm-dependent comm-host2host comm-failure comm-throttling diff --git a/examples/cpp/battery-chiller-solar/s4u-battery-chiller-solar.cpp b/examples/cpp/battery-chiller-solar/s4u-battery-chiller-solar.cpp index 454b2590cd..c428b32948 100644 --- a/examples/cpp/battery-chiller-solar/s4u-battery-chiller-solar.cpp +++ b/examples/cpp/battery-chiller-solar/s4u-battery-chiller-solar.cpp @@ -66,18 +66,6 @@ static void end_manager(sp::BatteryPtr b) b->delete_handler(handler); } -static void logger(sp::BatteryPtr battery, sp::SolarPanelPtr solar_panel, sp::ChillerPtr chiller, sg4::Host* host1, - sg4::Host* host2) -{ - while (true) { - XBT_INFO("SoC: %f Solar_Power: %f E_chiller: %f E_hosts_brown: %f E_hosts_green: %f", - battery->get_state_of_charge(), solar_panel->get_power(), chiller->get_energy_consumed(), - sg_host_get_consumed_energy(host1) + sg_host_get_consumed_energy(host2) - battery->get_energy_provided(), - battery->get_energy_provided()); - simgrid::s4u::this_actor::sleep_for(100); - } -} - int main(int argc, char* argv[]) { sg4::Engine e(&argc, argv); @@ -113,7 +101,6 @@ int main(int argc, char* argv[]) 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); - // sg4::Actor::create("logger", myhost1, logger, battery, solar_panel, chiller, myhost1, myhost2)->daemonize(); e.run(); XBT_INFO("State of charge of the battery: %0.1f%%", battery->get_state_of_charge() * 100); diff --git a/examples/cpp/battery-connector/s4u-battery-connector.cpp b/examples/cpp/battery-connector/s4u-battery-connector.cpp new file mode 100644 index 0000000000..b4d9434580 --- /dev/null +++ b/examples/cpp/battery-connector/s4u-battery-connector.cpp @@ -0,0 +1,63 @@ +/* Copyright (c) 2017-2023. The SimGrid Team. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * 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 solar panel is connected to the connector and power a host. +*/ + +#include "simgrid/plugins/battery.hpp" +#include "simgrid/plugins/chiller.hpp" +#include "simgrid/plugins/energy.h" +#include "simgrid/plugins/solar_panel.hpp" +#include "simgrid/s4u.hpp" +#include +#include +#include + +XBT_LOG_NEW_DEFAULT_CATEGORY(battery_chiller_solar, "Messages specific for this s4u example"); +namespace sg4 = simgrid::s4u; +namespace sp = simgrid::plugins; + +int main(int argc, char* argv[]) +{ + sg4::Engine e(&argc, argv); + e.load_platform(argv[1]); + sg_host_energy_plugin_init(); + + auto myhost1 = e.host_by_name("MyHost1"); + + auto connector = sp::Battery::init(); + auto solar_panel = sp::SolarPanel::init("Solar Panel", 1, 1, 200, 0, 1e3); + + connector->set_load("Solar Panel", solar_panel->get_power() * -1); + connector->connect_host(myhost1); + + solar_panel->on_this_power_change_cb([connector](sp::SolarPanel *s) { + connector->set_load("Solar Panel", s->get_power() * -1); + }); + + sg4::Actor::create("manager", myhost1, [&myhost1, & solar_panel, &connector]{ + XBT_INFO("Solar Panel power = %.2fW, MyHost1 power = %.2fW. The Solar Panel provides more than needed.", solar_panel->get_power(), sg_host_get_current_consumption(myhost1)); + simgrid::s4u::this_actor::sleep_for(100); + XBT_INFO("Energy consumption MyHost1: %.2fkJ, Energy from the Solar Panel %.2fkJ", sg_host_get_consumed_energy(myhost1) / 1e3, connector->get_energy_provided() / 1e3); + + solar_panel->set_solar_irradiance(100); + XBT_INFO("Solar Panel power = %.2fW, MyHost1 power = %.2fW. The Solar Panel provides exactly what is needed.", solar_panel->get_power(), sg_host_get_current_consumption(myhost1)); + double last_measure_host_energy = sg_host_get_consumed_energy(myhost1); + double last_measure_connector_energy = connector->get_energy_provided(); + + simgrid::s4u::this_actor::sleep_for(100); + XBT_INFO("Energy consumption MyHost1: %.2fkJ, Energy from the Solar Panel %.2fkJ", (sg_host_get_consumed_energy(myhost1) - last_measure_host_energy) / 1e3, (connector->get_energy_provided() - last_measure_connector_energy) / 1e3); + + XBT_INFO("MyHost1 executes something for 100s. The Solar Panel does not provide enough energy."); + last_measure_host_energy = sg_host_get_consumed_energy(myhost1); + last_measure_connector_energy = connector->get_energy_provided(); + myhost1->execute(100 * myhost1->get_speed()); + XBT_INFO("Energy MyHost1: %.2fkJ, Energy from the Solar Panel %.2fkJ", (sg_host_get_consumed_energy(myhost1) - last_measure_host_energy) / 1e3, (connector->get_energy_provided() - last_measure_connector_energy) / 1e3); + }); + + e.run(); + return 0; +} diff --git a/examples/cpp/battery-connector/s4u-battery-connector.tesh b/examples/cpp/battery-connector/s4u-battery-connector.tesh new file mode 100644 index 0000000000..2dd264da3f --- /dev/null +++ b/examples/cpp/battery-connector/s4u-battery-connector.tesh @@ -0,0 +1,13 @@ +#!/usr/bin/env tesh + +$ ${bindir:=.}/s4u-battery-connector ${platfdir}/energy_platform.xml +> [MyHost1:manager:(1) 0.000000] [battery_chiller_solar/INFO] Solar Panel power = 200.00W, MyHost1 power = 100.00W. The Solar Panel provides more than needed. +> [MyHost1:manager:(1) 100.000000] [battery_chiller_solar/INFO] Energy consumption MyHost1: 10.00kJ, Energy from the Solar Panel 10.00kJ +> [MyHost1:manager:(1) 100.000000] [battery_chiller_solar/INFO] Solar Panel power = 100.00W, MyHost1 power = 100.00W. The Solar Panel provides exactly what is needed. +> [MyHost1:manager:(1) 200.000000] [battery_chiller_solar/INFO] Energy consumption MyHost1: 10.00kJ, Energy from the Solar Panel 10.00kJ +> [MyHost1:manager:(1) 200.000000] [battery_chiller_solar/INFO] MyHost1 executes something for 100s. The Solar Panel does not provide enough energy. +> [MyHost1:manager:(1) 300.000000] [battery_chiller_solar/INFO] Energy MyHost1: 12.00kJ, Energy from the Solar Panel 10.00kJ +> [300.000000] [host_energy/INFO] Total energy consumption: 92000.000000 Joules (used hosts: 32000.000000 Joules; unused/idle hosts: 60000.000000) +> [300.000000] [host_energy/INFO] Energy consumption of host MyHost1: 32000.000000 Joules +> [300.000000] [host_energy/INFO] Energy consumption of host MyHost2: 30000.000000 Joules +> [300.000000] [host_energy/INFO] Energy consumption of host MyHost3: 30000.000000 Joules \ No newline at end of file diff --git a/examples/cpp/chiller-simple/s4u-chiller-simple.cpp b/examples/cpp/chiller-simple/s4u-chiller-simple.cpp index c5a45b3d16..079d7c5b39 100644 --- a/examples/cpp/chiller-simple/s4u-chiller-simple.cpp +++ b/examples/cpp/chiller-simple/s4u-chiller-simple.cpp @@ -16,49 +16,21 @@ static void manager(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(), c->get_energy_consumed()); - XBT_INFO("The machines slowly heat up the room."); - simgrid::s4u::this_actor::sleep_until(400); - 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()); - simgrid::s4u::this_actor::sleep_until(800); - 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()); simgrid::s4u::this_actor::sleep_until(1000); XBT_INFO("The Chiller now compensates the heat generated by the machines."); - 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()); simgrid::s4u::this_actor::sleep_until(1200); - 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()); - XBT_INFO("Let's compute something."); sg4::this_actor::exec_async(1e10); - simgrid::s4u::this_actor::sleep_until(1250); - 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()); - simgrid::s4u::this_actor::sleep_until(1300); XBT_INFO("Computation done."); - simgrid::s4u::this_actor::sleep_until(1400); - 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()); - 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(1600); - 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()); - simgrid::s4u::this_actor::sleep_until(1800); - 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()); + + simgrid::s4u::this_actor::sleep_until(1900); simgrid::s4u::this_actor::sleep_until(2000); - 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()); - simgrid::s4u::this_actor::sleep_until(2200); - 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()); + simgrid::s4u::this_actor::sleep_until(2100); } int main(int argc, char* argv[]) @@ -72,6 +44,10 @@ int main(int argc, char* argv[]) 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()); + }); e.run(); return 0; diff --git a/examples/cpp/chiller-simple/s4u-chiller-simple.tesh b/examples/cpp/chiller-simple/s4u-chiller-simple.tesh index c1d4c27f46..cdad59de11 100644 --- a/examples/cpp/chiller-simple/s4u-chiller-simple.tesh +++ b/examples/cpp/chiller-simple/s4u-chiller-simple.tesh @@ -4,21 +4,18 @@ $ ${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. -> [MyHost1:sender:(1) 400.000000] [chiller_simple/INFO] Chiller: Power: 0.000000W T_in: 23.486875°C Energy consumed: 0.000000J -> [MyHost1:sender:(1) 800.000000] [chiller_simple/INFO] Chiller: Power: 0.000000W T_in: 23.973749°C Energy consumed: 0.000000J +> [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. -> [MyHost1:sender:(1) 1000.000000] [chiller_simple/INFO] Chiller: Power: 356.866667W T_in: 24.000000°C Energy consumed: 71373.333333J -> [MyHost1:sender:(1) 1200.000000] [chiller_simple/INFO] Chiller: Power: 400.000000W T_in: 24.000000°C Energy consumed: 151373.333333J +> [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. -> [MyHost1:sender:(1) 1250.000000] [chiller_simple/INFO] Chiller: Power: 426.666667W T_in: 24.000000°C Energy consumed: 172706.666667J +> [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. -> [MyHost1:sender:(1) 1400.000000] [chiller_simple/INFO] Chiller: Power: 400.000000W T_in: 24.000000°C Energy consumed: 234040.000000J +> [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. -> [MyHost1:sender:(1) 1600.000000] [chiller_simple/INFO] Chiller: Power: 1000.000000W T_in: 23.634844°C Energy consumed: 434040.000000J -> [MyHost1:sender:(1) 1800.000000] [chiller_simple/INFO] Chiller: Power: 1000.000000W T_in: 23.269688°C Energy consumed: 634040.000000J -> [MyHost1:sender:(1) 2000.000000] [chiller_simple/INFO] Chiller: Power: 843.133333W T_in: 23.000000°C Energy consumed: 802666.666667J -> [MyHost1:sender:(1) 2200.000000] [chiller_simple/INFO] Chiller: Power: 400.000000W T_in: 23.000000°C Energy consumed: 882666.666667J -> [2200.000000] [host_energy/INFO] Total energy consumption: 662000.000000 Joules (used hosts: 222000.000000 Joules; unused/idle hosts: 440000.000000) -> [2200.000000] [host_energy/INFO] Energy consumption of host MyHost1: 222000.000000 Joules -> [2200.000000] [host_energy/INFO] Energy consumption of host MyHost2: 220000.000000 Joules -> [2200.000000] [host_energy/INFO] Energy consumption of host MyHost3: 220000.000000 Joules +> [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 diff --git a/include/simgrid/plugins/battery.hpp b/include/simgrid/plugins/battery.hpp index 64c97532da..058428beb4 100644 --- a/include/simgrid/plugins/battery.hpp +++ b/include/simgrid/plugins/battery.hpp @@ -6,6 +6,7 @@ #ifndef SIMGRID_PLUGINS_BATTERY_HPP_ #define SIMGRID_PLUGINS_BATTERY_HPP_ +#include #include #include #include @@ -87,23 +88,24 @@ private: static std::shared_ptr battery_model_; std::string name_; - double nominal_charge_power_w_; - double nominal_discharge_power_w_; - double charge_efficiency_; - double discharge_efficiency_; - double initial_capacity_wh_; - double energy_budget_j_; + double nominal_charge_power_w_ = -INFINITY; + double nominal_discharge_power_w_ = INFINITY; + double charge_efficiency_ = 1; + double discharge_efficiency_ = 1; + double initial_capacity_wh_ = 0; + double energy_budget_j_ = 0; std::map host_loads_ = {}; std::map> named_loads_ = {}; std::vector> handlers_; - double capacity_wh_; - double energy_stored_j_; + double capacity_wh_ = 0; + double energy_stored_j_ = 0; double energy_provided_j_ = 0; double energy_consumed_j_ = 0; double last_updated_ = 0; + explicit Battery(); explicit Battery(const std::string& name, double state_of_charge, double nominal_charge_power_w, double nominal_discharge_power_w, double charge_efficiency, double discharge_efficiency, double initial_capacity_wh, int cycles); @@ -124,6 +126,7 @@ private: #endif public: + static BatteryPtr init(); static BatteryPtr init(const std::string& name, double state_of_charge, double nominal_charge_power_w, double nominal_discharge_power_w, double charge_efficiency, double discharge_efficiency, double initial_capacity_wh, int cycles); diff --git a/include/simgrid/plugins/chiller.hpp b/include/simgrid/plugins/chiller.hpp index b60e03dc82..f0297fabd9 100644 --- a/include/simgrid/plugins/chiller.hpp +++ b/include/simgrid/plugins/chiller.hpp @@ -68,6 +68,9 @@ private: friend void intrusive_ptr_add_ref(Chiller* o) { o->refcount_.fetch_add(1, std::memory_order_relaxed); } #endif + inline static xbt::signal on_power_change; + xbt::signal on_this_power_change; + public: static ChillerPtr init(const std::string& name, double air_mass_kg, double specific_heat_j_per_kg_per_c, double alpha, double cooling_efficiency, double initial_temp_c, double goal_temp_c, double max_power_w); @@ -96,6 +99,13 @@ public: 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& 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& cb) { on_power_change.connect(cb); } }; } // namespace simgrid::plugins diff --git a/src/plugins/battery.cpp b/src/plugins/battery.cpp index bf18ae1946..9639bf67e5 100644 --- a/src/plugins/battery.cpp +++ b/src/plugins/battery.cpp @@ -81,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"); @@ -104,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(); @@ -159,6 +170,7 @@ void Battery::update() else 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_); @@ -181,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_); @@ -252,6 +272,8 @@ double Battery::next_occurring_handler() return time_delta; } +Battery::Battery() {} + Battery::Battery(const std::string& name, double state_of_charge, double nominal_charge_power_w, double nominal_discharge_power_w, double charge_efficiency, double discharge_efficiency, double initial_capacity_wh, int cycles) @@ -279,11 +301,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). diff --git a/src/plugins/chiller.cpp b/src/plugins/chiller.cpp index 501f155865..b0c814e5db 100644 --- a/src/plugins/chiller.cpp +++ b/src/plugins/chiller.cpp @@ -75,7 +75,19 @@ void ChillerModel::update_actions_state(double now, double delta) double ChillerModel::next_occurring_event(double now) { - return -1; + static bool init = false; + if (!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; } /* Chiller */ @@ -105,7 +117,7 @@ void Chiller::update() 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) { + if (not active_ or delta_temp_c <= 0) { temp_in_c_ = temp_out_c_; power_w_ = 0; last_updated_ = now; @@ -113,17 +125,16 @@ void Chiller::update() } double cooling_demand_w = delta_temp_c * air_mass_kg_ * specific_heat_j_per_kg_per_c_ / time_delta_s; - if (cooling_demand_w / cooling_efficiency_ <= max_power_w_) { - 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_); - } else { - power_w_ = max_power_w_; - temp_in_c_ = temp_out_c_ - - (power_w_ * time_delta_s * cooling_efficiency_) / (air_mass_kg_ * specific_heat_j_per_kg_per_c_); - } + double previous_power_w = power_w_; + 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; }); } @@ -284,4 +295,20 @@ ChillerPtr Chiller::remove_host(s4u::Host* host) return this; } +/** @ingroup plugin_chiller + * @return Time of the next event, i.e., + when the chiller will reach the goal temp if possible, -1 otherwise. + */ +double Chiller::get_next_event() +{ + if (not is_active() or goal_temp_c_ <= temp_out_c_) + 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; + } +} } // namespace simgrid::plugins -- 2.20.1