Add processes components as multi-link alternative#1333
Add processes components as multi-link alternative#1333FabianHofmann merged 48 commits intoPyPSA:masterfrom
Conversation
4210200 to
d71e67d
Compare
|
Rebased to the actual master now. Had an old state. The test failures are deprecations in the master branch. |
d71e67d to
24efddb
Compare
|
Instead of setting reference_bus="bus1"That way, the rates have no implied meaning and users do not need to calculate the rates relative to one particular rate (one less calculation step that can be erroneous). Say in your example you have the inputs and outputs of the process in absolute values, then you could plug these values directly (dummy values, with approx 5 MWh/t ammonia) n.add(
"Process",
nodes,
suffix=" Haber-Bosch",
bus0=nodes,
bus1=spatial.ammonia.nodes,
bus2=nodes + " H2",
p_nom_extendable=True,
carrier="Haber-Bosch",
rate0=-1.2,
rate1=5,
rate2=-5.5,
reference_bus="bus1",
capital_cost=costs.at["Haber-Bosch", "capital_cost"],
marginal_cost=costs.at["Haber-Bosch", "VOM"],
lifetime=costs.at["Haber-Bosch", "lifetime"],
) |
|
Hi, @euronion, the reference_bus would then be for fixing the units for capital and marginal costs? Efficiencies are already fully determined by the ratios of the rates. Not sure what this would then do? I think i fail to understand what would be the input data that would lead you to set do factsheets of a process not always report efficiencies as ratios between ports? In your example, the process is producing 5 t of ammonia, by consuming 1.2 MWh of electricity and 5.5t H2. Did you mean that? And marginal costs are expected as Eur/5t ammonia or Eur/1.2MWhel. Setting the reference bus to bus1 would then allow you to specify it as Eur/t ammonia, i guess. |
Yes, you understood that correctly. |
|
I'll wait for #1349 to land and then rebase on that. |
I only skimmed this, not questioning the processes component, but you are adhering to the component architecture wonderfully 👍 |
|
Instead of |
@coroa I thought about it again: I imagine use cases where you have a process component with a reference unit, however the sector of that reference unit is not in the system (or not any more). For example you want to model haber-bosch without the explicit ammonia sector, just model the hydrogen and electricity consumption, potentially keeping the same dispatch of the HB asset from a previous run. In that case you would loose the flexibility to use the original rate data and have to convert all units to either hydrogen or electricity. Therefore, the way I see it, most flexibility you gain with discarding the reference bus and allow for arbitrary rate values. The output of the process would contain a |
well I agree with you, and this internal dispatch is also already in the code, since it made sense anyway, but that is not what was decided. |
I think this was not fully clear to the other (at least it wasn't to me). The flexibility would be very helpful and we should go for it. @lkstrp @brynpickering @euronion let's reconsider? perhaps @fneum also has a view on this |
|
🚫 I'm still strongly in favour of making this information explicit, not implicit. ✔️ I do see the point that you are making for cases where the reference is not available or part of the system/process. An option could be a compromise, where we allow overloading of relative_to: str | float = "bus1"
# or
relative_to: str | float = <p> |
|
I took a stab at an implementation of n.add(
"Process",
nodes,
suffix=" Haber-Bosch",
bus0=nodes,
bus1=spatial.ammonia.nodes,
bus2=nodes + " H2",
p_nom_extendable=True,
carrier="Haber-Bosch",
rate0=-costs.at["Haber-Bosch", "electricity-input"], # negative rate consumes
rate1=1, # positive rate produces; 1 sets the reference bus
rate2=-costs.at["Haber-Bosch", "hydrogen-input"],
capital_cost=costs.at["Haber-Bosch", "capital_cost"],
marginal_cost=costs.at["Haber-Bosch", "VOM"],
lifetime=costs.at["Haber-Bosch", "lifetime"],
relative_to="bus2",
)Ie. the internal dispatch variable is synced with the ammonia output; the I think this means, that the Does this mean that p_nom_opt is then expected in if so, i think that means i need to actually rescale all the rate variables internally by that |
That's a bit complicated by the fact that we are starting to allow also just the port numbers as integers as valid port signifiers, as introduced in #1386 . If we tried to be consistent, then this would mean |
|
I didn't know about the port and discussion in the other PR. Is it a good idea to allow just the port numbers as integers? I understand it is convenient, at the same time it reduces our degrees of freedom for future development (maybe?). Having Shall we revisit this discussion next Wednesday and collect the options and ideas again by then? |
I talked with both Fabians again, and @fneum is also very much in favor of keeping this implicit without the need for an extra attribute. Just bring one of your rates to 1 and all good. I think this is also more intuitive and simpler. I am also against any of those mixed solutions where reference_to could be optional. Since @coroa and @FabianHofmann see it the same way I guess the vote would have changed already anyway. Could still discuss that next week (again) if you think it's needed |
|
After the arguments that @brynpickering shared about making it explict I was under the impression last time that explicit should be preferred. But feel free to go ahead if that is the current majority vote. |
|
thanks for being flexible @euronion on this (it's always a back and forth, isn't it). if we see there the interpretation is too complicated we still can add explicit things later |
|
@lkstrp could you have a look at the |
lkstrp
left a comment
There was a problem hiding this comment.
A couple of comments. Multiport wants to inherit from Components and be a Mixin, that will also clean up all the patched type stuff
|
I would add one more test and "bug fix" that columns from attributes from additional port are appearing after there predecessor |
|
The I have one request for the finishing touches before merging: The |
| SPDX-License-Identifier: CC-BY-4.0 | ||
| --> | ||
|
|
||
| ::: pypsa.components.Multiport |
There was a problem hiding this comment.
No, we don't wanna expose this, methods here should be inherited to Links and Processes and shown there. I can just fix that
good point! done |
Closes #549 .
Changes proposed in this Pull Request
Adds a new
processescomponent as a multi-link alternative.The difference to links is that
efficiency,efficiency2, ... are replaced byrate0,rate1,rate2, ... to determine the energy output (always positive sign) atbus0. As well as a consistent sign convention, in that the power output at busX of the process is alwaysrateX * pwhere p is the internal optimization variable.This allows implicitly to choose the reference bus, by setting any
rateto 1 or -1.Take the example of the Haber-Bosch process, which is written with a (Multi-)Link as:
with the
Processcomponent this becomes:The last commit 4210200 adds a variant of the sector coupling notebook replacing all Links (incl. a CHP Multilink) with Processes. The results are identical.
Todo
Checklist
doc.doc/release_notes.rstof the upcoming release is included.