From c95ea56f163adc9eca3dd0e637d7de4733e96952 Mon Sep 17 00:00:00 2001 From: Bachibouzouk Date: Thu, 4 Mar 2021 14:58:10 +0100 Subject: [PATCH 1/3] Move process_fixcost to E0 instead of E1 to avoid cicular import --- .../C0_data_processing.py | 1 - src/multi_vector_simulator/E0_evaluation.py | 47 ++++++++++++++++++- .../E1_process_results.py | 47 ------------------- 3 files changed, 46 insertions(+), 49 deletions(-) diff --git a/src/multi_vector_simulator/C0_data_processing.py b/src/multi_vector_simulator/C0_data_processing.py index 6e093d42b..b7725f53a 100644 --- a/src/multi_vector_simulator/C0_data_processing.py +++ b/src/multi_vector_simulator/C0_data_processing.py @@ -44,7 +44,6 @@ import multi_vector_simulator.B0_data_input_json as B0 import multi_vector_simulator.C1_verification as C1 import multi_vector_simulator.C2_economic_functions as C2 -import multi_vector_simulator.F0_output as F0 def all(dict_values): diff --git a/src/multi_vector_simulator/E0_evaluation.py b/src/multi_vector_simulator/E0_evaluation.py index b8c303997..355a15ba2 100644 --- a/src/multi_vector_simulator/E0_evaluation.py +++ b/src/multi_vector_simulator/E0_evaluation.py @@ -176,7 +176,7 @@ def evaluate_dict(dict_values, results_main, results_meta): store_result_matrix(dict_values[KPI], dict_values[group][asset]) # Add fix project costs - E1.process_fixcost(dict_values) + process_fixcost(dict_values) logging.info("Evaluating key performance indicators of the system") E3.all_totals(dict_values) @@ -293,3 +293,48 @@ def initalize_kpi(dict_values): } } ) + + +def process_fixcost(dict_values): + r""" + Adds fix costs of the project to the economic evaluation of the energy system. + + Parameters + ---------- + dict_values: dict + All simulation data with inputs and results of the assets + + Returns + ------- + Updated dict_values with costs attributed in dict values also appended to the dict_values[KPI] (scalar results) + + Notes + ----- + + Function is tested with: + - test_E0_evaluation.test_process_fixcost() + """ + for asset in dict_values[FIX_COST]: + # Add parameters that are needed for E2.get_costs() + dict_values[FIX_COST][asset].update( + { + OPTIMIZED_ADD_CAP: {VALUE: 1}, + INSTALLED_CAP: {VALUE: 0}, + LIFETIME_PRICE_DISPATCH: {VALUE: 0}, + FLOW: pd.Series([0, 0]), + } + ) + + E2.get_costs(dict_values[FIX_COST][asset], dict_values[ECONOMIC_DATA]) + # Remove all parameters that were added before and the KPI that do not apply + for key in [ + OPTIMIZED_ADD_CAP, + LIFETIME_PRICE_DISPATCH, + INSTALLED_CAP, + FLOW, + COST_DISPATCH, + ]: + dict_values[FIX_COST][asset].pop(key) + store_result_matrix( + dict_values[KPI], dict_values[FIX_COST][asset], fix_cost=True + ) diff --git a/src/multi_vector_simulator/E1_process_results.py b/src/multi_vector_simulator/E1_process_results.py index 138f7e3d1..75a5fbc5d 100644 --- a/src/multi_vector_simulator/E1_process_results.py +++ b/src/multi_vector_simulator/E1_process_results.py @@ -71,8 +71,6 @@ LIFETIME_PRICE_DISPATCH, ) -from multi_vector_simulator.E0_evaluation import store_result_matrix -import multi_vector_simulator.E2_economics as E2 # Determines which assets are defined by... # a influx from a bus @@ -1095,48 +1093,3 @@ def get_units_of_cost_matrix_entries(dict_economic, kpi_list): else: unit_list.append(kpi_cost_unit_dict[key]) return unit_list - - -def process_fixcost(dict_values): - r""" - Adds fix costs of the project to the economic evaluation of the energy system. - - Parameters - ---------- - dict_values: dict - All simulation data with inputs and results of the assets - - Returns - ------- - Updated dict_values with costs attributed in dict values also appended to the dict_values[KPI] (scalar results) - - Notes - ----- - - Function is tested with: - - test_E1_process_results.test_process_fixcost() - """ - for asset in dict_values[FIX_COST]: - # Add parameters that are needed for E2.get_costs() - dict_values[FIX_COST][asset].update( - { - OPTIMIZED_ADD_CAP: {VALUE: 1}, - INSTALLED_CAP: {VALUE: 0}, - LIFETIME_PRICE_DISPATCH: {VALUE: 0}, - FLOW: pd.Series([0, 0]), - } - ) - - E2.get_costs(dict_values[FIX_COST][asset], dict_values[ECONOMIC_DATA]) - # Remove all parameters that were added before and the KPI that do not apply - for key in [ - OPTIMIZED_ADD_CAP, - LIFETIME_PRICE_DISPATCH, - INSTALLED_CAP, - FLOW, - COST_DISPATCH, - ]: - dict_values[FIX_COST][asset].pop(key) - store_result_matrix( - dict_values[KPI], dict_values[FIX_COST][asset], fix_cost=True - ) From 4b0acbeb57e0cb30eaa7d0002aa7f853803e9875 Mon Sep 17 00:00:00 2001 From: Bachibouzouk Date: Thu, 4 Mar 2021 14:58:18 +0100 Subject: [PATCH 2/3] Adapt tests --- tests/test_E0_evaluation.py | 73 ++++++++++++++++++++++++++++---- tests/test_E1_process_results.py | 64 ---------------------------- 2 files changed, 64 insertions(+), 73 deletions(-) diff --git a/tests/test_E0_evaluation.py b/tests/test_E0_evaluation.py index 5e170d663..19b118088 100644 --- a/tests/test_E0_evaluation.py +++ b/tests/test_E0_evaluation.py @@ -5,6 +5,7 @@ import mock import pandas as pd +import numpy as np import multi_vector_simulator.A0_initialization as A0 import multi_vector_simulator.B0_data_input_json as B0 @@ -14,15 +15,8 @@ from multi_vector_simulator.utils.constants import OUTPUT_FOLDER -from multi_vector_simulator.utils.constants_json_strings import ( - VALUE, - KPI, - KPI_SCALARS, - KPI_COST_MATRIX, - KPI_SCALAR_MATRIX, - KPI_SCALARS_DICT, - OPTIMIZED_FLOWS, -) +from multi_vector_simulator.utils.constants_json_strings import * + from _constants import ( TEST_REPO_PATH, INPUT_FOLDER, @@ -142,6 +136,67 @@ def test_evaluate_check_dict_fields_in_output_dict_under_kpi_scalar_fields(): # assert k in KPI_SCALARS +def test_process_fixcost(): + economic_data = { + PROJECT_DURATION: {VALUE: 20}, + ANNUITY_FACTOR: {VALUE: 1}, + CRF: {VALUE: 1}, + DISCOUNTFACTOR: {VALUE: 0}, + TAX: {VALUE: 0}, + CURR: CURR, + } + fix_cost_entry = "one entry" + dict_test = { + ECONOMIC_DATA: economic_data, + SIMULATION_SETTINGS: {EVALUATED_PERIOD: {VALUE: 365, UNIT: "Days"}}, + FIX_COST: { + fix_cost_entry: { + LABEL: fix_cost_entry, + SPECIFIC_COSTS_OM: {VALUE: 1, UNIT: CURR}, + SPECIFIC_COSTS: {VALUE: 1, UNIT: CURR}, + DEVELOPMENT_COSTS: {VALUE: 1, UNIT: CURR}, + LIFETIME: {VALUE: 20}, + AGE_INSTALLED: {VALUE: 0}, + LIFETIME_SPECIFIC_COST: {VALUE: 1, UNIT: CURR}, + LIFETIME_SPECIFIC_COST_OM: {VALUE: 1, UNIT: CURR}, + ANNUITY_SPECIFIC_INVESTMENT_AND_OM: {VALUE: 1, UNIT: CURR}, + SIMULATION_ANNUITY: {VALUE: 1, UNIT: CURR}, + SPECIFIC_REPLACEMENT_COSTS_INSTALLED: {VALUE: 1, UNIT: CURR}, + SPECIFIC_REPLACEMENT_COSTS_OPTIMIZED: {VALUE: 1, UNIT: CURR}, + } + }, + } + E0.initalize_kpi(dict_test) + E0.process_fixcost(dict_test) + assert ( + fix_cost_entry in dict_test[KPI][KPI_COST_MATRIX][LABEL].values + ), f"The fix cost entry `{fix_cost_entry}` is not added to the cost matrix ({KPI_COST_MATRIX})." + for k in [ + COST_TOTAL, + COST_OPERATIONAL_TOTAL, + COST_INVESTMENT, + COST_UPFRONT, + COST_REPLACEMENT, + COST_OM, + ANNUITY_TOTAL, + ANNUITY_OM, + ]: + assert isinstance(dict_test[KPI][KPI_COST_MATRIX][k][0], float) or isinstance( + dict_test[KPI][KPI_COST_MATRIX][k][0], int + ), f"A float or int should be added for fix cost entry `{fix_cost_entry}` and its KPI `{k}`." + for k in [ + COST_DISPATCH, + LCOE_ASSET, + ]: + assert np.isnan( + dict_test[KPI][KPI_COST_MATRIX][k][0] + ), f"No value should be added for fix cost entry `{fix_cost_entry}` and KPI `{k}`, but value {dict_test[KPI][KPI_COST_MATRIX][k][fix_cost_entry]} is attributed." + + assert ( + fix_cost_entry not in dict_test[KPI][KPI_SCALAR_MATRIX][LABEL].values + ), f"No line should be added for the fix cost entry `{fix_cost_entry}` to the scalar matrix ({KPI_SCALAR_MATRIX})." + + def teardown_module(): # Remove the output folder if os.path.exists(TEST_OUTPUT_PATH): diff --git a/tests/test_E1_process_results.py b/tests/test_E1_process_results.py index 4bf344194..145c93593 100644 --- a/tests/test_E1_process_results.py +++ b/tests/test_E1_process_results.py @@ -14,8 +14,6 @@ import multi_vector_simulator.D0_modelling_and_optimization as D0 import multi_vector_simulator.E1_process_results as E1 -from multi_vector_simulator.E0_evaluation import initalize_kpi - from multi_vector_simulator.utils.constants import OUTPUT_FOLDER, CSV_EXT from multi_vector_simulator.utils.constants_json_strings import * @@ -27,7 +25,6 @@ PATH_INPUT_FOLDER, PATH_OUTPUT_FOLDER, TEST_INPUT_DIRECTORY, - # JSON_PATH, CSV_ELEMENTS, ) @@ -309,67 +306,6 @@ def test_cut_below_micro_pd_Series_larger_0_smaller_threshold(caplog): ).all(), f"One value in pd.Series is below 0 but smaller then the threshold, its value should be changed to zero (but it is {result})." -def test_process_fixcost(): - economic_data = { - PROJECT_DURATION: {VALUE: 20}, - ANNUITY_FACTOR: {VALUE: 1}, - CRF: {VALUE: 1}, - DISCOUNTFACTOR: {VALUE: 0}, - TAX: {VALUE: 0}, - CURR: CURR, - } - fix_cost_entry = "one entry" - dict_test = { - ECONOMIC_DATA: economic_data, - SIMULATION_SETTINGS: {EVALUATED_PERIOD: {VALUE: 365, UNIT: "Days"}}, - FIX_COST: { - fix_cost_entry: { - LABEL: fix_cost_entry, - SPECIFIC_COSTS_OM: {VALUE: 1, UNIT: CURR}, - SPECIFIC_COSTS: {VALUE: 1, UNIT: CURR}, - DEVELOPMENT_COSTS: {VALUE: 1, UNIT: CURR}, - LIFETIME: {VALUE: 20}, - AGE_INSTALLED: {VALUE: 0}, - LIFETIME_SPECIFIC_COST: {VALUE: 1, UNIT: CURR}, - LIFETIME_SPECIFIC_COST_OM: {VALUE: 1, UNIT: CURR}, - ANNUITY_SPECIFIC_INVESTMENT_AND_OM: {VALUE: 1, UNIT: CURR}, - SIMULATION_ANNUITY: {VALUE: 1, UNIT: CURR}, - SPECIFIC_REPLACEMENT_COSTS_INSTALLED: {VALUE: 1, UNIT: CURR}, - SPECIFIC_REPLACEMENT_COSTS_OPTIMIZED: {VALUE: 1, UNIT: CURR}, - } - }, - } - initalize_kpi(dict_test) - E1.process_fixcost(dict_test) - assert ( - fix_cost_entry in dict_test[KPI][KPI_COST_MATRIX][LABEL].values - ), f"The fix cost entry `{fix_cost_entry}` is not added to the cost matrix ({KPI_COST_MATRIX})." - for k in [ - COST_TOTAL, - COST_OPERATIONAL_TOTAL, - COST_INVESTMENT, - COST_UPFRONT, - COST_REPLACEMENT, - COST_OM, - ANNUITY_TOTAL, - ANNUITY_OM, - ]: - assert isinstance(dict_test[KPI][KPI_COST_MATRIX][k][0], float) or isinstance( - dict_test[KPI][KPI_COST_MATRIX][k][0], int - ), f"A float or int should be added for fix cost entry `{fix_cost_entry}` and its KPI `{k}`." - for k in [ - COST_DISPATCH, - LCOE_ASSET, - ]: - assert np.isnan( - dict_test[KPI][KPI_COST_MATRIX][k][0] - ), f"No value should be added for fix cost entry `{fix_cost_entry}` and KPI `{k}`, but value {dict_test[KPI][KPI_COST_MATRIX][k][fix_cost_entry]} is attributed." - - assert ( - fix_cost_entry not in dict_test[KPI][KPI_SCALAR_MATRIX][LABEL].values - ), f"No line should be added for the fix cost entry `{fix_cost_entry}` to the scalar matrix ({KPI_SCALAR_MATRIX})." - - """ def test_get_optimal_cap_optimize_input_flow_timeseries_peak_provided(): pass From 2a0cf56b2cb38c425878157109fcdd40b0b99fcb Mon Sep 17 00:00:00 2001 From: Bachibouzouk Date: Thu, 4 Mar 2021 15:02:26 +0100 Subject: [PATCH 3/3] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e3b1442e..853337971 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -119,6 +119,7 @@ Here is a template for new release sections - Fix: `ENERGY_PROVIDER` assets are missing parameter `DISPATCHABILITY` when parsed from EPA to MVS (#810) - Fix: No `DISPATCHABILITY` parameter for `ENERGY_PRODUCTION` assets in EPA (#810) - Fix: Default value of `MAXIMUM_EMISSIONS` when parsing from EPA (#810) +- Move `process_fixcost` from `E1` to `E0` to avoid circular imports (#820) ## [0.5.4] - 2020-12-18