Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ repos:
rev: v4.4.0
hooks:
- id: check-added-large-files # Don't accidentally commit giant files.
args: ["--maxkb=9000"]
args: ["--maxkb=25000"]
- id: check-merge-conflict # Watch for lingering merge markers.
- id: check-yaml # Validate all YAML files.
- id: check-case-conflict # Avoid case sensitivity in file names.
Expand Down
16 changes: 10 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,24 @@ Description
=======================================================================================

``Dispatch`` is a hugely simplified production cost model. It takes in a
portfolio of dispatchable and storage resources and asks, how can these resources
be dispatched to meet [net] load? And how much would it cost?
portfolio of dispatchable, fixed-output and storage resources and asks, how can these
resources be dispatched to meet [net] load? And how much would it cost?

It contains no optimization, security constraints, or formal unit commitment. It
attempts a loose approximation of a production cost model by applying the following
procedure in each hour:

1. Iterate through operating dispatchable plants in order of their marginal cost and
1. Augment or diminish load to be met by operating dispatchable plants based on state
of charge relative to storage reserve. The storage reserve can be dynamically set
each hour based on ramping requirements over the next 24 hours.
2. Iterate through operating dispatchable plants in order of their marginal cost and
adjust their output to meet load, limited by their ramp rate.
2. If there is excess energy from renewables, use it to charge storage. If there is
still unmet load, discharge storage.
3. If there is still unmet load, iterate through non-operating plants in order of
3. If there is excess energy from renewables, use it to charge storage. If there is
still unmet load, discharge storage but holding some in state of charge in reserve.
4. If there is still unmet load, iterate through non-operating plants in order of
their start-up cost and turn them on if they are needed to meet load, limited by
their ramp rate.
5. If there is still unmet load, use any reserve state of charge to meet load.

For more information about how the model works and how to use it, please see the
`model documentation <https://rmi.github.io/dispatch/>`__.
Expand Down
29 changes: 20 additions & 9 deletions docs/approach.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,31 @@ Approach

In which we explain in greater detail how the thing works.

---------------------------------------------------------------------------------------
Preparing the input data
---------------------------------------------------------------------------------------
#. Data alignment and validation
#. Determining renewable AC profiles and excess for DC charging
#. Calculating net load


---------------------------------------------------------------------------------------
Dispatch logic
---------------------------------------------------------------------------------------
#. The first hour
#. Dynamic reserves
#. Provisional deficit
#. Operating generators
#. Charge storage
#. Discharge storage (first round)
#. Start generators
#. Discharge storage (second round)


---------------------------------------------------------------------------------------
Issues in the current approach
Limitations
---------------------------------------------------------------------------------------

#. Place of storage in dispatch sequence means it reduces fossil dispatch more than it
helps reliability. It can even make the latter worse by deferring fossil start-up
until it is too late, i.e. make the required ramp steeper than the resources can
Expand All @@ -19,11 +38,3 @@ Issues in the current approach
deficits in those hours.
#. No ability to save state of charge for future needs or deliberately bank it by
charging with fossil. This is absolutely required for storage to replace peakers.

---------------------------------------------------------------------------------------
Things to consider without adding look-aheads
---------------------------------------------------------------------------------------
#. Enforce minimum uptime for fossil generators. This will provide more opportunities
for charging storage.
#. Segment dispatchable generators and storage to allow interspersing in the dispatch
sequence.
11 changes: 9 additions & 2 deletions docs/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,28 @@ What's New?
^^^^^^^^^^^
* Initial implementation of dynamic storage reserves. If storage does not have a
reserve or the reserve is ``0.0``, we calculate a dynamic reserve based on the next
24 hours of net load using :eq:`reserve`.
24 hours of net load using :eq:`reserve`. The value of ``coeff`` can be set manually
when creating :class:`.DispatchModel`, or automatically (default) by trying a number
of values between 0.0 and 1.5 and selecting the one that best minimizes deficit and
curtailment, using :func:`dispatch.engine.choose_best_coefficient`.

.. math::
:label: reserve

ramp &= \frac{max(load_{h+1}, ..., load_{h+24})}{load_h} - 1

reserve &= 1 - e^{-1.5 ramp}
reserve &= 1 - e^{-coeff \times ramp}

* Additional deficit and curtailment metrics in
:meth:`.DispatchModel.system_level_summary`.
* :meth:`.DispatchModel.dispatchable_summary` and :meth:`.DispatchModel.full_output`
now include all columns provided in ``<x>_specs``.
* Enable multiple storage generators under a single ``plant_id_eia`` so long as they
don't share a ``plant_id_eia`` with a renewable generator.
* :meth:`.DispatchModel.system_level_summary` allows for the roll-up of storage
facilities to create higher-level metrics using the ``storage_rollup`` parameter.
* :meth:`.DispatchModel.hourly_data_check` allows exploration of hours preceding and
including both deficit and curtailment hours.

Bug Fixes
^^^^^^^^^
Expand Down
Loading