Replies: 35 comments
-
Thank you @jkiviluo - this looks very clear. This proposal seems to simplify the single-input-single-output case a lot, however it doesn't seem to do much for the multiple-input-multiple-output case. Users still need to define the convertion ratio via a |
Beta Was this translation helpful? Give feedback.
-
By the way, I realized that the new changes in toolbox 0.8 support defining multi-D entities where the dimensions are themselves multi-D entities. This is something @DillonJ was asking in our last call - it looks like we inadvertently supported it. This would allow us to relate two flows in SpineOpt, nicely limiting the choices for, say, Essentially it defines a fix_ratio between the flow from the fuel node and the flow to the electricity node, and then a max ratio between the two output flows. |
Beta Was this translation helpful? Give feedback.
-
I like both this efficiency approach and the reference flow approach and would hope that we would be able to implement both as different input data methods without overwhelming a regular user. If I'm not mistaken, in this efficiency approach, we would assume an input-output relationship and efficiency characteristics as illustrated below (using Juha's gas turbine example and assuming 0.3 is the efficiency at 50 MW elec and no additional parameters to modify the curves or to set minimum operating points): |
Beta Was this translation helpful? Give feedback.
-
I don't see how that is much different from having to define a reference flow and then a conversion ratio between the "reference_flow" and the other flow. The comparison should include both: how easy to make and how easy to understand. Reference method is, in this case, a bit faster to do (with current DB editor), when you know what you are doing. But when you try to understand an existing unit, it's more slow and error-prone. You will need to figure out from two different parameters how they relate and what they mean, while the ratio parameter between electricity and heat is stating it's intent directly in one row.
To me, that is the crucial improvement (although it also greatly simplified the 1 input/output case). With 'in_out', the parameter required a lot of thinking to be understood. Now its a quite straightforward 'sentence' that directly translates to the equation going to the model. I see a lot of value in that. Finally, there is the issue with the reference flow method where the coefficient will need to be changed and calculated when changing from constant efficiency to part-load efficiency. #769 (comment) |
Beta Was this translation helpful? Give feedback.
-
I suppose it would be ok if the hybrid (both methods) could be made nice for the user. E.g. we could allow user/developer to turn one of them off in a particular db. |
Beta Was this translation helpful? Give feedback.
-
The reference flow removes the need for a three way relationship, I think that's its main advantage. Users were finding difficult to create unit__node__node on top of the unit__from_node and unit__to_node. With the reference flow they do not need to do that. But I believe unit__from_node__unit__to_node and friends (i.e. relationships between relationships) can be more understandable. Users would be creating flows between units and nodes, and then relating those flows with a conversion ratio. I think that's the nicest alternative so far. |
Beta Was this translation helpful? Give feedback.
-
Now I have had some time to digest this suggestion and I think it would be straightforward to implement hydro power plants as well. What we have is a unit that takes a water flow as input (I) and generates two outputs: electricity (O1) and water flow (O2). The electricity generation is a piecewise linear function of the input water flow, whereas the output water flow is always equal to the input water flow. Let us say that the piecewise linear function is expressed as O1 = mu_11I_1 + mu_22I_2, where I_1 and I_2 are the segments of the input variable I (i.e., I = I_1 + I_2). To model this with the approach above, I would set the efficiency to 1+mu_1 for the first segment and 1+mu_2 and then the unit_node_unit_node would be mu_1 for the first segment and mu_2 for the second segment. The resulting equations for segment j will then be O1_j + O2_j = (1+mu_j)I_j Assuming that I got the equations above correct, I would say that this is quite straightforward and maybe a slight improvement compared to the present implementation in SpineOpt. However, it would probably be easier for a beginner to just define the inflow water flow as the reference flow and then set piece-wise linear input-output conversion rates for each respective input, i.e., O1_j = mu_jI_j This representation eliminates the efficiency (which is not really relevant for hydro power plants) from the data. |
Beta Was this translation helpful? Give feedback.
-
I still do not understand how this approach would manage units which have more than two outputs. Would there be several unit_node_unit_node relationships? By the way, many of the parameter names in SpineOpt are quite long and I often do not intuitively understand what they represent. Maybe you already have agreed on some parameter naming convention, but otherwise I think a parameter that represents the conversion rate between two outputs would rather be called output_ratio instead of unit_node_unit_node. |
Beta Was this translation helpful? Give feedback.
-
An advantage of this approach is of course that it manages extraction CHP in a straightforward manner. How would that be managed with the reference flow approach? |
Beta Was this translation helpful? Give feedback.
-
That should be discussed in the other issue: #769 |
Beta Was this translation helpful? Give feedback.
-
Yes, you can have as many as you need (and if we use unit__node__unit__node instead of unit__node__node, then we can also assign relations between flows in different units). The extraction CHP example is showing multiple constraints, although they are between the same outputs, but they could also be about other inputs/outputs.
Not sure if you're talking about parameter names of current SpineOpt or the ones in this proposal. In any case we should try to make as understandable parameter names as possible. I think they sometimes need to be bit long in order to make them unambiguous, but they shouldn't be any longer than necessary. In the case of the 'conversion rate', the plan is to call the parameter fix_ratio while its applied to the relation |
Beta Was this translation helpful? Give feedback.
-
@MikaelAmelin I would do a piece-wise linear hydro this way in the inputs to outputs approach: The conversion equation will take In any case, the piece-wise efficiencies will apply to the hydro turbine and we can directly use the efficiencies given in sources for hydro turbines (in that regard I don't understand when you say that efficiencies are not relevant for hydro power - turbines have efficiencies and I've never seen them presented in any other way). SpineOpt code will then take care of the segmenting. And you could also switch between different conversion presentations, e.g. change to constant efficiency when modelling investments and technological detail has to be decreased. In that case, the code will just pick the full load efficiency. My turbine efficiency source was from here: https://www.ipcc.ch/report/renewable-energy-sources-and-climate-change-mitigation/hydropower/ |
Beta Was this translation helpful? Give feedback.
-
@jkiviluo This is probably a sidetrack, so I keep it as short as I can. As you can see in your source, the efficiency of a hydro turbine is highly non-linear and it has a best efficiency point at around 70% loading (varies from turbine to turbine). In addition to the efficiency of the turbine, you also have efficiency losses in the penstock, generator etc. Moreover, most hydro power plants have more than one turbine. Therefore, for a given discharge, they distribute the water flow between the turbines so that the overall efficiency is as high as possible. This so-called "station optimisation" results in curve describing the electricity generation as a function of the discharge. This curve is non-linear, with several local maxima, where various combinations of turbines are operating at their best efficiency. It is this curve that we approximate with a piecewise linear function. The efficiency is not relevant in the sense that it has already been accounted for when the power-discharge-curve was computed. The data that are considered when we are building hydro power models is therefore primarily installed capacity, maximal discharge and maximal contents of the reservoir. |
Beta Was this translation helpful? Give feedback.
-
Ok, let us see if I understand the hydro example above correctly. There is a parameter conversion_coefficient, which if set to 0 will exclude an output from the conversion equation. Using my earlier notation, that means that the conversion equation will simply be O1 = mu_1I1_1 + mu_2I1_2 (assuming a two-segment piecewise linear function). In addition to the conversion equation for power plant, the unit_node_unit_node relation will set up a relation between the input from the first node and the output to the second node, which in the case of flows in m3 will simply be O2 = I1. If I have got this correctly, then I would say that this would be a nice and straightforward solution (clearly better than the one that I had in my mind) to hydro power modelling. Additional questions: Where would we add delay times? As electricity generation is in the same time period as the discharge from the upper reservoir whereas the water flow to the lower reservoir will be delayed, I would think that it is most straightforward to include the delay in the unit_node_unit_node relation. Is that what you intended too? |
Beta Was this translation helpful? Give feedback.
-
My main issue is that we can use nodes and units for anything and inputs and outputs are not always energy. E.g. emissions or inertia. This is what the efficiency idea assumes. E.g. the ENTSO-E data has about 10 emissions that in some cases would need to be modelled. The efficiency idea would be awkward and constraining here - expecially if you are forced to make exceptions when every unit in you model will have them. I think there are ideas in here that could be useful. I don't see this as competing proposals that we have to choose between - but rather collections of ideas that we could combine and do something that best weighs simplicity for the user, function (ensuring we don't lose any) implementation while remaining faithful to the key defining ideas of SpineOpt that make it a flexible tool that people appreciate. In my view this is the general and flexible nature of SpineOpt - that we can do anything with units, nodes and connections. I think an efficiency parameter that triggers a constraint where sum(outputs) = sum(input) * efficiency could be very useful and make some cases nice and easy for a user. However, this won't be enough in many cases and I think in any case it should be opt-in. I think a potential issue with some of the ideas is there is an underlying assumption that inputs and outputs are all energy. This is very definitely not generally true. In fact this is what makes SpineOpt very useful and ideal for modelling the energy transition - because we can use units, nodes and connections to model anything, not just energy. For example, emissions are outputs but not energy and can't be implemented using efficiency. Same goes for many other things that one might want to use units and nodes for, like inertia, reserve, reactive power, flexibility services, fast frequency response. I have created an issue where I discuss a general approach for performing the translation from specific to general here: #775. I think this could be the way to make things nice for a user in a way that doesn't cause an implementation head-ache and preserves the extesive functionality we have. In any case, we need to preserve the functionality in SpineOpt and keep it general and flexible - the efficiency idea is too constraining in my view and could be implemented alongside other things but should be opt-in. For example, I don't like the idea at all, that a user would have to use efficiency and then specify that certain inputs/outputs are excepted. |
Beta Was this translation helpful? Give feedback.
-
I don't think having |
Beta Was this translation helpful? Give feedback.
-
I think that if this is to be a runner, there needs to be some gain in terms of usability and/or function. If we are to change things, then it needs to support all conversions. The key functionality of the existing system is that you can create ratios between any two flows of a unit (inputs or outputs). The title of this topic is iteself quite limiting - because right now we support ratios between inputs and inputs, outputs and output and outputs and inputs (and inputs and outputs) and I don't see a good reason here why we would want to take away this functionality. To preserve existing functionality, you would need at least:
I would also add To put it another way, Also, I saw how we can use multi-d entities consisting of multi-d entities to implement What is desirable is a single system to define all these relationships that is better that what we have now, ideally in terms of functionality and usability. I think that should be a key criteria. @jkiviluo during the call last week, you described how non-energy inputs and outputs could be handled in the context of the efficiency constraint - maybe I missed it, but can you remind me how that would work? |
Beta Was this translation helpful? Give feedback.
-
Just to add another key advantage of going in a direction that implements all the ratios that we currently have using Another advantage is that the changes to the tutorials and documentation won't be too severe. |
Beta Was this translation helpful? Give feedback.
-
Instead of creating three new entity classes, the special cases can be managed with methods and parameters. First, storages should have conversion_methods of their own, because there are anyway modelling choices to be made. One can limit the simultaneous 2-way transfer (that the model can use to spill energy to avoid downward penalty) using a linear formulation, which is not fully accurate, or an integer version, that would be exact. After that method choice, there is no need for Second, if there are further situations where a unit has 2 links to the same node and needs some extra constraints, then those could be handled with an extra parameter called e.g. change_input_output_ordering, which would have the options input__output, output__input, input__input and output__output. The default is naturally input__output, so in those cases this doesn't need to be given. Third, if there are still remaining use cases beyond this, we can think whether we want to serve them with special parameters or leave those cases to user constraints.
Look at the 'Reserves etc.' section in the original issue description. |
Beta Was this translation helpful? Give feedback.
-
What might be helpful to appreicate is how the existing functionalities are being used by existing users. People are using SpineOpt because it's felxible and this places extra weight on "special cases" which aren't especially special at all in a SpineOpt context. I think what is proposed here could have benefits to the user and be compatible with SpineOpt's flexible and general nature, just by simply adding two additional classes - we get the same flexible functionality we have now and it makes things easier and robust for the user and the spirit of the functionality is the same, only enhanced. I think the fact that we have a system now where a unit can have any number of inputs and any number of outputs and a user can relatively easily define ratios between any two input or output flows is very fundamental and a defining characteristic of SpineOpt.
I just used storages as an example, generally, we support a flow to and from a unit to the same node, this is basic functionality that makes SpineOpt flexible and we should keep it. The whole idea is that Spine is a flexible framework that allows modelling of technologies no one has thought of. We shouldn't be baking in lots of specific things like this, regarding storage in this instance. I think the WP2 conversion tool is the place for that if we want lots of specific stuff. Maybe even an higher-level SpineDB data structure for a different type of user.
I don't think that's an improvement. It sounds very complicated for the user. Fundamentally, I think the power of SpineOpt is its flexibility and users can already very easily define arbitrary inputs and outputs and define relationships between any of those. It's a flexible, general system that allows users to model sectors and technologies no one has thought of yet. I think perhaps we need to address this philisophical question first. I feel that this simplicity and flexibily is greatly appreciated by existing users. |
Beta Was this translation helpful? Give feedback.
-
I'm not sure what you have in mind @jkiviluo but I would agree with @DillonJ in that in principle, we'd need all four combinations of I don't see any of those combinations as a special case, all of them are core cases in my opinion. In other words, we need to be able to constraint any pair of flows with a fix, min or max ratio, and in my opinion, the relationship between flows is the best alternative so far. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
The problem with the one class (unit__node__unit__node) is the selection of entities. If I select the first unit and then want to select the associated node, the system will show me all the nodes. I could very easily choose the wrong one and spend a lot of time debugging. I think most of our users have fallen for that with the current unit__node__node system. With the four classes, I need to spend a little more time selecting the class, but then I'm sure I'm making valid selections for the entities. It is more robust in that sense. Things build upon each other. It would be a real pitty to miss the opportunity to apply this robustness in our model. But the abstract class idea - I was also thinking about that. It should be easy to implement now after the recent changes. That would allow us to define an abstract class It also feels like a normal thing to have in an object-oriented system. And since we want to have the best system out there, maybe we need to give it a go? |
Beta Was this translation helpful? Give feedback.
-
It's a good point about selecting the right classes. One option could be to prioritize available options based on the existing classes (show them first on the list). But the other option is much nicer.
I'm all for it. And the way you put is better. I was thinking to add classes |
Beta Was this translation helpful? Give feedback.
-
Actually, there four possible ways to interpret battery_c__elec__battery_c__battery_c_stor because I think it's not enough that
Please don't get me wrong - I am completely open to change that improves things for the SpineOpt user. I think
along with multi-d entities consisting of multi-d entities brings benefits to the user in the form of additional flexibility (relating flows of different units) and robustness/convenience because they can only select from existing multi-d entities (the flows). Also, along with the idea of efficiency to make the very simple cases easy. The choices of what to relate to what need to be made in the end of the day. A convenience that involves an assumption is, in my opinion a faux convenience. I think it's cleaner and easier to understand being explicit about what we are relating to what. Regarding ambiguity
The whole point of SpineOpt is that we don't put resrictions or bake in assumptions regarding technologies. I don't believe in preferring certain flows or coversions based on subjective view of what people want to do or model. Here are some real examples of conversions that aren't simply input to output, (in addition to reserve) :
I think some of these are good examples of how SpineOpt makes possible things you haven't thought of, and that was the whole point and vision. This is how SpineOpt is being used right now. These are all real world example of how we leverage the existing flexibility to do complex things relatively easily, assuming arbitrary numbers of input flows and output flows and the ability to define ratios between any two of them. I believe the proposal here translates into convenience for a very specific type of user and makes life a lot harder for the kind of user that will appreciate the flexibility of SpineOpt and this was the original motivation. I think there are elements of the proposal that could enhance what we have and make things better and easier for users. @jkiviluo what do you think about achieving some of the convenience and complexity at the WP2 conversion tool level and keeping SpineOpt a little more pure? |
Beta Was this translation helpful? Give feedback.
-
Jody and I had a call and we cleared out the picture. As the abstract class will remove the ambiguity from the choice between The link above to the 'Better Add entity dialog' should help to visualize what it will be like to add entities with abstract classes. Similarly, when adding parameter values to There is also a possible discussion about the conversion_method. I think this whole thing cannot be done in a nice way without using that - it would be too ambiguous to base model behavior on parameter values only especially when there are overlapping functionalities between the methods. If need be, that can be discussed further (but should be in another issue, since it's a wider thing than just this issue). We could use just_constraints as the default conversion_method. One reason for that would be that it's the current way SpineOpt works (it does not force our hand though, db migration could handle it). Another reason is that the efficiency based methods are a bunch and maybe it's not so easy to say which one of them is more default (although constant_efficiency feels more default to me). |
Beta Was this translation helpful? Give feedback.
-
If the directions of
|
Beta Was this translation helpful? Give feedback.
-
Some thoughts/summary following this inspiring discussion:
|
Beta Was this translation helpful? Give feedback.
-
@nnhjy
As far as I can see, one abstract class (named e.g. |
Beta Was this translation helpful? Give feedback.
-
I would like to have a summary of the main aspects of this discussion. Starting with the conceptual part. So, we have two main modelling proposals to deal with the Multiple Inputs Multiple Outputs (MIMO) in SpineOpt:
Where Here are some PROs and CONS:
There are other aspects to the implementation in SpineOpt or if we should allow both to users, but I want to have a general overview of the concepts first. So, @jkiviluo and @DillonJ, do you think this is a fair summary? Is there anything else to add/change here? |
Beta Was this translation helpful? Give feedback.
-
Maybe due to my modelling background, I think of (energy) conversion units as something that take inputs and convert them to outputs. There is typically a conversion loss, which is most often expressed as efficiency. Efficiency could also be expressed as a heat rate, which is a common way to express efficiency for thermal power plants in most English speaking countries. In any case, efficiency is a more generic term that applies to other conversions besides thermal power plants.
Therefore, the basic equation governing conversions in units is
[sum of inputs] * [efficiency] = [sum of outputs]
Single input, single output
Most units have just one energy input and one energy output and therefore the sum can be ignored. In these cases it is enough to state
efficiency
, onemaximum flow
and optionally a part-load efficiency, which is expressed as online_coefficient or through operating point(s). Here is an example:Multiple inputs/outputs with fixed constraints
When there are multiple inputs, outputs or both, typically there needs to be some additional limits defined (although, in a rare case, inputs or outputs can be interchangeable, e.g. with alternative fuels). A common case is where one input/output is tied to another with fixed ratio. E.g. CHP backpressure plant:
The fixing uses
fix_ratio
parameter of theCHP_backpressure | elec | CHP_backpressure | heat
relationship. It directly translates to the equation:CHP_backpressure | elec
=CHP_backpressure | heat
x fix_ratioThis is an improvement over current SpineOpt, where there are complicated 'in_out' terms in the
unit | node | node
parameters and where it's not directly clear how the parameter translates to a constraint.The unit could be mentioned only once (
CHP_backpressure | elec | heat
) and thus reducing the dimensionality. However, that would also reduce applicability, since it can sometimes be useful to tie flows between different conversion processes (e.g. when describing industrial processes in detail). However, since user_constraints could cover those more complicated cases, it's possible to drop that extra dimension if it feels too much (we could also try to make it easier for the user to construct these entities based on theentity_classes
that are relevant for the selectedentity
).Piecewise linear efficiency etc.
Since the approach assumes that the conversion happens in the unit, efficiency would be a parameter of the unit. Efficiency could of course be expressed in piecewise linear terms when needed and it would not interfere with other constraints the unit may have (by this I mean that the parameters of the other constraints are good even if the
conversion_method
is changed). Part-load efficiencies could be expressed either through a map of operating points and their efficiencies or by usingonline_coefficient
like done in these examples.There would be only one piece-wise linear efficiency available for one unit. Therefore, if a unit would require multiple separate piece-wise linearised efficiencies, it would need to be implemented using two or more units. Not sure if there are such use cases. Furthermore, piece-wise linear efficiencies would be limited to be between inputs and outputs (not e.g. between two outputs). If there are use cases where this would be needed, they would need to be implemented using two units (or maybe by turning one output to input using negative
conversion_coefficient
).Reserves etc.
To present e.g. a reserve in the current system, we would either need to 1) assume that flows going to nodes with
is_reserve_node
are not included in the conversion equation. 2) There needs to be an additional parameter that removes the reserve 'flow' from the real outputs of the unit (so that it's not part of the conversion equation). This would be done by setting theconversion_coefficient
parameter to zero. We should have this parameter anyway available (it can be used e.g. to set different fuel values between lignite and hard coal).However, this would become pointless, if we would model reserves and inertia explicitly (#774).
OPTIONAL to cover further use cases
There are more complicated conversion cases where one would like to define an operating area rather than fixed ratio. These can be built using user_constraints and therefore it's not necessary to provide the following (but could be nice for the user):
Introducing
greater_than_ratio
andless_than_ratio
parameters to theunit | node | unit | node
relationship would allow to model e.g. an extraction CHP plant with an operating area like this:In this case setting
greater_than_ratio
for theCHP_extraction | elec | CHP_extraction | heat
unit would create the darker blue line:CHP_extraction | elec
>=CHP_extraction | heat
x fix_ratio (1.8, commonly known as cb)The grey line doesn't start from zero (electricity consumption is 35 when heat is 0), so it needs a constant in addition to
lesser_than_ratio
:CHP_extraction | elec | CHP_extraction | heat
parameterless_than_constant
(35)CHP_extraction | elec
<=CHP_extraction | heat
xless_than_ratio
(-0.15, commonly known as cv)Finally the yellow line would need this:
CHP_extraction | elec | CHP_extraction | heat
parametergreater_than_constant
(15)CHP_extraction | elec
>=CHP_extraction | heat
xgreater_than_ratio
(-0.15, commonly known as cv)However, therein lies a problem. It would redefine the cb line above and that's not allowed. So, the alternatives are to either, 1) reverse the entities:
CHP_extraction | heat | CHP_extraction | elec
parameterless_than_constant
(15)CHP_extraction | heat
>=CHP_extraction | elec
xless_than_ratio
(1/-0.15)or 2) wrap the parameters in a map (which we might want to do anyway). We would then have a
constraint
parameter map:The unit would look like this. The additional relationship needed can be seen as a hindrance or as clearly depicting an additional constraint the unit actually has (I naturally see the latter).
As you can see, the efficiency has been set to 1. It's replaced by separate coefficients that state how much more fuel is consumed per a MW of electricity or heat output (
conversion_coefficient
). Instead, one could keep a reasonable value for efficiency and adjust these conversion_coefficients to match that, but that would obscure how the unit uses fuel in relation to outputs. So, it would make sense to have a specificconversion_method
for these types of cases (and then efficiency would not need to be defined at all).Reference flow based option is presented here: #769
Beta Was this translation helpful? Give feedback.
All reactions