# README: Optimized hourly dispatch outputs for large-scale solar + storage projects

This README describes the plant-level hourly CSV files produced by Lawrence Berkeley National Laboratory's optimized dispatch modeling of large-scale co-located photovoltaic-plus-storage (PV+S) projects. It is intended to help users interpret the output columns in the released data files. It does not restate the broader project motivation or findings described on the OEDI project page.

## File organization and naming

Each CSV represents one PV+S project and is named using the project's EIA Plant ID, for example:

```text
57912.csv
```

The released scenarios are organized by optimization assumptions, for example:

```text
Grid Charge True, DegThresh 10, AS True, Market DA/
Grid Charge False, DegThresh 10, AS True, Market DA/
```

The scenario labels mean:

- **Grid Charge True**: the battery is allowed to charge from the grid when economically optimal.
- **Grid Charge False**: grid charging is restricted; storage charging is limited to the co-located solar resource, with additional restrictions on regulation-down participation to avoid implicit grid charging.
- **DegThresh 10**: the optimization includes a $10/MWh degradation penalty for modeled battery cycling and ancillary-service deployment. This penalty affects dispatch decisions but is not a column in the hourly CSVs.
- **AS True**: the optimization allows ancillary-service participation where the relevant market products are represented in the input data.
- **Market DA**: the base energy-market dispatch is optimized against the day-ahead market price series used in the model. In this release, that price series may include upstream capacity-value adders used for valuation modeling; see `price_energy` below.

## Time index

The first column of each CSV is the timestamp index. Timestamps are hourly and in UTC. Each row represents one hour beginning at the timestamp. For example, `2020-01-01 00:00:00+00:00` represents the hour beginning at midnight UTC.

The date range can vary by project. Projects are generally included only for full calendar years after both the solar and storage components are operational in the modeling sample.

## Units and sign conventions

Unless otherwise noted:

- Power and dispatch columns are in **MW**. Because the data are hourly, summing an MW column over rows gives **MWh**.
- State-of-charge is in **MWh-equivalent model units**.
- Energy prices are in **$/MWh**.
- Ancillary-service award prices are in **$/MW-h**.
- Positive dispatch generally indicates export or discharge to the grid; negative net dispatch indicates grid import or charging.
- Very small negative values, such as `-1e-15`, are numerical solver tolerances and can be treated as zero.

For most public uses, the columns ending in `_ac` are the safest physical dispatch columns because they provide a consistent AC-equivalent interpretation across both AC-coupled and DC-coupled projects.

## Column dictionary

### Solar and hybrid energy dispatch

| Column | Units | Interpretation |
|---|---:|---|
| `profile_input` | MW | Modeled available solar generation profile before optimized curtailment, in the model's native units. For AC-coupled projects this is AC; for DC-coupled projects this is a DC-side profile used internally by the optimizer. |
| `profile_actual` | MW | Optimized solar generation after curtailment, in native model units. This is solar energy accepted by the hybrid system before separating direct solar export from solar energy used to charge the battery. |
| `asset_dispatch` | MW | Net base energy-market dispatch of the hybrid resource at the grid interface, excluding ancillary-service deployment energy. Positive values indicate net export; negative values indicate net grid import, which can occur in the Grid Charge True scenario. |
| `solar_bleed` | MW | Modeled solar curtailment, in native model units. For AC-coupled projects this is approximately `profile_input - profile_actual`, clipped at zero. For DC-coupled projects it accounts for PV that can be routed to the battery on the DC side. |
| `solar_grid_ac` | MW_AC | Estimated solar generation delivered directly to the grid in AC terms, after accounting for solar used to charge the battery and modeled curtailment. This is a derived output intended for valuation and interpretation, not a separate optimization variable. |
| `profile_input_ac` | MW_AC | Available solar generation converted to AC-equivalent terms. This is the recommended solar denominator for comparing projects and calculating generation-weighted metrics. |
| `solar_bleed_ac` | MW_AC | Modeled solar curtailment in AC-equivalent terms. |

### Storage dispatch and state of charge

| Column | Units | Interpretation |
|---|---:|---|
| `storage_in` | MW | Battery charging power in native model units. In AC-coupled projects this is AC-side charging. In DC-coupled projects this is DC-side charging before AC-equivalent conversion. |
| `storage_out` | MW | Battery discharging power in native model units. In AC-coupled projects this is AC-side discharge. In DC-coupled projects this is DC-side discharge before AC-equivalent conversion. |
| `storage_dispatch` | MW | Native net storage dispatch, calculated as `storage_out - storage_in`. Positive values indicate discharge; negative values indicate charging. This excludes ancillary-service deployment. |
| `SoC` | MWh-equivalent | Battery state of charge at the end of the modeled hour, in native model energy units. |
| `storage_in_ac` | MW_AC | Battery charging power converted to AC-equivalent terms. Recommended for cross-project analysis. |
| `storage_out_ac` | MW_AC | Battery discharging power converted to AC-equivalent terms. Recommended for cross-project analysis. |
| `storage_dispatch_ac` | MW_AC | AC-equivalent net storage dispatch, calculated as `storage_out_ac - storage_in_ac`. Positive values indicate discharge; negative values indicate charging. This excludes ancillary-service deployment energy. |

Note: `storage_dispatch_ac` describes the base energy-market storage dispatch. If users want an AS-inclusive storage dispatch estimate, they should add upward AS deployment and subtract regulation-down deployment, for example:

