1 /* Copyright (c) 2023. The SimGrid Team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
5 #include <simgrid/Exception.hpp>
6 #include <simgrid/plugins/photovoltaic.hpp>
7 #include <simgrid/s4u/Actor.hpp>
8 #include <simgrid/s4u/Engine.hpp>
9 #include <simgrid/s4u/Host.hpp>
10 #include <simgrid/s4u/VirtualMachine.hpp>
11 #include <simgrid/simix.hpp>
13 #include "src/kernel/resource/CpuImpl.hpp"
14 #include "src/simgrid/module.hpp"
16 #include <boost/algorithm/string/classification.hpp>
17 #include <boost/algorithm/string/split.hpp>
19 SIMGRID_REGISTER_PLUGIN(photovoltaic, "Photovoltaic management", &sg_photovoltaic_plugin_init)
21 /** @defgroup plugin_photovoltaic plugin_photovoltaic Plugin photovoltaic
25 This is the photovoltaic plugin, enabling management of photovoltaic panels on hosts.
26 To activate this plugin, first call :cpp:func:`sg_photovoltaic_plugin_init()`.
28 This plugin allows evaluation of photovoltaic panels power generation during simulation depending on size, solar
29 irradiance and conversion factor.
31 The power model is taken from the paper `"Reinforcement Learning Based Load Balancing for
32 Geographically Distributed Data Centres" <https://dro.dur.ac.uk/33395/1/33395.pdf?DDD280+kkgc95+vbdv77>`_ by Max Mackie et. al.
34 The cost model is taken from the chapter 4 of the thesis `Sizing and Operation of Multi-Energy Hydrogen-Based
35 Microgrids <https://tel.archives-ouvertes.fr/tel-02077668/document>`_ by Bei Li.
37 Photovoltaic Panel properties
40 Properties of panels are defined as properties of hosts in the platform XML file.
42 Here is an example of XML declaration where we consider a host as a photovoltaic panel:
46 <host id="pv_panel" speed="0f">
47 <prop id="photovoltaic_area" value="4" />
48 <prop id="photovoltaic_conversion_efficiency" value="0.2" />
51 The different properties are:
53 - ``photovoltaic_area``: Set the area of the panel in m² (default=0)
54 - ``photovoltaic_conversion_efficiency``: Set the conversion efficiency of the panel (default=0)
55 - ``photovoltaic_solar_irradiance``: Set the initial solar irradiance in W/m² (default=0)
56 - ``photovoltaic_min_power``: Set the minimum power of the panel in W (default=-1). Power generation below this value is automatically 0. Value is ignored if negative
57 - ``photovoltaic_max_power``: Set the maximal power of the panel in W (default=-1). Power generation above this value is automatically truncated. Value is ignored if negative
58 - ``photovoltaic_eval_cost``: Evaluate the cost of the panel during the simulation if set to 1 (defaulf=0)
59 - ``photovoltaic_lifespan``: Set the lifespan of the panel in years (default=0)
60 - ``photovoltaic_investment_cost``: Set the investment cost of the panel (default=0)
61 - ``photovoltaic_maintenance_cost``: Set the maintenance cost of the panel (default=0)
66 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(photovoltaic, kernel, "Logging specific to the photovoltaic plugin");
68 namespace simgrid::plugin {
71 simgrid::s4u::Host* host_ = nullptr;
74 double conversion_efficiency_ = 0;
75 double solar_irradiance_w_per_m2_ = 0;
76 double min_power_w_ = -1;
77 double max_power_w_ = -1;
80 double last_updated_ = 0;
82 bool eval_cost_ = false;
83 double cumulative_cost_ = 0;
84 int lifespan_years_ = 0;
85 double investment_cost_per_w_ = 0;
86 double maintenance_cost_per_wh_ = 0;
88 void init_photovoltaic_params();
89 void init_cost_params();
92 Photovoltaic* set_area(double a);
93 Photovoltaic* set_conversion_efficiency(double e);
94 Photovoltaic* set_min_power(double p);
95 Photovoltaic* set_max_power(double p);
96 Photovoltaic* set_eval_cost(bool eval);
97 Photovoltaic* set_lifespan(int l);
98 Photovoltaic* set_investment_cost(double c);
99 Photovoltaic* set_maintenance_cost(double c);
102 static simgrid::xbt::Extension<simgrid::s4u::Host, Photovoltaic> EXTENSION_ID;
104 explicit Photovoltaic(simgrid::s4u::Host* host);
107 Photovoltaic* set_solar_irradiance(double s);
112 Photovoltaic* Photovoltaic::set_area(double a)
114 xbt_assert(a > 0, " : area should be > 0 (provided: %f)", a);
115 simgrid::kernel::actor::simcall_answered([this, a] { area_m2_ = a; });
119 Photovoltaic* Photovoltaic::set_conversion_efficiency(double e)
121 xbt_assert(e > 0 and e <= 1, " : conversion efficiency should be in [0,1] (provided: %f)", e);
122 simgrid::kernel::actor::simcall_answered([this, e] { conversion_efficiency_ = e; });
126 Photovoltaic* Photovoltaic::set_solar_irradiance(double s)
128 xbt_assert(s > 0, " : solar irradiance should be > 0 (provided: %f)", s);
129 simgrid::kernel::actor::simcall_answered([this, s] { solar_irradiance_w_per_m2_ = s; });
133 Photovoltaic* Photovoltaic::set_min_power(double p)
135 simgrid::kernel::actor::simcall_answered([this, p] { min_power_w_ = p; });
139 Photovoltaic* Photovoltaic::set_max_power(double p)
141 simgrid::kernel::actor::simcall_answered([this, p] { max_power_w_ = p; });
145 Photovoltaic* Photovoltaic::set_eval_cost(bool e)
147 simgrid::kernel::actor::simcall_answered([this, e] { eval_cost_ = e; });
151 Photovoltaic* Photovoltaic::set_lifespan(int l)
153 xbt_assert(l > 0, " : lifespan should be > 0 (provided: %d)", l);
154 simgrid::kernel::actor::simcall_answered([this, l] { lifespan_years_ = l; });
158 Photovoltaic* Photovoltaic::set_investment_cost(double c)
160 xbt_assert(c > 0, " : investment cost should be > 0 (provided: %f)", c);
161 simgrid::kernel::actor::simcall_answered([this, c] { investment_cost_per_w_ = c; });
165 Photovoltaic* Photovoltaic::set_maintenance_cost(double c)
167 xbt_assert(c > 0, " : maintenance cost hould be > 0 (provided: %f)", c);
168 simgrid::kernel::actor::simcall_answered([this, c] { maintenance_cost_per_wh_ = c; });
172 double Photovoltaic::get_power()
178 simgrid::xbt::Extension<simgrid::s4u::Host, Photovoltaic> Photovoltaic::EXTENSION_ID;
180 void Photovoltaic::init_photovoltaic_params()
182 const char* prop_chars;
183 prop_chars = host_->get_property("photovoltaic_area");
185 set_area(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
186 prop_chars = host_->get_property("photovoltaic_conversion_efficiency");
188 set_conversion_efficiency(
189 xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
190 prop_chars = host_->get_property("photovoltaic_solar_irradiance");
192 set_solar_irradiance(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
193 prop_chars = host_->get_property("photovoltaic_min_power");
195 set_min_power(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
196 prop_chars = host_->get_property("photovoltaic_max_power");
198 set_max_power(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
199 prop_chars = host_->get_property("photovoltaic_eval_cost");
201 set_eval_cost(xbt_str_parse_int(prop_chars, ("cannot parse int: " + std::string(prop_chars)).c_str()));
202 prop_chars = host_->get_property("photovoltaic_lifespan");
204 set_lifespan(xbt_str_parse_int(prop_chars, ("cannot parse int: " + std::string(prop_chars)).c_str()));
205 prop_chars = host_->get_property("photovoltaic_investment_cost");
207 set_investment_cost(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
208 prop_chars = host_->get_property("photovoltaic_maintenance_cost");
210 set_maintenance_cost(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
211 simgrid::kernel::actor::simcall_answered([this] { last_updated_ = simgrid::s4u::Engine::get_clock(); });
214 void Photovoltaic::update()
216 simgrid::kernel::actor::simcall_answered([this] {
217 double now = simgrid::s4u::Engine::get_clock();
218 if (now <= last_updated_)
220 double power_w = conversion_efficiency_ * area_m2_ * solar_irradiance_w_per_m2_;
221 if (min_power_w_ > 0 && power_w_ < min_power_w_)
223 if (max_power_w_ > 0 && power_w_ > max_power_w_)
224 power_w = max_power_w_;
227 xbt_assert(max_power_w_ > 0, " : max power must be > 0 (provided: %f)", max_power_w_);
228 cumulative_cost_ += max_power_w_ * (now - last_updated_) *
229 (investment_cost_per_w_ / (lifespan_years_ * 8760 * 3600) + maintenance_cost_per_wh_ / 3600);
235 Photovoltaic::Photovoltaic(simgrid::s4u::Host* host) : host_(host)
237 init_photovoltaic_params();
240 Photovoltaic::~Photovoltaic() = default;
241 } // namespace simgrid::plugin
243 using simgrid::plugin::Photovoltaic;
245 /* **************************** events callback *************************** */
247 static void on_creation(simgrid::s4u::Host& host)
249 if (dynamic_cast<simgrid::s4u::VirtualMachine*>(&host)) // Ignore virtual machines
251 host.extension_set(new Photovoltaic(&host));
254 /* **************************** Public interface *************************** */
256 static void ensure_plugin_inited()
258 if (not Photovoltaic::EXTENSION_ID.valid())
259 throw simgrid::xbt::InitializationError(
260 "The Photovoltaic plugin is not active. Please call sg_photovoltaic_plugin_init() "
261 "before calling any function related to that plugin.");
264 /** @ingroup plugin_photovoltaic
265 * @brief Enable photovoltaic plugin.
267 void sg_photovoltaic_plugin_init()
269 if (Photovoltaic::EXTENSION_ID.valid())
271 Photovoltaic::EXTENSION_ID = simgrid::s4u::Host::extension_create<Photovoltaic>();
272 simgrid::s4u::Host::on_creation_cb(&on_creation);
275 /** @ingroup plugin_photovoltaic
276 * @param s The solar irradiance to set in W/m².
278 void sg_photovoltaic_set_solar_irradiance(const_sg_host_t host, double s)
280 ensure_plugin_inited();
281 host->extension<Photovoltaic>()->set_solar_irradiance(s);
284 /** @ingroup plugin_photovoltaic
285 * @return Power generation in W.
287 double sg_photovoltaic_get_power(const_sg_host_t host)
289 ensure_plugin_inited();
290 return host->extension<Photovoltaic>()->get_power();