diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 0000000..e52fd2e --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,27 @@ +name: deploy-docs + +on: [push, pull_request, workflow_dispatch] + +permissions: + contents: write + +jobs: + docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + - name: Install dependencies + run: | + pip install -r docs/requirements.txt + - name: Sphinx build + run: | + sphinx-build docs _build + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + with: + publish_branch: gh-pages + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: _build/ + force_orphan: true \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..904fdcb --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,114 @@ +# Contributing guidelines + +Any kind of contribution to **The Illuminator** is welcome, from a simple comment or a question, to a full fledged [pull request](https://help.github.com/articles/about-pull-requests/). + +A contribution can be associated with the following cases: + +- You have a question. +- You think you may have found a bug, including unexpected behavior. +- You want to make changes to the code base to fix a bug, make improvements, add a new functionality, or to update the documentation. +- You want to improve the Illuminator's documentation + +The sections below outlines the steps to make your contribution to the software for each of the aforementioned cases. + +## A. You have a question + +1. Use the search functionality [here](link-to-issues) to see if someone already filed the same issue. +1. If your issue search did not yield any relevant results, open a new issue. +1. Apply the "Question" label. Additionally, apply other labels when relevant. + +## B. You think you may have found a bug + +1. Use the search functionality [here](link-to-issues) to see if someone already filed the same issue. +1. If your issue search did not yield any relevant results, open a new issue and provide enough information to understand the cause and the context of the problem. Depending on the issue, you may also want to include: + - the [SHA hashcode](https://help.github.com/articles/autolinked-references-and-urls/#commit-shas) of the commit that is causing your problem + - some identifying information (name and version number) for dependencies you're using + - information about the operating system + +## C. You want to make changes to the code base + + +### Announce your plan + +1. (**important**) Announce your plan to the rest of the community *before you start working*. This announcement should be in the form of a (new) issue on the Github repository. +2. (**important**) Wait until a consensus is reached about your idea being a good idea. + + +### Set up a local development environment to work on your changes + +If you are a part of the Illuminator team and have write access to the Illuminator GitHub repository, skip to the next subsection [Develop your contribution](CONTRIBUTING.md#develop-your-contribution). If you are a first-time contributor, follow the below steps: + +1. Go to the [Illuminator GitHub repository](url-repository) and click on 'Fork'. This will create a copy of the Illuminator repository in your GitHub account. + +1. Clone the project to your local computer: + + ```bash + git clone https://github.com/your-username/Illuminator.git + ``` + +1. Change the directory + + ```bash + cd Illuminator + ``` + +1. Add the upstream repository + + ```bash + git remote add upstream https://github.com/.git + ``` + +1. Now, `git remote -v` will show two remote repositories named: + + * `upstream`, which refers to the Illumator repository + * `origin`, which refers to your personal fork + +### Develop your contribution + +> TODO: update this section after refactoring + +1. Create a branch of the latest commit on the `main` branch to work on your feature. + + ```bash + git checkout -b my-feature + ``` + +2. If you are contributing via a fork, make sure to pull in changes from the 'upstream' repository to stay up to date with the `main` branch while working on your feature branch. Follow the instructions [here](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/configuring-a-remote-repository-for-a-fork) and [here](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork). + +3. Set up a development environment on your computer by installing the Illuminator in development mode with the following command: (Consider using a virtual environment for this purpose.) + + ```bash + # TODO: this part needs to be updated after refactoring + ``` + +4. Set up your code editor to follow [PEP 8](https://peps.python.org/pep-0008/) (remove trailing white space, no tabs, etc.). Check code with [flake8](https://flake8.pycqa.org/en/latest/). + +5. Make sure the existing tests pass by running `pytest` from the root of the repository. + +6. Write tests for any new lines of code you add. + +7. Include in-code documentation in form of comments and docstrings. Use the [numpydoc](https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard) documentation style. + +8. Update the user/developer documentation if relevant. Undocumented contributions might not be merged. + + +### Submitting your contribution + +1. Push your feature branch to (your fork of) the Illuminator GitHub repository. + +1. Create a pull request, for an example, following the instructions [here](https://help.github.com/articles/creating-a-pull-request/). + + +## D. You want to improve the Illuminator's documentation + +We use Sphinx and Markdown to write documentation for the Illuminator. The root of the documentation is the `docs/` directory. + +1. [Announce your plan.](#announce-your-plan) +1. Follow the same steps to set up a development environment for [making changes to the code base](#set-up-a-local-development-environment-to-work-on-your-changes). +1. Install the dependencies in `docs/requirements.txt` using `pip install -r docs/requirments.txt` (Sphnix will also be installed). +1. Update the documentation using Markdown. If familiar with writing Markdown for MyST consult their [guides and documentation](https://myst-parser.readthedocs.io/en/latest/syntax/optional.html) +1. Make sure your contributions are built without errors. Go to the `docs` directory in the terminal with `cd docs/`. Then, build the documentation using `make html`. +1. [Submit your contribution](#submitting-your-contribution) for review. + + +In case you feel you've made a valuable contribution, but you don't know how to write or run tests for it, or how to generate the documentation; don't let this discourage you from making the pull request. We can help you! Just go ahead and submit the pull request. But keep in mind that you might be asked to append additional commits to your pull request. \ No newline at end of file diff --git a/LICENSE b/LICENSE index 104ae93..f99be76 100644 --- a/LICENSE +++ b/LICENSE @@ -6,10 +6,6 @@ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - Preamble The licenses for most software are designed to take away your @@ -456,49 +452,3 @@ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - The Illuminator, a Energy System Integration Development kit - Copyright (C) 2024 Illuminator Team - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random - Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/Models/Controller/controller_mosaik.py b/Models/Controller/controller_mosaik.py index 4346eeb..59ddc85 100644 --- a/Models/Controller/controller_mosaik.py +++ b/Models/Controller/controller_mosaik.py @@ -9,7 +9,7 @@ import Models.Controller.controller_model as controller_model #import Battery.model as batterymodel import sys -sys.path.insert(1,'/home/illuminator/Desktop/Final_illuminator') +sys.path.insert(1, '/home/illuminator/Desktop/Final_illuminator') try: import Models.Battery.battery_model as batterymodel diff --git a/Models/collector.py b/Models/collector.py index 9405daf..cb0d237 100644 --- a/Models/collector.py +++ b/Models/collector.py @@ -89,11 +89,22 @@ def step(self, time, inputs, max_advance): wandb.log({key: value[0], "custom_step":time/900}) - if self.results_show['write2csv']==True: + if self.results_show['write2csv'] == True: if time == 0: + # Overwrite the CSV file at the first time step df.to_csv(self.output_file, mode='w', header=True) else: - df.to_csv(self.output_file, mode='a', header=False) + if os.path.exists(self.output_file): + # Read existing CSV + existing_df = pd.read_csv(self.output_file, index_col='date', parse_dates=True) + + # Align the columns + combined_df = pd.concat([existing_df, df]) + else: + combined_df = df + + # Write the merged data to CSV + combined_df.to_csv(self.output_file, mode='w', header=True) if self.results_show['database']==True: diff --git a/WAIVER b/WAIVER new file mode 100644 index 0000000..099e486 --- /dev/null +++ b/WAIVER @@ -0,0 +1,6 @@ +Technische Universiteit Delft hereby disclaims all copyright interest in the +program “Illuminator”, an easy-to-use Energy System Integration Development Kit +to demystify energy system operation, illustrate challenges that arise due to +the energy transition and test state-of-the-art energy management concepts, +written by the Author(s). +[Name Dean], Dean of Faculty Electrical Engineering, Mathematics and Computer Science \ No newline at end of file diff --git a/configuration/buildmodelset.py b/configuration/buildmodelset.py index 17c42e7..58389ff 100644 --- a/configuration/buildmodelset.py +++ b/configuration/buildmodelset.py @@ -1,4 +1,9 @@ - +# [Manuel] FROM Balassis thesis: +# The buildmodelset.py file holds the parameters for each simulator. It is imported into the Main file and used to +# instantiate the models with the appropriate setup. This file allows for the specification of various parameters related +# to physical energy assets, like the initial SoC of batteries or the rated power of wind turbines. Additionally, economic +# parameters, such as the marginal cost or benefit of each asset in agents’ portfolios, can also be defined among the +# available parameters. resolution=15 Battery_initialset = {'initial_soc': 20} diff --git a/configuration/interpreter.py b/configuration/interpreter.py index 9b9ecd9..0387ef4 100644 --- a/configuration/interpreter.py +++ b/configuration/interpreter.py @@ -1,3 +1,25 @@ +""" +The Illuminator, a Energy System Integration Development kit + Copyright (C) 2024 Illuminator Team + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + + For questions and support, please contact us at illuminator@tudelft.nl + +""" import shutil diff --git a/docs/conf.py b/docs/conf.py index b70a593..64c50ac 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -18,7 +18,7 @@ 'sphinx_rtd_theme', 'sphinx.ext.autodoc', 'sphinx.ext.napoleon', - 'sphinx-copybutton', + 'sphinx_copybutton', ] templates_path = ['_templates'] diff --git a/docs/index.rst b/docs/index.rst index 1efa3ae..c83250d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -24,6 +24,8 @@ and the simulation engine is based on [Mosaik](https://mosaik.offis.de/). :caption: User's Documentation: user/start + user/user-guide + user/models .. toctree:: :maxdepth: 2 diff --git a/Models.md b/docs/user/models.md similarity index 92% rename from Models.md rename to docs/user/models.md index 4cbd20c..bd4f96a 100644 --- a/Models.md +++ b/docs/user/models.md @@ -1,320 +1,333 @@ -# Battery storage -The battery storage parameters are all set in the python file named 'buildmodelset.py' in the configuration folder. -``` -'max_p': the rated charging power -'min_p': the rated discharging negative power. -'max_energy': the battery capacity -'soc_min': the minimum soc limitation -'soc_max': the maximum soc limitation -'flage': the status of the battery. flag=1 means fully charged; flag=-1 means fully discharged; flag=0 means ready for charge and discharge -'resolution': the time-step of simulation in minutes -``` -## Model build-up methodology -" output_power(self, flow2b, soc) " is a controller method to decide whether to charge or discharge the battery. -(flow2b: The requested power flow. soc: The current state of charge. -Returns: A dictionary with updated battery parameters.) -The method for charge and discharge calculation: -``` -Energy_discharge = Power_flow * Resoluation \ Efficiency_discharge -Energy_charge = Power_flow * Resoluation * Efficiency_charge -``` -Update the Soc of the battery at each time resolution. - - -------------------------------------------------- -# Electric Boiler -The Electric Boiler parameters are all set in the python file named 'buildmodelset.py' in the configuration folder. -``` -'capacity': the maximum capacity of the boiler in kilowatts (kW). -'min_load': the minimum operational load of the boiler in kilowatts (kW). -'max_load': the maximum operational load of the boiler in kilowatts (kW). -'standby_loss': the heat loss while the boiler is in standby mode as a fraction of the capacity. -'efficiency': the operational efficiency of the boiler under maximum load. -'resolution': the time-step of simulation in minutes. - -``` -## Model Build-Up Methodology -The demand method is used to calculate the heat supply and electricity consumption based on the boiler's demand. - -Parameters: -eboiler_dem: The heat demand in watts (W). -Returns: A dictionary containing the heat supplied (q_gen), electricity consumed (e_consumed), and standby loss. - -The operational logic for the electric boiler is as follows: -``` -Power_require = (Q_Demand + Standby_loss) / Efficiency -Q_supply = (Electricity_input - Standby_loss) * Efficiency * 1000 # in Watts -``` -The heat supplied (Q_supply) and electricity consumed are calculated based on the demand, considering the boiler's capacity, load limits, and efficiency. The calculations are adjusted to ensure the operation stays within the defined minimum and maximum load limits. - ------------------------------------------------------ - -# Electrolyser - -The electrolyser model parameters are all set in the python file named 'buildmodelset.py' in the configuration folder. -``` -'eff': the efficiency of the electrolyser. -'resolution': the time-step of the simulation in minutes. -'term_eff': the thermal efficiency of the electrolyser. -'rated_power': the rated power input of the electrolyser. -'ramp_rate': the maximum rate at which the power input can change. -``` - -## Model Build-Up Methodology -The electrolyser method is used to calculate hydrogen production and energy consumption based on the input power flow. - -Parameters: -flow2e: The power flow to the electrolyser in kW. -temperature: Optional. The temperature of the operation in degrees Celsius (default is 15°C). -pressure: Optional. The pressure of the operation in kPa (default is 100 kPa). -Returns: A dictionary containing the hydrogen generated (h2_gen), power flow (flow2e), thermal energy (q_product), and energy consumed (e_consume). - -The operational logic for the electrolyser is as follows: -``` -Desired_power = min(Rated_power, Flow2e) -E_consume = ramp_rate_limit(Desired_power) -Q_product = E_consume * Term_eff -HHV = 286.6 kJ/mol -Mole = (E_consume * Resolution * 60 kJ) / HHV * Eff -H_mass = (2.02 grams/mole * Mole) / 1000 kg -H_out = H_mass * 11.2 m^3/min at NTP / Resolution -``` -The electrolyser model calculates the amount of hydrogen produced and the energy consumed. It accounts for the ramp rate limits and the electrolyser's efficiency to provide realistic performance metrics. - - ----------------------------------------------- - -# Fuel Cell - -The Fuel Cell model parameters are all set in the python file named 'buildmodelset.py' in the configuration folder. -``` -'eff': the base efficiency of the fuel cell. -'term_eff': the thermal efficiency of the fuel cell. -'max_flow': the maximum hydrogen flow rate. -'min_flow': the minimum hydrogen flow rate. -'resolution': the time-step of the simulation in minutes. -``` -## Model Build-Up Methodology - -The output method is used to calculate the power output and thermal energy based on hydrogen consumption. - -Parameters: - -h2_consume: The hydrogen consumption rate in m³/min. -temperature: Optional. The temperature of the operation in degrees Celsius (default is 25°C). -pressure: Optional. The pressure of the operation in kPa (default is 100 kPa). -Returns: A dictionary containing the fuel cell power output (fc_gen), hydrogen fuel rate (h2fuel), hydrogen consumed (h2_consume), and thermal energy (q_product). - -The operational logic for the fuel cell is as follows: - -``` -H2fuel = max(Min_flow, min(Max_flow, H2_consume)) -Efficiency = efficiency(H2_consume, Temperature, Pressure) -Energy_density = 120,000 kJ/m³ # Energy from 1 m³ hydrogen -Out = (H2_consume * Energy_density * Efficiency) / 60 kW # Power output -Q_out = Out * Term_eff # Thermal energy output -``` - -The fuel cell model computes the power output and thermal energy based on the hydrogen consumed. It takes into account the efficiency of the fuel cell, which can vary based on the load, temperature, and pressure. The model also ensures that the hydrogen consumption is within the specified minimum and maximum flow rates. - -------------------------------------------------- -# Hydrogen Storage -The hydrogen storage model parameters are all set in the python file named 'buildmodelset.py' in the configuration folder. -``` -'initial_soc': the initial state of charge of the hydrogen storage. -'h2storage_soc_min': the minimum state of charge limitation. -'h2storage_soc_max': the maximum state of charge limitation. -'eff': the efficiency of hydrogen storage. -'max_h2': the maximum hydrogen flow rate. -'min_h2': the minimum hydrogen flow rate. -'capacity': the total capacity of the hydrogen storage. -'resolution': the time-step of simulation in minutes. -``` -## Model Build-Up Methodology - -The `output_h2` method determines whether to charge or discharge based on the net hydrogen flow. - -Parameters: -flow2h2s: The flow rate of hydrogen. -eleh2_in: The rate of hydrogen input from the electrolyser. -fuelh2_out: The rate of hydrogen output to the fuel cell. -soc: The current state of charge. -Returns: A dictionary with parameters indicating the operation and state of the hydrogen storage. -Overall Logic: -``` -Flow2h2s_net = Flow2h2s + Eleh2_in - Fuelh2_out -# Decide on charging or discharging based on Flow2h2s_net. -``` -This model manages the state of charge of a hydrogen storage system, factoring in the efficiency, capacity, and operational limits of the storage. It also accounts for the dynamics of charging and discharging based on the system's resolution and the net flow of hydrogen. - -Charging Logic: -``` -H2_flow = min(Max_h2, Flow2h2s_net) -If H2_flow > 0: - Calculate hydrogen discharge and capacity. - Update state of charge and flag accordingly. -``` -Discharging Logic: -``` -H2_flow = max(Min_h2, Flow2h2s_net) -If H2_flow < 0: - Calculate hydrogen discharge and capacity. - Update state of charge and flag accordingly. -``` - ----------------------------------------- -# Heat Pump -The Heat Pump model contains three models, which is original developed by [Mosaik](https://gitlab.com/mosaik/components/energy/mosaik-heatpump) - -1. A heat pump model, based on the [TESPy](https://github.com/oemof/tespy) library. -2. A hot water tank model -3. A controller model --------------------------------------- - -# Heat Storage -The heat storage model parameters are all set in the python file named 'buildmodelset.py' in the configuration folder. -``` -'soc_init': the initial state of charge based on the temperature. -'max_temperature': the maximum temperature the storage can reach. -'min_temperature': the minimum temperature the storage can reach. -'insulation': the insulation quality of the storage. -'ext_temp': the external temperature. -'therm_cond': the thermal conductivity. -'length': the length of the storage container. -'diameter': the diameter of the storage container. -'density': the density of the storage medium. -'c': the specific heat capacity. -'eff': the efficiency of heat storage. -'max_q': the maximum heat flow rate. -'min_q': the minimum heat flow rate. -'resolution': the time-step of simulation in minutes. -``` -The output_q method determines whether to charge or discharge based on the net heat flow. - -Parameters: - -flow2qs: The net heat flow rate. -Returns: A dictionary with parameters indicating the operation and state of the heat storage. - -Overall Logic: -``` -Calculate heat loss. -Adjust Flow2qs based on heat loss. -Decide on charging or discharging based on Flow2qs. -``` -Charging Logic: -``` -Q_flow = min(Max_q, Flow2qs) -Calculate heat charge and internal temperature. -Update state of charge and flag accordingly. -``` -Discharging Logic: -``` -Q_flow = max(Min_q, Flow2qs) -Calculate heat discharge and internal temperature. -Update state of charge and flag accordingly. -``` ---------------------------------------- -# PV Model -## Data input -The PV data is obtained from the Meteonorm software, and solar radiation and positioning values were obtained for the region -of Rotterdam. With the new updates, it was possible to extract 15-minute interval data from within -meteonorm. The input data and parameter setting for PV models are through the '.csv' or '.txt' file in the `Scenario` folder -and the file 'buildmodelset.py' in the configuration folder. The input data from '.csv' or '.txt' file are as follows, -``` -`G_Gh'GHI global horizontal irradiance -`G_Dh'DHI direct horizontal irradiance -`G_Bn': DNI direct normal irradiance -`Ta`: temperature -`hs`: elevation of the sun -`FF`: wind speed -`Az`: azimuth of the sun -``` -The parameters set in the python file are shown as follows, -``` -'Module_area': module area. available in the spec sheet of a PV module -'NOCT': module temperature under the standard test conditions (STC) and stands for Nominal Operating Cell Temperature -'Module_Efficiency' -'Irradiance_at_NOCT': W/m2 This is the irradiance that falls on the panel under NOCT conditions -'Power_output_at_STC': Watts. Available in the spec sheet of a module -'m_tilt': module tilt angle -'m_az': azimuth of the module -'cap': capacity -'output_type': power or energy -``` -## Model build up methodology -Calculating the irradiance on a module at a specific location is essential to calculate the output of -a PV system, and is governed by multiple factors. Irradiance is the incoming power of -solar radiation over a unit area and is measured in W/m2. Due to the rotation and revolution of the -earth, the position of the sun is not constant. Hence, the amount of irradiation received changes -continuously with the time of day, month, and year. Location on the earth also factors in for the amount of -irradiance received. Due to the changing elevation and azimuth angle of the sun throughout the day, -the incoming solar radiations are not normal to the surface. The angle between the normal surface and the solar radiation is called the Angle of Incidence (AOI), and it affects the amount of irradiance of the module surface. The equation -to calculate the AOI is shown below. -``` -cos_aoi = cos(90 - m_tilt)) * cos(hs) * cos(m_az - Az) + sin(90 - m_tilt)) * sin(hs) -``` -For testing the PV modules during manufacturing and calculating the output from a module over a while, some standard test conditions (STC) have been defined, according to which we have AM1.5 spectrum as standard with an irradiance of 1000 W/m2. The attenuation of solar radiation upon entering the earth is because of scattering and absorption by dust particles, -aerosols in the atmosphere, and air molecules. The presence of water vapor, oxygen, and carbon dioxide are significant -contributors to the absorption of radiation. Because of this attenuation, the incoming radiation breaks into a diffused component, -called Diffused Horizontal Irradiance (DHI) and a direct component of light, called Direct Normal Irradiance (DNI). -There is another component of the radiation that falls on the module surface, and that is the reflected component which is -because of the reflected radiations from the surface around the module. This is called Global Horizontal irradiance (GHI). -Meteorological stations measure the DHI and DNI and GHI can be calculated using the following formula where albedo ranges between 0.05 - 0.20 for urban environments, -0.05 - 0.10 for forests and 0.60 for snow. The following formulas are used to calculate the irradiance using the DHI, DNI, and GHI. -``` -svf = (1 + cos(m_tilt)) / 2 -g_diff = svf * G_Dn # svf is Sky View Factor -g_ref = albedo * (1 - self.svf) * G_Gh #albedo is the Albedo value 0.2 -g_dir = G_Bn * cos_aoi -g_all=g_diff+g_ref+g_dir -``` -Changing module temperature hurts the output of the module. Wind speed and the mounting height of the panel from the ground impact the module temperature. Blowing wind decreases the temperature due to convective heat transfer, and mounting above the ground makes enough space for heat to dissipate from the module and for its interaction with the blowing wind. -The Duffie-Beckman model covers these factors while calculating the module temperature. -``` -m_temp = Ta + (g_all/ Irradiance_at_NOCT)) * (NOCT - 20) * (9.5/(5.7 + 3.8*FF))) * (1 - Module_Efficiency / 0.90)) -``` -The module manufacturer provides it to give an estimate of average cell temperature. Instead of individual values of T and a, for silicon-based solar cells, T ∗ a -is taken as 0.9. -``` -efficiency = Module_Efficiency * (1 + (-0.0035 * (m_temp - 25))) -P_AC=cap * sf/P_STC*m_area*g_all*efficiency*inv_eff*mppt_eff*losses - -``` ---------------------------------------------- - -# Wind Model -## Data input -Wind data chosen is from an on-shore site situated in The Netherlands at 100m at 5 minutes intervals. -The input data and parameter setting for Wind models are through the '.csv' or '.txt' file in the `Scenario` folder -and the file 'buildmodelset.py' in the configuration folder. The input data from '.csv' or '.txt' file is the wind speed 'u'. -The parameters set in the python file are shown as follows, - -``` -'p_rated': kW power it generates at rated wind speed and above -'u_rated': m/s #windspeed it generates most power at -'u_cutin': m/s #below this wind speed no power generation -'u_cutout': m/s #above this wind speed no power generation. Blades are pitched -'cp': coefficient of performance of a turbine. Usually around0.40. Never more than 0.59 -'diameter': Wind turbine rotor diameter -'powerout': output power at wind speed u -``` -## Model build-up methodology -The Power curve of the wind turbine is shown below. -
- -
- - ------------------------------------------------------------------- -# Load, Heat demand, Heat Product, Hydrogen product and Hydrogen demand -These models are very simple. Some of them just make a unit transfer from input to output.Some of them just read the data. - ---------------------------------------------------------------------- -# Electricity network, Hydrogen network and Heat network -These models are very simple like a tube. - --------------------------------------------------------------------- -# Distribution network -The distribution network is build based on [Pandapower](https://pandapower.readthedocs.io/en/v2.13.1/) -More details refer to Pandapower \ No newline at end of file +# Models +> This resembles the API documentation. Would be better to add the explanations as docstring and +> generate the documentation using **autodoc** +> However, we should separtate explanatios from API references. + +## Battery storage +The battery storage parameters are all set in the python file named 'buildmodelset.py' in the configuration folder. + +```python +'max_p': the rated charging power +'min_p': the rated discharging negative power. +'max_energy': the battery capacity +'soc_min': the minimum soc limitation +'soc_max': the maximum soc limitation +'flage': the status of the battery. # flag=1 means fully charged; flag=-1 means fully discharged; flag=0 means ready for charge and discharge +'resolution': the time-step of simulation in minutes +``` +### Model build-up methodology +"output_power(self, flow2b, soc) " is a controller method to decide whether to charge or discharge the battery. +(flow2b: The requested power flow. soc: The current state of charge. +Returns: A dictionary with updated battery parameters.) +The method for charge and discharge calculation: + +``` +Energy_discharge = Power_flow * Resoluation \ Efficiency_discharge +Energy_charge = Power_flow * Resoluation * Efficiency_charge +``` +Update the Soc of the battery at each time resolution. + + +------------------------------------------------- +## Electric Boiler +The Electric Boiler parameters are all set in the python file named `buildmodelset.py` in the configuration folder. + +``` +'capacity': the maximum capacity of the boiler in kilowatts (kW). +'min_load': the minimum operational load of the boiler in kilowatts (kW). +'max_load': the maximum operational load of the boiler in kilowatts (kW). +'standby_loss': the heat loss while the boiler is in standby mode as a fraction of the capacity. +'efficiency': the operational efficiency of the boiler under maximum load. +'resolution': the time-step of simulation in minutes. + +``` + +### Model Build-Up Methodology +The demand method is used to calculate the heat supply and electricity consumption based on the boiler's demand. + +Parameters: +eboiler_dem: The heat demand in watts (W). +Returns: A dictionary containing the heat supplied (q_gen), electricity consumed (e_consumed), and standby loss. + +The operational logic for the electric boiler is as follows: + +``` +Power_require = (Q_Demand + Standby_loss) / Efficiency +Q_supply = (Electricity_input - Standby_loss) * Efficiency * 1000 # in Watts +``` +The heat supplied (Q_supply) and electricity consumed are calculated based on the demand, considering the boiler's capacity, load limits, and efficiency. The calculations are adjusted to ensure the operation stays within the defined minimum and maximum load limits. + +----------------------------------------------------- + +## Electrolyser + +The electrolyser model parameters are all set in the python file named 'buildmodelset.py' in the configuration folder. +``` +'eff': the efficiency of the electrolyser. +'resolution': the time-step of the simulation in minutes. +'term_eff': the thermal efficiency of the electrolyser. +'rated_power': the rated power input of the electrolyser. +'ramp_rate': the maximum rate at which the power input can change. +``` + +### Model Build-Up Methodology +The electrolyser method is used to calculate hydrogen production and energy consumption based on the input power flow. + +Parameters: +flow2e: The power flow to the electrolyser in kW. +temperature: Optional. The temperature of the operation in degrees Celsius (default is 15°C). +pressure: Optional. The pressure of the operation in kPa (default is 100 kPa). +Returns: A dictionary containing the hydrogen generated (h2_gen), power flow (flow2e), thermal energy (q_product), and energy consumed (e_consume). + +The operational logic for the electrolyser is as follows: + +``` +Desired_power = min(Rated_power, Flow2e) +E_consume = ramp_rate_limit(Desired_power) +Q_product = E_consume * Term_eff +HHV = 286.6 kJ/mol +Mole = (E_consume * Resolution * 60 kJ) / HHV * Eff +H_mass = (2.02 grams/mole * Mole) / 1000 kg +H_out = H_mass * 11.2 m^3/min at NTP / Resolution +``` +The electrolyser model calculates the amount of hydrogen produced and the energy consumed. It accounts for the ramp rate limits and the electrolyser's efficiency to provide realistic performance metrics. + + +---------------------------------------------- + +## Fuel Cell + +The Fuel Cell model parameters are all set in the python file named 'buildmodelset.py' in the configuration folder. +``` +'eff': the base efficiency of the fuel cell. +'term_eff': the thermal efficiency of the fuel cell. +'max_flow': the maximum hydrogen flow rate. +'min_flow': the minimum hydrogen flow rate. +'resolution': the time-step of the simulation in minutes. +``` +### Model Build-Up Methodology + +The output method is used to calculate the power output and thermal energy based on hydrogen consumption. + +Parameters: + +h2_consume: The hydrogen consumption rate in m³/min. +temperature: Optional. The temperature of the operation in degrees Celsius (default is 25°C). +pressure: Optional. The pressure of the operation in kPa (default is 100 kPa). +Returns: A dictionary containing the fuel cell power output (fc_gen), hydrogen fuel rate (h2fuel), hydrogen consumed (h2_consume), and thermal energy (q_product). + +The operational logic for the fuel cell is as follows: + +``` +H2fuel = max(Min_flow, min(Max_flow, H2_consume)) +Efficiency = efficiency(H2_consume, Temperature, Pressure) +Energy_density = 120,000 kJ/m³ # Energy from 1 m³ hydrogen +Out = (H2_consume * Energy_density * Efficiency) / 60 kW # Power output +Q_out = Out * Term_eff # Thermal energy output +``` + +The fuel cell model computes the power output and thermal energy based on the hydrogen consumed. It takes into account the efficiency of the fuel cell, which can vary based on the load, temperature, and pressure. The model also ensures that the hydrogen consumption is within the specified minimum and maximum flow rates. + +------------------------------------------------- +## Hydrogen Storage +The hydrogen storage model parameters are all set in the python file named 'buildmodelset.py' in the configuration folder. +``` +'initial_soc': the initial state of charge of the hydrogen storage. +'h2storage_soc_min': the minimum state of charge limitation. +'h2storage_soc_max': the maximum state of charge limitation. +'eff': the efficiency of hydrogen storage. +'max_h2': the maximum hydrogen flow rate. +'min_h2': the minimum hydrogen flow rate. +'capacity': the total capacity of the hydrogen storage. +'resolution': the time-step of simulation in minutes. +``` +### Model Build-Up Methodology + +The `output_h2` method determines whether to charge or discharge based on the net hydrogen flow. + +Parameters: +flow2h2s: The flow rate of hydrogen. +eleh2_in: The rate of hydrogen input from the electrolyser. +fuelh2_out: The rate of hydrogen output to the fuel cell. +soc: The current state of charge. +Returns: A dictionary with parameters indicating the operation and state of the hydrogen storage. +Overall Logic: +``` +Flow2h2s_net = Flow2h2s + Eleh2_in - Fuelh2_out +# Decide on charging or discharging based on Flow2h2s_net. +``` +This model manages the state of charge of a hydrogen storage system, factoring in the efficiency, capacity, and operational limits of the storage. It also accounts for the dynamics of charging and discharging based on the system's resolution and the net flow of hydrogen. + +Charging Logic: +``` +H2_flow = min(Max_h2, Flow2h2s_net) +If H2_flow > 0: + Calculate hydrogen discharge and capacity. + Update state of charge and flag accordingly. +``` +Discharging Logic: +``` +H2_flow = max(Min_h2, Flow2h2s_net) +If H2_flow < 0: + Calculate hydrogen discharge and capacity. + Update state of charge and flag accordingly. +``` + +---------------------------------------- +## Heat Pump +The Heat Pump model contains three models, which is original developed by [Mosaik](https://gitlab.com/mosaik/components/energy/mosaik-heatpump) + +1. A heat pump model, based on the [TESPy](https://github.com/oemof/tespy) library. +2. A hot water tank model +3. A controller model +-------------------------------------- + +## Heat Storage +The heat storage model parameters are all set in the python file named 'buildmodelset.py' in the configuration folder. +``` +'soc_init': the initial state of charge based on the temperature. +'max_temperature': the maximum temperature the storage can reach. +'min_temperature': the minimum temperature the storage can reach. +'insulation': the insulation quality of the storage. +'ext_temp': the external temperature. +'therm_cond': the thermal conductivity. +'length': the length of the storage container. +'diameter': the diameter of the storage container. +'density': the density of the storage medium. +'c': the specific heat capacity. +'eff': the efficiency of heat storage. +'max_q': the maximum heat flow rate. +'min_q': the minimum heat flow rate. +'resolution': the time-step of simulation in minutes. +``` +The output_q method determines whether to charge or discharge based on the net heat flow. + +Parameters: + +flow2qs: The net heat flow rate. +Returns: A dictionary with parameters indicating the operation and state of the heat storage. + +Overall Logic: +``` +Calculate heat loss. +Adjust Flow2qs based on heat loss. +Decide on charging or discharging based on Flow2qs. +``` +Charging Logic: +``` +Q_flow = min(Max_q, Flow2qs) +Calculate heat charge and internal temperature. +Update state of charge and flag accordingly. +``` +Discharging Logic: +``` +Q_flow = max(Min_q, Flow2qs) +Calculate heat discharge and internal temperature. +Update state of charge and flag accordingly. +``` +--------------------------------------- +## PV Model + +### Data input +The PV data is obtained from the Meteonorm software, and solar radiation and positioning values were obtained for the region +of Rotterdam. With the new updates, it was possible to extract 15-minute interval data from within +meteonorm. The input data and parameter setting for PV models are through the '.csv' or '.txt' file in the `Scenario` folder +and the file 'buildmodelset.py' in the configuration folder. The input data from '.csv' or '.txt' file are as follows, +``` +`G_Gh'GHI global horizontal irradiance +`G_Dh'DHI direct horizontal irradiance +`G_Bn': DNI direct normal irradiance +`Ta`: temperature +`hs`: elevation of the sun +`FF`: wind speed +`Az`: azimuth of the sun +``` +The parameters set in the python file are shown as follows, +``` +'Module_area': module area. available in the spec sheet of a PV module +'NOCT': module temperature under the standard test conditions (STC) and stands for Nominal Operating Cell Temperature +'Module_Efficiency' +'Irradiance_at_NOCT': W/m2 This is the irradiance that falls on the panel under NOCT conditions +'Power_output_at_STC': Watts. Available in the spec sheet of a module +'m_tilt': module tilt angle +'m_az': azimuth of the module +'cap': capacity +'output_type': power or energy +``` +### Model build up methodology +Calculating the irradiance on a module at a specific location is essential to calculate the output of +a PV system, and is governed by multiple factors. Irradiance is the incoming power of +solar radiation over a unit area and is measured in W/m2. Due to the rotation and revolution of the +earth, the position of the sun is not constant. Hence, the amount of irradiation received changes +continuously with the time of day, month, and year. Location on the earth also factors in for the amount of +irradiance received. Due to the changing elevation and azimuth angle of the sun throughout the day, +the incoming solar radiations are not normal to the surface. The angle between the normal surface and the solar radiation is called the Angle of Incidence (AOI), and it affects the amount of irradiance of the module surface. The equation +to calculate the AOI is shown below. +``` +cos_aoi = cos(90 - m_tilt)) * cos(hs) * cos(m_az - Az) + sin(90 - m_tilt)) * sin(hs) +``` +For testing the PV modules during manufacturing and calculating the output from a module over a while, some standard test conditions (STC) have been defined, according to which we have AM1.5 spectrum as standard with an irradiance of 1000 W/m2. The attenuation of solar radiation upon entering the earth is because of scattering and absorption by dust particles, +aerosols in the atmosphere, and air molecules. The presence of water vapor, oxygen, and carbon dioxide are significant +contributors to the absorption of radiation. Because of this attenuation, the incoming radiation breaks into a diffused component, +called Diffused Horizontal Irradiance (DHI) and a direct component of light, called Direct Normal Irradiance (DNI). +There is another component of the radiation that falls on the module surface, and that is the reflected component which is +because of the reflected radiations from the surface around the module. This is called Global Horizontal irradiance (GHI). +Meteorological stations measure the DHI and DNI and GHI can be calculated using the following formula where albedo ranges between 0.05 - 0.20 for urban environments, +0.05 - 0.10 for forests and 0.60 for snow. The following formulas are used to calculate the irradiance using the DHI, DNI, and GHI. +``` +svf = (1 + cos(m_tilt)) / 2 +g_diff = svf * G_Dn # svf is Sky View Factor +g_ref = albedo * (1 - self.svf) * G_Gh #albedo is the Albedo value 0.2 +g_dir = G_Bn * cos_aoi +g_all=g_diff+g_ref+g_dir +``` +Changing module temperature hurts the output of the module. Wind speed and the mounting height of the panel from the ground impact the module temperature. Blowing wind decreases the temperature due to convective heat transfer, and mounting above the ground makes enough space for heat to dissipate from the module and for its interaction with the blowing wind. +The Duffie-Beckman model covers these factors while calculating the module temperature. +``` +m_temp = Ta + (g_all/ Irradiance_at_NOCT)) * (NOCT - 20) * (9.5/(5.7 + 3.8*FF))) * (1 - Module_Efficiency / 0.90)) +``` +The module manufacturer provides it to give an estimate of average cell temperature. Instead of individual values of T and a, for silicon-based solar cells, T ∗ a +is taken as 0.9. +``` +efficiency = Module_Efficiency * (1 + (-0.0035 * (m_temp - 25))) +P_AC=cap * sf/P_STC*m_area*g_all*efficiency*inv_eff*mppt_eff*losses + +``` +--------------------------------------------- + +## Wind Model +### Data input +Wind data chosen is from an on-shore site situated in The Netherlands at 100m at 5 minutes intervals. +The input data and parameter setting for Wind models are through the '.csv' or '.txt' file in the `Scenario` folder +and the file 'buildmodelset.py' in the configuration folder. The input data from '.csv' or '.txt' file is the wind speed 'u'. +The parameters set in the python file are shown as follows, + +``` +'p_rated': kW power it generates at rated wind speed and above +'u_rated': m/s #windspeed it generates most power at +'u_cutin': m/s #below this wind speed no power generation +'u_cutout': m/s #above this wind speed no power generation. Blades are pitched +'cp': coefficient of performance of a turbine. Usually around0.40. Never more than 0.59 +'diameter': Wind turbine rotor diameter +'powerout': output power at wind speed u +``` +### Model build-up methodology + +The Power curve of the wind turbine is shown below. +
+ +
+ + +------------------------------------------------------------------ +## Load, Heat demand, Heat Product, Hydrogen product and Hydrogen demand +These models are very simple. Some of them just make a unit transfer from input to output.Some of them just read the data. + +--------------------------------------------------------------------- +## Electricity network, Hydrogen network and Heat network +These models are very simple like a tube. + +-------------------------------------------------------------------- +## Distribution network +The distribution network is build based on [Pandapower](https://pandapower.readthedocs.io/en/v2.13.1/) +More details refer to Pandapower diff --git a/user-guide.md b/docs/user/user-guide.md similarity index 65% rename from user-guide.md rename to docs/user/user-guide.md index f4a1ebe..ef88496 100644 --- a/user-guide.md +++ b/docs/user/user-guide.md @@ -1,45 +1,49 @@ -# User Guide document +# User's Guide + ## Configuration There are three methods to configurate the cases. -1. Through provide `config.xml` and `connection.xml` files in the `Cases` folder. We provide four example in `Cases` folder: +### 1. Using Existing Cases + +You can use the provided `config.xml` and `connection.xml` files in the `Cases/` directory. +We provide four example in `Cases` folder: * Residential Case study(`ResidentialCase`) * Multienergy system case study(`MultienergyCase`) - * Electricity market game case study (`GameCase`), and + * Electricity market game case study (`GameCase`) For more information about the electricity market case study, you can reference the [Msc thesis](https://repository.tudelft.nl/islandora/object/uuid:58029e39-5541-4a17-90cd-cc487383beec?collection=education), and * Distribution voltage control case study (`DNcontrolCase`) . -For more information about the electricity market case study, you can reference the [Msc thesis](https://repository.tudelft.nl/islandora/object/uuid:58029e39-5541-4a17-90cd-cc487383beec?collection=education) - + The `config.xml` file is used to define the models in the case and where to -run the model. Here is an example of the information in the config.xml file. -It means we would like build only Wind and PV models in our simulation study. -The wind model is running and import from python file, and the PV model is running in another Raspi which ip address is ‘192.168.0.1’, and the master get the pv model information from the port ’5123’. +run the model. +For example in the `config.xml` below, we built a simulation with only Wind and PV models. +In the configuration below, the wind model runs (localy? in the master?) and the PV model runs in a **client** with IP '192.168.0.1', and the **master** get the PV model's information from the port the **client**'s port `5123`. + +```xml + #'Wind' ,'python','Models.Wind.wind_mosaik:WindSim' + #'PV','connect', '192.168.0.1:5123' + + + + + 0 + Wind + python + Models.Wind.wind_mosaik:WindSim + + + 1 + PV + connect + 192.168.0.1:5123 + +``` - ```xml - #'Wind' ,'python','Models.Wind.wind_mosaik:WindSim' - #'PV','connect', '192.168.0.1:5123' - - - - - 0 - Wind - python - Models.Wind.wind_mosaik:WindSim - - - 1 - PV - connect - 192.168.0.1:5123 - - ``` - The `connection.xml` file is to set how the message transferred from one model to others. - Here is an example of the information in the connection file. - The model ctrl send the information ‘flow2e’ to electrolyser to control its hydrogen generating speed. - The electrolyser send the ‘h2_gen’ information to model h2storage ‘h2_in’ to control the hydrogen storing speed. - ``` +The `connection.xml` file sets how the message are transfered from one model to others. +For example in the snippet below, the `ctrl` model sends information about 'flow2e' to `electrolyser` to control its hydrogen generating speed. +The `electrolyser` send the 'h2_gen' information to model `h2storage` ‘h2_in’ to control the hydrogen storing speed. + +```xml #['ctrl', 'electrolyser', 'flow2e'], #['electrolyser', 'h2storage', 'h2_gen', 'h2_in'], @@ -56,24 +60,30 @@ The wind model is running and import from python file, and the PV model is runni h2storage h2_gen h2_in - ``` +``` -2. The users can build case through run the python scripts `build_configuration_xml` in the folder `configuration`. Through running the scripts, the `config.xml` and `connection.xml` -file will be automatically built. If you want to change the configuration, the user need to change the parameter 'sim_config' and 'connection'. +### 2. Using the 'build configuration' Script + +User can configure a case using the python scripts `build_configuration_xml` in the folder `configuration/` directory. By executing the script, the `config.xml` and `connection.xml` +file will be automatically built. Use change the configuration by changing the parameters `sim_config` and `connection`. + + +### 3. Drawing Configurations + +The Illuminator also provide visualized method to create configuration. The user can use a smart board, touch screen or mouse to configurate +the case. To to this, firstly, run `drawpptx.py`. +Secondly, draw a configuration by hand and save as a PowerPoint file with a `.pptx` file extension. For example: -3. The Illuminator also provide visualized method to do the configuration. The user can use smarter board, touch screen or mouse to configurate -the case. Firstly, run `drawpptx.py`, the user can draw their configuration by hard draw and save as 'example.pptx' file, such as below.
- +
-Then run the script `readppt_connectionxml.py` to build the configuration. +Thirdly, run the script `readppt_connectionxml.py` to build the configuration files. -## Define models -The model parameters, results presentation and real-time simulation are all set in the file `buildmodelse.py`. +## Defining Models +Model parameters, results presentation and real-time simulation are all set in the file `buildmodelse.py`. ```python - Battery_initialset = {'initial_soc': 20} Battery_set = {'max_p': 500, 'min_p': -500, 'max_energy': 500, 'charge_efficiency': 0.9, 'discharge_efficiency': 0.9, @@ -190,46 +200,56 @@ The model parameters, results presentation and real-time simulation are all set 'prosumer_s1_4': {'MC': [0.10,0.37], 'MB': [0.44], 'MO': [0.01, 0.20], 'MR': [0.20]}, 'prosumer_s1_5': {'MC': [0.12], 'MB': [0.28], 'MO': [0.17], 'MR': [0.19]}, } - ``` -## Simulation + +## Running Simulations + +> This was set up as a shortcut to collect data and do plotting + Run the `simulation creator_**.py` to create and run the simulation based on the provided case and scenario. -If the user want to see the results shown in the dashboard, you need internet and sign up in [wandb software](https://wandb.ai/site). -There is also a simple example `simple_test.py` that show a simple case with the configuration inside of the file. +To see the results via the dashboard, you need Internet and sign up in [wandb software](https://wandb.ai/site). +The `simple_test.py` shows a simple case with the configuration inside of the file. ## Demos -We build four case study as demos to show how to use Illuminator to demonstrate this system at -a general user level and verify the Illuminator’s performance. -1. The first demo shows the residential energy community system which include Households, +Four case studies show how to use Illuminator, and to verify the Illuminator’s performance. + + +### 1. Residencial Case + +The first demo shows a residential energy community system which include Households, PV panels, Wind generators, Battery and Hydrogen system -to achieve electric power self-sufficiency. The controller’s -algorithm in the case study runs in the Master RasPi `Controllers\ResidentialController` , and -the rest simulators are separately deployed in different Client -RasPis.The data flow between the simulators is also shown in -the figure. Based on the inputs, including the generated power +to achieve electric power self-sufficiency. +The controller’s algorithm in this case runs in the **master** RasPi `Controllers/ResidentialController`, and +the rest **client** simulators are separately deployed in different +RasPis. The data flow between the simulators (clients) is also shown in +the figure below. Based on the inputs, including the generated power from PV and Wind, the consuming power of households, and the state of charge (Soc) of the Battery and Hydrogen, the controller decides the power from the Battery and Fuel cell -and the power to the Electrolyser. In the case study, we use +and the power to the Electrolyser. + +In the case study, we use simple logic to achieve self-sufficiency. If Battery has enough capacity for charging or discharging to achieve power balance, use the Battery first. If Battery doesn’t have enough capacity to achieve power balance, then use Electrolyser or Fuel cell -to achieve power balance. All the input data are in file `Scenarios` and all the output data are in file `Result\ResidentialCase`. +to achieve power balance. All the input data are in the `Scenarios/` directory and all the output data are in file `Result/ResidentialCase/`.
- +
-2. The second demo shows the Multi-carriers energy system, which including teh electricity +### 2. Multi-carriers Case +The second demo shows the Multi-carriers energy system, which incorporate the electricity network, hydrogen network and heat network. All the energy assets are shown in the below figure.
- +
-3. The third demon shows the electricity trade game and more details please refer to the Msc thesis https://repository.tudelft.nl/islandora/object/uuid:58029e39-5541-4a17-90cd-cc487383beec?collection=education +### 3. Electricity Trade Game +The third demo shows the electricity trade game and more details please refer to this [Msc thesis](https://repository.tudelft.nl/islandora/object/uuid:58029e39-5541-4a17-90cd-cc487383beec?collection=education) -4. The fourth demon shows the voltage control in the CIGRE LV voltage network. The network model is in the folder -`Models\EleDisNetworkSim`, the control method is in the `Controllers\NetVoltageControllerSim` +### 4. CIGRE LV Case +The fourth demo shows the voltage control in the CIGRE LV voltage network. The network model is in the `Models/EleDisNetworkSim/` directory, and the control method is in `Controllers/NetVoltageControllerSim/` diff --git a/readme.md b/readme.md index 7c805b7..f1262c8 100644 --- a/readme.md +++ b/readme.md @@ -6,7 +6,6 @@ state-of-the-art energy management concepts. The kit utilises Raspberry Pi's as individual components of an energy system emulator, and the simulation engine is based on [Mosaik](https://mosaik.offis.de/). - ## Installation [Describe the steps that users (not developers) should follow to install the code in each of the intended platforms (e.g. Window 10, MacOS, etc.).] @@ -75,16 +74,17 @@ The **master** provides a Dashboard to viazulize the results, and saves them to matplotlib itertools ``` -5. Send the Illuminator package [TODO: What is the illuminator package] to all *clients*. Use the following command on the *master's* terminal to check the connection between *master* and the *clients* +5. Send the Illuminator package [TODO: What is the illuminator package?] to all *clients*. Use the following command on the *master's* terminal to check the connection between *master* and the *clients* - ``` + ```shell ssh illuminator@ip #ip represent your follower IP address ``` [TODO: This suggest that all Pi's need a user with the name 'illuminator'] 6. Run the `buildcilentremoterun.py` file on each *client* and give all users execute permission to all the documents in `runshfile/` in order to make sure the leader can access the *client* model. - ``` + + ```shell chmod -R a+X *dir* ``` @@ -94,6 +94,7 @@ More detialed instructions are given in the [user guide document](user-guide.md) Since the Illuminator is Python based, this code can also run on regular machines(PC). If you run the Illuminator in one regular PC, then you don't need to do the Illuminator environment set up. + [TODO: More details are needed here] ## Contributing Guidelines @@ -127,5 +128,5 @@ The Illuminator project is supported by [TU Delft PowerWeb](https://www.tudelft. ## Contact and Support For more comprehensive support, please contact us at [illuminator@tudelft.nl](mailto:illuminator@tudelft.nl). Additionally, you can reach out to the main contributors for specific inquiries: -* [Aihui Fu](mailto:A.Fu@tudelft.nl) +* [Aihui Fu](mailto:A.Fu@tudelft.nl) [TODO: should we keep this name?] * [Dr.ir. Milos Cvetkovic](mailto:M.Cvetkovic@tudelft.nl) \ No newline at end of file diff --git a/simulation creator_DNcontrolCase.py b/simulation creator_DNcontrolCase.py index ba737fe..c543914 100644 --- a/simulation creator_DNcontrolCase.py +++ b/simulation creator_DNcontrolCase.py @@ -75,7 +75,6 @@ - controller=world.start('Controller') ctrl = controller.Ctrl(net=net, room=room) diff --git a/simulation creator_residentialcase.py b/simulation creator_residentialcase.py index 7b4172a..e2fe287 100644 --- a/simulation creator_residentialcase.py +++ b/simulation creator_residentialcase.py @@ -7,27 +7,27 @@ from mosaik.util import connect_many_to_one import time from configuration.buildmodelset import * -outputfile='Result/ResidentialCase/results.csv' -sim_config_file="Cases/ResidentialCase/" -sim_config_ddf=pd.read_xml(sim_config_file+'config.xml') -sim_config={row[1]:{row[2]:row[3]}for row in sim_config_ddf.values} +outputfile = 'Result/ResidentialCase/results.csv' +sim_config_file = "Cases/ResidentialCase/" +sim_config_ddf = pd.read_xml(sim_config_file + 'config.xml') +sim_config = {row[1]: {row[2]: row[3]} for row in sim_config_ddf.values} + +tosh = sim_config_ddf[sim_config_ddf['method'] == 'connect'] +# ! /usr/bin/env python # ERROR: # No errors found. Runs fine -tosh=sim_config_ddf[sim_config_ddf['method']=='connect'] -#! /usr/bin/env python if not tosh.empty: - with open ('run.sh', 'w') as rsh: + with open('run.sh', 'w') as rsh: rsh.write("#! /bin/bash") for row in tosh.values: - rsh.write("\n"+"lxterminal -e ssh illuminator@"+row[3].replace(':5123',' ')+"'./Desktop/Illuminator/configuration/runshfile/run"+row[1]+".sh'&") + rsh.write("\n" + "lxterminal -e ssh illuminator@" + row[3].replace(':5123', ' ') + + "'./Desktop/Illuminator/configuration/runshfile/run" + row[1] + ".sh'&") subprocess.run(['/bin/bash', '/home/illuminator/Desktop/Illuminator/configuration/run.sh']) - -connection=pd.read_xml(sim_config_file+'connection.xml') - +connection = pd.read_xml(sim_config_file + 'connection.xml') # if RESULTS_SHOW_TYPE['dashboard_show']==True: # #62f0da4aff384fd9b382b1d8057a128af9d102fe @@ -36,38 +36,37 @@ # wandb.define_metric("custom_step") - START_DATE = '2012-06-01 00:00:00' # START_DATE = '2012-06-30 23:45:00' -end = 1 * 24 * 3600 #last one interval is not computed +end = 1 * 24 * 3600 # last one interval is not computed WIND_DATA = 'Scenarios/winddata_NL.txt' Pv_DATA = 'Scenarios/pv_data_Rotterdam_NL-15min.txt' # solar data file ######################## -load_DATA = 'Scenarios/load_data.txt' ####################### -#set up the "world" of the scenario +load_DATA = 'Scenarios/load_data.txt' ####################### +# set up the "world" of the scenario world = mosaik.World(sim_config, debug=True) -models=pd.concat([connection["send"], connection["receive"]]) -models=models.drop_duplicates(keep='first', inplace=False) +models = pd.concat([connection["send"], connection["receive"]]) +models = models.drop_duplicates(keep='first', inplace=False) models.reset_index(drop=True, inplace=True) ##############################start simulator -Defined_models=pd.DataFrame() -Defined_models['model']=pd.Series(['Wind','PV','Load', - 'Electrolyser','H2storage','Battery','Fuelcell']) -number=[] +Defined_models = pd.DataFrame() +Defined_models['model'] = pd.Series(['Wind', 'PV', 'Load', + 'Electrolyser', 'H2storage', 'Battery', 'Fuelcell']) +number = [] for model in Defined_models['model']: number.append( - int((models.str.startswith(model.lower())==True).sum()) + int((models.str.startswith(model.lower()) == True).sum()) ) -Defined_models['number']=number +Defined_models['number'] = number ctrlsim = world.start('Controller') ctrl = ctrlsim.Ctrl(sim_start=START_DATE, soc_min=Battery_set['soc_min'], soc_max=Battery_set['soc_max'], h2_soc_min=h2_set['h2storage_soc_min'], h2_soc_max=h2_set['h2storage_soc_max'], fc_eff=fuelcell_set['eff']) - #### the controller gives us just a basic value of power flow which needs to be there. so -ve or +ve -collector = world.start('Collector', start_date=START_DATE,results_show=RESULTS_SHOW_TYPE,output_file=outputfile) +#### the controller gives us just a basic value of power flow which needs to be there. so -ve or +ve +collector = world.start('Collector', start_date=START_DATE, results_show=RESULTS_SHOW_TYPE, output_file=outputfile) monitor = collector.Monitor() for model_i in Defined_models.iterrows(): @@ -78,8 +77,8 @@ # 'Power_output_at_STC': 250} ## instantiating the pv model by giving the parameter values. pv = pvsim.PVset.create(model_i[1]['number'], sim_start=START_DATE, panel_data=pv_panel_set, - m_tilt=pv_set['m_tilt'], m_az=pv_set['m_az'], cap=pv_set['cap'], - output_type=pv_set['output_type']) # cap in W + m_tilt=pv_set['m_tilt'], m_az=pv_set['m_az'], cap=pv_set['cap'], + output_type=pv_set['output_type']) # cap in W solarprofile_data = solardata.Solar_data.create(model_i[1]['number']) # instantiating an entity of the solar data file for i in range(model_i[1]['number']): world.connect(solarprofile_data[i], pv[i], 'G_Gh', 'G_Dh', 'G_Bn', 'Ta', 'hs', 'FF', 'Az') @@ -88,8 +87,9 @@ windsim = world.start('Wind') # the name you gave to the in sim_config above wind = windsim.windmodel.create(model_i[1]['number'], sim_start=START_DATE, p_rated=Wind_set['p_rated'], u_rated=Wind_set['u_rated'], - u_cutin=Wind_set['u_cutin'],u_cutout=Wind_set['u_cutout'], - cp=Wind_set['cp'],diameter=Wind_set['diameter'], output_type=Wind_set['output_type']) # p_rated in kW #Resolution here is in minutes + u_cutin=Wind_set['u_cutin'], u_cutout=Wind_set['u_cutout'], + cp=Wind_set['cp'], diameter=Wind_set['diameter'], + output_type=Wind_set['output_type']) # p_rated in kW #Resolution here is in minutes ## print(wind.full_id) windspeed_data = WSdata.WS_datafile.create(model_i[1]['number']) # instantiating an entity of the wind data file for i in range(model_i[1]['number']): @@ -107,14 +107,14 @@ #### no battery input data file as the input 'p_ask' comes from the controller. We connect the controller and the battery ahead. batterysim = world.start('Battery') # the name you gave to the in sim_config above - #Battery_initialset = {'initial_soc': 20} + # Battery_initialset = {'initial_soc': 20} # Battery_set = {'max_p': 500, 'min_p': -500, 'max_energy': 500, # 'charge_efficiency': 0.9, 'discharge_efficiency': 0.9, # 'soc_min': 10, 'soc_max': 90, 'flag': -1, 'resolution': 15} # p in kW battery = batterysim.Batteryset(sim_start=START_DATE, initial_set=Battery_initialset, battery_set=Battery_set) ## print(battery.full_id) - elif model_i[1]['model'] == 'Electrolyser': + elif model_i[1]['model'] == 'Electrolyser': electrosim = world.start('Electrolyser') h2storagesim = world.start('H2storage') fcsim = world.start('Fuelcell') @@ -125,8 +125,8 @@ ramp_rate=electrolyser_set['ramp_rate']) # here resolution should be the same we have for the data sets for ## wind and pv and load. Make sure to keep the same resolution all across - #h2storage_initial = {'initial_soc': 20} - #h2_set = {'h2storage_soc_min': 10, 'h2storage_soc_max': 90, 'max_h2': 200, 'min_h2': -200, 'flag': -1} + # h2storage_initial = {'initial_soc': 20} + # h2_set = {'h2storage_soc_min': 10, 'h2storage_soc_max': 90, 'max_h2': 200, 'min_h2': -200, 'flag': -1} h2storage = h2storagesim.compressed_hydrogen(sim_start=START_DATE, initial_set=h2storage_initial, h2_set=h2_set) ## @@ -140,32 +140,32 @@ try: row['more'] except KeyError: - world.connect(eval(row['send']), eval(row['receive']), (row['messages'],row['messager'])) + world.connect(eval(row['send']), eval(row['receive']), (row['messages'], row['messager'])) else: - if row['more']=='async_requests=True': + if row['more'] == 'async_requests=True': # world.connect(eval(row['send']),eval(row['receive']),(row['messages'],row['messager']), # time_shifted=True, initial_data={row['messages']: 0}) world.connect(eval(row['send']), eval(row['receive']), (row['messages'], row['messager']), async_requests=True) else: - world.connect(eval(row['send']), eval(row['receive']), (row['messages'],row['messager'])) -if realtimefactor==0: + world.connect(eval(row['send']), eval(row['receive']), (row['messages'], row['messager'])) +if realtimefactor == 0: world.run(until=end) else: - world.run(until=end,rt_factor=realtimefactor) + world.run(until=end, rt_factor=realtimefactor) #################################final results show############################################ -if RESULTS_SHOW_TYPE['Finalresults_show']==True: +if RESULTS_SHOW_TYPE['Finalresults_show'] == True: import matplotlib.pyplot as plt import matplotlib - matplotlib.use('TkAgg') + # matplotlib.use('TkAgg') import pandas as pd - data=pd.read_csv(outputfile) - # Get all axes of figure - fig= plt.figure() - fig.subplots_adjust(hspace=0.5,wspace = 0.5) + data = pd.read_csv(outputfile) + # Get all axes of figure + fig = plt.figure() + fig.subplots_adjust(hspace=0.5, wspace=0.5) fig.suptitle('simulation results') - # Plot new data - ax1=fig.add_subplot(221) + # Plot new data + ax1 = fig.add_subplot(221) try: ax1.plot(data['PV-0.pv_0-pv_gen']) except KeyError: @@ -174,7 +174,7 @@ ax1.set_xlabel('time') ax1.set_ylabel('P [kW]') - ax2=fig.add_subplot(222) + ax2 = fig.add_subplot(222) try: ax2.plot(data['Wind-0.wind_0-wind_gen']) except KeyError: @@ -183,7 +183,7 @@ ax2.set_xlabel('time') ax2.set_ylabel('P [kW]') - ax3=fig.add_subplot(223) + ax3 = fig.add_subplot(223) try: ax3.plot(data['H2storage-0.h2storage_0-h2_soc']) except KeyError: @@ -192,8 +192,7 @@ ax3.set_xlabel('time') ax3.set_ylabel('soc [%]') - - ax4=fig.add_subplot(224) + ax4 = fig.add_subplot(224) try: ax4.plot(data['Battery-0.Battery_0-soc']) except KeyError: