Skip to content
This repository has been archived by the owner on Jul 17, 2020. It is now read-only.

Commit

Permalink
Merge pull request #54 from Energy-MAC/pll_refactor
Browse files Browse the repository at this point in the history
Pll refactor
  • Loading branch information
jd-lara authored May 1, 2020
2 parents c4cbdf3 + a5c054f commit 48a186a
Show file tree
Hide file tree
Showing 30 changed files with 542 additions and 333 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#Files generated by invoking Julia with --code-coverage
*.jl.cov
*.jl.*.cov
*.log

# Files generated by invoking Julia with --track-allocation
*.jl.mem
Expand Down Expand Up @@ -113,6 +114,5 @@ $RECYCLE.BIN/
# Windows shortcuts
*.lnk


## Acknowledgements
# Many thanks to `https://gitignore.io/`, written and maintained by Joe Blau, which contributed much material to this gitignore file.
5 changes: 3 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
InfrastructureSystems = "2cd47ed4-ca9b-11e9-27f2-ab636a7671f1"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56"
PowerSystems = "bcd98974-b02a-5e2f-9ee0-a103f5c450dd"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[compat]
DiffEqBase = "6"
ForwardDiff = "~v0.10"
InfrastructureSystems = "~0.6"
InfrastructureSystems = "~0.6.3"
NLsolve = "4"
PowerSystems = "~0.16"
PowerSystems = "~0.17"
julia = "^1.2"
1 change: 1 addition & 0 deletions src/LITS.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export get_voltagemag_series
export print_init_states