```python
storage_dispatch_ac_including_as = (
    df["storage_dispatch_ac"]
    + df["reg_up_deploy"]
    + df["spin_deploy"]
    + df["nonspin_deploy"]
    + df["ecrs_deploy"]
    - df["reg_dn_deploy"]
)
```

A corresponding AS-inclusive net hybrid grid dispatch can be approximated as:

```python
asset_dispatch_including_as = (
    df["asset_dispatch"]
    + df["reg_up_deploy"]
    + df["spin_deploy"]
    + df["nonspin_deploy"]
    + df["ecrs_deploy"]
    - df["reg_dn_deploy"]
)
```

### Ancillary-service awards

Ancillary-service award columns represent modeled reserve capacity awards. They are capacity commitments, not necessarily actual energy deployment.

| Column | Units | Interpretation |
|---|---:|---|
| `reg_up_award` | MW | Modeled regulation-up award. Regulation up represents the ability to increase net injection or reduce net charging relative to the base dispatch. |
| `reg_dn_award` | MW | Modeled regulation-down award. Regulation down represents the ability to reduce net injection or increase charging relative to the base dispatch. |
| `spin_award` | MW | Modeled spinning-reserve award where this product is available in the represented market. |
| `nonspin_award` | MW | Modeled non-spinning-reserve award where this product is available in the represented market. |
| `ecrs_award` | MW | Modeled ERCOT Contingency Reserve Service award, or an analogous reserve product in markets where this column was used. Values are zero where the product is not modeled. |
| `as_out_sumtot_award` | MW | Sum of upward ancillary-service awards modeled as potential battery discharge: `reg_up_award + spin_award + nonspin_award + ecrs_award`. This does not include `reg_dn_award`, which is a downward service. |

Caution for regulation products: in markets modeled as single regulation-product markets, the optimizer may report equal `reg_up_award` and `reg_dn_award` values as a modeling convention. These should not automatically be interpreted as two separately compensated products. Revenue calculations should follow the market-specific convention used in the valuation model.

### Ancillary-service deployment

Deployment columns represent modeled energy deployment associated with ancillary-service awards. In this implementation, deployment is represented as a fixed fraction of the corresponding award rather than an observed AGC or reserve-deployment signal.

| Column | Units | Interpretation |
|---|---:|---|
| `reg_up_deploy` | MW | Modeled regulation-up deployment. This increases net injection or reduces charging relative to the base dispatch. |
| `reg_dn_deploy` | MW | Modeled regulation-down deployment. This represents additional charging or reduced injection relative to the base dispatch. In AS-inclusive net-dispatch calculations, subtract this column. |
| `spin_deploy` | MW | Modeled spinning-reserve deployment. |
| `nonspin_deploy` | MW | Modeled non-spinning-reserve deployment. |
| `ecrs_deploy` | MW | Modeled ECRS or analogous reserve deployment. |
| `as_out_sumtot_deploy` | MW | Sum of upward AS deployment: `reg_up_deploy + spin_deploy + nonspin_deploy + ecrs_deploy`. This does not include `reg_dn_deploy`. |

### Price columns

Price columns are included to document the prices used by the optimization. They should be interpreted as model inputs, not observed plant settlements.

| Column | Units | Interpretation |
|---|---:|---|
| `price_energy` | $/MWh | Energy price series used for base energy-market optimization. For the `Market DA` release, this is the day-ahead price series used by the model. In the workflow used for this release, the energy price series can include an upstream capacity-value adder used to represent capacity value in selected hours, so it should not always be interpreted as raw day-ahead LMP. |
| `price_reg_up` | $/MW-h | Regulation-up award price used in the optimization. |
| `price_reg_dn` | $/MW-h | Regulation-down award price used in the optimization. |
| `price_spin` | $/MW-h | Spinning-reserve award price used in the optimization. |
| `price_nonspin` | $/MW-h | Non-spinning-reserve award price used in the optimization. |
| `price_ecrs` | $/MW-h | ECRS or analogous reserve award price used in the optimization. |
| `price_as_deploy` | $/MWh | Energy price basis used for upward ancillary-service deployment. In the workflow used for this release, AS deployment is typically valued using the selected AS deployment energy-price basis rather than the base `price_energy` column. Regulation-down deployment uses the opposite sign convention in the optimization. |

## Recommended columns for common analyses

For most external users interested in physical dispatch profiles:

- Available solar generation: `profile_input_ac`
- Direct solar-to-grid output: `solar_grid_ac`
- Solar curtailment: `solar_bleed_ac`
- Battery charging: `storage_in_ac`
- Battery discharging: `storage_out_ac`
- Net storage dispatch: `storage_dispatch_ac`
- Base net hybrid grid dispatch: `asset_dispatch`
- Ancillary-service awards: `*_award` columns
- Ancillary-service deployment: `*_deploy` columns

## Important limitations for interpreting these outputs

These CSVs contain optimized dispatch profiles, not observed project operations. The model uses perfect foresight of the price and solar-generation series used in the optimization and represents market participation subject to simplified operational constraints. Ancillary-service deployment is modeled parametrically rather than from observed deployment instructions. The files therefore describe an optimized benchmark under the stated scenario assumptions, not actual plant dispatch or actual settlement revenue.

The outputs also do not contain project metadata such as plant name, balancing authority, PV capacity, storage power capacity, storage duration, coupling configuration, or commercial operation date. Those fields should be joined from the accompanying project metadata file using the EIA Plant ID embedded in each CSV filename.