Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revision/explicit network kwargs #1032

Merged
merged 16 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/oemof/solph/_energy_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,16 @@ def __init__(
infer_last_interval=None,
periods=None,
use_remaining_value=False,
**kwargs,
groupings=None,
):
# Doing imports at runtime is generally frowned upon, but should work
# for now. See the TODO in :func:`constraint_grouping
# <oemof.solph.groupings.constraint_grouping>` for more information.
from oemof.solph import GROUPINGS

kwargs["groupings"] = GROUPINGS + kwargs.get("groupings", [])
if groupings is None:
groupings = []
groupings = GROUPINGS + groupings

if not (
isinstance(timeindex, pd.DatetimeIndex)
Expand Down Expand Up @@ -161,7 +163,9 @@ def __init__(
raise TypeError(msg)

super().__init__(
timeindex=timeindex, timeincrement=timeincrement, **kwargs
groupings=groupings,
timeindex=timeindex,
timeincrement=timeincrement,
)

self.periods = periods
Expand Down
23 changes: 20 additions & 3 deletions src/oemof/solph/buses/_bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,26 @@ class Bus(Node):

"""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.balanced = kwargs.get("balanced", True)
def __init__(
self,
label=None,
*,
inputs=None,
outputs=None,
balanced=True,
custom_properties=None,
):
if inputs is None:
inputs = {}
if outputs is None:
outputs = {}
super().__init__(
label,
inputs=inputs,
outputs=outputs,
custom_properties=custom_properties,
)
self.balanced = balanced

def constraint_group(self):
if self.balanced:
Expand Down
25 changes: 20 additions & 5 deletions src/oemof/solph/buses/experimental/_electrical_bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,23 @@ class ElectricalBus(Bus):

"""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.slack = kwargs.get("slack", False)
self.v_max = kwargs.get("v_max", 1000)
self.v_min = kwargs.get("v_min", -1000)
def __init__(
self,
label=None,
*,
v_max,
v_min,
inputs=None,
outputs=None,
custom_properties=None,
slack=False,
):
super().__init__(
label,
inputs=inputs,
outputs=outputs,
custom_properties=custom_properties,
)
self.slack = slack
self.v_max = v_max
self.v_min = v_min
10 changes: 5 additions & 5 deletions src/oemof/solph/components/_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,9 @@ def __init__(
conversion_factors=None,
custom_attributes=None,
):
self.label = label

if inputs is None:
warn_if_missing_attribute(self, "inputs")
inputs = {}
if outputs is None:
warn_if_missing_attribute(self, "outputs")
outputs = {}

if custom_attributes is None:
Expand All @@ -117,8 +113,12 @@ def __init__(
label=label,
inputs=inputs,
outputs=outputs,
**custom_attributes,
custom_properties=custom_attributes,
Copy link
Contributor

@nailend nailend Mar 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@p-snft why aren't these parameter-names aligned? I guess it started here. Wouldn't it be best to change in oemof.network to custom_attributes as well, especially as custom-attributes are frequently used in the oemof-tabular API?!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Python, an attribute is a fixed term referring to a variable defined by the class in the scope of an object. The implementation that some though we had (but never had) in network added attributes

my_node = Node("name", some_feature= 5)  # API was never implemented
my_node.some_feature # "some_feature" is an attribute, API was never implemented
# 5

However, the API now is

my_node = Node("name", custom_properties={"some_feature": 5})
my_node.custom_properties["some_feature"]  # "some feature" is not an attribute
# 5

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well custom_properties is an attribute though 😆

)
if not inputs:
warn_if_missing_attribute(self, "inputs")
if not outputs:
warn_if_missing_attribute(self, "outputs")

if conversion_factors is None:
conversion_factors = {}
Expand Down
4 changes: 2 additions & 2 deletions src/oemof/solph/components/_generic_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,10 @@ def __init__(
if custom_attributes is None:
custom_attributes = {}
super().__init__(
label=label,
label,
inputs=inputs,
outputs=outputs,
**custom_attributes,
custom_properties=custom_attributes,
)
# --- BEGIN: The following code can be removed for versions >= v0.6 ---
if investment is not None:
Expand Down
17 changes: 10 additions & 7 deletions src/oemof/solph/components/_link.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,26 @@ def __init__(
conversion_factors=None,
custom_attributes=None,
):
# compatibility with omeof.network w/o explicit named arguments
if inputs is None:
warn_if_missing_attribute(self, "inputs")
inputs = {}
if outputs is None:
warn_if_missing_attribute(self, "outputs")
outputs = {}
if conversion_factors is None:
warn_if_missing_attribute(self, "conversion_factors")
conversion_factors = {}
if custom_attributes is None:
custom_attributes = {}
super().__init__(
label=label,
label,
inputs=inputs,
outputs=outputs,
**custom_attributes,
custom_properties=custom_attributes,
)
if not inputs:
warn_if_missing_attribute(self, "inputs")
if not outputs:
warn_if_missing_attribute(self, "outputs")
if conversion_factors is None:
warn_if_missing_attribute(self, "conversion_factors")
conversion_factors = {}
self.conversion_factors = {
k: sequence(v) for k, v in conversion_factors.items()
}
Expand Down
34 changes: 24 additions & 10 deletions src/oemof/solph/components/experimental/_generic_caes.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,32 @@ class GenericCAES(Node):
<class 'oemof.solph.components.experimental._generic_caes.GenericCAES'>
"""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

self.electrical_input = kwargs.get("electrical_input")
self.fuel_input = kwargs.get("fuel_input")
self.electrical_output = kwargs.get("electrical_output")
self.params = kwargs.get("params")
def __init__(
self,
label,
*,
electrical_input,
fuel_input,
electrical_output,
params,
custom_properties=None,
):
super().__init__(
label=label,
inputs={},
outputs={},
custom_properties=custom_properties,
)

self.electrical_input = electrical_input
self.fuel_input = fuel_input
self.electrical_output = electrical_output
self.params = params

# map specific flows to standard API
self.inputs.update(kwargs.get("electrical_input"))
self.inputs.update(kwargs.get("fuel_input"))
self.outputs.update(kwargs.get("electrical_output"))
self.inputs.update(electrical_input)
self.inputs.update(fuel_input)
self.outputs.update(electrical_output)

def constraint_group(self):
return GenericCAESBlock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,27 @@ class PiecewiseLinearConverter(Node):
PiecewiseLinearConverter'>
"""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def __init__(
self,
label,
*,
inputs,
outputs,
conversion_function,
in_breakpoints,
pw_repn,
custom_properties=None,
):
super().__init__(
label,
inputs=inputs,
outputs=outputs,
custom_properties=custom_properties,
)

self.in_breakpoints = list(kwargs.get("in_breakpoints"))
self.conversion_function = kwargs.get("conversion_function")
self.pw_repn = kwargs.get("pw_repn")
self.in_breakpoints = list(in_breakpoints)
self.conversion_function = conversion_function
self.pw_repn = pw_repn

if len(self.inputs) > 1 or len(self.outputs) > 1:
raise ValueError(
Expand Down
28 changes: 7 additions & 21 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,9 @@ def test_multi_period_default_discount_rate():
def test_cellular_structure_detection():
"""Test flag creation if list is passed as energysystem to model"""
timeindex = pd.date_range(start="2020-01-01", periods=1, freq="H")
es = solph.EnergySystem(
label="es", timeindex=timeindex, infer_last_interval=True
)
ec_1 = solph.EnergySystem(
label="ec_1", timeindex=timeindex, infer_last_interval=True
)
ec_2 = solph.EnergySystem(
label="ec_2", timeindex=timeindex, infer_last_interval=True
)
es = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True)
ec_1 = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True)
ec_2 = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True)
m = solph.Model(energysystem=[es, ec_1, ec_2])
assert m.is_cellular

Expand All @@ -132,12 +126,8 @@ def test_sub_cell_node_consideration():
energysystems.
"""
timeindex = pd.date_range(start="2020-01-01", periods=1, freq="H")
es = solph.EnergySystem(
label="es", timeindex=timeindex, infer_last_interval=True
)
ec_1 = solph.EnergySystem(
label="ec_1", timeindex=timeindex, infer_last_interval=True
)
es = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True)
ec_1 = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True)
bus_es = solph.buses.Bus(label="bus_es")
bus_ec_1 = solph.buses.Bus(label="bus_ec_1")
es.add(bus_es)
Expand All @@ -152,12 +142,8 @@ def test_sub_cell_flow_consideration():
energysystems.
"""
timeindex = pd.date_range(start="2020-01-01", periods=1, freq="H")
es = solph.EnergySystem(
label="es", timeindex=timeindex, infer_last_interval=True
)
ec_1 = solph.EnergySystem(
label="ec_1", timeindex=timeindex, infer_last_interval=True
)
es = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True)
ec_1 = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True)
bus_es = solph.buses.Bus(label="bus_es")
bus_ec_1 = solph.buses.Bus(label="bus_ec_1")
es.add(bus_es)
Expand Down
49 changes: 22 additions & 27 deletions tests/test_scripts/test_solph/test_lopf/test_lopf.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from oemof.solph.flows import experimental as exp_flow


