Except where otherwise noted, this content is Copyright (c) 2020, RTE and licensed under a CC-BY-4.0 license.
We has already seen Consumption, Production and Link to attach on node. Hadar has also a Stockage element. We will work on a simple network with two nodes : one with two producitons (stochastic and constant) other with consumption and stockage
img
import numpy as np import hadar as hd
np.random.seed(12684681) eolien = np.random.rand(168) * 500 + 200 # random from 200 to 700 load = np.sin(np.linspace(-1, -1+np.pi*14, 168)) * 250 + 750 # sinus moving 500 to 1000
Start storage by remove storage !
study = hd.Study(horizon=eolien.size)\ .network()\ .node('a')\ .production(name='gas', cost=100, quantity=200)\ .production(name='nulcear', cost=50, quantity=300)\ .production(name='eolien', cost=10, quantity=eolien)\ .node('b')\ .consumption(name='load', cost=10 ** 6, quantity=load)\ .link(src='a', dest='b', cost=1, quantity=2000)\ .build() optim = hd.LPOptimizer() res = optim.solve(study) plot_without = hd.HTMLPlotting(agg=hd.ResultAnalyzer(study=study, result=res), unit_symbol='MW')
plot_without.network().node('b').stack()
Node B has a lot of lost of load. Network has not enough power to sustain consumption during peak.
plot_without.network().node('a').stack()
Productions are used immediately just to match load
Now we add a storage. In our case cell efficiency is 80%, efficient must be < 1, Hadar use eff=0.99 as default. Other important parameter is cost it represents cost of storage per quantity during on time-step. cost at 0 or positive mean we want to minimize storage used. By default Hadar use cost=0.
eff=0.99
cost
cost=0
So in the configuration, cost=0and eff=0.80. Therefore, a quantity stored costs 25% (\(\frac{1}{0.8} = 1.25\)) higher than same production without stored before. At any time Hadar has choice between these productions and cost.
eff=0.80
Prod
use cost
stored before use cost
eolien
10
12,5
nuclear
50
62,75
gas
100
125
Moreover than just fix lost of load, storage can also optimize productions. Looks, a stored nuclear or eolien production is cheaper than a direct gas production. Hadar knows it and will use it !
study = hd.Study(horizon=eolien.size)\ .network()\ .node('a')\ .production(name='gas', cost=100, quantity=200)\ .production(name='nulcear', cost=50, quantity=300)\ .production(name='eolien', cost=10, quantity=eolien)\ .node('b')\ .consumption(name='load', cost=10 ** 6, quantity=load)\ .storage(name='cell', init_capacity=200, capacity=800, flow_in=400, flow_out=400, eff=.8)\ .link(src='a', dest='b', cost=1, quantity=2000)\ .build() res = optim.solve(study) plot = hd.HTMLPlotting(agg=hd.ResultAnalyzer(study=study, result=res), unit_symbol='MW')
plot.network().node('b').stack()
Yeah ! We avoid network shutdown !
plot.network().node('b').storage('cell').candles()
Hadar fills cell before each peaks.
plot.network().node('a').stack()
And yes, Hadars starts nuclear before peak, and use less gas during peak.
What happen, if we use negative cost ?
In this case, storage has some interest. If interest is higher than gain from optimizing productions. Hadar will automatically fill cell.
study = hd.Study(horizon=eolien.size)\ .network()\ .node('a')\ .production(name='gas', cost=100, quantity=200)\ .production(name='nulcear', cost=50, quantity=300)\ .production(name='eolien', cost=10, quantity=eolien)\ .node('b')\ .consumption(name='load', cost=10 ** 6, quantity=load)\ .storage(name='cell', init_capacity=200, capacity=800, flow_in=400, flow_out=400, eff=.8, cost=-10)\ .link(src='a', dest='b', cost=1, quantity=2000)\ .build() res = optim.solve(study) plot_cost_neg = hd.HTMLPlotting(agg=hd.ResultAnalyzer(study=study, result=res), unit_symbol='MW')
plot_cost_neg.network().node('b').storage('cell').candles()
Hadar doesn’t try to optimize import, now it saves into storage to earn interest.