From f36c79b180a801f1ca100ab18b5657081863eeac Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 9 Sep 2024 11:22:13 -0700 Subject: [PATCH 01/15] add st8c model --- src/models/generator_models/avr_models.jl | 97 +++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/src/models/generator_models/avr_models.jl b/src/models/generator_models/avr_models.jl index 748e38362..e5161b8c8 100644 --- a/src/models/generator_models/avr_models.jl +++ b/src/models/generator_models/avr_models.jl @@ -75,6 +75,17 @@ function mass_matrix_avr_entries!( return end +function mass_matrix_avr_entries!( + mass_matrix, + avr::PSY.ST8C, + global_index::Base.ImmutableDict{Symbol, Int64}, +) + mass_matrix[global_index[:Vm], global_index[:Vm]] = PSY.get_Tr(avr) + mass_matrix[global_index[:x_a3], global_index[:x_a3]] = PSY.get_T_a(avr) + mass_matrix[global_index[:x_a4], global_index[:x_a4]] = PSY.get_T_f(avr) + return +end + ################################## ##### Differential Equations ##### ################################## @@ -724,3 +735,89 @@ function mdl_avr_ode!( inner_vars[Vf_var] = E_fd return end + +function mdl_avr_ode!( + device_states::AbstractArray, + output_ode::AbstractArray, + inner_vars::AbstractArray, + dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, PSY.ST8C, TG, P}}, + h, + t, +) where {M <: PSY.Machine, S <: PSY.Shaft, TG <: PSY.TurbineGov, P <: PSY.PSS} + + #Obtain references + V_ref = get_V_ref(dynamic_device) + + #Obtain indices for component w/r to device + local_ix = get_local_state_ix(dynamic_device, PSY.ST8C) + + #Define inner states for component + internal_states = @view device_states[local_ix] + Vm = internal_states[1] # Sensed Voltage + x_a1 = internal_states[2] # Regulator Integrator + x_a2 = internal_states[3] # Field Regulator + x_a3 = internal_states[4] # Controller Integrator + x_a4 = internal_states[5] # Regulator Feedback + + #Define external states for device + Vt = sqrt(inner_vars[VR_gen_var]^2 + inner_vars[VI_gen_var]^2) # machine's terminal voltage + Vs = inner_vars[V_pss_var] # PSS output + Ifd = inner_vars[Xad_Ifd_var] # machine's field current in exciter base + + #Get parameters + avr = PSY.get_avr(dynamic_device) + SW1_Flag = PSY.get_SW1_flags(avr) + if SW1_Flag == 1 + error("Source from generator terminal voltage not supported.") + end + Tr = PSY.get_Tr(avr) + K_pr = PSY.get_K_pr(avr) + K_ir = PSY.get_K_ir(avr) + Vpi_min, Vpi_max = PSY.get_Vpi_lim(avr) + K_pa = PSY.get_K_pa(avr) + K_ia = PSY.get_K_ia(avr) + Va_min, Va_max = PSY.get_Va_lim(avr) + K_a = PSY.get_K_a(avr) + T_a = PSY.get_T_a(avr) + Vr_min, Vr_max = PSY.get_Vr_lim(avr) + K_f = PSY.get_K_f(avr) + T_f = PSY.get_T_f(avr) + K_c1 = PSY.get_K_c1(avr) + K_p = PSY.get_K_p(avr) + K_i2 = PSY.get_K_i2(avr) + VB1_max = PSY.get_VB1_max(avr) + + if K_i2 != 0.0 + error("Feedforward Current for AVR ST8C not implemented yet.") + end + #TODO: Implement Terminal Current FF for AVR + V_b2 = 0.0 + #TODO: Implement Voltage Compensation if needed + V_e = K_p + + # Compute block derivatives + _, dVm_dt = low_pass_mass_matrix(Vt, Vm, 1.0, Tr) + V_pi_in = V_ref + Vs - Vm + Ifd_ref, dxa1_dt = pi_block_nonwindup(V_pi_in, x_a1, K_pr, K_ir, Vpi_min, Vpi_max) + Ifd_diff = Ifd_ref - x_a4 + pi_out, dxa2_dt = pi_block_nonwindup(Ifd_diff, x_a2, K_pa, K_ia, Va_min, Va_max) + _, dxa3_dt = low_pass_nonwindup_mass_matrix(pi_out, x_a3, K_a, T_a, Vr_min, Vr_max) + _, dxa4_dt = low_pass_mass_matrix(Ifd, x_a4, K_f, T_f) + + # Compute V_b1 + I_n1 = K_c1 * Ifd / V_e + F_ex = rectifier_function(I_n1) + V_b1 = min(F_ex * V_e, VB1_max) + + #Compute 5 States AVR ODE: + output_ode[local_ix[1]] = dVm_dt + output_ode[local_ix[2]] = dxa1_dt + output_ode[local_ix[3]] = dxa2_dt + output_ode[local_ix[4]] = dxa3_dt + output_ode[local_ix[5]] = dxa4_dt + + #Update inner_vars + Efd = V_b1 * x_a3 + V_b2 + inner_vars[Vf_var] = Efd + return +end From c36a6267b53af9586434a80d3d3f59e9545d0ef1 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 9 Sep 2024 17:19:28 -0700 Subject: [PATCH 02/15] add initialization routine --- .../generator_components/init_avr.jl | 115 ++++++++++++++++++ src/models/generator_models/avr_models.jl | 2 +- 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/src/initialization/generator_components/init_avr.jl b/src/initialization/generator_components/init_avr.jl index 87965eadd..83c0cd375 100644 --- a/src/initialization/generator_components/init_avr.jl +++ b/src/initialization/generator_components/init_avr.jl @@ -652,3 +652,118 @@ function initialize_avr!( return end + +function initialize_avr!( + device_states, + static::PSY.StaticInjection, + dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, PSY.ST8C, TG, P}}, + inner_vars::AbstractVector, +) where {M <: PSY.Machine, S <: PSY.Shaft, TG <: PSY.TurbineGov, P <: PSY.PSS} + #Obtain Vf0 solved from Machine + Vf0 = inner_vars[Vf_var] + #Obtain Ifd limiter + Ifd = inner_vars[Xad_Ifd_var] # read Lad Ifd (field current times Lad) + #Obtain measured terminal voltage + Vt0 = sqrt(inner_vars[VR_gen_var]^2 + inner_vars[VI_gen_var]^2) + + #Get parameters + avr = PSY.get_avr(dynamic_device) + SW1_Flag = PSY.get_SW1_Flag(avr) + if SW1_Flag == 1 + error("Source from generator terminal voltage not supported.") + end + Tr = PSY.get_Tr(avr) + K_pr = PSY.get_K_pr(avr) + K_ir = PSY.get_K_ir(avr) + Vpi_min, Vpi_max = PSY.get_Vpi_lim(avr) + K_pa = PSY.get_K_pa(avr) + K_ia = PSY.get_K_ia(avr) + Va_min, Va_max = PSY.get_Va_lim(avr) + K_a = PSY.get_K_a(avr) + T_a = PSY.get_T_a(avr) + Vr_min, Vr_max = PSY.get_Vr_lim(avr) + K_f = PSY.get_K_f(avr) + T_f = PSY.get_T_f(avr) + K_c1 = PSY.get_K_c1(avr) + K_p = PSY.get_K_p(avr) + K_i2 = PSY.get_K_i2(avr) + VB1_max = PSY.get_VB1_max(avr) + + if K_i2 != 0.0 + error("Feedforward Current for AVR ST8C not implemented yet.") + end + if K_ia == 0.0 + error( + "Integrator gain cannot be zero for AVR ST8C of $(PSY.get_name(dynamic_device))", + ) + end + #To solve V_ref, Vr + function f!(out, x) + V_ref = x[1] + Vm = x[2] # Sensed Voltage + x_a1 = x[3] # Regulator Integrator + x_a2 = x[4] # Field Regulator + x_a3 = x[5] # Controller Integrator + x_a4 = x[6] # Regulator Feedback + + #TODO: Implement Terminal Current FF for AVR + V_b2 = 0.0 + #TODO: Implement Voltage Compensation if needed + V_e = K_p + + # Compute block derivatives + Vs = 0.0 + V_pi_in = V_ref + Vs - Vm + Ifd_ref, dxa1_dt = pi_block_nonwindup(V_pi_in, x_a1, K_pr, K_ir, Vpi_min, Vpi_max) + Ifd_diff = Ifd_ref - x_a4 + pi_out, dxa2_dt = pi_block_nonwindup(Ifd_diff, x_a2, K_pa, K_ia, Va_min, Va_max) + _, dxa3_dt = low_pass_nonwindup_mass_matrix(pi_out, x_a3, K_a, T_a, Vr_min, Vr_max) + _, dxa4_dt = low_pass_mass_matrix(Ifd, x_a4, K_f, T_f) + + # Compute V_b1 + I_n1 = K_c1 * Ifd / V_e + F_ex = rectifier_function(I_n1) + V_b1 = F_ex * V_e + + Efd = V_b1 * x_a3 + V_b2 + + #V_ll output first block + out[1] = Efd - Vf0 # we are asking for Vf0 + out[2] = Vm - Vt0 # Low Pass Sensor + out[3] = dxa1_dt + out[4] = dxa2_dt + out[5] = dxa3_dt + out[6] = dxa4_dt + end + # Initial Guess + V_e0 = K_p + I_n10 = K_c1 * Ifd / V_e0 + F_ex0 = rectifier_function(I_n10) + V_b10 = F_ex0 * V_e0 + x_a30 = Vf0 / V_b10 + x_a20 = x_a30 / (K_a * K_ia) + x0 = [Vt0, Vt0, K_f * Ifd / K_ir, x_a20, x_a30, Ifd * K_f] + sol = NLsolve.nlsolve(f!, x0; ftol = STRICT_NLSOLVE_F_TOLERANCE) + if !NLsolve.converged(sol) + @warn("Initialization of AVR in $(PSY.get_name(static)) failed") + else # if converge + sol_x0 = sol.zero + Vreg = sol_x0[6] + if (Vreg > Vr_max) || (Vreg < Vr_min) + @error( + "Regulator Voltage V_R = $(Vreg) outside the limits for AVR of $(PSY.get_name(dynamic_device)). Consider updating its limits." + ) + end + #Update V_ref + PSY.set_V_ref!(avr, sol_x0[1]) + set_V_ref(dynamic_device, sol_x0[1]) + #Update AVR states + avr_ix = get_local_state_ix(dynamic_device, PSY.ST8C) + avr_states = @view device_states[avr_ix] + avr_states[1] = sol_x0[2] + avr_states[2] = sol_x0[3] + avr_states[3] = sol_x0[4] + avr_states[4] = sol_x0[5] + avr_states[5] = sol_x0[6] + end +end diff --git a/src/models/generator_models/avr_models.jl b/src/models/generator_models/avr_models.jl index e5161b8c8..9ad7455b7 100644 --- a/src/models/generator_models/avr_models.jl +++ b/src/models/generator_models/avr_models.jl @@ -766,7 +766,7 @@ function mdl_avr_ode!( #Get parameters avr = PSY.get_avr(dynamic_device) - SW1_Flag = PSY.get_SW1_flags(avr) + SW1_Flag = PSY.get_SW1_Flag(avr) if SW1_Flag == 1 error("Source from generator terminal voltage not supported.") end From 9d8c4247f709436a46669a72b2499a2bc8584c0e Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 9 Sep 2024 17:19:34 -0700 Subject: [PATCH 03/15] add test data --- test/benchmarks/psse/ST8C/ThreeBusMulti.raw | 32 +++++++++++++++++++++ test/benchmarks/psse/ST8C/ThreeBus_ST8C.dyr | 10 +++++++ 2 files changed, 42 insertions(+) create mode 100644 test/benchmarks/psse/ST8C/ThreeBusMulti.raw create mode 100644 test/benchmarks/psse/ST8C/ThreeBus_ST8C.dyr diff --git a/test/benchmarks/psse/ST8C/ThreeBusMulti.raw b/test/benchmarks/psse/ST8C/ThreeBusMulti.raw new file mode 100644 index 000000000..318f19291 --- /dev/null +++ b/test/benchmarks/psse/ST8C/ThreeBusMulti.raw @@ -0,0 +1,32 @@ +0, 100.00, 33, 0, 0, 60.00 / PSS(R)E 33 RAW created by rawd33 TUE, JUL 21 2020 17:55 + + + 101,'BUS 1', 138.0000,3, 1, 1, 1,1.05000, 0.0000,1.10000,0.90000,1.10000,0.90000 + 102,'BUS 2', 138.0000,2, 1, 1, 1,1.02000, -0.9440,1.10000,0.90000,1.10000,0.90000 + 103,'BUS 3', 138.0000,1, 1, 1, 1,0.99341, -8.7697,1.10000,0.90000,1.10000,0.90000 + 0 /End of Bus data, Begin Load data + 103,'1 ',1, 1, 1, 200.000, 30.000, 0.000, 0.000, 0.000, 0.000, 1,1,0 + 0 /End of Load data, Begin Fixed shunt data + 0 /End of Fixed shunt data, Begin Generator data + 101,'1 ', 133.335, 73.271, 100.000, -100.000,1.05000, 0, 100.000, 0.00000E+0, 1.00000E-5, 0.00000E+0, 0.00000E+0,1.00000,1, 100.0, 318.000, 0.000, 1,1.0000 + 102,'1 ', 70.000, -3.247, 100.000, -100.000,1.02000, 0, 100.000, 0.00000E+0, 2.500E-1, 0.00000E+0, 0.00000E+0,1.00000,1, 100.0, 318.000, 0.000, 1,1.0000 + 0 /End of Generator data, Begin Branch data + 101, 102,'1 ', 1.00000E-2, 1.20000E-1, 0.00000, 250.00, 250.00, 250.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.00, 1,1.0000 + 101, 103,'1 ', 1.00000E-2, 1.20000E-1, 0.00000, 250.00, 250.00, 250.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.00, 1,1.0000 + 102, 103,'1 ', 1.00000E-2, 1.20000E-1, 0.00000, 250.00, 250.00, 250.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.00, 1,1.0000 + 0 /End of Branch data, Begin Transformer data + 0 /End of Transformer data, Begin Area interchange data + 0 /End of Area interchange data, Begin Two-terminal dc line data + 0 /End of Two-terminal dc line data, Begin VSC dc line data + 0 /End of VSC dc line data, Begin Impedance correction table data + 0 /End of Impedance correction table data, Begin Multi-terminal dc line data + 0 /End of Multi-terminal dc line data, Begin Multi-section line data + 0 /End of Multi-section line data, Begin Zone data + 0 /End of Zone data, Begin Inter-area transfer data + 0 /End of Inter-area transfer data, Begin Owner data + 0 /End of Owner data, Begin FACTS device data + 0 /End of FACTS device data, Begin Switched shunt data + 0 /End of Switched shunt data, Begin GNE device data + 0 /End of GNE device data, Begin Induction machine data + 0 /End of Induction machine data +Q \ No newline at end of file diff --git a/test/benchmarks/psse/ST8C/ThreeBus_ST8C.dyr b/test/benchmarks/psse/ST8C/ThreeBus_ST8C.dyr new file mode 100644 index 000000000..d4f4cb611 --- /dev/null +++ b/test/benchmarks/psse/ST8C/ThreeBus_ST8C.dyr @@ -0,0 +1,10 @@ + 101 'GENCLS' 1 0.0000 0.0000 / + 102 'GENROU' 1 8.0000 0.30000E-01 0.40000 0.50000E-01 + 6.1750 0.50000E-01 1.8000 1.7000 0.30000 + 0.55000 0.25000 0.20000 0.10000 0.80000 / + 102 'ST8C' 1 0 0 0 0 + 0.10000E-01 5.0000 5.0000 99.9900 0.0000 + 4.0000 0.1000 99.99620 -99.86600 1.3500 + 0.30000E-02 99.3449 -99.1691 0.50000 0.50000E-02 + 0.10000 4.0000 0.0000 0.0000 0.0000 + 99.000 0.0000 0.0000 99.000 / From 2189b83e5188f2b41855e166abc4e1810f18221d Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 9 Sep 2024 20:21:22 -0700 Subject: [PATCH 04/15] add ST8C field voltage post processing --- src/post_processing/post_proc_generator.jl | 38 +++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/post_processing/post_proc_generator.jl b/src/post_processing/post_proc_generator.jl index db8d715fb..883abf9e1 100644 --- a/src/post_processing/post_proc_generator.jl +++ b/src/post_processing/post_proc_generator.jl @@ -832,7 +832,7 @@ function _field_voltage( end """ -Function to obtain the field voltage time series of a Dynamic Generator with avr ESST1A. +Function to obtain the field voltage time series of a Dynamic Generator with avr ST6B. """ function _field_voltage( @@ -894,6 +894,42 @@ function _field_voltage( return ts, Efd end +""" +Function to obtain the field voltage time series of a Dynamic Generator with avr ST8C. + +""" +function _field_voltage( + avr::PSY.ST8C, + name::String, + res::SimulationResults, + dt::Union{Nothing, Float64, Vector{Float64}}, +) + # Obtain state Vm + ts, x_a3 = post_proc_state_series(res, (name, :x_a3), dt) + + # Obtain state Xad_Ifd + ts, Xad_Ifd = post_proc_field_current_series(res, name, dt) + + #Get parameters + K_c1 = PSY.get_K_c1(avr) + K_p = PSY.get_K_p(avr) + VB1_max = PSY.get_VB1_max(avr) + + Efd = zeros(length(ts)) + for (ix, t) in enumerate(ts) + #TODO: Get proper V_e and V_b2 + V_e = K_p + V_b2 = 0.0 + Ifd = Xad_Ifd[ix] + I_N1 = K_c1 * Ifd / V_e + F_ex = rectifier_function(I_N1) + V_b1 = min(F_ex * V_e, VB1_max) + Efd[ix] = V_b1 * x_a3[ix] + V_b2 + end + + return ts, Efd +end + """ Function to obtain the pss output time series of a Dynamic Generator with pss PSSFixed. From 3d815d130c0f231227380b6b57832c3ce91db7dd Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 9 Sep 2024 20:21:31 -0700 Subject: [PATCH 05/15] add test 60 --- .../generator_components/init_avr.jl | 2 - test/results/results_eigenvalues.jl | 14 ++ test/results/results_initial_conditions.jl | 26 +++ test/test_case60_st8c.jl | 157 ++++++++++++++++++ 4 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 test/test_case60_st8c.jl diff --git a/src/initialization/generator_components/init_avr.jl b/src/initialization/generator_components/init_avr.jl index 83c0cd375..1a9bbbb33 100644 --- a/src/initialization/generator_components/init_avr.jl +++ b/src/initialization/generator_components/init_avr.jl @@ -672,7 +672,6 @@ function initialize_avr!( if SW1_Flag == 1 error("Source from generator terminal voltage not supported.") end - Tr = PSY.get_Tr(avr) K_pr = PSY.get_K_pr(avr) K_ir = PSY.get_K_ir(avr) Vpi_min, Vpi_max = PSY.get_Vpi_lim(avr) @@ -687,7 +686,6 @@ function initialize_avr!( K_c1 = PSY.get_K_c1(avr) K_p = PSY.get_K_p(avr) K_i2 = PSY.get_K_i2(avr) - VB1_max = PSY.get_VB1_max(avr) if K_i2 != 0.0 error("Feedforward Current for AVR ST8C not implemented yet.") diff --git a/test/results/results_eigenvalues.jl b/test/results/results_eigenvalues.jl index c7cb82601..f065627a3 100644 --- a/test/results/results_eigenvalues.jl +++ b/test/results/results_eigenvalues.jl @@ -983,3 +983,17 @@ test59_eigvals = [ -0.36823401395037775 - 0.5649228138733879im -0.36823401395037775 + 0.5649228138733879im ] + +test60_eigvals = [ + -351.6684302703973 + 0.0im + -163.4858530295313 + 0.0im + -98.32270507099068 + 0.0im + -49.907783868123786 + 0.0im + -39.63477584570041 + 0.0im + -10.878948461924733 + 0.0im + -2.752172823341148 - 8.057381046225618im + -2.752172823341148 + 8.057381046225618im + -1.5898057550991769 + 0.0im + -0.3644442941887857 + 0.0im + -0.025119358661025975 + 0.0im +] diff --git a/test/results/results_initial_conditions.jl b/test/results/results_initial_conditions.jl index cb38572b8..46191594c 100644 --- a/test/results/results_initial_conditions.jl +++ b/test/results/results_initial_conditions.jl @@ -1806,3 +1806,29 @@ test59_x0_init = Dict( 2.153115531256307 ], ) + +test60_x0_init = Dict( + "V_R" => [ + 1.05 + 1.0197944718502572 + 0.9923907751848658 + ], + "V_I" => [ + 0.0 + -0.020475233421259967 + -0.1243212484458825 + ], + "generator-102-1" => [ + 0.7884763261345278 + 0.5085259590582243 + 0.7414384926786595 + 0.6865254295904037 + 0.8631405314160565 + 1.0 + 1.02 + 0.15882529455273622 + 3.0101738941140193 + 0.4063734757053926 + 0.7941264727636811 + ], +) diff --git a/test/test_case60_st8c.jl b/test/test_case60_st8c.jl new file mode 100644 index 000000000..90d1fb03e --- /dev/null +++ b/test/test_case60_st8c.jl @@ -0,0 +1,157 @@ +""" +Validation PSSE/ST6B: +This case study defines a three bus system with an infinite bus, GENROU and a load. +The GENROU machine has connected an ST8C Excitation System. +The fault drop the line connecting the infinite bus and GENROU. +""" +################################################## +############### LOAD DATA ######################## +################################################## + +raw_file = joinpath(TEST_FILES_DIR, "benchmarks/psse/ST8C/ThreeBusMulti.raw") +dyr_file = joinpath(TEST_FILES_DIR, "benchmarks/psse/ST8C/ThreeBus_ST8C.dyr") +#csv_file = joinpath(TEST_FILES_DIR, "benchmarks/psse/ST8C/results_PSSe.csv") + +@testset "Test 60 ST8C ResidualModel" begin + path = joinpath(pwd(), "test-psse-ST8C") + !isdir(path) && mkdir(path) + try + # Define system + sys = System(raw_file, dyr_file) + for l in get_components(PSY.StandardLoad, sys) + transform_load_to_constant_impedance(l) + end + + # Define Simulation Problem + sim = Simulation( + ResidualModel, + sys, #system + path, + (0.0, 20.0), #time span + BranchTrip(1.0, Line, "BUS 1-BUS 2-i_1"), #Type of Fault + ) + + # Test Initial Condition + diff_val = [0.0] + res = get_init_values_for_comparison(sim) + for (k, v) in test60_x0_init + diff_val[1] += LinearAlgebra.norm(res[k] - v) + end + + @test diff_val[1] < 1e-3 + + # Obtain small signal results for initial conditions + small_sig = small_signal_analysis(sim) + eigs = small_sig.eigenvalues + @test small_sig.stable + + # Test Eigenvalues + @test LinearAlgebra.norm(eigs - test60_eigvals) < 1e-3 + + # Solve problem + @test execute!(sim, IDA(); dtmax = 0.005, saveat = 0.005) == + PSID.SIMULATION_FINALIZED + results = read_results(sim) + + # Obtain results + + t_psid, v2_psid = get_voltage_magnitude_series(results, 102) + _, v3_psid = get_voltage_magnitude_series(results, 103) + _, ω_psid = get_state_series(results, ("generator-102-1", :ω)) + _, Vf = get_field_voltage_series(results, "generator-102-1") + + #= + # Obtain PSSE results + M = get_csv_data(csv_file) + t_psse = M[:, 1] + v1_psse = M[:, 2] + v2_psse = M[:, 3] + v3_psse = M[:, 4] + v4_psse = M[:, 5] + ω_psse = M[:, 6] .+ 1.0 + efd_psse = M[:, 7] + + # Test Transient Simulation Results + + @test LinearAlgebra.norm(t_psid - round.(t_psse, digits = 3)) == 0.0 + @test LinearAlgebra.norm(v2_psid - v2_psse, Inf) <= 1e-3 + @test LinearAlgebra.norm(v3_psid - v3_psse, Inf) <= 1e-3 + @test LinearAlgebra.norm(ω_psid - ω_psse, Inf) <= 1e-3 + =# + finally + @info("removing test files") + rm(path; force = true, recursive = true) + end +end + +@testset "Test 60 ST8C MassMatrixModel" begin + path = joinpath(pwd(), "test-psse-ST6B") + !isdir(path) && mkdir(path) + try + # Define system + sys = System(raw_file, dyr_file) + for l in get_components(PSY.StandardLoad, sys) + transform_load_to_constant_impedance(l) + end + + # Define Simulation Problem + sim = Simulation( + MassMatrixModel, + sys, #system + path, + (0.0, 20.0), #time span + BranchTrip(1.0, Line, "BUS 1-BUS 2-i_1"), #Type of Fault + ) + + # Test Initial Condition + diff_val = [0.0] + res = get_init_values_for_comparison(sim) + for (k, v) in test60_x0_init + diff_val[1] += LinearAlgebra.norm(res[k] - v) + end + + @test diff_val[1] < 1e-3 + + # Obtain small signal results for initial conditions + small_sig = small_signal_analysis(sim) + eigs = small_sig.eigenvalues + @test small_sig.stable + + # Test Eigenvalues + @test LinearAlgebra.norm(eigs - test60_eigvals) < 1e-3 + + # Solve problem + @test execute!(sim, Rodas4(); dtmax = 0.005, saveat = 0.005) == + PSID.SIMULATION_FINALIZED + results = read_results(sim) + + # Obtain results + + t_psid, v2_psid = get_voltage_magnitude_series(results, 102) + _, v3_psid = get_voltage_magnitude_series(results, 103) + _, ω_psid = get_state_series(results, ("generator-102-1", :ω)) + _, Vf = get_field_voltage_series(results, "generator-102-1") + + #= + # Obtain PSSE results + M = get_csv_data(csv_file) + t_psse = M[:, 1] + v1_psse = M[:, 2] + v2_psse = M[:, 3] + v3_psse = M[:, 4] + v4_psse = M[:, 5] + ω_psse = M[:, 6] .+ 1.0 + efd_psse = M[:, 7] + + # Test Transient Simulation Results + + @test LinearAlgebra.norm(t_psid - round.(t_psse, digits = 3)) == 0.0 + @test LinearAlgebra.norm(v2_psid - v2_psse, Inf) <= 1e-3 + @test LinearAlgebra.norm(v3_psid - v3_psse, Inf) <= 1e-3 + @test LinearAlgebra.norm(ω_psid - ω_psse, Inf) <= 1e-3 + =# + finally + @info("removing test files") + rm(path; force = true, recursive = true) + end +end From be19afc624be6c7462514a10606f80cd008ef5fd Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 9 Sep 2024 20:22:55 -0700 Subject: [PATCH 06/15] remove windows from test temporarily --- .github/workflows/main-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main-tests.yml b/.github/workflows/main-tests.yml index c371e1050..19e337ad9 100644 --- a/.github/workflows/main-tests.yml +++ b/.github/workflows/main-tests.yml @@ -15,7 +15,7 @@ jobs: matrix: julia-version: ['1', 'nightly'] julia-arch: [x64] - os: [ubuntu-latest, windows-latest] + os: [ubuntu-latest, macOS-latest] steps: - uses: actions/checkout@v2 From ba67ac4ad97bb697d4df9f2bbe5c895f40b1f4d0 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 9 Sep 2024 20:23:46 -0700 Subject: [PATCH 07/15] also remove windows test in PR testing temporarily --- .github/workflows/pr_testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_testing.yml b/.github/workflows/pr_testing.yml index 203fae504..f47462273 100644 --- a/.github/workflows/pr_testing.yml +++ b/.github/workflows/pr_testing.yml @@ -12,7 +12,7 @@ jobs: matrix: julia-version: ['1'] julia-arch: [x64] - os: [ubuntu-latest, windows-latest, macOS-latest] + os: [ubuntu-latest, macOS-latest] steps: - uses: actions/checkout@v2 From 1cfb17edadb760b706d522b08085a10e226eec05 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Thu, 19 Sep 2024 11:27:44 -0700 Subject: [PATCH 08/15] formatter --- test/results/results_eigenvalues.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/results/results_eigenvalues.jl b/test/results/results_eigenvalues.jl index 6a5b7585b..c4b5417b9 100644 --- a/test/results/results_eigenvalues.jl +++ b/test/results/results_eigenvalues.jl @@ -1013,5 +1013,5 @@ test61_eigvals = [ -2.752172823341148 + 8.057381046225618im -1.5898057550991769 + 0.0im -0.3644442941887857 + 0.0im - -0.025119358661025975 + 0.0im + -0.025119358661025975 + 0.0im ] From 2db53220ad7f2a8943927ad66fa37ca20c2428e7 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Thu, 19 Sep 2024 11:36:24 -0700 Subject: [PATCH 09/15] update test names --- test/results/results_initial_conditions.jl | 2 +- test/{test_case60_st8c.jl => test_case61_st8c.jl} | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) rename test/{test_case60_st8c.jl => test_case61_st8c.jl} (94%) diff --git a/test/results/results_initial_conditions.jl b/test/results/results_initial_conditions.jl index e5da1d7d0..7a0f9de27 100644 --- a/test/results/results_initial_conditions.jl +++ b/test/results/results_initial_conditions.jl @@ -1837,7 +1837,7 @@ test60_x0_init = Dict( ], ) -test60_x0_init = Dict( +test61_x0_init = Dict( "V_R" => [ 1.05 1.0197944718502572 diff --git a/test/test_case60_st8c.jl b/test/test_case61_st8c.jl similarity index 94% rename from test/test_case60_st8c.jl rename to test/test_case61_st8c.jl index 90d1fb03e..c19c56cb4 100644 --- a/test/test_case60_st8c.jl +++ b/test/test_case61_st8c.jl @@ -12,7 +12,7 @@ raw_file = joinpath(TEST_FILES_DIR, "benchmarks/psse/ST8C/ThreeBusMulti.raw") dyr_file = joinpath(TEST_FILES_DIR, "benchmarks/psse/ST8C/ThreeBus_ST8C.dyr") #csv_file = joinpath(TEST_FILES_DIR, "benchmarks/psse/ST8C/results_PSSe.csv") -@testset "Test 60 ST8C ResidualModel" begin +@testset "Test 61 ST8C ResidualModel" begin path = joinpath(pwd(), "test-psse-ST8C") !isdir(path) && mkdir(path) try @@ -34,7 +34,7 @@ dyr_file = joinpath(TEST_FILES_DIR, "benchmarks/psse/ST8C/ThreeBus_ST8C.dyr") # Test Initial Condition diff_val = [0.0] res = get_init_values_for_comparison(sim) - for (k, v) in test60_x0_init + for (k, v) in test61_x0_init diff_val[1] += LinearAlgebra.norm(res[k] - v) end @@ -46,7 +46,7 @@ dyr_file = joinpath(TEST_FILES_DIR, "benchmarks/psse/ST8C/ThreeBus_ST8C.dyr") @test small_sig.stable # Test Eigenvalues - @test LinearAlgebra.norm(eigs - test60_eigvals) < 1e-3 + @test LinearAlgebra.norm(eigs - test61_eigvals) < 1e-3 # Solve problem @test execute!(sim, IDA(); dtmax = 0.005, saveat = 0.005) == @@ -84,7 +84,7 @@ dyr_file = joinpath(TEST_FILES_DIR, "benchmarks/psse/ST8C/ThreeBus_ST8C.dyr") end end -@testset "Test 60 ST8C MassMatrixModel" begin +@testset "Test 61 ST8C MassMatrixModel" begin path = joinpath(pwd(), "test-psse-ST6B") !isdir(path) && mkdir(path) try @@ -106,7 +106,7 @@ end # Test Initial Condition diff_val = [0.0] res = get_init_values_for_comparison(sim) - for (k, v) in test60_x0_init + for (k, v) in test61_x0_init diff_val[1] += LinearAlgebra.norm(res[k] - v) end @@ -118,7 +118,7 @@ end @test small_sig.stable # Test Eigenvalues - @test LinearAlgebra.norm(eigs - test60_eigvals) < 1e-3 + @test LinearAlgebra.norm(eigs - test61_eigvals) < 1e-3 # Solve problem @test execute!(sim, Rodas4(); dtmax = 0.005, saveat = 0.005) == From abd4ac3f5d92f8b0ff2c836cceb442f372c9398c Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Fri, 20 Sep 2024 15:35:24 -0700 Subject: [PATCH 10/15] add tgsimple model --- .../generator_components/init_tg.jl | 20 +++++++++++ src/models/generator_models/tg_models.jl | 36 +++++++++++++++++++ src/post_processing/post_proc_generator.jl | 14 ++++++++ 3 files changed, 70 insertions(+) diff --git a/src/initialization/generator_components/init_tg.jl b/src/initialization/generator_components/init_tg.jl index e0c4b1028..e382d25f3 100644 --- a/src/initialization/generator_components/init_tg.jl +++ b/src/initialization/generator_components/init_tg.jl @@ -14,6 +14,26 @@ function initialize_tg!( return end +function initialize_tg!( + device_states, + static::PSY.StaticInjection, + dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, PSY.TGSimple, P}}, + inner_vars::AbstractVector, +) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS} + + #Get mechanical torque to SyncMach + τm0 = inner_vars[τm_var] + #Set Parameters + tg = PSY.get_prime_mover(dynamic_device) + + PSY.set_P_ref!(tg, τm0) + set_P_ref(dynamic_device, τm0) + tg_ix = get_local_state_ix(dynamic_device, PSY.TGSimple) + tg_states = @view device_states[tg_ix] + tg_states[1] = τm0 + return +end + function initialize_tg!( device_states, static::PSY.StaticInjection, diff --git a/src/models/generator_models/tg_models.jl b/src/models/generator_models/tg_models.jl index 2cf8baad4..60fc993c9 100644 --- a/src/models/generator_models/tg_models.jl +++ b/src/models/generator_models/tg_models.jl @@ -73,6 +73,42 @@ function mdl_tg_ode!( return end +function mdl_tg_ode!( + device_states::AbstractArray{<:ACCEPTED_REAL_TYPES}, + output_ode::AbstractArray{<:ACCEPTED_REAL_TYPES}, + inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, + ω_sys::ACCEPTED_REAL_TYPES, + device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, PSY.TGSimple, P}}, + h, + t, +) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS} + + #Update inner vars + P_ref = get_P_ref(device) + ω_ref = get_ω_ref(device) + + local_ix = get_local_state_ix(device, PSY.TGSimple) + + internal_states = @view device_states[local_ix] + τm = internal_states[1] + + #Obtain external states inputs for component + external_ix = get_input_port_ix(device, PSY.TGSimple) + ω = @view device_states[external_ix] + + tg = PSY.get_prime_mover(device) + d_t = PSY.get_d_t(tg) + Tm = PSY.get_Tm(tg) + + # Compute differential equation + droop_τ = P_ref + d_t * (ω_ref = get_ω_ref(device) - ω[1]) + output_ode[local_ix[1]] = (1.0 / Tm) * (droop_τ - τm) + + # Update Inner Vars + inner_vars[τm_var] = τm + return +end + function mdl_tg_ode!( device_states::AbstractArray{<:ACCEPTED_REAL_TYPES}, output_ode::AbstractArray{<:ACCEPTED_REAL_TYPES}, diff --git a/src/post_processing/post_proc_generator.jl b/src/post_processing/post_proc_generator.jl index 96efce98d..5f495c787 100644 --- a/src/post_processing/post_proc_generator.jl +++ b/src/post_processing/post_proc_generator.jl @@ -1246,3 +1246,17 @@ function _mechanical_torque( τm = Pm ./ ω return ts, τm end + +""" +Function to obtain the mechanical torque time series of a Dynamic Generator with TGSimple Turbine Governor. + +""" +function _mechanical_torque( + ::PSY.TGSimple, + name::String, + res::SimulationResults, + dt::Union{Nothing, Float64}, +) + ts, τm = post_proc_state_series(res, (name, :τm), dt) + return ts, τm +end From de2ccc443fba3d3376c14b699cfe09ee22cb9c39 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Fri, 20 Sep 2024 15:35:34 -0700 Subject: [PATCH 11/15] add test 62 tgsimple --- test/data_tests/dynamic_test_data.jl | 5 + test/data_tests/test62.jl | 54 +++++++++++ test/results/results_eigenvalues.jl | 17 ++++ test/results/results_initial_conditions.jl | 31 ++++++ test/test_case62_tgsimple.jl | 108 +++++++++++++++++++++ 5 files changed, 215 insertions(+) create mode 100644 test/data_tests/test62.jl create mode 100644 test/test_case62_tgsimple.jl diff --git a/test/data_tests/dynamic_test_data.jl b/test/data_tests/dynamic_test_data.jl index f56a65b3c..8a2a4b2f6 100644 --- a/test/data_tests/dynamic_test_data.jl +++ b/test/data_tests/dynamic_test_data.jl @@ -227,6 +227,11 @@ tg_type2() = TGTypeII( (min = 0.1, max = 1.5), #τ_lims ) +tg_simple() = TGSimple(; + d_t = 130.0, + Tm = 0.2, +) + ######## AVR Data ######### avr_none() = AVRFixed(0.0) diff --git a/test/data_tests/test62.jl b/test/data_tests/test62.jl new file mode 100644 index 000000000..78bd8a98f --- /dev/null +++ b/test/data_tests/test62.jl @@ -0,0 +1,54 @@ +using PowerSystems +using NLsolve +const PSY = PowerSystems + +############### Data Network ######################## +include(joinpath(dirname(@__FILE__), "dynamic_test_data.jl")) + +############### Data Network ######################## +threebus_file_dir = joinpath(dirname(@__FILE__), "ThreeBusNetwork.raw") +threebus_sys = System(threebus_file_dir; runchecks = false) +add_source_to_ref(threebus_sys) + +function dyn_gen_tg_simple(generator) + return PSY.DynamicGenerator(; + name = get_name(generator), #static generator + ω_ref = 1.0, # ω_ref + machine = machine_oneDoneQ(), #machine + shaft = shaft_no_damping(), #shaft + avr = avr_type2(), #avr + prime_mover = tg_simple(), #tg + pss = pss_none(), + ) #pss +end + +function dyn_gen_simple_avr(generator) + return PSY.DynamicGenerator(; + name = get_name(generator), #static generator + ω_ref = 1.0, # ω_ref + machine = machine_oneDoneQ(), #machine + shaft = shaft_no_damping(), #shaft + avr = avr_propr(), #avr + prime_mover = tg_none(), #tg + pss = pss_none(), + ) #pss +end + +for l in get_components(PSY.StandardLoad, threebus_sys) + transform_load_to_constant_impedance(l) +end + +# Add dynamic generators to the system (each gen is linked through a static one) +for g in get_components(Generator, threebus_sys) + if get_number(get_bus(g)) == 102 + case_gen = dyn_gen_tg_simple(g) + add_component!(threebus_sys, case_gen, g) + elseif get_number(get_bus(g)) == 103 + case_gen = dyn_gen_simple_avr(g) + add_component!(threebus_sys, case_gen, g) + end +end + +#Compute Y_bus after fault +fault_branches = deepcopy(collect(get_components(Branch, threebus_sys))[2:end]) +Ybus_fault = PNM.Ybus(fault_branches, collect(get_components(ACBus, threebus_sys)))[:, :] diff --git a/test/results/results_eigenvalues.jl b/test/results/results_eigenvalues.jl index c4b5417b9..d6e74fd24 100644 --- a/test/results/results_eigenvalues.jl +++ b/test/results/results_eigenvalues.jl @@ -1015,3 +1015,20 @@ test61_eigvals = [ -0.3644442941887857 + 0.0im -0.025119358661025975 + 0.0im ] + +test62_eigvals = [ + -10459.358851619487 + 0.0im + -9518.115670613777 + 0.0im + -187.2382951105011 + 0.0im + -6.27581492402704 + 0.0im + -4.386996429201749 + 0.0im + -3.411988679439486 + 0.0im + -1.794938559823694 - 18.61457224254591im + -1.794938559823694 + 18.61457224254591im + -0.925460254940432 - 14.645727550143585im + -0.925460254940432 + 14.645727550143585im + -0.8920346522905136 - 0.5103528532335275im + -0.8920346522905136 + 0.5103528532335275im + -0.7855979325597521 - 3.4230121753657374im + -0.7855979325597521 + 3.4230121753657374im +] diff --git a/test/results/results_initial_conditions.jl b/test/results/results_initial_conditions.jl index 7a0f9de27..7c843bffc 100644 --- a/test/results/results_initial_conditions.jl +++ b/test/results/results_initial_conditions.jl @@ -1862,3 +1862,34 @@ test61_x0_init = Dict( 0.7941264727636811 ], ) + +test61_x0_init = Dict( + "V_R" => [ + 1.02 + 1.0135824431277969 + 1.0058149733250097 + ], + "V_I" => [ + 0.0 + -0.03538744103614196 + 0.013078586896530407 + ], + "generator-102-1" => [ + 1.0767866298987512 + 0.42832746888394896 + 0.5202803856576895 + 1.0 + 2.41771421082291 + 1.813285658117182 + -0.10879713948703092 + 1.0142 + 1.0 + ], + "generator-103-1" => [ + 0.8114728517709782 + 0.6034056242089947 + 0.859059349494541 + 1.0 + 1.7138202875847097 + ], +) diff --git a/test/test_case62_tgsimple.jl b/test/test_case62_tgsimple.jl new file mode 100644 index 000000000..55519b4cf --- /dev/null +++ b/test/test_case62_tgsimple.jl @@ -0,0 +1,108 @@ +""" +Case 62: +This case study a three bus system with 2 machines (One d- One q-: 4th order model) and an infinite source. +The case is similar to case 13, with different AVR and TG models. +""" + +################################################## +############### LOAD DATA ######################## +################################################## + +include(joinpath(TEST_FILES_DIR, "data_tests/test62.jl")) + +################################################## +############### SOLVE PROBLEM #################### +################################################## + +# Time span +tspan = (0.0, 20.0) + +#Define Fault: Change of YBus +Ybus_change = NetworkSwitch( + 1.0, #change at t = 1.0 + Ybus_fault, +) #New YBus + +@testset "Test 13 AVR ResidualModel" begin + path = mktempdir() + try + # Define Simulation Problem + sim = Simulation( + ResidualModel, + threebus_sys, #system, + path, + tspan, #time span + Ybus_change, #Type of Fault + ) + + # Test Initial Condition + diff_val = [0.0] + res = get_init_values_for_comparison(sim) + for (k, v) in test62_x0_init + diff_val[1] += LinearAlgebra.norm(res[k] - v) + end + + @test (diff_val[1] < 1e-3) + + # Obtain small signal results for initial conditions + small_sig = small_signal_analysis(sim) + eigs = small_sig.eigenvalues + @test small_sig.stable + + # Test Eigenvalues + @test LinearAlgebra.norm(eigs - test62_eigvals) < 1e-3 + + #Solve problem + @test execute!(sim, IDA(); dtmax = 0.02) == PSID.SIMULATION_FINALIZED + results = read_results(sim) + + #Obtain data for angles + series = get_state_series(results, ("generator-102-1", :δ)) + series2 = get_mechanical_torque_series(results, "generator-102-1") + finally + @info("removing test files") + rm(path; force = true, recursive = true) + end +end + +@testset "Test 13 AVR MassMarixcModel" begin + path = mktempdir() + try + # Define Simulation Problem + sim = Simulation( + MassMatrixModel, + threebus_sys, #system, + path, + tspan, #time span + Ybus_change, #Type of Fault + ) + + # Test Initial Condition + diff_val = [0.0] + res = get_init_values_for_comparison(sim) + for (k, v) in test62_x0_init + diff_val[1] += LinearAlgebra.norm(res[k] - v) + end + + @test (diff_val[1] < 1e-3) + + # Obtain small signal results for initial conditions + small_sig = small_signal_analysis(sim) + eigs = small_sig.eigenvalues + @test small_sig.stable + + # Test Eigenvalues + @test LinearAlgebra.norm(eigs - test62_eigvals) < 1e-3 + + #Solve problem + @test execute!(sim, Rodas4(); dtmax = 0.02) == PSID.SIMULATION_FINALIZED + results = read_results(sim) + + #Obtain data for angles + series = get_state_series(results, ("generator-102-1", :δ)) + series2 = get_mechanical_torque_series(results, "generator-102-1") + finally + @info("removing test files") + rm(path; force = true, recursive = true) + end +end From 9a2352653e8efa94678ccf65dd83619928def12a Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Fri, 20 Sep 2024 15:38:26 -0700 Subject: [PATCH 12/15] update test 62 typos --- test/results/results_initial_conditions.jl | 2 +- test/test_case62_tgsimple.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/results/results_initial_conditions.jl b/test/results/results_initial_conditions.jl index 7c843bffc..3f5505d4b 100644 --- a/test/results/results_initial_conditions.jl +++ b/test/results/results_initial_conditions.jl @@ -1863,7 +1863,7 @@ test61_x0_init = Dict( ], ) -test61_x0_init = Dict( +test62_x0_init = Dict( "V_R" => [ 1.02 1.0135824431277969 diff --git a/test/test_case62_tgsimple.jl b/test/test_case62_tgsimple.jl index 55519b4cf..c236ae4c0 100644 --- a/test/test_case62_tgsimple.jl +++ b/test/test_case62_tgsimple.jl @@ -23,7 +23,7 @@ Ybus_change = NetworkSwitch( Ybus_fault, ) #New YBus -@testset "Test 13 AVR ResidualModel" begin +@testset "Test 62 TGSimple ResidualModel" begin path = mktempdir() try # Define Simulation Problem @@ -65,7 +65,7 @@ Ybus_change = NetworkSwitch( end end -@testset "Test 13 AVR MassMarixcModel" begin +@testset "Test 62 TGSimple MassMarixcModel" begin path = mktempdir() try # Define Simulation Problem From 6ce7cce31092a96060946c8c2caf2272a26cc9e4 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Fri, 20 Sep 2024 16:53:25 -0700 Subject: [PATCH 13/15] add degov1 model --- .../generator_components/init_tg.jl | 33 ++++++ src/models/generator_models/tg_models.jl | 102 ++++++++++++++++++ src/post_processing/post_proc_generator.jl | 15 +++ 3 files changed, 150 insertions(+) diff --git a/src/initialization/generator_components/init_tg.jl b/src/initialization/generator_components/init_tg.jl index e382d25f3..ab2bc7664 100644 --- a/src/initialization/generator_components/init_tg.jl +++ b/src/initialization/generator_components/init_tg.jl @@ -210,6 +210,39 @@ function initialize_tg!( return end +function initialize_tg!( + device_states, + static::PSY.StaticInjection, + dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, PSY.DEGOV1, P}}, + inner_vars::AbstractVector, +) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS} + tg = PSY.get_prime_mover(dynamic_device) + droop_flag = PSY.get_droop_flag(tg) + R = PSY.get_R(tg) + #Get mechanical torque to SyncMach + τm0 = inner_vars[τm_var] + τe0 = inner_vars[τe_var] + if droop_flag == 0 + PSY.set_P_ref!(tg, τm0 * R) + set_P_ref(dynamic_device, τm0 * R) + else + PSY.set_P_ref!(tg, τe0 * R) + set_P_ref(dynamic_device, τe0 * R) + end + #Update states + tg_ix = get_local_state_ix(dynamic_device, typeof(tg)) + tg_states = @view device_states[tg_ix] + tg_states[1] = 0.0 + tg_states[2] = 0.0 + tg_states[3] = 0.0 + tg_states[4] = 0.0 + tg_states[5] = τm0 + if droop_flag == 1 + tg_states[6] = τe0 + end + return +end + function initialize_tg!( device_states, ::PSY.StaticInjection, diff --git a/src/models/generator_models/tg_models.jl b/src/models/generator_models/tg_models.jl index 60fc993c9..3789f0866 100644 --- a/src/models/generator_models/tg_models.jl +++ b/src/models/generator_models/tg_models.jl @@ -31,6 +31,21 @@ function mass_matrix_tg_entries!( return end +function mass_matrix_tg_entries!( + mass_matrix, + tg::PSY.DEGOV1, + global_index::Base.ImmutableDict{Symbol, Int64}, +) + mass_matrix[global_index[:x_g1], global_index[:x_g1]] = + PSY.get_T1(tg) * PSY.get_T2(tg) + mass_matrix[global_index[:x_g3], global_index[:x_g3]] = PSY.get_T5(tg) * PSY.get_T6(tg) + droop_flag = PSY.get_droop_flag(tg) + if droop_flag == 1 + mass_matrix[global_index[:x_g6], global_index[:x_g6]] = PSY.get_Te(tg) + end + return +end + function mass_matrix_tg_entries!( mass_matrix, tg::PSY.PIDGOV, @@ -454,6 +469,93 @@ function mdl_tg_ode!( return end +function mdl_tg_ode!( + device_states::AbstractArray{<:ACCEPTED_REAL_TYPES}, + output_ode::AbstractArray{<:ACCEPTED_REAL_TYPES}, + inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, + ω_sys::ACCEPTED_REAL_TYPES, + device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, PSY.DEGOV1, P}}, + h, + t, +) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS} + + #Obtain references + P_ref = get_P_ref(device) + + #Obtain indices for component w/r to device + local_ix = get_local_state_ix(device, PSY.DEGOV1) + + #Define internal states for component + internal_states = @view device_states[local_ix] + x_g1 = internal_states[1] # Electric Control Box 1 + x_g2 = internal_states[2] # Electric Control Box 2 + x_g3 = internal_states[3] # Actuator 1 + x_g4 = internal_states[4] # Actuator 2 + x_g5 = internal_states[5] # Actuator 3 + + #Get Parameters + tg = PSY.get_prime_mover(device) + droop_flag = PSY.get_droop_flag(tg) + if droop_flag == 0 + feedback = x_g5 + else + feedback = internal_states[6] # Low-Pass Power + end + T1 = PSY.get_T1(tg) + T2 = PSY.get_T2(tg) + T3 = PSY.get_T3(tg) + K = PSY.get_K(tg) + T4 = PSY.get_T4(tg) + T5 = PSY.get_T5(tg) + T6 = PSY.get_T6(tg) + Td = PSY.get_Td(tg) + Te = PSY.get_Te(tg) + + #Obtain external states inputs for component + external_ix = get_input_port_ix(device, PSY.DEGOV1) + ω = @view device_states[external_ix] + + #Get Parameters + T1 = PSY.get_T1(tg) + T2 = PSY.get_T2(tg) + T3 = PSY.get_T3(tg) + K = PSY.get_K(tg) + T4 = PSY.get_T4(tg) + T5 = PSY.get_T5(tg) + T6 = PSY.get_T6(tg) + Td = PSY.get_Td(tg) + R = PSY.get_R(tg) + Te = PSY.get_Te(tg) + + #Compute block derivatives + ll_in = P_ref - (ω[1] - 1.0) - feedback * R + y1, dx_g1, dx_g2 = + lead_lag_2nd_mass_matrix(ll_in, x_g1, x_g2, T1, T1 * T2, T3, 0.0) + y2, dx_g3, dx_g4 = lead_lag_2nd_mass_matrix(y1, x_g3, x_g4, T5 + T6, T5 * T6, T4, 0.0) + _, dx_g5 = integrator_windup(y2, x_g5, K, 1.0, -Inf, Inf) + delayed_x_g5 = get_delayed_value(h, t, Td, x_g5, get_global_index(device)[:x_g5]) + P_m = delayed_x_g5 * (ω[1]) + + #Compute 5 (or 6) State TG ODE: + output_ode[local_ix[1]] = dx_g1 + output_ode[local_ix[2]] = dx_g2 + output_ode[local_ix[3]] = dx_g3 + output_ode[local_ix[4]] = dx_g4 + output_ode[local_ix[5]] = dx_g5 + + if droop_flag == 1 + # Read Inner Vars + τ_e = inner_vars[τe_var] + _, dx_g6 = low_pass_mass_matrix(τ_e, feedback, 1.0, Te) + output_ode[local_ix[6]] = dx_g6 + end + + #Update mechanical torque + inner_vars[τm_var] = P_m / ω[1] #Fails when trying to assign a Dual to a cache of type Float? + + return +end + function mdl_tg_ode!( device_states::AbstractArray{<:ACCEPTED_REAL_TYPES}, output_ode::AbstractArray{<:ACCEPTED_REAL_TYPES}, diff --git a/src/post_processing/post_proc_generator.jl b/src/post_processing/post_proc_generator.jl index 5f495c787..cc84c7a6f 100644 --- a/src/post_processing/post_proc_generator.jl +++ b/src/post_processing/post_proc_generator.jl @@ -1155,6 +1155,21 @@ function _mechanical_torque( ts, x_a3 = post_proc_state_series(res, (name, :x_a3), dt) return ts, x_a3 end + +""" +Function to obtain the mechanical torque time series of a Dynamic Generator with DEGOV1 Turbine Governor. + +""" +function _mechanical_torque( + ::PSY.DEGOV1, + name::String, + res::SimulationResults, + dt::Union{Nothing, Float64}, +) + ts, x_g5 = post_proc_state_series(res, (name, :x_g5), dt) + return ts, x_g5 +end + """ Function to obtain the mechanical torque time series of a Dynamic Generator with HydroTurbineGov (HYGOV) Turbine Governor. From 32008832aef61096c2dc4b7c3f49235246bf1a6d Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Fri, 20 Sep 2024 16:53:36 -0700 Subject: [PATCH 14/15] add degov1 test --- test/benchmarks/psse/DEGOV1/ThreeBusMulti.raw | 32 +++ .../DEGOV1/ThreeBus_DEGOV1_nodelay_flag0.dyr | 7 + .../DEGOV1/ThreeBus_DEGOV1_nodelay_flag1.dyr | 7 + test/results/results_eigenvalues.jl | 27 +++ test/results/results_initial_conditions.jl | 53 +++++ test/test_case63_degov1.jl | 208 ++++++++++++++++++ 6 files changed, 334 insertions(+) create mode 100644 test/benchmarks/psse/DEGOV1/ThreeBusMulti.raw create mode 100644 test/benchmarks/psse/DEGOV1/ThreeBus_DEGOV1_nodelay_flag0.dyr create mode 100644 test/benchmarks/psse/DEGOV1/ThreeBus_DEGOV1_nodelay_flag1.dyr create mode 100644 test/test_case63_degov1.jl diff --git a/test/benchmarks/psse/DEGOV1/ThreeBusMulti.raw b/test/benchmarks/psse/DEGOV1/ThreeBusMulti.raw new file mode 100644 index 000000000..8fee35b92 --- /dev/null +++ b/test/benchmarks/psse/DEGOV1/ThreeBusMulti.raw @@ -0,0 +1,32 @@ +0, 100.00, 33, 0, 0, 60.00 / PSS(R)E 33 RAW created by rawd33 TUE, JUL 21 2020 17:55 + + + 101,'BUS 1', 138.0000,3, 1, 1, 1,1.05000, 0.0000,1.10000,0.90000,1.10000,0.90000 + 102,'BUS 2', 138.0000,2, 1, 1, 1,1.02000, -0.9440,1.10000,0.90000,1.10000,0.90000 + 103,'BUS 3', 138.0000,1, 1, 1, 1,0.99341, -8.7697,1.10000,0.90000,1.10000,0.90000 + 0 /End of Bus data, Begin Load data + 103,'1 ',1, 1, 1, 250.000, 30.000, 0.000, 0.000, 0.000, 0.000, 1,1,0 + 0 /End of Load data, Begin Fixed shunt data + 0 /End of Fixed shunt data, Begin Generator data + 101,'1 ', 153.335, 73.271, 100.000, -100.000,1.05000, 0, 100.000, 0.00000E+0, 1.00000E-5, 0.00000E+0, 0.00000E+0,1.00000,1, 100.0, 318.000, 0.000, 1,1.0000 + 102,'1 ', 100.000, -3.247, 100.000, -100.000,1.02000, 0, 100.000, 0.00000E+0, 2.500E-1, 0.00000E+0, 0.00000E+0,1.00000,1, 100.0, 318.000, 0.000, 1,1.0000 + 0 /End of Generator data, Begin Branch data + 101, 102,'1 ', 1.00000E-2, 1.20000E-1, 0.00000, 250.00, 250.00, 250.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.00, 1,1.0000 + 101, 103,'1 ', 1.00000E-2, 1.20000E-1, 0.00000, 250.00, 250.00, 250.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.00, 1,1.0000 + 102, 103,'1 ', 1.00000E-2, 1.20000E-1, 0.00000, 250.00, 250.00, 250.00, 0.00000, 0.00000, 0.00000, 0.00000,1,1, 0.00, 1,1.0000 + 0 /End of Branch data, Begin Transformer data + 0 /End of Transformer data, Begin Area interchange data + 0 /End of Area interchange data, Begin Two-terminal dc line data + 0 /End of Two-terminal dc line data, Begin VSC dc line data + 0 /End of VSC dc line data, Begin Impedance correction table data + 0 /End of Impedance correction table data, Begin Multi-terminal dc line data + 0 /End of Multi-terminal dc line data, Begin Multi-section line data + 0 /End of Multi-section line data, Begin Zone data + 0 /End of Zone data, Begin Inter-area transfer data + 0 /End of Inter-area transfer data, Begin Owner data + 0 /End of Owner data, Begin FACTS device data + 0 /End of FACTS device data, Begin Switched shunt data + 0 /End of Switched shunt data, Begin GNE device data + 0 /End of GNE device data, Begin Induction machine data + 0 /End of Induction machine data +Q \ No newline at end of file diff --git a/test/benchmarks/psse/DEGOV1/ThreeBus_DEGOV1_nodelay_flag0.dyr b/test/benchmarks/psse/DEGOV1/ThreeBus_DEGOV1_nodelay_flag0.dyr new file mode 100644 index 000000000..f8dc3731e --- /dev/null +++ b/test/benchmarks/psse/DEGOV1/ThreeBus_DEGOV1_nodelay_flag0.dyr @@ -0,0 +1,7 @@ + 101 'GENCLS' 1 0 0 / + 102 'GENROU' 1 8.0000 0.30000E-01 0.40000 0.50000E-01 + 6.1750 0.50000E-01 1.8000 1.7000 0.30000 + 0.55000 0.25000 0.20000 0.10000 0.80000 / + 102 'DEGOV1' 1 0 0.19050 0.47600E-01 0.18000E-01 + 1.0000 5.1000 0.32200 0.0000 0.0000 + 99.99 -99.99 0.70000E-01 0.50000E-01 / diff --git a/test/benchmarks/psse/DEGOV1/ThreeBus_DEGOV1_nodelay_flag1.dyr b/test/benchmarks/psse/DEGOV1/ThreeBus_DEGOV1_nodelay_flag1.dyr new file mode 100644 index 000000000..8cfe3486c --- /dev/null +++ b/test/benchmarks/psse/DEGOV1/ThreeBus_DEGOV1_nodelay_flag1.dyr @@ -0,0 +1,7 @@ + 101 'GENCLS' 1 0 0 / + 102 'GENROU' 1 8.0000 0.30000E-01 0.40000 0.50000E-01 + 6.1750 0.50000E-01 1.8000 1.7000 0.30000 + 0.55000 0.25000 0.20000 0.10000 0.80000 / + 102 'DEGOV1' 1 1 0.19050 0.47600E-01 0.18000E-01 + 1.0000 5.1000 0.32200 0.0000 0.0000 + 99.99 -99.99 0.70000E-01 0.50000E-01 / diff --git a/test/results/results_eigenvalues.jl b/test/results/results_eigenvalues.jl index d6e74fd24..cc3c025bf 100644 --- a/test/results/results_eigenvalues.jl +++ b/test/results/results_eigenvalues.jl @@ -1032,3 +1032,30 @@ test62_eigvals = [ -0.7855979325597521 - 3.4230121753657374im -0.7855979325597521 + 3.4230121753657374im ] + +test63_eigvals_Flag0 = [ + -39.22517856531171 - 0.23706643304840616im + -39.22517856531171 + 0.23706643304840616im + -13.403547886572664 + 0.0im + -8.122746726423252 + 0.0im + -5.391500486820183 - 2.241842433737118im + -5.391500486820183 + 2.241842433737118im + -0.6466138560537371 - 8.624155441599354im + -0.6466138560537371 + 8.624155441599354im + -0.20824914641735212 + 0.0im + -0.05243031034640425 + 0.0im +] + +test63_eigvals_Flag1 = [ + -39.224926800052884 - 0.23735163098908485im + -39.224926800052884 + 0.23735163098908485im + -19.85028250949885 + 0.0im + -13.323569303234533 + 0.0im + -7.521736802553002 + 0.0im + -5.905690613400367 - 2.3710175079240416im + -5.905690613400367 + 2.3710175079240416im + -0.5479840603712405 - 8.276315089713018im + -0.5479840603712405 + 8.276315089713018im + -0.2082414387220071 + 0.0im + -0.05252688447358956 + 0.0im +] diff --git a/test/results/results_initial_conditions.jl b/test/results/results_initial_conditions.jl index 3f5505d4b..82ec16ff0 100644 --- a/test/results/results_initial_conditions.jl +++ b/test/results/results_initial_conditions.jl @@ -1893,3 +1893,56 @@ test62_x0_init = Dict( 1.7138202875847097 ], ) + +test63_x0_init_Flag0 = Dict( + "V_R" => [ + 1.05 + 1.0198615749401696 + 0.9817964461177487 + ], + "V_I" => [ + 0.0 + -0.01680380791834505 + -0.15145839832533242 + ], + "generator-102-1" => [ + 0.8084146853601003 + 0.5302614530689579 + 0.7288775579091269 + 0.7311890654084042 + 0.9615873122791482 + 1.0 + 0.0 + 0.0 + 0.0 + 0.0 + 0.9999999999999999 + ], +) + +test63_x0_init_Flag1 = Dict( + "V_R" => [ + 1.05 + 1.0198615749401696 + 0.9817964461177487 + ], + "V_I" => [ + 0.0 + -0.01680380791834505 + -0.15145839832533242 + ], + "generator-102-1" => [ + 0.8084146853601003 + 0.5302614530689579 + 0.7288775579091269 + 0.7311890654084042 + 0.9615873122791482 + 1.0 + 0.0 + 0.0 + 0.0 + 0.0 + 0.9999999999999999 + 0.9999999999999999 + ], +) diff --git a/test/test_case63_degov1.jl b/test/test_case63_degov1.jl new file mode 100644 index 000000000..7855190ba --- /dev/null +++ b/test/test_case63_degov1.jl @@ -0,0 +1,208 @@ +""" +Validation PSSE/PIDGOV: +This case study defines a three bus system with an infinite bus, GENROU+DEGOV1 and a load. +The fault drop the line connecting the infinite bus and GENROU +""" + +################################################## +############### SOLVE PROBLEM #################### +################################################## + +# Define dyr files + +names = ["DEGOV1 MechTorque Flag", "DEGOV1 ElecTorque Flag"] + +dyr_files = [ + joinpath(TEST_FILES_DIR, "benchmarks/psse/DEGOV1/ThreeBus_DEGOV1_nodelay_flag0.dyr"), + joinpath(TEST_FILES_DIR, "benchmarks/psse/DEGOV1/ThreeBus_DEGOV1_nodelay_flag1.dyr"), +] + +csv_files = [ + joinpath(TEST_FILES_DIR, "benchmarks/psse/DEGOV1/DEGOV1_results_nodelay_flag0.csv"), + joinpath(TEST_FILES_DIR, "benchmarks/psse/DEGOV1/DEGOV1_results_nodelay_flag0.csv"), +] + +init_conditions = [test63_x0_init_Flag0, test63_x0_init_Flag1] + +eigs_values = [test63_eigvals_Flag0, test63_eigvals_Flag1] + +raw_file_dir = joinpath(TEST_FILES_DIR, "benchmarks/psse/DEGOV1/ThreeBusMulti.raw") +tspan = (0.0, 20.0) + +function test_degov1_implicit(dyr_file, csv_file, init_cond, eigs_value) + path = (joinpath(pwd(), "test-psse-degov1")) + !isdir(path) && mkdir(path) + try + sys = System(raw_file_dir, dyr_file) + for l in get_components(PSY.StandardLoad, sys) + transform_load_to_constant_impedance(l) + end + + # Define Simulation Problem + sim = Simulation!( + ResidualModel, + sys, #system + path, + tspan, #time span + BranchTrip(1.0, Line, "BUS 1-BUS 2-i_1"), #Type of Fault + ) #Type of Fault + + # Test Initial Condition + diff_val = [0.0] + res = get_init_values_for_comparison(sim) + for (k, v) in init_cond + diff_val[1] += LinearAlgebra.norm(res[k] - v) + end + + @test (diff_val[1] < 1e-3) + + # Obtain small signal results for initial conditions. Testing the simulation reset + small_sig = small_signal_analysis(sim) + eigs = small_sig.eigenvalues + @test small_sig.stable + + # Test Eigenvalues + @test LinearAlgebra.norm(eigs - eigs_value) < 1e-3 + + # Solve problem + @test execute!(sim, IDA(); dtmax = 0.005, saveat = 0.005) == + PSID.SIMULATION_FINALIZED + results = read_results(sim) + + # Obtain data for voltage magnitude at bus 102 + series = get_voltage_magnitude_series(results, 102) + t = series[1] + V = series[2] + # Test Vf, τm and branch series flows with PSSE + _, P101_103 = get_activepower_branch_flow(results, "BUS 1-BUS 3-i_1", :from) + _, Q101_103 = get_reactivepower_branch_flow(results, "BUS 1-BUS 3-i_1", :from) + _, P103_101 = get_activepower_branch_flow(results, "BUS 1-BUS 3-i_1", :to) + _, Q103_101 = get_reactivepower_branch_flow(results, "BUS 1-BUS 3-i_1", :to) + _, τm = get_mechanical_torque_series(results, "generator-102-1") + + # TODO: Get PSSE CSV files and enable tests + #M = get_csv_data(csv_file) + #t_psse = M[:, 1] + #V_psse = M[:, 2] + #P101_103_psse = M[:, 3] ./ 100.0 # convert to pu + #Q101_103_psse = M[:, 4] ./ 100.0 # convert to pu + #P103_101_psse = M[:, 5] ./ 100.0 # convert to pu + #Q103_101_psse = M[:, 6] ./ 100.0 # convert to pu + #Vf_psse = M[:, 7] + #τm_psse = M[:, 8] + + # Test Transient Simulation Results + #@test LinearAlgebra.norm(V - V_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(P101_103 - P101_103_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(Q101_103 - Q101_103_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(P103_101 - P103_101_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(Q103_101 - Q103_101_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(Vf - Vf_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(τm - τm_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(t - round.(t_psse, digits = 3)) == 0.0 + finally + @info("removing test files") + rm(path; force = true, recursive = true) + end +end + +function test_degov1_mass_matrix(dyr_file, csv_file, init_cond, eigs_value) + path = (joinpath(pwd(), "test-psse-degov1")) + !isdir(path) && mkdir(path) + try + sys = System(raw_file_dir, dyr_file) + for l in get_components(PSY.StandardLoad, sys) + transform_load_to_constant_impedance(l) + end + + # Define Simulation Problem + sim = Simulation!( + MassMatrixModel, + sys, #system + path, + tspan, #time span + BranchTrip(1.0, Line, "BUS 1-BUS 2-i_1"), #Type of Fault + ) #Type of Fault + + # Test Initial Condition + diff_val = [0.0] + res = get_init_values_for_comparison(sim) + for (k, v) in init_cond + diff_val[1] += LinearAlgebra.norm(res[k] - v) + end + + @test (diff_val[1] < 1e-3) + + # Obtain small signal results for initial conditions. Testing the simulation reset + small_sig = small_signal_analysis(sim) + eigs = small_sig.eigenvalues + @test small_sig.stable + + # Test Eigenvalues + @test LinearAlgebra.norm(eigs - eigs_value) < 1e-3 + + # Solve problem + @test execute!(sim, Rodas4(); dtmax = 0.005, saveat = 0.005) == + PSID.SIMULATION_FINALIZED + results = read_results(sim) + + # Obtain data for voltage magnitude at bus 102 + series = get_voltage_magnitude_series(results, 102) + t = series[1] + V = series[2] + # Test Vf, τm and branch series flows with PSSE + _, P101_103 = get_activepower_branch_flow(results, "BUS 1-BUS 3-i_1", :from) + _, Q101_103 = get_reactivepower_branch_flow(results, "BUS 1-BUS 3-i_1", :from) + _, P103_101 = get_activepower_branch_flow(results, "BUS 1-BUS 3-i_1", :to) + _, Q103_101 = get_reactivepower_branch_flow(results, "BUS 1-BUS 3-i_1", :to) + _, τm = get_mechanical_torque_series(results, "generator-102-1") + + # TODO: Get PSSE CSV files and enable tests + #M = get_csv_data(csv_file) + #t_psse = M[:, 1] + #V_psse = M[:, 2] + #P101_103_psse = M[:, 3] ./ 100.0 # convert to pu + #Q101_103_psse = M[:, 4] ./ 100.0 # convert to pu + #P103_101_psse = M[:, 5] ./ 100.0 # convert to pu + #Q103_101_psse = M[:, 6] ./ 100.0 # convert to pu + #Vf_psse = M[:, 7] + #τm_psse = M[:, 8] + + # Test Transient Simulation Results + #@test LinearAlgebra.norm(V - V_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(P101_103 - P101_103_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(Q101_103 - Q101_103_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(P103_101 - P103_101_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(Q103_101 - Q103_101_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(Vf - Vf_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(τm - τm_psse, Inf) <= 1e-2 + #@test LinearAlgebra.norm(t - round.(t_psse, digits = 3)) == 0.0 + finally + @info("removing test files") + rm(path; force = true, recursive = true) + end +end + +@testset "Test 63 DEGOV1 ResidualModel" begin + for (ix, name) in enumerate(names) + @testset "$(name)" begin + dyr_file = dyr_files[ix] + csv_file = csv_files[ix] + init_cond = init_conditions[ix] + eigs_value = eigs_values[ix] + test_degov1_implicit(dyr_file, csv_file, init_cond, eigs_value) + end + end +end + +@testset "Test 63 DEGOV1 MassMatrixModel" begin + for (ix, name) in enumerate(names) + @testset "$(name)" begin + dyr_file = dyr_files[ix] + csv_file = csv_files[ix] + init_cond = init_conditions[ix] + eigs_value = eigs_values[ix] + test_degov1_mass_matrix(dyr_file, csv_file, init_cond, eigs_value) + end + end +end From 8dd3f4d691dc6b211ea2c278e32cb99a34efb411 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Fri, 20 Sep 2024 16:56:36 -0700 Subject: [PATCH 15/15] fix typo --- src/models/generator_models/tg_models.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/generator_models/tg_models.jl b/src/models/generator_models/tg_models.jl index 3789f0866..900fecea5 100644 --- a/src/models/generator_models/tg_models.jl +++ b/src/models/generator_models/tg_models.jl @@ -116,7 +116,7 @@ function mdl_tg_ode!( Tm = PSY.get_Tm(tg) # Compute differential equation - droop_τ = P_ref + d_t * (ω_ref = get_ω_ref(device) - ω[1]) + droop_τ = P_ref + d_t * (ω_ref - ω[1]) output_ode[local_ix[1]] = (1.0 / Tm) * (droop_τ - τm) # Update Inner Vars