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

Allow Network Charges #73

Merged
merged 16 commits into from
Sep 14, 2024
10 changes: 5 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ TEST_ARGS =
export

test: setup-test test-docs
pytest tests --cov=energypylinear --cov-report=html -n $(PARALLEL) --color=yes --durations=5 --verbose --ignore tests/phmdoctest $(TEST_ARGS)
pytest tests --cov=energypylinear --cov-report=html --cov-report=term-missing -n $(PARALLEL) --color=yes --durations=5 --verbose --ignore tests/phmdoctest $(TEST_ARGS)
# -coverage combine
# -coverage html
-coverage report
Expand All @@ -56,7 +56,7 @@ generate-test-docs: setup-test
bash ./tests/generate-test-docs.sh

test-docs: setup-test generate-test-docs
pytest tests/phmdoctest -n $(PARALLEL) --dist loadfile --color=yes --verbose $(TEST_ARGS)
pytest tests/phmdoctest -n 1 --dist loadfile --color=yes --verbose $(TEST_ARGS)


# ----- CHECK -----
Expand All @@ -71,7 +71,7 @@ static: setup-static
rm -rf ./tests/phmdoctest
mypy --version
mypy $(MYPY_ARGS) ./energypylinear
mypy $(MYPY_ARGS) ./tests
mypy $(MYPY_ARGS) ./tests --explicit-package-bases

