Skip to content

Commit 5b18600

Browse files
authored
Update DERA output and minor fixes (#302)
* update pref * update power ratios in DERA model * add DERA output current * update test 45
1 parent 30cc1fc commit 5b18600

File tree

4 files changed

+125
-4
lines changed

4 files changed

+125
-4
lines changed

src/initialization/init_device.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,7 @@ function initialize_dynamic_device!(
571571
end
572572

573573
set_P_ref(dynamic_wrapper, Pref)
574+
PSY.set_P_ref!(dynamic_device, Pref)
574575
set_Q_ref(dynamic_wrapper, Qref)
575576
set_V_ref(dynamic_wrapper, Vref)
576577
set_ω_ref(dynamic_wrapper, Freq_ref)

src/models/device.jl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,7 @@ function _mdl_ode_AggregateDistributedGenerationA!(
10151015
t,
10161016
) where {T <: ACCEPTED_REAL_TYPES}
10171017
sys_ω = global_vars[GLOBAL_VAR_SYS_FREQ_INDEX]
1018+
Sbase = get_system_base_power(dynamic_device)
10181019
Vt = sqrt(voltage_r^2 + voltage_i^2)
10191020

10201021
#Obtain References (from wrapper and device)
@@ -1050,6 +1051,8 @@ function _mdl_ode_AggregateDistributedGenerationA!(
10501051
rrpwr = PSY.get_rrpwr(get_device(dynamic_device))
10511052
Tv = PSY.get_Tv(get_device(dynamic_device))
10521053
Iq_lim = PSY.get_Iq_lim(get_device(dynamic_device))
1054+
basepower = PSY.get_base_power(get_device(dynamic_device))
1055+
base_power_ratio = basepower / Sbase
10531056

10541057
#STATE Vmeas
10551058
_, dVmeas_dt = low_pass_mass_matrix(Vt, Vmeas, 1.0, T_rv)
@@ -1115,8 +1118,8 @@ function _mdl_ode_AggregateDistributedGenerationA!(
11151118
Iq_neg = -Iq
11161119
I_r = real(complex(Ip_limited, Iq_neg) * exp(im * θ))
11171120
I_i = imag(complex(Ip_limited, Iq_neg) * exp(im * θ))
1118-
current_r[1] = I_r
1119-
current_i[1] = I_i
1121+
current_r[1] = I_r * base_power_ratio
1122+
current_i[1] = I_i * base_power_ratio
11201123
end
11211124

11221125
#Freq_Flag = 1
@@ -1134,6 +1137,7 @@ function _mdl_ode_AggregateDistributedGenerationA!(
11341137
t,
11351138
) where {T <: ACCEPTED_REAL_TYPES}
11361139
sys_ω = global_vars[GLOBAL_VAR_SYS_FREQ_INDEX]
1140+
Sbase = get_system_base_power(dynamic_device)
11371141
Vt = sqrt(voltage_r^2 + voltage_i^2)
11381142

11391143
#Obtain References (from wrapper and device)
@@ -1182,6 +1186,8 @@ function _mdl_ode_AggregateDistributedGenerationA!(
11821186
rrpwr = PSY.get_rrpwr(get_device(dynamic_device))
11831187
Tv = PSY.get_Tv(get_device(dynamic_device))
11841188
Iq_lim = PSY.get_Iq_lim(get_device(dynamic_device))
1189+
basepower = PSY.get_base_power(get_device(dynamic_device))
1190+
base_power_ratio = basepower / Sbase
11851191

11861192
#STATE Vmeas
11871193
_, dVmeas_dt = low_pass_mass_matrix(Vt, Vmeas, 1.0, T_rv)
@@ -1273,6 +1279,6 @@ function _mdl_ode_AggregateDistributedGenerationA!(
12731279
Iq_neg = -Iq
12741280
I_r = real(complex(Ip_limited, Iq_neg) * exp(im * θ))
12751281
I_i = imag(complex(Ip_limited, Iq_neg) * exp(im * θ))
1276-
current_r[1] = I_r
1277-
current_i[1] = I_i
1282+
current_r[1] = I_r * base_power_ratio
1283+
current_i[1] = I_i * base_power_ratio
12781284
end

src/post_processing/post_proc_generator.jl

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
"""
2+
Default function to compute output current.
3+
Returns an error
4+
5+
"""
6+
function compute_output_current(
7+
::SimulationResults,
8+
dynamic_device::I,
9+
::Vector{Float64},
10+
::Vector{Float64},
11+
::Union{Nothing, Float64},
12+
) where {I <: PSY.DynamicInjection}
13+
14+
#Return error
15+
error(
16+
"Output current for device type $(typeof(dynamic_device)) is not implemented yet.",
17+
)
18+
end
19+
120
"""
221
Function to obtain the output current time series of a Dynamic Generator model out of the DAE Solution. It receives the simulation inputs,
322
the dynamic device and bus voltage. It is dispatched for device type to compute the specific current.
@@ -30,6 +49,99 @@ function compute_output_current(
3049
)
3150
end
3251

52+
"""
53+
Function to obtain the output current time series of a AggregateDistributedGenerationA (DERA) model out of the DAE Solution.
54+
It receives the simulation inputs, the dynamic device and bus voltage.
55+
56+
"""
57+
function compute_output_current(
58+
res::SimulationResults,
59+
dynamic_device::PSY.AggregateDistributedGenerationA,
60+
V_R::Vector{Float64},
61+
V_I::Vector{Float64},
62+
dt::Union{Nothing, Float64},
63+
)
64+
65+
#Obtain Data
66+
sys = get_system(res)
67+
Sbase = PSY.get_base_power(sys)
68+
basepower = PSY.get_base_power(dynamic_device)
69+
base_power_ratio = basepower / Sbase
70+
Freq_Flag = PSY.get_Freq_Flag(dynamic_device)
71+
name = PSY.get_name(dynamic_device)
72+
if Freq_Flag == 1
73+
_, Pord = post_proc_state_series(res, (name, :Pord), dt)
74+
_, dPord = post_proc_state_series(res, (name, :dPord), dt)
75+
Tpord = PSY.get_Tpord(dynamic_device)
76+
P_lim = PSY.get_P_lim(dynamic_device)
77+
end
78+
79+
# Get states
80+
θ = atan.(V_I ./ V_R)
81+
ts, Ip = post_proc_state_series(res, (name, :Ip), dt)
82+
ts, Iq = post_proc_state_series(res, (name, :Iq), dt)
83+
_, Mult = post_proc_state_series(res, (name, :Mult), dt)
84+
_, Vmeas = post_proc_state_series(res, (name, :Vmeas), dt)
85+
Iq_neg = -Iq
86+
Ip_cmd = Ip
87+
Iq_cmd = Iq
88+
89+
# Get Params
90+
Tg = PSY.get_Tg(dynamic_device)
91+
rrpwr = PSY.get_rrpwr(dynamic_device)
92+
P_ref = PSY.get_P_ref(dynamic_device)
93+
94+
I_R = similar(Ip)
95+
I_I = similar(Iq)
96+
for (ix, Ip_cmd_val) in enumerate(Ip_cmd)
97+
Ip_min, Ip_max, _, _ = current_limit_logic(dynamic_device, Ip_cmd_val, Iq_cmd[ix])
98+
if Ip[ix] >= 0
99+
Rup = abs(rrpwr)
100+
Rdown = -Inf
101+
else
102+
Rdown = -abs(rrpwr)
103+
Rup = Inf
104+
end
105+
if Freq_Flag == 0
106+
Ip_input = clamp(P_ref / max(Vmeas[ix], 0.01), Ip_min, Ip_max) * Mult[ix]
107+
Ip_limited, _ = low_pass_nonwindup_ramp_limits(
108+
Ip_input,
109+
Ip[ix],
110+
1.0,
111+
Tg,
112+
-Inf,
113+
Inf,
114+
Rdown,
115+
Rup,
116+
)
117+
else
118+
Pord_limited, _ = low_pass_nonwindup_mass_matrix(
119+
dPord[ix],
120+
Pord[ix],
121+
1.0,
122+
Tpord,
123+
P_lim[:min],
124+
P_lim[:max],
125+
)
126+
Ip_input = clamp(Pord_limited / max(Vmeas[ix], 0.01), Ip_min, Ip_max) * Mult[ix]
127+
Ip_limited, _ = low_pass_nonwindup_ramp_limits(
128+
Ip_input,
129+
Ip[ix],
130+
1.0,
131+
Tg,
132+
-Inf,
133+
Inf,
134+
Rdown,
135+
Rup,
136+
)
137+
end
138+
I_R[ix] = real(complex(Ip_limited, Iq_neg[ix]) * exp(im * θ[ix])) * base_power_ratio
139+
I_I[ix] = imag(complex(Ip_limited, Iq_neg[ix]) * exp(im * θ[ix])) * base_power_ratio
140+
end
141+
142+
return ts, I_R, I_I
143+
end
144+
33145
"""
34146
Function to obtain the field current time series of a Dynamic Generator model out of the DAE Solution. It receives the simulation inputs,
35147
the dynamic device and bus voltage. It is dispatched for device type to compute the specific current.

test/test_case42_dera.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ function test_dera_residual(freqflag_value, csv_file, init_cond, eigs_value)
7979
t_psid = get_voltage_angle_series(results, 102)[1]
8080
θ_psid = get_voltage_angle_series(results, 102)[2]
8181
V_psid = get_voltage_magnitude_series(results, 102)[2]
82+
power = get_activepower_series(results, "generator-102-1")
8283

8384
M = get_csv_data(csv_file)
8485
t_psse, V_psse = clean_extra_timestep!(M[:, 1], M[:, 2])
@@ -143,6 +144,7 @@ function test_dera_massmatrix(freqflag_value, csv_file, init_cond, eigs_value)
143144
t_psid = get_voltage_angle_series(results, 102)[1]
144145
θ_psid = get_voltage_angle_series(results, 102)[2]
145146
V_psid = get_voltage_magnitude_series(results, 102)[2]
147+
power = get_activepower_series(results, "generator-102-1")
146148

147149
M = get_csv_data(csv_file)
148150
t_psse, V_psse = clean_extra_timestep!(M[:, 1], M[:, 2])

0 commit comments

Comments
 (0)