Except where otherwise noted, this content is Copyright (c) 2020, RTE and licensed under a CC-BY-4.0 license.
When you want to simulate adequacy in a network for the next weeks or month, you need to create stochastic study, and generate scenarios (c.f. Begin Stochastic)
Workflow is the preprocessing module for Hadar. Workflow will help user to generate scenarios and sample them to create a stochastic study. It’s a toolbox to create pipelines to transform data for optimizer.
With workflow, you will plug stage themself to create pipeline. Stages can already be developed or you can develop your own Stage.
To understand workflow power we will generate data previously used in Begin Stochastic
Let’s begin by constant production like nuclear and gas. These productions are not stochastic by default. However fault can occur and it’s what we will generate. For this example all stages belongs to hadar ready-to-use library.
import hadar as hd import numpy as np import pandas as pd import plotly.graph_objects as go
# We generate 5 fault scenarios where a fault remove 100 MW with an odd of 1% by timestep, # minimum downtime are one step (one hour) and maximum downtime are 12 step. fault_pipe = hd.RepeatScenario(n=5) + hd.Fault(loss=300, occur_freq=0.01, downtime_min=1, downtime_max=12) + hd.ToShuffler('quantity')
In this case, we have to develop our own stage. Let’s begin with wind. We know max wind power, we will apply a linear random between 0 to max for each timestep
class WindRandom(hd.Stage): def __init__(self): hd.Stage.__init__(self, plug=hd.FreePlug()) # We will see in other example what is FreePlug # Method to implement from Stage to create your own Stage with its behaviour def _process_timeline(self, timeline: pd.DataFrame) -> pd.DataFrame: return timeline * np.random.rand(*timeline.shape)
wind_pipe = hd.RepeatScenario(n=3) + WindRandom() + hd.ToShuffler('quantity')
Then we generate load. For load we will apply a cumulative normal distribution with given value as mean.
class LoadRandom(hd.Stage): def __init__(self): hd.Stage.__init__(self, plug=hd.FreePlug()) # We will see in other example what is FreePlug # Method to implement from Stage to create your own Stage with its behaviour def _process_timeline(self, timeline: pd.DataFrame) -> pd.DataFrame: return timeline + np.cumsum(np.random.randn(*timeline.shape) * 10, axis=0)
load_pipe = hd.RepeatScenario(n=3) + LoadRandom() + hd.ToShuffler('quantity')
We use Shuffler object to generate data by pipeline and then sample 10 scenarios
ones = pd.DataFrame({'quantity': np.ones(168)}) # Load are simply a sinus shape sinus = pd.DataFrame({'quantity': np.sin(np.linspace(-1, -1+np.pi*14, 168))*.2 + .8}) shuffler = hd.Shuffler() shuffler.add_pipeline(name='gas', data=ones * 1000, pipeline=fault_pipe) shuffler.add_pipeline(name='nuclear', data=ones * 5000, pipeline=fault_pipe) shuffler.add_pipeline(name='eolien', data=ones * 1000, pipeline=wind_pipe) shuffler.add_pipeline(name='load_A', data=sinus * 2000, pipeline=load_pipe) shuffler.add_pipeline(name='load_B', data=sinus * 3000, pipeline=load_pipe) shuffler.add_pipeline(name='load_D', data=sinus * 1000, pipeline=load_pipe)
sampling = shuffler.shuffle(nb_scn=10)
def input_plot(title, raw, generate): x = np.arange(raw.size) fig = go.Figure() for i, scn in enumerate(generate): fig.add_trace(go.Scatter(x=x, y=scn, name='scn %d' % i, line=dict(color='rgba(100, 100, 100, 0.2)'))) fig.add_traces(go.Scatter(x=x, y=raw.values.T[0], name='raw')) fig.update_layout(title_text=title) return fig
input_plot('Gas', ones * 1000, sampling['gas'])