Tutorial 2: Dynamic Lines

Tutorial: Dynamic Lines

This tutorial will introduce an example of considering dynamic lines in LITS. Note that this tutorial is for LITS 0.2.0. Future versions will have dedicated functions to find an equilibrium point and a proper functions for running perturbations without coding directly the callbacks.

This tutorial presents a simulation of a three-bus system, with an infinite bus (represented as a voltage source behind an impedance) at bus 1, and a one d- one q- machine on bus 2 and an inverter of 19 states, as a virtual synchronous machine at bus 3. The perturbation will be the trip of two of the three circuits (triplicating its resistance and impedance) of the line that connects bus 1 and bus 3. This case also consider a dynamic line model for connection between buses 2 and 3.

This tutorial can be found on LITS/Examples repository.

Step 1: Package Initialization

using LITS
using PowerSystems
using NLsolve
using DiffEqBase
using Sundials
const PSY = PowerSystems

Step 2: Data creation

To start we will define the data structures for the network.

Buses and Branches

nodes_case9   = [Bus(1 , "Bus 1"  , "REF" , 0 , 1.02  , (min=0.94, max=1.06), 138),
                    Bus(2 , "Bus 2"  , "PV" , 0 , 1.00 , (min=0.94, max=1.06), 138),
                    Bus(3 , "Bus 3"  , "PQ" , 0 , 1.00 , (min=0.94, max=1.06), 138)]

branch_case9  =  [Line("Line1", true, 0.0, 0.0, Arc(from=nodes_case9[1], to=nodes_case9[3]), 0.01, 0.12, (from=0.1, to=0.1), 100, 1.04),
                    Line("Line2", true, 0.0, 0.0, Arc(from=nodes_case9[1], to=nodes_case9[2]), 0.01, 0.12, (from=0.1, to=0.1), 100, 1.04)]

#Trip of Line 1. Triplicates its impedance
branch_case9_fault = [Line("Line1", true, 0.0, 0.0, Arc(from=nodes_case9[1], to=nodes_case9[3]), 0.03, 0.36, (from=0.03, to=0.03), 100, 1.04),
    Line("Line2", true, 0.0, 0.0, Arc(from=nodes_case9[1], to=nodes_case9[2]), 0.01, 0.12, (from=0.1, to=0.1), 100, 1.04)]

#Dynamic Branch between nodes 2 and 3.
dyn_branch9 = [LITS.DynLine("Line3", true, Arc(from=nodes_case9[2], to=nodes_case9[3]), 0.02, 0.9, (from=0.5, to=0.5))];

Injection devices

loads_case9 =   [PowerLoad("Bus1", true, nodes_case9[1], PowerSystems.ConstantPower, 0.5, 0.1, 1.5, 0.8),
                   PowerLoad("Bus2", true, nodes_case9[2], PowerSystems.ConstantPower, 1.0, 0.3, 1.5, 0.8),
                   PowerLoad("Bus3", true, nodes_case9[3], PowerSystems.ConstantPower, 0.3, 0.1, 0.5, 0.3)]

inf_gen_case9 = StaticSource(1, #number
                    :InfBus, #name
                    nodes_case9[1],#bus
                    1.00, #VR
                    0.0, #VI
                    0.000005); #Xth

Dynamic injection devices

First we define our generator data:

######## Machine Data #########

### Case: 4th Order Model with AVR (3-bus case) ###
case9_machine =  OneDOneQMachine(0.0, #R
                                  1.3125, #Xd
                                  1.2578, #Xq
                                  0.1813, #Xd_p
                                  0.25, #Xq_p
                                  5.89, #Td0_p
                                  0.6, #Tq0_p
                                  100.0)   #MVABase

######## Shaft Data #########

### Shafts for Gen ###
case9_shaft = SingleMass(3.01, #H (M = 6.02 -> H = M/2)
                            0.0) #D

######## PSS Data #########

### No PSS ###
cases_no_pss = PSSFixed(0.0)


######## TG Data #########

### No TG ###
case9_no_tg = TGFixed(1.0) #eff


########  AVR Data #########
### AVRs for this case ###
case9_avr = AVRTypeI(20.0, #Ka - Gain
                        0.01, #Ke
                        0.063, #Kf
                        0.2, #Ta
                        0.314, #Te
                        0.35, #Tf
                        0.001, #Tr
                        5.0, #Vrmax
                        -5.0, #Vrmin
                        0.0039, #Ae - 1st ceiling coefficient
                        1.555) #Be - 2nd ceiling coefficient

### Generators ###
case9_gen = DynGenerator(1, #Number
                         :Case9Gen,
                         nodes_case9[2], #bus
                         1.0, # ω_ref,
                         1.0124, #V_ref
                         0.6, #P_ref
                         case9_machine, #machine
                         case9_shaft, #shaft
                         case9_avr, #avr
                         case9_no_tg, #tg
                         cases_no_pss); #pss

and for the inverter:

############### Inverter Data ########################

converter = AvgCnvFixedDC(138.0, #Rated Voltage
                          100.0) #Rated MVA

dc_source = FixedDCSource(1500.0) #Not in the original data, guessed.

