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

Difference between objective_weighting and timeincrement #987

Open
henhuy opened this issue Oct 9, 2023 · 3 comments
Open

Difference between objective_weighting and timeincrement #987

henhuy opened this issue Oct 9, 2023 · 3 comments
Labels

Comments

@henhuy
Copy link
Contributor

henhuy commented Oct 9, 2023

I recently found out, that a model can be set up using objective_weighting parameter, which is used in SimpleFlowBlock, NonConvexFlowBlock and SinkDSM component.
First I thought, that this is very nice and could help me with integrating TSAM in oemof (see #980).
But then I saw, that objective_weighting is basically used like timeincrement in other components - if not set, it is set up per default as same array as timeincrement.

As far as I can read out from code, objective_weighting is used to calculate variable costs, while timeincrement is used for calculating energy flows, but both are used somehow identically.
For example compare variable cost implementation in SimpleFlowBlock:

for i, o in m.FLOWS:
if m.flows[i, o].variable_costs[0] is not None:
for p, t in m.TIMEINDEX:
variable_costs += (
m.flow[i, o, p, t]
* m.objective_weighting[t]
* m.flows[i, o].variable_costs[t]
)

with full_load_hours implementation in SimpleFlowBlock:
for inp, out in self.FULL_LOAD_TIME_MAX_FLOWS:
lhs = sum(
m.flow[inp, out, p, ts] * m.timeincrement[ts]
for p, ts in m.TIMEINDEX
)
rhs = (
m.flows[inp, out].full_load_time_max
* m.flows[inp, out].nominal_value
)
self.full_load_time_max_constr.add((inp, out), lhs <= rhs)

For TSAM integration in oemof, I need to integrate weighting of clusters (i.e. how often does a "typical day" occurs in original timeseries) but still need unrelated time-increments, as hours of a day might be segmented into three-hour steps.
Thus, energy flows must be calculated using `timeincrement and variable costs and full load hours have to be calculated using occurrence mapping.

My question is somehow, if oemof.solph implements those two parameters in a coherent way? For example, I would have thought, that full load hours use objective_weighting instead of timeincrement.

@henhuy henhuy added the question label Oct 9, 2023
@p-snft
Copy link
Member

p-snft commented Oct 10, 2023

To my understanding, objective_weighting is the generalised version of timeincrement. It makes sense, to include (or even default to) timeincrement as time steps of variable lengths should be weighted according to their length. Maybe, it's been changed in the costs but not in the full load constraint, as the objective_weighting might also include a factor for discounting the costs. (Currently, it is not and I would also rather put that into the variable_costs. What do you think @jokochems?) Still, there might be a point in putting e.g. more weight in sooner than in later time steps for real-time optimisation, to consider the uncertainty of the future.

Maybe, we need something (represented_duration) more concrete than objective_weighting that is still more abstract than timeincrement.

@jokochems
Copy link
Member

Hi, excellent that you brought this up, @henhuy. In my view, this is bit of a weak spot.

  • When initially developing the SinkDSM and also the multi-period feature, I also found that they are used pretty much interchangably at the moment.
  • To be honest, I didn't give it too much thought since I consider only hourly time steps.
  • As @p-snft stated, I also used the objective_weighting for variable_costs terms as I used other flows as a role model.
  • I used the timeincrement attribute to represent energy amounts, i.e. some power (MW) value multiplied with $\tau(t)$ (you might also think of it as $\Delta t$ in case it is constant) to obtain MWh (of stored energy e.g.). This is where I think, it makes sense to use the timeincrement.

Now concerning the weighting of an objective value:

  • If you explicitly want to define a weighting that deviates from the timeincrement, I think this requires an extension of the status quo.
  • One could also think of multiplying the variable costs with the timeincrement (as it is the same as the objective_weighting and serves to account for time steps deviating from your default, let's assume one hour for instance) and then explicitly set an objective_weighting to account for deviating weights for later time steps of the optimization horizon for instance.
  • I think, also thinking about renaming or introducing additional attributes, as @p-snft suggested, might be worthwhile considering.

I checked the code basis: timeincrement and objective_weighting seem to be used consistently throughout if you take @p-snft and my understanding of these attributes. You already detected the inconsistency in the definition of the timeincrement for a standard model compared to a multi-period model: #979. Again, sorry for that and that I unfortunately cannot provide a quick fix for this.

@henhuy
Copy link
Contributor Author

henhuy commented Oct 16, 2023

Thanks for your feedback!
My suggestion, regarding your feedback, would be as follows:

  • We should unify usage of timeincrement as default to calculate energy flows, variable costs, full load hours
  • objective_weighting should be used to address i.e. deviating weights for later time steps of the optimization horizon or (in my case) for weighting different occurrences of typical period clusters
  • objective_weighting could be renamed to something more meaningful
  • as objective_weighting is part of Model class since 5 years, this change is a breaking change and must be communicated accordingly.

If you agree to above suggestions, I could start an issue to propose above mentioned changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants