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

The OffsetConverter is broken in the new implementation #1067

Closed
fwitte opened this issue May 21, 2024 · 4 comments
Closed

The OffsetConverter is broken in the new implementation #1067

fwitte opened this issue May 21, 2024 · 4 comments

Comments

@fwitte
Copy link
Member

fwitte commented May 21, 2024

Describe the bug
With the current formulation, the OffsetConverter can produce the outputs at the level of each respective offset without consuming anything from the input.

I am preparing a PR to solve the issue.

To Reproduce
Consider the following example of an electrolyzer producing hydrogen and heat. The electrolyzer follows a fixed hydrogen demand, a slack source is available in case the demand cannot be supplied due to part load restrictions.

from oemof import solph


es = solph.EnergySystem(timeindex=solph.create_time_index(year=2023, number=5))

eta_h2_min = 0.6                 # efficiency at minimal operation point
eta_h2_max = 0.5                 # efficiency at nominal operation point
P_in_min = 20                   # absolute minimal output power
P_in_max = 100                  # absolute nominal output power

# calculate limits of input power flow
P_out_min_h2 = P_in_min * eta_h2_min
P_out_max_h2 = P_in_max * eta_h2_max

# calculate coefficients of input-output line equation
slope_h2 = (P_out_max_h2 - P_out_min_h2) / (P_in_max - P_in_min)
offset_h2 = (P_out_max_h2 - slope_h2 * P_in_max) / P_out_max_h2


eta_heat_min = 0.3                 # efficiency at minimal operation point
eta_heat_max = 0.4                 # efficiency at nominal operation point

# calculate limits of input power flow
P_out_min = P_in_min * eta_heat_min
P_out_max = P_in_max * eta_heat_max

# calculate coefficients of input-output line equation
slope_heat = (P_out_max - P_out_min) / (P_in_max - P_in_min)
offset_heat = (P_out_max - slope_heat * P_in_max) / P_out_max

b_h2 = solph.Bus("hydrogen bus")
b_heat = solph.Bus("heat bus")
b_el = solph.Bus("electricity bus")

b_electrolyzer_h2 = solph.Bus("electrolyzer virtual input for h2")
b_electrolyzer_heat = solph.Bus("electrolyzer virtual input for heat")

source_el = solph.components.Source("electricity import", outputs={b_el: solph.Flow()})
source_slack_h2 = solph.components.Source("hydrogen slack", outputs={b_h2: solph.Flow(variable_costs=1000)})
sink_heat = solph.components.Sink("heat export", inputs={b_heat: solph.Flow()})
sink_h2 = solph.components.Sink("hydrogen export", inputs={b_h2: solph.Flow(fix=[10, 20, 30, 40, 50, 60], nominal_value=1)})

electrolyzer = solph.components.OffsetConverter(
    label="electrolyzer",
    inputs={b_el: solph.Flow(nominal_value=P_in_max)},
    outputs={
        b_heat: solph.Flow(
            nominal_value=P_out_max,
            nonconvex=solph.NonConvex(),
            min=P_out_min / P_out_max
        ),
        b_h2: solph.Flow(
            nominal_value=P_out_max_h2,
            nonconvex=solph.NonConvex()
        )
    },
    coefficients={
        b_heat: [offset_heat, slope_heat],
        b_h2: [offset_h2, slope_h2],
    }
)

es.add(
    b_el, b_heat, b_h2,
    source_el, sink_h2, sink_heat, source_slack_h2,
    electrolyzer
)

om = solph.Model(es)

om.solve("gurobi")

result = solph.views.convert_keys_to_strings(om.results())
result[("electrolyzer", "hydrogen bus")]["sequences"]

The minimum hydrogen production should be at 12, but due to the offset it is at 2.5.

flow status status_nominal
2023-01-01 00:00:00 2.5 1 50
2023-01-01 01:00:00 20 1 50
2023-01-01 02:00:00 30 1 50
2023-01-01 03:00:00 40 1 50
2023-01-01 04:00:00 50 1 50
2023-01-01 05:00:00 50 1 50

The reason for that is, that the status_nominal is multiplied with the output binary variable instead of the input binary variable.

@fwitte
Copy link
Member Author

fwitte commented May 23, 2024

Never mind, I think my example is just missing the min attribute of the H2 output Flow. Still, I would like to make the cleanup with enforcing a single NonConvex flow as the reference for all other flow's slopes and offsets.

@p-snft
Copy link
Member

p-snft commented May 29, 2024

Never mind, I think my example is just missing the min attribute of the H2 output Flow. Still, I would like to make the cleanup with enforcing a single NonConvex flow as the reference for all other flow's slopes and offsets.

Does that mean this issue is closed, then?

@fwitte
Copy link
Member Author

fwitte commented May 29, 2024

Does that mean this issue is closed, then?

Kind of yes, the linked pull requests is still valid. Now it is more of a complete rework of the OffsetConverter and might close #1010 instead?

@p-snft
Copy link
Member

p-snft commented Jun 4, 2024

So, this was not a real bug, only the API was very inviting to put unreasonable parameters. I will close this, as it can be seen as a duplicate of the "mislieading documentation" issue.

@p-snft p-snft closed this as not planned Won't fix, can't repro, duplicate, stale Jun 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants