diff --git a/.gitignore b/.gitignore index 9ba7ddfa6..f92752b52 100644 --- a/.gitignore +++ b/.gitignore @@ -131,4 +131,5 @@ mvs_csv_config.json /validation_tests/ -/docs/*.inc \ No newline at end of file +*.inc +*.tbl \ No newline at end of file diff --git a/.readthedocs.yml b/.readthedocs.yml index 7a51a1112..29ca0d058 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -9,10 +9,6 @@ sphinx: # Build documentation with MkDocs #mkdocs: # configuration: mkdocs.yml - -# Optionally build your docs in additional formats such as PDF -#formats: -# - pdf # Optionally set the version of Python and requirements required to build your docs python: version: 3.7 @@ -20,4 +16,6 @@ python: - requirements: requirements/docs.txt - requirements: requirements/default.txt - method: setuptools - path: . \ No newline at end of file + path: . +# Optionally build your docs in additional formats such as PDF +formats: all \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fdf871a2..b7448fc0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,8 @@ Here is a template for new release sections - Add tests for `C1.check_energy_system_can_fulfill_max_demand()`, including pseudo-benchmark test in `test_C1` (#824) - Zenodo badge on README (#850) - `VERSION_NUM` to simulation settings, added with `C0.add_version_number_used()` (#855) +- Generation of pdf version of the readthedocs (#853) +- `sphinx.ext.imgconverter` in `docs/conf.py` for svg images into pdf (#853) ### Changed - Update the release protocol in `CONTRIBUTING.md` (#821) @@ -52,11 +54,14 @@ Here is a template for new release sections - The `DISPATCHABILITY` of energyConsumption assets is now set to FALSE by default (#824) - Function `C0.define_sink()` now also defines `DISPATCHABILITY=TRUE` for the created sink. - Only implement the constraints defined by the user explicitly: move accessing the constraint key in `dict_value` in the respective constraint preparation functions (#845) +- Readthedocs restructure of chapters (#853) + ### Removed - `AUTO_SOURCE` and `AUTO_SINK` as this overcomplicated the labelling process (#837) - `EXCESS_SINK_POSTFIX` and only use `EXCESS` (#837) - Quotes for command line instruction in README.rst (#850) +- Superfluous `docs/readthedocs.yml` file (#853) ### Fixed - Skip `test_benchmark_KPI` as it was seen to be consuming the whole test time leading to timeout on github action (#826) diff --git a/docs/Installation.rst b/docs/Installation.rst index 86c2cdd5a..ead167d84 100644 --- a/docs/Installation.rst +++ b/docs/Installation.rst @@ -1,3 +1,7 @@ .. _installation-steps: -.. include:: ../README.rst +============ +Installation +============ + +.. include:: readme.inc diff --git a/docs/MVS_kpis_list.csv b/docs/MVS_kpis_list.csv new file mode 100644 index 000000000..e127c8c54 --- /dev/null +++ b/docs/MVS_kpis_list.csv @@ -0,0 +1,2 @@ +:Definition:,:Valid Interval:,:Type:,:Unit:,label,ref,category,see_also +None,real number,numeric,curreny,Net Present Costs,net_present_cost,economic, \ No newline at end of file diff --git a/docs/Model_Assumptions.rst b/docs/Model_Assumptions.rst deleted file mode 100644 index 3d7e1e6a0..000000000 --- a/docs/Model_Assumptions.rst +++ /dev/null @@ -1,1099 +0,0 @@ -================================ -Modeling Assumptions of the MVS -================================ - -Cost calculations ------------------ - -The optimization in the MVS is mainly a cost optimization. There are some additional constraints that can be introduced, mainly by adding bounds eg. by limiting the maximum capacity that can be installed (comp. :ref:`maxcap-label`) or adding constraints for certain key performance indicators (see :ref:`constraints-label`). To optimize the energy systems properly, the economic data provided with the input data has to be pre-processed (also see :ref:`economic_precalculation-label`) and then also post-processed when evaluating the results. Following assumptions are important: - -* :ref:`Project lifetime `: The simulation has a defined project lifetime, for which continuous operation is assumed - which means that the first year of operation is exactly like the last year of operation. Existing and optimized assets have to be replaced to make this possible. -* :ref:`Simulation duration `: It is advisable to simulate whole year to find the most suitable combination of energy assets for your system. Sometimes however you might want to look at specific seasons to see their effect - this is possible in the MVS by choosing a specific start date and simulation duration. -* :ref:`Asset costs `: Each asset can have development costs, specific investment costs, specific operation and management costs as well as dispatch costs. - * *Replacement costs* are calculated based on the lifetime of the assets, and residual values are paid at the end of the project. - * *Development costs* are costs that will occurr regardless of the installed capacity of an asset - even if it is not installed at all. It stands for system planning and licensing costs. If you have optimized your energy system and see that an asset might not be favourable (zero optimized capacities), you might want to run the simulation again and remove the asset, or remove the development costs of the asset. - * *Specific investment costs* and *specific operation and maintenance costs* are used to calculate the annual expenditures that an asset has per year, in the process also adding the replacement costs. - * *Dispatch price* can often be set to zero, but are supposed to cover instances where utilization of an asset requires increased operation and maintenance or leads to wear. -* :ref:`Pre-existing capacities `: It is possible to add assets that already exist in your energy system with their capacity and age. - * *Replacements* - To ensure that the energy system operates continously, the existing assets are replaced with the same capacities when they reached their end of life within the project lifetime. - * *Replacement costs* are calculated based on the lifetime of the asset in general and the age of the pre-existing capacities -* `Fix project costs `__: It is possible to define fix costs of the project - this is important if you want to compare different project locations with each other. You can define... - * *Development costs*, which could for example stand for the cost of licenses of the whole energy system - * *(Specific) investment costs*, which could be an investment into land or buildings at the project site. When you define a lifetime for the investment, the MVS will also consider replacements and reimbursements. - * *(Specific) operation and management costs*, which can cover eg. the salaries of at the project site - -.. _component_models: - -Component models ----------------- - -The component models of the MVS result from the used python-library `oemof-solph` for energy modeling. - -It requires component models to be simplified and linearized. -This is the reason that the MVS can provide a pre-feasibility study of a specific system setup, -but not the final sizing and system design. -The types of assets are presented below. - -.. _energy_consumption: - -Energy consumption -################## - -Demands within the MVS are added as energy consumption assets in `energyConsumption.csv`. Most importantly, they are defined by a timeseries, representing the demand profile, and their energy vector. A number of demand profiles can be defined for one energy system, both of the same and different energy vectors. -The main optimization goal for the MVS is to supply the defined demand withouth fail for all of the timesteps in the simulation with the least cost of supply (comp. :ref:`economic_precalculation-label`). - - -.. _energy_production: - -Energy production -################# - -Non-dispatchable sources of generation -====================================== - -`Examples`: - - - PV plants - - Wind plants - - Run-of-the-river hydro power plants - - Solar thermal collectors - -Variable renewable energy (VRE) sources, like wind and PV, are non-dispatchable due to their fluctuations in supply. They are added as sources in `energyProduction.csv`. - -The fluctuating nature of non-dispatchable sources is represented by generation time series that show the respective production for each time step of the simulated period. In energy system modelling it is common to use hourly time series. -The name of the file containing the time series is added to `energyProduction.csv` with the parameter :ref:`filename-label`. For further requirements concerning the time series see section :ref:`time_series_folder`. - -If you cannot provide time series for your VRE assets you can consider to calculate them by using models for generating feed-in time series from weather data. The following is a list of examples, which is not exhaustive: - - - PV: `pvlib `_ , `Renewables Ninja `_ (download capacity factors) - - Wind: `windpowerlib `_, `Renewables Ninja `_ (download capacity factors) - - Hydro power (run-of-the-river): `hydropowerlib `_ - - Solar thermal: `flat plate collectors `_ of `oemof.thermal `_ - - -.. _dispatchable_sources: - -Dispatchable sources of generation -================================== - -`Examples`: - - - Fuel sources - - Deep-ground geothermal plant (ground assumed to allow unlimited extraction of heat, not depending on season) - -Fuel sources are added as dispatchable sources, which can have development, investment, operational and dispatch costs. -They are added to `energyProduction.csv`, while setting :ref:`filename-label` to `None`. - -Fuel sources are for example needed as source for a diesel generator (diesel), biogas plant (gas) or a condensing power plant (gas, coal, ...), see :ref:`energy_conversion`. - -Energy providers, even though also dispatchable sources of generation, should be added via `energyProviders.csv`, -as there are some additional features available then, see :ref:`energy_providers`. - -Both energy providers and the additional fuel sources are limited to the options of energy carriers provided in the table of :ref:`table_default_energy_carrier_weights_label`, as the default weighting factors to translate the energy carrier into electricity equivalent need to be defined. - - -.. _energy_conversion: - -Energy conversion -################# - -`Examples`: - - - Electric transformers (rectifiers, inverters, transformer stations, charge controllers) - - HVAC and Heat pumps (as heater and/or chiller) - - Combined heat and power (CHP) and other condensing power plants - - Diesel generators - - Electrolyzers - - Biogas power plants - -Conversion assets are added as transformers and are defined in `energyConversion.csv`. - -The parameters `dispatch_price`, `efficiency` and `installedCap` of transformers are assigned to their output flows. -This means that these parameters need to be given for the output of the asset and that the costs of the input, e.g. fuel, if existent, are not included in its `dispatch_price` but in the `dispatch_price` of the fuel source, see :ref:`dispatchable_sources`. - -Conversion assets can be defined with multiple inputs or multiple outputs, but one asset currently cannot have both, multiple inputs and multiple outputs. Note that multiple inputs/output have not been tested, yet. - -.. _energyconversion_electric_transformers: - -Electric transformers -===================== - -Electric rectifiers and inverters that are transforming electricity in one direction only, are simply added as transformers. -Bidirectional converters and transformer stations are defined by two transformers that are optimized independently from each other, if optimized. -The same accounts for charge controllers for a :ref:`battery_storage` that are defined by two transformers, one for charging and one for discharging. -The parameters `dispatch_price`, `efficiency` and `installedCap` need to be given for the electrical output power of the electric transformers. - -.. note:: - When using two conversion objects to emulate a bidirectional conversion asset, their capacity should be interdependent. This is currently not the case, see `Infeasible bi-directional flow in one timestep `_. - -.. _energyconversion_hvac: - -Heating, Ventilation, and Air Conditioning (HVAC) -================================================= - -Like other conversion assets, devices for heating, ventilation and air conditioning (HVAC) are added as transformers. As the parameters `dispatch_price`, `efficiency` and `installedCap` are assigned to the output flows they need to be given for the nominal heat output of the HVAC. - -Different types of HVAC can be modelled. Except for an air source device with ambient temperature as heat reservoir, the device could be modelled with two inputs (electricity and heat) in case the user is interested in the heat reservoir. This has not been tested, yet. Also note that currently efficiencies are assigned to the output flows the see `issue #799 `_. -Theoretically, a HVAC device can be modelled with multiple outputs (heat, cooling, ...); this has not been tested, yet. - -The efficiency of HVAC systems is defined by the coefficient of performance (COP), which is strongly dependent on the temperature. In order to take account of this, the efficiency can be defined as time series, see section :ref:`time_series_params`. -If you do not provide your own COP time series you can calculate them with `oemof.thermal `_, see `documentation on compression heat pumps and chillers `_ and `documentation on absorption chillers `_. - -.. _energyconversion_electrolyzers: - -Electrolyzers -============= - -Electrolyzers are added as transformers with a constant or time dependent but in any case pre-defined efficiency. The parameters `dispatch_price`, `efficiency` and `installedCap` need to be given for the output of the electrolyzers (hydrogen). - -Currently, electrolyzers are modelled with only one input flow (electricity), not taking into account the costs of water; see `issue #799 `_. -The minimal operation level and consumption in standby mode are not taken into account, yet, see `issue #50 `_. - -.. _power_plants: - -Condensing power plants and Combined heat and power (CHP) -========================================================= - -Condensing power plants are added as transformers with one input (fuel) and one output (electricity), while CHP plants are defined with two outputs (electricity and heat). -The parameters `dispatch_price`, `efficiency` and `installedCap` need to be given for the electrical output power (and nominal heat output) of the power plant, while fuel costs need to be included in the `dispatch_price` of the fuel source. - -The ratio between the heat and electricity output of a CHP is currently simulated as fix values. This might be changed in the future by using the `ExtractionTurbineCHP `_ -or the `GenericCHP `_ component of oemof, see `issue #803 `_ - -Note that multiple inputs/output have not been tested, yet. - -Other fuel powered plants -========================= - -Fuel powered conversion assets, such as diesel generators and biogas power plants, are added as transformers. -The parameters `dispatch_price`, `efficiency` and `installedCap` need to be given for the electrical output power of the diesel generator or biogas power plant. -As described above, the costs for diesel and gas need to be included in the `dispatch_price` of the fuel source. - - -.. _energy_providers: - -Energy providers -################ - -The energy providers are the most complex assets in the MVS model. They are composed of a number of sub-assets - - - Energy consumption source, providing the energy required from the system with a certain price - - Energy peak demand pricing "transformers", which represent the costs induced due to peak demand - - Bus connecting energy consumption source and energy peak demand pricing transformers - - Energy feed-in sink, able to take in generation that is provided to the energy provider for revenue - - Optionally: Transformer Station connecting the energy provider bus to the energy bus of the LES - -With all these components, the energy provider can be visualized as follows: - -.. image:: images/Model_Assumptions_energyProvider_assets.png - :width: 600 - -Variable energy consumption prices (time-series) -================================================ - -Energy consumption prices can be added as values that vary over time. See section :ref:`time_series_folder` or more information. - -.. _energy_providers_peak_demand_pricing: - -Peak demand pricing -=================== - -A peak demand pricing scheme is based on an electricity tariff, -that requires the consumer not only to pay for the aggregated energy consumption in a time period (eg. kWh electricity), -but also for the maximum peak demand (load, eg. kW power) towards the grid of the energy provider within a specific pricing period. - -In the MVS, this information is gathered for the `energyProviders` with: - - - :const:`multi_vector_simulator.utils.constants_json_strings.PEAK_DEMAND_PRICING_PERIOD` as the period used in peak demand pricing. Possible is 1 (yearly), 2 (half-yearly), 3 (each trimester), 4 (quaterly), 6 (every 2 months) and 12 (each month). If you have a `simulation_duration` < 365 days, the periods will still be set up assuming a year! This means, that if you are simulating 14 days, you will never be able to have more than one peak demand pricing period in place. - - - :const:`multi_vector_simulator.utils.constants_json_strings.PEAK_DEMAND_PRICING` as the costs per peak load unit, eg. kW - -To represent the peak demand pricing, the MVS adds a "transformer" that is optimized with specific operation and maintenance costs per year equal to the PEAK_DEMAND_PRICING for each of the pricing periods. -For two peak demand pricing periods, the resulting dispatch could look as following: - -.. image:: images/Model_Assumptions_Peak_Demand_Pricing_Dispatch_Graph.png - :width: 600 - -.. _energy_storage: - -Energy storage -############## - -Energy storages such as battery storages, thermal storages or H2 storages are modelled with the *GenericStorage* component of *oemof.solph*. They are designed for one input and one output and are defined with files `energyStorage.csv` and `storage_*.csv` and have several parameters, which are listed in the section :ref:`storage_csv`. - -The state of charge of a storage at the first and last time step of an optimization are equal. -Charge and discharge of the whole capacity of the energy storage are possible within one time step in case the capacity of the storage is not optimized. In case of -capacity optimization charge and discharge is limited by the :ref:`crate-label`. - -.. _battery_storage: - -Battery energy storage system (BESS) -==================================== - -BESS are modelled as *GenericStorage* like described above. The BESS can either be connected directly to the electricity bus of the LES or via a charge controller that manages the BESS. -When choosing the second option, the capacity of the charge controller can be optimized individually, which takes its specific costs and lifetime into consideration. -If you do not want to optimize the charge controller's capacity you can take its costs and efficiency into account when defining the storage's input and output power, see :ref:`storage_csv`. -A charge controller is defined by two transformers, see section :ref:`energy_conversion` above. - -Note that capacity reduction over the lifetime of a BESS that may occur due to different effects during aging cannot be taken into consideration in MVS. A possible workaround for this could be to manipulate the lifetime. - - -Hydrogen storage (H2) -===================== - -Hydrogen storages are modelled as all storage types in MVS with as *GenericStorage* like described above. - -The most common hydrogen storages store H2 as liquid under temperatures lower than -253 °C or under high pressures. -The energy needed to provide these requirements cannot be modelled via the storage component as another energy sector such as cooling or electricity is needed. It could therefore, be modelled as an additional demand of the energy system, see `issue #811 `_ - -.. _thermal_storage: - -Thermal energy storage -====================== - -Thermal energy storages of the type sensible heat storage (SHS) are modelled as *GenericStorage* like described above. The implementation of a specific type of SHS, the stratified thermal energy storage, is described in section :ref:`stratified_tes`. -The modelling of latent-heat (or Phase-change) and chemical storages have not been tested with MVS, but might be achieved by precalculations. - -.. _stratified_tes: - -Stratified thermal energy storage -================================= - -Stratified thermal energy storage is defined by the two optional parameters `fixed_losses_relative` and `fixed_losses_absolute`. If they are not included in `storage_*.csv` or are equal to zero, then a normal generic storage is simulated. -These two parameters are used to take into account temperature dependent losses of a thermal storage. To model a thermal energy storage without stratification, the two parameters are not set. The default values of `fixed_losses_relative` and `fixed_losses_absolute` are zero. -Except for these two additional parameters the stratified thermal storage is implemented in the same way as other storage components. - -Precalculations of the `installedCap`, `efficiency`, `fixed_losses_relative` and `fixed_losses_absolute` can be done orientating on the stratified thermal storage component of `oemof.thermal `__. -The parameters `U-value`, `volume` and `surface` of the storage, which are required to calculate `installedCap`, can be precalculated as well. - -The efficiency :math:`\eta` of the storage is calculated as follows: - -.. math:: - \eta = 1 - loss{\_}rate - -This example shows how to do precalculations using stratified thermal storage specific input data: - - -.. code-block:: python - - from oemof.thermal.stratified_thermal_storage import ( - calculate_storage_u_value, - calculate_storage_dimensions, - calculate_capacities, - calculate_losses, - ) - - # Precalculation - u_value = calculate_storage_u_value( - input_data['s_iso'], - input_data['lamb_iso'], - input_data['alpha_inside'], - input_data['alpha_outside']) - - volume, surface = calculate_storage_dimensions( - input_data['height'], - input_data['diameter'] - ) - - nominal_storage_capacity = calculate_capacities( - volume, - input_data['temp_h'], - input_data['temp_c']) - - loss_rate, fixed_losses_relative, fixed_losses_absolute = calculate_losses( - u_value, - input_data['diameter'], - input_data['temp_h'], - input_data['temp_c'], - input_data['temp_env']) - -Please see the `oemof.thermal` `examples `__ and the `documentation `__ for further information. - -For an investment optimization the height of the storage should be left open in the precalculations and `installedCap` should be set to 0 or NaN. - -An implementation of the stratified thermal storage component has been done in `pvcompare `__. You can find the precalculations of the stratified thermal energy storage made in `pvcompare` `here `__. - - -Energy excess -############# - -.. note:: - Energy excess components are implemented **automatically** by MVS! You do not need to define them yourself. - -An energy excess sink is placed on each of the LES energy busses, and therefore energy excess is allowed to take place on each bus of the LES. -This means that there are assumed to be sufficient vents (heat) or transistors (electricity) to dump excess (waste) generation. -Excess generation can only take place when a non-dispatchable source is present or if an asset can supply energy without any fuel or dispatch costs. - -In case of excessive excess energy, a warning is given that it seems to be cheaper to have high excess generation than investing into more capacities. -High excess energy can for example result into an optimized inverter capacity that is smaller than the peak generation of installed PV. -This becomes unrealistic when the excess is very high. - -.. _constraints-label: - -Constraints ------------ - -Constraints are controlled with the file `constraints.csv`. - -.. _constraint_min_re_factor: - -Minimal renewable factor constraint -################################### - -The minimal renewable factor constraint requires the capacity and dispatch optimization of the MVS to reach at least the minimal renewable factor defined within the constraint. The renewable share of the optimized energy system may also be higher than the minimal renewable factor. - -The minimal renewable factor is applied to the minimal renewable factor of the whole, sector-coupled energy system, but not to specific sectors. As such, energy carrier weighting plays a role and may lead to unexpected results. The constraint reads as follows: - -.. math:: - minimal renewable factor <= \frac{\sum renewable generation \cdot weighting factor}{\sum renewable generation \cdot weighting factor + \sum non-renewable generation \cdot weighting factor} - -Please be aware that the minimal renewable factor constraint defines bounds for the :ref:`kpi_renewable_factor` of the system, ie. taking into account both local generation as well as renewable supply from the energy providers. The constraint explicitly does not aim to reach a certain :ref:`kpi_renewable_share_of_local_generation` on-site. - -:Deactivating the constraint: - -The minimal renewable factor constraint is deactivated by inserting the following row in `constraints.csv` as follows: - -```minimal_renewable_factor,factor,0``` - -:Activating the constraint: - -The constraint is enabled when the value of the minimal renewable factor factor is above 0 in `constraints.csv`: - -```minimal_renewable_factor,factor,0.3``` - - -Depending on the energy system, especially when working with assets which are not to be capacity-optimized, it is possible that the minimal renewable factor criterion cannot be met. The simulation terminates in that case. If you are not sure if your energy system can meet the constraint, set all `optimize_Cap` parameters to `True`, and then investigate further. -Also, if you are aiming at very high minimal renewable factors, the simulation time can increase drastically. If you do not get a result after a maximum of 20 Minutes, you should consider terminating the simulation and trying with a lower minimum renewable share. - -The minimum renewable share is introduced to the energy system by `D2.constraint_minimal_renewable_share()` and a validation test is performed with `E4.minimal_renewable_share_test()`. - -.. _constraint_minimal_degree_of_autonomy: - -Minimal degree of autonomy constraint -###################################### - -The minimal degree of autonomy constraint requires the capacity and dispatch optimization of the MVS to reach at least the minimal degree of autonomy defined within the constraint. The degree of autonomy of the optimized energy system may also be higher than the minimal degree of autonomy. Please find the definition of here: :ref:`kpi_degree_of_autonomy` - -The minimal degree of autonomy is applied to the whole, sector-coupled energy system, but not to specific sectors. As such, energy carrier weighting plays a role and may lead to unexpected results. The constraint reads as follows: - -.. math:: - minimal~degree~of~autonomy <= DA = \frac{\sum E_{demand,i} \cdot w_i - \sum E_{consumption,provider,j} \cdot w_j}{\sum E_{demand,i} \cdot w_i} - -:Deactivating the constraint: - -The minimal degree of autonomy constraint is deactivated by inserting the following row in `constraints.csv` as follows: - -```minimal_degree_of_autonomy,factor,0``` - -:Activating the constraint: - -The constraint is enabled when the value of the minimal degree of autonomy is above 0 in `constraints.csv`: - -```minimal_degree_of_autonomy,factor,0.3``` - - -Depending on the energy system, especially when working with assets which are not to be capacity-optimized, it is possible that the minimal degree of autonomy criterion cannot be met. The simulation terminates in that case. If you are not sure if your energy system can meet the constraint, set all `optimizeCap` parameters to `True`, and then investigate further. - -The minimum degree of autonomy is introduced to the energy system by `D2.constraint_minimal_degree_of_autonomy()` and a validation test is performed with `E4.minimal_degree_of_autonomy()`. - -.. _constraint_maximum_emissions: - -Maximum emission constraint -########################### - -The maximum emission constraint limits the maximum amount of total emissions per year of the energy system. It allows the capacity and dispatch optimization of the MVS to result into a maximum amount of emissions defined by the maximum emission constraint. The yearly emissions of the optimized energy system may also be lower than the maximum emission constraint. - -Please note that the maximum emissions constraint currently does not take into consideration life cycle emissions, also see :ref:`emissions` section for an explanation. - -:Activating the constraint: - -The maximum emissions constraint is enabled by inserting the following row in `constraints.csv` as follows: - -```maximum_emissions,kgCO2eq/a,800000``` - -:Deactivating the constraint: - -The constraint is deactivated by setting the value in `constraints.csv` to None: - -```maximum_emissions,kgCO2eq/a,None``` - -The unit of the constraint is `kgCO2eq/a`. To select a useful value for this constraint you can e.g.: - -- Firstly, optimize your system without the constraint to get an idea about the scale of the emissions and then, secondly, set the constraint and lower the emissions step by step until you receive an unbound problem (which then represents the non-archievable minimum of emissions for your energy system) -- Check the emissions targets of your region/country and disaggregate the number - -The maximum emissions constraint is introduced to the energy system by `D2.constraint_maximum_emissions()` and a validation test is performed with `E4.maximum_emissions_test()`. - -.. _constraint_net_zero_energy: - -Net zero energy (NZE) constraint -################################ - -The net zero energy (NZE) constraint requires the capacity and dispatch optimization of the MVS to result into a net zero system, but can also result in a plus energy system. -The degree of NZE of the optimized energy system may be higher than 1, in case of a plus energy system. Please find the definition of net zero energy (NZE) and the KPI here: :ref:`kpi_degree_of_nze`. - -Some definitions of NZE systems in literature allow the energy system's demand solely be provided by locally generated renewable energy. In MVS this is not the case - all locally generated energy is taken into consideration. To enlarge the share of renewables in the energy system you can use the :ref:`constraint_min_re_factor`. - -The NZE constraint is applied to the whole, sector-coupled energy system, but not to specific sectors. As such, energy carrier weighting plays a role and may lead to unexpected results. The constraint reads as follows: - -.. math:: - \sum_{i} {E_{feedin, DSO} (i) \cdot w_i - E_{consumption, DSO} (i) \cdot w_i} >= 0 - -:Deactivating the constraint: - -The NZE constraint is deactivated by inserting the following row in `constraints.csv` as follows: - -```net_zero_energy,bool,False``` - -:Activating the constraint: - -The constraint is enabled when the value of the NZE constraint is set to `True` in `constraints.csv`: - -```net_zero_energy,bool,True``` - - -Depending on the energy system, especially when working with assets which are not to be capacity-optimized, it is possible that the NZE criterion cannot be met. The simulation terminates in that case. If you are not sure if your energy system can meet the constraint, set all `optimizeCap` parameters to `True`, and then investigate further. - -The net zero energy constraint is introduced to the energy system by `D2.constraint_net_zero_energy()` and a validation test is performed with `E4.net_zero_energy_test()`. - - - - -Weighting of energy carriers ----------------------------- - -To be able to calculate sector-wide key performance indicators, it is necessary to assign weights to the energy carriers based on their usable potential. In the conference paper handed in to the CIRED workshop, we have proposed a methodology comparable to Gasoline Gallon Equivalents. - -After thorough consideration, it has been decided to base the equivalence in tonnes of oil equivalent (TOE). Electricity has been chosen as a baseline energy carrier, as our pilot sites mainly revolve around it and also because we believe that this energy carrier will play a larger role in the future. For converting the results into a more conventional unit, we choose crude oil as a secondary baseline energy carrier. This also enables comparisons with crude oil price developments in the market. For most KPIs, the baseline energy carrier used is of no relevance as the result is not dependent on it. This is the case for KPIs such as the share of renewables at the project location or its self-sufficiency. The choice of the baseline energy carrier is relevant only for the levelized cost of energy (LCOE), as it will either provide a system-wide supply cost in Euro per kWh electrical or per kg crude oil. - -First, the conversion factors to kg crude oil equivalent [`1 `__] were determined (see :ref:`table_kgoe_conversion_factors` below). These are equivalent to the energy carrier weighting factors with baseline energy carrier crude oil. - -Following conversion factors and energy carriers are defined: - -.. _table_kgoe_conversion_factors: - -.. list-table:: Conversion factors: kg crude oil equivalent (kgoe) per unit of a fuel - :widths: 50 25 25 - :header-rows: 1 - - * - Energy carrier - - Unit - - Value - * - H2 [`3 `__] - - kgoe/kgH2 - - 2.87804 - * - LNG - - kgoe/kg - - 1.0913364 - * - Crude oil - - kgoe/kg - - 1 - * - Gas oil/diesel - - kgoe/litre - - 0.81513008 - * - Kerosene - - kgoe/litre - - 0.0859814 - * - Gasoline - - kgoe/litre - - 0.75111238 - * - LPG - - kgoe/litre - - 0.55654228 - * - Ethane - - kgoe/litre - - 0.44278427 - * - Electricity - - kgoe/kWh(el) - - 0.0859814 - * - Biodiesel - - kgoe/litre - - 0.00540881 - * - Ethanol - - kgoe/litre - - 0.0036478 - * - Natural gas - - kgoe/litre - - 0.00080244 - * - Heat - - kgoe/kWh(therm) - - 0.086 - * - Heat - - kgoe/kcal - - 0.0001 - * - Heat - - kgoe/BTU - - 0.000025 - -The values of ethanol and biodiesel seem comparably low in [`1 `__] and [`2 `__] and do not seem to be representative of the net heating value (or lower heating value) that was expected to be used here. - -From this, the energy weighting factors using the baseline energy carrier electricity are calculated (see :ref:`table_default_energy_carrier_weights_label`). - -.. _table_default_energy_carrier_weights_label: - -.. list-table:: Electricity equivalent conversion per unit of a fuel - :widths: 50 25 25 - :header-rows: 1 - - * - Product - - Unit - - Value - * - LNG - - kWh(eleq)/kg - - 33.4728198 - * - Crude oil - - kWh(eleq)/kg - - 12.6927029 - * - Gas oil/diesel - - kWh(eleq)/litre - - 11.630422 - * - Kerosene - - kWh(eleq)/litre - - 9.48030688 - * - Gasoline - - kWh(eleq)/litre - - 8.90807395 - * - LPG - - kWh(eleq)/litre - - 8.73575397 - * - Ethane - - kWh(eleq)/litre - - 6.47282161 - * - H2 - - kWh(eleq)/kgH2 - - 5.14976795 - * - Electricity - - kWh(eleq)/kWh(el) - - 1 - * - Biodiesel - - kWh(eleq)/litre - - 0.06290669 - * - Ethanol - - kWh(eleq)/litre - - 0.04242544 - * - Natural gas - - kWh(eleq)/litre - - 0.00933273 - * - Heat - - kWh(eleq)/kWh(therm) - - 1.0002163 - * - Heat - - kWh(eleq)/kcal - - 0.00116304 - * - Heat - - kWh(eleq)/BTU - - 0.00029076 - -With this, the equivalent potential of an energy carrier *E*:sub:`{eleq,i}`, compared to electricity, can be calculated with its conversion factor *w*:sub:`i` as: - -.. math:: - E_{eleq,i} = E_{i} \cdot w_{i} - -As it can be noticed, the conversion factor between heat (kWh(therm)) and electricity (kWh(el)) is almost 1. The deviation stems from the data available in source [`1 `__] and [`2 `__]. The equivalency of heat and electricity can be a source of discussion, as from an exergy point of view these energy carriers can not be considered equivalent. When combined, say with a heat pump, the equivalency can also result in ripple effects in combination with the minimal renewable factor or the minimal degree of autonomy, which need to be evaluated during the pilot simulations. - -:Code: - -Currently, the energy carrier conversion factors are defined in `constants.py` with `DEFAULT_WEIGHTS_ENERGY_CARRIERS`. New energy carriers should be added to its list when needed. Unknown carriers raise an `UnknownEnergyVectorError` error. - -:Comment: - -Please note that the energy carrier weighting factor is not applied dependent on the LABEL of the energy asset, but based on its energy vector. Let us consider an example: - -In our system, we have a dispatchable `diesel fuel source`, with dispatch carrying the unit `l Diesel`. -The energy vector needs to be defined as `Diesel` for the energy carrier weighting to be applied, ie. the energy vector of `diesel fuel source` needs to be `Diesel`. This will also have implications for the KPI: -For example, the `degree of sector coupling` will reach its maximum, when the system only has heat demand and all of it is provided by processing diesel fuel. If you want to portrait diesel as something inherent to heat supply, you will need to make the diesel source a heat source, and set its `dispatch costs` to currency/kWh, ie. divide the diesel costs by the heating value of the fuel. - -:Comment: - -In the MVS, there is no distinction between energy carriers and energy vector. For `Electricity` of the `Electricity` vector this may be self-explanatory. However, the energy carriers of the `Heat` vector can have different technical characteristics: A fluid on different temperature levels. As the MVS measures the energy content of a flow in kWh(thermal) however, this distinction is only relevant for the end user to be aware of, as two assets that have different energy carriers as an output should not be connected to one and the same bus if a detailed analysis is expected. An example of this would be, that a system where the output of the diesel boiler as well as the output of a solar thermal panel are connected to the same bus, eventhough they can not both supply the same kind of heat demands (radiator vs. floor heating). This, however, is something that the end-user has to be aware of themselves, eg. by defining self-explanatory labels. - -Emission factors ----------------- - -In order to optimise the energy system with minimum emissions, it is important to calculate emission per unit of fuel consumption. - -In table :ref:`table_emissions_energyCarriers` the emission factors for energy carriers are defined. These values are based on direct emissions during stationary consumption of the mentioned fuels. - -.. _table_emissions_energyCarriers: - -.. list-table:: Emission factors: Kg of CO2 equivalent per unit of fuel consumption - :widths: 50 25 25 25 - :header-rows: 1 - - * - Energy carrier - - Unit - - Value - - Source - * - Diesel - - kgCO2eq/litre - - 2.7 - - [`4 `__] Page No. 26 - * - Gasoline - - kgCO2eq/litre - - 2.3 - - [`4 `__] Page No. 26 - * - Kerosene - - kgCO2eq/litre - - 2.5 - - [`4 `__] Page No. 26 - * - Natural gas - - kgCO2eq/m3 - - 1.9 - - [`4 `__] Page No. 26 - * - LPG - - kgCO2eq/litre - - 1.6 - - [`4 `__] Page No. 26 - * - Biodiesel - - kgCO2eq/litre - - 0.000125 - - [`5 `__] Page No. 6 - * - Bioethanol - - kgCO2eq/litre - - 0.0000807 - - [`5 `__] Page No. 6 - * - Biogas - - kgCO2eq/m3 - - 0.12 - - [`6 `__] Page No. 1 - -In table :ref:`table_CO2_emissions_countries` the CO2 emissions for Germany and the four pilot sites (Norway, Spain, Romania, India) are defined: - -.. _table_CO2_emissions_countries: - -.. list-table:: CO2 Emission factors: grams of CO2 equivalent per kWh of electricity consumption - :widths: 50 25 25 25 - :header-rows: 1 - - * - Country - - Unit - - Value - - Source - * - Germany - - gCO2eq/kWh - - 338 - - [`7 `__] Fig. 2 - * - Norway - - gCO2eq/kWh - - 19 - - [`7 `__] Fig. 2 - * - Spain - - gCO2eq/kWh - - 207 - - [`7 `__] Fig. 2 - * - Romania - - gCO2eq/kWh - - 293 - - [`7 `__] Fig. 2 - * - India - - gCO2eq/kWh - - 708 - - [`8 `__] Page No. 7 - -The values mentioned in the table above account for emissions during the complete life cycle. This includes emissions during energy production, energy conversion, energy storage and energy transmission. - -Limitations ------------ - -When running simulations with the MVS, there are certain peculiarities to be aware of. -The peculiarities can be considered as limitations, some of which are merely model assumptions and others are drawbacks of the model. -A number of those are inherited due to the nature of the MVS and its underlying modules, -and others can still be addressed in the future during the MVS development process, which is still ongoing. -The following table (:ref:`table_limitations_label`) lists the MVS limitations based on their type. - - -.. _table_limitations_label: - -.. list-table:: Limitations - :widths: 25 25 - :header-rows: 1 - - * - Inherited - - Can be addressed - * - :ref:`limitations-real-life-constraint` - - :ref:`limitations-missing-kpi` - * - :ref:`limitations-simplified_model` - - :ref:`limitations-random-excess` - * - :ref:`limitations-degradation` - - :ref:`limitations-renewable-share-definition` - * - :ref:`limitations-perfect_foresight` - - :ref:`limitations-energy_carrier_weighting` - * - - - :ref:`limitations-energy_shortage` - * - - - :ref:`limitations-bidirectional-transformers` - -.. _limitations-real-life-constraint: - -Infeasible bi-directional flow in one timestep -############################################## - -:Limitation: - -The real life constraint of the dispatch of assets, that it is not possible to have two flows in opposite directions at the same time step, is not adhered to in the MVS. - -:Reason: - -The MVS is based on the python library `oemof-solph`. Its generic components are used to set up the energy system. As a ground rule, the components of `oemof-solph` are unidirectional. This means that for an asset that is bidirectional two transformer objects have to be used. Examples for this are: - -* Physical bi-directional assets, eg. inverters -* Logical bi-directional assets, eg. consumption from the grid and feed-in to the grid - -To achieve the real-life constraint one flow has to be zero when the other is larger zero, one would have to implement following relation: - -.. math:: - E_{in} \cdot E_{out} = 0 - -However, this relation creates a non-linear problem and can not be implemented in `oemof-solph`. - -:Implications: - -This limitation means that the MVS might result in infeasible dispatch of assets. For instance, a bus might be supplied by a rectifier and itself supplying an inverter at the same time step t, which cannot logically happen if these assets are part of one physical bi-directional inverter. Another case that could occur is feeding the grid and consuming from it at the same time t. - -Under certain conditions, including an excess generation as well as dispatch costs of zero, the infeasible dispatch can also be observed for batteries and result in a parallel charge and discharge of the battery. If this occurs, a solution may be to set a marginal dispatch cost of battery charge. - -.. _limitations-simplified_model: - -Simplified linear component models -################################## - -:Limitation: - -The MVS simplifies the component model of some assets. - - * Generators have an efficiency that is not load-dependent - * Storage have a charging efficiency that is not SOC-dependent - * Turbines are implemented without ramp rates - -:Reason: - -The MVS is based oemof-solph python library and uses its generic components to set up an energy system. Transformers and storages cannot have variable efficiencies. - -:Implications: - -Simplifying the implementation of some component specifications can be beneficial for the ease of the model, however, it contributes to the lack of realism and might result in less accurate values. The MVS accepts the decreased level of detail in return for a quick evaluation of its scenarios, which are often only used for a pre-feasibility analysis. - -.. _limitations-degradation: - -No degradation of efficiencies over a component lifetime -######################################################## - -:Limitation: - -The MVS does not degrade the efficiencies of assets over the lifetime of the project, eg. in the case of production assets like PV panels. - -:Reason: - -The simulation of the MVS is only based on a single reference year, and it is not possible to take into account multi-year degradation of asset efficiency. - -:Implications: - -This results in an overestimation of the energy generated by the asset, which implies that the calculation of some other results might also be overestimated (e.g. overestimation of feed-in energy). The user can circumvent this by applying a degradation factor manually to the generation time series used as an input for the MVS. - -.. _limitations-perfect_foresight: - -Perfect foresight -################# - -:Limitation: - -The optimal solution of the energy system is based on perfect foresight. - -:Reason: - -As the MVS and thus oemof-solph, which is handling the energy system model, know the generation and demand profiles for the whole simulation time and solve the optimization problem based on a linear equation system, the solver knows their dispatch for certain, whereas in reality the generation and demand could only be forecasted. - -:Implications: - -The perfect foresight can lead to suspicious dispatch of assets, for example charging of a battery right before a (in real-life) random blackout occurs. The systems optimized with the MVS therefore, represent their optimal potential, which in reality could not be reached. The MVS has thus a tendency to underestimate the needed battery capacity or the minimal state of charge for backup purposes, and also designs the PV system and backup power according to perfect forecasts. In reality, operational margins would need to be added. - -.. _limitations-missing-kpi: - - -Optimization precision -###################### - -:Limitation: - -Marginal capacities and flows below a threshold of 10^-6 are rounded to zero. - -:Reason: - -The MVS makes use of the open energy modelling framework (oemof) by using oemof-solph. For the MVS, we use the `cbc-solver` and at a `ratioGap=0.03`. This influences the precision of the optimized decision variables, ie. the optimized capacities as well as the dispatch of the assets. -In some cases the dispatch and capacities vary around 0 with fluctuations of the order of floating point precision (well below <10e-6), thus resulting in marginal and also marginal negative dispatch or capacities. When calculating KPI from these decision variables, the results can be nonsensical, for example leading to SoC curves with negative values or values far above the viable value 1. -As the reason for these inconsistencies is known, the MVS enforces the capacities and dispatch of to be above 10e-6, ie. all capacities or flows smaller than that are set to zero. This is applied to absolute values, so that irregular (and incorrect) values for decision variables can still be detected. - -:Implications: - -If your energy system has demand or resource profiles that include marginal values below the threshold of 10^-6, the MVS will not result in appropriate results. For example, that means that if you have an energy system with usually is measured in `MW` but one demand is in the `W` range, the dispatch of assets serving this minor demand is not displayed correctly. Please chose `kW` or even `W` as a base unit then. - -Extension of KPIs necessary -########################### - -:Limitation: - -Some important KPIs usually required by developers are currently not implemented in the MVS: - -* Internal rate of return (IRR) -* Payback period -* Return on equity (ROE), - -:Reason: - -The MVS tool is a work in progress and this can still be addressed in the future. - -:Implications: - -The absence of such indicators might affect decision-making. - -.. _limitations-random-excess: - -Random excess energy distribution -################################# - -:Limitation: - -There is random excess distribution between the feed-in sink and the excess sink when no feed-in-tariff is assumed in the system. - -:Reason: - -Since there is no feed-in-tariff to benefit from, the MVS randomly distributes the excess energy between the feed-in and excess sinks. As such, the distribution of excess energy changes when running several simulations for the same input files. - -:Implications: - -On the first glance, the distribution of excess energy onto both feed-in sink and excess sink may seem off to the end-user. Other than these inconveniences, there are no real implications that affect the capacity and dispatch optimization. When a degree of self-supply and self-consumption is defined, the limitation might tarnish these results. - -.. _limitations-renewable-share-definition: - -Renewable energy share defintion relative to energy carriers -############################################################ - -:Limitation: - -The current renewable energy share depends on the share of renewable energy production assets directly feeding the load. The equation to calculate the share also includes the energy carrier rating as described here below: - -.. math:: - RES &= \frac{\sum_i E_{RE,generation}(i) \cdot w_i}{\sum_i E_{RE,generation}(i) \cdot w_i + \sum_k E_{nonRE,generation}(k) \cdot w_k} - - \text{with~} & i \text{: renewable energy asset} - - & k \text{: non-renewable energy asset} - -:Reason: - -The MVS tool is a work in progress and this can still be addressed in the future. - -:Implications: - -This might result in different values when comparing them to other models. Another way to calculate it is by considering the share of energy consumption supplied from renewable sources. - -.. _limitations-energy_carrier_weighting: - -Energy carrier weighting -######################## - -:Limitation: - -The MVS assumes a usable potential/energy content rating for every energy carrier. The current version assumes that 1 kWh thermal is equivalent to 1 kWh electricity. - -:Reason: - -This is an approach that the MVS currently uses. - -:Implications: - -By weighing the energy carriers according to their energy content (Gasoline Gallon Equivalent (GGE)), the MVS might result in values that can't be directly assessed. Those ratings affect the calculation of the levelized cost of the energy carriers, but also the minimum renewable energy share constraint. - -.. _limitations-energy_shortage: - -Events of energy shortage or grid interruption can not be modelled -################################################################## - -:Limitation: - -The MVS assumes no shortage or grid interruption in the system. - -:Reason: - -The aim of the MVS does not cover this scenario. - -:Implications: - -Electricity shortages due to power cuts might happen in real life and the MVS currently omits this scenario. -If a system is self-sufficient but relies on grid-connected PV systems, -the latter stop feeding the load if any power cuts occur -and the battery storage systems might not be enough to serve the load (energy shortage). - -.. _limitations-bidirectional-transformers: - -Need of two transformer assets for of one technical unit -######################################################## - -:Limitation: - -Two transformer objects representing one technical unit in real life are currently unlinked in terms of capacity and attributed costs. - -:Reason: - -The MVS uses oemof-solph's generic components which are unidirectional so for a bidirectional asset, -two transformer objects have to be used. - -:Implications: - -Since one input is only allowed, such technical units are modelled as two separate transformers that are currently unlinked in the MVS -(e.g., hybrid inverter, heat pump, distribution transformer, etc.). -This raises a difficulty to define costs in the input data. -It also results in two optimized capacities for one logical unit. - -This limitation is to be addressed with a constraint which links both capacities of one logical unit, -and therefore solves both the problem to attribute costs and the previously differing capacities. - -.. _verification_of_inputs: - -Input verification ------------------- - -The inputs for a simulation with the MVS are subjected to a couple of verification tests to make sure that the inputs result in valid oemof simulations. This should ensure: - -- Uniqueness of labels (`C1.check_for_label_duplicates`): This function checks if any LABEL provided for the energy system model in dict_values is a duplicate. This is not allowed, as oemof can not build a model with identical labels. - -- No levelized costs of generation lower than feed-in tariff of same energy vector in case of investment optimization (`optimizeCap` is True) (`C1.check_feedin_tariff_vs_levelized_cost_of_generation_of_providers`): Raises error if feed-in tariff > levelized costs of generation if `maximumCap` is None for energy asset in ENERGY_PRODUCTION. This is not allowed, as oemof otherwise may be subjected to an unbound problem, ie. a business case in which an asset should be installed with infinite capacities to maximize revenue. If maximumCap is not None a logging.warning is shown as the maximum capacity of the asset will be installed. - -- No feed-in tariff higher then energy price from an energy provider (`C1.check_feedin_tariff_vs_energy_price`): Raises error if feed-in tariff > energy price of any asset in 'energyProvider.csv'. This is not allowed, as oemof otherwise is subjected to an unbound and unrealistic problem, eg. one where the owner should consume electricity to feed it directly back into the grid for its revenue. - -- Assets have well-defined energy vectors and belong to an existing bus (`C1.check_if_energy_vector_of_all_assets_is_valid`): Validates for all assets, whether 'energyVector' is defined within DEFAULT_WEIGHTS_ENERGY_CARRIERS and within the energyBusses. - -- Energy carriers used in the simulation have defined factors for the electricity equivalency weighting (`C1.check_if_energy_vector_is_defined_in_DEFAULT_WEIGHTS_ENERGY_CARRIERS`): Raises an error message if an energy vector is unknown. It then needs to be added to the DEFAULT_WEIGHTS_ENERGY_CARRIERS in constants.py - -- An energy bus is always connected to one inflow and one outflow (`C1.check_for_sufficient_assets_on_busses`): Validating model regarding busses - each bus has to have 2+ assets connected to it, exluding energy excess sinks - -- Time series of energyProduction assets that are to be optimized have specific generation profiles (`C1.check_non_dispatchable_source_time_series`, `C1.check_time_series_values_between_0_and_1`): Raises error if time series of non-dispatchable sources are not between [0, 1]. - -- Provided timeseries are checked for `NaN` values, which are replaced by zeroes (`C0.replace_nans_in_timeseries_with_0`). - -- Asset capacities connected to each bus are sized sufficiently to fulfill the maximum demand (`C1.check_energy_system_can_fulfill_max_demand`): Logs a logging.warning message if the aggregated installed capacity and maximum capacity (if applicable) of all conversion, generation and storage assets connected to one bus is smaller than the maximum demand. The check is applied to each bus of the energy system. Check passes when the potential peak supply is larger then or equal to the peak demand on the bus, or if the maximum capacity of an asset is set to None when optimizing. - -.. _validation-methodology: - -Validation Methodology ----------------------- - -As mentioned in :ref:`validation-plan`, the MVS is validated using three validation methods: conceptual model validation, model verification and operational validity. - -**Conceptual model validation** consists of looking into the underlying theories and assumptions. Therefore, the conceptual validation scheme includes a comprehensive review of the generated equations by the oemof-solph python library and the components’ models. Next step is to try and adapt them to a sector coupled example with specific constraints. Tracing and examining the flowchart is also considered as part of this validation type which can be found in :ref:`Flowchart`. The aim is to assess the reasonability of the model behavior through pre-requisite knowledge; this technique is known as face validity. - -**Model verification** is related to computer programming and looks into whether the code is a correct representation of the conceptual model. To accomplish this, static testing methods are used to validate the output with respect to an input. Unit tests and integration tests, using proof of correctness techniques, are integrated within the code and evaluate the output of the MVS for any change occuring as they are automated. Unit tests target a single unit such as an individual component, while integration tests target more general parts such as entire modules. Both tests are implemented as pytests for the MVS, which allows automatized testing. - -**Operational validity** assesses the model’s output with respect to the required accuracy. In order to achieve that, several validation techniques are used, namely: - -* **Graphical display**, which is the use of model generated or own graphs for result interpretation. Graphs are simultaneously used with other validation techniques to inspect the results; - -* **Benchmark testing**, through which scenarios are created with different constraints and component combinations, and the output is calculated and compared to the expected one to evaluate the performance of the model; - -* **Extreme scenarios** (e.g., drastic meteorological conditions, very high costs, etc.) are created to make sure the simulation runs through and check if the output behavior is still valid by the use of graphs and qualitative analysis; - -* **Comparison to other validated model**, which compares the results of a case study simulated with the model at hand to the results of a validated optimization model in order to identify the similarities and differences in results; - -* **Sensitivity analysis**, through which input-output transformations are studied to show the impact of changing the values of some input parameters. - -Unit and Integration Tests -########################## - -The goal is to have unit tests for each single function of the MVS, and integration tests for the larger modules. As previously mentioned, pytests are used for those kind of tests as they always assert that an externally determined output is archieved when applying a specific function. Unit tests and integration tests are gauged by using test coverage measurement. Examples of those tests can be found `here `__ and it is possible to distinguish them from other tests from the nomination that refers to the names of the source modules (e.g., A0, A1, B0, etc.). The MVS covers so far 80% of the modules and sub-modules as seen in the next figure. - -.. image:: images/Test_coverage.png - :width: 200 - -Since those tests are automated, this coverage is updated for any changes in the model. - -Benchmark Tests -############### - -A benchmark is a point of reference against which results are compared to assess the operational validity of a model. Benchmark tests are also automated like unit and integration tests, hence it is necessary to check that they are always passing for any implemented changes in the model. The implemented benchmark tests, which cover several features and functionalities of the MVS, are listed here below. - -* Electricity Grid + PV (`data `__/`pytest `__): Maximum use of PV to serve the demand and the rest is compensated from the grid - -* Electricity Grid + PV + Battery (`data `__/`pytest `__): Reduced excess energy compared to Grid + PV scenario to charge the battery - -* Electricity Grid + Diesel Generator (`data `__/`pytest `__): The diesel generator is only used if its LCOE is less than the grid price - -* Electricity Grid + Battery (`data `__/`pytest `__): The grid is only used to feed the load - -* Electricity Grid + Battery + Peak Demand Pricing (`data `__/`pytest `__): Battery is charged at times of peak demand and used when demand is larger - -* Electricity Grid (Price as Time Series) + Heat Pump + Heat Grid (`data `__/`pytest `__): Heat pump is used when electricity_price/COP is less than the heat grid price - -* Maximum emissions constraint: Grid + PV + Diesel Generator (data: `set 1 `__, `set 2 `__, `set 3 `__/`pytest `__): Emissions are limited by constraint, more PV is installed to reduce emissions. For RE share of 100 % in grid, more electricity from the grid is used - -* Parser converting an energy system model from EPA to MVS (`data `__/`pytest `__) - -* Stratified thermal energy storage (`data `__/`pytest `__): With fixed thermal losses absolute and relative reduced storage capacity only if these losses apply - -* Net zero energy (NZE) constraint: Grid + PV and Grid + PV + Heat Pump (data `set 1 `__, `set 2 `__, `set 3 `__, `set 4 `__/`pytest `__): Degree of NZE >= 1 when constraint is used and degree of NZE < 1 when constraint is not used. - -More tests can still be implemented with regard to: - -* The investment model within the MVS - -* Components with two input sources - -Sensitivity Analysis Tests -########################## - -For sensitivity analysis, the behaviour of the MVS is studied by testing the effect of changing the value of the feed-in tariff (FIT) for a fixed value of an asset's LCOE such that LCOE_ASSET is less than the electricity price. The implemented sensitivity analysis test is shown here below with the resulting graph. More information can be found `here `__ on pages 54-55. - -* Comparing FIT to LCOE_ASSET: Investment in maximum allowed capacity of asset for FIT values larger than LCOE_ASSET - -.. image:: images/Sensitivity_1.png - :width: 600 - -The previous graph is not generated by the MVS itself and the results are drawn and interpreted subjectively from it, which points back to the use of graphical displays validation technique with another one simultaneously. This sensitivity analysis test can be translated into a benchmark test so that it becomes automatized. The idea is to check that for every value of FIT greater than LCOE_ASSET, the MVS is investing in the entire allowed maximum capacity of the asset. - -More input-output transformations for sensitivity analyses can be investigated such as: - -* Checking the randomness of supply between the electricity grid and a diesel generator when fuel_price/generator_efficiency is equal to electricity_price/transformer_efficiency - -* Checking if a diesel generator actually replaces the consumption from the grid at times of peak demand--i.e., dispatch_price is less or equal to peak_demand_charge - -Comparison to Other Models -########################## - -So far, the MVS' results for a sector coupled system (electricity + hydrogen) are compared to those of HOMER for the same exact system. This comparison is important to highlight the similarities and differences between the two optimization models. On the electricity side, most of the values are comparable and in the same range. The differences mainly show on the hydrogen part in terms of investment in an electrolyzer capacity (component linking the two sectors) and the values related to that. On another note, both models have different approaches for calculating the value of the levelized cost of a certain energy carrier and therefore the values are apart. Details regarding the comparison drawn between the two models can be found `here `__ on pages 55-63. - -This validation method is commonly used. However, one model cannot absolutely validate another model or claim that one is better than the other. This is why the focus should be on testing the correctness, appropriateness and accuracy of a model vis-à-vis its purpose. Since the MVS is an open source tool, it is important to use a validated model for comparison, but also similar open source tools like urbs and Calliope for instance. The following two articles list some of the models that could be used for comparison to the MVS: `A review of modelling tools for energy and electricity systems with large shares of variable renewables `__ and `Power-to-heat for renewable energy integration: A review of technologies, modeling approaches, and flexibility potentials `__. - - -.. _verification-tests: - -Automatic output verification -############################# - -There is a suite of functions within the MVS codebase module E4_verification.py that run a few checks on some of the outputs of the simulation in order to make sure that the results are meaningful and if something like an excessive excess energy flow is noteworthy. These are valuable tests that act as a safeguard for the user, as the model is not only validated for benchmark tests but for every run simulation. -The following is the list of functions in E4_verification.py that carry out the verification tests: - -* detect_excessive_excess_generation_in_bus -* maximum_emissions_test -* minimal_renewable_share_test -* verify_state_of_charge - -The first test serves as an alert to the energy system modeler to check their inputs again, whereas if there are any errors raised within the other functions, it is an indication of something seriously wrong. - -detect_excessive_excess_generation_in_bus -========================================= - -This test is here to notify to the modeler in case there is an excess generation within a bus in the energy system. Precisely, the modeler is given a heads-up when the ratio of total outflows to total inflows for one or more buses is less than 0.9 - -maximum_emissions_test -====================== - -Other than renewables, source components in the energy system have a certain emissions value associated with the generation of energy. The user is able to apply a constraint on the maximum allowed emissions in the energy mix of the output energy system. This function runs a verification test on the output energy system data to determine if the user-supplied constraint on maximum emissions is correctly applied or not. If not, then the modeler is notified. - -minimal_renewable_share_test -============================ - -This test is carried out on the energy system model after optimization of its capacities. It verifies whether the user-provided constraint for the minimal share of renewables in the energy mix of the optimized system was respected or not. In case this lower bound constraint is not met, the user is notified. - -verify_state_of_charge -====================== - -This test is intended to check the time-series of the state of charge values for storages in the energy system simulation results to notify of a serious error in case, the SoC value at any time-step is not between 0 and 1, which is physically not feasible. diff --git a/docs/Model_Equations.rst b/docs/Model_Equations.rst deleted file mode 100644 index 3559db72e..000000000 --- a/docs/Model_Equations.rst +++ /dev/null @@ -1,327 +0,0 @@ -====================== -Set of Model Equations -====================== - -The MVS is based on the programming framework `oemof-solph` and builds an energy system model based up on its nomenclature. -As such, the energy system model can be described with a linear equation system. -Below, the most important aspects are described in a genrealized way, as well as explained based on an example. -This will ease the comparision to other energy system models. - -.. _economic_precalculation-label: - -Economic Dispatch ------------------ - -Linear programming is a mathematical modelling and optimization technique for a system of a linear objective function subject to linear constraints. -The goal of a linear programming problem is to find the optimal value for the objective function, be it a maximum or a minimum. -The MVS is based on `oemof-solph`, which in turn uses `Pyomo` to create a linear problem. -The economic dispatch problem in the MVS has the objective of minimizing the production cost by allocating the total demand among the generating units at each time step. -The equation is the following: - -.. math:: - min Z = \sum_i a_i \cdot CAP_i + \sum_i \sum_t c_{var,i} \cdot E_i(t) - -.. math:: - CAP_i &\geq 0 - - E_i(t) &\geq 0 \qquad \forall t - - i &\text{: asset} - - a_i &\text{: asset annuity [currency/kWp/year, currency/kW/year, currency/kWh/year]} - - CAP_i &\text{: asset capacity [kWp, kW, kWh]} - - c_{var,i} &\text{: variable operational or dispatch cost [currency/kWh, currency/L]} - - E_i(t) &\text{: asset dispatch [kWh]} - -The annual cost function of each asset includes the capital expenditure (investment cost) and residual value, as well as the operating expenses of each asset. -It is expressed as follows: - -.. math:: - a_i &= \left( capex_i + \sum_{k=1}^{n} \frac{capex_i}{(1+d)^{k \cdot t_a}} - c_{res,i} \right) \cdot CRF(T) + opex_i - - CRF(T) &= \frac{d \cdot (1+d)^T}{(1+d)^t - 1} - -.. math:: - capex_i &\text{: specific investment costs [currency/unit]} - - n &\text{: number of replacements of an asset within project lifetime T} - - t_a &\text{: asset lifetime [years]} - - CRF &\text{: capital recovery factor} - - c_{res,i} &\text{: residual value of asset i at the end of project lifetime T [currency/unit]} - - opex_i &\text{: annual operational and management costs [currency/unit/year]} - - d &\text{: discount factor} - - T &\text{: project lifetime [years]} - -The CRF is a ratio used to calculate the present value of the the annuity. -The discount factor can be replaced by the weighted average cost of capital (WACC), calculated by the user. - -The lifetime of the asset :math:`t_a` and the lifetime of the project :math:`T` can be different from each other; -hence, the number of replacements n is estimated using the equation below: - -.. math:: - n = round \left( \frac{T}{t_a} + 0.5 \right) - 1 - -The residual value is also known as salvage value and it represents an estimate of the monetary value of an asset at the end of the project lifetime T. -The MVS considers a linear depreciation over T and accounts for the time value of money by using the following equation: - -.. math:: - c_{res,i} = \frac{capex_i}{(1+d)^{n \cdot t_a}} \cdot \frac{1}{T} \cdot \frac{(n+1) \cdot t_a - T}{(1+d)^T} - -Energy Balance Equation ------------------------ - -One main constraint that the optimization model is subject to is the energy balance equation. -The latter maintains equality between the incoming energy into a bus and the outgoing energy from that bus. -This balancing equation is applicable to all bus types, be it electrical, thermal, hydrogen or for any other energy carrier. - -.. math:: - \sum E_{in,i}(t) - \sum E_{out,j}(t) = 0 \qquad \forall t - -.. math:: - E_{in,i} &\text{: energy flowing from asset i to the bus} - - E_{out,j} &\text{: energy flowing from the bus to asset j} - -It is very important to note that assets i and j can be the same asset (e.g., battery). -`oemof-solph` allows both :math:`E_{in}` or :math:`E_{out}` to be larger zero in same time step t (see :ref:`limitations-real-life-constraint`). - - -Example: Sector Coupled Energy System -------------------------------------- - -In order to understand the component models, a generic sector coupled example is shown in the next figure. -It brings together the electricity and heat sector through Transformer 4 as it connects the two sector buses. - -.. image:: images/26-10-2020_sector_coupled_example.png - :width: 600 - -For the sake of simplicity, the following table gives an example for each asset type with an abbreviation to be used in the energy balance and component equations. - - .. list-table:: Asset Types and Examples - :widths: 50 25 25 25 - :header-rows: 1 - - * - Asset Type - - Asset Example - - Abbreviation - - Unit - * - Non-dispatchable source 1 - - Wind turbine - - wind - - kW - * - Non-dispatchable source 2 - - Photovoltaic panels - - pv - - kWp - * - Storage 1 - - Battery energy storage - - bat - - kWh - * - Transformer 1 - - Rectifier - - rec - - kW - * - Transformer 2 - - Solar inverter - - inv - - kW - * - Non-dispatchable source 3 - - Solar thermal collector - - stc - - kWth - * - Storage 2 - - Thermal energy storage - - tes - - kWth - * - Dispatchable source - - Heat source (e.g., biogas) - - heat - - L - * - Transformer 3 - - Turbine - - turb - - kWth - * - Transformer 4 - - Heat pump - - hp - - kWth - -All grids and dispatchable sources are assumed to be available 100% of the time with no consumption limits. -The MVS includes a sink component for excess energy, connected to each bus in the system and denoted by :math:`E_{ex}` in the equations. -This excess sink accounts for the extra energy in the system that has to be dumped. - -Electricity Grid Equation -######################### - -The electricity grid is modeled though a feed-in and a consumption node. -Transformers limit the peak flow into or from the local electricity line. -Electricity sold to the grid experiences losses in the transformer :math:`(ts,f)`. - -.. math:: - E_{grid,c}(t) - E_{grid,f}(t) + E_{ts,f}(t) \cdot \eta_{ts,f} - E_{ts,c}(t) = 0 \qquad \forall t - -.. math:: - E_{grid,c} &\text{: energy consumed from the electricity grid} - - E_{grid,f} &\text{: energy fed into the electricity grid} - - E_{grid,c} &\text{: transformer station feed-in} - - \eta_{ts,f} &\text{: transformer station efficiency} - - E_{grid,c} &\text{: transformer station consumption} - -Non-Dispatchable Source Equations -################################# - -Non-dispatchable sources in our example are wind, pv and solar thermal plant. -Their generation is determined by the provided timeseries of instantaneous generation, providing :math:`\alpha`, :math:`\beta`, :math:`\gamma` respectively. - -.. math:: - E_{wind}(t) &= CAP_{wind} \cdot \alpha_{wind}(t) \qquad \forall t - - E_{pv}(t) &= CAP_{pv} \cdot \beta_{pv}(t) \qquad \forall t - - E_{stc}(t) &= CAP_{stc} \cdot \gamma_{stc}(t) \qquad \forall t - -.. math:: - E_{wind} &\text{: energy generated from the wind turbine} - - CAP_{wind} &\text{: wind turbine capacity [kW]} - - \alpha_{wind} &\text{: instantaneous wind turbine performance metric [kWh/kW]} - - E_{pv} &\text{: energy generated from the PV panels} - - CAP_{pv} &\text{: PV panel capacity [kWp]} - - \beta_{pv} &\text{: instantaneous PV specific yield [kWh/kWp]} - - E_{stc} &\text{: energy generated from the solar thermal collector} - - CAP_{stc} &\text{: Solar thermal collector capacity [kWth]} - - \gamma_{stc} &\text{: instantaneous collector's production [kWh/kWth]} - -Storage Model -############# - -There are two storages in our system: An electrical energy storage (Storage 1, :math:`bat`) and a thermal energy storage (Storage 2, :math:`tes`). -Below, the equations for the Storage 1 are provided, but Storage 2 follows analogous equations for charge, discharge and bounds. - -.. math:: - E_{bat}(t) = E_{bat}(t - 1) + E_{bat,in}(t) \cdot \eta_{bat,in} - \frac{E_{bat,out}}{\eta_{bat,out}} - E_{bat}(t - 1) \cdot \epsilon \qquad \forall t - -.. math:: - CAP_{bat} \cdot SOC_{min} \leq E_{bat}(t) \leq CAP_{bat} \cdot SOC_{max} \qquad \forall t - - 0 \leq E_{bat}(t) - E_{bat}(t - 1) \leq CAP_{bat} \cdot C_{rate,in} \qquad \forall t - - 0 \leq E_{bat}(t - 1) - E_{bat}(t) \leq CAP_{bat} \cdot C_{rate,out} \qquad \forall t - -.. math:: - E_{bat} &\text{: energy stored in the battery at time t} - - E_{bat,in} &\text{: battery charging energy} - - \eta_{bat,in} &\text{: battery charging efficiency} - - E_{bat,out} &\text{: battery discharging energy} - - \eta_{bat,out} &\text{: battery discharging efficiency} - - \epsilon &\text{: decay per time step} - - CAP_{bat} &\text{: battery capacity [kWh]} - - SOC_{min} &\text{: minimum state of charge} - - SOC_{max} &\text{: maximum state of charge} - - C_{rate,in} &\text{: battery charging rate} - - C_{rate,in} &\text{: battery discharging rate} - -DC Electricity Bus Equation -########################### - -This is an example of a DC bus with a battery, PV and a bi-directional inverter. - -.. math:: - E_{pv}(t) + E_{bat,out}(t) \cdot \eta_{bat,out} + E_{rec}(t) \cdot \eta_{rec} - E_{inv}(t) - E_{bat,in} - E_{ex}(t) = 0 \qquad \forall t - -.. math:: - E_{rec} &\text{: rectifier energy} - - \eta_{rec} &\text{: rectifier efficiency} - - E_{inv} &\text{: inverter energy} - -AC Electricity Bus Equation -########################### - -This describes the local electricity grid and all connected assets: - -.. math:: - E_{ts,c}(t) \cdot \eta_{ts,c} + E_{wind}(t) + E_{inv}(t) \cdot \eta_{inv} - E_{ts,c}(t) - E_{rec}(t) - E_{hp}(t) - E_{el}(t) - E_{ex}(t) = 0 \qquad \forall t - -.. math:: - \eta_{ts,c} &\text{: transformer station efficiency} - - \eta_{inv} &\text{: inverter efficiency} - - E_{hp} &\text{: heat pump electrical consumption} - - E_{el} &\text{: electrical load} - -Heat Bus Equation -################# - -This describes the heat bus and all connected assets: - -.. math:: - E_{tes}(t) \cdot \eta_{tes} + E_{turb}(t) \cdot \eta_{turb} + E_{hp}(t) \cdot COP - E_{th}(t) - E_{ex}(t) = 0 - -.. math:: - \eta_{tes} &\text{: thermal storage efficiency} - - \eta_{turb} &\text{: turbine efficiency} - - COP &\text{: heat pump coefficient of performance} - - E_{th} &\text{: heat load} - -NDS3 Bus Equation -################# - -The NDS3 Bus is an example of a bus, which does not serve both as in- and output of a storage system. -Instead, the thermal storage is charged from the NDS3 bus, but discharges into the heat bus. - -.. math:: - E_{stc}(t) - E_{tes}(t) - E_{ex}(t) = 0 - -.. math:: - E_{tes} \text{: thermal energy storage} - -DS Bus Equation -############### - -The DS Bus shows an example of a fuel source providing an energy carrier (biogas) to a transformer (turbine). - -.. math:: - E_{heat}(t) - E_{turb}(t) - E_{ex}(t) = 0 - -.. math:: - E_{heat} &\text{: thermal energy (biogas) production} - - E_{turb} &\text{: turbine (biogas turbine) energy} - diff --git a/docs/Overview.rst b/docs/Overview.rst index fd871f1ce..bf2a71468 100644 --- a/docs/Overview.rst +++ b/docs/Overview.rst @@ -5,33 +5,12 @@ About the Project H2020 Project E-Land -------------------- -License -------- -The MVS is licensed with the **GNU General Public License v2.0**. The GNU GPL is the most widely used free software license and has a strong copyleft requirement. When distributing derived works, the source code of the work must be made available under the same license. There are multiple variants of the GNU GPL, each with different requirements. -.. _Flowchart: Flowchart --------- -The MVS' global flowchart, or graphical model, is divided into three connected blocks that trace the logic sequence: inputs, system model, and outputs. This is a typical representation of a simulation model. - -.. image:: images/MVS_flowchart.png - :width: 600 - -The user is asked to enter the required data through a web interface. In developer mode, the data is submitted as a number of csv files. This input data is split into four categories: - -1. Project description, which entails the general information regarding the project (country, coordinates, etc.), as well as the economic data such as the discount factor, project duration, or tax; - -2. Energy consumption, which is expressed as times series based on the type of energy (in this case: electrical and therma); - -3. System configuration, in which the user specifies the technical and financial data of each asset; and - -4. Meteorological data, which is related to the components that generate electricity by harnessing an existing source of energy that is weather- and time-dependent (e.g., solar and wind power). - -This set of input data is then translated to a linear programming problem, also known as a constrained optimization problem. The MVS is based on the oemof-solph python library that describes the problem by specifying the objective function, the decision variables and the bounds and constraints. The goal is to (1) minimize the production costs by determining the generating units' optimal output, which meets the total demand, and (2) optimize near-future investments in generation and storage assets with the least possible cost of energy. -The simulation outputs are also separated into categories: the economic results used for the financial evaluation, such as the levelized cost of electricity or heat or the net present value of the projected investments, the technical results that include the optimized capacities and dispatch of each asset for instance, and the system’s environmental contribution in terms of CO2 emissions. All these results are valuable for the decision making. .. _validation-plan: diff --git a/docs/References.rst b/docs/References.rst deleted file mode 100644 index d8e595ace..000000000 --- a/docs/References.rst +++ /dev/null @@ -1,9 +0,0 @@ -===================== -References of the MVS -===================== - -The MVS is currently under development in the H2020 research project `E-Land`. Still, there are already some references where additional information can be found regarding its intention, application, and method. - -* Research project website: `E-LAND Horizon 2020. Novel solutions for decarbonized energy islands `__ - -* Martha M. Hoffmann, Sanket Puranik, Marc Juanpera, José M Martín-Rapún, Heidi Tuiskula, Philipp Blechinger. *Investment planning in multi-vector energy systems: Definition of key performance indicators*, conference paper, poster to be presented at the virtual `*CIRED Berlin 2020 Workshop* `__, 22 - 23 September. \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 0653882fe..32d48d6d1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -154,9 +154,6 @@ def generate_parameter_table(input_csv_file, output_csv_file): ":Type:", ":Unit:", ":Default:", - ":Example:", - ":Definition:", - ":Restrictions:", ] name_mapping = {c: c.replace(":", "") for c in parameter_properties} @@ -170,13 +167,25 @@ def generate_parameter_table(input_csv_file, output_csv_file): ) -generate_parameter_description("MVS_parameters_list.csv", "MVS_parameters_list.inc") -generate_parameter_table("MVS_parameters_list.csv", "MVS_parameters_list.tbl") +def copy_readme(): + with open("../README.rst", "r", encoding="utf8") as fp: + data = fp.readlines() + with open("readme.inc", "w") as fp: + fp.writelines(data[data.index("Setup\n") :]) + + +generate_parameter_description( + "MVS_parameters_list.csv", "model/parameters/MVS_parameters_list.inc" +) +generate_parameter_table( + "MVS_parameters_list.csv", "model/parameters/MVS_parameters_list.tbl" +) generate_parameter_categories( "MVS_parameters_list.csv", "MVS_parameters_categories.csv", - "MVS_parameters_categories.inc", + "model/parameters/MVS_parameters_categories.inc", ) +copy_readme() # -- Project information ----------------------------------------------------- @@ -201,6 +210,7 @@ def generate_parameter_table(input_csv_file, output_csv_file): "sphinx.ext.napoleon", "sphinx.ext.imgmath", "sphinx.ext.autosummary", + "sphinx.ext.imgconverter", "numpydoc", ] diff --git a/docs/examples/multiple_busses.rst b/docs/examples/multiple_busses.rst new file mode 100644 index 000000000..2a65554dd --- /dev/null +++ b/docs/examples/multiple_busses.rst @@ -0,0 +1,39 @@ +.. _multiple_busses_example: + +Using multiple in- or output busses +################################### + +Sometimes, you may also want to have multiple input- our output busses connected to a component. +This is for example the case if you want to implement an electrolyzer with a transformer, +and want to track water consumption at the same time as you want to track electricity consumption. + +You can define this, again, in the csv´s. +Here, you would insert a list of your parameters instead of the scalar value of a parameter: + + [0.99, 0.98] + +Would be an example of a transformer with two efficiencies. + +You can also wrap multiple inputs/outputs with scalars that are defined as efficiencies. +For that, you define one or multiple of the parameters within the list with the above introduced dictionary: + + [0.99, {'value': {'file_name': 'your_file_name.csv', 'header': 'your_header'}, 'unit': 'your_unit'}] + +If you define an output- or input flow with with a list, +you also have to define related parameters as a list. +So, for example, if you define the input direction as a list for an energyConsumption asset, +you need to define the efficiencies and dispatch_price costs as a list as well. + +You can see an implemented example here, where the heat pump has a time-dependent efficiency: + +.. csv-table:: Example for defining a component with multiple inputs/outputs + :file: ../files_to_be_displayed/example_multiple_inputs_energyConversion.csv + :widths: 70, 30, 50 + :header-rows: 1 + +The features were integrated with `Pull Request #63 `__. +For more information, you might also reference following issues: + +- Parameters can now be a list of values, eg. efficiencies for two busses or multiple input/output vectors(`Issue #52 `__) + +- Parameters can now be defined as a list as well as as a timeseries (`Issue #52 `__, `Issue #82 `__) diff --git a/docs/examples/time_series_params.rst b/docs/examples/time_series_params.rst new file mode 100644 index 000000000..63e008eb4 --- /dev/null +++ b/docs/examples/time_series_params.rst @@ -0,0 +1,39 @@ +.. _time_series_params_example: + +Adding a timeseries for a parameter +################################### + +Sometimes you may want to define a parameter not as a scalar value but as a time series. +This can for example happen for efficiencies (heat pump COP during the seasons), +energy prices (currently only hourly resolution), or the state of charge +(for example if you want to achieve a certain stage of charge of an FCEV at a certain point of time). + +You can define a scalar as a time series in the csv input files (not applicable for `energyConsumption.csv`), +by replacing the scalar value with following dictionary: + + {'file_name': 'your_file_name.csv', 'header': 'your_header', 'unit': 'your_unit'} + +The feature was tested for following parameters: + +- energy_price + +- feedin_tariff + +- dispatch_price + +- efficiency + +You can see an implemented example here, where the heat pump has a time-dependent efficiency: + +.. csv-table:: Example for defining a scalar parameter as a time series + :file: ../files_to_be_displayed/example_scalar_as_timeseries_energyConversion.csv + :widths: 70, 30, 50 + :header-rows: 1 + +The feature is tested with benchmark test `test_benchmark_feature_parameters_as_timeseries()`. + +Example input files, where at least one parameter is defined as a time series, can be found here: + +* `First example `__: Defines the `energy_price` (`file `__) of an energy provider as a time series + +* `Second example `__: Defines the `energy_price` (`file `__) of an energy provider and the efficiency of a diesel generator (`file `__) as a time series. diff --git a/docs/index.rst b/docs/index.rst index 578e22179..602fb61e8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,26 +1,104 @@ -.. Multi-Vector Simulator (MVS) documentation master file, created by - sphinx-quickstart on Wed Dec 11 11:34:59 2019. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. +.. + SPDX-FileCopyrightText: MVS Authors -======================================================== -Welcome to Multi-Vector Simulator (MVS)'s documentation! -======================================================== + SPDX-License-Identifier: CC-BY-4.0 +.. _Flowchart: + +Multi-vector simulator +====================== +|badge_docs| |badge_CI| |badge_coverage| |badge_zenodo| + +The MVS' global flowchart, or graphical model, is divided into three connected blocks that trace the logic sequence: inputs, system model, and outputs. This is a typical representation of a simulation model. + +.. image:: images/MVS_flowchart.png + :width: 600 + +The user is asked to enter the required data through a web interface. In developer mode, the data is submitted as a number of csv files. This input data is split into four categories: + +1. Project description, which entails the general information regarding the project (country, coordinates, etc.), as well as the economic data such as the discount factor, project duration, or tax; + +2. Energy consumption, which is expressed as times series based on the type of energy (in this case: electrical and therma); + +3. System configuration, in which the user specifies the technical and financial data of each asset; and + +4. Meteorological data, which is related to the components that generate electricity by harnessing an existing source of energy that is weather- and time-dependent (e.g., solar and wind power). + +This set of input data is then translated to a linear programming problem, also known as a constrained optimization problem. The MVS is based on the oemof-solph python library that describes the problem by specifying the objective function, the decision variables and the bounds and constraints. The goal is to (1) minimize the production costs by determining the generating units' optimal output, which meets the total demand, and (2) optimize near-future investments in generation and storage assets with the least possible cost of energy. +The simulation outputs are also separated into categories: the economic results used for the financial evaluation, such as the levelized cost of electricity or heat or the net present value of the projected investments, the technical results that include the optimized capacities and dispatch of each asset for instance, and the system’s environmental contribution in terms of CO2 emissions. All these results are valuable for the decision making. + + +Maintainers +=========== + +Say who develop and maintains this + +Say a word about funding + +Origin +====== + +What started MVS + +Getting Started +=============== + +Follow the :ref:`Quick start guide ` + +.. Documentation +.. ============= .. toctree:: - Overview + :hidden: + :maxdepth: 1 + :caption: Getting Started + Installation simulating_with_the_mvs - Model_Assumptions - Model_Equations - MVS_parameters - MVS_Outputs - E-Land_Requirements - Code - References - Developing - troubleshooting + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Examples + + examples/time_series_params + examples/multiple_busses + + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Model Reference + + model/assumptions + model/components + model/constraints + model/limitations + model/input_parameters + model/simulation_outputs + model/validation + model/eland_requirements + +.. + release_notes (for website, remove for report, not implemented yet, nice to have) + contributing (here paste content of contributing.md --> convert to RST and include it as we did for readme, the mention to contributing in getting started will link to this chapter) + + +.. toctree:: + :hidden: + :maxdepth: 1 + :caption: References + + references/code + references/release_notes + references/license + references/contributing + references/publications + references/citations + references/troubleshooting + references/bug_report + + ================== Indices and tables @@ -29,3 +107,23 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` + + + +.. |badge_docs| image:: https://readthedocs.org/projects/multi-vector-simulator/badge/?version=latest + :target: https://multi-vector-simulator.readthedocs.io/en/latest/?badge=latest + :alt: Documentation Status + +.. |badge_CI| image:: https://github.com/rl-institut/multi-vector-simulator/workflows/CI/badge.svg + :alt: Build status + +.. |badge_coverage| image:: https://coveralls.io/repos/github/rl-institut/multi-vector-simulator/badge.svg + :target: https://coveralls.io/github/rl-institut/multi-vector-simulator + :alt: Test coverage + +.. |badge_zenodo| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.4610237.svg + :target: https://doi.org/10.5281/zenodo.4610237 + :alt: Zenodo DOI + + + diff --git a/docs/model/assumptions.rst b/docs/model/assumptions.rst new file mode 100644 index 000000000..b545dc41c --- /dev/null +++ b/docs/model/assumptions.rst @@ -0,0 +1,613 @@ +=========== +Assumptions +=========== + +The MVS is based on the programming framework `oemof-solph` and builds an energy system model based up on its nomenclature. +As such, the energy system model can be described with a linear equation system. +Below, the most important aspects are described in a genrealized way, as well as explained based on an example. +This will ease the comparision to other energy system models. + +.. _economic_precalculation-label: + +Economic Dispatch +----------------- + +Linear programming is a mathematical modelling and optimization technique for a system of a linear objective function subject to linear constraints. +The goal of a linear programming problem is to find the optimal value for the objective function, be it a maximum or a minimum. +The MVS is based on `oemof-solph`, which in turn uses `Pyomo` to create a linear problem. +The economic dispatch problem in the MVS has the objective of minimizing the production cost by allocating the total demand among the generating units at each time step. +The equation is the following: + +.. math:: + min Z = \sum_i a_i \cdot CAP_i + \sum_i \sum_t c_{var,i} \cdot E_i(t) + +.. math:: + CAP_i &\geq 0 + + E_i(t) &\geq 0 \qquad \forall t + + i &\text{: asset} + + a_i &\text{: asset annuity [currency/kWp/year, currency/kW/year, currency/kWh/year]} + + CAP_i &\text{: asset capacity [kWp, kW, kWh]} + + c_{var,i} &\text{: variable operational or dispatch cost [currency/kWh, currency/L]} + + E_i(t) &\text{: asset dispatch [kWh]} + +The annual cost function of each asset includes the capital expenditure (investment cost) and residual value, as well as the operating expenses of each asset. +It is expressed as follows: + +.. math:: + a_i &= \left( capex_i + \sum_{k=1}^{n} \frac{capex_i}{(1+d)^{k \cdot t_a}} - c_{res,i} \right) \cdot CRF(T) + opex_i + + CRF(T) &= \frac{d \cdot (1+d)^T}{(1+d)^t - 1} + +.. math:: + capex_i &\text{: specific investment costs [currency/unit]} + + n &\text{: number of replacements of an asset within project lifetime T} + + t_a &\text{: asset lifetime [years]} + + CRF &\text{: capital recovery factor} + + c_{res,i} &\text{: residual value of asset i at the end of project lifetime T [currency/unit]} + + opex_i &\text{: annual operational and management costs [currency/unit/year]} + + d &\text{: discount factor} + + T &\text{: project lifetime [years]} + +The CRF is a ratio used to calculate the present value of the the annuity. +The discount factor can be replaced by the weighted average cost of capital (WACC), calculated by the user. + +The lifetime of the asset :math:`t_a` and the lifetime of the project :math:`T` can be different from each other; +hence, the number of replacements n is estimated using the equation below: + +.. math:: + n = round \left( \frac{T}{t_a} + 0.5 \right) - 1 + +The residual value is also known as salvage value and it represents an estimate of the monetary value of an asset at the end of the project lifetime T. +The MVS considers a linear depreciation over T and accounts for the time value of money by using the following equation: + +.. math:: + c_{res,i} = \frac{capex_i}{(1+d)^{n \cdot t_a}} \cdot \frac{1}{T} \cdot \frac{(n+1) \cdot t_a - T}{(1+d)^T} + +Energy Balance Equation +----------------------- + +One main constraint that the optimization model is subject to is the energy balance equation. +The latter maintains equality between the incoming energy into a bus and the outgoing energy from that bus. +This balancing equation is applicable to all bus types, be it electrical, thermal, hydrogen or for any other energy carrier. + +.. math:: + \sum E_{in,i}(t) - \sum E_{out,j}(t) = 0 \qquad \forall t + +.. math:: + E_{in,i} &\text{: energy flowing from asset i to the bus} + + E_{out,j} &\text{: energy flowing from the bus to asset j} + +It is very important to note that assets i and j can be the same asset (e.g., battery). +`oemof-solph` allows both :math:`E_{in}` or :math:`E_{out}` to be larger zero in same time step t (see :ref:`limitations-real-life-constraint`). + + +Example: Sector Coupled Energy System +------------------------------------- + +In order to understand the component models, a generic sector coupled example is shown in the next figure. +It brings together the electricity and heat sector through Transformer 4 as it connects the two sector buses. + +.. image:: ../images/26-10-2020_sector_coupled_example.png + :width: 600 + +For the sake of simplicity, the following table gives an example for each asset type with an abbreviation to be used in the energy balance and component equations. + + .. list-table:: Asset Types and Examples + :widths: 50 25 25 25 + :header-rows: 1 + + * - Asset Type + - Asset Example + - Abbreviation + - Unit + * - Non-dispatchable source 1 + - Wind turbine + - wind + - kW + * - Non-dispatchable source 2 + - Photovoltaic panels + - pv + - kWp + * - Storage 1 + - Battery energy storage + - bat + - kWh + * - Transformer 1 + - Rectifier + - rec + - kW + * - Transformer 2 + - Solar inverter + - inv + - kW + * - Non-dispatchable source 3 + - Solar thermal collector + - stc + - kWth + * - Storage 2 + - Thermal energy storage + - tes + - kWth + * - Dispatchable source + - Heat source (e.g., biogas) + - heat + - L + * - Transformer 3 + - Turbine + - turb + - kWth + * - Transformer 4 + - Heat pump + - hp + - kWth + +All grids and dispatchable sources are assumed to be available 100% of the time with no consumption limits. +The MVS includes a sink component for excess energy, connected to each bus in the system and denoted by :math:`E_{ex}` in the equations. +This excess sink accounts for the extra energy in the system that has to be dumped. + +Electricity Grid Equation +######################### + +The electricity grid is modeled though a feed-in and a consumption node. +Transformers limit the peak flow into or from the local electricity line. +Electricity sold to the grid experiences losses in the transformer :math:`(ts,f)`. + +.. math:: + E_{grid,c}(t) - E_{grid,f}(t) + E_{ts,f}(t) \cdot \eta_{ts,f} - E_{ts,c}(t) = 0 \qquad \forall t + +.. math:: + E_{grid,c} &\text{: energy consumed from the electricity grid} + + E_{grid,f} &\text{: energy fed into the electricity grid} + + E_{grid,c} &\text{: transformer station feed-in} + + \eta_{ts,f} &\text{: transformer station efficiency} + + E_{grid,c} &\text{: transformer station consumption} + +Non-Dispatchable Source Equations +################################# + +Non-dispatchable sources in our example are wind, pv and solar thermal plant. +Their generation is determined by the provided timeseries of instantaneous generation, providing :math:`\alpha`, :math:`\beta`, :math:`\gamma` respectively. + +.. math:: + E_{wind}(t) &= CAP_{wind} \cdot \alpha_{wind}(t) \qquad \forall t + + E_{pv}(t) &= CAP_{pv} \cdot \beta_{pv}(t) \qquad \forall t + + E_{stc}(t) &= CAP_{stc} \cdot \gamma_{stc}(t) \qquad \forall t + +.. math:: + E_{wind} &\text{: energy generated from the wind turbine} + + CAP_{wind} &\text{: wind turbine capacity [kW]} + + \alpha_{wind} &\text{: instantaneous wind turbine performance metric [kWh/kW]} + + E_{pv} &\text{: energy generated from the PV panels} + + CAP_{pv} &\text{: PV panel capacity [kWp]} + + \beta_{pv} &\text{: instantaneous PV specific yield [kWh/kWp]} + + E_{stc} &\text{: energy generated from the solar thermal collector} + + CAP_{stc} &\text{: Solar thermal collector capacity [kWth]} + + \gamma_{stc} &\text{: instantaneous collector's production [kWh/kWth]} + +Storage Model +############# + +There are two storages in our system: An electrical energy storage (Storage 1, :math:`bat`) and a thermal energy storage (Storage 2, :math:`tes`). +Below, the equations for the Storage 1 are provided, but Storage 2 follows analogous equations for charge, discharge and bounds. + +.. math:: + E_{bat}(t) = E_{bat}(t - 1) + E_{bat,in}(t) \cdot \eta_{bat,in} - \frac{E_{bat,out}}{\eta_{bat,out}} - E_{bat}(t - 1) \cdot \epsilon \qquad \forall t + +.. math:: + CAP_{bat} \cdot SOC_{min} \leq E_{bat}(t) \leq CAP_{bat} \cdot SOC_{max} \qquad \forall t + + 0 \leq E_{bat}(t) - E_{bat}(t - 1) \leq CAP_{bat} \cdot C_{rate,in} \qquad \forall t + + 0 \leq E_{bat}(t - 1) - E_{bat}(t) \leq CAP_{bat} \cdot C_{rate,out} \qquad \forall t + +.. math:: + E_{bat} &\text{: energy stored in the battery at time t} + + E_{bat,in} &\text{: battery charging energy} + + \eta_{bat,in} &\text{: battery charging efficiency} + + E_{bat,out} &\text{: battery discharging energy} + + \eta_{bat,out} &\text{: battery discharging efficiency} + + \epsilon &\text{: decay per time step} + + CAP_{bat} &\text{: battery capacity [kWh]} + + SOC_{min} &\text{: minimum state of charge} + + SOC_{max} &\text{: maximum state of charge} + + C_{rate,in} &\text{: battery charging rate} + + C_{rate,in} &\text{: battery discharging rate} + +DC Electricity Bus Equation +########################### + +This is an example of a DC bus with a battery, PV and a bi-directional inverter. + +.. math:: + E_{pv}(t) + E_{bat,out}(t) \cdot \eta_{bat,out} + E_{rec}(t) \cdot \eta_{rec} - E_{inv}(t) - E_{bat,in} - E_{ex}(t) = 0 \qquad \forall t + +.. math:: + E_{rec} &\text{: rectifier energy} + + \eta_{rec} &\text{: rectifier efficiency} + + E_{inv} &\text{: inverter energy} + +AC Electricity Bus Equation +########################### + +This describes the local electricity grid and all connected assets: + +.. math:: + E_{ts,c}(t) \cdot \eta_{ts,c} + E_{wind}(t) + E_{inv}(t) \cdot \eta_{inv} - E_{ts,c}(t) - E_{rec}(t) - E_{hp}(t) - E_{el}(t) - E_{ex}(t) = 0 \qquad \forall t + +.. math:: + \eta_{ts,c} &\text{: transformer station efficiency} + + \eta_{inv} &\text{: inverter efficiency} + + E_{hp} &\text{: heat pump electrical consumption} + + E_{el} &\text{: electrical load} + +Heat Bus Equation +################# + +This describes the heat bus and all connected assets: + +.. math:: + E_{tes}(t) \cdot \eta_{tes} + E_{turb}(t) \cdot \eta_{turb} + E_{hp}(t) \cdot COP - E_{th}(t) - E_{ex}(t) = 0 + +.. math:: + \eta_{tes} &\text{: thermal storage efficiency} + + \eta_{turb} &\text{: turbine efficiency} + + COP &\text{: heat pump coefficient of performance} + + E_{th} &\text{: heat load} + +NDS3 Bus Equation +################# + +The NDS3 Bus is an example of a bus, which does not serve both as in- and output of a storage system. +Instead, the thermal storage is charged from the NDS3 bus, but discharges into the heat bus. + +.. math:: + E_{stc}(t) - E_{tes}(t) - E_{ex}(t) = 0 + +.. math:: + E_{tes} \text{: thermal energy storage} + +DS Bus Equation +############### + +The DS Bus shows an example of a fuel source providing an energy carrier (biogas) to a transformer (turbine). + +.. math:: + E_{heat}(t) - E_{turb}(t) - E_{ex}(t) = 0 + +.. math:: + E_{heat} &\text{: thermal energy (biogas) production} + + E_{turb} &\text{: turbine (biogas turbine) energy} + + + +Cost calculations +----------------- + +The optimization in the MVS is mainly a cost optimization. There are some additional constraints that can be introduced, mainly by adding bounds eg. by limiting the maximum capacity that can be installed (comp. :ref:`maxcap-label`) or adding constraints for certain key performance indicators (see :ref:`constraints-label`). To optimize the energy systems properly, the economic data provided with the input data has to be pre-processed (also see :ref:`economic_precalculation-label`) and then also post-processed when evaluating the results. Following assumptions are important: + +* :ref:`Project lifetime `: The simulation has a defined project lifetime, for which continuous operation is assumed - which means that the first year of operation is exactly like the last year of operation. Existing and optimized assets have to be replaced to make this possible. +* :ref:`Simulation duration `: It is advisable to simulate whole year to find the most suitable combination of energy assets for your system. Sometimes however you might want to look at specific seasons to see their effect - this is possible in the MVS by choosing a specific start date and simulation duration. +* :ref:`Asset costs `: Each asset can have development costs, specific investment costs, specific operation and management costs as well as dispatch costs. + * *Replacement costs* are calculated based on the lifetime of the assets, and residual values are paid at the end of the project. + * *Development costs* are costs that will occurr regardless of the installed capacity of an asset - even if it is not installed at all. It stands for system planning and licensing costs. If you have optimized your energy system and see that an asset might not be favourable (zero optimized capacities), you might want to run the simulation again and remove the asset, or remove the development costs of the asset. + * *Specific investment costs* and *specific operation and maintenance costs* are used to calculate the annual expenditures that an asset has per year, in the process also adding the replacement costs. + * *Dispatch price* can often be set to zero, but are supposed to cover instances where utilization of an asset requires increased operation and maintenance or leads to wear. +* :ref:`Pre-existing capacities `: It is possible to add assets that already exist in your energy system with their capacity and age. + * *Replacements* - To ensure that the energy system operates continously, the existing assets are replaced with the same capacities when they reached their end of life within the project lifetime. + * *Replacement costs* are calculated based on the lifetime of the asset in general and the age of the pre-existing capacities +* `Fix project costs `__: It is possible to define fix costs of the project - this is important if you want to compare different project locations with each other. You can define... + * *Development costs*, which could for example stand for the cost of licenses of the whole energy system + * *(Specific) investment costs*, which could be an investment into land or buildings at the project site. When you define a lifetime for the investment, the MVS will also consider replacements and reimbursements. + * *(Specific) operation and management costs*, which can cover eg. the salaries of at the project site + + + + + + + +Weighting of energy carriers +---------------------------- + +To be able to calculate sector-wide key performance indicators, it is necessary to assign weights to the energy carriers based on their usable potential. In the conference paper handed in to the CIRED workshop, we have proposed a methodology comparable to Gasoline Gallon Equivalents. + +After thorough consideration, it has been decided to base the equivalence in tonnes of oil equivalent (TOE). Electricity has been chosen as a baseline energy carrier, as our pilot sites mainly revolve around it and also because we believe that this energy carrier will play a larger role in the future. For converting the results into a more conventional unit, we choose crude oil as a secondary baseline energy carrier. This also enables comparisons with crude oil price developments in the market. For most KPIs, the baseline energy carrier used is of no relevance as the result is not dependent on it. This is the case for KPIs such as the share of renewables at the project location or its self-sufficiency. The choice of the baseline energy carrier is relevant only for the levelized cost of energy (LCOE), as it will either provide a system-wide supply cost in Euro per kWh electrical or per kg crude oil. + +First, the conversion factors to kg crude oil equivalent [`1 `__] were determined (see :ref:`table_kgoe_conversion_factors` below). These are equivalent to the energy carrier weighting factors with baseline energy carrier crude oil. + +Following conversion factors and energy carriers are defined: + +.. _table_kgoe_conversion_factors: + +.. list-table:: Conversion factors: kg crude oil equivalent (kgoe) per unit of a fuel + :widths: 50 25 25 + :header-rows: 1 + + * - Energy carrier + - Unit + - Value + * - H2 [`3 `__] + - kgoe/kgH2 + - 2.87804 + * - LNG + - kgoe/kg + - 1.0913364 + * - Crude oil + - kgoe/kg + - 1 + * - Gas oil/diesel + - kgoe/litre + - 0.81513008 + * - Kerosene + - kgoe/litre + - 0.0859814 + * - Gasoline + - kgoe/litre + - 0.75111238 + * - LPG + - kgoe/litre + - 0.55654228 + * - Ethane + - kgoe/litre + - 0.44278427 + * - Electricity + - kgoe/kWh(el) + - 0.0859814 + * - Biodiesel + - kgoe/litre + - 0.00540881 + * - Ethanol + - kgoe/litre + - 0.0036478 + * - Natural gas + - kgoe/litre + - 0.00080244 + * - Heat + - kgoe/kWh(therm) + - 0.086 + * - Heat + - kgoe/kcal + - 0.0001 + * - Heat + - kgoe/BTU + - 0.000025 + +The values of ethanol and biodiesel seem comparably low in [`1 `__] and [`2 `__] and do not seem to be representative of the net heating value (or lower heating value) that was expected to be used here. + +From this, the energy weighting factors using the baseline energy carrier electricity are calculated (see :ref:`table_default_energy_carrier_weights_label`). + +.. _table_default_energy_carrier_weights_label: + +.. list-table:: Electricity equivalent conversion per unit of a fuel + :widths: 50 25 25 + :header-rows: 1 + + * - Product + - Unit + - Value + * - LNG + - kWh(eleq)/kg + - 33.4728198 + * - Crude oil + - kWh(eleq)/kg + - 12.6927029 + * - Gas oil/diesel + - kWh(eleq)/litre + - 11.630422 + * - Kerosene + - kWh(eleq)/litre + - 9.48030688 + * - Gasoline + - kWh(eleq)/litre + - 8.90807395 + * - LPG + - kWh(eleq)/litre + - 8.73575397 + * - Ethane + - kWh(eleq)/litre + - 6.47282161 + * - H2 + - kWh(eleq)/kgH2 + - 5.14976795 + * - Electricity + - kWh(eleq)/kWh(el) + - 1 + * - Biodiesel + - kWh(eleq)/litre + - 0.06290669 + * - Ethanol + - kWh(eleq)/litre + - 0.04242544 + * - Natural gas + - kWh(eleq)/litre + - 0.00933273 + * - Heat + - kWh(eleq)/kWh(therm) + - 1.0002163 + * - Heat + - kWh(eleq)/kcal + - 0.00116304 + * - Heat + - kWh(eleq)/BTU + - 0.00029076 + +With this, the equivalent potential of an energy carrier *E*:sub:`{eleq,i}`, compared to electricity, can be calculated with its conversion factor *w*:sub:`i` as: + +.. math:: + E_{eleq,i} = E_{i} \cdot w_{i} + +As it can be noticed, the conversion factor between heat (kWh(therm)) and electricity (kWh(el)) is almost 1. The deviation stems from the data available in source [`1 `__] and [`2 `__]. The equivalency of heat and electricity can be a source of discussion, as from an exergy point of view these energy carriers can not be considered equivalent. When combined, say with a heat pump, the equivalency can also result in ripple effects in combination with the minimal renewable factor or the minimal degree of autonomy, which need to be evaluated during the pilot simulations. + +:Code: + +Currently, the energy carrier conversion factors are defined in `constants.py` with `DEFAULT_WEIGHTS_ENERGY_CARRIERS`. New energy carriers should be added to its list when needed. Unknown carriers raise an `UnknownEnergyVectorError` error. + +:Comment: + +Please note that the energy carrier weighting factor is not applied dependent on the LABEL of the energy asset, but based on its energy vector. Let us consider an example: + +In our system, we have a dispatchable `diesel fuel source`, with dispatch carrying the unit `l Diesel`. +The energy vector needs to be defined as `Diesel` for the energy carrier weighting to be applied, ie. the energy vector of `diesel fuel source` needs to be `Diesel`. This will also have implications for the KPI: +For example, the `degree of sector coupling` will reach its maximum, when the system only has heat demand and all of it is provided by processing diesel fuel. If you want to portrait diesel as something inherent to heat supply, you will need to make the diesel source a heat source, and set its `dispatch costs` to currency/kWh, ie. divide the diesel costs by the heating value of the fuel. + +:Comment: + +In the MVS, there is no distinction between energy carriers and energy vector. For `Electricity` of the `Electricity` vector this may be self-explanatory. However, the energy carriers of the `Heat` vector can have different technical characteristics: A fluid on different temperature levels. As the MVS measures the energy content of a flow in kWh(thermal) however, this distinction is only relevant for the end user to be aware of, as two assets that have different energy carriers as an output should not be connected to one and the same bus if a detailed analysis is expected. An example of this would be, that a system where the output of the diesel boiler as well as the output of a solar thermal panel are connected to the same bus, eventhough they can not both supply the same kind of heat demands (radiator vs. floor heating). This, however, is something that the end-user has to be aware of themselves, eg. by defining self-explanatory labels. + +Emission factors +---------------- + +In order to optimise the energy system with minimum emissions, it is important to calculate emission per unit of fuel consumption. + +In table :ref:`table_emissions_energyCarriers` the emission factors for energy carriers are defined. These values are based on direct emissions during stationary consumption of the mentioned fuels. + +.. _table_emissions_energyCarriers: + +.. list-table:: Emission factors: Kg of CO2 equivalent per unit of fuel consumption + :widths: 50 25 25 25 + :header-rows: 1 + + * - Energy carrier + - Unit + - Value + - Source + * - Diesel + - kgCO2eq/litre + - 2.7 + - [`4 `__] Page No. 26 + * - Gasoline + - kgCO2eq/litre + - 2.3 + - [`4 `__] Page No. 26 + * - Kerosene + - kgCO2eq/litre + - 2.5 + - [`4 `__] Page No. 26 + * - Natural gas + - kgCO2eq/m3 + - 1.9 + - [`4 `__] Page No. 26 + * - LPG + - kgCO2eq/litre + - 1.6 + - [`4 `__] Page No. 26 + * - Biodiesel + - kgCO2eq/litre + - 0.000125 + - [`5 `__] Page No. 6 + * - Bioethanol + - kgCO2eq/litre + - 0.0000807 + - [`5 `__] Page No. 6 + * - Biogas + - kgCO2eq/m3 + - 0.12 + - [`6 `__] Page No. 1 + +In table :ref:`table_CO2_emissions_countries` the CO2 emissions for Germany and the four pilot sites (Norway, Spain, Romania, India) are defined: + +.. _table_CO2_emissions_countries: + +.. list-table:: CO2 Emission factors: grams of CO2 equivalent per kWh of electricity consumption + :widths: 50 25 25 25 + :header-rows: 1 + + * - Country + - Unit + - Value + - Source + * - Germany + - gCO2eq/kWh + - 338 + - [`7 `__] Fig. 2 + * - Norway + - gCO2eq/kWh + - 19 + - [`7 `__] Fig. 2 + * - Spain + - gCO2eq/kWh + - 207 + - [`7 `__] Fig. 2 + * - Romania + - gCO2eq/kWh + - 293 + - [`7 `__] Fig. 2 + * - India + - gCO2eq/kWh + - 708 + - [`8 `__] Page No. 7 + +The values mentioned in the table above account for emissions during the complete life cycle. This includes emissions during energy production, energy conversion, energy storage and energy transmission. + + +.. _verification_of_inputs: + +Input verification +------------------ + +The inputs for a simulation with the MVS are subjected to a couple of verification tests to make sure that the inputs result in valid oemof simulations. This should ensure: + +- Uniqueness of labels (`C1.check_for_label_duplicates`): This function checks if any LABEL provided for the energy system model in dict_values is a duplicate. This is not allowed, as oemof can not build a model with identical labels. + +- No levelized costs of generation lower than feed-in tariff of same energy vector in case of investment optimization (`optimizeCap` is True) (`C1.check_feedin_tariff_vs_levelized_cost_of_generation_of_providers`): Raises error if feed-in tariff > levelized costs of generation if `maximumCap` is None for energy asset in ENERGY_PRODUCTION. This is not allowed, as oemof otherwise may be subjected to an unbound problem, ie. a business case in which an asset should be installed with infinite capacities to maximize revenue. If maximumCap is not None a logging.warning is shown as the maximum capacity of the asset will be installed. + +- No feed-in tariff higher then energy price from an energy provider (`C1.check_feedin_tariff_vs_energy_price`): Raises error if feed-in tariff > energy price of any asset in 'energyProvider.csv'. This is not allowed, as oemof otherwise is subjected to an unbound and unrealistic problem, eg. one where the owner should consume electricity to feed it directly back into the grid for its revenue. + +- Assets have well-defined energy vectors and belong to an existing bus (`C1.check_if_energy_vector_of_all_assets_is_valid`): Validates for all assets, whether 'energyVector' is defined within DEFAULT_WEIGHTS_ENERGY_CARRIERS and within the energyBusses. + +- Energy carriers used in the simulation have defined factors for the electricity equivalency weighting (`C1.check_if_energy_vector_is_defined_in_DEFAULT_WEIGHTS_ENERGY_CARRIERS`): Raises an error message if an energy vector is unknown. It then needs to be added to the DEFAULT_WEIGHTS_ENERGY_CARRIERS in constants.py + +- An energy bus is always connected to one inflow and one outflow (`C1.check_for_sufficient_assets_on_busses`): Validating model regarding busses - each bus has to have 2+ assets connected to it, exluding energy excess sinks + +- Time series of energyProduction assets that are to be optimized have specific generation profiles (`C1.check_non_dispatchable_source_time_series`, `C1.check_time_series_values_between_0_and_1`): Raises error if time series of non-dispatchable sources are not between [0, 1]. + +- Provided timeseries are checked for `NaN` values, which are replaced by zeroes (`C0.replace_nans_in_timeseries_with_0`). + +- Asset capacities connected to each bus are sized sufficiently to fulfill the maximum demand (`C1.check_energy_system_can_fulfill_max_demand`): Logs a logging.warning message if the aggregated installed capacity and maximum capacity (if applicable) of all conversion, generation and storage assets connected to one bus is smaller than the maximum demand. The check is applied to each bus of the energy system. Check passes when the potential peak supply is larger then or equal to the peak demand on the bus, or if the maximum capacity of an asset is set to None when optimizing. diff --git a/docs/model/components.rst b/docs/model/components.rst new file mode 100644 index 000000000..a7b2c7649 --- /dev/null +++ b/docs/model/components.rst @@ -0,0 +1,305 @@ +.. _component_models: + +Component models +---------------- + +The component models of the MVS result from the used python-library `oemof-solph` for energy modeling. + +It requires component models to be simplified and linearized. +This is the reason that the MVS can provide a pre-feasibility study of a specific system setup, +but not the final sizing and system design. +The types of assets are presented below. + +.. _energy_consumption: + +Energy consumption +################## + +Demands within the MVS are added as energy consumption assets in `energyConsumption.csv`. Most importantly, they are defined by a timeseries, representing the demand profile, and their energy vector. A number of demand profiles can be defined for one energy system, both of the same and different energy vectors. +The main optimization goal for the MVS is to supply the defined demand withouth fail for all of the timesteps in the simulation with the least cost of supply (comp. :ref:`economic_precalculation-label`). + + +.. _energy_production: + +Energy production +################# + +Non-dispatchable sources of generation +====================================== + +`Examples`: + + - PV plants + - Wind plants + - Run-of-the-river hydro power plants + - Solar thermal collectors + +Variable renewable energy (VRE) sources, like wind and PV, are non-dispatchable due to their fluctuations in supply. They are added as sources in `energyProduction.csv`. + +The fluctuating nature of non-dispatchable sources is represented by generation time series that show the respective production for each time step of the simulated period. In energy system modelling it is common to use hourly time series. +The name of the file containing the time series is added to `energyProduction.csv` with the parameter :ref:`filename-label`. For further requirements concerning the time series see section :ref:`time_series_folder`. + +If you cannot provide time series for your VRE assets you can consider to calculate them by using models for generating feed-in time series from weather data. The following is a list of examples, which is not exhaustive: + + - PV: `pvlib `_ , `Renewables Ninja `_ (download capacity factors) + - Wind: `windpowerlib `_, `Renewables Ninja `_ (download capacity factors) + - Hydro power (run-of-the-river): `hydropowerlib `_ + - Solar thermal: `flat plate collectors `_ of `oemof.thermal `_ + + +.. _dispatchable_sources: + +Dispatchable sources of generation +================================== + +`Examples`: + + - Fuel sources + - Deep-ground geothermal plant (ground assumed to allow unlimited extraction of heat, not depending on season) + +Fuel sources are added as dispatchable sources, which can have development, investment, operational and dispatch costs. +They are added to `energyProduction.csv`, while setting :ref:`filename-label` to `None`. + +Fuel sources are for example needed as source for a diesel generator (diesel), biogas plant (gas) or a condensing power plant (gas, coal, ...), see :ref:`energy_conversion`. + +Energy providers, even though also dispatchable sources of generation, should be added via `energyProviders.csv`, +as there are some additional features available then, see :ref:`energy_providers`. + +Both energy providers and the additional fuel sources are limited to the options of energy carriers provided in the table of :ref:`table_default_energy_carrier_weights_label`, as the default weighting factors to translate the energy carrier into electricity equivalent need to be defined. + + +.. _energy_conversion: + +Energy conversion +################# + +`Examples`: + + - Electric transformers (rectifiers, inverters, transformer stations, charge controllers) + - HVAC and Heat pumps (as heater and/or chiller) + - Combined heat and power (CHP) and other condensing power plants + - Diesel generators + - Electrolyzers + - Biogas power plants + +Conversion assets are added as transformers and are defined in `energyConversion.csv`. + +The parameters `dispatch_price`, `efficiency` and `installedCap` of transformers are assigned to their output flows. +This means that these parameters need to be given for the output of the asset and that the costs of the input, e.g. fuel, if existent, are not included in its `dispatch_price` but in the `dispatch_price` of the fuel source, see :ref:`dispatchable_sources`. + +Conversion assets can be defined with multiple inputs or multiple outputs, but one asset currently cannot have both, multiple inputs and multiple outputs. Note that multiple inputs/output have not been tested, yet. + +.. _energyconversion_electric_transformers: + +Electric transformers +===================== + +Electric rectifiers and inverters that are transforming electricity in one direction only, are simply added as transformers. +Bidirectional converters and transformer stations are defined by two transformers that are optimized independently from each other, if optimized. +The same accounts for charge controllers for a :ref:`battery_storage` that are defined by two transformers, one for charging and one for discharging. +The parameters `dispatch_price`, `efficiency` and `installedCap` need to be given for the electrical output power of the electric transformers. + +.. note:: + When using two conversion objects to emulate a bidirectional conversion asset, their capacity should be interdependent. This is currently not the case, see `Infeasible bi-directional flow in one timestep `_. + +.. _energyconversion_hvac: + +Heating, Ventilation, and Air Conditioning (HVAC) +================================================= + +Like other conversion assets, devices for heating, ventilation and air conditioning (HVAC) are added as transformers. As the parameters `dispatch_price`, `efficiency` and `installedCap` are assigned to the output flows they need to be given for the nominal heat output of the HVAC. + +Different types of HVAC can be modelled. Except for an air source device with ambient temperature as heat reservoir, the device could be modelled with two inputs (electricity and heat) in case the user is interested in the heat reservoir. This has not been tested, yet. Also note that currently efficiencies are assigned to the output flows the see `issue #799 `_. +Theoretically, a HVAC device can be modelled with multiple outputs (heat, cooling, ...); this has not been tested, yet. + +The efficiency of HVAC systems is defined by the coefficient of performance (COP), which is strongly dependent on the temperature. In order to take account of this, the efficiency can be defined as time series, see section :ref:`time_series_params_example`. +If you do not provide your own COP time series you can calculate them with `oemof.thermal `_, see `documentation on compression heat pumps and chillers `_ and `documentation on absorption chillers `_. + +.. _energyconversion_electrolyzers: + +Electrolyzers +============= + +Electrolyzers are added as transformers with a constant or time dependent but in any case pre-defined efficiency. The parameters `dispatch_price`, `efficiency` and `installedCap` need to be given for the output of the electrolyzers (hydrogen). + +Currently, electrolyzers are modelled with only one input flow (electricity), not taking into account the costs of water; see `issue #799 `_. +The minimal operation level and consumption in standby mode are not taken into account, yet, see `issue #50 `_. + +.. _power_plants: + +Condensing power plants and Combined heat and power (CHP) +========================================================= + +Condensing power plants are added as transformers with one input (fuel) and one output (electricity), while CHP plants are defined with two outputs (electricity and heat). +The parameters `dispatch_price`, `efficiency` and `installedCap` need to be given for the electrical output power (and nominal heat output) of the power plant, while fuel costs need to be included in the `dispatch_price` of the fuel source. + +The ratio between the heat and electricity output of a CHP is currently simulated as fix values. This might be changed in the future by using the `ExtractionTurbineCHP `_ +or the `GenericCHP `_ component of oemof, see `issue #803 `_ + +Note that multiple inputs/output have not been tested, yet. + +Other fuel powered plants +========================= + +Fuel powered conversion assets, such as diesel generators and biogas power plants, are added as transformers. +The parameters `dispatch_price`, `efficiency` and `installedCap` need to be given for the electrical output power of the diesel generator or biogas power plant. +As described above, the costs for diesel and gas need to be included in the `dispatch_price` of the fuel source. + + +.. _energy_providers: + +Energy providers +################ + +The energy providers are the most complex assets in the MVS model. They are composed of a number of sub-assets + + - Energy consumption source, providing the energy required from the system with a certain price + - Energy peak demand pricing "transformers", which represent the costs induced due to peak demand + - Bus connecting energy consumption source and energy peak demand pricing transformers + - Energy feed-in sink, able to take in generation that is provided to the energy provider for revenue + - Optionally: Transformer Station connecting the energy provider bus to the energy bus of the LES + +With all these components, the energy provider can be visualized as follows: + +.. image:: ../images/Model_Assumptions_energyProvider_assets.png + :width: 600 + +Variable energy consumption prices (time-series) +================================================ + +Energy consumption prices can be added as values that vary over time. See section :ref:`time_series_folder` or more information. + +.. _energy_providers_peak_demand_pricing: + +Peak demand pricing +=================== + +A peak demand pricing scheme is based on an electricity tariff, +that requires the consumer not only to pay for the aggregated energy consumption in a time period (eg. kWh electricity), +but also for the maximum peak demand (load, eg. kW power) towards the grid of the energy provider within a specific pricing period. + +In the MVS, this information is gathered for the `energyProviders` with: + + - :const:`multi_vector_simulator.utils.constants_json_strings.PEAK_DEMAND_PRICING_PERIOD` as the period used in peak demand pricing. Possible is 1 (yearly), 2 (half-yearly), 3 (each trimester), 4 (quaterly), 6 (every 2 months) and 12 (each month). If you have a `simulation_duration` < 365 days, the periods will still be set up assuming a year! This means, that if you are simulating 14 days, you will never be able to have more than one peak demand pricing period in place. + + - :const:`multi_vector_simulator.utils.constants_json_strings.PEAK_DEMAND_PRICING` as the costs per peak load unit, eg. kW + +To represent the peak demand pricing, the MVS adds a "transformer" that is optimized with specific operation and maintenance costs per year equal to the PEAK_DEMAND_PRICING for each of the pricing periods. +For two peak demand pricing periods, the resulting dispatch could look as following: + +.. image:: ../images/Model_Assumptions_Peak_Demand_Pricing_Dispatch_Graph.png + :width: 600 + +.. _energy_storage: + +Energy storage +############## + +Energy storages such as battery storages, thermal storages or H2 storages are modelled with the *GenericStorage* component of *oemof.solph*. They are designed for one input and one output and are defined with files `energyStorage.csv` and `storage_*.csv` and have several parameters, which are listed in the section :ref:`storage_csv`. + +The state of charge of a storage at the first and last time step of an optimization are equal. +Charge and discharge of the whole capacity of the energy storage are possible within one time step in case the capacity of the storage is not optimized. In case of +capacity optimization charge and discharge is limited by the :ref:`crate-label`. + +.. _battery_storage: + +Battery energy storage system (BESS) +==================================== + +BESS are modelled as *GenericStorage* like described above. The BESS can either be connected directly to the electricity bus of the LES or via a charge controller that manages the BESS. +When choosing the second option, the capacity of the charge controller can be optimized individually, which takes its specific costs and lifetime into consideration. +If you do not want to optimize the charge controller's capacity you can take its costs and efficiency into account when defining the storage's input and output power, see :ref:`storage_csv`. +A charge controller is defined by two transformers, see section :ref:`energy_conversion` above. + +Note that capacity reduction over the lifetime of a BESS that may occur due to different effects during aging cannot be taken into consideration in MVS. A possible workaround for this could be to manipulate the lifetime. + + +Hydrogen storage (H2) +===================== + +Hydrogen storages are modelled as all storage types in MVS with as *GenericStorage* like described above. + +The most common hydrogen storages store H2 as liquid under temperatures lower than -253 °C or under high pressures. +The energy needed to provide these requirements cannot be modelled via the storage component as another energy sector such as cooling or electricity is needed. It could therefore, be modelled as an additional demand of the energy system, see `issue #811 `_ + +.. _thermal_storage: + +Thermal energy storage +====================== + +Thermal energy storages of the type sensible heat storage (SHS) are modelled as *GenericStorage* like described above. The implementation of a specific type of SHS, the stratified thermal energy storage, is described in section :ref:`stratified_tes`. +The modelling of latent-heat (or Phase-change) and chemical storages have not been tested with MVS, but might be achieved by precalculations. + +.. _stratified_tes: + +Stratified thermal energy storage +================================= + +Stratified thermal energy storage is defined by the two optional parameters `fixed_losses_relative` and `fixed_losses_absolute`. If they are not included in `storage_*.csv` or are equal to zero, then a normal generic storage is simulated. +These two parameters are used to take into account temperature dependent losses of a thermal storage. To model a thermal energy storage without stratification, the two parameters are not set. The default values of `fixed_losses_relative` and `fixed_losses_absolute` are zero. +Except for these two additional parameters the stratified thermal storage is implemented in the same way as other storage components. + +Precalculations of the `installedCap`, `efficiency`, `fixed_losses_relative` and `fixed_losses_absolute` can be done orientating on the stratified thermal storage component of `oemof.thermal `__. +The parameters `U-value`, `volume` and `surface` of the storage, which are required to calculate `installedCap`, can be precalculated as well. + +The efficiency :math:`\eta` of the storage is calculated as follows: + +.. math:: + \eta = 1 - loss{\_}rate + +This example shows how to do precalculations using stratified thermal storage specific input data: + + +.. code-block:: python + + from oemof.thermal.stratified_thermal_storage import ( + calculate_storage_u_value, + calculate_storage_dimensions, + calculate_capacities, + calculate_losses, + ) + + # Precalculation + u_value = calculate_storage_u_value( + input_data['s_iso'], + input_data['lamb_iso'], + input_data['alpha_inside'], + input_data['alpha_outside']) + + volume, surface = calculate_storage_dimensions( + input_data['height'], + input_data['diameter'] + ) + + nominal_storage_capacity = calculate_capacities( + volume, + input_data['temp_h'], + input_data['temp_c']) + + loss_rate, fixed_losses_relative, fixed_losses_absolute = calculate_losses( + u_value, + input_data['diameter'], + input_data['temp_h'], + input_data['temp_c'], + input_data['temp_env']) + +Please see the `oemof.thermal` `examples `__ and the `documentation `__ for further information. + +For an investment optimization the height of the storage should be left open in the precalculations and `installedCap` should be set to 0 or NaN. + +An implementation of the stratified thermal storage component has been done in `pvcompare `__. You can find the precalculations of the stratified thermal energy storage made in `pvcompare` `here `__. + + +Energy excess +############# + +.. note:: + Energy excess components are implemented **automatically** by MVS! You do not need to define them yourself. + +An energy excess sink is placed on each of the LES energy busses, and therefore energy excess is allowed to take place on each bus of the LES. +This means that there are assumed to be sufficient vents (heat) or transistors (electricity) to dump excess (waste) generation. +Excess generation can only take place when a non-dispatchable source is present or if an asset can supply energy without any fuel or dispatch costs. + +In case of excessive excess energy, a warning is given that it seems to be cheaper to have high excess generation than investing into more capacities. +High excess energy can for example result into an optimized inverter capacity that is smaller than the peak generation of installed PV. +This becomes unrealistic when the excess is very high. \ No newline at end of file diff --git a/docs/model/constraints.rst b/docs/model/constraints.rst new file mode 100644 index 000000000..53ed737c3 --- /dev/null +++ b/docs/model/constraints.rst @@ -0,0 +1,127 @@ +.. _constraints-label: + +Constraints +----------- + +Constraints are controlled with the file `constraints.csv`. + +.. _constraint_min_re_factor: + +Minimal renewable factor constraint +################################### + +The minimal renewable factor constraint requires the capacity and dispatch optimization of the MVS to reach at least the minimal renewable factor defined within the constraint. The renewable share of the optimized energy system may also be higher than the minimal renewable factor. + +The minimal renewable factor is applied to the minimal renewable factor of the whole, sector-coupled energy system, but not to specific sectors. As such, energy carrier weighting plays a role and may lead to unexpected results. The constraint reads as follows: + +.. math:: + minimal renewable factor <= \frac{\sum renewable generation \cdot weighting factor}{\sum renewable generation \cdot weighting factor + \sum non-renewable generation \cdot weighting factor} + +Please be aware that the minimal renewable factor constraint defines bounds for the :ref:`kpi_renewable_factor` of the system, ie. taking into account both local generation as well as renewable supply from the energy providers. The constraint explicitly does not aim to reach a certain :ref:`kpi_renewable_share_of_local_generation` on-site. + +:Deactivating the constraint: + +The minimal renewable factor constraint is deactivated by inserting the following row in `constraints.csv` as follows: + +```minimal_renewable_factor,factor,0``` + +:Activating the constraint: + +The constraint is enabled when the value of the minimal renewable factor factor is above 0 in `constraints.csv`: + +```minimal_renewable_factor,factor,0.3``` + + +Depending on the energy system, especially when working with assets which are not to be capacity-optimized, it is possible that the minimal renewable factor criterion cannot be met. The simulation terminates in that case. If you are not sure if your energy system can meet the constraint, set all `optimize_Cap` parameters to `True`, and then investigate further. +Also, if you are aiming at very high minimal renewable factors, the simulation time can increase drastically. If you do not get a result after a maximum of 20 Minutes, you should consider terminating the simulation and trying with a lower minimum renewable share. + +The minimum renewable share is introduced to the energy system by `D2.constraint_minimal_renewable_share()` and a validation test is performed with `E4.minimal_renewable_share_test()`. + +.. _constraint_minimal_degree_of_autonomy: + +Minimal degree of autonomy constraint +###################################### + +The minimal degree of autonomy constraint requires the capacity and dispatch optimization of the MVS to reach at least the minimal degree of autonomy defined within the constraint. The degree of autonomy of the optimized energy system may also be higher than the minimal degree of autonomy. Please find the definition of here: :ref:`kpi_degree_of_autonomy` + +The minimal degree of autonomy is applied to the whole, sector-coupled energy system, but not to specific sectors. As such, energy carrier weighting plays a role and may lead to unexpected results. The constraint reads as follows: + +.. math:: + minimal~degree~of~autonomy <= DA = \frac{\sum E_{demand,i} \cdot w_i - \sum E_{consumption,provider,j} \cdot w_j}{\sum E_{demand,i} \cdot w_i} + +:Deactivating the constraint: + +The minimal degree of autonomy constraint is deactivated by inserting the following row in `constraints.csv` as follows: + +```minimal_degree_of_autonomy,factor,0``` + +:Activating the constraint: + +The constraint is enabled when the value of the minimal degree of autonomy is above 0 in `constraints.csv`: + +```minimal_degree_of_autonomy,factor,0.3``` + + +Depending on the energy system, especially when working with assets which are not to be capacity-optimized, it is possible that the minimal degree of autonomy criterion cannot be met. The simulation terminates in that case. If you are not sure if your energy system can meet the constraint, set all `optimizeCap` parameters to `True`, and then investigate further. + +The minimum degree of autonomy is introduced to the energy system by `D2.constraint_minimal_degree_of_autonomy()` and a validation test is performed with `E4.minimal_degree_of_autonomy()`. + +.. _constraint_maximum_emissions: + +Maximum emission constraint +########################### + +The maximum emission constraint limits the maximum amount of total emissions per year of the energy system. It allows the capacity and dispatch optimization of the MVS to result into a maximum amount of emissions defined by the maximum emission constraint. The yearly emissions of the optimized energy system may also be lower than the maximum emission constraint. + +Please note that the maximum emissions constraint currently does not take into consideration life cycle emissions, also see :ref:`emissions` section for an explanation. + +:Activating the constraint: + +The maximum emissions constraint is enabled by inserting the following row in `constraints.csv` as follows: + +```maximum_emissions,kgCO2eq/a,800000``` + +:Deactivating the constraint: + +The constraint is deactivated by setting the value in `constraints.csv` to None: + +```maximum_emissions,kgCO2eq/a,None``` + +The unit of the constraint is `kgCO2eq/a`. To select a useful value for this constraint you can e.g.: + +- Firstly, optimize your system without the constraint to get an idea about the scale of the emissions and then, secondly, set the constraint and lower the emissions step by step until you receive an unbound problem (which then represents the non-archievable minimum of emissions for your energy system) +- Check the emissions targets of your region/country and disaggregate the number + +The maximum emissions constraint is introduced to the energy system by `D2.constraint_maximum_emissions()` and a validation test is performed with `E4.maximum_emissions_test()`. + +.. _constraint_net_zero_energy: + +Net zero energy (NZE) constraint +################################ + +The net zero energy (NZE) constraint requires the capacity and dispatch optimization of the MVS to result into a net zero system, but can also result in a plus energy system. +The degree of NZE of the optimized energy system may be higher than 1, in case of a plus energy system. Please find the definition of net zero energy (NZE) and the KPI here: :ref:`kpi_degree_of_nze`. + +Some definitions of NZE systems in literature allow the energy system's demand solely be provided by locally generated renewable energy. In MVS this is not the case - all locally generated energy is taken into consideration. To enlarge the share of renewables in the energy system you can use the :ref:`constraint_min_re_factor`. + +The NZE constraint is applied to the whole, sector-coupled energy system, but not to specific sectors. As such, energy carrier weighting plays a role and may lead to unexpected results. The constraint reads as follows: + +.. math:: + \sum_{i} {E_{feedin, DSO} (i) \cdot w_i - E_{consumption, DSO} (i) \cdot w_i} >= 0 + +:Deactivating the constraint: + +The NZE constraint is deactivated by inserting the following row in `constraints.csv` as follows: + +```net_zero_energy,bool,False``` + +:Activating the constraint: + +The constraint is enabled when the value of the NZE constraint is set to `True` in `constraints.csv`: + +```net_zero_energy,bool,True``` + + +Depending on the energy system, especially when working with assets which are not to be capacity-optimized, it is possible that the NZE criterion cannot be met. The simulation terminates in that case. If you are not sure if your energy system can meet the constraint, set all `optimizeCap` parameters to `True`, and then investigate further. + +The net zero energy constraint is introduced to the energy system by `D2.constraint_net_zero_energy()` and a validation test is performed with `E4.net_zero_energy_test()`. diff --git a/docs/E-Land_Requirements.rst b/docs/model/eland_requirements.rst similarity index 100% rename from docs/E-Land_Requirements.rst rename to docs/model/eland_requirements.rst diff --git a/docs/MVS_parameters.rst b/docs/model/input_parameters.rst similarity index 75% rename from docs/MVS_parameters.rst rename to docs/model/input_parameters.rst index b7416ffb7..82ae7ff1c 100644 --- a/docs/MVS_parameters.rst +++ b/docs/model/input_parameters.rst @@ -1,43 +1,48 @@ -======================================= -Parameters and Definitions in CSVs/JSON -======================================= +================ +Input parameters +================ -Each of the parameters has the following properties -:Definition: parameter's definition, could also contain potential use cases of the parameter -:Type: str (text), numeric (integer or double precision number), boolean (True or False) -:Unit: physical unit -:Example: an example of parameter's value -:Restrictions: specific restrictions on the parameter's value (e.g., "positive integer number", "must be an even number", "must be one of ['val1', 'val2']" -:Default: default parameter's value +************************************ +Parameters in each category/CSV file +************************************ + +Important note: Each asset and bus needs to have an unique label. +In the `csv` input files, these are defined by the column headers. +The input parameters are gathered under the following categories. These categories reflect the structure of the `csv` input files or the firsts keys of the `json` input file. + +.. This file is generated automatically when conf.py is executed (function generate_parameter_categories) + +.. include:: parameters/MVS_parameters_categories.inc + + +******************* +Table of parameters +******************* .. This file is generated automatically when conf.py is executed (function generate_parameter_table) +The input parameters are gathered in the table below. Each parameter is provided with unit, type and example values. For more information about one parameter, please click on it. + .. csv-table:: Parameters summary - :file: MVS_parameters_list.tbl + :file: parameters/MVS_parameters_list.tbl :header-rows: 1 - ****************** List of parameters ****************** -Below is the list of all the parameters of MVS, sorted in alphabetical order. Each parameter is provided with the definition, unit, type and example values as well to make it easy for users to provide custom values for their systems. - -.. This file is generated automatically when conf.py is executed (function generate_parameter_description) - -.. include:: MVS_parameters_list.inc - - -************************************ -Parameters in each category/CSV file -************************************ +Below is the list of all the parameters of MVS, sorted in alphabetical order. +Each of the parameters has the following properties -Important note: Each asset and bus needs to have an unique label. -In the `csv` input files, these are defined by the column headers. -The input parameters are gathered under the following categories. These categories reflect the structure of the `csv` input files or the firsts keys of the `json` input file. +:Definition: parameter's definition, could also contain potential use cases of the parameter +:Type: str (text), numeric (integer or double precision number), boolean (True or False) +:Unit: physical unit +:Example: an example of parameter's value +:Restrictions: specific restrictions on the parameter's value (e.g., "positive integer number", "must be an even number", "must be one of ['val1', 'val2']" +:Default: default parameter's value -.. This file is generated automatically when conf.py is executed (function generate_parameter_categories) +.. This file is generated automatically when conf.py is executed (function generate_parameter_description) -.. include:: MVS_parameters_categories.inc +.. include:: parameters/MVS_parameters_list.inc diff --git a/docs/model/limitations.rst b/docs/model/limitations.rst new file mode 100644 index 000000000..1ce755b04 --- /dev/null +++ b/docs/model/limitations.rst @@ -0,0 +1,255 @@ +Limitations +----------- + +When running simulations with the MVS, there are certain peculiarities to be aware of. +The peculiarities can be considered as limitations, some of which are merely model assumptions and others are drawbacks of the model. +A number of those are inherited due to the nature of the MVS and its underlying modules, +and others can still be addressed in the future during the MVS development process, which is still ongoing. +The following table (:ref:`table_limitations_label`) lists the MVS limitations based on their type. + + +.. _table_limitations_label: + +.. list-table:: Limitations + :widths: 25 25 + :header-rows: 1 + + * - Inherited + - Can be addressed + * - :ref:`limitations-real-life-constraint` + - :ref:`limitations-missing-kpi` + * - :ref:`limitations-simplified_model` + - :ref:`limitations-random-excess` + * - :ref:`limitations-degradation` + - :ref:`limitations-renewable-share-definition` + * - :ref:`limitations-perfect_foresight` + - :ref:`limitations-energy_carrier_weighting` + * - + - :ref:`limitations-energy_shortage` + * - + - :ref:`limitations-bidirectional-transformers` + +.. _limitations-real-life-constraint: + +Infeasible bi-directional flow in one timestep +############################################## + +:Limitation: + +The real life constraint of the dispatch of assets, that it is not possible to have two flows in opposite directions at the same time step, is not adhered to in the MVS. + +:Reason: + +The MVS is based on the python library `oemof-solph`. Its generic components are used to set up the energy system. As a ground rule, the components of `oemof-solph` are unidirectional. This means that for an asset that is bidirectional two transformer objects have to be used. Examples for this are: + +* Physical bi-directional assets, eg. inverters +* Logical bi-directional assets, eg. consumption from the grid and feed-in to the grid + +To achieve the real-life constraint one flow has to be zero when the other is larger zero, one would have to implement following relation: + +.. math:: + E_{in} \cdot E_{out} = 0 + +However, this relation creates a non-linear problem and can not be implemented in `oemof-solph`. + +:Implications: + +This limitation means that the MVS might result in infeasible dispatch of assets. For instance, a bus might be supplied by a rectifier and itself supplying an inverter at the same time step t, which cannot logically happen if these assets are part of one physical bi-directional inverter. Another case that could occur is feeding the grid and consuming from it at the same time t. + +Under certain conditions, including an excess generation as well as dispatch costs of zero, the infeasible dispatch can also be observed for batteries and result in a parallel charge and discharge of the battery. If this occurs, a solution may be to set a marginal dispatch cost of battery charge. + +.. _limitations-simplified_model: + +Simplified linear component models +################################## + +:Limitation: + +The MVS simplifies the component model of some assets. + + * Generators have an efficiency that is not load-dependent + * Storage have a charging efficiency that is not SOC-dependent + * Turbines are implemented without ramp rates + +:Reason: + +The MVS is based oemof-solph python library and uses its generic components to set up an energy system. Transformers and storages cannot have variable efficiencies. + +:Implications: + +Simplifying the implementation of some component specifications can be beneficial for the ease of the model, however, it contributes to the lack of realism and might result in less accurate values. The MVS accepts the decreased level of detail in return for a quick evaluation of its scenarios, which are often only used for a pre-feasibility analysis. + +.. _limitations-degradation: + +No degradation of efficiencies over a component lifetime +######################################################## + +:Limitation: + +The MVS does not degrade the efficiencies of assets over the lifetime of the project, eg. in the case of production assets like PV panels. + +:Reason: + +The simulation of the MVS is only based on a single reference year, and it is not possible to take into account multi-year degradation of asset efficiency. + +:Implications: + +This results in an overestimation of the energy generated by the asset, which implies that the calculation of some other results might also be overestimated (e.g. overestimation of feed-in energy). The user can circumvent this by applying a degradation factor manually to the generation time series used as an input for the MVS. + +.. _limitations-perfect_foresight: + +Perfect foresight +################# + +:Limitation: + +The optimal solution of the energy system is based on perfect foresight. + +:Reason: + +As the MVS and thus oemof-solph, which is handling the energy system model, know the generation and demand profiles for the whole simulation time and solve the optimization problem based on a linear equation system, the solver knows their dispatch for certain, whereas in reality the generation and demand could only be forecasted. + +:Implications: + +The perfect foresight can lead to suspicious dispatch of assets, for example charging of a battery right before a (in real-life) random blackout occurs. The systems optimized with the MVS therefore, represent their optimal potential, which in reality could not be reached. The MVS has thus a tendency to underestimate the needed battery capacity or the minimal state of charge for backup purposes, and also designs the PV system and backup power according to perfect forecasts. In reality, operational margins would need to be added. + +.. _limitations-missing-kpi: + + +Optimization precision +###################### + +:Limitation: + +Marginal capacities and flows below a threshold of 10^-6 are rounded to zero. + +:Reason: + +The MVS makes use of the open energy modelling framework (oemof) by using oemof-solph. For the MVS, we use the `cbc-solver` and at a `ratioGap=0.03`. This influences the precision of the optimized decision variables, ie. the optimized capacities as well as the dispatch of the assets. +In some cases the dispatch and capacities vary around 0 with fluctuations of the order of floating point precision (well below <10e-6), thus resulting in marginal and also marginal negative dispatch or capacities. When calculating KPI from these decision variables, the results can be nonsensical, for example leading to SoC curves with negative values or values far above the viable value 1. +As the reason for these inconsistencies is known, the MVS enforces the capacities and dispatch of to be above 10e-6, ie. all capacities or flows smaller than that are set to zero. This is applied to absolute values, so that irregular (and incorrect) values for decision variables can still be detected. + +:Implications: + +If your energy system has demand or resource profiles that include marginal values below the threshold of 10^-6, the MVS will not result in appropriate results. For example, that means that if you have an energy system with usually is measured in `MW` but one demand is in the `W` range, the dispatch of assets serving this minor demand is not displayed correctly. Please chose `kW` or even `W` as a base unit then. + +Extension of KPIs necessary +########################### + +:Limitation: + +Some important KPIs usually required by developers are currently not implemented in the MVS: + +* Internal rate of return (IRR) +* Payback period +* Return on equity (ROE), + +:Reason: + +The MVS tool is a work in progress and this can still be addressed in the future. + +:Implications: + +The absence of such indicators might affect decision-making. + +.. _limitations-random-excess: + +Random excess energy distribution +################################# + +:Limitation: + +There is random excess distribution between the feed-in sink and the excess sink when no feed-in-tariff is assumed in the system. + +:Reason: + +Since there is no feed-in-tariff to benefit from, the MVS randomly distributes the excess energy between the feed-in and excess sinks. As such, the distribution of excess energy changes when running several simulations for the same input files. + +:Implications: + +On the first glance, the distribution of excess energy onto both feed-in sink and excess sink may seem off to the end-user. Other than these inconveniences, there are no real implications that affect the capacity and dispatch optimization. When a degree of self-supply and self-consumption is defined, the limitation might tarnish these results. + +.. _limitations-renewable-share-definition: + +Renewable energy share defintion relative to energy carriers +############################################################ + +:Limitation: + +The current renewable energy share depends on the share of renewable energy production assets directly feeding the load. The equation to calculate the share also includes the energy carrier rating as described here below: + +.. math:: + RES &= \frac{\sum_i E_{RE,generation}(i) \cdot w_i}{\sum_i E_{RE,generation}(i) \cdot w_i + \sum_k E_{nonRE,generation}(k) \cdot w_k} + + \text{with~} & i \text{: renewable energy asset} + + & k \text{: non-renewable energy asset} + +:Reason: + +The MVS tool is a work in progress and this can still be addressed in the future. + +:Implications: + +This might result in different values when comparing them to other models. Another way to calculate it is by considering the share of energy consumption supplied from renewable sources. + +.. _limitations-energy_carrier_weighting: + +Energy carrier weighting +######################## + +:Limitation: + +The MVS assumes a usable potential/energy content rating for every energy carrier. The current version assumes that 1 kWh thermal is equivalent to 1 kWh electricity. + +:Reason: + +This is an approach that the MVS currently uses. + +:Implications: + +By weighing the energy carriers according to their energy content (Gasoline Gallon Equivalent (GGE)), the MVS might result in values that can't be directly assessed. Those ratings affect the calculation of the levelized cost of the energy carriers, but also the minimum renewable energy share constraint. + +.. _limitations-energy_shortage: + +Events of energy shortage or grid interruption can not be modelled +################################################################## + +:Limitation: + +The MVS assumes no shortage or grid interruption in the system. + +:Reason: + +The aim of the MVS does not cover this scenario. + +:Implications: + +Electricity shortages due to power cuts might happen in real life and the MVS currently omits this scenario. +If a system is self-sufficient but relies on grid-connected PV systems, +the latter stop feeding the load if any power cuts occur +and the battery storage systems might not be enough to serve the load (energy shortage). + +.. _limitations-bidirectional-transformers: + +Need of two transformer assets for of one technical unit +######################################################## + +:Limitation: + +Two transformer objects representing one technical unit in real life are currently unlinked in terms of capacity and attributed costs. + +:Reason: + +The MVS uses oemof-solph's generic components which are unidirectional so for a bidirectional asset, +two transformer objects have to be used. + +:Implications: + +Since one input is only allowed, such technical units are modelled as two separate transformers that are currently unlinked in the MVS +(e.g., hybrid inverter, heat pump, distribution transformer, etc.). +This raises a difficulty to define costs in the input data. +It also results in two optimized capacities for one logical unit. + +This limitation is to be addressed with a constraint which links both capacities of one logical unit, +and therefore solves both the problem to attribute costs and the previously differing capacities. diff --git a/docs/model/outputs/.gitkeep b/docs/model/outputs/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/docs/model/parameters/.gitkeep b/docs/model/parameters/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/docs/MVS_Outputs.rst b/docs/model/simulation_outputs.rst similarity index 93% rename from docs/MVS_Outputs.rst rename to docs/model/simulation_outputs.rst index bee6b9e95..681de2fc4 100644 --- a/docs/MVS_Outputs.rst +++ b/docs/model/simulation_outputs.rst @@ -1,32 +1,20 @@ -============================= -Outputs of the MVS simulation -============================= +======================= +Outputs of a simulation +======================= -System schematic ----------------- -- plot_networkx_graph - -Optimized dispatch ------------------- - -Dispatch of all assets (timeseries) -################################### +KPIs +---- -Energy flows on each bus (graphic) -################################## - -Optimal capacities ------------------- +.. the .inc files describing the kpis are automatically generated in `conf.py` from the `MVS_kpis_list.csv` file +.. TODO: write the `MVS_kpis_list.csv` file, the function to generate the .inc files and add ..include:: for each file Cost data ---------- +######### -.. _net_present_costs: -Net present cost -################ +.. include:: outputs/net_present_costs.inc The Net present cost (NPC) is the present value of all the costs associated with installation, operation, maintenance and replacement of energy technologies comprising the sector-coupled system over the project lifetime, @@ -38,7 +26,7 @@ The capital recovery factor (CRF) is used to calculate the present value of the .. _lcoe: Levelized costs of energy (LCOE) -################################ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ As a sector-coupled system connects energy vectors, not the costs associated to each individual energy carrier but the overall energy costs should be minimized. Therefore, we propose a new KPI: The levelized costs of energy (LCOEnergy) aggregates the costs for energy supply and distributes them over the total energy demand supplied, which is calculated by weighting the energy carriers by their energy content. To determine the weighting factors of the different energy carriers, we reference the method of gasoline gallon equivalent (GGE) [12], which enables the comparison of alternative fuels. Instead of comparing the energy carriers of an MES to gasoline, we rebase the factors introduced in [12] onto the energy carrier electricity, thus proposing a unit Electricity Equivalent (ElEq). The necessary weights are summarized in Table 1. With this, we propose to calculate LCOEnergy based on the annual energy demand and the systems annuity, calculated with the CRF, as follows: @@ -49,7 +37,7 @@ Specific electricity supply costs, eg. levelized costs of electricity (LCOElectr .. _lcoe_asset: Levelized Cost of Energy of Asset (LCOE ASSET) -############################################## +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This KPI measures the cost of generating 1 kWh for each asset in the system. It can be used to assess and compare the available alternative methods of energy production. @@ -81,23 +69,23 @@ For assets in energyConsumption, the MVS outputs 0 for the LCOE ASSET. Technical data --------------- +############## .. _aggregated_flow: Energy flows (aggregated) per asset -################################### +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. _peak_flow: Peak dispatch per asset -####################### +^^^^^^^^^^^^^^^^^^^^^^^ .. _kpi_renewable_share_of_local_generation: Renewable share of local generation (REGen) -########################################### +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The renewable share of local generation describes how much of the energy generated locally is produced from renewable sources. It does not take into account the consumption from energy providers. @@ -146,7 +134,7 @@ This results in: .. _kpi_renewable_factor: Renewable factor (RF) -##################### +^^^^^^^^^^^^^^^^^^^^^ Describes the share of the energy influx to the local energy system that is provided from renewable sources. This includes both local generation as well as consumption from energy providers. @@ -183,7 +171,7 @@ The renewable factor can, just like the :ref:`kpi_renewable_share_of_local_gener .. _emissions: Emissions -######### +^^^^^^^^^ The total emissions of the MES in question are calculated with all aggregated energy flows from the generation assets including energy providers and their subsequent emission factor: @@ -205,7 +193,7 @@ Currently the emissions do not include life cycle emissions of energy conversion .. _kpi_degree_of_sector_coupling: Degree of sector-coupling (DSC) -############################### +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ While a MES includes multiple energy carriers, this fact does not define how strongly interconnected its sectors are. @@ -221,7 +209,7 @@ To measure this, we propose to compare the energy flows in between the sectors t .. _kpi_onsite_energy_fraction: Onsite energy fraction (OEF) -############################ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Onsite energy fraction is also referred to as self-consumption. It describes @@ -242,7 +230,7 @@ the feed into the grid can only be positive. .. _kpi_onsite_energy_matching: Onsite energy matching (OEM) -############################ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The onsite energy matching is also referred to as "self-sufficiency". It describes the fraction of the total demand that can be @@ -265,7 +253,7 @@ or an excess sink. .. _kpi_degree_of_autonomy: Degree of autonomy (DA) -####################### +^^^^^^^^^^^^^^^^^^^^^^^ The degree of autonomy describes the overall energy consumed minus the energy consumed from the grid divided by the overall energy consumed. Adapted from this definition `[3] `__. @@ -278,11 +266,11 @@ As above, we apply a weighting based on Electricity Equivalent. .. _kpi_degree_of_nze: Degree of net zero energy (NZE) -############################### +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The degree of net zero energy describes the ability of an energy system to provide its aggregated annual demand though local sources. For that, the balance between local generation as well as consumption from and feed-in towards the energy provider is compared. In a net zero energy system, demand can be supplied by energy import, but then local energy generation must provide an equally high energy export of energy in the course of the year. In a plus energy system, the export exceeds the import, while local generation can supply all demand (from an aggregated perspective). -To calculate the degree of NZE, the margin between grid feed-in and grid consumption is compared to the overall demand. +To calculate the degree of NZE, the margin between grid feed-in and grid consumption is compared to the overall demand. Some definitions of NZE systems require that the local demand is solely covered by locally generated renewable energy. In MVS this is not the case - all locally generated energy is taken into consideration. For information about the share of renewables in the local energy system checkout :ref:`kpi_renewable_share_of_local_generation`. @@ -296,10 +284,31 @@ As above, we apply a weighting based on Electricity Equivalent. Degree of NZE &= 1 + \frac{(\sum_{i} {E_{grid feedin}(i)} \cdot w_i - E_{grid consumption} (i) \cdot w_i)}{\sum_i {E_{demand, i} \cdot w_i}} + +Suffixes +-------- + +Explain the logic of the suffixes for the output parameters + + +Files +----- +Energy system model graph +######################### +- plot_networkx_graph + +Figures +####### + +- Energy flows on each bus (graphic) +- Optimal Capacities +- Optimized dispatch +- Dispatch of all assets (timeseries) + .. _output_report: Automatic Report ------------------ +################ MVS has a feature to automatically `generate a PDF report `__ that contains the main elements from the input data as well as the simulation results' data. The report can also be viewed as a web app on the browser, which provides some interactivity. @@ -316,3 +325,4 @@ Please, refer to the `report section `__ and it is possible to distinguish them from other tests from the nomination that refers to the names of the source modules (e.g., A0, A1, B0, etc.). The MVS covers so far 80% of the modules and sub-modules as seen in the next figure. + +.. image:: ../images/Test_coverage.png + :width: 200 + +Since those tests are automated, this coverage is updated for any changes in the model. + +Benchmark Tests +############### + +A benchmark is a point of reference against which results are compared to assess the operational validity of a model. Benchmark tests are also automated like unit and integration tests, hence it is necessary to check that they are always passing for any implemented changes in the model. The implemented benchmark tests, which cover several features and functionalities of the MVS, are listed here below. + +* Electricity Grid + PV (`data `__/`pytest `__): Maximum use of PV to serve the demand and the rest is compensated from the grid + +* Electricity Grid + PV + Battery (`data `__/`pytest `__): Reduced excess energy compared to Grid + PV scenario to charge the battery + +* Electricity Grid + Diesel Generator (`data `__/`pytest `__): The diesel generator is only used if its LCOE is less than the grid price + +* Electricity Grid + Battery (`data `__/`pytest `__): The grid is only used to feed the load + +* Electricity Grid + Battery + Peak Demand Pricing (`data `__/`pytest `__): Battery is charged at times of peak demand and used when demand is larger + +* Electricity Grid (Price as Time Series) + Heat Pump + Heat Grid (`data `__/`pytest `__): Heat pump is used when electricity_price/COP is less than the heat grid price + +* Maximum emissions constraint: Grid + PV + Diesel Generator (data: `set 1 `__, `set 2 `__, `set 3 `__/`pytest `__): Emissions are limited by constraint, more PV is installed to reduce emissions. For RE share of 100 % in grid, more electricity from the grid is used + +* Parser converting an energy system model from EPA to MVS (`data `__/`pytest `__) + +* Stratified thermal energy storage (`data `__/`pytest `__): With fixed thermal losses absolute and relative reduced storage capacity only if these losses apply + +* Net zero energy (NZE) constraint: Grid + PV and Grid + PV + Heat Pump (data `set 1 `__, `set 2 `__, `set 3 `__, `set 4 `__/`pytest `__): Degree of NZE >= 1 when constraint is used and degree of NZE < 1 when constraint is not used. + +More tests can still be implemented with regard to: + +* The investment model within the MVS + +* Components with two input sources + +Sensitivity Analysis Tests +########################## + +For sensitivity analysis, the behaviour of the MVS is studied by testing the effect of changing the value of the feed-in tariff (FIT) for a fixed value of an asset's LCOE such that LCOE_ASSET is less than the electricity price. The implemented sensitivity analysis test is shown here below with the resulting graph. More information can be found `here `__ on pages 54-55. + +* Comparing FIT to LCOE_ASSET: Investment in maximum allowed capacity of asset for FIT values larger than LCOE_ASSET + +.. image:: ../images/Sensitivity_1.png + :width: 600 + +The previous graph is not generated by the MVS itself and the results are drawn and interpreted subjectively from it, which points back to the use of graphical displays validation technique with another one simultaneously. This sensitivity analysis test can be translated into a benchmark test so that it becomes automatized. The idea is to check that for every value of FIT greater than LCOE_ASSET, the MVS is investing in the entire allowed maximum capacity of the asset. + +More input-output transformations for sensitivity analyses can be investigated such as: + +* Checking the randomness of supply between the electricity grid and a diesel generator when fuel_price/generator_efficiency is equal to electricity_price/transformer_efficiency + +* Checking if a diesel generator actually replaces the consumption from the grid at times of peak demand--i.e., dispatch_price is less or equal to peak_demand_charge + +Comparison to Other Models +########################## + +So far, the MVS' results for a sector coupled system (electricity + hydrogen) are compared to those of HOMER for the same exact system. This comparison is important to highlight the similarities and differences between the two optimization models. On the electricity side, most of the values are comparable and in the same range. The differences mainly show on the hydrogen part in terms of investment in an electrolyzer capacity (component linking the two sectors) and the values related to that. On another note, both models have different approaches for calculating the value of the levelized cost of a certain energy carrier and therefore the values are apart. Details regarding the comparison drawn between the two models can be found `here `__ on pages 55-63. + +This validation method is commonly used. However, one model cannot absolutely validate another model or claim that one is better than the other. This is why the focus should be on testing the correctness, appropriateness and accuracy of a model vis-à-vis its purpose. Since the MVS is an open source tool, it is important to use a validated model for comparison, but also similar open source tools like urbs and Calliope for instance. The following two articles list some of the models that could be used for comparison to the MVS: `A review of modelling tools for energy and electricity systems with large shares of variable renewables `__ and `Power-to-heat for renewable energy integration: A review of technologies, modeling approaches, and flexibility potentials `__. + + +.. _verification-tests: + +Automatic output verification +############################# + +There is a suite of functions within the MVS codebase module E4_verification.py that run a few checks on some of the outputs of the simulation in order to make sure that the results are meaningful and if something like an excessive excess energy flow is noteworthy. These are valuable tests that act as a safeguard for the user, as the model is not only validated for benchmark tests but for every run simulation. +The following is the list of functions in E4_verification.py that carry out the verification tests: + +* detect_excessive_excess_generation_in_bus +* maximum_emissions_test +* minimal_renewable_share_test +* verify_state_of_charge + +The first test serves as an alert to the energy system modeler to check their inputs again, whereas if there are any errors raised within the other functions, it is an indication of something seriously wrong. + +detect_excessive_excess_generation_in_bus +========================================= + +This test is here to notify to the modeler in case there is an excess generation within a bus in the energy system. Precisely, the modeler is given a heads-up when the ratio of total outflows to total inflows for one or more buses is less than 0.9 + +maximum_emissions_test +====================== + +Other than renewables, source components in the energy system have a certain emissions value associated with the generation of energy. The user is able to apply a constraint on the maximum allowed emissions in the energy mix of the output energy system. This function runs a verification test on the output energy system data to determine if the user-supplied constraint on maximum emissions is correctly applied or not. If not, then the modeler is notified. + +minimal_renewable_share_test +============================ + +This test is carried out on the energy system model after optimization of its capacities. It verifies whether the user-provided constraint for the minimal share of renewables in the energy mix of the optimized system was respected or not. In case this lower bound constraint is not met, the user is notified. + +verify_state_of_charge +====================== + +This test is intended to check the time-series of the state of charge values for storages in the energy system simulation results to notify of a serious error in case, the SoC value at any time-step is not between 0 and 1, which is physically not feasible. diff --git a/docs/readthedocs.yml b/docs/readthedocs.yml deleted file mode 100644 index 677a0ceb7..000000000 --- a/docs/readthedocs.yml +++ /dev/null @@ -1,23 +0,0 @@ -# .readthedocs.yml -# Read the Docs configuration file -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details - -# Required -version: 2 - -# Build documentation in the docs/ directory with Sphinx -sphinx: - configuration: docs/conf.py - -# Build documentation with MkDocs -#mkdocs: -# configuration: mkdocs.yml - -# Optionally build your docs in additional formats such as PDF and ePub -formats: all - -# Optionally set the version of Python and requirements required to build your docs -python: - version: 3.7 - install: - - requirements: docs/readthedocs_requirements.txt \ No newline at end of file diff --git a/docs/references/bug_report.rst b/docs/references/bug_report.rst new file mode 100644 index 000000000..15f58ce3f --- /dev/null +++ b/docs/references/bug_report.rst @@ -0,0 +1,7 @@ +========== +Bug report +========== + +Have a look at :ref:`troubleshooting` section. + +Please submit your bug reports via our `github issues `__ \ No newline at end of file diff --git a/docs/references/citations.rst b/docs/references/citations.rst new file mode 100644 index 000000000..a16e48881 --- /dev/null +++ b/docs/references/citations.rst @@ -0,0 +1,11 @@ +======== +Cite MVS +======== + +If you use the mvs, please site as + +.. + + Hoffmann, Martha Marie, Duc, Pierre-Francois, & Haas, Sabine. (2021, March 4). Multi-Vector Simulator (Version v0.5.5, beta release). Zenodo. http://doi.org/10.5281/zenodo.4610237 + +in your references \ No newline at end of file diff --git a/docs/Code.rst b/docs/references/code.rst similarity index 97% rename from docs/Code.rst rename to docs/references/code.rst index fecf8d2b6..482c9d157 100644 --- a/docs/Code.rst +++ b/docs/references/code.rst @@ -2,6 +2,8 @@ Code documentation ================== +TODO : add an explanation about the different modules + Util functions -------------- @@ -23,7 +25,7 @@ Initialization .. automodule:: multi_vector_simulator.A1_csv_to_json :members: :undoc-members: - + Data input ---------- diff --git a/docs/Developing.rst b/docs/references/contributing.rst similarity index 81% rename from docs/Developing.rst rename to docs/references/contributing.rst index 1875c8a68..6803dc932 100644 --- a/docs/Developing.rst +++ b/docs/references/contributing.rst @@ -4,13 +4,13 @@ Contributing to MVS Proposed workflow ----------------- -The workflow is described in the `CONTRIBUTING.md file `__ in the repository. +The workflow is described in the `CONTRIBUTING.md `__ file in the repository. Unit tests (pytests) -------------------- -When developing code for the MVS please make sure that you always also develop test in `tests`. We integrate those unit tests with `pytest`. +When developing code for the MVS please make sure that you always also develop test in `tests`. We integrate those unit tests with `pytest`. Make sure that your tests are as lightweight as possible - this means that you do not always have to run the whole code to test for one feature, but can test a function with a standalone tests. Please refer to the other tests that have already been introduced. Always aim for the test coverage button on `the main page of the github repository `__ to reach 100%! @@ -32,7 +32,7 @@ All functions in the code will be automatically documented via their docstrings. Here is how to set that in pycharm -.. image:: _static/docstring-setting.png +.. image:: ../_static/docstring-setting.png :width: 600 :alt: pycharm docstring's format setting @@ -41,9 +41,9 @@ Format of Docstrings -------------------- Please add docstrings for every function you add. As docstrings are a powerful means of documentation we give an example here: -Download: :download:`Example docstring ` +Download: :download:`Example docstring <../files_to_be_displayed/example_docstring.py>` -.. literalinclude:: files_to_be_displayed/example_docstring.py +.. literalinclude:: ../files_to_be_displayed/example_docstring.py :language: python diff --git a/docs/references/license.rst b/docs/references/license.rst new file mode 100644 index 000000000..cd7a46c08 --- /dev/null +++ b/docs/references/license.rst @@ -0,0 +1,5 @@ +======= +License +======= + +The MVS is licensed with the **GNU General Public License v2.0**. The GNU GPL is the most widely used free software license and has a strong copyleft requirement. When distributing derived works, the source code of the work must be made available under the same license. There are multiple variants of the GNU GPL, each with different requirements. diff --git a/docs/references/publications.rst b/docs/references/publications.rst new file mode 100644 index 000000000..51678d406 --- /dev/null +++ b/docs/references/publications.rst @@ -0,0 +1,34 @@ +============ +Publications +============ + +The MVS is currently under development in the H2020 research project `E-Land`. Still, there are already some references where additional information can be found regarding its intention, application, and method. + +* Research project website: `E-LAND Horizon 2020. Novel solutions for decarbonized energy islands `__ + +Article +------- + +* Martha M. Hoffmann, Sanket Puranik, Marc Juanpera, José M. Martín-Rapún, Heidi Tuiskula, & Philipp Blechinger. (2020). *Investment planning in multi-vector energy systems: Definition of key performance indicators.* Presented at the CIRED 2020 Berlin Workshop (CIRED 2020), Berlin / online: Zenodo. http://doi.org/10.5281/zenodo.4449918 + +Poster +------ + +* Martha M. Hoffmann, Sanket Puranik, Marc Juanpera, José M. Martín-Rapún, Heidi Tuiskula, & Philipp Blechinger. (2020). *Investment planning in multi-vector energy systems: Definition of key performance indicators.* Presented at the CIRED 2020 Berlin Workshop (CIRED 2020), Berlin / online: Zenodo. http://doi.org/10.5281/zenodo.4449969 + +Projects using MVS +------------------ + +master thesis +############# + +Andra Backhaus is using the MVS to simulate different energy systems and compare them to each other. He uses the MVS to see how energy systems planned on different levels influence the consumption and feedin on the national electricity grid. His research on "Analyzing the application of different energy cell sizes as an approach for the integration of decentralized renewable energy sources" is done in the context of the master Renewable Energy Engineering and Management at Albert-Ludwigs Universität Freiburg. + +pvcompare +######### + + +- `_pvcompare_ `__ is a model for comparing the benefits of different PV technologies in local energy systems in different energy supply scenarios. It uses MVS for optimizing these energy systems and calculating specific KPIs. +- Functionalities of _pvcompare_ include among others the calculation of an area potential for PV on roof-tops and facades, heat and electricity demand profiles, PV feed-in time series for different technologies, temperature dependent COPs for heat pumps and pre-calculations for a stratified thermal storage. +- _pvcompare_ concentrates on the integration of PV technologies into local energy systems but could easily be enhanced to analyze other conversion technologies. +- Checkout the `documentation `__ to learn more about _pvcompare_. diff --git a/docs/references/release_notes.rst b/docs/references/release_notes.rst new file mode 100644 index 000000000..d75b38f33 --- /dev/null +++ b/docs/references/release_notes.rst @@ -0,0 +1,5 @@ +============= +Release Notes +============= + +TBD (adapt the changelog) \ No newline at end of file diff --git a/docs/troubleshooting.rst b/docs/references/troubleshooting.rst similarity index 96% rename from docs/troubleshooting.rst rename to docs/references/troubleshooting.rst index 35289d7c5..9a40e0716 100644 --- a/docs/troubleshooting.rst +++ b/docs/references/troubleshooting.rst @@ -1,3 +1,5 @@ +.. _troubleshooting: + =============== Troubleshooting =============== @@ -8,16 +10,16 @@ Installation Python package "pygraphviz" ########################### -The installation of pygraphviz can cause errors. -You can circumvent this issue by setting the *simulation_setting* *plot_nx_graph* to False. +The installation of pygraphviz can cause errors. +You can circumvent this issue by setting the *simulation_setting* *plot_nx_graph* to False. If you need to plot the network graphs (set parameter *plot_nx_graph* to True) or run all pytests, check if we already have a solution for your OS/distribution: -**Ubuntu 18.4**: +**Ubuntu 18.4**: Pygraphviz could not be installed with pip. Solution: sudo apt-get install python3-dev graphviz libgraphviz-dev pkg-config - + pip install pygraphviz **Windows 10** @@ -64,9 +66,9 @@ pyppeteer ########## If you are using OS X, you might need to install this package separately with conda using: - + `conda install -c conda-forge pyppeteer` - + or `conda install -c conda-forge/label/cf202003 pyppeteer` @@ -76,7 +78,7 @@ More information is available on `their website `__: Defines the `energy_price` (`file `__) of an energy provider as a time series - -* `Second example `__: Defines the `energy_price` (`file `__) of an energy provider and the efficiency of a diesel generator (`file `__) as a time series. - - -Using multiple in- or output busses -################################### - -Sometimes, you may also want to have multiple input- our output busses connected to a component. -This is for example the case if you want to implement an electrolyzer with a transformer, -and want to track water consumption at the same time as you want to track electricity consumption. - -You can define this, again, in the csv´s. -Here, you would insert a list of your parameters instead of the scalar value of a parameter: - - [0.99, 0.98] - -Would be an example of a transformer with two efficiencies. - -You can also wrap multiple inputs/outputs with scalars that are defined as efficiencies. -For that, you define one or multiple of the parameters within the list with the above introduced dictionary: - - [0.99, {'value': {'file_name': 'your_file_name.csv', 'header': 'your_header'}, 'unit': 'your_unit'}] - -If you define an output- or input flow with with a list, -you also have to define related parameters as a list. -So, for example, if you define the input direction as a list for an energyConsumption asset, -you need to define the efficiencies and dispatch_price costs as a list as well. - -You can see an implemented example here, where the heat pump has a time-dependent efficiency: - -.. csv-table:: Example for defining a component with multiple inputs/outputs - :file: files_to_be_displayed/example_multiple_inputs_energyConversion.csv - :widths: 70, 30, 50 - :header-rows: 1 - -The features were integrated with `Pull Request #63 `__. -For more information, you might also reference following issues: - -- Parameters can now be a list of values, eg. efficiencies for two busses or multiple input/output vectors(`Issue #52 `__) - -- Parameters can now be defined as a list as well as as a timeseries (`Issue #52 `__, `Issue #82 `__) +The MVS does neither perform a logical check, nor does it transform units, eg. from MWh to kWh.** \ No newline at end of file diff --git a/src/multi_vector_simulator/E3_indicator_calculation.py b/src/multi_vector_simulator/E3_indicator_calculation.py index a7157b602..c24ef6038 100644 --- a/src/multi_vector_simulator/E3_indicator_calculation.py +++ b/src/multi_vector_simulator/E3_indicator_calculation.py @@ -550,7 +550,7 @@ def add_degree_of_autonomy(dict_values): def equation_degree_of_autonomy(total_consumption_from_energy_provider, total_demand): - """ + r""" Calculates the degree of autonomy (DA). The degree of autonomy describes the relation of how much demand is supplied by local generation (as opposed to @@ -635,7 +635,7 @@ def add_degree_of_net_zero_energy(dict_values): def equation_degree_of_net_zero_energy( total_feedin, total_grid_consumption, total_demand ): - """ + r""" Calculates the degree of net zero energy (NZE). In NZE systems import and export of energy is allowed while the balance over one @@ -736,7 +736,7 @@ def add_degree_of_sector_coupling(dict_values): def equation_degree_of_sector_coupling( total_flow_of_energy_conversion_equivalent, total_demand_equivalent ): - """Calculates degree of sector coupling. + r"""Calculates degree of sector coupling. Parameters ---------- @@ -752,7 +752,7 @@ def equation_degree_of_sector_coupling( Degree of sector coupling based on conversion flows and energy demands in electricity equivalent. .. math:: - DSC=\frac{\sum_{i,j}{E_{conversion} (i,j)⋅w_i}}{\sum_i {E_{demand} (i)⋅w_i}} + DSC=\frac{\sum_{i,j}{E_{conversion} (i,j) \cdot w_i}}{\sum_i {E_{demand} (i) \cdot w_i}} with i,j \epsilon [Electricity,H2…] @@ -980,7 +980,7 @@ def add_onsite_energy_matching(dict_values): def equation_onsite_energy_matching( total_generation, total_feedin, total_excess, total_demand ): - """ + r""" Calculates onsite energy matching (OEM), i.e. self-sufficiency. OEM describes the fraction of the total demand that can be