switch-model / switch

A Modern Platform for Planning High-Renewable Power Systems
http://switch-model.org/
Other
130 stars 85 forks source link

Add pumped hydro in a generalized & backwards-compatible way #117

Open josiahjohnston opened 5 years ago

josiahjohnston commented 5 years ago

Generalized implementation of simple pumped hydro with an example/test case. This implementation requires the sequence of simple_hydro, storage in modules.txt.

My goals were modeling accuracy, backwards compatibility, avoiding redundancy, checks to aid debugging of common errors, and allow pumped hydro to participate in reserves like any other generator.

Pumped hydro is different from normal hydro because of need to the track energy balance, and that average dispatch is not solely determined by average stream flow (but also includes storage decisions). It's also different from normal storage because energy tracking needs to include both stream inflow and any spilled water.

In this implementation, if any pumped hydro generators are specified, the simple_hydro module will validate that the storage module is also included. The pre-existing rules for maintaining average stream flow are restricted to non-pumped hydro. Special rules for pumped hydro energy tracking and streamflow are implemented with an extra few lines in the storage energy tracking constraint, which capture the mathematical requirements of average daily balancing and additionally tracks state-of-charge. If the pumped hydro terms are not available, the storage module will skip that stanza without complaint.

I also updated the storage documentation to reflect how StateOfCharge is unbound for one timepoint in each timeseries (that is, the optimization can choose to start a day with an arbitrary storage level), because I found myself having to re-read through equations to convince myself of that behavior.

I reviewed the pumped_hydro module in Hawaii before starting this. That implementation looked great for a rapid prototype, but had a few drawbacks:

The second two bullet points meant I couldn't just reuse that module for my problem, and the first bullet point prompted me to devise an alternate design patterns.

bmaluenda commented 5 years ago

I haven't been able to find enough time to review the example in detail, but the code looks good. It is great that you found a clever way to implement this behavior using the existing hydro_simple and storage modules, instead of adding a new one.

From what I understand, StateOfCharge is effectively unbound for the first timepoint of each timeseries, but depends on the StateOfCharge and dispatch decisions at the last timepoint. This creates a circular behavior that makes perfect sense if the representative day repeats itself consecutively. If the selected representative days are alternating, this behavior might be a bit imprecise. In such case, the ability to exogenously constraint the initial StateOfCharge (and, thus, also the final StateOfCharge) of each timeseries would be useful. It could be nice to have this idea in a TODO list.

A more advanced implementation that considers the full mass balance using the hydro_system module could be added to the TODO list as well. That would be useful for studies in systems that have cascading pumped hydro.

I do have a more relevant question: It seems to me that in this implementation you assume that the generator will have infinite availability of water at the lower reservoir to pump back to the upper reservoir. If so, it could be good to explicitely note it in the documentation. This behavior impacts the modeling of pumped hydro that doesn't have natural inflows into the upper reservoirs and for cascading water reservoirs. It's not wrong at all, but the modeler should be aware of limitations.

josiahjohnston commented 5 years ago

Thanks for the comments Benjamin! I'll update the documentation to add a description of how energy capacity is handled, with particular emphasis on the lower reservoir. Your interpretation is consistent with the modeling, but there are a more nuances that I'll add in.

Agreed on the to-do list for integrating with the hydro system module, and changing behavior of state of charge from circular to sequential or something else. Circularity vs non-circularity of timeseries has been a standing to-do item, but I don't remember if that's written anywhere.

bmaluenda commented 5 years ago

I don't really think that state-of-charge tracking should be sequential, given that timeseries don't necessarily represent consecutive time periods. Additionally, making tracking sequential would increase the difficulty of the problem, since pumped hydro dispatch decisions would be linked throughout all timeseries.

I think a reasonable solution could be to allow setting initial (and final) volumes as an input.

josiahjohnston commented 5 years ago

Yeah, that makes sense for use cases I've run into. I expect someone will need sequential (rather than circular) behavior at some point, but I haven't encountered it yet.

I added documentation per your suggestions. Look good to you?

mfripp commented 5 years ago

As you noted, we don't officially consider timeseries as having any chronological relationship to each other. This impairs our ability to model seasonal phenomena. We could fix this by adding another level of time between timeseries and periods (probably seasons, maybe months of year), but I don't think we're ready to go there yet.

In the past, for hydro, I've just constrained inflow and outflow on each day to match the average reported values for that month of the year. That seemed conservative, since there may be some ability to vary flows from day to day within the month.

In Hawaii, I've assumed that hydrogen consumption might be concentrated during a particular period of the year, i.e., stocks would build up during one part of the year and they would decline during another part. So then it's possible to cover seasonality conservatively by just requiring a storage volume that exceeds the total amount stored at all times of the year. If in fact there are multiple cycles of build up, draw down, build up, draw down, then you could actually get away with less storage capacity. But storage volume is a small part of the cost of using hydrogen, so the conservative approach probably doesn't skew the results too much.

bmaluenda commented 5 years ago

I still haven't had the time to study the example you provided, but the code and documentation looks good to me.