@pytest.mark.skip(reason="Constraints of Electrical Line do not build.")
def test_lopf(solver="cbc"):
logging.info("Initialize the energy system")

Expand All @@ -50,37 +51,31 @@ def test_lopf(solver="cbc"):

es.add(b_el0, b_el1, b_el2)

es.add(
exp_flow.ElectricalLine(
input=b_el0,
output=b_el1,
reactance=0.0001,
nominal_value=Investment(ep_costs=10),
min=-1,
max=1,
)
b_el1.inputs[b_el0] = exp_flow.ElectricalLine(
input=b_el0,
output=b_el1,
reactance=0.0001,
nominal_value=Investment(ep_costs=10),
min=-1,
max=1,
)

es.add(
exp_flow.ElectricalLine(
input=b_el1,
output=b_el2,
reactance=0.0001,
nominal_value=60,
min=-1,
max=1,
)
b_el2.inputs[b_el1] = exp_flow.ElectricalLine(
input=b_el1,
output=b_el2,
reactance=0.0001,
nominal_value=60,
min=-1,
max=1,
)

es.add(
exp_flow.ElectricalLine(
input=b_el2,
output=b_el0,
reactance=0.0001,
nominal_value=60,
min=-1,
max=1,
)
b_el0.inputs[b_el2] = exp_flow.ElectricalLine(
input=b_el2,
output=b_el0,
reactance=0.0001,
nominal_value=60,
min=-1,
max=1,
)

es.add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,13 @@ def conv_func(x):
return 0.01 * x**2

in_breakpoints = np.arange(0, 110, 25)
out_breakpoints = conv_func(in_breakpoints)

# Create and add PiecewiseLinearConverter
pwltf = solph.components.experimental.PiecewiseLinearConverter(
label="pwltf",
inputs={b_gas: solph.flows.Flow(nominal_value=100, variable_costs=1)},
outputs={b_el: solph.flows.Flow()},
in_breakpoints=in_breakpoints,
out_breakpoints=out_breakpoints,
conversion_function=conv_func,
pw_repn="CC",
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def test_dispatch_one_time_step(solver="cbc"):
conversion_factors={bel: 1 / 3, b_heat_source: (cop - 1) / cop},
)

energysystem = EnergySystem(timeincrement=[1], timemode="explicit")
energysystem = EnergySystem(timeincrement=[1])
energysystem.add(
bgas,
bel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def test_dispatch_one_time_step(solver="cbc"):
conversion_factors={bel: 1 / 3, b_heat_source: (cop - 1) / cop},
)

energysystem = EnergySystem(timeincrement=[1], timemode="explicit")
energysystem = EnergySystem(timeincrement=[1])
energysystem.add(
bgas,
bel,
Expand Down
Loading