@@ -19,10 +19,27 @@ Evaluate the frequency response of a linear system
1919
2020of system `sys` over the frequency vector `w`.
2121"""
22- @autovec () function freqresp (sys:: LTISystem , w_vec:: AbstractVector{<:Real} )
22+ @autovec () function freqresp (sys:: LTISystem , w_vec:: AbstractVector{W} ) where W <: Real
23+ te = timeevol (sys)
24+ ny,nu = noutputs (sys), ninputs (sys)
25+ T = promote_type (Complex{real (numeric_type (sys))}, Complex{W})
26+ R = Array {T, 3} (undef, ny, nu, length (w_vec))
27+ freqresp! (R, sys, w_vec)
28+ end
29+
30+ """
31+ freqresp!(R::Array{T, 3}, sys::LTISystem, w_vec::AbstractVector{<:Real})
32+
33+ In-place version of [`freqresp`](@ref) that takes a pre-allocated array `R` of size (ny, nu, nw)`
34+ """
35+ function freqresp! (R:: Array{T,3} , sys:: LTISystem , w_vec:: AbstractVector{<:Real} ) where T
2336 te = sys. timeevol
2437 ny,nu = noutputs (sys), ninputs (sys)
25- [evalfr (sys[i,j], _freq (w, te))[] for w in w_vec, i in 1 : ny, j in 1 : nu]
38+ @boundscheck size (R) == (ny,nu,length (w_vec))
39+ @inbounds for wi = eachindex (w_vec), ui = 1 : nu, yi = 1 : ny
40+ R[yi,ui,wi] = evalfr (sys[yi,ui], _freq (w_vec[wi], te))[]
41+ end
42+ PermutedDimsArray {T,3,(3,1,2),(2,3,1),Array{T,3}} (R)
2643end
2744
2845@autovec () function freqresp (G:: AbstractMatrix , w_vec:: AbstractVector{<:Real} )
3653_freq (w, :: Continuous ) = complex (0 , w)
3754_freq (w, te:: Discrete ) = cis (w* te. Ts)
3855
39- @autovec () function freqresp (sys:: AbstractStateSpace , w_vec:: AbstractVector{W} ) where W <: Real
56+ function freqresp (sys:: AbstractStateSpace , w_vec:: AbstractVector{W} ) where W <: Real
4057 ny, nu = size (sys)
4158 T = promote_type (Complex{real (eltype (sys. A))}, Complex{W})
59+ R = Array {T, 3} (undef, ny, nu, length (w_vec))
60+ freqresp! (R, sys, w_vec)
61+ end
62+ @autovec () function freqresp! (R:: Array{T,3} , sys:: AbstractStateSpace , w_vec:: AbstractVector{W} ) where {T, W <: Real }
63+ ny, nu = size (sys)
64+ @boundscheck size (R) == (ny,nu,length (w_vec))
4265 PDT = PermutedDimsArray{T,3 ,(3 ,1 ,2 ),(2 ,3 ,1 ),Array{T,3 }}
4366 if sys. nx == 0 # Only D-matrix
44- return PDT (repeat (T .(sys. D), 1 , 1 , length (w_vec)))
67+ @inbounds for i in eachindex (w_vec)
68+ R[:,:,i] .= sys. D
69+ end
70+ return PDT (R)
4571 end
4672 local F, Q
4773 try
4874 F = hessenberg (sys. A)
4975 Q = Matrix (F. Q)
5076 catch e
5177 # For matrix types that do not have a hessenberg implementation, we call the standard version of freqresp.
52- e isa MethodError && return freqresp_nohess ( sys, w_vec)
78+ e isa MethodError && return freqresp_nohess! (R, sys, w_vec)
5379 rethrow ()
5480 end
5581 A = F. H
@@ -58,9 +84,8 @@ _freq(w, te::Discrete) = cis(w*te.Ts)
5884 D = sys. D
5985
6086 te = sys. timeevol
61- R = Array {T, 3} (undef, ny, nu, length (w_vec))
6287 Bc = similar (B, T) # for storage
63- for i in eachindex (w_vec)
88+ @inbounds for i in eachindex (w_vec)
6489 Ri = @views R[:,:,i]
6590 copyto! (Ri,D) # start with the D-matrix
6691 isinf (w_vec[i]) && continue
@@ -72,27 +97,36 @@ _freq(w, te::Discrete) = cis(w*te.Ts)
7297 PDT (R) # PermutedDimsArray doesn't allocate to perform the permutation
7398end
7499
100+ function freqresp_nohess (sys:: AbstractStateSpace , w_vec:: AbstractVector{W} ) where W <: Real
101+ ny, nu = size (sys)
102+ T = promote_type (Complex{real (eltype (sys. A))}, Complex{W})
103+ R = Array {T, 3} (undef, ny, nu, length (w_vec))
104+ freqresp_nohess! (R, sys, w_vec)
105+ end
106+
75107"""
76108 freqresp_nohess(sys::AbstractStateSpace, w_vec::AbstractVector{<:Real})
77109
78110Compute the frequency response of `sys` without forming a Hessenberg factorization.
79111This function is called automatically if the Hessenberg factorization fails.
80112"""
81113freqresp_nohess
82- @autovec () function freqresp_nohess ( sys:: AbstractStateSpace , w_vec:: AbstractVector{W} ) where W <: Real
114+ @autovec () function freqresp_nohess! (R :: Array{T,3} , sys:: AbstractStateSpace , w_vec:: AbstractVector{W} ) where {T, W <: Real }
83115 ny, nu = size (sys)
116+ @boundscheck size (R) == (ny,nu,length (w_vec))
84117 nx = sys. nx
85- T = promote_type (Complex{real (eltype (sys. A))}, Complex{W})
86118 PDT = PermutedDimsArray{T,3 ,(3 ,1 ,2 ),(2 ,3 ,1 ),Array{T,3 }}
87119 if nx == 0 # Only D-matrix
88- return PDT (repeat (T .(sys. D), 1 , 1 , length (w_vec)))
120+ @inbounds for i in eachindex (w_vec)
121+ R[:,:,i] .= sys. D
122+ end
123+ return PDT (R)
89124 end
90125 A,B,C,D = ssdata (sys)
91126 te = sys. timeevol
92- R = Array {T, 3} (undef, ny, nu, length (w_vec))
93127 Ac = (A+ one (T)* I) # for storage
94128 Adiag = diagind (A)
95- for i in eachindex (w_vec)
129+ @inbounds for i in eachindex (w_vec)
96130 Ri = @views R[:,:,i]
97131 copyto! (Ri,D) # start with the D-matrix
98132 isinf (w_vec[i]) && continue
0 commit comments