Skip to content

Commit

Permalink
add degov1 model
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigomha committed Sep 20, 2024
1 parent 9a23526 commit 6ce7cce
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/initialization/generator_components/init_tg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,39 @@ function initialize_tg!(
return
end

function initialize_tg!(
device_states,
static::PSY.StaticInjection,
dynamic_device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, PSY.DEGOV1, P}},
inner_vars::AbstractVector,
) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS}
tg = PSY.get_prime_mover(dynamic_device)
droop_flag = PSY.get_droop_flag(tg)
R = PSY.get_R(tg)
#Get mechanical torque to SyncMach
τm0 = inner_vars[τm_var]
τe0 = inner_vars[τe_var]
if droop_flag == 0
PSY.set_P_ref!(tg, τm0 * R)
set_P_ref(dynamic_device, τm0 * R)
else
PSY.set_P_ref!(tg, τe0 * R)
set_P_ref(dynamic_device, τe0 * R)
end
#Update states
tg_ix = get_local_state_ix(dynamic_device, typeof(tg))
tg_states = @view device_states[tg_ix]
tg_states[1] = 0.0
tg_states[2] = 0.0
tg_states[3] = 0.0
tg_states[4] = 0.0
tg_states[5] = τm0
if droop_flag == 1
tg_states[6] = τe0
end
return
end

function initialize_tg!(
device_states,
::PSY.StaticInjection,
Expand Down
102 changes: 102 additions & 0 deletions src/models/generator_models/tg_models.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ function mass_matrix_tg_entries!(
return
end

function mass_matrix_tg_entries!(
mass_matrix,
tg::PSY.DEGOV1,
global_index::Base.ImmutableDict{Symbol, Int64},
)
mass_matrix[global_index[:x_g1], global_index[:x_g1]] =
PSY.get_T1(tg) * PSY.get_T2(tg)
mass_matrix[global_index[:x_g3], global_index[:x_g3]] = PSY.get_T5(tg) * PSY.get_T6(tg)
droop_flag = PSY.get_droop_flag(tg)
if droop_flag == 1
mass_matrix[global_index[:x_g6], global_index[:x_g6]] = PSY.get_Te(tg)
end
return
end

function mass_matrix_tg_entries!(
mass_matrix,
tg::PSY.PIDGOV,
Expand Down Expand Up @@ -454,6 +469,93 @@ function mdl_tg_ode!(
return
end

function mdl_tg_ode!(
device_states::AbstractArray{<:ACCEPTED_REAL_TYPES},
output_ode::AbstractArray{<:ACCEPTED_REAL_TYPES},
inner_vars::AbstractArray{<:ACCEPTED_REAL_TYPES},
ω_sys::ACCEPTED_REAL_TYPES,
device::DynamicWrapper{PSY.DynamicGenerator{M, S, A, PSY.DEGOV1, P}},
h,
t,
) where {M <: PSY.Machine, S <: PSY.Shaft, A <: PSY.AVR, P <: PSY.PSS}

#Obtain references
P_ref = get_P_ref(device)

#Obtain indices for component w/r to device
local_ix = get_local_state_ix(device, PSY.DEGOV1)

#Define internal states for component
internal_states = @view device_states[local_ix]
x_g1 = internal_states[1] # Electric Control Box 1
x_g2 = internal_states[2] # Electric Control Box 2
x_g3 = internal_states[3] # Actuator 1
x_g4 = internal_states[4] # Actuator 2
x_g5 = internal_states[5] # Actuator 3

#Get Parameters
tg = PSY.get_prime_mover(device)
droop_flag = PSY.get_droop_flag(tg)
if droop_flag == 0
feedback = x_g5
else
feedback = internal_states[6] # Low-Pass Power
end
T1 = PSY.get_T1(tg)
T2 = PSY.get_T2(tg)
T3 = PSY.get_T3(tg)
K = PSY.get_K(tg)
T4 = PSY.get_T4(tg)
T5 = PSY.get_T5(tg)
T6 = PSY.get_T6(tg)
Td = PSY.get_Td(tg)
Te = PSY.get_Te(tg)

#Obtain external states inputs for component
external_ix = get_input_port_ix(device, PSY.DEGOV1)
ω = @view device_states[external_ix]

#Get Parameters
T1 = PSY.get_T1(tg)
T2 = PSY.get_T2(tg)
T3 = PSY.get_T3(tg)
K = PSY.get_K(tg)
T4 = PSY.get_T4(tg)
T5 = PSY.get_T5(tg)
T6 = PSY.get_T6(tg)
Td = PSY.get_Td(tg)
R = PSY.get_R(tg)
Te = PSY.get_Te(tg)

#Compute block derivatives
ll_in = P_ref - (ω[1] - 1.0) - feedback * R
y1, dx_g1, dx_g2 =
lead_lag_2nd_mass_matrix(ll_in, x_g1, x_g2, T1, T1 * T2, T3, 0.0)
y2, dx_g3, dx_g4 = lead_lag_2nd_mass_matrix(y1, x_g3, x_g4, T5 + T6, T5 * T6, T4, 0.0)
_, dx_g5 = integrator_windup(y2, x_g5, K, 1.0, -Inf, Inf)
delayed_x_g5 = get_delayed_value(h, t, Td, x_g5, get_global_index(device)[:x_g5])
P_m = delayed_x_g5 * (ω[1])

#Compute 5 (or 6) State TG ODE:
output_ode[local_ix[1]] = dx_g1
output_ode[local_ix[2]] = dx_g2
output_ode[local_ix[3]] = dx_g3
output_ode[local_ix[4]] = dx_g4
output_ode[local_ix[5]] = dx_g5

if droop_flag == 1
# Read Inner Vars
τ_e = inner_vars[τe_var]
_, dx_g6 = low_pass_mass_matrix(τ_e, feedback, 1.0, Te)
output_ode[local_ix[6]] = dx_g6
end

#Update mechanical torque
inner_vars[τm_var] = P_m / ω[1] #Fails when trying to assign a Dual to a cache of type Float?

return
end

function mdl_tg_ode!(
device_states::AbstractArray{<:ACCEPTED_REAL_TYPES},
output_ode::AbstractArray{<:ACCEPTED_REAL_TYPES},
Expand Down
15 changes: 15 additions & 0 deletions src/post_processing/post_proc_generator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,21 @@ function _mechanical_torque(
ts, x_a3 = post_proc_state_series(res, (name, :x_a3), dt)
return ts, x_a3
end

"""
Function to obtain the mechanical torque time series of a Dynamic Generator with DEGOV1 Turbine Governor.
"""
function _mechanical_torque(
::PSY.DEGOV1,
name::String,
res::SimulationResults,
dt::Union{Nothing, Float64},
)
ts, x_g5 = post_proc_state_series(res, (name, :x_g5), dt)
return ts, x_g5
end

"""
Function to obtain the mechanical torque time series of a Dynamic Generator with HydroTurbineGov (HYGOV) Turbine Governor.
Expand Down

0 comments on commit 6ce7cce

Please sign in to comment.