Skip to content

Commit

Permalink
Merge pull request #965 from rl-institut/feature/upgrade-oemof-0_5_1
Browse files Browse the repository at this point in the history
Upgrade oemof to 0.5.1
  • Loading branch information
Bachibouzouk authored Apr 27, 2024
2 parents b6b3a16 + 1324ee1 commit 3e19405
Show file tree
Hide file tree
Showing 27 changed files with 485 additions and 345 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Here is a template for new release sections
- Now oemof-solph ExtractionTurbine CHP component can be simulated (only tested from the json input) (#952)
- The heat pump and chp components can now be simulated with MVS although no explicit support/documentation is present for running from the command line (#954)
- Saving the raw oemof result in a pandas Dataframe with multi index (#958)
- Raise error for wrongly formatted emission factor (#965)

### Changed
- `F0_output.parse_simulation_log`, so that `SIMULATION_RESULTS` are not overwritten anymore (#901)
Expand All @@ -60,6 +61,7 @@ Here is a template for new release sections
- The user can choose on which bus the investment will take place (useful for transformers with 2 inputs and 1 outputs or 1 input and 2 outputs) (#954)
- energy_price and feedin of DSO (providers) can be provided as timeseries (#954)
- The peak-demand pricing cost is applied to the consumption of DSO only (before was split between consumption and feedin) (#958)
- Upgrade to `oemof-solph==0.5.1` (#965)

### Removed
- Input timeseries is now not returned to epa in `utils.data_parser.py` (#936)
Expand All @@ -73,6 +75,7 @@ Here is a template for new release sections
- Add missing file for test `test_F0_output.TestLogCreation.test_parse_simulation_log` (#937)
- Transformers can have multiple input or output busses (tested in `tests/test_D1_model_components` by `test_transformer_optimize_cap_multiple_output_busses_multiple_inst_cap`, `test_transformer_optimize_cap_multiple_output_busses_multiple_max_add_cap`, `test_transformer_fix_cap_multiple_output_busses_multiple_inst_cap` and in `tests/test_benchmark_special_features` by `test_benchmark_feature_parameters_as_timeseries_multiple_inputs`)(#949)
- The constraints are not all set to default values if only one constraint is missing, only the missing constraint is set to default value (#953)
- If the age of an asset is such that it should be replaced on the project's last year, we do not take it into account as the resell price would be deduced anyway (#965)

## [1.0.0] - 2021-05-31

Expand Down
5 changes: 1 addition & 4 deletions requirements/default.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
oemof.solph==0.4.4
pandas>=0.24.0,!=1.1.0,!=1.1.1,!=1.1.2
pyomo!=5.7.3,!=6.0 # version 5.7.3 and 6.0 make mvs very slow
graphviz>=0.14.1
plotly
psutil
kaleido>=0.0.2
openpyxl>=3.0.5
xlrd==1.2.0
numpy>=1.21.0
oemof.solph==0.5.1
2 changes: 1 addition & 1 deletion src/multi_vector_simulator/A0_initialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ def process_user_arguments(
logger.define_logging(
logpath=path_output_folder,
logfile=LOGFILE,
file_level=logging.DEBUG,
file_level=logging.INFO,
screen_level=screen_level,
)

Expand Down
1 change: 1 addition & 0 deletions src/multi_vector_simulator/A1_csv_to_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ def create_json_from_csv(
sep=CSV_SEPARATORS[idx],
header=0,
index_col=0,
na_filter=False,
)

if len(df.columns) > 0:
Expand Down
4 changes: 4 additions & 0 deletions src/multi_vector_simulator/C1_verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,10 @@ def check_emission_factor_of_providers(dict_values):
"""
for key, asset in dict_values[ENERGY_PROVIDERS].items():
if isinstance(asset[EMISSION_FACTOR][VALUE], str):
raise TypeError(
f"The emission factor of the provider asset {asset[LABEL]} is a string, this is likely due to a missing value in the csv input file 'energyProviders.csv', please check your input file for missing values or typos"
)
if asset[EMISSION_FACTOR][VALUE] > 0 and asset[RENEWABLE_SHARE_DSO][VALUE] == 1:
logging.warning(
f"The renewable share of provider {key} is {asset[RENEWABLE_SHARE_DSO][VALUE] * 100} % while its emission_factor is >0. Check if this is what you intended to define."
Expand Down
46 changes: 30 additions & 16 deletions src/multi_vector_simulator/C2_economic_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,12 @@ def annuity_factor(project_life, discount_factor):
discountfactor \cdot (1 + discount factor)^{project life}}
"""
annuity_factor = 1 / discount_factor - 1 / (
discount_factor * (1 + discount_factor) ** project_life
)
if discount_factor != 0:
annuity_factor = 1 / discount_factor - 1 / (
discount_factor * (1 + discount_factor) ** project_life
)
else:
annuity_factor = project_life
return annuity_factor


Expand All @@ -71,9 +74,13 @@ def crf(project_life, discount_factor):
:param discount_factor: weighted average cost of capital, which is the after-tax average cost of various capital sources
:return: capital recovery factor, a ratio used to calculate the present value of an annuity
"""
crf = (discount_factor * (1 + discount_factor) ** project_life) / (
(1 + discount_factor) ** project_life - 1
)
if discount_factor != 0:
crf = (discount_factor * (1 + discount_factor) ** project_life) / (
(1 + discount_factor) ** project_life - 1
)
else:
crf = 1 / project_life

return crf


Expand Down Expand Up @@ -201,12 +208,11 @@ def get_replacement_costs(
)

replacement_costs = 0

# Latest investment is first investment
latest_investment = first_time_investment
# Starting from first investment (in the past for installed capacities)
year = -age_of_asset
if abs(year) >= asset_lifetime:
if abs(year) > asset_lifetime:
logging.error(
f"The age of the asset `{asset_label}` ({age_of_asset} years) is lower or equal than "
f"the asset lifetime ({asset_lifetime} years). This does not make sense, as a "
Expand All @@ -222,16 +228,24 @@ def get_replacement_costs(
for count_of_replacements in range(1, number_of_investments):
# replacements taking place after an asset ends its lifetime
year += asset_lifetime

# Update latest_investment (to be used for residual value)
latest_investment = first_time_investment / ((1 + discount_factor) ** (year))
# Add latest investment to replacement costs
replacement_costs += latest_investment
# Update cash flow projection (specific)
present_value_of_capital_expenditures.loc[year] = latest_investment
if year < project_lifetime:
# Update latest_investment (to be used for residual value)
latest_investment = first_time_investment / (
(1 + discount_factor) ** (year)
)
# Add latest investment to replacement costs
replacement_costs += latest_investment
# Update cash flow projection (specific)
present_value_of_capital_expenditures.loc[year] = latest_investment
elif year == project_lifetime:
logging.warning(
f"No asset `{asset_label}` replacement costs are computed for the project's "
f"last year as the asset reach its end-of-life exactly on that year"
)

# Calculation of residual value / value at project end
year += asset_lifetime
if year != project_lifetime:
year += asset_lifetime
if year > project_lifetime:
# the residual of the capex at the end of the simulation time takes into
linear_depreciation_last_investment = latest_investment / asset_lifetime
Expand Down
7 changes: 4 additions & 3 deletions src/multi_vector_simulator/D0_modelling_and_optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
import timeit
import warnings

from oemof.solph import processing, network
import oemof.solph as solph
from oemof.solph import processing
from oemof import solph

import multi_vector_simulator.D1_model_components as D1
import multi_vector_simulator.D2_model_constraints as D2
Expand Down Expand Up @@ -142,7 +142,8 @@ def initialize(dict_values):
"""
logging.info("Initializing oemof simulation.")
model = solph.EnergySystem(
timeindex=dict_values[SIMULATION_SETTINGS][TIME_INDEX]
timeindex=dict_values[SIMULATION_SETTINGS][TIME_INDEX],
infer_last_interval=True,
)

# this dictionary will include all generated oemof objects
Expand Down
Loading

0 comments on commit 3e19405

Please sign in to comment.