filt = LCLFilter(0.08, #Series inductance lf in pu
                   0.003, #Series resitance rf in pu
                   0.074, #Shunt capacitance cf in pu
                   0.2, #Series reactance rg to grid connection (#Step up transformer or similar)
                   0.01) #Series resistance lg to grid connection (#Step up transformer or similar)

pll = PLL(500.0, #ω_lp: Cut-off frequency for LowPass filter of PLL filter.
          0.084, #k_p: PLL proportional gain
          4.69) #k_i: PLL integral gain

virtual_H = VirtualInertia(2.0, #Ta:: VSM inertia constant
                           400.0, #kd:: VSM damping coefficient
                           20.0, #kω:: Frequency droop gain in pu
                           2*pi*50.0) #ωb:: Rated angular frequency

Q_control = ReactivePowerDroop(0.2, #kq:: Reactive power droop gain in pu
                              1000.0) #ωf:: Reactive power cut-off low pass filter frequency

outer_control = VirtualInertiaQdroop(virtual_H, Q_control)

vsc = CombinedVIwithVZ(0.59, #kpv:: Voltage controller proportional gain
                       736.0, #kiv:: Voltage controller integral gain
                       0.0, #kffv:: Binary variable enabling the voltage feed-forward in output of current controllers
                       0.0, #rv:: Virtual resistance in pu
                       0.2, #lv: Virtual inductance in pu
                       1.27, #kpc:: Current controller proportional gain
                       14.3, #kiv:: Current controller integral gain
                       0.0, #kffi:: Binary variable enabling the current feed-forward in output of current controllers
                       50.0, #ωad:: Active damping low pass filter cut-off frequency
                       0.2) #kad:: Active damping gain

case9_inv = DynInverter(2, #number
                             :DARCO, #name
                             nodes_case9[3], #bus location
                             1.0, #ω_ref
                             0.8, #V_ref
                             0.5, #P_ref
                             -0.3, #Q_ref
                             100.0, #MVABase
                             converter, #Converter
                             outer_control, #OuterControl
                             vsc, #Voltage Source Controller
                             dc_source, #DC Source
                             pll, #Frequency Estimator
                             filt); #Output Filter

Dynamic System

case9_DynSystem = DynamicSystem(nodes_case9, #Vector of Buses
                                 branch_case9, #Vector of Branches
                                 [case9_inv, case9_gen], #Vector of Dynamic Injections
                                 vcat(inf_gen_case9, loads_case9), #Vector of Injections
                                 100.0, #MVA Base
                                 50.0, #Freq. Base
                                 dyn_branch9); #Vector of Dynamic Branches

Step 3: Initializing the problem

To initialize the problem we need to define an initial guess of the states:

dx0 = zeros(LITS.get_total_rows(case9_DynSystem))
x0 = [1.00, #V1_R
          1.00, #V2_R
          1.00, #V3_R
          0.0, #V1_I
         -0.01, #V2_I
         -0.01, #V3_I
         0.0, #δω_vsm
          0.2, #δθ_vsm
          0.025, #qm
          0.0015, #ξ_d
          -0.07, #ξ_q
          0.05, #γ_d
        -0.001, #γ_q
         0.95, #ϕ_d
         -0.10, #ϕ_q
         1.004, #vpll_d
         0.0, #vpll_q
         0.0, #ε_pll
         0.1, #δθ_pll
         0.5, #id_cv
         0.0, #iq_cv
         0.95, #vod
         -0.1, #voq
         0.49, #iod
        -0.1, #ioq
          1.0, #eq_p
          0.47, #ed_p
          0.6, #δ
          1.0, #ω
          2.1, #Vf
          0.28, #Vr1
          -0.39, #Vr2,
          1.0, #Vm
          0.5, #IL1_R
          0.5] #IL1_I

case9_inv.inner_vars[13] = 0.95 #Initialize internal variables of inverter: Vd_cnv var
case9_inv.inner_vars[14] = -0.1 #Initialize internal variables of inverter: Vq_cnv var
tspan = (0.0, 30.0);

We will use NLsolve to find the initial condition of the system:

#Find initial condition
inif! = (out,x) -> LITS.system_model!(out, dx0 ,x, ([0.0],case9_DynSystem), 0.0)
sys_solve = nlsolve(inif!, x0, xtol=:1e-8,ftol=:1e-8,method=:trust_region)
x0_init = sys_solve.zero

Step 4: Build the Simulation

#Compute Y_bus after fault
Ybus_fault = Ybus(branch_case9_fault, nodes_case9)[:,:]

#Define Fault using Callbacks
cb = DiffEqBase.DiscreteCallback(LITS.change_t_one, LITS.Y_change!)

#Define Simulation Problem
sim = DynamicSimulation(case9_DynSystem, tspan, Ybus_fault, cb, x0_init)

#Solve problem
run_simulation!(sim, IDA());

Step 5: Explore the solution

using Plots
volt = get_voltagemag_series(sim, 2)
plot(volt, xlabel="time", ylabel="Voltage [pu]", label="V_2")

zoom = [(volt[1][ix], volt[2][ix]) for (ix, s) in enumerate(volt[1]) if (s > 0.90 && s < 1.6)]
plot(zoom, xlabel="time", ylabel="Voltage [pu]", label="V_2")