|
| 1 | +# PSSE Hydro Turbine Governor Components |
| 2 | +# |
| 3 | +# Original work Copyright (c) 2016-2022 Luigi Vanfretti, ALSETLab, and contributors |
| 4 | +# Original work licensed under BSD 3-Clause License |
| 5 | +# Original source: https://github.com/OpenIPSL/OpenIPSL |
| 6 | +# |
| 7 | +# This Julia/PowerDynamics port maintains the same mathematical formulation |
| 8 | +# while adapting to PowerDynamics/ModelingToolkit framework conventions. |
| 9 | + |
| 10 | +@mtkmodel PSSE_HYGOV begin |
| 11 | + @parameters begin |
| 12 | + # Governor parameters |
| 13 | + R=0.05, [description="Permanent droop gain [pu]"] |
| 14 | + r=0.3, [description="Temporary droop gain [pu]"] |
| 15 | + T_r=5, [description="Governor time constant [s]"] |
| 16 | + T_f=0.05, [description="Filter time constant [s]"] |
| 17 | + T_g=0.5, [description="Servo time constant [s]"] |
| 18 | + VELM=0.2, [description="Gate open/close velocity limit [pu/s]"] |
| 19 | + G_MAX=0.9, [description="Maximum gate limit [pu]"] |
| 20 | + G_MIN=0, [description="Minimum gate limit [pu]"] |
| 21 | + |
| 22 | + # Hydraulic turbine parameters |
| 23 | + T_w=1.25, [description="Water time constant [s]"] |
| 24 | + A_t=1.2, [description="Turbine gain [pu]"] |
| 25 | + D_turb=0.2, [description="Turbine damping [pu]"] |
| 26 | + q_NL=0.08, [description="Water flow at no load [pu]"] |
| 27 | + h0=1, [description="Water head initial value [pu]", bounds=(0, Inf)] |
| 28 | + |
| 29 | + # Initialization parameters (determined during initialization) |
| 30 | + n_ref, [guess=1, description="Speed reference [pu]"] |
| 31 | + end |
| 32 | + |
| 33 | + # Protected parameters calculated from initial conditions (like OpenIPSL) |
| 34 | + # These follow the OpenIPSL initialization logic: |
| 35 | + # P_m0 := PMECH0 |
| 36 | + # q0 := P_m0/(A_t*h0) + q_NL |
| 37 | + # g0 := q0/sqrt(h0) |
| 38 | + # c0 := g0 |
| 39 | + # nref := R*c0 |
| 40 | + |
| 41 | + @components begin |
| 42 | + # Active inputs/outputs |
| 43 | + SPEED_in = RealInput() # Machine speed deviation from nominal [pu] |
| 44 | + PMECH_out = RealOutput() # Turbine mechanical power [pu] |
| 45 | + |
| 46 | + # Building block components |
| 47 | + filter = SimpleLag(K=1, T=T_f, guess=0) |
| 48 | + temp_droop = SimpleLead(K=r*T_r, T=T_r, guess=0) |
| 49 | + position_limiter = LimIntegrator(K=1, outMin=G_MIN, outMax=G_MAX, guess=nothing) |
| 50 | + servo = SimpleLag(K=1, T=T_g, guess=nothing) |
| 51 | + water_integrator = LimIntegrator(K=1/T_w, outMin=-Inf, outMax=Inf, guess=nothing) |
| 52 | + end |
| 53 | + |
| 54 | + @variables begin |
| 55 | + # Governor system variables |
| 56 | + speed_input(t), [description="Speed input signal [pu]"] |
| 57 | + droop_feedback(t), [description="Permanent droop feedback [pu]"] |
| 58 | + governor_error(t), [description="Governor error signal [pu]"] |
| 59 | + velocity_limited_signal(t), [description="Velocity limited signal [pu/s]"] |
| 60 | + desired_gate_position(t), [description="Desired gate position [pu]"] |
| 61 | + gate_position(t), [description="Actual gate position [pu]"] |
| 62 | + |
| 63 | + # Hydraulic system variables |
| 64 | + flow_gate_ratio(t), [description="Flow to gate ratio"] |
| 65 | + flow_gate_ratio_squared(t), [description="(Q/G)^2"] |
| 66 | + water_flow(t), [description="Water flow Q [pu]"] |
| 67 | + flow_minus_noload(t), [description="Flow minus no-load Q-qNL [pu]"] |
| 68 | + turbine_head(t), [description="Turbine head H [pu]"] |
| 69 | + head_flow_product(t), [description="H*(Q-qNL) [pu]"] |
| 70 | + base_power(t), [description="A_t * H * (Q-qNL) [pu]"] |
| 71 | + damping_term(t), [description="D_turb * G * SPEED [pu]"] |
| 72 | + end |
| 73 | + |
| 74 | + @equations begin |
| 75 | + # Governor system (following OpenIPSL signal flow) |
| 76 | + speed_input ~ SPEED_in.u |
| 77 | + |
| 78 | + # Permanent droop feedback (R * gate_position) |
| 79 | + droop_feedback ~ R * desired_gate_position |
| 80 | + |
| 81 | + # Main error calculation (add: n_ref - (SPEED + R*c)) |
| 82 | + governor_error ~ n_ref - (speed_input + droop_feedback) |
| 83 | + |
| 84 | + # Filter (SimpleLag1) |
| 85 | + filter.in ~ governor_error |
| 86 | + |
| 87 | + # Temporary droop compensation (simpleLead) |
| 88 | + temp_droop.in ~ filter.out |
| 89 | + |
| 90 | + # Velocity limiting |
| 91 | + velocity_limited_signal ~ clamp(temp_droop.out, -VELM, VELM) |
| 92 | + |
| 93 | + # Position limiter (LimIntegrator) |
| 94 | + position_limiter.in ~ velocity_limited_signal |
| 95 | + desired_gate_position ~ position_limiter.out |
| 96 | + |
| 97 | + # Servo motor |
| 98 | + servo.in ~ desired_gate_position |
| 99 | + gate_position ~ servo.out |
| 100 | + |
| 101 | + # Hydraulic turbine system (following OpenIPSL connections) |
| 102 | + # Division: Q/G |
| 103 | + flow_gate_ratio ~ water_flow / gate_position |
| 104 | + |
| 105 | + # Product: (Q/G)^2 |
| 106 | + flow_gate_ratio_squared ~ flow_gate_ratio^2 |
| 107 | + |
| 108 | + # Water integrator: dQ/dt = (h0 - (Q/G)^2)/T_w |
| 109 | + water_integrator.in ~ h0 - flow_gate_ratio_squared |
| 110 | + water_flow ~ water_integrator.out |
| 111 | + |
| 112 | + # Add3: Q - qNL |
| 113 | + # flow_minus_noload ~ water_flow - q_NL |
| 114 | + |
| 115 | + # Turbine head calculation: H = (Q/G)^2 |
| 116 | + turbine_head ~ flow_gate_ratio_squared |
| 117 | + |
| 118 | + # Gain6: A_t * H * (Q - qNL) |
| 119 | + base_power ~ A_t * turbine_head * (water_flow - q_NL) |
| 120 | + |
| 121 | + # Damping term: D_turb * G * SPEED |
| 122 | + damping_term ~ D_turb * gate_position * speed_input |
| 123 | + |
| 124 | + # Final power: base_power - damping_term |
| 125 | + PMECH_out.u ~ base_power - damping_term |
| 126 | + end |
| 127 | +end |
0 commit comments