Skip to content

Commit

Permalink
Fixes in costs calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
birgits committed Apr 24, 2024
1 parent 3983c49 commit be09833
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 20 deletions.
104 changes: 94 additions & 10 deletions edisgo/flex_opt/costs.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
import os

import pandas as pd
Expand All @@ -7,6 +8,8 @@

from edisgo.tools.geo import proj2equidistant

logger = logging.getLogger(__name__)


def grid_expansion_costs(edisgo_obj, without_generator_import=False):
"""
Expand Down Expand Up @@ -67,7 +70,8 @@ def _get_transformer_costs(trafos):
costs_trafos = pd.DataFrame(
{
"costs_transformers": len(hvmv_trafos)
* [float(edisgo_obj.config["costs_transformers"]["mv"])]
* [float(edisgo_obj.config["costs_transformers"]["mv"])],
"voltage_level": len(hvmv_trafos) * ["hv/mv"],
},
index=hvmv_trafos,
)
Expand All @@ -77,13 +81,14 @@ def _get_transformer_costs(trafos):
pd.DataFrame(
{
"costs_transformers": len(mvlv_trafos)
* [float(edisgo_obj.config["costs_transformers"]["lv"])]
* [float(edisgo_obj.config["costs_transformers"]["lv"])],
"voltage_level": len(mvlv_trafos) * ["mv/lv"],
},
index=mvlv_trafos,
),
]
)
return costs_trafos.loc[trafos.index, "costs_transformers"].values
return costs_trafos.loc[trafos.index, :]

def _get_line_costs(lines_added):
costs_lines = line_expansion_costs(edisgo_obj, lines_added.index)
Expand All @@ -107,9 +112,8 @@ def _get_line_costs(lines_added):
# costs for transformers
if not equipment_changes.empty:
transformers = equipment_changes[
equipment_changes.index.isin(
[f"{_}_station" for _ in edisgo_obj.topology._grids_repr]
)
equipment_changes.equipment.str.contains("Transformer")
| equipment_changes.equipment.str.contains("transformer")
]
added_transformers = transformers[transformers["change"] == "added"]
removed_transformers = transformers[transformers["change"] == "removed"]
Expand All @@ -129,15 +133,16 @@ def _get_line_costs(lines_added):
)
trafos = all_trafos.loc[added_transformers["equipment"]]
# calculate costs for each transformer
transformer_costs = _get_transformer_costs(trafos)
costs = pd.concat(
[
costs,
pd.DataFrame(
{
"type": trafos.type_info.values,
"total_costs": _get_transformer_costs(trafos),
"total_costs": transformer_costs.costs_transformers,
"quantity": len(trafos) * [1],
"voltage_level": len(trafos) * ["mv/lv"],
"voltage_level": transformer_costs.voltage_level,
},
index=trafos.index,
),
Expand All @@ -161,6 +166,19 @@ def _get_line_costs(lines_added):
.sum()
.loc[lines_added_unique, ["quantity"]]
)
# use the minimum of quantity and num_parallel, as sometimes lines are added
# and in a next reinforcement step removed again, e.g. when feeder is split
# at 2/3 and a new single standard line is added
lines_added = pd.merge(
lines_added,
edisgo_obj.topology.lines_df.loc[:, ["num_parallel"]],
how="left",
left_index=True,
right_index=True,
)
lines_added["quantity_added"] = lines_added.loc[
:, ["quantity", "num_parallel"]
].min(axis=1)
lines_added["length"] = edisgo_obj.topology.lines_df.loc[
lines_added.index, "length"
]
Expand All @@ -176,9 +194,9 @@ def _get_line_costs(lines_added):
].values,
"total_costs": line_costs.costs.values,
"length": (
lines_added.quantity * lines_added.length
lines_added.quantity_added * lines_added.length
).values,
"quantity": lines_added.quantity.values,
"quantity": lines_added.quantity_added.values,
"voltage_level": line_costs.voltage_level.values,
},
index=lines_added.index,
Expand Down Expand Up @@ -288,3 +306,69 @@ def line_expansion_costs(edisgo_obj, lines_names=None):
]
)
return costs_lines.loc[lines_df.index]


def transformer_expansion_costs(edisgo_obj, transformer_names=None):
"""
Returns costs per transformer in kEUR as well as voltage level they are in.
Parameters
-----------
edisgo_obj : :class:`~.EDisGo`
eDisGo object
transformer_names: None or list(str)
List of names of transformers to return cost information for. If None, it is
returned for all transformers in
:attr:`~.network.topology.Topology.transformers_df` and
:attr:`~.network.topology.Topology.transformers_hvmv_df`.
Returns
-------
costs: :pandas:`pandas.DataFrame<DataFrame>`
Dataframe with names of transformers in index and columns 'costs' with
costs per transformer in kEUR and 'voltage_level' with information on voltage
level the transformer is in.
"""
transformers_df = pd.concat(
[
edisgo_obj.topology.transformers_df.copy(),
edisgo_obj.topology.transformers_hvmv_df.copy(),
]
)
if transformer_names is not None:
transformers_df = transformers_df.loc[transformer_names, ["type_info"]]

if len(transformers_df) == 0:
return pd.DataFrame(columns=["costs", "voltage_level"])

hvmv_transformers = transformers_df[
transformers_df.index.isin(edisgo_obj.topology.transformers_hvmv_df.index)
].index
mvlv_transformers = transformers_df[
transformers_df.index.isin(edisgo_obj.topology.transformers_df.index)
].index

costs_hvmv = float(edisgo_obj.config["costs_transformers"]["mv"])
costs_mvlv = float(edisgo_obj.config["costs_transformers"]["lv"])

costs_df = pd.DataFrame(
{
"costs": costs_hvmv,
"voltage_level": "hv/mv",
},
index=hvmv_transformers,
)
costs_df = pd.concat(
[
costs_df,
pd.DataFrame(
{
"costs": costs_mvlv,
"voltage_level": "mv/lv",
},
index=mvlv_transformers,
),
]
)
return costs_df
41 changes: 34 additions & 7 deletions tests/flex_opt/test_costs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pytest

from edisgo import EDisGo
from edisgo.flex_opt.costs import grid_expansion_costs, line_expansion_costs
from edisgo.flex_opt import costs as costs_mod


class TestCosts:
Expand Down Expand Up @@ -76,12 +76,12 @@ def test_costs(self):
],
)

costs = grid_expansion_costs(self.edisgo)
costs = costs_mod.grid_expansion_costs(self.edisgo)

assert len(costs) == 4
assert (
costs.loc["MVStation_1_transformer_reinforced_2", "voltage_level"]
== "mv/lv"
== "hv/mv"
)
assert costs.loc["MVStation_1_transformer_reinforced_2", "quantity"] == 1
assert costs.loc["MVStation_1_transformer_reinforced_2", "total_costs"] == 1000
Expand All @@ -97,13 +97,13 @@ def test_costs(self):
assert costs.loc["Line_10019", "type"] == "48-AL1/8-ST1A"
assert costs.loc["Line_10019", "voltage_level"] == "mv"
assert np.isclose(costs.loc["Line_50000002", "total_costs"], 2.34)
assert np.isclose(costs.loc["Line_50000002", "length"], 0.09)
assert costs.loc["Line_50000002", "quantity"] == 3
assert np.isclose(costs.loc["Line_50000002", "length"], 0.03)
assert costs.loc["Line_50000002", "quantity"] == 1
assert costs.loc["Line_50000002", "type"] == "NAYY 4x1x35"
assert costs.loc["Line_50000002", "voltage_level"] == "lv"

def test_line_expansion_costs(self):
costs = line_expansion_costs(self.edisgo)
costs = costs_mod.line_expansion_costs(self.edisgo)
assert len(costs) == len(self.edisgo.topology.lines_df)
assert (costs.index == self.edisgo.topology.lines_df.index).all()
assert len(costs[costs.voltage_level == "mv"]) == len(
Expand All @@ -116,7 +116,9 @@ def test_line_expansion_costs(self):
assert np.isclose(costs.at["Line_10000015", "costs_cable"], 0.27)
assert costs.at["Line_10000015", "voltage_level"] == "lv"

costs = line_expansion_costs(self.edisgo, ["Line_10003", "Line_10000015"])
costs = costs_mod.line_expansion_costs(
self.edisgo, ["Line_10003", "Line_10000015"]
)
assert len(costs) == 2
assert (costs.index.values == ["Line_10003", "Line_10000015"]).all()
assert np.isclose(costs.at["Line_10003", "costs_earthworks"], 0.083904 * 60)
Expand All @@ -125,3 +127,28 @@ def test_line_expansion_costs(self):
assert np.isclose(costs.at["Line_10000015", "costs_earthworks"], 1.53)
assert np.isclose(costs.at["Line_10000015", "costs_cable"], 0.27)
assert costs.at["Line_10000015", "voltage_level"] == "lv"

def test_transformer_expansion_costs(self):
costs = costs_mod.transformer_expansion_costs(self.edisgo)
transformers_df = pd.concat(
[
self.edisgo.topology.transformers_df,
self.edisgo.topology.transformers_hvmv_df,
]
)
assert len(costs) == len(transformers_df)
assert sorted(costs.index) == sorted(transformers_df.index)
assert len(costs[costs.voltage_level == "hv/mv"]) == len(
self.edisgo.topology.transformers_hvmv_df
)
assert np.isclose(costs.at["MVStation_1_transformer_1", "costs"], 1000)
assert costs.at["MVStation_1_transformer_1", "voltage_level"] == "hv/mv"
assert np.isclose(costs.at["LVStation_4_transformer_2", "costs"], 10)
assert costs.at["LVStation_4_transformer_2", "voltage_level"] == "mv/lv"

costs = costs_mod.transformer_expansion_costs(
self.edisgo, ["LVStation_5_transformer_1"]
)
assert len(costs) == 1
assert np.isclose(costs.at["LVStation_5_transformer_1", "costs"], 10)
assert costs.at["LVStation_5_transformer_1", "voltage_level"] == "mv/lv"
2 changes: 1 addition & 1 deletion tests/flex_opt/test_reinforce_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def test_run_separate_lv_grids(self):
assert len(g.buses_df) > 1

assert len(lv_grids_new) == 26
assert np.isclose(edisgo.results.grid_expansion_costs.total_costs.sum(), 280.06)
assert np.isclose(edisgo.results.grid_expansion_costs.total_costs.sum(), 440.06)

# check if all generators are still present
assert np.isclose(
Expand Down
4 changes: 2 additions & 2 deletions tests/test_edisgo.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ def test_reinforce_catch_convergence(self):
)
results = self.edisgo.reinforce(catch_convergence_problems=True)
assert results.unresolved_issues.empty
assert len(results.grid_expansion_costs) == 132
assert len(results.grid_expansion_costs) == 134
assert len(results.equipment_changes) == 218
assert results.v_res.shape == (4, 142)

Expand All @@ -543,7 +543,7 @@ def test_enhanced_reinforce_grid(self):

results = edisgo_obj.results

assert len(results.grid_expansion_costs) == 445
assert len(results.grid_expansion_costs) == 454
assert len(results.equipment_changes) == 892
assert results.v_res.shape == (4, 148)

Expand Down

0 comments on commit be09833

Please sign in to comment.