####################################### Package Imports ####################################
import Logging
import InfrastructureSystems
import DiffEqBase
import ForwardDiff
Expand Down
28 changes: 20 additions & 8 deletions src/base/definitions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,36 +40,48 @@ Inverter Inner Vars:
md_var :: Modulation signal on the d-component
mq_var :: Modulation signal on the q-component
Vdc_var :: DC voltage supplied by the DC source
Vd_filter_var :: Voltage seen in the capacitor of the filter in the d-component
Vq_filter_var :: Voltage seen in the capacitor of the filter in the q-component
Vr_filter_var :: Voltage seen in the capacitor of the filter in the R-component
Vi_filter_var :: Voltage seen in the capacitor of the filter in the I-component
ω_freq_estimator_var :: Frequency estimated by the frequency estimator.
V_oc_var :: Control voltage supplied from the outer loop control to the inner loop
ω_oc_var :: Control frequency supplied from the outer loop control the inner loop
θ_oc_var :: Variation of the angle (PLL or VSM) of the inverter
VR_inv_var :: Real terminal voltage on the inverter
VI_inv_var :: Imaginary terminal voltage on the inverter
Vd_cnv_var :: Voltage supplied from the converter in the d-component
Vq_cnv_var :: Voltage supplied from the converter in the q-component
Vr_cnv_var :: Voltage supplied from the converter in the R-component
Vi_cnv_var :: Voltage supplied from the converter in the I-component
"""

@enum inverter_inner_vars begin
md_var = 1
mq_var = 2
Vdc_var = 3
Vd_filter_var = 4
Vq_filter_var = 5
Vr_filter_var = 4
Vi_filter_var = 5
ω_freq_estimator_var = 6
V_oc_var = 7
ω_oc_var = 8
θ_oc_var = 9
VR_inv_var = 10
VI_inv_var = 11
Vd_cnv_var = 12
Vq_cnv_var = 13
Vr_cnv_var = 12
Vi_cnv_var = 13
end

Base.to_index(ix::inverter_inner_vars) = Int(ix)

@enum dq_ref begin
d = 1
q = 2
end
@enum RI_ref begin
R = 1
I = 2
end

Base.to_index(ix::dq_ref) = Int(ix)
Base.to_index(ix::RI_ref) = Int(ix)

const V_ref_index = 1
const ω_ref_index = 2
const P_ref_index = 3
Expand Down
22 changes: 11 additions & 11 deletions src/base/ports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ end
#### Converter Ports ####
function Ports(::PSY.Converter)
state_input = Vector{Symbol}()
inner_input = [md_var, mq_var, Vdc_var, Vd_cnv_var, Vq_cnv_var]
inner_input = [md_var, mq_var, Vdc_var, Vr_cnv_var, Vi_cnv_var]
return Ports(state_input, inner_input)
end

Expand All @@ -63,34 +63,34 @@ function Ports(::PSY.Filter)
inner_input = [
VR_inv_var,
VI_inv_var,
Vd_cnv_var,
Vq_cnv_var,
Vr_cnv_var,
Vi_cnv_var,
θ_oc_var,
Vd_filter_var,
Vq_filter_var,
Vr_filter_var,
Vi_filter_var,
]
return Ports(state_input, inner_input)
end

#### Freq. Estimator Ports ####

function Ports(::PSY.FrequencyEstimator)
state_input = [:vd_filter, :vq_filter, :θ_oc]
state_input = [:vr_filter, :vi_filter, :θ_oc]
#TODO: Move PLL to PCC, i.e. move v_cap (D'Arco v_o), to inner inputs
inner_input = [Vd_filter_var, Vq_filter_var, θ_oc_var, ω_freq_estimator_var]
inner_input = [Vr_filter_var, Vi_filter_var, θ_oc_var, ω_freq_estimator_var]
return Ports(state_input, inner_input)
end

#### Outer Control Ports ####
function Ports(::PSY.OuterControl)
state_input = [:vd_pll, :vq_pll, :ε_pll, :vd_filter, :vq_filter, :id_filter, :iq_filter]
inner_input = [Vd_filter_var, Vq_filter_var, ω_freq_estimator_var]
state_input = [:vd_pll, :vq_pll, :ε_pll, :vr_filter, :vi_filter, :ir_filter, :ii_filter]
inner_input = [Vr_filter_var, Vi_filter_var, ω_freq_estimator_var]
return Ports(state_input, inner_input)
end

#### Inner Control Ports ####
function Ports(::PSY.InnerControl)
state_input = [:id_filter, :iq_filter, :id_cnv, :iq_cnv, :vd_filter, :vq_filter]
inner_input = [Vd_filter_var, Vq_filter_var, V_oc_var, ω_oc_var]
state_input = [:ir_filter, :ii_filter, :ir_cnv, :ii_cnv, :vr_filter, :vi_filter]
inner_input = [Vr_filter_var, Vi_filter_var, V_oc_var, ω_oc_var]
return Ports(state_input, inner_input)
end
14 changes: 7 additions & 7 deletions src/models/inverter_models/converter_models.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ function mdl_converter_ode!(
#Obtain inner variables for component
md = get_inner_vars(device)[md_var]
mq = get_inner_vars(device)[mq_var]
VDC = get_inner_vars(device)[Vdc_var]
Vdc = get_inner_vars(device)[Vdc_var]
θ_oc = get_inner_vars(device)[θ_oc_var]

#Transform reference frame to grid reference frame
m_ri = dq_ri(θ_oc + pi / 2) * [md; mq]

#Update inner_vars
get_inner_vars(device)[Vd_cnv_var] = md * VDC
get_inner_vars(device)[Vq_cnv_var] = mq * VDC
get_inner_vars(device)[Vr_cnv_var] = m_ri[R] * Vdc
get_inner_vars(device)[Vi_cnv_var] = m_ri[I] * Vdc
end

#TODO: Same as above, but:
## VDC is state of DC source
## IDC is algebraic inner_var output from Vcnv real output power
61 changes: 25 additions & 36 deletions src/models/inverter_models/filter_models.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,14 @@ function mdl_filter_ode!(
P <: PSY.FrequencyEstimator,
}

#Obtain external states inputs for component
#TODO: If converter has dynamics, need to reference states:
#external_ix = device.input_port_mapping[device.converter]
#Vd_cnv = device_states[external_ix[1]]
#Vq_cnv = device_states[external_ix[2]]
external_ix = get_input_port_ix(device, PSY.LCLFilter)
δ = device_states[external_ix[1]]
#external_ix = get_input_port_ix(device, PSY.LCLFilter)
#θ_oc = device_states[external_ix[1]]

#Obtain inner variables for component
V_tR = get_inner_vars(device)[VR_inv_var]
V_tI = get_inner_vars(device)[VI_inv_var]
Vd_cnv = get_inner_vars(device)[Vd_cnv_var]
Vq_cnv = get_inner_vars(device)[Vq_cnv_var]
Vr_cnv = get_inner_vars(device)[Vr_cnv_var]
Vi_cnv = get_inner_vars(device)[Vi_cnv_var]

#Get parameters
filter = PSY.get_filter(device)
Expand All @@ -39,64 +34,58 @@ function mdl_filter_ode!(
rg = PSY.get_rg(filter)
MVABase = PSY.get_inverter_Sbase(device)

#RI to dq transformation
V_dq = ri_dq+ pi / 2) * [V_tR; V_tI]
V_g = sqrt(V_tR^2 + V_tI^2)

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

#Define internal states for filter
internal_states = @view device_states[local_ix]
Id_cnv = internal_states[1]
Iq_cnv = internal_states[2]
Vd_filter = internal_states[3]
Vq_filter = internal_states[4]
Id_filter = internal_states[5]
Iq_filter = internal_states[6]
Ir_cnv = internal_states[1]
Ii_cnv = internal_states[2]
Vr_filter = internal_states[3]
Vi_filter = internal_states[4]
Ir_filter = internal_states[5]
Ii_filter = internal_states[6]

#Inputs (control signals) - N/A

#Compute 6 states ODEs (D'Arco EPSR122 Model)
#Inverter Output Inductor (internal state)
#𝜕id_c/𝜕t
output_ode[local_ix[1]] = (
ωb / lf * Vd_cnv - ωb / lf * Vd_filter - ωb * rf / lf * Id_cnv +
ωb * ω_sys * Iq_cnv
ωb / lf * Vr_cnv - ωb / lf * Vr_filter - ωb * rf / lf * Ir_cnv +
ωb * ω_sys * Ii_cnv
)
#𝜕iq_c/𝜕t
output_ode[local_ix[2]] = (
ωb / lf * Vq_cnv - ωb / lf * Vq_filter - ωb * rf / lf * Iq_cnv -
ωb * ω_sys * Id_cnv
ωb / lf * Vi_cnv - ωb / lf * Vi_filter - ωb * rf / lf * Ii_cnv -
ωb * ω_sys * Ir_cnv
)
#LCL Capacitor (internal state)
#𝜕vd_o/𝜕t
output_ode[local_ix[3]] =
(ωb / cf * Id_cnv - ωb / cf * Id_filter + ωb * ω_sys * Vq_filter)
(ωb / cf * Ir_cnv - ωb / cf * Ir_filter + ωb * ω_sys * Vi_filter)
#𝜕vq_o/𝜕t
output_ode[local_ix[4]] =
(ωb / cf * Iq_cnv - ωb / cf * Iq_filter - ωb * ω_sys * Vd_filter)
(ωb / cf * Ii_cnv - ωb / cf * Ii_filter - ωb * ω_sys * Vr_filter)
#Grid Inductance (internal state)
#𝜕id_o/𝜕t
output_ode[local_ix[5]] = (
ωb / lg * Vd_filter - ωb / lg * V_dq[1] - ωb * rg / lg * Id_filter +
ωb * ω_sys * Iq_filter
ωb / lg * Vr_filter - ωb / lg * V_tR - ωb * rg / lg * Ir_filter +
ωb * ω_sys * Ii_filter
)
#𝜕iq_o/𝜕t (Multiply Vq by -1 to lag instead of lead)
#𝜕iq_o/𝜕t
output_ode[local_ix[6]] = (
ωb / lg * Vq_filter + ωb / lg * (-V_dq[2]) - ωb * rg / lg * Iq_filter -
ωb * ω_sys * Id_filter
ωb / lg * Vi_filter - ωb / lg * V_tI - ωb * rg / lg * Ii_filter -
ωb * ω_sys * Ir_filter
)

#Update inner_vars
get_inner_vars(device)[Vd_filter_var] = Vd_filter
get_inner_vars(device)[Vq_filter_var] = Vq_filter
#TODO: If PLL models at PCC, need to update inner vars:
#get_inner_vars(device)[Vd_filter_var] = V_dq[q::dq_ref]
#get_inner_vars(device)[Vq_filter_var] = V_dq[q::dq_ref]
get_inner_vars(device)[Vr_filter_var] = Vr_filter
get_inner_vars(device)[Vi_filter_var] = Vi_filter

#Compute current from the inverter to the grid
I_RI = (MVABase / sys_Sbase) * dq_ri+ pi / 2) * [Id_filter; Iq_filter]
I_RI = (MVABase / sys_Sbase) * [Ir_filter; Ii_filter]

#Update current
current_r[1] += I_RI[1]
current_i[1] += I_RI[2]
Expand Down
24 changes: 9 additions & 15 deletions src/models/inverter_models/frequency_estimator_models.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,11 @@ function mdl_freq_estimator_ode!(

#Obtain external states inputs for component
external_ix = get_input_port_ix(device, PSY.KauraPLL)
Vd_filter = device_states[external_ix[1]]
Vq_filter = device_states[external_ix[2]]
θ_oc = device_states[external_ix[3]]
Vr_filter = device_states[external_ix[1]]
Vi_filter = device_states[external_ix[2]]

#Obtain inner variables for component
#Vd_filter = device.inner_vars[Vd_filter_var]
#Vq_filter = device.inner_vars[Vq_filter_var]
#θ_oc = device.inner_vars[θ_oc_var]
#V_tR = get_inner_vars(device)[VR_inv_var]
#V_tI = get_inner_vars(device)[VI_inv_var]

#Get parameters
pll_control = PSY.get_freq_estimator(device)
Expand All @@ -40,20 +37,17 @@ function mdl_freq_estimator_ode!(
ϵ_pll = internal_states[3]
θ_pll = internal_states[4]

#Transform to internal dq-PLL reference frame
V_dq_pll = ri_dq(θ_pll + pi / 2) * [Vr_filter; Vi_filter]

#Inputs (control signals)

#Compute 6 states ODEs (D'Arco EPSR122 Model)
#Output Voltage LPF (internal state)
#𝜕vpll_d/𝜕t, D'Arco ESPR122 eqn. 12
output_ode[local_ix[1]] = (
ω_lp * Vd_filter * cos(θ_pll - θ_oc) + ω_lp * Vq_filter * sin(θ_pll - θ_oc) -
ω_lp * vpll_d
)
output_ode[local_ix[1]] = ω_lp * (V_dq_pll[d] - vpll_d)
#𝜕vpll_q/𝜕t, D'Arco ESPR122 eqn. 12
output_ode[local_ix[2]] = (
-ω_lp * Vd_filter * sin(θ_pll - θ_oc) + ω_lp * Vq_filter * cos(θ_pll - θ_oc) -
ω_lp * vpll_q
)
output_ode[local_ix[2]] = ω_lp * (V_dq_pll[q] - vpll_q)
#PI Integrator (internal state)
#𝜕dϵ_pll/𝜕t, D'Arco ESPR122 eqn. 13
output_ode[local_ix[3]] = atan(vpll_q / vpll_d)
Expand Down
Loading

2 comments on commit 48a186a

@jd-lara
Copy link
Member Author

@jd-lara jd-lara commented on 48a186a May 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register()

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/13994

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.3.5 -m "<description of version>" 48a186a585342ea9eb4fb21d853246b61ab899ff
git push origin v0.3.5

Please sign in to comment.