From 3d162cea6ff3405edc06c1d7f85494eb15f35d82 Mon Sep 17 00:00:00 2001 From: Adrien Gougeon Date: Tue, 16 May 2023 16:07:34 +0200 Subject: [PATCH] add photovoltaic plugin --- ChangeLog | 5 + MANIFEST.in | 5 + docs/source/Plugins.rst | 7 + examples/cpp/CMakeLists.txt | 1 + .../s4u-photovoltaic-simple.cpp | 30 ++ .../s4u-photovoltaic-simple.tesh | 6 + examples/platforms/photovoltaic_platform.xml | 10 + include/simgrid/plugins/photovoltaic.hpp | 18 ++ src/plugins/photovoltaic.cpp | 287 ++++++++++++++++++ tools/cmake/DefinePackages.cmake | 3 + 10 files changed, 372 insertions(+) create mode 100644 examples/cpp/photovoltaic-simple/s4u-photovoltaic-simple.cpp create mode 100644 examples/cpp/photovoltaic-simple/s4u-photovoltaic-simple.tesh create mode 100644 examples/platforms/photovoltaic_platform.xml create mode 100644 include/simgrid/plugins/photovoltaic.hpp create mode 100644 src/plugins/photovoltaic.cpp diff --git a/ChangeLog b/ChangeLog index d68448eed3..8a065d91d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -30,6 +30,11 @@ New plugin: Battery - Enable the management of batteries on hosts. - Documentation: https://simgrid.frama.io/simgrid/Plugins.html#battery - Examples: examples/cpp/battery-* + +New plugin: Photovoltaic + - Enable the management of photovoltaic panels on hosts. + - Documentation: https://simgrid.frama.io/simgrid/Plugins.html#photovoltaic + - Examples: examples/cpp/photovoltaic-* Kernel: - optimize an internal datastructure (use a set instead of a list for ongoing activities), diff --git a/MANIFEST.in b/MANIFEST.in index 3a5d39ce5e..6c530f2b3e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -356,6 +356,8 @@ include examples/cpp/operation-switch-host/s4u-operation-switch-host.cpp include examples/cpp/operation-switch-host/s4u-operation-switch-host.tesh include examples/cpp/operation-variable-load/s4u-operation-variable-load.cpp include examples/cpp/operation-variable-load/s4u-operation-variable-load.tesh +include examples/cpp/photovoltaic-simple/s4u-photovoltaic-simple.cpp +include examples/cpp/photovoltaic-simple/s4u-photovoltaic-simple.tesh include examples/cpp/platform-comm-serialize/s4u-platform-comm-serialize.cpp include examples/cpp/platform-comm-serialize/s4u-platform-comm-serialize.tesh include examples/cpp/platform-failures/s4u-platform-failures.cpp @@ -1832,6 +1834,7 @@ include examples/platforms/onelink.xml include examples/platforms/optorsim/gridpp_grid_2004.conf include examples/platforms/optorsim/lcg_sept2004_grid.conf include examples/platforms/optorsim/transform_optorsim_platform.pl +include examples/platforms/photovoltaic_platform.xml include examples/platforms/profiles/fafard_state.profile include examples/platforms/profiles/faulty_host.profile include examples/platforms/profiles/ginette_state.profile @@ -1932,6 +1935,7 @@ include include/simgrid/plugins/live_migration.h include include/simgrid/plugins/load.h include include/simgrid/plugins/ns3.hpp include include/simgrid/plugins/operation.hpp +include include/simgrid/plugins/photovoltaic.hpp include include/simgrid/s4u.hpp include include/simgrid/s4u/Activity.hpp include include/simgrid/s4u/Actor.hpp @@ -2290,6 +2294,7 @@ include src/plugins/link_energy.cpp include src/plugins/link_energy_wifi.cpp include src/plugins/link_load.cpp include src/plugins/operation.cpp +include src/plugins/photovoltaic.cpp include src/plugins/vm/VmLiveMigration.cpp include src/plugins/vm/VmLiveMigration.hpp include src/plugins/vm/dirty_page_tracking.cpp diff --git a/docs/source/Plugins.rst b/docs/source/Plugins.rst index 2fae39481b..f5d8a1387e 100644 --- a/docs/source/Plugins.rst +++ b/docs/source/Plugins.rst @@ -173,4 +173,11 @@ Operation .. doxygengroup:: plugin_operation +.. _plugin_photovoltaic: + +Photovoltaic +=========== + +.. doxygengroup:: plugin_photovoltaic + .. LocalWords: SimGrid diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt index 76dc61ee4f..8b370a7856 100644 --- a/examples/cpp/CMakeLists.txt +++ b/examples/cpp/CMakeLists.txt @@ -169,6 +169,7 @@ foreach (example activity-testany activity-waitany network-ns3 network-ns3-wifi network-wifi io-async io-priority io-degradation io-file-system io-file-remote io-disk-raw io-dependent operation-simple operation-variable-load operation-switch-host + photovoltaic-simple platform-comm-serialize platform-failures platform-profile platform-properties plugin-host-load plugin-link-load plugin-prodcons replay-comm replay-io diff --git a/examples/cpp/photovoltaic-simple/s4u-photovoltaic-simple.cpp b/examples/cpp/photovoltaic-simple/s4u-photovoltaic-simple.cpp new file mode 100644 index 0000000000..25e8421669 --- /dev/null +++ b/examples/cpp/photovoltaic-simple/s4u-photovoltaic-simple.cpp @@ -0,0 +1,30 @@ +/* Copyright (c) 2003-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. */ + +#include "simgrid/plugins/photovoltaic.hpp" +#include "simgrid/s4u.hpp" + +XBT_LOG_NEW_DEFAULT_CATEGORY(photovoltaic_simple, "Messages specific for this s4u example"); + +static void manager() +{ + auto pv_panel = simgrid::s4u::Engine::get_instance()->host_by_name("pv_panel"); + std::vector> solar_irradiance = {{0, 10}, {100, 5}, {200, 20}}; + for (auto [t, s] : solar_irradiance) { + simgrid::s4u::this_actor::sleep_until(t); + sg_photovoltaic_set_solar_irradiance(pv_panel, s); + XBT_INFO("%s power: %f", pv_panel->get_cname(), sg_photovoltaic_get_power(pv_panel)); + } +} + +int main(int argc, char* argv[]) +{ + simgrid::s4u::Engine e(&argc, argv); + e.load_platform(argv[1]); + sg_photovoltaic_plugin_init(); + simgrid::s4u::Actor::create("manager", e.host_by_name("pv_panel"), manager); + e.run(); + return 0; +} diff --git a/examples/cpp/photovoltaic-simple/s4u-photovoltaic-simple.tesh b/examples/cpp/photovoltaic-simple/s4u-photovoltaic-simple.tesh new file mode 100644 index 0000000000..f8b3fa15e5 --- /dev/null +++ b/examples/cpp/photovoltaic-simple/s4u-photovoltaic-simple.tesh @@ -0,0 +1,6 @@ +#!/usr/bin/env tesh + +$ ${bindir:=.}/s4u-photovoltaic-simple ${platfdir}/photovoltaic_platform.xml +> [pv_panel:manager:(1) 0.000000] [photovoltaic_simple/INFO] pv_panel power: 0.000000 +> [pv_panel:manager:(1) 100.000000] [photovoltaic_simple/INFO] pv_panel power: 4.000000 +> [pv_panel:manager:(1) 200.000000] [photovoltaic_simple/INFO] pv_panel power: 16.000000 diff --git a/examples/platforms/photovoltaic_platform.xml b/examples/platforms/photovoltaic_platform.xml new file mode 100644 index 0000000000..8e499e1482 --- /dev/null +++ b/examples/platforms/photovoltaic_platform.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/include/simgrid/plugins/photovoltaic.hpp b/include/simgrid/plugins/photovoltaic.hpp new file mode 100644 index 0000000000..7cc1f3bdb0 --- /dev/null +++ b/include/simgrid/plugins/photovoltaic.hpp @@ -0,0 +1,18 @@ +#ifndef SIMGRID_PLUGINS_PHOTOVOLTAIC_H_ +#define SIMGRID_PLUGINS_PHOTOVOLTAIC_H_ + +#include +#include +#include + +SG_BEGIN_DECL + +XBT_PUBLIC void sg_photovoltaic_plugin_init(); + +XBT_PUBLIC void sg_photovoltaic_set_solar_irradiance(const_sg_host_t host, double s); + +XBT_PUBLIC double sg_photovoltaic_get_power(const_sg_host_t host); + +SG_END_DECL + +#endif diff --git a/src/plugins/photovoltaic.cpp b/src/plugins/photovoltaic.cpp new file mode 100644 index 0000000000..5131dd5f91 --- /dev/null +++ b/src/plugins/photovoltaic.cpp @@ -0,0 +1,287 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "src/kernel/resource/CpuImpl.hpp" +#include "src/simgrid/module.hpp" + +#include +#include + +SIMGRID_REGISTER_PLUGIN(photovoltaic, "Photovoltaic management", &sg_photovoltaic_plugin_init) + +/** @defgroup plugin_photovoltaic plugin_photovoltaic Plugin photovoltaic + + @beginrst + +This is the photovoltaic plugin, enabling management of photovoltaic panels on hosts. +To activate this plugin, first call :cpp:func:`sg_photovoltaic_plugin_init()`. + +This plugin allows evaluation of photovoltaic panels power generation during simulation depending on size, solar +irradiance and conversion factor. + +Photovoltaic Panel properties +.................... + +Properties of panels are defined as properties of hosts in the platform XML file. + +Here is an example of XML declaration where we consider a host as a photovoltaic panel: + +.. code-block:: xml + + + + + + +The different properties are: + +- ``photovoltaic_area``: Set the area of the panel in m² (default=0) +- ``photovoltaic_conversion_efficiency``: Set the conversion efficiency of the panel (default=0) +- ``photovoltaic_solar_irradiance``: Set the initial solar irradiance in W/m² (default=0) +- ``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 +- ``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 +- ``photovoltaic_eval_cost``: Evaluate the cost of the panel during the simulation if set to 1 (defaulf=0) +- ``photovoltaic_lifespan``: Set the lifespan of the panel in years (default=0) +- ``photovoltaic_investment_cost``: Set the investment cost of the panel (default=0) +- ``photovoltaic_maintenance_cost``: Set the maintenance cost of the panel (default=0) + + @endrst + */ + +/*These equations are taken from the paper "Reinforcement Learning Based Load Balancing for +Geographically Distributed Data Centres" of Max Mackie et. al +https://dro.dur.ac.uk/33395/1/33395.pdf?DDD280+kkgc95+vbdv77 +*/ + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(photovoltaic, kernel, "Logging specific to the photovoltaic plugin"); + +namespace simgrid::plugin { +class Photovoltaic { +private: + simgrid::s4u::Host* host_ = nullptr; + + double area_m2_ = 0; + double conversion_efficiency_ = 0; + double solar_irradiance_w_per_m2_ = 0; + double min_power_w_ = -1; + double max_power_w_ = -1; + + double power_w_ = 0; + double last_updated_ = 0; + + // Calculation of costs from Bei Li thesis (link :https://tel.archives-ouvertes.fr/tel-02077668/document) (chapter 4) + bool eval_cost_ = false; + double cumulative_cost_ = 0; + int lifespan_years_ = 0; + double investment_cost_per_w_ = 0; + double maintenance_cost_per_wh_ = 0; + + void init_photovoltaic_params(); + void init_cost_params(); + void update(); + + Photovoltaic* set_area(double a); + Photovoltaic* set_conversion_efficiency(double e); + Photovoltaic* set_min_power(double p); + Photovoltaic* set_max_power(double p); + Photovoltaic* set_eval_cost(bool eval); + Photovoltaic* set_lifespan(int l); + Photovoltaic* set_investment_cost(double c); + Photovoltaic* set_maintenance_cost(double c); + +public: + static simgrid::xbt::Extension EXTENSION_ID; + + explicit Photovoltaic(simgrid::s4u::Host* host); + ~Photovoltaic(); + + Photovoltaic* set_solar_irradiance(double s); + + double get_power(); +}; + +Photovoltaic* Photovoltaic::set_area(double a) +{ + xbt_assert(a > 0, " : area should be > 0 (provided: %f)", a); + simgrid::kernel::actor::simcall_answered([this, a] { area_m2_ = a; }); + return this; +} + +Photovoltaic* Photovoltaic::set_conversion_efficiency(double e) +{ + xbt_assert(e > 0 and e <= 1, " : conversion efficiency should be in [0,1] (provided: %f)", e); + simgrid::kernel::actor::simcall_answered([this, e] { conversion_efficiency_ = e; }); + return this; +} + +Photovoltaic* Photovoltaic::set_solar_irradiance(double s) +{ + xbt_assert(s > 0, " : solar irradiance should be > 0 (provided: %f)", s); + simgrid::kernel::actor::simcall_answered([this, s] { solar_irradiance_w_per_m2_ = s; }); + return this; +} + +Photovoltaic* Photovoltaic::set_min_power(double p) +{ + simgrid::kernel::actor::simcall_answered([this, p] { min_power_w_ = p; }); + return this; +} + +Photovoltaic* Photovoltaic::set_max_power(double p) +{ + simgrid::kernel::actor::simcall_answered([this, p] { max_power_w_ = p; }); + return this; +} + +Photovoltaic* Photovoltaic::set_eval_cost(bool e) +{ + simgrid::kernel::actor::simcall_answered([this, e] { eval_cost_ = e; }); + return this; +} + +Photovoltaic* Photovoltaic::set_lifespan(int l) +{ + xbt_assert(l > 0, " : lifespan should be > 0 (provided: %d)", l); + simgrid::kernel::actor::simcall_answered([this, l] { lifespan_years_ = l; }); + return this; +} + +Photovoltaic* Photovoltaic::set_investment_cost(double c) +{ + xbt_assert(c > 0, " : investment cost should be > 0 (provided: %f)", c); + simgrid::kernel::actor::simcall_answered([this, c] { investment_cost_per_w_ = c; }); + return this; +} + +Photovoltaic* Photovoltaic::set_maintenance_cost(double c) +{ + xbt_assert(c > 0, " : maintenance cost hould be > 0 (provided: %f)", c); + simgrid::kernel::actor::simcall_answered([this, c] { maintenance_cost_per_wh_ = c; }); + return this; +} + +double Photovoltaic::get_power() +{ + update(); + return power_w_; +} + +simgrid::xbt::Extension Photovoltaic::EXTENSION_ID; + +void Photovoltaic::init_photovoltaic_params() +{ + const char* prop_chars; + prop_chars = host_->get_property("photovoltaic_area"); + if (prop_chars) + set_area(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str())); + prop_chars = host_->get_property("photovoltaic_conversion_efficiency"); + if (prop_chars) + set_conversion_efficiency( + xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str())); + prop_chars = host_->get_property("photovoltaic_solar_irradiance"); + if (prop_chars) + set_solar_irradiance(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str())); + prop_chars = host_->get_property("photovoltaic_min_power"); + if (prop_chars) + set_min_power(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str())); + prop_chars = host_->get_property("photovoltaic_max_power"); + if (prop_chars) + set_max_power(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str())); + prop_chars = host_->get_property("photovoltaic_eval_cost"); + if (prop_chars) + set_eval_cost(xbt_str_parse_int(prop_chars, ("cannot parse int: " + std::string(prop_chars)).c_str())); + prop_chars = host_->get_property("photovoltaic_lifespan"); + if (prop_chars) + set_lifespan(xbt_str_parse_int(prop_chars, ("cannot parse int: " + std::string(prop_chars)).c_str())); + prop_chars = host_->get_property("photovoltaic_investment_cost"); + if (prop_chars) + set_investment_cost(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str())); + prop_chars = host_->get_property("photovoltaic_maintenance_cost"); + if (prop_chars) + set_maintenance_cost(xbt_str_parse_double(prop_chars, ("cannot parse double: " + std::string(prop_chars)).c_str())); + simgrid::kernel::actor::simcall_answered([this] { last_updated_ = simgrid::s4u::Engine::get_clock(); }); +} + +void Photovoltaic::update() +{ + simgrid::kernel::actor::simcall_answered([this] { + double now = simgrid::s4u::Engine::get_clock(); + if (now <= last_updated_) + return; + double power_w = conversion_efficiency_ * area_m2_ * solar_irradiance_w_per_m2_; + if (min_power_w_ > 0 and power_w_ < min_power_w_) + power_w = 0; + if (max_power_w_ > 0 and power_w_ > max_power_w_) + power_w = max_power_w_; + power_w_ = power_w; + if (eval_cost_) { + xbt_assert(max_power_w_ > 0, " : max power must be > 0 (provided: %f)", max_power_w_); + cumulative_cost_ += max_power_w_ * (now - last_updated_) * + (investment_cost_per_w_ / (lifespan_years_ * 8760 * 3600) + maintenance_cost_per_wh_ / 3600); + } + last_updated_ = now; + }); +} + +Photovoltaic::Photovoltaic(simgrid::s4u::Host* host) : host_(host) +{ + init_photovoltaic_params(); +} + +Photovoltaic::~Photovoltaic() = default; +} // namespace simgrid::plugin + +using simgrid::plugin::Photovoltaic; + +/* **************************** events callback *************************** */ + +static void on_creation(simgrid::s4u::Host& host) +{ + if (dynamic_cast(&host)) // Ignore virtual machines + return; + host.extension_set(new Photovoltaic(&host)); +} + +/* **************************** Public interface *************************** */ + +static void ensure_plugin_inited() +{ + if (not Photovoltaic::EXTENSION_ID.valid()) + throw simgrid::xbt::InitializationError( + "The Photovoltaic plugin is not active. Please call sg_photovoltaic_plugin_init() " + "before calling any function related to that plugin."); +} + +/** @ingroup plugin_photovoltaic + * @brief Enable photovoltaic plugin. + */ +void sg_photovoltaic_plugin_init() +{ + if (Photovoltaic::EXTENSION_ID.valid()) + return; + Photovoltaic::EXTENSION_ID = simgrid::s4u::Host::extension_create(); + simgrid::s4u::Host::on_creation_cb(&on_creation); +} + +/** @ingroup plugin_photovoltaic + * @param s The solar irradiance to set in W/m². + */ +void sg_photovoltaic_set_solar_irradiance(const_sg_host_t host, double s) +{ + ensure_plugin_inited(); + host->extension()->set_solar_irradiance(s); +} + +/** @ingroup plugin_photovoltaic + * @return Power generation in W. + */ +double sg_photovoltaic_get_power(const_sg_host_t host) +{ + ensure_plugin_inited(); + return host->extension()->get_power(); +} \ No newline at end of file diff --git a/tools/cmake/DefinePackages.cmake b/tools/cmake/DefinePackages.cmake index c7e01f71a6..d6d2a5b7bd 100644 --- a/tools/cmake/DefinePackages.cmake +++ b/tools/cmake/DefinePackages.cmake @@ -455,6 +455,7 @@ set(PLUGINS_SRC src/plugins/vm/dirty_page_tracking.cpp src/plugins/battery.cpp src/plugins/operation.cpp + src/plugins/photovoltaic.cpp ) @@ -646,6 +647,7 @@ set(headers_to_install include/simgrid/plugins/live_migration.h include/simgrid/plugins/load.h include/simgrid/plugins/operation.hpp + include/simgrid/plugins/photovoltaic.hpp include/simgrid/plugins/ProducerConsumer.hpp include/simgrid/instr.h include/simgrid/mailbox.h @@ -1123,6 +1125,7 @@ set(PLATFORMS_EXAMPLES examples/platforms/optorsim/gridpp_grid_2004.conf examples/platforms/optorsim/lcg_sept2004_grid.conf examples/platforms/optorsim/transform_optorsim_platform.pl + examples/platforms/photovoltaic_platform.xml examples/platforms/profiles/fafard_state.profile examples/platforms/profiles/faulty_host.profile examples/platforms/profiles/ginette_state.profile -- 2.20.1