|
| 1 | +using PowerDynamics |
| 2 | +PowerDynamics.load_pdtesting() |
| 3 | +using Main.PowerDynamicsTesting |
| 4 | + |
| 5 | +using PowerDynamics.Library |
| 6 | +using ModelingToolkit |
| 7 | +using OrdinaryDiffEqRosenbrock |
| 8 | +using OrdinaryDiffEqNonlinearSolve |
| 9 | + |
| 10 | +using CSV |
| 11 | +using DataFrames |
| 12 | +using CairoMakie |
| 13 | + |
| 14 | +# Load reference data from SCRX simulation |
| 15 | +ref = CSV.read( |
| 16 | + joinpath(pkgdir(PowerDynamics),"test","OpenIPSL_test","SCRX","modelica_results.csv.gz"), |
| 17 | + DataFrame; |
| 18 | + drop=(i,name) -> contains(string(name), "nrows="), |
| 19 | + silencewarnings=true |
| 20 | +) |
| 21 | + |
| 22 | +# SCRX test system parameters from OpenIPSL SCRX test case |
| 23 | +BUS = let |
| 24 | + # Power flow from OpenIPSL SCRX test |
| 25 | + v_0 = 1.0 |
| 26 | + angle_0 = 0.070492225331847 |
| 27 | + |
| 28 | + # Create GENROU machine with EFD input enabled for exciter control |
| 29 | + @named genrou = PSSE_GENROU(; |
| 30 | + # System parameters |
| 31 | + S_b = 100e6, |
| 32 | + M_b = 100e6, |
| 33 | + # GENROU machine parameters from OpenIPSL SCRX.mo (lines 6-28) |
| 34 | + H = 4.28, |
| 35 | + D = 0, |
| 36 | + Xd = 1.84, |
| 37 | + Xq = 1.75, |
| 38 | + Xpd = 0.41, |
| 39 | + Xpq = 0.6, |
| 40 | + Xppd = 0.2, |
| 41 | + Xppq = 0.2, |
| 42 | + Xl = 0.12, |
| 43 | + Tpd0 = 5, |
| 44 | + Tppd0 = 0.07, |
| 45 | + Tpq0 = 0.9, |
| 46 | + Tppq0 = 0.09, |
| 47 | + S10 = 0.11, |
| 48 | + S12 = 0.39, |
| 49 | + R_a = 0, |
| 50 | + pmech_input = false, |
| 51 | + efd_input = true # EFD controlled by SCRX |
| 52 | + ) |
| 53 | + |
| 54 | + # Create SCRX exciter with parameters matching OpenIPSL test (lines 30-38) |
| 55 | + @named scrx = PSSE_SCRX(; |
| 56 | + T_AT_B = 0.1, |
| 57 | + T_B = 1, |
| 58 | + K = 100, |
| 59 | + T_E = 0.005, |
| 60 | + E_MIN = -10, |
| 61 | + E_MAX = 10, |
| 62 | + r_cr_fd = 0, |
| 63 | + C_SWITCH = false, # Bus fed mode |
| 64 | + vothsg_input = false, # No other signal input |
| 65 | + vuel_input = false, # No under-excitation limiter |
| 66 | + voel_input = false # No over-excitation limiter |
| 67 | + ) |
| 68 | + |
| 69 | + con = [ |
| 70 | + # Connect exciter output to machine field voltage |
| 71 | + connect(scrx.EFD_out, genrou.EFD_in) |
| 72 | + |
| 73 | + # Connect machine field current to exciter |
| 74 | + connect(genrou.XADIFD_out, scrx.XADIFD_in) |
| 75 | + |
| 76 | + # Connect terminal voltage measurement |
| 77 | + connect(genrou.ETERM_out, scrx.ECOMP_in) |
| 78 | + ] |
| 79 | + |
| 80 | + # Create bus model with proper connections |
| 81 | + busmodel = MTKBus([genrou, scrx], con; name=:GEN1) |
| 82 | + bm = compile_bus(busmodel, pf=pfSlack(V=v_0, δ=angle_0)) |
| 83 | +end |
| 84 | + |
| 85 | +sol = OpenIPSL_SMIB(BUS); |
| 86 | + |
| 87 | +## Validation tests for GENROU machine variables (core 3 variables) |
| 88 | +@test ref_rms_error(sol, ref, VIndex(:GEN1, :genrou₊w), "gENROU.w") < 1e-5 |
| 89 | +@test ref_rms_error(sol, ref, VIndex(:GEN1, :genrou₊delta), "gENROU.delta") < 1e-3 |
| 90 | +@test ref_rms_error(sol, ref, VIndex(:GEN1, :genrou₊Vt), "gENROU.Vt") < 1e-4 |
| 91 | + |
| 92 | +## Validation tests for SCRX exciter variables (4 control path variables) |
| 93 | +@test ref_rms_error(sol, ref, VIndex(:GEN1, :scrx₊leadlag₊out), "sCRX.imLeadLag.y") < 5e-5 |
| 94 | +@test ref_rms_error(sol, ref, VIndex(:GEN1, :scrx₊amplifier₊out), "sCRX.simpleLagLim.y") < 5e-3 |
| 95 | +@test ref_rms_error(sol, ref, VIndex(:GEN1, :genrou₊XADIFD_out₊u), "gENROU.XADIFD") < 1e-3 |
| 96 | +@test ref_rms_error(sol, ref, VIndex(:GEN1, :scrx₊EFD_out₊u), "sCRX.EFD") < 2e-3 |
| 97 | + |
| 98 | +#= |
| 99 | +fig_scrx = let |
| 100 | + fig = Figure(size=(1400, 1200)) |
| 101 | + ts = refine_timeseries(sol.t) |
| 102 | +
|
| 103 | + # Plot 1: Generator Rotor Angle |
| 104 | + ax1 = Axis(fig[1,1]; xlabel="Time [s]", ylabel="δ [rad]", title="Generator: Rotor Angle") |
| 105 | + lines!(ax1, ref.time, ref[!, Symbol("gENROU.delta")]; label="OpenIPSL", color=Cycled(1), linewidth=2, alpha=0.7) |
| 106 | + lines!(ax1, ts, sol(ts, idxs=VIndex(:GEN1, :genrou₊delta)).u; label="PowerDynamics", color=Cycled(1), linewidth=2, linestyle=:dash) |
| 107 | + axislegend(ax1) |
| 108 | +
|
| 109 | + # Plot 2: Generator Speed Deviation |
| 110 | + ax2 = Axis(fig[1,2]; xlabel="Time [s]", ylabel="ω [pu]", title="Generator: Speed Deviation") |
| 111 | + lines!(ax2, ref.time, ref[!, Symbol("gENROU.w")]; label="OpenIPSL", color=Cycled(2), linewidth=2, alpha=0.7) |
| 112 | + lines!(ax2, ts, sol(ts, idxs=VIndex(:GEN1, :genrou₊w)).u; label="PowerDynamics", color=Cycled(2), linewidth=2, linestyle=:dash) |
| 113 | + axislegend(ax2) |
| 114 | +
|
| 115 | + # Plot 3: Generator Terminal Voltage |
| 116 | + ax3 = Axis(fig[2,1]; xlabel="Time [s]", ylabel="Vt [pu]", title="Generator: Terminal Voltage") |
| 117 | + lines!(ax3, ref.time, ref[!, Symbol("gENROU.Vt")]; label="OpenIPSL", color=Cycled(3), linewidth=2, alpha=0.7) |
| 118 | + lines!(ax3, ts, sol(ts, idxs=VIndex(:GEN1, :genrou₊Vt)).u; label="PowerDynamics", color=Cycled(3), linewidth=2, linestyle=:dash) |
| 119 | + axislegend(ax3) |
| 120 | +
|
| 121 | + # Plot 4: SCRX LeadLag Output |
| 122 | + ax4 = Axis(fig[2,2]; xlabel="Time [s]", ylabel="[pu]", title="SCRX: LeadLag Output") |
| 123 | + lines!(ax4, ref.time, ref[!, Symbol("sCRX.imLeadLag.y")]; label="OpenIPSL", color=Cycled(4), linewidth=2, alpha=0.7) |
| 124 | + lines!(ax4, ts, sol(ts, idxs=VIndex(:GEN1, :scrx₊leadlag₊out)).u; label="PowerDynamics", color=Cycled(4), linewidth=2, linestyle=:dash) |
| 125 | + axislegend(ax4) |
| 126 | +
|
| 127 | + # Plot 5: SCRX Amplifier Output |
| 128 | + ax5 = Axis(fig[3,1]; xlabel="Time [s]", ylabel="[pu]", title="SCRX: Amplifier Output") |
| 129 | + lines!(ax5, ref.time, ref[!, Symbol("sCRX.simpleLagLim.y")]; label="OpenIPSL", color=Cycled(5), linewidth=2, alpha=0.7) |
| 130 | + lines!(ax5, ts, sol(ts, idxs=VIndex(:GEN1, :scrx₊amplifier₊out)).u; label="PowerDynamics", color=Cycled(5), linewidth=2, linestyle=:dash) |
| 131 | + axislegend(ax5) |
| 132 | +
|
| 133 | + # Plot 6: SCRX Final EFD Output |
| 134 | + ax6 = Axis(fig[3,2]; xlabel="Time [s]", ylabel="EFD [pu]", title="SCRX: Final Field Voltage") |
| 135 | + lines!(ax6, ref.time, ref[!, Symbol("sCRX.EFD")]; label="OpenIPSL", color=Cycled(6), linewidth=2, alpha=0.7) |
| 136 | + lines!(ax6, ts, sol(ts, idxs=VIndex(:GEN1, :scrx₊EFD_out₊u)).u; label="PowerDynamics", color=Cycled(6), linewidth=2, linestyle=:dash) |
| 137 | + axislegend(ax6) |
| 138 | +
|
| 139 | + fig |
| 140 | +end |
| 141 | +=# |
0 commit comments