From e35ddcf79d9cbcaaa05c43a1adfa100df5be8696 Mon Sep 17 00:00:00 2001 From: Matt Bossart Date: Fri, 17 Nov 2023 11:12:51 -0500 Subject: [PATCH 1/7] add degov --- .../generator_components/init_tg.jl | 22 + src/models/generator_models/tg_models.jl | 69 + src/post_processing/post_proc_generator.jl | 13 + test/benchmarks/psse/DEGOV/ThreeBusMulti.raw | 32 + .../psse/DEGOV/ThreeBus_DEGOV_delay.dyr | 3 + .../psse/DEGOV/ThreeBus_DEGOV_nodelay.dyr | 3 + .../psse/DEGOV/ThreeBus_GAST_simple.dyr | 4 + .../psse/DEGOV/degov_delay_speed_final.csv | 1202 +++++++++++++++++ .../psse/DEGOV/degov_nodelay_speed_final.csv | 1202 +++++++++++++++++ test/results/results_eigenvalues.jl | 9 + test/results/results_initial_conditions.jl | 22 + test/test_case57_degov.jl | 216 +++ 12 files changed, 2797 insertions(+) create mode 100644 test/benchmarks/psse/DEGOV/ThreeBusMulti.raw create mode 100644 test/benchmarks/psse/DEGOV/ThreeBus_DEGOV_delay.dyr create mode 100644 test/benchmarks/psse/DEGOV/ThreeBus_DEGOV_nodelay.dyr create mode 100644 test/benchmarks/psse/DEGOV/ThreeBus_GAST_simple.dyr create mode 100644 test/benchmarks/psse/DEGOV/degov_delay_speed_final.csv create mode 100644 test/benchmarks/psse/DEGOV/degov_nodelay_speed_final.csv create mode 100644 test/test_case57_degov.jl diff --git a/src/initialization/generator_components/init_tg.jl b/src/initialization/generator_components/init_tg.jl index af4f5a725..7b91d492a 100644 --- a/src/initialization/generator_components/init_tg.jl +++ b/src/initialization/generator_components/init_tg.jl @@ -168,6 +168,28 @@ function initialize_tg!( return end +function initialize_tg!( + device_states, + static::PSY.StaticInjection, + dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, PSY.DEGOV, P}}, + inner_vars::AbstractVector, +) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS} + tg = PSY.get_prime_mover(dynamic_device) + #Get mechanical torque to SyncMach + τm0 = inner_vars[τm_var] + PSY.set_P_ref!(tg, τm0) + set_P_ref(dynamic_device, τm0) + #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 + 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 54a5f9770..f2ca9e1b7 100644 --- a/src/models/generator_models/tg_models.jl +++ b/src/models/generator_models/tg_models.jl @@ -16,6 +16,17 @@ function mass_matrix_tg_entries!( return end +function mass_matrix_tg_entries!( + mass_matrix, + tg::PSY.DEGOV, + global_index::Base.ImmutableDict{Symbol, Int64}, +) + mass_matrix[global_index[:x_ecb1], global_index[:x_ecb1]] = + PSY.get_T1(tg) * PSY.get_T2(tg) + mass_matrix[global_index[:x_a1], global_index[:x_a1]] = PSY.get_T5(tg) * PSY.get_T6(tg) + return +end + function mdl_tg_ode!( device_states::AbstractArray{<:ACCEPTED_REAL_TYPES}, ::AbstractArray{<:ACCEPTED_REAL_TYPES}, @@ -295,3 +306,61 @@ function mdl_tg_ode!( inner_vars[τm_var] = ((x_g4 - q_nl) * h * At - D_T * Δω * x_g3) / ω[1] 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.DEGOV, P}}, +) 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.DEGOV) + + #Define internal states for component + internal_states = @view device_states[local_ix] + x_ecb1 = internal_states[1] + x_ecb2 = internal_states[2] + x_a1 = internal_states[3] + x_a2 = internal_states[4] + x_a3 = internal_states[5] + + #Obtain external states inputs for component + external_ix = get_input_port_ix(device, PSY.DEGOV) + ω = @view device_states[external_ix] + + #Get Parameters + tg = PSY.get_prime_mover(device) + 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) + + #Compute block derivatives + Δω = ω[1] - 1.0 + y1, dx_ecb1, dx_ecb2 = + lead_lag_2nd_mass_matrix(-1.0 * Δω, x_ecb1, x_ecb2, T1, T1 * T2, T3, 0.0) + y2, dx_a1, dx_a2 = lead_lag_2nd_mass_matrix(y1, x_a1, x_a2, T5 + T6, T5 * T6, T4, 0.0) + y3, dx_a3 = integrator_windup(y2, x_a3, K, 1.0, -Inf, Inf) + P_m = y3 * (ω[1]) + + #Compute 1 State TG ODE: + output_ode[local_ix[1]] = dx_ecb1 + output_ode[local_ix[2]] = dx_ecb2 + output_ode[local_ix[3]] = dx_a1 + output_ode[local_ix[4]] = dx_a2 + output_ode[local_ix[5]] = dx_a3 + + #Update mechanical torque + inner_vars[τm_var] = P_m / ω[1] + + return +end diff --git a/src/post_processing/post_proc_generator.jl b/src/post_processing/post_proc_generator.jl index 105f8f811..44d09e971 100644 --- a/src/post_processing/post_proc_generator.jl +++ b/src/post_processing/post_proc_generator.jl @@ -1043,6 +1043,19 @@ function _mechanical_torque( return ts, τm end +""" +Function to obtain the mechanical torque time series of a Dynamic Generator with DEGOV Turbine Governor. + +""" +function _mechanical_torque( + tg::PSY.DEGOV, + name::String, + res::SimulationResults, + dt::Union{Nothing, Float64}, +) + 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 HydroTurbineGov (HYGOV) Turbine Governor. diff --git a/test/benchmarks/psse/DEGOV/ThreeBusMulti.raw b/test/benchmarks/psse/DEGOV/ThreeBusMulti.raw new file mode 100644 index 000000000..8fee35b92 --- /dev/null +++ b/test/benchmarks/psse/DEGOV/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/DEGOV/ThreeBus_DEGOV_delay.dyr b/test/benchmarks/psse/DEGOV/ThreeBus_DEGOV_delay.dyr new file mode 100644 index 000000000..327b44693 --- /dev/null +++ b/test/benchmarks/psse/DEGOV/ThreeBus_DEGOV_delay.dyr @@ -0,0 +1,3 @@ + 101 'GENCLS' 1 0 0 / + 102 'GENCLS' 1 8 0.03 / + 102 'DEGOV' 1 0 0 0 18 12 5 0.2 1 2 -0.1 / diff --git a/test/benchmarks/psse/DEGOV/ThreeBus_DEGOV_nodelay.dyr b/test/benchmarks/psse/DEGOV/ThreeBus_DEGOV_nodelay.dyr new file mode 100644 index 000000000..df98de821 --- /dev/null +++ b/test/benchmarks/psse/DEGOV/ThreeBus_DEGOV_nodelay.dyr @@ -0,0 +1,3 @@ + 101 'GENCLS' 1 0 0 / + 102 'GENCLS' 1 8 0.03 / + 102 'DEGOV' 1 0 0 0 18 12 5 0.2 0 2 -0.1 / diff --git a/test/benchmarks/psse/DEGOV/ThreeBus_GAST_simple.dyr b/test/benchmarks/psse/DEGOV/ThreeBus_GAST_simple.dyr new file mode 100644 index 000000000..1ed5bcaca --- /dev/null +++ b/test/benchmarks/psse/DEGOV/ThreeBus_GAST_simple.dyr @@ -0,0 +1,4 @@ + 101 'GENCLS' 1 0.0000 0.0000 / + 102 'GENCLS' 1 8.0000 0.30000E-01 / + 102 'GAST' 1 0.50000E-01 0.20000 0.20000 2.0000 + 2.0000 2.5000 1.1000 0.10000E-01 0.0000 / diff --git a/test/benchmarks/psse/DEGOV/degov_delay_speed_final.csv b/test/benchmarks/psse/DEGOV/degov_delay_speed_final.csv new file mode 100644 index 000000000..96d1c7fb6 --- /dev/null +++ b/test/benchmarks/psse/DEGOV/degov_delay_speed_final.csv @@ -0,0 +1,1202 @@ +0,1 +0.004167,1 +0.008333,1 +0.0125,1 +0.016667,1 +0.020833,1 +0.025,1 +0.029167,1 +0.033333,1 +0.0375,1 +0.041667,1 +0.045833,1 +0.05,1 +0.054167,1 +0.058333,1 +0.0625,1 +0.066667,1 +0.070833,1 +0.075,1 +0.079167,1 +0.083333,1 +0.0875,1 +0.091667,1 +0.095833,1 +0.1,1 +0.104167,1 +0.108333,1 +0.1125,1 +0.116667,1 +0.120833,1 +0.125,1 +0.129167,1 +0.133333,1 +0.1375,1 +0.141667,1 +0.145833,1 +0.15,1 +0.154167,1 +0.158333,1 +0.1625,1 +0.166667,1 +0.170833,1 +0.175,1 +0.179167,1 +0.183333,1 +0.1875,1 +0.191667,1 +0.195833,1 +0.2,1 +0.204167,1 +0.208333,1 +0.2125,1 +0.216667,1 +0.220833,1 +0.225,1 +0.229167,1 +0.233333,1 +0.2375,1 +0.241667,1 +0.245833,1 +0.25,1 +0.254167,1 +0.258333,1 +0.2625,1 +0.266667,1 +0.270833,1 +0.275,1 +0.279167,1 +0.283333,1 +0.2875,1 +0.291667,1 +0.295833,1 +0.3,1 +0.304167,1 +0.308333,1 +0.3125,1 +0.316667,1 +0.320833,1 +0.325,1 +0.329167,1 +0.333333,1 +0.3375,1 +0.341667,1 +0.345833,1 +0.35,1 +0.354167,1 +0.358333,1 +0.3625,1 +0.366667,1 +0.370833,1 +0.375,1 +0.379167,1 +0.383333,1 +0.3875,1 +0.391667,1 +0.395833,1 +0.4,1 +0.404167,1 +0.408333,1 +0.4125,1 +0.416667,1 +0.420833,1 +0.425,1 +0.429167,1 +0.433333,1 +0.4375,1 +0.441667,1 +0.445833,1 +0.45,1 +0.454167,1 +0.458333,1 +0.4625,1 +0.466667,1 +0.470833,1 +0.475,1 +0.479167,1 +0.483333,1 +0.4875,1 +0.491667,1 +0.495833,1 +0.5,1 +0.504167,1 +0.508333,1 +0.5125,1 +0.516667,1 +0.520833,1 +0.525,1 +0.529167,1 +0.533333,1 +0.5375,1 +0.541667,1 +0.545833,1 +0.55,1 +0.554167,1 +0.558333,1 +0.5625,1 +0.566667,1 +0.570833,1 +0.575,1 +0.579167,1 +0.583333,1 +0.5875,1 +0.591667,1 +0.595833,1 +0.6,1 +0.604167,1 +0.608333,1 +0.6125,1 +0.616667,1 +0.620833,1 +0.625,1 +0.629167,1 +0.633333,1 +0.6375,1 +0.641667,1 +0.645833,1 +0.65,1 +0.654167,1 +0.658333,1 +0.6625,1 +0.666667,1 +0.670833,1 +0.675,1 +0.679167,1 +0.683333,1 +0.6875,1 +0.691667,1 +0.695833,1 +0.7,1 +0.704167,1 +0.708333,1 +0.7125,1 +0.716667,1 +0.720833,1 +0.725,1 +0.729167,1 +0.733333,1 +0.7375,1 +0.741667,1 +0.745833,1 +0.75,1 +0.754167,1 +0.758333,1 +0.7625,1 +0.766667,1 +0.770833,1 +0.775,1 +0.779167,1 +0.783333,1 +0.7875,1 +0.791667,1 +0.795833,1 +0.8,1 +0.804167,1 +0.808333,1 +0.8125,1 +0.816667,1 +0.820833,1 +0.825,1 +0.829167,1 +0.833333,1 +0.8375,1 +0.841667,1 +0.845833,1 +0.85,1 +0.854167,1 +0.858333,1 +0.8625,1 +0.866667,1 +0.870833,1 +0.875,1 +0.879167,1 +0.883333,1 +0.8875,1 +0.891667,1 +0.895833,1 +0.9,1 +0.904167,1 +0.908333,1 +0.9125,1 +0.916667,1 +0.920833,1 +0.925,1 +0.929167,1 +0.933333,1 +0.9375,1 +0.941667,1 +0.945833,1 +0.95,1 +0.954167,1 +0.958333,1 +0.9625,1 +0.966667,1 +0.970833,1 +0.975,1 +0.979167,1 +0.983333,1 +0.9875,1 +0.991667,1 +0.995833,1 +1,1 +1,1 +1.004167,0.999990463 +1.008333,0.999980986 +1.0125,0.999971509 +1.016667,0.999962032 +1.020833,0.999952614 +1.025,0.999943197 +1.029167,0.999933839 +1.033333,0.999924541 +1.0375,0.999915302 +1.041667,0.999906123 +1.045833,0.999897063 +1.05,0.999888003 +1.054167,0.999879122 +1.058333,0.999870241 +1.0625,0.999861538 +1.066667,0.999852896 +1.070833,0.999844432 +1.075,0.999836028 +1.079167,0.999827743 +1.083333,0.999819636 +1.0875,0.999811649 +1.091667,0.999803841 +1.095833,0.999796152 +1.1,0.999788642 +1.104167,0.999781311 +1.108333,0.999774158 +1.1125,0.999767184 +1.116667,0.99976033 +1.120833,0.999753714 +1.125,0.999747336 +1.129167,0.999741077 +1.133333,0.999735057 +1.1375,0.999729276 +1.141667,0.999723673 +1.145833,0.999718249 +1.15,0.999713123 +1.154167,0.999708176 +1.158333,0.999703467 +1.1625,0.999699056 +1.166667,0.999694824 +1.170833,0.999690831 +1.175,0.999687076 +1.179167,0.999683619 +1.183333,0.99968034 +1.1875,0.99967736 +1.191667,0.999674618 +1.195833,0.999672174 +1.2,0.999669969 +1.204167,0.999668002 +1.208333,0.999666333 +1.2125,0.999664903 +1.216667,0.999663711 +1.220833,0.999662817 +1.225,0.99966222 +1.229167,0.999661863 +1.233333,0.999661803 +1.2375,0.999661982 +1.241667,0.999662399 +1.245833,0.999663115 +1.25,0.999664128 +1.254167,0.99966538 +1.258333,0.99966687 +1.2625,0.999668658 +1.266667,0.999670744 +1.270833,0.999673009 +1.275,0.999675632 +1.279167,0.999678433 +1.283333,0.999681532 +1.2875,0.99968487 +1.291667,0.999688447 +1.295833,0.999692261 +1.3,0.999696374 +1.304167,0.999700665 +1.308333,0.999705255 +1.3125,0.999710023 +1.316667,0.99971509 +1.320833,0.999720335 +1.325,0.999725819 +1.329167,0.999731481 +1.333333,0.999737442 +1.3375,0.999743521 +1.341667,0.999749839 +1.345833,0.999756396 +1.35,0.999763131 +1.354167,0.999770045 +1.358333,0.999777138 +1.3625,0.99978435 +1.366667,0.999791801 +1.370833,0.99979943 +1.375,0.999807179 +1.379167,0.999815106 +1.383333,0.999823213 +1.3875,0.999831378 +1.391667,0.999839723 +1.395833,0.999848247 +1.4,0.99985683 +1.404167,0.999865532 +1.408333,0.999874353 +1.4125,0.999883235 +1.416667,0.999892294 +1.420833,0.999901354 +1.425,0.999910533 +1.429167,0.999919772 +1.433333,0.99992913 +1.4375,0.999938488 +1.441667,0.999947906 +1.445833,0.999957323 +1.45,0.99996686 +1.454167,0.999976337 +1.458333,0.999985874 +1.4625,0.99999547 +1.466667,1.000005007 +1.470833,1.000014544 +1.475,1.00002408 +1.479167,1.000033617 +1.483333,1.000043035 +1.4875,1.000052571 +1.491667,1.000061989 +1.495833,1.000071287 +1.5,1.000080585 +1.504167,1.000089884 +1.508333,1.000099063 +1.5125,1.000108123 +1.516667,1.000117183 +1.520833,1.000126004 +1.525,1.000134826 +1.529167,1.000143528 +1.533333,1.000152111 +1.5375,1.000160575 +1.541667,1.00016892 +1.545833,1.000177145 +1.55,1.000185251 +1.554167,1.000193119 +1.558333,1.000200868 +1.5625,1.000208497 +1.566667,1.000215888 +1.570833,1.00022316 +1.575,1.000230312 +1.579167,1.000237107 +1.583333,1.000243902 +1.5875,1.00025034 +1.591667,1.000256658 +1.595833,1.000262737 +1.6,1.000268698 +1.604167,1.00027442 +1.608333,1.000279784 +1.6125,1.000285029 +1.616667,1.000290155 +1.620833,1.000294924 +1.625,1.000299454 +1.629167,1.000303745 +1.633333,1.000307798 +1.6375,1.000311613 +1.641667,1.000315189 +1.645833,1.000318527 +1.65,1.000321627 +1.654167,1.000324368 +1.658333,1.000326991 +1.6625,1.000329256 +1.666667,1.000331283 +1.670833,1.000333071 +1.675,1.000334501 +1.679167,1.000335813 +1.683333,1.000336766 +1.6875,1.000337481 +1.691667,1.000337958 +1.695833,1.000338078 +1.7,1.000337958 +1.704167,1.000337601 +1.708333,1.000337005 +1.7125,1.000336051 +1.716667,1.000334859 +1.720833,1.000333428 +1.725,1.000331759 +1.729167,1.000329733 +1.733333,1.000327587 +1.7375,1.000325084 +1.741667,1.000322342 +1.745833,1.000319362 +1.75,1.000316024 +1.754167,1.000312567 +1.758333,1.000308871 +1.7625,1.000304818 +1.766667,1.000300646 +1.770833,1.000296116 +1.775,1.000291467 +1.779167,1.00028646 +1.783333,1.000281334 +1.7875,1.00027597 +1.791667,1.000270367 +1.795833,1.000264525 +1.8,1.000258446 +1.804167,1.000252247 +1.808333,1.00024581 +1.8125,1.000239134 +1.816667,1.000232339 +1.820833,1.000225425 +1.825,1.000218153 +1.829167,1.000210881 +1.833333,1.000203371 +1.8375,1.000195622 +1.841667,1.000187874 +1.845833,1.000179887 +1.85,1.000171781 +1.854167,1.000163436 +1.858333,1.000155091 +1.8625,1.000146627 +1.866667,1.000137925 +1.870833,1.000129223 +1.875,1.000120401 +1.879167,1.000111461 +1.883333,1.000102401 +1.8875,1.000093341 +1.891667,1.000084162 +1.895833,1.000074983 +1.9,1.000065684 +1.904167,1.000056267 +1.908333,1.000046968 +1.9125,1.000037551 +1.916667,1.000028014 +1.920833,1.000018597 +1.925,1.00000906 +1.929167,0.999999583 +1.933333,0.999990046 +1.9375,0.999980569 +1.941667,0.999971092 +1.945833,0.999961674 +1.95,0.999952197 +1.954167,0.999942839 +1.958333,0.999933481 +1.9625,0.999924183 +1.966667,0.999915004 +1.970833,0.999905825 +1.975,0.999896705 +1.979167,0.999887705 +1.983333,0.999878824 +1.9875,0.999870002 +1.991667,0.99986124 +1.995833,0.999852657 +2,0.999844193 +2.004167,0.999835789 +2.008333,0.999827564 +2.0125,0.999819458 +2.016667,0.999811471 +2.020833,0.999803662 +2.025,0.999796033 +2.029167,0.999788523 +2.033333,0.999781191 +2.0375,0.999774039 +2.041667,0.999767065 +2.045833,0.99976027 +2.05,0.999753654 +2.054167,0.999747276 +2.058333,0.999741077 +2.0625,0.999735057 +2.066667,0.999729276 +2.070833,0.999723673 +2.075,0.999718308 +2.079167,0.999713182 +2.083333,0.999708295 +2.0875,0.999703586 +2.091667,0.999699175 +2.095833,0.999695003 +2.1,0.99969101 +2.104167,0.999687314 +2.108333,0.999683857 +2.1125,0.999680698 +2.116667,0.999677718 +2.120833,0.999675035 +2.125,0.999672592 +2.129167,0.999670446 +2.133333,0.999668539 +2.1375,0.999666929 +2.141667,0.999665558 +2.145833,0.999664426 +2.15,0.999663591 +2.154167,0.999663055 +2.158333,0.999662757 +2.1625,0.999662757 +2.166667,0.999663055 +2.170833,0.999663591 +2.175,0.999664366 +2.179167,0.999665439 +2.183333,0.99966681 +2.1875,0.999668419 +2.191667,0.999670327 +2.195833,0.999672472 +2.2,0.999674916 +2.204167,0.999677598 +2.208333,0.999680519 +2.2125,0.999683738 +2.216667,0.999687195 +2.220833,0.99969095 +2.225,0.999694943 +2.229167,0.999699175 +2.233333,0.999703646 +2.2375,0.999708354 +2.241667,0.999713302 +2.245833,0.999718547 +2.25,0.999723971 +2.254167,0.999729633 +2.258333,0.999735475 +2.2625,0.999741614 +2.266667,0.999747932 +2.270833,0.999754429 +2.275,0.999761164 +2.279167,0.999768078 +2.283333,0.999775231 +2.2875,0.999782503 +2.291667,0.999790013 +2.295833,0.999797702 +2.3,0.99980551 +2.304167,0.999813497 +2.308333,0.999821663 +2.3125,0.999830008 +2.316667,0.999838471 +2.320833,0.999847054 +2.325,0.999855757 +2.329167,0.999864638 +2.333333,0.999873579 +2.3375,0.999882698 +2.341667,0.999891877 +2.345833,0.999901116 +2.35,0.999910474 +2.354167,0.999919951 +2.358333,0.999929488 +2.3625,0.999939024 +2.366667,0.99994868 +2.370833,0.999958396 +2.375,0.999968112 +2.379167,0.999977887 +2.383333,0.999987662 +2.3875,0.999997497 +2.391667,1.000007272 +2.395833,1.000017166 +2.4,1.000026941 +2.404167,1.000036716 +2.408333,1.000046492 +2.4125,1.000056267 +2.416667,1.000065923 +2.420833,1.000075579 +2.425,1.000085235 +2.429167,1.000094771 +2.433333,1.000104308 +2.4375,1.000113726 +2.441667,1.000123024 +2.445833,1.000132203 +2.45,1.000141382 +2.454167,1.000150323 +2.458333,1.000159264 +2.4625,1.000168085 +2.466667,1.000176668 +2.470833,1.000185251 +2.475,1.000193596 +2.479167,1.000201821 +2.483333,1.000209928 +2.4875,1.000217795 +2.491667,1.000225544 +2.495833,1.000233054 +2.5,1.000240445 +2.504167,1.000247598 +2.508333,1.000254631 +2.5125,1.000261426 +2.516667,1.000267982 +2.520833,1.000274301 +2.525,1.000280499 +2.529167,1.00028646 +2.533333,1.000292182 +2.5375,1.000297546 +2.541667,1.000302792 +2.545833,1.000307798 +2.55,1.000312567 +2.554167,1.000316978 +2.558333,1.000321269 +2.5625,1.000325203 +2.566667,1.000329018 +2.570833,1.000332475 +2.575,1.000335574 +2.579167,1.000338554 +2.583333,1.000341177 +2.5875,1.000343561 +2.591667,1.000345588 +2.595833,1.000347495 +2.6,1.000349045 +2.604167,1.000350237 +2.608333,1.000351191 +2.6125,1.000351906 +2.616667,1.000352263 +2.620833,1.000352383 +2.625,1.000352263 +2.629167,1.000351787 +2.633333,1.000351071 +2.6375,1.000349998 +2.641667,1.000348687 +2.645833,1.000347137 +2.65,1.00034523 +2.654167,1.000343084 +2.658333,1.000340581 +2.6625,1.000337839 +2.666667,1.000334859 +2.670833,1.00033164 +2.675,1.000328064 +2.679167,1.000324249 +2.683333,1.000320196 +2.6875,1.000315905 +2.691667,1.000311255 +2.695833,1.000306368 +2.7,1.000301242 +2.704167,1.000295877 +2.708333,1.000290275 +2.7125,1.000284433 +2.716667,1.000278354 +2.720833,1.000272036 +2.725,1.000265598 +2.729167,1.000258803 +2.733333,1.00025177 +2.7375,1.000244617 +2.741667,1.000237226 +2.745833,1.000229597 +2.75,1.000221848 +2.754167,1.000213861 +2.758333,1.000205755 +2.7625,1.000197411 +2.766667,1.000188947 +2.770833,1.000180244 +2.775,1.000171423 +2.779167,1.000162482 +2.783333,1.000153303 +2.7875,1.000144124 +2.791667,1.000134706 +2.795833,1.000125289 +2.8,1.000115633 +2.804167,1.000105977 +2.808333,1.000096202 +2.8125,1.000086308 +2.816667,1.000076294 +2.820833,1.00006628 +2.825,1.000056148 +2.829167,1.000046015 +2.833333,1.000035763 +2.8375,1.000025511 +2.841667,1.000015259 +2.845833,1.000005007 +2.85,0.999994636 +2.854167,0.999984324 +2.858333,0.999973953 +2.8625,0.999963641 +2.866667,0.99995333 +2.870833,0.999943018 +2.875,0.999932766 +2.879167,0.999922574 +2.883333,0.999912441 +2.8875,0.999902308 +2.891667,0.999892294 +2.895833,0.999882281 +2.9,0.999872446 +2.904167,0.999862611 +2.908333,0.999852955 +2.9125,0.999843359 +2.916667,0.999833882 +2.920833,0.999824524 +2.925,0.999815285 +2.929167,0.999806166 +2.933333,0.999797225 +2.9375,0.999788463 +2.941667,0.99977982 +2.945833,0.999771357 +2.95,0.999763012 +2.954167,0.999754906 +2.958333,0.999746978 +2.9625,0.99973923 +2.966667,0.999731719 +2.970833,0.999724388 +2.975,0.999717236 +2.979167,0.999710321 +2.983333,0.999703646 +2.9875,0.999697208 +2.991667,0.99969095 +2.995833,0.999684989 +3,0.999679208 +3.004167,0.999673724 +3.008333,0.999668539 +3.0125,0.999663532 +3.016667,0.999658823 +3.020833,0.999654353 +3.025,0.99965018 +3.029167,0.999646306 +3.033333,0.99964267 +3.0375,0.999639332 +3.041667,0.999636292 +3.045833,0.999633491 +3.05,0.999631047 +3.054167,0.999628842 +3.058333,0.999626935 +3.0625,0.999625325 +3.066667,0.999624074 +3.070833,0.99962306 +3.075,0.999622345 +3.079167,0.999621928 +3.083333,0.999621868 +3.0875,0.999622047 +3.091667,0.999622583 +3.095833,0.999623358 +3.1,0.999624491 +3.104167,0.999625921 +3.108333,0.99962765 +3.1125,0.999629676 +3.116667,0.999631941 +3.120833,0.999634564 +3.125,0.999637485 +3.129167,0.999640703 +3.133333,0.99964422 +3.1375,0.999647975 +3.141667,0.999652088 +3.145833,0.999656439 +3.15,0.999661028 +3.154167,0.999665976 +3.158333,0.999671161 +3.1625,0.999676585 +3.166667,0.999682307 +3.170833,0.999688327 +3.175,0.999694526 +3.179167,0.999701023 +3.183333,0.999707758 +3.1875,0.999714792 +3.191667,0.999722004 +3.195833,0.999729455 +3.2,0.999737084 +3.204167,0.999745011 +3.208333,0.999753118 +3.2125,0.999761403 +3.216667,0.999769926 +3.220833,0.999778628 +3.225,0.999787509 +3.229167,0.999796629 +3.233333,0.999805868 +3.2375,0.999815285 +3.241667,0.999824822 +3.245833,0.999834538 +3.25,0.999844432 +3.254167,0.999854445 +3.258333,0.999864519 +3.2625,0.999874771 +3.266667,0.999885142 +3.270833,0.999895632 +3.275,0.999906182 +3.279167,0.999916792 +3.283333,0.999927521 +3.2875,0.999938309 +3.291667,0.999949157 +3.295833,0.999960065 +3.3,0.999970973 +3.304167,0.99998194 +3.308333,0.999992967 +3.3125,1.000003934 +3.316667,1.00001502 +3.320833,1.000025988 +3.325,1.000037074 +3.329167,1.000048041 +3.333333,1.000059009 +3.3375,1.000069857 +3.341667,1.000080824 +3.345833,1.000091553 +3.35,1.000102401 +3.354167,1.00011301 +3.358333,1.00012362 +3.3625,1.00013411 +3.366667,1.000144601 +3.370833,1.000154853 +3.375,1.000165105 +3.379167,1.000175118 +3.383333,1.000185132 +3.3875,1.000194907 +3.391667,1.000204563 +3.395833,1.000213981 +3.4,1.000223398 +3.404167,1.000232577 +3.408333,1.000241518 +3.4125,1.00025034 +3.416667,1.000258923 +3.420833,1.000267267 +3.425,1.000275493 +3.429167,1.00028348 +3.433333,1.000291228 +3.4375,1.000298738 +3.441667,1.00030601 +3.445833,1.000313044 +3.45,1.000319839 +3.454167,1.000326395 +3.458333,1.000332713 +3.4625,1.000338793 +3.466667,1.000344515 +3.470833,1.000349998 +3.475,1.000355244 +3.479167,1.00036025 +3.483333,1.0003649 +3.4875,1.000369191 +3.491667,1.000373363 +3.495833,1.000377059 +3.5,1.000380516 +3.504167,1.000383735 +3.508333,1.000386596 +3.5125,1.000389099 +3.516667,1.000391364 +3.520833,1.000393391 +3.525,1.00039494 +3.529167,1.000396252 +3.533333,1.000397205 +3.5375,1.000397921 +3.541667,1.000398278 +3.545833,1.000398278 +3.55,1.00039804 +3.554167,1.000397444 +3.558333,1.00039649 +3.5625,1.000395298 +3.566667,1.000393748 +3.570833,1.000391841 +3.575,1.000389576 +3.579167,1.000387073 +3.583333,1.000384331 +3.5875,1.000381112 +3.591667,1.000377774 +3.595833,1.00037396 +3.6,1.000369906 +3.604167,1.000365615 +3.608333,1.000360966 +3.6125,1.000355959 +3.616667,1.000350714 +3.620833,1.00034523 +3.625,1.000339508 +3.629167,1.000333428 +3.633333,1.00032711 +3.6375,1.000320435 +3.641667,1.00031352 +3.645833,1.000306487 +3.65,1.000299096 +3.654167,1.000291467 +3.658333,1.000283599 +3.6625,1.000275493 +3.666667,1.000267148 +3.670833,1.000258565 +3.675,1.000249863 +3.679167,1.000240922 +3.683333,1.000231743 +3.6875,1.000222325 +3.691667,1.000212789 +3.695833,1.000203133 +3.7,1.000193238 +3.704167,1.000183105 +3.708333,1.000172973 +3.7125,1.000162601 +3.716667,1.000152111 +3.720833,1.000141382 +3.725,1.000130653 +3.729167,1.000119805 +3.733333,1.000108838 +3.7375,1.000097752 +3.741667,1.000086546 +3.745833,1.00007534 +3.75,1.000064015 +3.754167,1.000052691 +3.758333,1.000041246 +3.7625,1.000029802 +3.766667,1.000018239 +3.770833,1.000006795 +3.775,0.999995232 +3.779167,0.999983668 +3.783333,0.999972105 +3.7875,0.999960601 +3.791667,0.999949038 +3.795833,0.999937594 +3.8,0.99992615 +3.804167,0.999914706 +3.808333,0.999903381 +3.8125,0.999892116 +3.816667,0.99988091 +3.820833,0.999869823 +3.825,0.999858797 +3.829167,0.999847829 +3.833333,0.999837041 +3.8375,0.999826372 +3.841667,0.999815822 +3.845833,0.999805391 +3.85,0.999795079 +3.854167,0.999784946 +3.858333,0.999774992 +3.8625,0.999765217 +3.866667,0.999755621 +3.870833,0.999746144 +3.875,0.999736965 +3.879167,0.999727905 +3.883333,0.999719083 +3.8875,0.999710441 +3.891667,0.999702096 +3.895833,0.99969393 +3.9,0.999686003 +3.904167,0.999678314 +3.908333,0.999670923 +3.9125,0.999663711 +3.916667,0.999656856 +3.920833,0.99965018 +3.925,0.999643803 +3.929167,0.999637723 +3.933333,0.999631941 +3.9375,0.999626398 +3.941667,0.999621212 +3.945833,0.999616265 +3.95,0.999611676 +3.954167,0.999607384 +3.958333,0.999603331 +3.9625,0.999599695 +3.966667,0.999596298 +3.970833,0.999593258 +3.975,0.999590516 +3.979167,0.999588132 +3.983333,0.999586046 +3.9875,0.999584317 +3.991667,0.999582946 +3.995833,0.999581873 +4,0.999581099 +4.004167,0.999580681 +4.008333,0.999580622 +4.0125,0.99958092 +4.016667,0.999581516 +4.020833,0.999582469 +4.025,0.999583781 +4.029167,0.99958539 +4.033333,0.999587357 +4.0375,0.999589622 +4.041667,0.999592245 +4.045833,0.999595225 +4.05,0.999598503 +4.054167,0.999602079 +4.058333,0.999606013 +4.0625,0.999610305 +4.066667,0.999614835 +4.070833,0.999619722 +4.075,0.999624968 +4.079167,0.999630451 +4.083333,0.999636292 +4.0875,0.999642372 +4.091667,0.999648809 +4.095833,0.999655485 +4.1,0.999662459 +4.104167,0.999669731 +4.108333,0.9996773 +4.1125,0.999685109 +4.116667,0.999693155 +4.120833,0.99970144 +4.125,0.999710023 +4.129167,0.999718845 +4.133333,0.999727905 +4.1375,0.999737203 +4.141667,0.99974668 +4.145833,0.999756396 +4.15,0.99976635 +4.154167,0.999776423 +4.158333,0.999786794 +4.1625,0.999797285 +4.166667,0.999807954 +4.170833,0.999818742 +4.175,0.999829769 +4.179167,0.999840915 +4.183333,0.99985218 +4.1875,0.999863565 +4.191667,0.999875128 +4.195833,0.999886751 +4.2,0.999898493 +4.204167,0.999910355 +4.208333,0.999922276 +4.2125,0.999934316 +4.216667,0.999946356 +4.220833,0.999958456 +4.225,0.999970675 +4.229167,0.999982834 +4.233333,0.999995053 +4.2375,1.000007272 +4.241667,1.00001955 +4.245833,1.000031829 +4.25,1.000044107 +4.254167,1.000056267 +4.258333,1.000068426 +4.2625,1.000080585 +4.266667,1.000092626 +4.270833,1.000104666 +4.275,1.000116587 +4.279167,1.000128388 +4.283333,1.00014019 +4.2875,1.000151873 +4.291667,1.000163436 +4.295833,1.00017488 +4.3,1.000186205 +4.304167,1.000197291 +4.308333,1.000208259 +4.3125,1.000219226 +4.316667,1.000229836 +4.320833,1.000240326 +4.325,1.000250697 +4.329167,1.00026083 +4.333333,1.000270724 +4.3375,1.000280499 +4.341667,1.000289917 +4.345833,1.000299215 +4.35,1.000308275 +4.354167,1.000317097 +4.358333,1.00032568 +4.3625,1.000333905 +4.366667,1.000342011 +4.370833,1.00034976 +4.375,1.00035727 +4.379167,1.000364423 +4.383333,1.000371337 +4.3875,1.000378013 +4.391667,1.000384331 +4.395833,1.00039041 +4.4,1.000396132 +4.404167,1.000401497 +4.408333,1.000406623 +4.4125,1.000411391 +4.416667,1.000415802 +4.420833,1.000419855 +4.425,1.00042367 +4.429167,1.000427127 +4.433333,1.000430226 +4.4375,1.000432968 +4.441667,1.000435352 +4.445833,1.000437379 +4.45,1.000439167 +4.454167,1.000440478 +4.458333,1.000441432 +4.4625,1.000442147 +4.466667,1.000442386 +4.470833,1.000442386 +4.475,1.000441909 +4.479167,1.000441194 +4.483333,1.000440001 +4.4875,1.000438571 +4.491667,1.000436783 +4.495833,1.000434518 +4.5,1.000432014 +4.504167,1.000429153 +4.508333,1.000425935 +4.5125,1.000422359 +4.516667,1.000418425 +4.520833,1.000414133 +4.525,1.000409603 +4.529167,1.000404596 +4.533333,1.000399351 +4.5375,1.000393748 +4.541667,1.000387907 +4.545833,1.000381708 +4.55,1.000375152 +4.554167,1.000368357 +4.558333,1.000361204 +4.5625,1.000353813 +4.566667,1.000346065 +4.570833,1.000338078 +4.575,1.000329733 +4.579167,1.00032115 +4.583333,1.000312328 +4.5875,1.000303268 +4.591667,1.00029397 +4.595833,1.000284433 +4.6,1.000274658 +4.604167,1.000264525 +4.608333,1.000254273 +4.6125,1.000243902 +4.616667,1.000233173 +4.620833,1.000222325 +4.625,1.000211239 +4.629167,1.000200033 +4.633333,1.000188589 +4.6375,1.000177026 +4.641667,1.000165343 +4.645833,1.000153542 +4.65,1.000141501 +4.654167,1.000129342 +4.658333,1.000117183 +4.6625,1.000104785 +4.666667,1.000092387 +4.670833,1.00007987 +4.675,1.000067234 +4.679167,1.000054598 +4.683333,1.000041842 +4.6875,1.000029087 +4.691667,1.000016332 +4.695833,1.000003457 +4.7,0.999990642 +4.704167,0.999977767 +4.708333,0.999964952 +4.7125,0.999952137 +4.716667,0.999939322 +4.720833,0.999926567 +4.725,0.999913871 +4.729167,0.999901175 +4.733333,0.999888599 +4.7375,0.999876082 +4.741667,0.999863625 +4.745833,0.999851286 +4.75,0.999839067 +4.754167,0.999826968 +4.758333,0.999814987 +4.7625,0.999803126 +4.766667,0.999791443 +4.770833,0.99977988 +4.775,0.999768496 +4.779167,0.99975729 +4.783333,0.999746263 +4.7875,0.999735415 +4.791667,0.999724746 +4.795833,0.999714315 +4.8,0.999704123 +4.804167,0.999694109 +4.808333,0.999684393 +4.8125,0.999674857 +4.816667,0.999665618 +4.820833,0.999656618 +4.825,0.999647856 +4.829167,0.999639392 +4.833333,0.999631226 +4.8375,0.999623299 +4.841667,0.999615729 +4.845833,0.999608397 +4.85,0.999601424 +4.854167,0.999594688 +4.858333,0.99958837 +4.8625,0.999582291 +4.866667,0.999576569 +4.870833,0.999571204 +4.875,0.999566138 +4.879167,0.999561429 +4.883333,0.999557078 +4.8875,0.999553084 +4.891667,0.999549389 +4.895833,0.999546111 +4.9,0.99954319 +4.904167,0.999540627 +4.908333,0.999538422 +4.9125,0.999536574 +4.916667,0.999535084 +4.920833,0.999534011 +4.925,0.999533296 +4.929167,0.999532938 +4.933333,0.999532938 +4.9375,0.999533355 +4.941667,0.99953413 +4.945833,0.999535322 +4.95,0.999536812 +4.954167,0.99953872 +4.958333,0.999540985 +4.9625,0.999543667 +4.966667,0.999546647 +4.970833,0.999550045 +4.975,0.9995538 +4.979167,0.999557912 +4.983333,0.999562383 +4.9875,0.999567211 +4.991667,0.999572396 +4.995833,0.99957794 +5,0.99958384 diff --git a/test/benchmarks/psse/DEGOV/degov_nodelay_speed_final.csv b/test/benchmarks/psse/DEGOV/degov_nodelay_speed_final.csv new file mode 100644 index 000000000..0fcec2bc0 --- /dev/null +++ b/test/benchmarks/psse/DEGOV/degov_nodelay_speed_final.csv @@ -0,0 +1,1202 @@ +0,1 +0.004167,1 +0.008333,1 +0.0125,1 +0.016667,1 +0.020833,1 +0.025,1 +0.029167,1 +0.033333,1 +0.0375,1 +0.041667,1 +0.045833,1 +0.05,1 +0.054167,1 +0.058333,1 +0.0625,1 +0.066667,1 +0.070833,1 +0.075,1 +0.079167,1 +0.083333,1 +0.0875,1 +0.091667,1 +0.095833,1 +0.1,1 +0.104167,1 +0.108333,1 +0.1125,1 +0.116667,1 +0.120833,1 +0.125,1 +0.129167,1 +0.133333,1 +0.1375,1 +0.141667,1 +0.145833,1 +0.15,1 +0.154167,1 +0.158333,1 +0.1625,1 +0.166667,1 +0.170833,1 +0.175,1 +0.179167,1 +0.183333,1 +0.1875,1 +0.191667,1 +0.195833,1 +0.2,1 +0.204167,1 +0.208333,1 +0.2125,1 +0.216667,1 +0.220833,1 +0.225,1 +0.229167,1 +0.233333,1 +0.2375,1 +0.241667,1 +0.245833,1 +0.25,1 +0.254167,1 +0.258333,1 +0.2625,1 +0.266667,1 +0.270833,1 +0.275,1 +0.279167,1 +0.283333,1 +0.2875,1 +0.291667,1 +0.295833,1 +0.3,1 +0.304167,1 +0.308333,1 +0.3125,1 +0.316667,1 +0.320833,1 +0.325,1 +0.329167,1 +0.333333,1 +0.3375,1 +0.341667,1 +0.345833,1 +0.35,1 +0.354167,1 +0.358333,1 +0.3625,1 +0.366667,1 +0.370833,1 +0.375,1 +0.379167,1 +0.383333,1 +0.3875,1 +0.391667,1 +0.395833,1 +0.4,1 +0.404167,1 +0.408333,1 +0.4125,1 +0.416667,1 +0.420833,1 +0.425,1 +0.429167,1 +0.433333,1 +0.4375,1 +0.441667,1 +0.445833,1 +0.45,1 +0.454167,1 +0.458333,1 +0.4625,1 +0.466667,1 +0.470833,1 +0.475,1 +0.479167,1 +0.483333,1 +0.4875,1 +0.491667,1 +0.495833,1 +0.5,1 +0.504167,1 +0.508333,1 +0.5125,1 +0.516667,1 +0.520833,1 +0.525,1 +0.529167,1 +0.533333,1 +0.5375,1 +0.541667,1 +0.545833,1 +0.55,1 +0.554167,1 +0.558333,1 +0.5625,1 +0.566667,1 +0.570833,1 +0.575,1 +0.579167,1 +0.583333,1 +0.5875,1 +0.591667,1 +0.595833,1 +0.6,1 +0.604167,1 +0.608333,1 +0.6125,1 +0.616667,1 +0.620833,1 +0.625,1 +0.629167,1 +0.633333,1 +0.6375,1 +0.641667,1 +0.645833,1 +0.65,1 +0.654167,1 +0.658333,1 +0.6625,1 +0.666667,1 +0.670833,1 +0.675,1 +0.679167,1 +0.683333,1 +0.6875,1 +0.691667,1 +0.695833,1 +0.7,1 +0.704167,1 +0.708333,1 +0.7125,1 +0.716667,1 +0.720833,1 +0.725,1 +0.729167,1 +0.733333,1 +0.7375,1 +0.741667,1 +0.745833,1 +0.75,1 +0.754167,1 +0.758333,1 +0.7625,1 +0.766667,1 +0.770833,1 +0.775,1 +0.779167,1 +0.783333,1 +0.7875,1 +0.791667,1 +0.795833,1 +0.8,1 +0.804167,1 +0.808333,1 +0.8125,1 +0.816667,1 +0.820833,1 +0.825,1 +0.829167,1 +0.833333,1 +0.8375,1 +0.841667,1 +0.845833,1 +0.85,1 +0.854167,1 +0.858333,1 +0.8625,1 +0.866667,1 +0.870833,1 +0.875,1 +0.879167,1 +0.883333,1 +0.8875,1 +0.891667,1 +0.895833,1 +0.9,1 +0.904167,1 +0.908333,1 +0.9125,1 +0.916667,1 +0.920833,1 +0.925,1 +0.929167,1 +0.933333,1 +0.9375,1 +0.941667,1 +0.945833,1 +0.95,1 +0.954167,1 +0.958333,1 +0.9625,1 +0.966667,1 +0.970833,1 +0.975,1 +0.979167,1 +0.983333,1 +0.9875,1 +0.991667,1 +0.995833,1 +1,1 +1,1 +1.004167,0.99999046 +1.008333,0.99998099 +1.0125,0.99997151 +1.016667,0.99996203 +1.020833,0.99995261 +1.025,0.9999432 +1.029167,0.99993384 +1.033333,0.99992454 +1.0375,0.9999153 +1.041667,0.99990612 +1.045833,0.99989706 +1.05,0.999888 +1.054167,0.99987912 +1.058333,0.9998703 +1.0625,0.99986154 +1.066667,0.99985296 +1.070833,0.99984443 +1.075,0.99983603 +1.079167,0.9998278 +1.083333,0.9998197 +1.0875,0.99981177 +1.091667,0.9998039 +1.095833,0.99979627 +1.1,0.99978876 +1.104167,0.99978143 +1.108333,0.99977428 +1.1125,0.99976736 +1.116667,0.99976057 +1.120833,0.99975395 +1.125,0.99974757 +1.129167,0.99974138 +1.133333,0.99973541 +1.1375,0.99972963 +1.141667,0.99972409 +1.145833,0.99971873 +1.15,0.99971366 +1.154167,0.99970877 +1.158333,0.99970412 +1.1625,0.99969971 +1.166667,0.99969554 +1.170833,0.99969167 +1.175,0.99968797 +1.179167,0.99968457 +1.183333,0.99968141 +1.1875,0.99967855 +1.191667,0.99967587 +1.195833,0.99967355 +1.2,0.9996714 +1.204167,0.99966955 +1.208333,0.999668 +1.2125,0.99966669 +1.216667,0.99966568 +1.220833,0.9996649 +1.225,0.99966443 +1.229167,0.99966419 +1.233333,0.99966425 +1.2375,0.9996646 +1.241667,0.9996652 +1.245833,0.99966609 +1.25,0.99966723 +1.254167,0.99966866 +1.258333,0.99967039 +1.2625,0.99967235 +1.266667,0.99967462 +1.270833,0.99967712 +1.275,0.99967986 +1.279167,0.9996829 +1.283333,0.99968618 +1.2875,0.99968976 +1.291667,0.99969357 +1.295833,0.99969763 +1.3,0.99970192 +1.304167,0.99970651 +1.308333,0.99971128 +1.3125,0.99971634 +1.316667,0.99972159 +1.320833,0.99972713 +1.325,0.99973285 +1.329167,0.99973881 +1.333333,0.99974495 +1.3375,0.99975133 +1.341667,0.99975795 +1.345833,0.99976474 +1.35,0.99977171 +1.354167,0.99977893 +1.358333,0.99978626 +1.3625,0.99979383 +1.366667,0.99980152 +1.370833,0.99980944 +1.375,0.99981749 +1.379167,0.99982566 +1.383333,0.999834 +1.3875,0.99984252 +1.391667,0.99985111 +1.395833,0.99985987 +1.4,0.99986875 +1.404167,0.99987769 +1.408333,0.99988681 +1.4125,0.99989599 +1.416667,0.99990529 +1.420833,0.99991459 +1.425,0.99992406 +1.429167,0.99993354 +1.433333,0.99994308 +1.4375,0.99995273 +1.441667,0.99996239 +1.445833,0.99997205 +1.45,0.99998176 +1.454167,0.99999148 +1.458333,1.00000119 +1.4625,1.00001097 +1.466667,1.00002074 +1.470833,1.00003052 +1.475,1.00004017 +1.479167,1.00004983 +1.483333,1.00005949 +1.4875,1.00006914 +1.491667,1.00007868 +1.495833,1.00008821 +1.5,1.00009763 +1.504167,1.00010693 +1.508333,1.00011623 +1.5125,1.00012541 +1.516667,1.00013447 +1.520833,1.00014341 +1.525,1.00015235 +1.529167,1.00016105 +1.533333,1.00016963 +1.5375,1.0001781 +1.541667,1.00018644 +1.545833,1.00019455 +1.55,1.00020266 +1.554167,1.00021052 +1.558333,1.00021815 +1.5625,1.00022566 +1.566667,1.00023305 +1.570833,1.00024009 +1.575,1.00024712 +1.579167,1.0002538 +1.583333,1.00026035 +1.5875,1.00026667 +1.591667,1.00027287 +1.595833,1.00027871 +1.6,1.00028431 +1.604167,1.0002898 +1.608333,1.00029504 +1.6125,1.00029993 +1.616667,1.0003047 +1.620833,1.00030911 +1.625,1.00031328 +1.629167,1.00031722 +1.633333,1.00032091 +1.6375,1.00032437 +1.641667,1.00032759 +1.645833,1.00033045 +1.65,1.00033307 +1.654167,1.00033545 +1.658333,1.00033748 +1.6625,1.00033927 +1.666667,1.00034082 +1.670833,1.00034201 +1.675,1.00034297 +1.679167,1.00034368 +1.683333,1.00034404 +1.6875,1.00034416 +1.691667,1.00034392 +1.695833,1.00034356 +1.7,1.00034273 +1.704167,1.00034177 +1.708333,1.00034046 +1.7125,1.00033879 +1.716667,1.000337 +1.720833,1.00033486 +1.725,1.00033236 +1.729167,1.00032961 +1.733333,1.00032663 +1.7375,1.00032341 +1.741667,1.00031996 +1.745833,1.00031614 +1.75,1.00031209 +1.754167,1.0003078 +1.758333,1.00030327 +1.7625,1.00029838 +1.766667,1.00029337 +1.770833,1.00028801 +1.775,1.00028253 +1.779167,1.00027668 +1.783333,1.00027072 +1.7875,1.00026441 +1.791667,1.00025797 +1.795833,1.00025129 +1.8,1.00024438 +1.804167,1.00023735 +1.808333,1.00022995 +1.8125,1.00022244 +1.816667,1.00021482 +1.820833,1.00020695 +1.825,1.00019884 +1.829167,1.00019073 +1.833333,1.00018227 +1.8375,1.00017381 +1.841667,1.0001651 +1.845833,1.00015628 +1.85,1.00014734 +1.854167,1.00013816 +1.858333,1.00012898 +1.8625,1.00011969 +1.866667,1.00011027 +1.870833,1.00010073 +1.875,1.00009108 +1.879167,1.00008142 +1.883333,1.00007164 +1.8875,1.00006175 +1.891667,1.00005186 +1.895833,1.00004184 +1.9,1.00003195 +1.904167,1.00002182 +1.908333,1.0000118 +1.9125,1.00000167 +1.916667,0.99999166 +1.920833,0.99998152 +1.925,0.99997145 +1.929167,0.99996138 +1.933333,0.9999513 +1.9375,0.99994129 +1.941667,0.99993134 +1.945833,0.99992138 +1.95,0.99991149 +1.954167,0.99990165 +1.958333,0.99989194 +1.9625,0.99988228 +1.966667,0.99987268 +1.970833,0.99986321 +1.975,0.99985379 +1.979167,0.99984449 +1.983333,0.99983537 +1.9875,0.99982631 +1.991667,0.99981743 +1.995833,0.99980867 +2,0.99980009 +2.004167,0.99979162 +2.008333,0.99978334 +2.0125,0.99977517 +2.016667,0.99976724 +2.020833,0.99975944 +2.025,0.99975187 +2.029167,0.99974447 +2.033333,0.99973732 +2.0375,0.99973035 +2.041667,0.99972355 +2.045833,0.99971706 +2.05,0.99971068 +2.054167,0.9997046 +2.058333,0.99969876 +2.0625,0.99969316 +2.066667,0.99968779 +2.070833,0.99968266 +2.075,0.99967778 +2.079167,0.99967319 +2.083333,0.99966884 +2.0875,0.99966472 +2.091667,0.99966091 +2.095833,0.99965739 +2.1,0.99965411 +2.104167,0.99965113 +2.108333,0.99964845 +2.1125,0.99964601 +2.116667,0.99964392 +2.120833,0.99964207 +2.125,0.99964052 +2.129167,0.99963921 +2.133333,0.99963826 +2.1375,0.9996376 +2.141667,0.99963725 +2.145833,0.99963713 +2.15,0.99963737 +2.154167,0.99963784 +2.158333,0.99963868 +2.1625,0.99963975 +2.166667,0.99964118 +2.170833,0.99964285 +2.175,0.99964482 +2.179167,0.99964714 +2.183333,0.9996497 +2.1875,0.99965256 +2.191667,0.99965566 +2.195833,0.99965912 +2.2,0.99966282 +2.204167,0.99966681 +2.208333,0.9996711 +2.2125,0.99967563 +2.216667,0.9996804 +2.220833,0.99968547 +2.225,0.99969083 +2.229167,0.99969643 +2.233333,0.99970227 +2.2375,0.99970835 +2.241667,0.99971467 +2.245833,0.99972129 +2.25,0.99972808 +2.254167,0.99973512 +2.258333,0.99974239 +2.2625,0.99974984 +2.266667,0.99975753 +2.270833,0.99976546 +2.275,0.99977356 +2.279167,0.99978185 +2.283333,0.99979031 +2.2875,0.99979895 +2.291667,0.99980778 +2.295833,0.99981678 +2.3,0.99982589 +2.304167,0.99983519 +2.308333,0.99984461 +2.3125,0.99985421 +2.316667,0.99986392 +2.320833,0.9998737 +2.325,0.99988365 +2.329167,0.99989367 +2.333333,0.9999038 +2.3375,0.99991405 +2.341667,0.9999243 +2.345833,0.99993467 +2.35,0.9999451 +2.354167,0.99995559 +2.358333,0.99996614 +2.3625,0.99997669 +2.366667,0.99998724 +2.370833,0.99999785 +2.375,1.00000846 +2.379167,1.00001907 +2.383333,1.00002968 +2.3875,1.00004029 +2.391667,1.0000509 +2.395833,1.00006139 +2.4,1.00007188 +2.404167,1.00008237 +2.408333,1.00009274 +2.4125,1.000103 +2.416667,1.00011325 +2.420833,1.00012338 +2.425,1.0001334 +2.429167,1.00014341 +2.433333,1.00015318 +2.4375,1.00016296 +2.441667,1.0001725 +2.445833,1.00018203 +2.45,1.00019133 +2.454167,1.00020051 +2.458333,1.00020945 +2.4625,1.00021839 +2.466667,1.00022697 +2.470833,1.00023556 +2.475,1.00024378 +2.479167,1.00025189 +2.483333,1.00025988 +2.4875,1.00026751 +2.491667,1.00027502 +2.495833,1.00028229 +2.5,1.00028932 +2.504167,1.00029612 +2.508333,1.00030267 +2.5125,1.00030899 +2.516667,1.00031507 +2.520833,1.00032091 +2.525,1.00032651 +2.529167,1.00033176 +2.533333,1.00033677 +2.5375,1.00034153 +2.541667,1.00034606 +2.545833,1.00035024 +2.55,1.00035417 +2.554167,1.00035775 +2.558333,1.00036108 +2.5625,1.00036418 +2.566667,1.00036693 +2.570833,1.00036943 +2.575,1.00037158 +2.579167,1.00037336 +2.583333,1.00037491 +2.5875,1.00037611 +2.591667,1.00037706 +2.595833,1.00037766 +2.6,1.00037801 +2.604167,1.00037801 +2.608333,1.00037777 +2.6125,1.00037706 +2.616667,1.00037622 +2.620833,1.00037491 +2.625,1.00037336 +2.629167,1.00037158 +2.633333,1.00036943 +2.6375,1.00036693 +2.641667,1.00036418 +2.645833,1.0003612 +2.65,1.00035787 +2.654167,1.00035417 +2.658333,1.00035024 +2.6625,1.00034606 +2.666667,1.00034153 +2.670833,1.00033677 +2.675,1.00033164 +2.679167,1.00032628 +2.683333,1.00032067 +2.6875,1.00031483 +2.691667,1.00030863 +2.695833,1.00030231 +2.7,1.00029564 +2.704167,1.00028872 +2.708333,1.00028157 +2.7125,1.00027418 +2.716667,1.00026667 +2.720833,1.0002588 +2.725,1.00025082 +2.729167,1.00024247 +2.733333,1.00023413 +2.7375,1.00022542 +2.741667,1.0002166 +2.745833,1.00020754 +2.75,1.00019836 +2.754167,1.00018907 +2.758333,1.00017953 +2.7625,1.00016987 +2.766667,1.00015998 +2.770833,1.00015008 +2.775,1.00013995 +2.779167,1.0001297 +2.783333,1.00011945 +2.7875,1.00010896 +2.791667,1.00009847 +2.795833,1.00008786 +2.8,1.00007713 +2.804167,1.0000664 +2.808333,1.00005555 +2.8125,1.0000447 +2.816667,1.00003374 +2.820833,1.00002289 +2.825,1.0000118 +2.829167,1.00000083 +2.833333,0.99998981 +2.8375,0.99997884 +2.841667,0.99996781 +2.845833,0.99995685 +2.85,0.99994588 +2.854167,0.99993491 +2.858333,0.99992406 +2.8625,0.99991322 +2.866667,0.99990249 +2.870833,0.99989176 +2.875,0.99988115 +2.879167,0.99987066 +2.883333,0.99986023 +2.8875,0.99984986 +2.891667,0.99983966 +2.895833,0.99982959 +2.9,0.99981964 +2.904167,0.9998098 +2.908333,0.99980015 +2.9125,0.99979061 +2.916667,0.99978125 +2.920833,0.99977207 +2.925,0.99976307 +2.929167,0.99975425 +2.933333,0.99974567 +2.9375,0.9997372 +2.941667,0.99972898 +2.945833,0.99972099 +2.95,0.99971318 +2.954167,0.99970567 +2.958333,0.99969834 +2.9625,0.99969125 +2.966667,0.99968439 +2.970833,0.99967784 +2.975,0.99967152 +2.979167,0.99966544 +2.983333,0.99965966 +2.9875,0.99965411 +2.991667,0.99964887 +2.995833,0.99964392 +3,0.99963921 +3.004167,0.9996348 +3.008333,0.99963075 +3.0125,0.99962693 +3.016667,0.99962348 +3.020833,0.99962026 +3.025,0.9996174 +3.029167,0.99961483 +3.033333,0.99961257 +3.0375,0.9996106 +3.041667,0.99960899 +3.045833,0.99960768 +3.05,0.99960667 +3.054167,0.99960601 +3.058333,0.99960566 +3.0625,0.99960566 +3.066667,0.99960595 +3.070833,0.99960661 +3.075,0.9996075 +3.079167,0.99960881 +3.083333,0.99961036 +3.0875,0.99961227 +3.091667,0.99961454 +3.095833,0.9996171 +3.1,0.99961996 +3.104167,0.99962312 +3.108333,0.99962658 +3.1125,0.99963039 +3.116667,0.9996345 +3.120833,0.99963892 +3.125,0.99964362 +3.129167,0.99964863 +3.133333,0.99965394 +3.1375,0.99965954 +3.141667,0.99966538 +3.145833,0.99967152 +3.15,0.99967796 +3.154167,0.99968463 +3.158333,0.99969161 +3.1625,0.99969882 +3.166667,0.99970627 +3.170833,0.99971402 +3.175,0.99972194 +3.179167,0.99973017 +3.183333,0.99973857 +3.1875,0.99974722 +3.191667,0.9997561 +3.195833,0.99976516 +3.2,0.9997744 +3.204167,0.99978387 +3.208333,0.99979353 +3.2125,0.99980336 +3.216667,0.99981332 +3.220833,0.99982351 +3.225,0.99983382 +3.229167,0.99984425 +3.233333,0.99985486 +3.2375,0.99986559 +3.241667,0.99987638 +3.245833,0.99988735 +3.25,0.99989837 +3.254167,0.99990952 +3.258333,0.99992079 +3.2625,0.99993205 +3.266667,0.99994344 +3.270833,0.99995482 +3.275,0.99996632 +3.279167,0.99997783 +3.283333,0.99998933 +3.2875,1.00000083 +3.291667,1.0000124 +3.295833,1.00002396 +3.3,1.00003552 +3.304167,1.00004709 +3.308333,1.00005853 +3.3125,1.00006998 +3.316667,1.00008142 +3.320833,1.00009274 +3.325,1.00010407 +3.329167,1.00011528 +3.333333,1.00012636 +3.3375,1.00013733 +3.341667,1.0001483 +3.345833,1.00015903 +3.35,1.00016975 +3.354167,1.00018024 +3.358333,1.00019073 +3.3625,1.00020099 +3.366667,1.00021112 +3.370833,1.00022101 +3.375,1.00023079 +3.379167,1.00024033 +3.383333,1.00024974 +3.3875,1.00025892 +3.391667,1.00026786 +3.395833,1.00027668 +3.4,1.00028515 +3.404167,1.00029349 +3.408333,1.0003016 +3.4125,1.00030947 +3.416667,1.0003171 +3.420833,1.00032437 +3.425,1.00033152 +3.429167,1.00033832 +3.433333,1.00034475 +3.4375,1.00035107 +3.441667,1.00035703 +3.445833,1.00036275 +3.45,1.00036812 +3.454167,1.00037324 +3.458333,1.00037801 +3.4625,1.00038254 +3.466667,1.00038671 +3.470833,1.00039053 +3.475,1.00039411 +3.479167,1.00039732 +3.483333,1.00040019 +3.4875,1.00040281 +3.491667,1.00040507 +3.495833,1.00040698 +3.5,1.00040853 +3.504167,1.00040984 +3.508333,1.0004108 +3.5125,1.00041127 +3.516667,1.00041151 +3.520833,1.00041151 +3.525,1.00041103 +3.529167,1.00041032 +3.533333,1.00040925 +3.5375,1.00040781 +3.541667,1.00040603 +3.545833,1.00040388 +3.55,1.0004015 +3.554167,1.00039876 +3.558333,1.00039566 +3.5625,1.0003922 +3.566667,1.0003885 +3.570833,1.00038445 +3.575,1.00038004 +3.579167,1.00037539 +3.583333,1.00037038 +3.5875,1.00036502 +3.591667,1.00035942 +3.595833,1.00035357 +3.6,1.00034738 +3.604167,1.00034094 +3.608333,1.00033414 +3.6125,1.00032711 +3.616667,1.00031984 +3.620833,1.00031221 +3.625,1.00030434 +3.629167,1.00029624 +3.633333,1.00028801 +3.6375,1.00027943 +3.641667,1.00027061 +3.645833,1.00026155 +3.65,1.00025225 +3.654167,1.00024283 +3.658333,1.00023317 +3.6625,1.00022328 +3.666667,1.00021327 +3.670833,1.00020301 +3.675,1.00019252 +3.679167,1.00018203 +3.683333,1.0001713 +3.6875,1.00016034 +3.691667,1.00014937 +3.695833,1.00013816 +3.7,1.00012696 +3.704167,1.00011551 +3.708333,1.00010407 +3.7125,1.00009251 +3.716667,1.00008082 +3.720833,1.00006914 +3.725,1.00005734 +3.729167,1.00004542 +3.733333,1.0000335 +3.7375,1.00002158 +3.741667,1.00000966 +3.745833,0.99999768 +3.75,0.99998569 +3.754167,0.99997371 +3.758333,0.99996173 +3.7625,0.99994975 +3.766667,0.99993783 +3.770833,0.99992597 +3.775,0.99991411 +3.779167,0.99990237 +3.783333,0.99989069 +3.7875,0.99987906 +3.791667,0.9998675 +3.795833,0.99985611 +3.8,0.99984479 +3.804167,0.99983358 +3.808333,0.9998225 +3.8125,0.99981153 +3.816667,0.99980074 +3.820833,0.99979007 +3.825,0.99977958 +3.829167,0.99976927 +3.833333,0.99975914 +3.8375,0.99974918 +3.841667,0.99973947 +3.845833,0.99972993 +3.85,0.99972057 +3.854167,0.99971145 +3.858333,0.99970257 +3.8625,0.99969393 +3.866667,0.99968553 +3.870833,0.99967736 +3.875,0.99966943 +3.879167,0.9996618 +3.883333,0.99965441 +3.8875,0.99964732 +3.891667,0.99964052 +3.895833,0.99963397 +3.9,0.99962771 +3.904167,0.99962181 +3.908333,0.99961615 +3.9125,0.99961084 +3.916667,0.99960583 +3.920833,0.99960113 +3.925,0.99959677 +3.929167,0.99959272 +3.933333,0.99958897 +3.9375,0.99958563 +3.941667,0.99958253 +3.945833,0.99957985 +3.95,0.99957746 +3.954167,0.99957544 +3.958333,0.99957377 +3.9625,0.99957246 +3.966667,0.99957144 +3.970833,0.99957079 +3.975,0.99957055 +3.979167,0.99957061 +3.983333,0.99957103 +3.9875,0.9995718 +3.991667,0.99957287 +3.995833,0.99957436 +4,0.99957621 +4.004167,0.99957836 +4.008333,0.99958086 +4.0125,0.99958372 +4.016667,0.99958694 +4.020833,0.99959046 +4.025,0.99959439 +4.029167,0.99959856 +4.033333,0.99960315 +4.0375,0.99960804 +4.041667,0.99961323 +4.045833,0.99961877 +4.05,0.99962461 +4.054167,0.99963075 +4.058333,0.99963725 +4.0625,0.99964404 +4.066667,0.99965107 +4.070833,0.99965847 +4.075,0.99966609 +4.079167,0.99967402 +4.083333,0.99968225 +4.0875,0.99969071 +4.091667,0.99969947 +4.095833,0.99970841 +4.1,0.99971765 +4.104167,0.99972713 +4.108333,0.99973685 +4.1125,0.9997468 +4.116667,0.99975693 +4.120833,0.9997673 +4.125,0.99977785 +4.129167,0.99978858 +4.133333,0.99979955 +4.1375,0.99981064 +4.141667,0.9998219 +4.145833,0.99983335 +4.15,0.99984491 +4.154167,0.99985659 +4.158333,0.99986845 +4.1625,0.99988037 +4.166667,0.99989247 +4.170833,0.99990463 +4.175,0.99991685 +4.179167,0.99992919 +4.183333,0.99994159 +4.1875,0.99995404 +4.191667,0.9999665 +4.195833,0.99997908 +4.2,0.9999916 +4.204167,1.00000417 +4.208333,1.00001681 +4.2125,1.00002933 +4.216667,1.00004196 +4.220833,1.00005448 +4.225,1.000067 +4.229167,1.00007939 +4.233333,1.00009179 +4.2375,1.00010419 +4.241667,1.00011647 +4.245833,1.00012863 +4.25,1.00014067 +4.254167,1.00015271 +4.258333,1.00016451 +4.2625,1.00017631 +4.266667,1.00018787 +4.270833,1.00019932 +4.275,1.00021064 +4.279167,1.00022173 +4.283333,1.0002327 +4.2875,1.00024343 +4.291667,1.00025403 +4.295833,1.00026441 +4.3,1.00027454 +4.304167,1.00028455 +4.308333,1.00029421 +4.3125,1.00030375 +4.316667,1.00031292 +4.320833,1.00032198 +4.325,1.00033069 +4.329167,1.00033915 +4.333333,1.00034738 +4.3375,1.00035524 +4.341667,1.00036287 +4.345833,1.00037026 +4.35,1.0003773 +4.354167,1.00038397 +4.358333,1.00039041 +4.3625,1.00039649 +4.366667,1.00040233 +4.370833,1.00040781 +4.375,1.00041294 +4.379167,1.00041771 +4.383333,1.00042224 +4.3875,1.00042629 +4.391667,1.00043011 +4.395833,1.00043344 +4.4,1.00043654 +4.404167,1.00043929 +4.408333,1.00044167 +4.4125,1.00044358 +4.416667,1.00044525 +4.420833,1.00044656 +4.425,1.00044739 +4.429167,1.00044799 +4.433333,1.00044811 +4.4375,1.00044799 +4.441667,1.00044739 +4.445833,1.00044644 +4.45,1.00044513 +4.454167,1.00044346 +4.458333,1.00044143 +4.4625,1.00043905 +4.466667,1.00043631 +4.470833,1.00043321 +4.475,1.00042975 +4.479167,1.00042593 +4.483333,1.00042188 +4.4875,1.00041735 +4.491667,1.00041246 +4.495833,1.00040722 +4.5,1.00040174 +4.504167,1.00039589 +4.508333,1.0003897 +4.5125,1.00038326 +4.516667,1.00037634 +4.520833,1.00036919 +4.525,1.0003618 +4.529167,1.00035405 +4.533333,1.00034606 +4.5375,1.00033772 +4.541667,1.00032914 +4.545833,1.0003202 +4.55,1.00031102 +4.554167,1.00030172 +4.558333,1.00029206 +4.5625,1.00028217 +4.566667,1.00027192 +4.570833,1.00026166 +4.575,1.00025105 +4.579167,1.00024021 +4.583333,1.00022924 +4.5875,1.00021803 +4.591667,1.00020659 +4.595833,1.00019503 +4.6,1.00018334 +4.604167,1.00017142 +4.608333,1.00015938 +4.6125,1.00014722 +4.616667,1.00013494 +4.620833,1.00012255 +4.625,1.00011003 +4.629167,1.00009739 +4.633333,1.00008464 +4.6375,1.00007188 +4.641667,1.00005901 +4.645833,1.00004613 +4.65,1.00003314 +4.654167,1.00002015 +4.658333,1.00000715 +4.6625,0.9999941 +4.666667,0.99998105 +4.670833,0.99996799 +4.675,0.99995494 +4.679167,0.99994195 +4.683333,0.99992895 +4.6875,0.99991608 +4.691667,0.9999032 +4.695833,0.99989039 +4.7,0.99987769 +4.704167,0.99986506 +4.708333,0.99985254 +4.7125,0.99984014 +4.716667,0.9998278 +4.720833,0.99981564 +4.725,0.99980366 +4.729167,0.99979174 +4.733333,0.99978006 +4.7375,0.9997685 +4.741667,0.99975711 +4.745833,0.99974597 +4.75,0.999735 +4.754167,0.99972421 +4.758333,0.99971366 +4.7625,0.99970329 +4.766667,0.99969321 +4.770833,0.99968332 +4.775,0.99967372 +4.779167,0.99966437 +4.783333,0.99965531 +4.7875,0.99964648 +4.791667,0.9996379 +4.795833,0.99962968 +4.8,0.99962175 +4.804167,0.99961406 +4.808333,0.99960673 +4.8125,0.9995997 +4.816667,0.99959302 +4.820833,0.99958664 +4.825,0.99958056 +4.829167,0.99957484 +4.833333,0.99956948 +4.8375,0.99956447 +4.841667,0.99955976 +4.845833,0.99955547 +4.85,0.99955153 +4.854167,0.9995479 +4.858333,0.99954468 +4.8625,0.99954182 +4.866667,0.99953932 +4.870833,0.99953723 +4.875,0.9995355 +4.879167,0.99953413 +4.883333,0.99953318 +4.8875,0.99953258 +4.891667,0.99953234 +4.895833,0.99953252 +4.9,0.99953306 +4.904167,0.99953401 +4.908333,0.99953532 +4.9125,0.99953699 +4.916667,0.99953908 +4.920833,0.99954152 +4.925,0.99954438 +4.929167,0.9995476 +4.933333,0.99955118 +4.9375,0.99955511 +4.941667,0.99955946 +4.945833,0.99956411 +4.95,0.99956918 +4.954167,0.9995746 +4.958333,0.99958032 +4.9625,0.99958646 +4.966667,0.9995929 +4.970833,0.9995997 +4.975,0.99960685 +4.979167,0.9996143 +4.983333,0.99962211 +4.9875,0.99963015 +4.991667,0.99963862 +4.995833,0.99964732 +5,0.99965632 diff --git a/test/results/results_eigenvalues.jl b/test/results/results_eigenvalues.jl index 91f5f3c43..e8dd1a497 100644 --- a/test/results/results_eigenvalues.jl +++ b/test/results/results_eigenvalues.jl @@ -926,3 +926,12 @@ test51_eigvals = [ -1.891493423695123 - 0.005547448083844577im, -1.891493423695123 + 0.005547448083844577im, ] + +test_57_eigvals = [ + -5.0 + 0.0im, + -0.2 + 0.0im, + -0.0009375000000000001 - 8.535768441947553im, + -0.0009375000000000001 + 8.535768441947553im, + 0.0 + 0.0im, + 0.0 + 0.0im, +] diff --git a/test/results/results_initial_conditions.jl b/test/results/results_initial_conditions.jl index 602f021c9..b78fa4c4b 100644 --- a/test/results/results_initial_conditions.jl +++ b/test/results/results_initial_conditions.jl @@ -1699,3 +1699,25 @@ test55_x0_init = Dict{String, Any}( 0.599999547004699 ], ) + +test_57_x0_init = Dict( + "V_R" => [ + 1.05 + 1.0198615749401696 + 0.9817964461177487 + ], + "V_I" => [ + 0.0 + -0.01680380791834505 + -0.15145839832533242 + ], + "generator-102-1" => [ + 0.22113174009221107 + 1.0 + 0.0 + 0.0 + 0.0 + 0.0 + 1.0 + ], +) diff --git a/test/test_case57_degov.jl b/test/test_case57_degov.jl new file mode 100644 index 000000000..0567f6401 --- /dev/null +++ b/test/test_case57_degov.jl @@ -0,0 +1,216 @@ +""" +Validation PSSE/DEGOV: +This case study defines a three bus system with an infinite bus, ClassicMachine+DEGOV and a load. +The fault drop the line connecting the infinite bus and generator +""" + +################################################## +############### SOLVE PROBLEM #################### +################################################## +raw_file = joinpath(TEST_FILES_DIR, "benchmarks/psse/DEGOV/ThreeBusMulti.raw") +dyr_file = joinpath(TEST_FILES_DIR, "benchmarks/psse/DEGOV/ThreeBus_GAST_simple.dyr") #manually replace with DEGOV + +csv_file_degov_nodelay_speed = + joinpath(TEST_FILES_DIR, "benchmarks/psse/DEGOV/degov_nodelay_speed_final.csv") +csv_file_degov_delay_speed = + joinpath(TEST_FILES_DIR, "benchmarks/psse/DEGOV/degov_delay_speed_final.csv") + +@testset "Test 57 DEGOV ResidualModel" begin + path = mktempdir() + try + sys = System(raw_file, dyr_file) + for l in get_components(PSY.StandardLoad, sys) + transform_load_to_constant_impedance(l) + end + gen = get_component(ThermalStandard, sys, "generator-102-1") + dyn_gen = get_component(DynamicGenerator, sys, "generator-102-1") + + new_gov = PSY.DEGOV(; + T1 = 0.0, + T2 = 0.0, + T3 = 0.0, + K = 18.0, + T4 = 12.0, + T5 = 5.0, + T6 = 0.2, + Td = 0.0, + P_ref = 0.0, + ) + dyn_gen_new = DynamicGenerator(; + name = get_name(dyn_gen), + ω_ref = get_ω_ref(dyn_gen), + machine = get_machine(dyn_gen), + shaft = get_shaft(dyn_gen), + avr = get_avr(dyn_gen), + prime_mover = new_gov, + pss = get_pss(dyn_gen), + base_power = get_base_power(dyn_gen), + ) + remove_component!(sys, dyn_gen) + add_component!(sys, dyn_gen_new, gen) + + # Define Simulation Problem + sim = Simulation!( + ResidualModel, + sys, + path, + (0.0, 5.0), + BranchTrip(1.0, Line, "BUS 1-BUS 2-i_1"); + frequency_reference = ReferenceBus(), + ) + + # Test Initial Condition + diff_val = [0.0] + res = get_init_values_for_comparison(sim) + for (k, v) in test_57_x0_init + diff_val[1] += LinearAlgebra.norm(res[k] - v) + end + @test (diff_val[1] < 1e-5) + + # 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 - test_57_eigvals) < 1e-10 + + # Solve problem + @test execute!(sim, IDA(); dtmax = (1 / 240), saveat = (1 / 240)) == + PSID.SIMULATION_FINALIZED + results_nodelay = read_results(sim) + + # Add delay + set_Td!(get_prime_mover(dyn_gen_new), 1.0) + sim = Simulation!( + ResidualModel, + sys, + path, + (0.0, 5.0), + BranchTrip(1.0, Line, "BUS 1-BUS 2-i_1"); + frequency_reference = ReferenceBus(), + ) + @test execute!(sim, IDA(); dtmax = (1 / 240), saveat = (1 / 240)) == + PSID.SIMULATION_FINALIZED + results_delay = read_results(sim) + + t_psid, ω_psid_nodelay = get_frequency_series(results_nodelay, "generator-102-1") + t_psid, ω_psid_delay = get_frequency_series(results_delay, "generator-102-1") + t_pw, ω_pw_nodelay = get_csv_delta(csv_file_degov_nodelay_speed) + t_pw, ω_pw_delay = get_csv_delta(csv_file_degov_delay_speed) + + @test LinearAlgebra.norm(ω_pw_nodelay - ω_psid_nodelay, Inf) <= 4.7e-5 + #@test LinearAlgebra.norm(ω_pw_delay - ω_psid_delay, Inf) <= 4.7e-5 #THIS SHOULD PASS ONCE DELAYS ARE INCLUDED IN PSID + + #Plotting for debug (add PlotlyJS): + #t1 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_nodelay, name = "speed-pw -- no delay") + #t2 = PlotlyJS.scatter(; x = t_psid, y = ω_psid_nodelay, name = "speed-psid -- no delay") + #t3 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_delay, name = "speed-pw -- 1s delay") + #t4 = PlotlyJS.scatter(; x = t_pw, y = ω_psid_delay, name = "speed-psid -- 1s delay") + #display(PlotlyJS.plot([t1, t2, t3, t4])) + + finally + @info("removing test files") + rm(path; force = true, recursive = true) + end +end + +@testset "Test 57 DEGOV MassMatrixModel" begin + path = mktempdir() + try + sys = System(raw_file, dyr_file) + for l in get_components(PSY.StandardLoad, sys) + transform_load_to_constant_impedance(l) + end + gen = get_component(ThermalStandard, sys, "generator-102-1") + dyn_gen = get_component(DynamicGenerator, sys, "generator-102-1") + + new_gov = PSY.DEGOV(; + T1 = 0.0, + T2 = 0.0, + T3 = 0.0, + K = 18.0, + T4 = 12.0, + T5 = 5.0, + T6 = 0.2, + Td = 0.0, + P_ref = 0.0, + ) + dyn_gen_new = DynamicGenerator(; + name = get_name(dyn_gen), + ω_ref = get_ω_ref(dyn_gen), + machine = get_machine(dyn_gen), + shaft = get_shaft(dyn_gen), + avr = get_avr(dyn_gen), + prime_mover = new_gov, + pss = get_pss(dyn_gen), + base_power = get_base_power(dyn_gen), + ) + remove_component!(sys, dyn_gen) + add_component!(sys, dyn_gen_new, gen) + + # Define Simulation Problem + sim = Simulation!( + MassMatrixModel, + sys, + path, + (0.0, 5.0), + BranchTrip(1.0, Line, "BUS 1-BUS 2-i_1"); + frequency_reference = ReferenceBus(), + ) + + # Test Initial Condition + diff_val = [0.0] + res = get_init_values_for_comparison(sim) + for (k, v) in test_57_x0_init + diff_val[1] += LinearAlgebra.norm(res[k] - v) + end + @test (diff_val[1] < 1e-5) + + # 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 - test_57_eigvals) < 1e-10 + + # Solve problem + @test execute!(sim, Rodas4(); dtmax = (1 / 240), saveat = (1 / 240)) == + PSID.SIMULATION_FINALIZED + results_nodelay = read_results(sim) + + # Add delay + set_Td!(get_prime_mover(dyn_gen_new), 1.0) + sim = Simulation!( + MassMatrixModel, + sys, + path, + (0.0, 5.0), + BranchTrip(1.0, Line, "BUS 1-BUS 2-i_1"); + frequency_reference = ReferenceBus(), + ) + @test execute!(sim, Rodas4(); dtmax = (1 / 240), saveat = (1 / 240)) == + PSID.SIMULATION_FINALIZED + results_delay = read_results(sim) + + t_psid, ω_psid_nodelay = get_frequency_series(results_nodelay, "generator-102-1") + t_psid, ω_psid_delay = get_frequency_series(results_delay, "generator-102-1") + t_pw, ω_pw_nodelay = get_csv_delta(csv_file_degov_nodelay_speed) + t_pw, ω_pw_delay = get_csv_delta(csv_file_degov_delay_speed) + + @test LinearAlgebra.norm(ω_pw_nodelay - ω_psid_nodelay, Inf) <= 4.7e-5 + #@test LinearAlgebra.norm(ω_pw_delay - ω_psid_delay, Inf) <= 4.7e-5 #THIS SHOULD PASS ONCE DELAYS ARE INCLUDED IN PSID + + #Plotting for debug (add PlotlyJS): + #t1 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_nodelay, name = "speed-pw -- no delay") + #t2 = PlotlyJS.scatter(; x = t_psid, y = ω_psid_nodelay, name = "speed-psid -- no delay") + #t3 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_delay, name = "speed-pw -- 1s delay") + #t4 = PlotlyJS.scatter(; x = t_pw, y = ω_psid_delay, name = "speed-psid -- 1s delay") + #display(PlotlyJS.plot([t1, t2, t3, t4])) + + finally + @info("removing test files") + rm(path; force = true, recursive = true) + end +end From e9b5afe6b83658a1c5b631cf12f761a391ed1d6e Mon Sep 17 00:00:00 2001 From: Matt Bossart Date: Mon, 11 Dec 2023 12:07:07 -0500 Subject: [PATCH 2/7] work in progress (add delays) --- src/base/device_wrapper.jl | 6 +++ src/base/jacobian.jl | 50 ++++++++++++++++++- src/base/nlsolve_wrapper.jl | 18 ++++++- src/base/simulation.jl | 37 +++++++++++++- src/base/simulation_inputs.jl | 18 +++++++ src/base/simulation_model.jl | 7 ++- src/base/system_model.jl | 9 ++-- src/models/device.jl | 38 ++++++++++---- src/models/generator_models/avr_models.jl | 23 ++++++++- src/models/generator_models/machine_models.jl | 24 +++++++++ src/models/generator_models/pss_models.jl | 14 ++++++ src/models/generator_models/shaft_models.jl | 4 ++ src/models/generator_models/tg_models.jl | 26 +++++++++- src/models/inverter_models/DCside_models.jl | 2 + .../inverter_models/converter_models.jl | 6 +++ src/models/inverter_models/filter_models.jl | 4 ++ .../frequency_estimator_models.jl | 6 +++ .../inverter_models/inner_control_models.jl | 12 +++++ .../inverter_models/outer_control_models.jl | 10 ++++ src/models/system.jl | 50 ++++++++++++++++--- test/Project.toml | 3 ++ test/runtests.jl | 3 ++ test/test_case57_degov.jl | 47 +++++++++++------ 23 files changed, 375 insertions(+), 42 deletions(-) diff --git a/src/base/device_wrapper.jl b/src/base/device_wrapper.jl index 7ef0c79a6..add78c12b 100644 --- a/src/base/device_wrapper.jl +++ b/src/base/device_wrapper.jl @@ -20,6 +20,12 @@ index(::Type{<:PSY.InnerControl}) = 4 index(::Type{<:PSY.Converter}) = 5 index(::Type{<:PSY.Filter}) = 6 +get_delays(::PSY.DynamicInjection) = nothing +get_delays( + dynamic_injector::PSY.DynamicGenerator{M, S, A, PSY.DEGOV, P}, +) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS} = + PSY.get_Td(PSY.get_prime_mover(dynamic_injector)) + """ Wraps DynamicInjection devices from PowerSystems to handle changes in controls and connection status, and allocate the required indexes of the state space. diff --git a/src/base/jacobian.jl b/src/base/jacobian.jl index 65fd020f3..53c7c4408 100644 --- a/src/base/jacobian.jl +++ b/src/base/jacobian.jl @@ -37,6 +37,17 @@ function (J::JacobianFunctionWrapper)( return end +function (J::JacobianFunctionWrapper)( + JM::U, + x::AbstractVector{Float64}, + h, + p, + t, +) where {U <: Union{Matrix{Float64}, SparseArrays.SparseMatrixCSC{Float64, Int64}}} + J(JM, x) + return +end + function (J::JacobianFunctionWrapper)( JM::U, dx::AbstractVector{Float64}, @@ -53,7 +64,7 @@ function (J::JacobianFunctionWrapper)( end function JacobianFunctionWrapper( - m!::SystemModel{MassMatrixModel}, + m!::SystemModel{MassMatrixModel, NoDelays}, x0_guess::Vector{Float64}; # Improve the heuristic to do sparsity detection sparse_retrieve_loop::Int = 0, #max(3, length(x0_guess) ÷ 100), @@ -122,6 +133,43 @@ function JacobianFunctionWrapper( return JacobianFunctionWrapper{typeof(Jf), typeof(Jv)}(Jf, Jv, x0, mass_matrix) end +function JacobianFunctionWrapper( + m!::SystemModel{MassMatrixModel, HasDelays}, + x0_guess::Vector{Float64}; + # Improve the heuristic to do sparsity detection + sparse_retrieve_loop::Int = 0, #max(3, length(x0_guess) ÷ 100), +) + x0 = deepcopy(x0_guess) + n = length(x0) + + h(p, t; idxs = nothing) = typeof(idxs) <: Number ? x0[idxs] : x0 #Possilby the problem? Should pass the h that is stored in the problem instead of redefining? + m_ = (residual, x) -> m!(residual, x, h, nothing, 0.0) + jconfig = ForwardDiff.JacobianConfig(m_, similar(x0), x0, ForwardDiff.Chunk(x0)) + Jf = (Jv, x) -> begin + @debug "Evaluating Jacobian Function" + ForwardDiff.jacobian!(Jv, m_, zeros(n), x, jconfig) + return + end + jac = zeros(n, n) + if sparse_retrieve_loop > 0 + for _ in 1:sparse_retrieve_loop + temp = zeros(n, n) + rng_state = copy(Random.default_rng()) + Jf(temp, x0 + Random.randn(n)) + copy!(Random.default_rng(), rng_state) + jac .+= abs.(temp) + end + Jv = SparseArrays.sparse(jac) + elseif sparse_retrieve_loop == 0 + Jv = jac + else + throw(IS.ConflictingInputsError("negative sparse_retrieve_loop not valid")) + end + Jf(Jv, x0) + mass_matrix = get_mass_matrix(m!.inputs) + return JacobianFunctionWrapper{typeof(Jf), typeof(Jv)}(Jf, Jv, x0, mass_matrix) +end + function get_jacobian( ::Type{T}, inputs::SimulationInputs, diff --git a/src/base/nlsolve_wrapper.jl b/src/base/nlsolve_wrapper.jl index 13e4ec0b3..371e29bcf 100644 --- a/src/base/nlsolve_wrapper.jl +++ b/src/base/nlsolve_wrapper.jl @@ -8,11 +8,25 @@ NLsolveWrapper() = NLsolveWrapper(Vector{Float64}(), false, true) converged(sol::NLsolveWrapper) = sol.converged failed(sol::NLsolveWrapper) = sol.failed -function _get_model_closure(model::SystemModel{MassMatrixModel}, ::Vector{Float64}) +function _get_model_closure( + model::SystemModel{MassMatrixModel, NoDelays}, + ::Vector{Float64}, +) return (residual, x) -> model(residual, x, nothing, 0.0) end -function _get_model_closure(model::SystemModel{ResidualModel}, x0::Vector{Float64}) +function _get_model_closure( + model::SystemModel{MassMatrixModel, HasDelays}, + x0::Vector{Float64}, +) + h(p, t; idxs = nothing) = typeof(idxs) <: Number ? x0[idxs] : x0 + return (residual, x) -> model(residual, x, h, nothing, 0.0) +end + +function _get_model_closure( + model::SystemModel{ResidualModel, NoDelays}, + x0::Vector{Float64}, +) dx0 = zeros(length(x0)) return (residual, x) -> model(residual, dx0, x, nothing, 0.0) end diff --git a/src/base/simulation.jl b/src/base/simulation.jl index f870709df..395bc1e0d 100644 --- a/src/base/simulation.jl +++ b/src/base/simulation.jl @@ -329,7 +329,7 @@ end function _get_diffeq_problem( sim::Simulation, - model::SystemModel{ResidualModel}, + model::SystemModel{ResidualModel, NoDelays}, jacobian::JacobianFunctionWrapper, ) x0 = get_initial_conditions(sim) @@ -354,7 +354,7 @@ end function _get_diffeq_problem( sim::Simulation, - model::SystemModel{MassMatrixModel}, + model::SystemModel{MassMatrixModel, NoDelays}, jacobian::JacobianFunctionWrapper, ) simulation_inputs = get_simulation_inputs(sim) @@ -375,6 +375,39 @@ function _get_diffeq_problem( return end +function get_history_function(simulation_inputs) + x0 = get_initial_conditions(simulation_inputs) + h(p, t; idxs = nothing) = typeof(idxs) <: Number ? x0[idxs] : x0 + return h +end + +function _get_diffeq_problem( + sim::Simulation, + model::SystemModel{MassMatrixModel, HasDelays}, + jacobian::JacobianFunctionWrapper, +) + simulation_inputs = get_simulation_inputs(sim) + h = get_history_function(sim) + sim.problem = SciMLBase.DDEProblem( + SciMLBase.DDEFunction{true}( + model; + mass_matrix = get_mass_matrix(simulation_inputs), + jac = jacobian, #Fails after time of delay if autodiff=true with non-zero delays + jac_prototype = jacobian.Jv, + # Necessary to avoid unnecessary calculations in Rosenbrock methods + #tgrad = (dT, u, h, p, t) -> dT .= false, #Doesn't work with passing tgrad yet + ), + sim.x0_init, + h, + get_tspan(sim), + simulation_inputs; + constant_lags = filter!(x -> x != 0, unique(simulation_inputs.delays)), + ) + sim.status = BUILT + + return +end + function _build!(sim::Simulation{T}; kwargs...) where {T <: SimulationModel} check_kwargs(kwargs, SIMULATION_ACCEPTED_KWARGS, "Simulation") # Branches are a super set of Lines. Passing both kwargs will diff --git a/src/base/simulation_inputs.jl b/src/base/simulation_inputs.jl index 925041dfe..ce03d01af 100644 --- a/src/base/simulation_inputs.jl +++ b/src/base/simulation_inputs.jl @@ -18,6 +18,7 @@ struct SimulationInputs global_vars_update_pointers::Dict{Int, Int} global_state_map::MAPPING_DICT global_inner_var_map::Dict{String, Dict} + delays::Vector function SimulationInputs( sys::PSY.System, @@ -39,6 +40,7 @@ struct SimulationInputs TimerOutputs.@timeit BUILD_TIMER "Wrap Dynamic Injectors" begin wrapped_injectors = _wrap_dynamic_injector_data(sys, lookup, injection_start) + delays = get_system_delays(sys) var_count = wrapped_injectors[end].ix_range[end] end @@ -71,6 +73,11 @@ struct SimulationInputs break end end + + if !isempty(delays) + @info "System has delays. Use the correct solver for delay differential equations." + end + new( wrapped_injectors, wrapped_static_injectors, @@ -91,6 +98,7 @@ struct SimulationInputs global_vars, MAPPING_DICT(), Dict{String, Dict}(), + delays, ) end end @@ -173,6 +181,7 @@ function _wrap_dynamic_injector_data(sys::PSY.System, lookup, injection_start::I @debug "ix_range=$ix_range ode_range=$ode_range inner_vars_range= $inner_vars_range" dynamic_device = PSY.get_dynamic_injector(device) @assert dynamic_device !== nothing + #TODO - add bus_size to the dynamic injector -- allows you to index into the voltages. wrapped_injector[ix] = DynamicWrapper( device, dynamic_device, @@ -191,6 +200,15 @@ function _wrap_dynamic_injector_data(sys::PSY.System, lookup, injection_start::I return wrapped_injector end +function get_system_delays(sys::PSY.System) + delays = [] + for injector in get_injectors_with_dynamics(sys) + device_delays = get_delays(PSY.get_dynamic_injector(injector)) + !isnothing(device_delays) && push!(delays, device_delays) + end + return delays +end + function _wrap_dynamic_branches(sys::PSY.System, lookup::Dict{Int, Int}) branches_start = 2 * get_n_buses(sys) + 1 sys_base_power = PSY.get_base_power(sys) diff --git a/src/base/simulation_model.jl b/src/base/simulation_model.jl index e314947ce..1b6df6bd5 100644 --- a/src/base/simulation_model.jl +++ b/src/base/simulation_model.jl @@ -1,4 +1,9 @@ -abstract type SimulationModel end +abstract type ModelVariations end +abstract type SimulationModel <: ModelVariations end struct MassMatrixModel <: SimulationModel end struct ResidualModel <: SimulationModel end + +abstract type DelayModel <: ModelVariations end +struct HasDelays <: DelayModel end +struct NoDelays <: DelayModel end diff --git a/src/base/system_model.jl b/src/base/system_model.jl index c16ae1a5d..21eb4510c 100644 --- a/src/base/system_model.jl +++ b/src/base/system_model.jl @@ -1,8 +1,11 @@ -struct SystemModel{T <: SimulationModel, C <: Cache} +struct SystemModel{T <: SimulationModel, D <: DelayModel, C <: Cache} inputs::SimulationInputs cache::C end -function SystemModel{T}(inputs, cache::U) where {T <: SimulationModel, U <: Cache} - return SystemModel{T, U}(inputs, cache) +function SystemModel{T, D}( + inputs, + cache::U, +) where {T <: SimulationModel, D <: DelayModel, U <: Cache} + return SystemModel{T, D, U}(inputs, cache) end diff --git a/src/models/device.jl b/src/models/device.jl index df339f843..46b564ce3 100644 --- a/src/models/device.jl +++ b/src/models/device.jl @@ -25,6 +25,7 @@ function device!( global_vars::AbstractArray{T}, inner_vars::AbstractArray{T}, dynamic_device::DynamicWrapper{DynG}, + h, t, ) where {DynG <: PSY.DynamicGenerator, T <: ACCEPTED_REAL_TYPES} if get_connection_status(dynamic_device) < 1.0 @@ -41,13 +42,13 @@ function device!( _update_inner_vars!(device_states, output_ode, sys_ω, inner_vars, dynamic_device) #Obtain ODEs and Mechanical Power for Turbine Governor - mdl_tg_ode!(device_states, output_ode, inner_vars, sys_ω, dynamic_device) + mdl_tg_ode!(device_states, output_ode, inner_vars, sys_ω, dynamic_device, h, t) #Obtain ODEs for PSS - mdl_pss_ode!(device_states, output_ode, inner_vars, sys_ω, dynamic_device) + mdl_pss_ode!(device_states, output_ode, inner_vars, sys_ω, dynamic_device, h, t) #Obtain ODEs for AVR - mdl_avr_ode!(device_states, output_ode, inner_vars, dynamic_device) + mdl_avr_ode!(device_states, output_ode, inner_vars, dynamic_device, h, t) #Obtain ODEs for Machine mdl_machine_ode!( @@ -57,10 +58,12 @@ function device!( current_r, current_i, dynamic_device, + h, + t, ) #Obtain ODEs for PSY.Shaft - mdl_shaft_ode!(device_states, output_ode, inner_vars, sys_ω, dynamic_device) + mdl_shaft_ode!(device_states, output_ode, inner_vars, sys_ω, dynamic_device, h, t) return end @@ -142,6 +145,7 @@ function device!( global_vars::AbstractArray{T}, inner_vars::AbstractArray{T}, dynamic_device::DynamicWrapper{DynI}, + h, t, ) where {DynI <: PSY.DynamicInverter, T <: ACCEPTED_REAL_TYPES} if get_connection_status(dynamic_device) < 1.0 @@ -164,19 +168,27 @@ function device!( _update_inner_vars!(device_states, output_ode, sys_ω, inner_vars, dynamic_device) #Obtain ODES for DC side - mdl_DCside_ode!(device_states, output_ode, sys_ω, inner_vars, dynamic_device) + mdl_DCside_ode!(device_states, output_ode, sys_ω, inner_vars, dynamic_device, h, t) #Obtain ODEs for PLL - mdl_freq_estimator_ode!(device_states, output_ode, inner_vars, sys_ω, dynamic_device) + mdl_freq_estimator_ode!( + device_states, + output_ode, + inner_vars, + sys_ω, + dynamic_device, + h, + t, + ) #Obtain ODEs for OuterLoop - mdl_outer_ode!(device_states, output_ode, inner_vars, sys_ω, dynamic_device) + mdl_outer_ode!(device_states, output_ode, inner_vars, sys_ω, dynamic_device, h, t) #Obtain inner controller ODEs and modulation commands - mdl_inner_ode!(device_states, output_ode, inner_vars, dynamic_device) + mdl_inner_ode!(device_states, output_ode, inner_vars, dynamic_device, h, t) #Obtain converter relations - mdl_converter_ode!(device_states, output_ode, inner_vars, dynamic_device) + mdl_converter_ode!(device_states, output_ode, inner_vars, dynamic_device, h, t) #Obtain ODEs for output filter mdl_filter_ode!( @@ -187,6 +199,8 @@ function device!( inner_vars, sys_ω, dynamic_device, + h, + t, ) return @@ -219,6 +233,7 @@ function device!( ::AbstractArray{T}, ::AbstractArray{T}, dynamic_device::DynamicWrapper{PSY.PeriodicVariableSource}, + h, t, ) where {T <: ACCEPTED_REAL_TYPES} ω_θ = PSY.get_internal_angle_frequencies(get_device(dynamic_device)) @@ -643,6 +658,7 @@ function device!( global_vars::AbstractArray{T}, ::AbstractArray{T}, dynamic_wrapper::DynamicWrapper{PSY.SingleCageInductionMachine}, + h, t, ) where {T <: ACCEPTED_REAL_TYPES} Sbase = get_system_base_power(dynamic_wrapper) @@ -726,6 +742,7 @@ function device!( global_vars::AbstractArray{T}, ::AbstractArray{T}, dynamic_wrapper::DynamicWrapper{PSY.SimplifiedSingleCageInductionMachine}, + h, t, ) where {T <: ACCEPTED_REAL_TYPES} Sbase = get_system_base_power(dynamic_wrapper) @@ -822,6 +839,7 @@ function device!( global_vars::AbstractArray{T}, ::AbstractArray{T}, dynamic_wrapper::DynamicWrapper{PSY.CSVGN1}, + h, t, ) where {T <: ACCEPTED_REAL_TYPES} Sbase = get_system_base_power(dynamic_wrapper) @@ -930,6 +948,7 @@ function device!( global_vars::AbstractArray{T}, ::AbstractArray{T}, dynamic_wrapper::DynamicWrapper{PSY.ActiveConstantPowerLoad}, + h, t, ) where {T <: ACCEPTED_REAL_TYPES} Sbase = get_system_base_power(dynamic_wrapper) @@ -1076,6 +1095,7 @@ function device!( global_vars::AbstractArray{T}, inner_vars::AbstractArray{T}, dynamic_device::DynamicWrapper{PSY.AggregateDistributedGenerationA}, + h, t, ) where {T <: ACCEPTED_REAL_TYPES} Freq_Flag = PSY.get_Freq_Flag(get_device(dynamic_device)) diff --git a/src/models/generator_models/avr_models.jl b/src/models/generator_models/avr_models.jl index 78492ac34..220fc2e4a 100644 --- a/src/models/generator_models/avr_models.jl +++ b/src/models/generator_models/avr_models.jl @@ -66,6 +66,8 @@ function mdl_avr_ode!( ::AbstractArray{<:ACCEPTED_REAL_TYPES}, inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, PSY.AVRFixed, TG, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, TG <: PSY.TurbineGov, P <: PSY.PSS} #Update Vf voltage on inner vars. In AVRFixed, Vf = V_ref @@ -79,6 +81,8 @@ function mdl_avr_ode!( output_ode::AbstractArray{<:ACCEPTED_REAL_TYPES}, inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, PSY.AVRSimple, TG, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, TG <: PSY.TurbineGov, P <: PSY.PSS} #Obtain references @@ -111,6 +115,8 @@ function mdl_avr_ode!( output_ode::AbstractArray{<:ACCEPTED_REAL_TYPES}, inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, PSY.AVRTypeI, TG, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, TG <: PSY.TurbineGov, P <: PSY.PSS} #Obtain references @@ -169,6 +175,8 @@ function mdl_avr_ode!( output_ode::AbstractArray{<:ACCEPTED_REAL_TYPES}, inner_vars, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, PSY.AVRTypeII, TG, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, TG <: PSY.TurbineGov, P <: PSY.PSS} #Obtain references @@ -229,6 +237,8 @@ function mdl_avr_ode!( output_ode::AbstractArray{<:ACCEPTED_REAL_TYPES}, inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, PSY.ESAC1A, TG, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, TG <: PSY.TurbineGov, P <: PSY.PSS} #Obtain references @@ -304,8 +314,9 @@ function mdl_avr_ode!( output_ode::AbstractArray{<:ACCEPTED_REAL_TYPES}, inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, PSY.SEXS, TG, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, TG <: PSY.TurbineGov, P <: PSY.PSS} - #Obtain references V0_ref = get_V_ref(dynamic_device) @@ -349,7 +360,9 @@ function mdl_avr_ode!( device_states::AbstractArray{<:ACCEPTED_REAL_TYPES}, output_ode::AbstractArray{<:ACCEPTED_REAL_TYPES}, inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, - dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, PSY.SCRX, TG, P}}, # + dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, PSY.SCRX, TG, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, TG <: PSY.TurbineGov, P <: PSY.PSS} #Obtain references @@ -410,6 +423,8 @@ function mdl_avr_ode!( output_ode::AbstractArray, inner_vars::AbstractArray, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, PSY.EXST1, TG, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, TG <: PSY.TurbineGov, P <: PSY.PSS} #Obtain references @@ -470,6 +485,8 @@ function mdl_avr_ode!( output_ode::AbstractArray, inner_vars::AbstractArray, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, PSY.EXAC1, TG, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, TG <: PSY.TurbineGov, P <: PSY.PSS} #Obtain references @@ -541,6 +558,8 @@ function mdl_avr_ode!( output_ode::AbstractArray, inner_vars::AbstractArray, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, PSY.ESST1A, TG, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, TG <: PSY.TurbineGov, P <: PSY.PSS} #Obtain references diff --git a/src/models/generator_models/machine_models.jl b/src/models/generator_models/machine_models.jl index c8cac83e3..a21e74e4d 100644 --- a/src/models/generator_models/machine_models.jl +++ b/src/models/generator_models/machine_models.jl @@ -17,6 +17,8 @@ function mdl_machine_ode!( current_r::AbstractArray{<:ACCEPTED_REAL_TYPES}, current_i::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{PSY.BaseMachine, S, A, TG, P}}, + h, + t, ) where {S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov, P <: PSY.PSS} Sbase = get_system_base_power(dynamic_device) #Obtain external states inputs for component @@ -66,6 +68,8 @@ function mdl_machine_ode!( current_r::AbstractArray{<:ACCEPTED_REAL_TYPES}, current_i::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{PSY.OneDOneQMachine, S, A, TG, P}}, + h, + t, ) where {S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov, P <: PSY.PSS} Sbase = get_system_base_power(dynamic_device) @@ -133,6 +137,8 @@ function mdl_machine_ode!( current_r::AbstractArray{<:ACCEPTED_REAL_TYPES}, current_i::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{PSY.SauerPaiMachine, S, A, TG, P}}, + h, + t, ) where {S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov, P <: PSY.PSS} Sbase = get_system_base_power(dynamic_device) f0 = get_system_base_frequency(dynamic_device) @@ -223,6 +229,8 @@ function mdl_machine_ode!( current_r::AbstractArray{<:ACCEPTED_REAL_TYPES}, current_i::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{PSY.MarconatoMachine, S, A, TG, P}}, + h, + t, ) where {S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov, P <: PSY.PSS} Sbase = get_system_base_power(dynamic_device) f0 = get_system_base_frequency(dynamic_device) @@ -311,6 +319,8 @@ function mdl_machine_ode!( dynamic_device::DynamicWrapper{ PSY.DynamicGenerator{PSY.SimpleMarconatoMachine, S, A, TG, P}, }, + h, + t, ) where {S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov, P <: PSY.PSS} Sbase = get_system_base_power(dynamic_device) f0 = get_system_base_frequency(dynamic_device) @@ -396,6 +406,8 @@ function mdl_machine_ode!( dynamic_device::DynamicWrapper{ PSY.DynamicGenerator{PSY.AndersonFouadMachine, S, A, TG, P}, }, + h, + t, ) where {S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov, P <: PSY.PSS} Sbase = get_system_base_power(dynamic_device) f0 = get_system_base_frequency(dynamic_device) @@ -477,6 +489,8 @@ function mdl_machine_ode!( current_r::AbstractArray{<:ACCEPTED_REAL_TYPES}, current_i::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{PSY.SimpleAFMachine, S, A, TG, P}}, + h, + t, ) where {S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov, P <: PSY.PSS} Sbase = get_system_base_power(dynamic_device) f0 = get_system_base_frequency(dynamic_device) @@ -552,6 +566,8 @@ function mdl_machine_ode!( current_r::AbstractArray{<:ACCEPTED_REAL_TYPES}, current_i::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, TG, P}}, + h, + t, ) where { M <: Union{PSY.RoundRotorQuadratic, PSY.RoundRotorExponential}, S <: PSY.Shaft, @@ -650,6 +666,8 @@ function mdl_machine_ode!( dynamic_device::DynamicWrapper{ PSY.DynamicGenerator{PSY.SalientPoleQuadratic, S, A, TG, P}, }, + h, + t, ) where {S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov, P <: PSY.PSS} Sbase = get_system_base_power(dynamic_device) f0 = get_system_base_frequency(dynamic_device) @@ -731,6 +749,8 @@ function mdl_machine_ode!( dynamic_device::DynamicWrapper{ PSY.DynamicGenerator{PSY.SalientPoleExponential, S, A, TG, P}, }, + h, + t, ) where {S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov, P <: PSY.PSS} Sbase = get_system_base_power(dynamic_device) f0 = get_system_base_frequency(dynamic_device) @@ -821,6 +841,8 @@ inner_vars, current_r::AbstractArray{<:ACCEPTED_REAL_TYPES}, current_i::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{PSY.FullMachine, S, A, TG, P}}, + h, + t, ) where {S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov, P <: PSY.PSS} #Obtain indices for component w/r to device @@ -903,6 +925,8 @@ inner_vars, current_r::AbstractArray{<:ACCEPTED_REAL_TYPES}, current_i::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{PSY.SimpleFullMachine, S, A, TG, P}}, + h, + t, ) where {S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov, P <: PSY.PSS} #Obtain indices for component w/r to device diff --git a/src/models/generator_models/pss_models.jl b/src/models/generator_models/pss_models.jl index b83c965c6..aa7ba9867 100644 --- a/src/models/generator_models/pss_models.jl +++ b/src/models/generator_models/pss_models.jl @@ -118,6 +118,8 @@ function mdl_pss_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, TG, PSY.PSSFixed}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov} #Update V_pss on inner vars @@ -132,6 +134,8 @@ function mdl_pss_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, TG, PSY.IEEEST}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov} #Get Signal Input Integer @@ -229,6 +233,8 @@ function mdl_pss_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, TG, PSY.STAB1}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov} #Get Signal Input Integer @@ -284,6 +290,8 @@ function mdl_pss_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, TG, PSY.PSS2A}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov} #Get Signal Input Integer @@ -452,6 +460,8 @@ function mdl_pss_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, TG, PSY.PSS2B}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov} #Get Signal Input Integer @@ -631,6 +641,8 @@ function mdl_pss_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, TG, PSY.PSS2C}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov} #Get Signal Input Integer @@ -845,6 +857,8 @@ function mdl_pss_ode!( inner_vars, ω_sys, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, TG, PSY.PSSSimple}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, TG <: PSY.TurbineGov} #Get references diff --git a/src/models/generator_models/shaft_models.jl b/src/models/generator_models/shaft_models.jl index 3de6ecc21..1894c692a 100644 --- a/src/models/generator_models/shaft_models.jl +++ b/src/models/generator_models/shaft_models.jl @@ -12,6 +12,8 @@ function mdl_shaft_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, PSY.SingleMass, A, TG, P}}, + h, + t, ) where {M <: PSY.Machine, A <: PSY.AVR, TG <: PSY.TurbineGov, P <: PSY.PSS} f0 = get_system_base_frequency(dynamic_device) #Obtain indices for component w/r to device @@ -43,6 +45,8 @@ function mdl_shaft_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, PSY.FiveMassShaft, A, TG, P}}, + h, + t, ) where {M <: PSY.Machine, A <: PSY.AVR, TG <: PSY.TurbineGov, P <: PSY.PSS} f0 = get_system_base_frequency(dynamic_device) diff --git a/src/models/generator_models/tg_models.jl b/src/models/generator_models/tg_models.jl index f2ca9e1b7..67755c0f6 100644 --- a/src/models/generator_models/tg_models.jl +++ b/src/models/generator_models/tg_models.jl @@ -33,6 +33,8 @@ function mdl_tg_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, PSY.TGFixed, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS} #Update inner vars @@ -48,6 +50,8 @@ function mdl_tg_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, PSY.TGTypeI, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS} #Obtain references @@ -102,6 +106,8 @@ function mdl_tg_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, PSY.TGTypeII, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS} #Obtain references @@ -144,6 +150,8 @@ function mdl_tg_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, PSY.SteamTurbineGov1, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS} #Obtain TG @@ -196,6 +204,8 @@ function mdl_tg_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, PSY.GasTG, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS} #Obtain references @@ -253,6 +263,8 @@ function mdl_tg_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, PSY.HydroTurbineGov, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS} #Obtain references @@ -307,12 +319,22 @@ function mdl_tg_ode!( return end +#Wrapper around h to handle delays of zero +function get_delayed_value(h, t, delay, state, index) + if delay == 0 + return state + else + return h(nothing, t - delay; idxs = index) + end +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.DEGOV, P}}, + h, + t, ) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS} #Obtain references @@ -351,6 +373,8 @@ function mdl_tg_ode!( y2, dx_a1, dx_a2 = lead_lag_2nd_mass_matrix(y1, x_a1, x_a2, T5 + T6, T5 * T6, T4, 0.0) y3, dx_a3 = integrator_windup(y2, x_a3, K, 1.0, -Inf, Inf) P_m = y3 * (ω[1]) + delayed_x_a3 = get_delayed_value(h, t, Td, x_a3, get_global_index(device)[:x_a3]) + P_m = delayed_x_a3 * (ω[1]) #Compute 1 State TG ODE: output_ode[local_ix[1]] = dx_ecb1 @@ -360,7 +384,7 @@ function mdl_tg_ode!( output_ode[local_ix[5]] = dx_a3 #Update mechanical torque - inner_vars[τm_var] = P_m / ω[1] + inner_vars[τm_var] = P_m / ω[1] #Fails when trying to assign a Dual to a cache of type Float? return end diff --git a/src/models/inverter_models/DCside_models.jl b/src/models/inverter_models/DCside_models.jl index 5f586b162..425e18e34 100644 --- a/src/models/inverter_models/DCside_models.jl +++ b/src/models/inverter_models/DCside_models.jl @@ -12,6 +12,8 @@ function mdl_DCside_ode!( ω_sys::ACCEPTED_REAL_TYPES, inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, dynamic_device::DynamicWrapper{PSY.DynamicInverter{C, O, IC, PSY.FixedDCSource, P, F}}, + h, + t, ) where { C <: PSY.Converter, O <: PSY.OuterControl, diff --git a/src/models/inverter_models/converter_models.jl b/src/models/inverter_models/converter_models.jl index 55bec94ea..55c324dec 100644 --- a/src/models/inverter_models/converter_models.jl +++ b/src/models/inverter_models/converter_models.jl @@ -13,6 +13,8 @@ function mdl_converter_ode!( dynamic_device::DynamicWrapper{ PSY.DynamicInverter{PSY.AverageConverter, O, IC, DC, P, F}, }, + h, + t, ) where { O <: PSY.OuterControl, IC <: PSY.InnerControl, @@ -43,6 +45,8 @@ function mdl_converter_ode!( dynamic_device::DynamicWrapper{ PSY.DynamicInverter{PSY.RenewableEnergyConverterTypeA, O, IC, DC, P, PSY.RLFilter}, }, + h, + t, ) where { O <: PSY.OuterControl, IC <: PSY.InnerControl, @@ -174,6 +178,8 @@ function mdl_converter_ode!( PSY.LCLFilter, }, }, + h, + t, ) where { O <: PSY.OuterControl, IC <: PSY.InnerControl, diff --git a/src/models/inverter_models/filter_models.jl b/src/models/inverter_models/filter_models.jl index a738c6bc0..4523c94a2 100644 --- a/src/models/inverter_models/filter_models.jl +++ b/src/models/inverter_models/filter_models.jl @@ -40,6 +40,8 @@ function mdl_filter_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, dynamic_device::DynamicWrapper{PSY.DynamicInverter{C, O, IC, DC, P, PSY.LCLFilter}}, + h, + t, ) where { C <: PSY.Converter, O <: PSY.OuterControl, @@ -121,6 +123,8 @@ function mdl_filter_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, dynamic_device::DynamicWrapper{PSY.DynamicInverter{C, O, IC, DC, P, PSY.RLFilter}}, + h, + t, ) where { C <: PSY.Converter, O <: PSY.OuterControl, diff --git a/src/models/inverter_models/frequency_estimator_models.jl b/src/models/inverter_models/frequency_estimator_models.jl index a34751fd1..04cdb73c3 100644 --- a/src/models/inverter_models/frequency_estimator_models.jl +++ b/src/models/inverter_models/frequency_estimator_models.jl @@ -12,6 +12,8 @@ function mdl_freq_estimator_ode!( inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES}, ω_sys::ACCEPTED_REAL_TYPES, dynamic_device::DynamicWrapper{PSY.DynamicInverter{C, O, IC, DC, PSY.KauraPLL, F}}, + h, + t, ) where { C <: PSY.Converter, O <: PSY.OuterControl, @@ -77,6 +79,8 @@ function mdl_freq_estimator_ode!( dynamic_device::DynamicWrapper{ PSY.DynamicInverter{C, O, IC, DC, PSY.ReducedOrderPLL, F}, }, + h, + t, ) where { C <: PSY.Converter, O <: PSY.OuterControl, @@ -137,6 +141,8 @@ function mdl_freq_estimator_ode!( dynamic_device::DynamicWrapper{ PSY.DynamicInverter{C, O, IC, DC, PSY.FixedFrequency, F}, }, + h, + t, ) where { C <: PSY.Converter, O <: PSY.OuterControl, diff --git a/src/models/inverter_models/inner_control_models.jl b/src/models/inverter_models/inner_control_models.jl index f5a78cc48..7ce2da942 100644 --- a/src/models/inverter_models/inner_control_models.jl +++ b/src/models/inverter_models/inner_control_models.jl @@ -37,6 +37,8 @@ function _mdl_ode_RE_inner_controller_B!( PSY.DynamicInverter{C, O, PSY.RECurrentControlB, DC, P, F}, }, inner_vars::AbstractVector, + h, + t, ) where { C <: PSY.Converter, O <: PSY.OuterControl, @@ -91,6 +93,8 @@ function _mdl_ode_RE_inner_controller_B!( PSY.DynamicInverter{C, O, PSY.RECurrentControlB, DC, P, F}, }, inner_vars::AbstractVector, + h, + t, ) where { C <: PSY.Converter, O <: PSY.OuterControl, @@ -151,6 +155,8 @@ function mdl_inner_ode!( dynamic_device::DynamicWrapper{ PSY.DynamicInverter{C, O, PSY.VoltageModeControl, DC, P, F}, }, + h, + t, ) where { C <: PSY.Converter, O <: PSY.OuterControl, @@ -260,6 +266,8 @@ function mdl_inner_ode!( dynamic_device::DynamicWrapper{ PSY.DynamicInverter{C, O, PSY.CurrentModeControl, DC, P, F}, }, + h, + t, ) where { C <: PSY.Converter, O <: PSY.OuterControl, @@ -331,6 +339,8 @@ function mdl_inner_ode!( dynamic_device::DynamicWrapper{ PSY.DynamicInverter{C, O, PSY.RECurrentControlB, DC, P, F}, }, + h, + t, ) where { C <: PSY.Converter, O <: PSY.OuterControl, @@ -358,6 +368,8 @@ function mdl_inner_ode!( inner_control, dynamic_device, inner_vars, + h, + t, ) return end diff --git a/src/models/inverter_models/outer_control_models.jl b/src/models/inverter_models/outer_control_models.jl index 55a54ea22..0fedc9d72 100644 --- a/src/models/inverter_models/outer_control_models.jl +++ b/src/models/inverter_models/outer_control_models.jl @@ -535,6 +535,8 @@ function mdl_outer_ode!( F, }, }, + h, + t, ) where { C <: PSY.Converter, IC <: PSY.InnerControl, @@ -623,6 +625,8 @@ function mdl_outer_ode!( F, }, }, + h, + t, ) where { C <: PSY.Converter, IC <: PSY.InnerControl, @@ -713,6 +717,8 @@ function mdl_outer_ode!( F, }, }, + h, + t, ) where { C <: PSY.Converter, IC <: PSY.InnerControl, @@ -805,6 +811,8 @@ function mdl_outer_ode!( F, }, }, + h, + t, ) where { C <: PSY.Converter, IC <: PSY.InnerControl, @@ -899,6 +907,8 @@ function mdl_outer_ode!( F, }, }, + h, + t, ) where { C <: PSY.Converter, IC <: PSY.InnerControl, diff --git a/src/models/system.jl b/src/models/system.jl index 116244cda..b8d559978 100644 --- a/src/models/system.jl +++ b/src/models/system.jl @@ -11,17 +11,17 @@ function ResidualModel( T, ForwardDiff.pickchunksize(length(x0_init)), } - return SystemModel{ResidualModel}(inputs, Ctype{U}(system_residual!, inputs)) + return SystemModel{ResidualModel, NoDelays}(inputs, Ctype{U}(system_residual!, inputs)) end """ Instantiate an ResidualModel for ODE inputs. """ function ResidualModel(inputs, ::Vector{Float64}, ::Type{Ctype}) where {Ctype <: SimCache} - return SystemModel{ResidualModel}(inputs, Ctype(system_residual!, inputs)) + return SystemModel{ResidualModel, NoDelays}(inputs, Ctype(system_residual!, inputs)) end -function (m::SystemModel{ResidualModel, C})( +function (m::SystemModel{ResidualModel, NoDelays, C})( out::AbstractArray{T}, du::AbstractArray{U}, u::AbstractArray{V}, @@ -78,6 +78,7 @@ function system_residual!( global_vars, device_inner_vars, dynamic_device, + nothing, t, ) M_ = @view M[ix_range, ix_range] @@ -152,9 +153,22 @@ end Instantiate a MassMatrixModel for ODE inputs. """ function MassMatrixModel(inputs, ::Vector{Float64}, ::Type{Ctype}) where {Ctype <: SimCache} - return SystemModel{MassMatrixModel}(inputs, Ctype(system_mass_matrix!, inputs)) + if isempty(inputs.delays) + return SystemModel{MassMatrixModel, NoDelays}( + inputs, + Ctype(system_mass_matrix!, inputs), + ) + else + return SystemModel{MassMatrixModel, HasDelays}( + inputs, + Ctype(system_mass_matrix!, inputs), + ) + end end +""" +Instantiate a MassMatrixModel for ForwardDiff calculations +""" function MassMatrixModel( inputs::SimulationInputs, x0_init::Vector{T}, @@ -165,21 +179,42 @@ function MassMatrixModel( T, ForwardDiff.pickchunksize(length(x0_init)), } - return SystemModel{MassMatrixModel}(inputs, Ctype{U}(system_mass_matrix!, inputs)) + if isempty(inputs.delays) + return SystemModel{MassMatrixModel, NoDelays}( + inputs, + Ctype{U}(system_mass_matrix!, inputs), + ) + else + return SystemModel{MassMatrixModel, HasDelays}( + inputs, + Ctype{U}(system_mass_matrix!, inputs), + ) + end +end + +function (m::SystemModel{MassMatrixModel, NoDelays, C})( + du::AbstractArray{T}, + u::AbstractArray{U}, + p, + t, +) where {C <: Cache, U <: ACCEPTED_REAL_TYPES, T <: ACCEPTED_REAL_TYPES} + system_mass_matrix!(du, u, nothing, m.inputs, m.cache, t) end -function (m::SystemModel{MassMatrixModel, C})( +function (m::SystemModel{MassMatrixModel, HasDelays, C})( du::AbstractArray{T}, u::AbstractArray{U}, + h, p, t, ) where {C <: Cache, U <: ACCEPTED_REAL_TYPES, T <: ACCEPTED_REAL_TYPES} - system_mass_matrix!(du, u, m.inputs, m.cache, t) + system_mass_matrix!(du, u, h, m.inputs, m.cache, t) end function system_mass_matrix!( dx::Vector{T}, x::Vector{V}, + h, inputs::SimulationInputs, cache::Cache, t, @@ -216,6 +251,7 @@ function system_mass_matrix!( global_vars, device_inner_vars, dynamic_device, + h, t, ) dx[ix_range] .= device_ode_output diff --git a/test/Project.toml b/test/Project.toml index 337b4a91e..fb580ea2e 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,6 +1,7 @@ [deps] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +DelayDiffEq = "bcd4f6db-9728-5f36-b5f7-82caef46ccdb" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" @@ -9,11 +10,13 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" +PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a" PowerFlows = "94fada2c-fd9a-4e89-8d82-81405f5cb4f6" PowerNetworkMatrices = "bed98974-b02a-5e2f-9fe0-a103f5c450dd" PowerSimulationsDynamics = "398b2ede-47ed-4edc-b52e-69e4a48b4336" PowerSystemCaseBuilder = "f00506e0-b84f-492a-93c2-c0a9afc4364e" PowerSystems = "bcd98974-b02a-5e2f-9ee0-a103f5c450dd" +Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4" diff --git a/test/runtests.jl b/test/runtests.jl index 1da57144f..b91f4211b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,3 +1,5 @@ +using Revise +using PlotlyJS using PowerSimulationsDynamics using PowerSystems using Test @@ -5,6 +7,7 @@ using NLsolve using SciMLBase using Sundials using OrdinaryDiffEq +using DelayDiffEq using DelimitedFiles using DataFrames using InfrastructureSystems diff --git a/test/test_case57_degov.jl b/test/test_case57_degov.jl index 0567f6401..2574da875 100644 --- a/test/test_case57_degov.jl +++ b/test/test_case57_degov.jl @@ -15,7 +15,7 @@ csv_file_degov_nodelay_speed = csv_file_degov_delay_speed = joinpath(TEST_FILES_DIR, "benchmarks/psse/DEGOV/degov_delay_speed_final.csv") -@testset "Test 57 DEGOV ResidualModel" begin +#= @testset "Test 57 DEGOV ResidualModel" begin path = mktempdir() try sys = System(raw_file, dyr_file) @@ -113,7 +113,7 @@ csv_file_degov_delay_speed = @info("removing test files") rm(path; force = true, recursive = true) end -end +end =# @testset "Test 57 DEGOV MassMatrixModel" begin path = mktempdir() @@ -176,10 +176,19 @@ end @test LinearAlgebra.norm(eigs - test_57_eigvals) < 1e-10 # Solve problem - @test execute!(sim, Rodas4(); dtmax = (1 / 240), saveat = (1 / 240)) == + @test execute!( + sim, + MethodOfSteps(Rodas4(; autodiff = true)); + dtmax = (1 / 240), + saveat = (1 / 240), + ) == PSID.SIMULATION_FINALIZED results_nodelay = read_results(sim) + t_psid, ω_psid_nodelay = get_frequency_series(results_nodelay, "generator-102-1") + t_pw, ω_pw_nodelay = get_csv_delta(csv_file_degov_nodelay_speed) + @test LinearAlgebra.norm(ω_pw_nodelay - ω_psid_nodelay, Inf) <= 4.7e-5 + # Add delay set_Td!(get_prime_mover(dyn_gen_new), 1.0) sim = Simulation!( @@ -190,24 +199,34 @@ end BranchTrip(1.0, Line, "BUS 1-BUS 2-i_1"); frequency_reference = ReferenceBus(), ) - @test execute!(sim, Rodas4(); dtmax = (1 / 240), saveat = (1 / 240)) == + + @test execute!( + sim, + MethodOfSteps(Rodas4(; autodiff = false)); #Fails for autodiff=true + dtmax = (1 / 240), + saveat = (1 / 240), + ) == PSID.SIMULATION_FINALIZED results_delay = read_results(sim) - t_psid, ω_psid_nodelay = get_frequency_series(results_nodelay, "generator-102-1") t_psid, ω_psid_delay = get_frequency_series(results_delay, "generator-102-1") - t_pw, ω_pw_nodelay = get_csv_delta(csv_file_degov_nodelay_speed) t_pw, ω_pw_delay = get_csv_delta(csv_file_degov_delay_speed) - - @test LinearAlgebra.norm(ω_pw_nodelay - ω_psid_nodelay, Inf) <= 4.7e-5 - #@test LinearAlgebra.norm(ω_pw_delay - ω_psid_delay, Inf) <= 4.7e-5 #THIS SHOULD PASS ONCE DELAYS ARE INCLUDED IN PSID + @test LinearAlgebra.norm(ω_pw_delay - ω_psid_delay, Inf) <= 3.1e-5 #Plotting for debug (add PlotlyJS): - #t1 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_nodelay, name = "speed-pw -- no delay") - #t2 = PlotlyJS.scatter(; x = t_psid, y = ω_psid_nodelay, name = "speed-psid -- no delay") - #t3 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_delay, name = "speed-pw -- 1s delay") - #t4 = PlotlyJS.scatter(; x = t_pw, y = ω_psid_delay, name = "speed-psid -- 1s delay") - #display(PlotlyJS.plot([t1, t2, t3, t4])) + t1 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_nodelay, name = "speed-pw -- no delay") + t2 = PlotlyJS.scatter(; + x = t_psid, + y = ω_psid_nodelay, + name = "speed-psid -- no delay", + ) + t3 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_delay, name = "speed-pw -- 1s delay") + t4 = PlotlyJS.scatter(; + x = t_psid, + y = ω_psid_delay, + name = "speed-psid -- 1s delay", + ) + display(PlotlyJS.plot([t1, t2, t3, t4])) finally @info("removing test files") From b51c6c2f873feae586dad1eb6fbde55232f79525 Mon Sep 17 00:00:00 2001 From: Matt Bossart Date: Thu, 14 Dec 2023 18:04:30 -0500 Subject: [PATCH 3/7] add docstring for small_signal_analysis --- src/base/small_signal.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/base/small_signal.jl b/src/base/small_signal.jl index 545af4b43..01313da91 100644 --- a/src/base/small_signal.jl +++ b/src/base/small_signal.jl @@ -191,6 +191,16 @@ function _small_signal_analysis( return _small_signal_analysis(jacwrapper.Jv, jacwrapper.x, inputs, multimachine) end +""" + small_signal_analysis( + sim::Simulation, + ) + +Returns the Small Signal Output object that contains the eigenvalues and participation factors. + +# Arguments +- `sim::Simulation` : Small Signal Output object that contains the eigenvalues and participation factors +""" function small_signal_analysis(sim::Simulation{T}; kwargs...) where {T <: SimulationModel} inputs = get_simulation_inputs(sim) x_eval = get(kwargs, :operating_point, get_initial_conditions(sim)) From daa2291c95b88b0b5c81e88ff3dd5ddf16b0c8f7 Mon Sep 17 00:00:00 2001 From: Matt Bossart Date: Thu, 14 Dec 2023 18:10:11 -0500 Subject: [PATCH 4/7] add simple docs page --- docs/make.jl | 1 + docs/src/delays.md | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 docs/src/delays.md diff --git a/docs/make.jl b/docs/make.jl index 78824ffa4..f2f8c857c 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -22,6 +22,7 @@ makedocs(; "Small Signal" => "small.md", "Reference Frames" => "reference_frames.md", "Perturbations" => "perturbations.md", + "Delays" => "delays.md", "Industrial Renewable Models" => "generic.md", "Generator Component Library" => Any[ "Machine" => "component_models/machines.md", diff --git a/docs/src/delays.md b/docs/src/delays.md new file mode 100644 index 000000000..e3d5a2d3d --- /dev/null +++ b/docs/src/delays.md @@ -0,0 +1,6 @@ +# Delays + +There is currently limited support for including models with time delays. The following limitations apply: + +* Only `MassMatrixModel` formulation is compatible with including delays. +* Small signal analysis is not available for systems with delays. From 695b14616c03014407b794c7638fefdeb23bd83e Mon Sep 17 00:00:00 2001 From: Matt Bossart Date: Fri, 15 Dec 2023 10:20:04 -0500 Subject: [PATCH 5/7] add more docs --- docs/make.jl | 2 +- docs/src/delays.md | 6 ------ docs/src/time_delays.md | 22 ++++++++++++++++++++++ 3 files changed, 23 insertions(+), 7 deletions(-) delete mode 100644 docs/src/delays.md create mode 100644 docs/src/time_delays.md diff --git a/docs/make.jl b/docs/make.jl index f2f8c857c..733595e8b 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -22,7 +22,7 @@ makedocs(; "Small Signal" => "small.md", "Reference Frames" => "reference_frames.md", "Perturbations" => "perturbations.md", - "Delays" => "delays.md", + "Time Delays" => "time_delays.md", "Industrial Renewable Models" => "generic.md", "Generator Component Library" => Any[ "Machine" => "component_models/machines.md", diff --git a/docs/src/delays.md b/docs/src/delays.md deleted file mode 100644 index e3d5a2d3d..000000000 --- a/docs/src/delays.md +++ /dev/null @@ -1,6 +0,0 @@ -# Delays - -There is currently limited support for including models with time delays. The following limitations apply: - -* Only `MassMatrixModel` formulation is compatible with including delays. -* Small signal analysis is not available for systems with delays. diff --git a/docs/src/time_delays.md b/docs/src/time_delays.md new file mode 100644 index 000000000..799af868c --- /dev/null +++ b/docs/src/time_delays.md @@ -0,0 +1,22 @@ +# Delays + +PowerSimulationsDynamics supports models with constant delays in a mass matrix formulation: + +```math +\begin{align} +M\frac{dx(t)}{dt} = f(x(t), x(t-\tau_1), ... , x(t-\tau_N)) +\end{align} +``` + +For more information on solving such models, refer to the documentation for [DelayDiffEq.jl](https://github.com/SciML/DelayDiffEq.jl) package. + +The following models include time delays: + +* `DEGOV` + +There is currently limited support for including models with time delays. The following limitations apply: + +* Only constant delays are supported (state dependent delays are not). +* System models with delays must use `MassMatrixModel` formulation (`ResidualModel` is not currently compatible). +* System models with delays are not compatible with small signal analysis tools. +* The system formulation with delays is not compatible with automatic differentiation for calculating the gradient with respect to time. The setting `autodiff=false` should be set when passing the solver (e.g. `MethodofSteps(Rodas5(autodiff=false))`). From faf0f99dc70db66ed04ebb149374001ecbb2e022 Mon Sep 17 00:00:00 2001 From: Matt Bossart Date: Fri, 15 Dec 2023 10:21:58 -0500 Subject: [PATCH 6/7] more changes --- src/base/jacobian.jl | 63 ++++++++++++------ src/base/simulation.jl | 11 ++-- src/base/small_signal.jl | 3 + src/models/system.jl | 19 +++++- test/Project.toml | 2 - test/test_case57_degov.jl | 133 +++++++++++--------------------------- 6 files changed, 109 insertions(+), 122 deletions(-) diff --git a/src/base/jacobian.jl b/src/base/jacobian.jl index 53c7c4408..a5beb2fa0 100644 --- a/src/base/jacobian.jl +++ b/src/base/jacobian.jl @@ -3,6 +3,7 @@ # in SparseDiffTools struct JacobianFunctionWrapper{ + D <: DelayModel, F, T <: Union{Matrix{Float64}, SparseArrays.SparseMatrixCSC{Float64, Int64}}, } <: Function @@ -13,12 +14,12 @@ struct JacobianFunctionWrapper{ end # This version of the function is type unstable should only be used for non-critial ops -function (J::JacobianFunctionWrapper)(x::AbstractVector{Float64}) +function (J::JacobianFunctionWrapper{NoDelays})(x::AbstractVector{Float64}) J.x .= x return J.Jf(J.Jv, x) end -function (J::JacobianFunctionWrapper)( +function (J::JacobianFunctionWrapper{NoDelays})( JM::U, x::AbstractVector{Float64}, ) where {U <: Union{Matrix{Float64}, SparseArrays.SparseMatrixCSC{Float64, Int64}}} @@ -27,7 +28,17 @@ function (J::JacobianFunctionWrapper)( return end -function (J::JacobianFunctionWrapper)( +function (J::JacobianFunctionWrapper{HasDelays})( + JM::U, + x::AbstractVector{Float64}, +) where {U <: Union{Matrix{Float64}, SparseArrays.SparseMatrixCSC{Float64, Int64}}} + h(p, t; idxs = nothing) = typeof(idxs) <: Number ? x[idxs] : x + J.x .= x + J.Jf(JM, x, h, 0.0) + return +end + +function (J::JacobianFunctionWrapper{NoDelays})( JM::U, x::AbstractVector{Float64}, p, @@ -37,18 +48,18 @@ function (J::JacobianFunctionWrapper)( return end -function (J::JacobianFunctionWrapper)( +function (J::JacobianFunctionWrapper{HasDelays})( JM::U, x::AbstractVector{Float64}, h, p, t, ) where {U <: Union{Matrix{Float64}, SparseArrays.SparseMatrixCSC{Float64, Int64}}} - J(JM, x) + J.Jf(JM, x, h, t) return end -function (J::JacobianFunctionWrapper)( +function (J::JacobianFunctionWrapper{NoDelays})( JM::U, dx::AbstractVector{Float64}, x::AbstractVector{Float64}, @@ -95,7 +106,12 @@ function JacobianFunctionWrapper( end Jf(Jv, x0) mass_matrix = get_mass_matrix(m!.inputs) - return JacobianFunctionWrapper{typeof(Jf), typeof(Jv)}(Jf, Jv, x0, mass_matrix) + return JacobianFunctionWrapper{NoDelays, typeof(Jf), typeof(Jv)}( + Jf, + Jv, + x0, + mass_matrix, + ) end function JacobianFunctionWrapper( @@ -130,7 +146,12 @@ function JacobianFunctionWrapper( end Jf(Jv, x0) mass_matrix = get_mass_matrix(m!.inputs) - return JacobianFunctionWrapper{typeof(Jf), typeof(Jv)}(Jf, Jv, x0, mass_matrix) + return JacobianFunctionWrapper{NoDelays, typeof(Jf), typeof(Jv)}( + Jf, + Jv, + x0, + mass_matrix, + ) end function JacobianFunctionWrapper( @@ -141,15 +162,15 @@ function JacobianFunctionWrapper( ) x0 = deepcopy(x0_guess) n = length(x0) - - h(p, t; idxs = nothing) = typeof(idxs) <: Number ? x0[idxs] : x0 #Possilby the problem? Should pass the h that is stored in the problem instead of redefining? - m_ = (residual, x) -> m!(residual, x, h, nothing, 0.0) - jconfig = ForwardDiff.JacobianConfig(m_, similar(x0), x0, ForwardDiff.Chunk(x0)) - Jf = (Jv, x) -> begin - @debug "Evaluating Jacobian Function" - ForwardDiff.jacobian!(Jv, m_, zeros(n), x, jconfig) - return - end + Jf = + (Jv, x, h, t) -> begin + @debug "Evaluating Jacobian Function" + m_ = (residual, x) -> m!(residual, x, h, nothing, t) + jconfig = + ForwardDiff.JacobianConfig(m_, similar(x0), x0, ForwardDiff.Chunk(x0)) + ForwardDiff.jacobian!(Jv, m_, zeros(n), x, jconfig) + return + end jac = zeros(n, n) if sparse_retrieve_loop > 0 for _ in 1:sparse_retrieve_loop @@ -165,9 +186,13 @@ function JacobianFunctionWrapper( else throw(IS.ConflictingInputsError("negative sparse_retrieve_loop not valid")) end - Jf(Jv, x0) mass_matrix = get_mass_matrix(m!.inputs) - return JacobianFunctionWrapper{typeof(Jf), typeof(Jv)}(Jf, Jv, x0, mass_matrix) + return JacobianFunctionWrapper{HasDelays, typeof(Jf), typeof(Jv)}( + Jf, + Jv, + x0, + mass_matrix, + ) end function get_jacobian( diff --git a/src/base/simulation.jl b/src/base/simulation.jl index 395bc1e0d..1799063d4 100644 --- a/src/base/simulation.jl +++ b/src/base/simulation.jl @@ -289,7 +289,10 @@ end function _get_jacobian(sim::Simulation{MassMatrixModel}) inputs = get_simulation_inputs(sim) x0_init = get_initial_conditions(sim) - return JacobianFunctionWrapper(MassMatrixModel(inputs, x0_init, JacobianCache), x0_init) + return JacobianFunctionWrapper( + MassMatrixModel(inputs, x0_init, JacobianCache), + x0_init, + ) end function _build_perturbations!(sim::Simulation) @@ -392,10 +395,8 @@ function _get_diffeq_problem( SciMLBase.DDEFunction{true}( model; mass_matrix = get_mass_matrix(simulation_inputs), - jac = jacobian, #Fails after time of delay if autodiff=true with non-zero delays + jac = jacobian, jac_prototype = jacobian.Jv, - # Necessary to avoid unnecessary calculations in Rosenbrock methods - #tgrad = (dT, u, h, p, t) -> dT .= false, #Doesn't work with passing tgrad yet ), sim.x0_init, h, @@ -450,7 +451,7 @@ function _build!(sim::Simulation{T}; kwargs...) where {T <: SimulationModel} model = T(simulation_inputs, get_initial_conditions(sim), SimCache) end TimerOutputs.@timeit BUILD_TIMER "Initial Condition NLsolve refinement" begin - refine_initial_condition!(sim, model, jacobian) + refine_initial_condition!(sim, model, jacobian) #Jacobian errors end TimerOutputs.@timeit BUILD_TIMER "Build Perturbations" begin _build_perturbations!(sim) diff --git a/src/base/small_signal.jl b/src/base/small_signal.jl index 01313da91..441c15e5b 100644 --- a/src/base/small_signal.jl +++ b/src/base/small_signal.jl @@ -203,6 +203,9 @@ Returns the Small Signal Output object that contains the eigenvalues and partici """ function small_signal_analysis(sim::Simulation{T}; kwargs...) where {T <: SimulationModel} inputs = get_simulation_inputs(sim) + if !(isempty(inputs.delays)) + return error("Small signal analysis not compatible with system model with delays") + end x_eval = get(kwargs, :operating_point, get_initial_conditions(sim)) return _small_signal_analysis(T, inputs, x_eval, sim.multimachine) end diff --git a/src/models/system.jl b/src/models/system.jl index b8d559978..ba641f7df 100644 --- a/src/models/system.jl +++ b/src/models/system.jl @@ -11,14 +11,29 @@ function ResidualModel( T, ForwardDiff.pickchunksize(length(x0_init)), } - return SystemModel{ResidualModel, NoDelays}(inputs, Ctype{U}(system_residual!, inputs)) + if isempty(inputs.delays) + return SystemModel{ResidualModel, NoDelays}( + inputs, + Ctype{U}(system_residual!, inputs), + ) + else + error( + "Cannot use ResidualModel for a system model with delays. Remove delays or use MassMatrixModel", + ) + end end """ Instantiate an ResidualModel for ODE inputs. """ function ResidualModel(inputs, ::Vector{Float64}, ::Type{Ctype}) where {Ctype <: SimCache} - return SystemModel{ResidualModel, NoDelays}(inputs, Ctype(system_residual!, inputs)) + if isempty(inputs.delays) + return SystemModel{ResidualModel, NoDelays}(inputs, Ctype(system_residual!, inputs)) + else + error( + "Cannot use ResidualModel for a system model with delays. Remove delays or use MassMatrixModel", + ) + end end function (m::SystemModel{ResidualModel, NoDelays, C})( diff --git a/test/Project.toml b/test/Project.toml index fb580ea2e..657f3f1f5 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -10,13 +10,11 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" -PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a" PowerFlows = "94fada2c-fd9a-4e89-8d82-81405f5cb4f6" PowerNetworkMatrices = "bed98974-b02a-5e2f-9fe0-a103f5c450dd" PowerSimulationsDynamics = "398b2ede-47ed-4edc-b52e-69e4a48b4336" PowerSystemCaseBuilder = "f00506e0-b84f-492a-93c2-c0a9afc4364e" PowerSystems = "bcd98974-b02a-5e2f-9ee0-a103f5c450dd" -Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4" diff --git a/test/test_case57_degov.jl b/test/test_case57_degov.jl index 2574da875..ddc8f6a02 100644 --- a/test/test_case57_degov.jl +++ b/test/test_case57_degov.jl @@ -15,7 +15,7 @@ csv_file_degov_nodelay_speed = csv_file_degov_delay_speed = joinpath(TEST_FILES_DIR, "benchmarks/psse/DEGOV/degov_delay_speed_final.csv") -#= @testset "Test 57 DEGOV ResidualModel" begin +@testset "Test 57 DEGOV MassMatrixModel" begin path = mktempdir() try sys = System(raw_file, dyr_file) @@ -51,7 +51,7 @@ csv_file_degov_delay_speed = # Define Simulation Problem sim = Simulation!( - ResidualModel, + MassMatrixModel, sys, path, (0.0, 5.0), @@ -67,55 +67,68 @@ csv_file_degov_delay_speed = end @test (diff_val[1] < 1e-5) - # 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 - test_57_eigvals) < 1e-10 + @test_throws ErrorException small_signal_analysis(sim) # Solve problem - @test execute!(sim, IDA(); dtmax = (1 / 240), saveat = (1 / 240)) == + @test execute!( + sim, + MethodOfSteps(Rodas4(; autodiff = false)); + dtmax = (1 / 240), + saveat = (1 / 240), + ) == PSID.SIMULATION_FINALIZED results_nodelay = read_results(sim) + t_psid, ω_psid_nodelay = get_frequency_series(results_nodelay, "generator-102-1") + t_pw, ω_pw_nodelay = get_csv_delta(csv_file_degov_nodelay_speed) + @test LinearAlgebra.norm(ω_pw_nodelay - ω_psid_nodelay, Inf) <= 4.7e-5 + # Add delay set_Td!(get_prime_mover(dyn_gen_new), 1.0) sim = Simulation!( - ResidualModel, + MassMatrixModel, sys, path, (0.0, 5.0), BranchTrip(1.0, Line, "BUS 1-BUS 2-i_1"); frequency_reference = ReferenceBus(), ) - @test execute!(sim, IDA(); dtmax = (1 / 240), saveat = (1 / 240)) == + + @test execute!( + sim, + MethodOfSteps(Rodas5(; autodiff = false)); + dtmax = (1 / 240), + saveat = (1 / 240), + ) == PSID.SIMULATION_FINALIZED results_delay = read_results(sim) - t_psid, ω_psid_nodelay = get_frequency_series(results_nodelay, "generator-102-1") t_psid, ω_psid_delay = get_frequency_series(results_delay, "generator-102-1") - t_pw, ω_pw_nodelay = get_csv_delta(csv_file_degov_nodelay_speed) t_pw, ω_pw_delay = get_csv_delta(csv_file_degov_delay_speed) - - @test LinearAlgebra.norm(ω_pw_nodelay - ω_psid_nodelay, Inf) <= 4.7e-5 - #@test LinearAlgebra.norm(ω_pw_delay - ω_psid_delay, Inf) <= 4.7e-5 #THIS SHOULD PASS ONCE DELAYS ARE INCLUDED IN PSID + @test LinearAlgebra.norm(ω_pw_delay - ω_psid_delay, Inf) <= 3.1e-5 #Plotting for debug (add PlotlyJS): - #t1 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_nodelay, name = "speed-pw -- no delay") - #t2 = PlotlyJS.scatter(; x = t_psid, y = ω_psid_nodelay, name = "speed-psid -- no delay") - #t3 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_delay, name = "speed-pw -- 1s delay") - #t4 = PlotlyJS.scatter(; x = t_pw, y = ω_psid_delay, name = "speed-psid -- 1s delay") - #display(PlotlyJS.plot([t1, t2, t3, t4])) +#= t1 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_nodelay, name = "speed-pw -- no delay") + t2 = PlotlyJS.scatter(; + x = t_psid, + y = ω_psid_nodelay, + name = "speed-psid -- no delay", + ) + t3 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_delay, name = "speed-pw -- 1s delay") + t4 = PlotlyJS.scatter(; + x = t_psid, + y = ω_psid_delay, + name = "speed-psid -- 1s delay", + ) + display(PlotlyJS.plot([t1, t2, t3, t4])) =# finally @info("removing test files") rm(path; force = true, recursive = true) end -end =# +end -@testset "Test 57 DEGOV MassMatrixModel" begin +@testset "Test 57 DEGOV ResidualModel" begin path = mktempdir() try sys = System(raw_file, dyr_file) @@ -151,82 +164,14 @@ end =# # Define Simulation Problem sim = Simulation!( - MassMatrixModel, - sys, - path, - (0.0, 5.0), - BranchTrip(1.0, Line, "BUS 1-BUS 2-i_1"); - frequency_reference = ReferenceBus(), - ) - - # Test Initial Condition - diff_val = [0.0] - res = get_init_values_for_comparison(sim) - for (k, v) in test_57_x0_init - diff_val[1] += LinearAlgebra.norm(res[k] - v) - end - @test (diff_val[1] < 1e-5) - - # 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 - test_57_eigvals) < 1e-10 - - # Solve problem - @test execute!( - sim, - MethodOfSteps(Rodas4(; autodiff = true)); - dtmax = (1 / 240), - saveat = (1 / 240), - ) == - PSID.SIMULATION_FINALIZED - results_nodelay = read_results(sim) - - t_psid, ω_psid_nodelay = get_frequency_series(results_nodelay, "generator-102-1") - t_pw, ω_pw_nodelay = get_csv_delta(csv_file_degov_nodelay_speed) - @test LinearAlgebra.norm(ω_pw_nodelay - ω_psid_nodelay, Inf) <= 4.7e-5 - - # Add delay - set_Td!(get_prime_mover(dyn_gen_new), 1.0) - sim = Simulation!( - MassMatrixModel, + ResidualModel, sys, path, (0.0, 5.0), BranchTrip(1.0, Line, "BUS 1-BUS 2-i_1"); frequency_reference = ReferenceBus(), ) - - @test execute!( - sim, - MethodOfSteps(Rodas4(; autodiff = false)); #Fails for autodiff=true - dtmax = (1 / 240), - saveat = (1 / 240), - ) == - PSID.SIMULATION_FINALIZED - results_delay = read_results(sim) - - t_psid, ω_psid_delay = get_frequency_series(results_delay, "generator-102-1") - t_pw, ω_pw_delay = get_csv_delta(csv_file_degov_delay_speed) - @test LinearAlgebra.norm(ω_pw_delay - ω_psid_delay, Inf) <= 3.1e-5 - - #Plotting for debug (add PlotlyJS): - t1 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_nodelay, name = "speed-pw -- no delay") - t2 = PlotlyJS.scatter(; - x = t_psid, - y = ω_psid_nodelay, - name = "speed-psid -- no delay", - ) - t3 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_delay, name = "speed-pw -- 1s delay") - t4 = PlotlyJS.scatter(; - x = t_psid, - y = ω_psid_delay, - name = "speed-psid -- 1s delay", - ) - display(PlotlyJS.plot([t1, t2, t3, t4])) + @test sim.status == PSID.BUILD_FAILED finally @info("removing test files") From 2e8b6f4f092b4d0533ccf82b733a01f035bbaf39 Mon Sep 17 00:00:00 2001 From: Matt Bossart Date: Fri, 15 Dec 2023 10:51:27 -0500 Subject: [PATCH 7/7] add bus_size to DW --- src/base/device_wrapper.jl | 9 +++++++++ src/base/simulation_inputs.jl | 3 ++- test/runtests.jl | 2 -- test/test_case57_degov.jl | 26 +++++++++++++------------- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/base/device_wrapper.jl b/src/base/device_wrapper.jl index add78c12b..3f7d5f88e 100644 --- a/src/base/device_wrapper.jl +++ b/src/base/device_wrapper.jl @@ -45,6 +45,7 @@ struct DynamicWrapper{T <: PSY.DynamicInjection} ix_range::Vector{Int} ode_range::Vector{Int} bus_ix::Int + bus_size::Int global_index::Base.ImmutableDict{Symbol, Int} component_state_mapping::Base.ImmutableDict{Int, Vector{Int}} input_port_mapping::Base.ImmutableDict{Int, Vector{Int}} @@ -65,6 +66,7 @@ struct DynamicWrapper{T <: PSY.DynamicInjection} ix_range, ode_range, bus_ix::Int, + bus_size::Int, global_index::Base.ImmutableDict{Symbol, Int}, component_state_mapping::Base.ImmutableDict{Int, Vector{Int}}, input_port_mapping::Base.ImmutableDict{Int, Vector{Int}}, @@ -87,6 +89,7 @@ struct DynamicWrapper{T <: PSY.DynamicInjection} Vector{Int}(ix_range), Vector{Int}(ode_range), bus_ix, + bus_size, global_index, component_state_mapping, input_port_mapping, @@ -119,6 +122,7 @@ function DynamicWrapper( device::T, dynamic_device::D, bus_ix::Int, + bus_size::Int, ix_range, ode_range, inner_var_range, @@ -152,6 +156,7 @@ function DynamicWrapper( ix_range, ode_range, bus_ix, + bus_size, Base.ImmutableDict( sort!(device_states .=> ix_range; by = x -> x.second, rev = true)..., ), @@ -173,6 +178,7 @@ function DynamicWrapper( device::PSY.ThermalStandard, dynamic_device::PSY.AggregateDistributedGenerationA, bus_ix::Int, + bus_size::Int, ix_range, ode_range, inner_var_range, @@ -200,6 +206,7 @@ function DynamicWrapper( ix_range, ode_range, bus_ix, + bus_size, Base.ImmutableDict( sort!(device_states .=> ix_range; by = x -> x.second, rev = true)..., ), @@ -221,6 +228,7 @@ function DynamicWrapper( device::PSY.Source, dynamic_device::D, bus_ix::Int, + bus_size::Int, ix_range, ode_range, inner_var_range, @@ -246,6 +254,7 @@ function DynamicWrapper( collect(ix_range), collect(ode_range), bus_ix, + bus_size, Base.ImmutableDict(Dict(device_states .=> ix_range)...), Base.ImmutableDict{Int, Vector{Int}}(), Base.ImmutableDict{Int, Vector{Int}}(), diff --git a/src/base/simulation_inputs.jl b/src/base/simulation_inputs.jl index ce03d01af..2c9a17293 100644 --- a/src/base/simulation_inputs.jl +++ b/src/base/simulation_inputs.jl @@ -167,6 +167,7 @@ function _wrap_dynamic_injector_data(sys::PSY.System, lookup, injection_start::I inner_vars_count = 1 sys_base_power = PSY.get_base_power(sys) sys_base_freq = PSY.get_frequency(sys) + bus_size = get_n_buses(sys) @assert !isempty(injector_data) for (ix, device) in enumerate(injector_data) @debug "Wrapping $(PSY.get_name(device))" @@ -181,11 +182,11 @@ function _wrap_dynamic_injector_data(sys::PSY.System, lookup, injection_start::I @debug "ix_range=$ix_range ode_range=$ode_range inner_vars_range= $inner_vars_range" dynamic_device = PSY.get_dynamic_injector(device) @assert dynamic_device !== nothing - #TODO - add bus_size to the dynamic injector -- allows you to index into the voltages. wrapped_injector[ix] = DynamicWrapper( device, dynamic_device, bus_ix, + bus_size, ix_range, ode_range, inner_vars_range, diff --git a/test/runtests.jl b/test/runtests.jl index b91f4211b..76b8cf297 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,5 +1,3 @@ -using Revise -using PlotlyJS using PowerSimulationsDynamics using PowerSystems using Test diff --git a/test/test_case57_degov.jl b/test/test_case57_degov.jl index ddc8f6a02..82b388970 100644 --- a/test/test_case57_degov.jl +++ b/test/test_case57_degov.jl @@ -108,19 +108,19 @@ csv_file_degov_delay_speed = @test LinearAlgebra.norm(ω_pw_delay - ω_psid_delay, Inf) <= 3.1e-5 #Plotting for debug (add PlotlyJS): -#= t1 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_nodelay, name = "speed-pw -- no delay") - t2 = PlotlyJS.scatter(; - x = t_psid, - y = ω_psid_nodelay, - name = "speed-psid -- no delay", - ) - t3 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_delay, name = "speed-pw -- 1s delay") - t4 = PlotlyJS.scatter(; - x = t_psid, - y = ω_psid_delay, - name = "speed-psid -- 1s delay", - ) - display(PlotlyJS.plot([t1, t2, t3, t4])) =# + #= t1 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_nodelay, name = "speed-pw -- no delay") + t2 = PlotlyJS.scatter(; + x = t_psid, + y = ω_psid_nodelay, + name = "speed-psid -- no delay", + ) + t3 = PlotlyJS.scatter(; x = t_pw, y = ω_pw_delay, name = "speed-pw -- 1s delay") + t4 = PlotlyJS.scatter(; + x = t_psid, + y = ω_psid_delay, + name = "speed-psid -- 1s delay", + ) + display(PlotlyJS.plot([t1, t2, t3, t4])) =# finally @info("removing test files")