lint: setup-check
rm -rf ./tests/phmdoctest
Expand All @@ -81,13 +81,13 @@ lint: setup-check
ruff format --check **/*.py
poetry check

CHECK_DOCSTRINGS=./energypylinear/assets/battery.py ./energypylinear/objectives.py
CHECK_DOCSTRINGS=./energypylinear/objectives.py ./energypylinear/assets/battery.py ./energypylinear/assets/renewable_generator.py

# currently only run manually
lint-docstrings:
flake8 --extend-ignore E501 --exclude=__init__.py,poc --exit-zero $(CHECK_DOCSTRINGS)
pydocstyle $(CHECK_DOCSTRINGS)
pylint $(CHECK_DOCSTRINGS)
# pylint $(CHECK_DOCSTRINGS)


# ----- FORMATTING -----
Expand Down
20 changes: 11 additions & 9 deletions docs/docs/assets/battery.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ asset = epl.Battery(
freq_mins=60,
initial_charge_mwh=1,
final_charge_mwh=3,
name="battery"
name="battery",
include_spill=True
)
simulation = asset.optimize()

Expand All @@ -36,12 +37,13 @@ assert all(
"site-import_power_mwh",
"site-export_power_mwh",
"site-electricity_prices",
"site-export_electricity_prices",
"site-electricity_carbon_intensities",
"site-gas_prices",
"site-electric_load_mwh",
"site-high_temperature_load_mwh",
"site-low_temperature_load_mwh",
"site-low_temperature_generation_mwh",
"site-gas_prices",
"site-electric_load_mwh",
"spill-electric_generation_mwh",
"spill-electric_load_mwh",
"spill-high_temperature_generation_mwh",
Expand All @@ -68,7 +70,7 @@ assert all(
"total-spills_mwh",
"total-electric_loss_mwh",
"site-electricity_balance_mwh",
]
],
)
```

Expand Down Expand Up @@ -153,11 +155,11 @@ print(balance)

```
input accumulation output balance import generation export load charge discharge loss spills soc
0 0.444444 -0.444444 0.0 True 0.444444 0.0 0.0 0.0 0.444444 0.0 0.044444 0.0 0.0
1 2.000000 -2.000000 0.0 True 2.000000 0.0 0.0 0.0 2.000000 0.0 0.200000 0.0 0.0
2 0.000000 2.000000 2.0 True 0.000000 0.0 2.0 0.0 0.000000 2.0 0.000000 0.0 0.0
3 2.000000 -2.000000 0.0 True 2.000000 0.0 0.0 0.0 2.000000 0.0 0.200000 0.0 0.0
4 0.000000 2.000000 2.0 True 0.000000 0.0 2.0 0.0 0.000000 2.0 0.000000 0.0 0.0
0 0.444444 -0.444444 0.0 True 0.444444 0.0 0.0 0 0.444444 0.0 0.044444 0.0 0.0
1 2.000000 -2.000000 0.0 True 2.000000 0.0 0.0 0 2.000000 0.0 0.200000 0.0 0.0
2 0.000000 2.000000 2.0 True 0.000000 0.0 2.0 0 0.000000 2.0 0.000000 0.0 0.0
3 2.000000 -2.000000 0.0 True 2.000000 0.0 0.0 0 2.000000 0.0 0.200000 0.0 0.0
4 0.000000 2.000000 2.0 True 0.000000 0.0 2.0 0 0.000000 2.0 0.000000 0.0 0.0
```

In the first interval, we charge the battery with `0.444444 MWh` - `0.4 MWh` goes into increasing the battery state of charge from `0.0 MWh` to `0.4 MWh`, with the balance `0.044444 MWh` going to battery losses.
Expand Down
14 changes: 4 additions & 10 deletions docs/docs/assets/chp.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ asset = epl.CHP(
low_temperature_efficiency_pct=0.2,
electricity_prices=[100, 50, 200, -100, 0, 200, 100, -100],
high_temperature_load_mwh=[100, 50, 200, 40, 0, 200, 100, 100],
low_temperature_load_mwh=20,
low_temperature_load_mwh=20
)

simulation = asset.optimize()
Expand All @@ -47,19 +47,13 @@ assert all(
"site-import_power_mwh",
"site-export_power_mwh",
"site-electricity_prices",
"site-export_electricity_prices",
"site-electricity_carbon_intensities",
"site-gas_prices",
"site-electric_load_mwh",
"site-high_temperature_load_mwh",
"site-low_temperature_load_mwh",
"site-low_temperature_generation_mwh",
"site-gas_prices",
"site-electric_load_mwh",
"spill-electric_generation_mwh",
"spill-electric_load_mwh",
"spill-high_temperature_generation_mwh",
"spill-low_temperature_generation_mwh",
"spill-high_temperature_load_mwh",
"spill-low_temperature_load_mwh",
"spill-gas_consumption_mwh",
"chp-electric_generation_mwh",
"chp-gas_consumption_mwh",
"chp-high_temperature_generation_mwh",
Expand Down
8 changes: 5 additions & 3 deletions docs/docs/assets/evs.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ asset = epl.EVs(
charger_turndown=0.1,
electricity_prices=electricity_prices,
charge_events=charge_events,
include_spill=True
)

simulation = asset.optimize()
Expand All @@ -40,12 +41,13 @@ assert all(
"site-import_power_mwh",
"site-export_power_mwh",
"site-electricity_prices",
"site-export_electricity_prices",
"site-electricity_carbon_intensities",
"site-gas_prices",
"site-electric_load_mwh",
"site-high_temperature_load_mwh",
"site-low_temperature_load_mwh",
"site-low_temperature_generation_mwh",
"site-gas_prices",
"site-electric_load_mwh",
"spill-electric_generation_mwh",
"spill-electric_load_mwh",
"spill-high_temperature_generation_mwh",
Expand Down Expand Up @@ -100,7 +102,7 @@ assert all(
"total-spills_mwh",
"total-electric_loss_mwh",
"site-electricity_balance_mwh",
]
],
)
```

Expand Down
13 changes: 9 additions & 4 deletions docs/docs/assets/heat-pump.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ asset = epl.HeatPump(
electricity_prices=[100, -100],
high_temperature_load_mwh=3.0,
low_temperature_generation_mwh=3.0,
include_spill=True
)
simulation = asset.optimize(verbose=False)
print(
Expand All @@ -43,12 +44,13 @@ assert all(
"site-import_power_mwh",
"site-export_power_mwh",
"site-electricity_prices",
"site-export_electricity_prices",
"site-electricity_carbon_intensities",
"site-gas_prices",
"site-electric_load_mwh",
"site-high_temperature_load_mwh",
"site-low_temperature_load_mwh",
"site-low_temperature_generation_mwh",
"site-gas_prices",
"site-electric_load_mwh",
"spill-electric_generation_mwh",
"spill-electric_load_mwh",
"spill-high_temperature_generation_mwh",
Expand All @@ -75,7 +77,7 @@ assert all(
"total-spills_mwh",
"total-electric_loss_mwh",
"site-electricity_balance_mwh",
]
],
)
```

Expand Down Expand Up @@ -126,6 +128,7 @@ asset = epl.HeatPump(
electricity_prices=[100, -100],
high_temperature_load_mwh=3.0,
low_temperature_generation_mwh=4.0,
include_spill=True
)
simulation = asset.optimize(verbose=4)
print(simulation.results[
Expand Down Expand Up @@ -171,6 +174,7 @@ asset = epl.HeatPump(
electricity_prices=[-100, -100, -100],
high_temperature_load_mwh=[3.0, 0.5, 3.0],
low_temperature_generation_mwh=[4.0, 4.0, 0.5],
include_spill=True,
include_valve=False
)
simulation = asset.optimize(
Expand Down Expand Up @@ -219,7 +223,8 @@ asset = epl.HeatPump(
electricity_prices=[-100, -100, -100],
high_temperature_load_mwh=[3.0, 0.5, 3.0],
low_temperature_generation_mwh=[4.0, 4.0, 0.0],
include_valve=True
include_valve=True,
include_spill=True,
)
simulation = asset.optimize(
verbose=4,
Expand Down
7 changes: 4 additions & 3 deletions docs/docs/assets/renewable-generator.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ assert all(
"site-import_power_mwh",
"site-export_power_mwh",
"site-electricity_prices",
"site-export_electricity_prices",
"site-electricity_carbon_intensities",
"site-gas_prices",
"site-electric_load_mwh",
"site-high_temperature_load_mwh",
"site-low_temperature_load_mwh",
"site-low_temperature_generation_mwh",
"site-gas_prices",
"site-electric_load_mwh",
"wind-electric_generation_mwh",
"total-electric_generation_mwh",
"total-electric_load_mwh",
Expand All @@ -38,7 +39,7 @@ assert all(
"total-spills_mwh",
"total-electric_loss_mwh",
"site-electricity_balance_mwh",
]
],
)
```

Expand Down
88 changes: 88 additions & 0 deletions docs/docs/how-to/custom-interval-data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
Interval data is a key input to an `energypylinear` simulation.

By default, `energypylinear` accepts interval data for things like electricity prices, carbon intensities and site electricity and heat consumption:

<!--phmdoctest-mark.skip-->
```python
--8<-- "energypylinear/assets/site.py:site"
```

These arguments are passed to the `SiteIntervalData` object, which is responsible for managing interval data for a site:

```python
import energypylinear as epl

asset = epl.Battery(electricity_prices=[100, 50, 200])
print(asset.site.cfg.interval_data)
```

```
electricity_prices=array([100., 50., 200.]) export_electricity_prices=array([100., 50., 200.]) electricity_carbon_intensities=array([0.1, 0.1, 0.1]) gas_prices=array([20, 20, 20]) electric_load_mwh=array([0, 0, 0]) high_temperature_load_mwh=array([0, 0, 0]) low_temperature_load_mwh=array([0, 0, 0]) low_temperature_generation_mwh=array([0, 0, 0]) idx=array([0, 1, 2])
```

## Custom Interval Data

Often you will want to use different interval data for your simulation - for example modelling site network charges.

Additional keyword arguments passed into a site or asset `__init__` are attempted to be parsed into interval data. These will be parsed into site interval data, even if passed into an asset.

For example, when we pass in a `network_charge` argument, we end up with a `network_charge` attribute on our `asset.site.cfg.interval_data` object:

```python
import energypylinear as epl

electricity_prices = [100, 50, 200]
asset = epl.Battery(electricity_prices=[100, 50, 200], network_charges=[10, 20, 30])
print(asset.site.cfg.interval_data)
```

```
electricity_prices=array([100., 50., 200.]) export_electricity_prices=array([100., 50., 200.]) electricity_carbon_intensities=array([0.1, 0.1, 0.1]) gas_prices=array([20, 20, 20]) electric_load_mwh=array([0, 0, 0]) high_temperature_load_mwh=array([0, 0, 0]) low_temperature_load_mwh=array([0, 0, 0]) low_temperature_generation_mwh=array([0, 0, 0]) idx=array([0, 1, 2]) network_charges=array([10., 20., 30.])
```

## Custom Interval Data in Simulation Results

All custom interval data will appear in the simulation results:

```python
import energypylinear as epl

asset = epl.Battery(electricity_prices=[100, 50, 200], network_charges=[10, 20, 30])
simulation = asset.optimize(verbose=3)
print(simulation.results["site-network_charges"])
```

```
0 10.0
1 20.0
2 30.0
Name: site-network_charges, dtype: float64
```

## Custom Interval Data in Custom Objective Functions

Custom interval data can be used in a custom objective function:

```python
import energypylinear as epl

asset = epl.Battery(electricity_prices=[100, 50, 200], network_charges=[10, 20, 30])
simulation = asset.optimize(
objective={
"terms": [
{
"asset_type": "site",
"variable": "import_power_mwh",
"interval_data": "electricity_prices",
},
{
"asset_type": "site",
"variable": "export_power_mwh",
"interval_data": "electricity_prices",
"coefficient": -1,
},
]
},
verbose=3
)
```
2 changes: 1 addition & 1 deletion docs/docs/how-to/custom-objectives.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ print(simulate(carbon_price=50, seed=42, n=72))
```

```
<energypylinear.SimulationResult feasible:True, rows:72, cols:28>
<energypylinear.SimulationResult feasible:True, rows:72, cols:29>
```

We can validate that our custom objective function is working as expected by running simulations across many carbon prices:
Expand Down
6 changes: 4 additions & 2 deletions docs/docs/how-to/dispatch-site.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Multiple Assets with the Site API

The `epl.Site` allows optimizing many assets at the same time. The site is a list of `energypylinear` asset models, like `epl.Battery` or `epl.RenewableGenerator`.
`energypylinear` can optimize many assets in a single linear program.

Below we give some examples of typical configurations of energy assets using an `epl.Site`.
The `epl.Site` accepts a list of `energypylinear` asset models, like `epl.Battery` or `epl.RenewableGenerator`.

Below are examples of typical configurations of multiple energy assets using a `epl.Site`.

## Fast & Slow Battery

Expand Down
Loading