@@ -83,17 +83,20 @@ set_default!(nw, VIndex(5, :P_ref), 1.5) # generator
83
83
nothing # hide #md
84
84
85
85
#=
86
- We can use `find_fixpoint` to find a valid initial condition of the network
86
+ We can use `find_fixpoint` to find a valid initial condition of the network.
87
+ We also use `set_defaults!` to overwirte all the default values for states and parameters
88
+ with the one of the fixpoint, this means that we can allways re-extract this setpoint by
89
+ using `u0 = NWState(nw)`.
87
90
=#
88
91
u0 = find_fixpoint (nw)
89
- set_defaults! (nw, u0) # overwrite the default values with the fixpoint values
92
+ set_defaults! (nw, u0)
90
93
nothing # hide #md
91
94
92
95
#=
93
96
## Component-based Callbacks
94
97
95
98
For the component based callback we need to define a condtion and an affect.
96
- Both functions take trhee inputs:
99
+ Both functions take three inputs:
97
100
- the actual function `f`
98
101
- the states which to be accessed `sym`
99
102
- the parameters to be accessed `psym`
@@ -119,38 +122,45 @@ nothing #hide #md
119
122
#=
120
123
The system starts at a steady state.
121
124
In order to see any dynamic, we need to fail a first line intentionally.
122
- For that we define a PresetTimecallback from DiffEqCallbacks library:
125
+ For that we use a [`PresetTimeComponentCallback`](@ref), which triggers an
126
+ `ComponentAffect` at a given time. We can reuse the previously defined component
127
+ affect for that and just add it to line number 5 at time 1.0.
123
128
=#
124
- trip_first_cb = PresetTimeCallback (1.0 , integrator -> begin
125
- @info " Trip initial line 5 at t=$(integrator. t) "
126
- p = NWParameter (integrator)
127
- p. e[5 ,:K ] = 0
128
- auto_dt_reset! (integrator)
129
- save_parameters! (integrator)
130
- end )
129
+ trip_first_cb = PresetTimeComponentCallback (1.0 , affect)
130
+ add_callback! (nw[EIndex (5 )], trip_first_cb)
131
131
nothing
132
-
133
132
#=
134
-
133
+ When we inspect the edge model for 5 no, we see that we've registered 2 callbacks:
135
134
=#
135
+ nw[EIndex (5 )]
136
136
137
+ #=
138
+ Now we can simulate the network. We use [`get_callbacks(::Networl)`](@ref)
139
+ to generate a callback set for the whole network which represents all of the individual
140
+ component callbacks.
141
+ =#
137
142
u0 = NWState (nw)
138
143
network_cb = get_callbacks (nw)
139
- all_cb = CallbackSet (network_cb, trip_first_cb)
140
- prob = ODEProblem (nw, uflat (u0), (0 , 6 ), pflat (u0); callback= all_cb)
144
+ prob = ODEProblem (nw, uflat (u0), (0 , 6 ), pflat (u0); callback= network_cb)
141
145
sol = solve (prob, Tsit5 ());
142
146
nothing # hide #md
143
147
144
148
#=
145
- Lastly we can plot the power on all of the powerlines:
149
+ Lastly we plot the power flow on all lines using the [`eidxs`](@ref) function to generate the
150
+ symbolic indices for the states of interest:
146
151
=#
147
152
plot (sol; idxs= eidxs (sol, :, :P ))
148
153
149
154
#=
150
155
## System wide Callbacks
151
156
152
- #
157
+ The above solution relies on the `ComponentCallback` features of
158
+ NetworkDyanmics. The "low-level" API would be to use `VectorContinousCallback`
159
+ and `PresetTimeCallback` directly to achieve the same effect, essentially doing
160
+ manually what [`get_callbacks(::Network)`](@ref) is doing for us.
153
161
162
+ While not necessary in this case, this method offers more flexiblity then the
163
+ component based appraoch.
154
164
155
165
In order to implement the line failures, we need to create a `VectorContinousCallback`.
156
166
In the callback, we compare the current flow on the line with the limit. If the limit is reached,
@@ -218,28 +228,26 @@ We can combine affect and condition to form the callback.
218
228
trip_cb = VectorContinuousCallback (condition, affect!, ne (g));
219
229
220
230
#=
221
- However, there is another component missing. If we look at the powerflow on the
222
- lines in the initial steady state
223
- =#
224
- u0. e[:, :P ]
225
- #=
231
+ Similarily to before, we need to generate a initial perturbation by failing one line
232
+ using a `PresetTimeCallback`.
226
233
We see that every flow is below the trip value 1.0. Therefor we need to add a distrubance
227
234
to the network. We do this by manually disabeling line 5 at time 1.
228
235
=#
229
236
trip_first_cb = PresetTimeCallback (1.0 , integrator-> affect! (integrator, 5 ));
230
237
231
238
#=
232
- With those components, we can create the problem and solve it.
239
+ Now we are set for solving the system again. This time we create our own callback
240
+ set by combining both Callbacks manually.
233
241
=#
234
-
235
- prob = ODEProblem (nw, uflat (u0), ( 0 , 6 ), copy ( pflat (p));
236
- callback = CallbackSet (trip_cb, trip_first_cb) )
242
+ u0 = NWState (nw)
243
+ cbset = CallbackSet (trip_cb, trip_first_cb)
244
+ prob = ODEProblem (nw, uflat (u0), ( 0 , 6 ), pflat (u0); callback = cbset )
237
245
Main. test_execution_styles (prob) # testing all ex styles #src
238
- sol = solve (prob, Tsit5 ());
246
+ sol2 = solve (prob, Tsit5 ());
239
247
# # we want to test the reconstruction of the observables # hide
240
- @test all (! iszero, sol (sol . t; idxs= eidxs (sol ,:,:P ))[begin ]) # hide
241
- @test all (iszero, sol (sol . t; idxs= eidxs (sol ,:,:P ))[end ][[1 : 5 ... ,7 ]]) # hide
248
+ @test all (! iszero, sol2 (sol2 . t; idxs= eidxs (sol2 ,:,:P ))[begin ]) # hide
249
+ @test all (iszero, sol2 (sol2 . t; idxs= eidxs (sol2 ,:,:P ))[end ][[1 : 5 ... ,7 ]]) # hide
242
250
nothing # hide
243
251
244
- # Through the magic of symbolic indexing we can plot the power flows on all lines :
245
- plot (sol ; idxs= eidxs (sol ,:,:P ))
252
+ # Then again we plot the solution :
253
+ plot (sol2 ; idxs= eidxs (sol2 ,:,:P ))
0 commit comments