Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
5131dd5f916e1bfbdf97301f6947bbaf20d14fb0
[simgrid.git] / src / plugins / photovoltaic.cpp
1 #include <simgrid/Exception.hpp>
2 #include <simgrid/plugins/photovoltaic.hpp>
3 #include <simgrid/s4u/Actor.hpp>
4 #include <simgrid/s4u/Engine.hpp>
5 #include <simgrid/s4u/Host.hpp>
6 #include <simgrid/s4u/VirtualMachine.hpp>
7 #include <simgrid/simix.hpp>
8
9 #include "src/kernel/resource/CpuImpl.hpp"
10 #include "src/simgrid/module.hpp"
11
12 #include <boost/algorithm/string/classification.hpp>
13 #include <boost/algorithm/string/split.hpp>
14
15 SIMGRID_REGISTER_PLUGIN(photovoltaic, "Photovoltaic management", &sg_photovoltaic_plugin_init)
16
17 /** @defgroup plugin_photovoltaic plugin_photovoltaic Plugin photovoltaic
18
19   @beginrst
20
21 This is the photovoltaic plugin, enabling management of photovoltaic panels on hosts.
22 To activate this plugin, first call :cpp:func:`sg_photovoltaic_plugin_init()`.
23
24 This plugin allows evaluation of photovoltaic panels power generation during simulation depending on size, solar
25 irradiance and conversion factor.
26
27 Photovoltaic Panel properties
28 ....................
29
30 Properties of panels are defined as properties of hosts in the platform XML file.
31
32 Here is an example of XML declaration where we consider a host as a photovoltaic panel:
33
34 .. code-block:: xml
35
36    <host id="pv_panel" speed="0f">
37       <prop id="photovoltaic_area" value="4" />
38       <prop id="photovoltaic_conversion_efficiency" value="0.2" />
39     </host>
40
41 The different properties are:
42
43 - ``photovoltaic_area``: Set the area of the panel in m² (default=0)
44 - ``photovoltaic_conversion_efficiency``: Set the conversion efficiency of the panel (default=0)
45 - ``photovoltaic_solar_irradiance``: Set the initial solar irradiance in W/m² (default=0)
46 - ``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
47 - ``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
48 - ``photovoltaic_eval_cost``: Evaluate the cost of the panel during the simulation if set to 1 (defaulf=0)
49 - ``photovoltaic_lifespan``: Set the lifespan of the panel in years (default=0)
50 - ``photovoltaic_investment_cost``: Set the investment cost of the panel (default=0)
51 - ``photovoltaic_maintenance_cost``: Set the maintenance cost of the panel (default=0)
52
53   @endrst
54  */
55
56 /*These equations are taken from  the paper "Reinforcement Learning Based Load Balancing for
57 Geographically Distributed Data Centres"  of Max Mackie et. al
58 https://dro.dur.ac.uk/33395/1/33395.pdf?DDD280+kkgc95+vbdv77
59 */
60
61 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(photovoltaic, kernel, "Logging specific to the photovoltaic plugin");
62
63 namespace simgrid::plugin {
64 class Photovoltaic {
65 private:
66   simgrid::s4u::Host* host_ = nullptr;
67
68   double area_m2_                   = 0;
69   double conversion_efficiency_     = 0;
70   double solar_irradiance_w_per_m2_ = 0;
71   double min_power_w_               = -1;
72   double max_power_w_               = -1;
73
74   double power_w_      = 0;
75   double last_updated_ = 0;
76
77   // Calculation of costs from Bei Li thesis (link :https://tel.archives-ouvertes.fr/tel-02077668/document) (chapter 4)
78   bool eval_cost_                 = false;
79   double cumulative_cost_         = 0;
80   int lifespan_years_             = 0;
81   double investment_cost_per_w_   = 0;
82   double maintenance_cost_per_wh_ = 0;
83
84   void init_photovoltaic_params();
85   void init_cost_params();
86   void update();
87
88   Photovoltaic* set_area(double a);
89   Photovoltaic* set_conversion_efficiency(double e);
90   Photovoltaic* set_min_power(double p);
91   Photovoltaic* set_max_power(double p);
92   Photovoltaic* set_eval_cost(bool eval);
93   Photovoltaic* set_lifespan(int l);
94   Photovoltaic* set_investment_cost(double c);
95   Photovoltaic* set_maintenance_cost(double c);
96
97 public:
98   static simgrid::xbt::Extension<simgrid::s4u::Host, Photovoltaic> EXTENSION_ID;
99
100   explicit Photovoltaic(simgrid::s4u::Host* host);
101   ~Photovoltaic();
102
103   Photovoltaic* set_solar_irradiance(double s);
104
105   double get_power();
106 };
107
108 Photovoltaic* Photovoltaic::set_area(double a)
109 {
110   xbt_assert(a > 0, " : area should be > 0 (provided: %f)", a);
111   simgrid::kernel::actor::simcall_answered([this, a] { area_m2_ = a; });
112   return this;
113 }
114
115 Photovoltaic* Photovoltaic::set_conversion_efficiency(double e)
116 {
117   xbt_assert(e > 0 and e <= 1, " : conversion efficiency should be in [0,1] (provided: %f)", e);
118   simgrid::kernel::actor::simcall_answered([this, e] { conversion_efficiency_ = e; });
119   return this;
120 }
121
122 Photovoltaic* Photovoltaic::set_solar_irradiance(double s)
123 {
124   xbt_assert(s > 0, " : solar irradiance should be > 0 (provided: %f)", s);
125   simgrid::kernel::actor::simcall_answered([this, s] { solar_irradiance_w_per_m2_ = s; });
126   return this;
127 }
128
129 Photovoltaic* Photovoltaic::set_min_power(double p)
130 {
131   simgrid::kernel::actor::simcall_answered([this, p] { min_power_w_ = p; });
132   return this;
133 }
134
135 Photovoltaic* Photovoltaic::set_max_power(double p)
136 {
137   simgrid::kernel::actor::simcall_answered([this, p] { max_power_w_ = p; });
138   return this;
139 }
140
141 Photovoltaic* Photovoltaic::set_eval_cost(bool e)
142 {
143   simgrid::kernel::actor::simcall_answered([this, e] { eval_cost_ = e; });
144   return this;
145 }
146
147 Photovoltaic* Photovoltaic::set_lifespan(int l)
148 {
149   xbt_assert(l > 0, " : lifespan should be > 0 (provided: %d)", l);
150   simgrid::kernel::actor::simcall_answered([this, l] { lifespan_years_ = l; });
151   return this;
152 }
153
154 Photovoltaic* Photovoltaic::set_investment_cost(double c)
155 {
156   xbt_assert(c > 0, " : investment cost should be > 0 (provided: %f)", c);
157   simgrid::kernel::actor::simcall_answered([this, c] { investment_cost_per_w_ = c; });
158   return this;
159 }
160
161 Photovoltaic* Photovoltaic::set_maintenance_cost(double c)
162 {
163   xbt_assert(c > 0, " : maintenance cost hould be > 0 (provided: %f)", c);
164   simgrid::kernel::actor::simcall_answered([this, c] { maintenance_cost_per_wh_ = c; });
165   return this;
166 }
167
168 double Photovoltaic::get_power()
169 {
170   update();
171   return power_w_;
172 }
173
174 simgrid::xbt::Extension<simgrid::s4u::Host, Photovoltaic> Photovoltaic::EXTENSION_ID;
175
176 void Photovoltaic::init_photovoltaic_params()
177 {
178   const char* prop_chars;
179   prop_chars = host_->get_property("photovoltaic_area");
180   if (prop_chars)
181     set_area(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
182   prop_chars = host_->get_property("photovoltaic_conversion_efficiency");
183   if (prop_chars)
184     set_conversion_efficiency(
185         xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
186   prop_chars = host_->get_property("photovoltaic_solar_irradiance");
187   if (prop_chars)
188     set_solar_irradiance(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
189   prop_chars = host_->get_property("photovoltaic_min_power");
190   if (prop_chars)
191     set_min_power(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
192   prop_chars = host_->get_property("photovoltaic_max_power");
193   if (prop_chars)
194     set_max_power(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
195   prop_chars = host_->get_property("photovoltaic_eval_cost");
196   if (prop_chars)
197     set_eval_cost(xbt_str_parse_int(prop_chars, ("cannot parse int: " + std::string(prop_chars)).c_str()));
198   prop_chars = host_->get_property("photovoltaic_lifespan");
199   if (prop_chars)
200     set_lifespan(xbt_str_parse_int(prop_chars, ("cannot parse int: " + std::string(prop_chars)).c_str()));
201   prop_chars = host_->get_property("photovoltaic_investment_cost");
202   if (prop_chars)
203     set_investment_cost(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
204   prop_chars = host_->get_property("photovoltaic_maintenance_cost");
205   if (prop_chars)
206     set_maintenance_cost(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str()));
207   simgrid::kernel::actor::simcall_answered([this] { last_updated_ = simgrid::s4u::Engine::get_clock(); });
208 }
209
210 void Photovoltaic::update()
211 {
212   simgrid::kernel::actor::simcall_answered([this] {
213     double now = simgrid::s4u::Engine::get_clock();
214     if (now <= last_updated_)
215       return;
216     double power_w = conversion_efficiency_ * area_m2_ * solar_irradiance_w_per_m2_;
217     if (min_power_w_ > 0 and power_w_ < min_power_w_)
218       power_w = 0;
219     if (max_power_w_ > 0 and power_w_ > max_power_w_)
220       power_w = max_power_w_;
221     power_w_ = power_w;
222     if (eval_cost_) {
223       xbt_assert(max_power_w_ > 0, " : max power must be > 0 (provided: %f)", max_power_w_);
224       cumulative_cost_ += max_power_w_ * (now - last_updated_) *
225                           (investment_cost_per_w_ / (lifespan_years_ * 8760 * 3600) + maintenance_cost_per_wh_ / 3600);
226     }
227     last_updated_ = now;
228   });
229 }
230
231 Photovoltaic::Photovoltaic(simgrid::s4u::Host* host) : host_(host)
232 {
233   init_photovoltaic_params();
234 }
235
236 Photovoltaic::~Photovoltaic() = default;
237 } // namespace simgrid::plugin
238
239 using simgrid::plugin::Photovoltaic;
240
241 /* **************************** events  callback *************************** */
242
243 static void on_creation(simgrid::s4u::Host& host)
244 {
245   if (dynamic_cast<simgrid::s4u::VirtualMachine*>(&host)) // Ignore virtual machines
246     return;
247   host.extension_set(new Photovoltaic(&host));
248 }
249
250 /* **************************** Public interface *************************** */
251
252 static void ensure_plugin_inited()
253 {
254   if (not Photovoltaic::EXTENSION_ID.valid())
255     throw simgrid::xbt::InitializationError(
256         "The Photovoltaic plugin is not active. Please call sg_photovoltaic_plugin_init() "
257         "before calling any function related to that plugin.");
258 }
259
260 /** @ingroup plugin_photovoltaic
261  *  @brief Enable photovoltaic plugin.
262  */
263 void sg_photovoltaic_plugin_init()
264 {
265   if (Photovoltaic::EXTENSION_ID.valid())
266     return;
267   Photovoltaic::EXTENSION_ID = simgrid::s4u::Host::extension_create<Photovoltaic>();
268   simgrid::s4u::Host::on_creation_cb(&on_creation);
269 }
270
271 /** @ingroup plugin_photovoltaic
272  *  @param s The solar irradiance to set in W/m².
273  */
274 void sg_photovoltaic_set_solar_irradiance(const_sg_host_t host, double s)
275 {
276   ensure_plugin_inited();
277   host->extension<Photovoltaic>()->set_solar_irradiance(s);
278 }
279
280 /** @ingroup plugin_photovoltaic
281  *  @return Power generation in W.
282  */
283 double sg_photovoltaic_get_power(const_sg_host_t host)
284 {
285   ensure_plugin_inited();
286   return host->extension<Photovoltaic>()->get_power();
287 }