1- struct NonLinModel{NT<: Real , F<: Function , H<: Function , DS<: DiffSolver } <: SimModel{NT}
1+ struct NonLinModel{
2+ NT<: Real , F<: Function , H<: Function , P<: Any , DS<: DiffSolver
3+ } <: SimModel{NT}
24 x0:: Vector{NT}
35 f!:: F
46 h!:: H
7+ p:: P
58 solver:: DS
9+ k:: Vector{Int}
610 Ts:: NT
711 t:: Vector{NT}
812 nu:: Int
@@ -19,10 +23,11 @@ struct NonLinModel{NT<:Real, F<:Function, H<:Function, DS<:DiffSolver} <: SimMod
1923 dname:: Vector{String}
2024 xname:: Vector{String}
2125 buffer:: SimModelBuffer{NT}
22- function NonLinModel {NT, F, H, DS} (
23- f!:: F , h!:: H , solver :: DS , Ts, nu, nx, ny, nd
24- ) where {NT<: Real , F<: Function , H<: Function , DS<: DiffSolver }
26+ function NonLinModel {NT, F, H, P, DS} (
27+ f!:: F , h!:: H , Ts, nu, nx, ny, nd, p :: P , solver :: DS
28+ ) where {NT<: Real , F<: Function , H<: Function , P <: Any , DS<: DiffSolver }
2529 Ts > 0 || error (" Sampling time Ts must be positive" )
30+ k = [0 ]
2631 uop = zeros (NT, nu)
2732 yop = zeros (NT, ny)
2833 dop = zeros (NT, nd)
@@ -35,11 +40,12 @@ struct NonLinModel{NT<:Real, F<:Function, H<:Function, DS<:DiffSolver} <: SimMod
3540 x0 = zeros (NT, nx)
3641 t = zeros (NT, 1 )
3742 buffer = SimModelBuffer {NT} (nu, nx, ny, nd)
38- return new {NT, F, H, DS} (
43+ return new {NT, F, H, P, DS} (
3944 x0,
40- f!, h!,
45+ f!, h!,
46+ p,
4147 solver,
42- Ts, t,
48+ k, Ts, t,
4349 nu, nx, ny, nd,
4450 uop, yop, dop, xop, fop,
4551 uname, yname, dname, xname,
@@ -49,8 +55,8 @@ struct NonLinModel{NT<:Real, F<:Function, H<:Function, DS<:DiffSolver} <: SimMod
4955end
5056
5157@doc raw """
52- NonLinModel{NT}(f::Function, h::Function, Ts, nu, nx, ny, nd=0; solver=RungeKutta(4))
53- NonLinModel{NT}(f!::Function, h!::Function, Ts, nu, nx, ny, nd=0; solver=RungeKutta(4))
58+ NonLinModel{NT}(f::Function, h::Function, Ts, nu, nx, ny, nd=0; p=[], solver=RungeKutta(4))
59+ NonLinModel{NT}(f!::Function, h!::Function, Ts, nu, nx, ny, nd=0; p=[], solver=RungeKutta(4))
5460
5561Construct a nonlinear model from state-space functions `f`/`f!` and `h`/`h!`.
5662
@@ -59,23 +65,27 @@ continuous dynamics. Use `solver=nothing` for the discrete case (see Extended He
5965functions are defined as:
6066```math
6167\b egin{aligned}
62- \m athbf{ẋ}(t) &= \m athbf{f}\B ig( \m athbf{x}(t), \m athbf{u}(t), \m athbf{d}(t) \B ig) \\
63- \m athbf{y}(t) &= \m athbf{h}\B ig( \m athbf{x}(t), \m athbf{d}(t) \B ig)
68+ \m athbf{ẋ}(t) &= \m athbf{f}\B ig( \m athbf{x}(t), \m athbf{u}(t), \m athbf{d}(t), \m athbf{p}(t), t \B ig) \\
69+ \m athbf{y}(t) &= \m athbf{h}\B ig( \m athbf{x}(t), \m athbf{d}(t), \m athbf{p}(t), t \B ig)
6470\e nd{aligned}
6571```
66- They can be implemented in two possible ways:
67-
68- 1. **Non-mutating functions** (out-of-place): define them as `f(x, u, d) -> ẋ` and
69- `h(x, d) -> y`. This syntax is simple and intuitive but it allocates more memory.
70- 2. **Mutating functions** (in-place): define them as `f!(ẋ, x, u, d) -> nothing` and
71- `h!(y, x, d) -> nothing`. This syntax reduces the allocations and potentially the
72+ where ``\m athbf{x}``, ``\m athbf{y}, ``\m athbf{u}``, ``\m athbf{d}`` and ``\m athbf{p}`` are
73+ respectively the state, output, manipulated input, measured disturbance and parameter vectors,
74+ and ``t`` the time in second. The functions can be implemented in two possible ways:
75+
76+ 1. **Non-mutating functions** (out-of-place): define them as `f(x, u, d, p, t) -> ẋ` and
77+ `h(x, d, p, t) -> y`. This syntax is simple and intuitive but it allocates more memory.
78+ 2. **Mutating functions** (in-place): define them as `f!(ẋ, x, u, d, p, t) -> nothing` and
79+ `h!(y, x, d, p, t) -> nothing`. This syntax reduces the allocations and potentially the
7280 computational burden as well.
7381
7482`Ts` is the sampling time in second. `nu`, `nx`, `ny` and `nd` are the respective number of
75- manipulated inputs, states, outputs and measured disturbances.
83+ manipulated inputs, states, outputs and measured disturbances. The keyword argument `p`
84+ is the parameters of the model passed to the two functions. It can be of any Julia object
85+ but use a mutable type if you want to change them later e.g.: a vector.
7686
7787!!! tip
78- Replace the `d` argument with `_` if `nd = 0` (see Examples below).
88+ Replace the `d`, `p` or `t` argument with `_` if not needed (see Examples below).
7989
8090A 4th order [`RungeKutta`](@ref) solver discretizes the differential equations by default.
8191The rest of the documentation assumes discrete dynamics since all models end up in this
@@ -118,52 +128,58 @@ NonLinModel with a sample time Ts = 2.0 s, empty solver and:
118128 State-space functions are similar for discrete dynamics:
119129 ```math
120130 \b egin{aligned}
121- \m athbf{x}(k+1) &= \m athbf{f}\B ig( \m athbf{x}(k), \m athbf{u}(k), \m athbf{d}(k) \B ig) \\
122- \m athbf{y}(k) &= \m athbf{h}\B ig( \m athbf{x}(k), \m athbf{d}(k) \B ig)
131+ \m athbf{x}(k+1) &= \m athbf{f}\B ig( \m athbf{x}(k), \m athbf{u}(k), \m athbf{d}(k), \m athbf{p}(k), k \B ig) \\
132+ \m athbf{y}(k) &= \m athbf{h}\B ig( \m athbf{x}(k), \m athbf{d}(k), \m athbf{p}(k), k \B ig)
123133 \e nd{aligned}
124134 ```
125135 with two possible implementations as well:
126136
127- 1. **Non-mutating functions**: define them as `f(x, u, d) -> xnext` and `h(x, d) -> y`.
128- 2. **Mutating functions**: define them as `f!(xnext, x, u, d) -> nothing` and
129- `h!(y, x, d) -> nothing`.
137+ 1. **Non-mutating functions**: define them as `f(x, u, d, p, k) -> xnext` and
138+ `h(x, d, p, k) -> y`.
139+ 2. **Mutating functions**: define them as `f!(xnext, x, u, d, p, k) -> nothing` and
140+ `h!(y, x, d, p, k) -> nothing`.
130141"""
131142function NonLinModel {NT} (
132- f:: Function , h:: Function , Ts:: Real , nu:: Int , nx:: Int , ny:: Int , nd:: Int = 0 ;
133- solver= RungeKutta (4 )
143+ f:: Function , h:: Function , Ts:: Real , nu:: Int , nx:: Int , ny:: Int , nd:: Int = 0 ;
144+ p = NT[], solver= RungeKutta (4 )
134145) where {NT<: Real }
135146 isnothing (solver) && (solver= EmptySolver ())
136147 ismutating_f = validate_f (NT, f)
137148 ismutating_h = validate_h (NT, h)
138- f! = ismutating_f ? f : (xnext, x, u, d) -> xnext .= f (x, u, d)
139- h! = ismutating_h ? h : (y, x, d) -> y .= h (x, d)
149+ f! = ismutating_f ? f : f! (xnext, x, u, d, p, k) = ( xnext .= f (x, u, d, p, k); nothing )
150+ h! = ismutating_h ? h : h! (y, x, d, p, k) = ( y .= h (x, d, p, k); nothing )
140151 f!, h! = get_solver_functions (NT, solver, f!, h!, Ts, nu, nx, ny, nd)
141- F, H, DS = get_types (f!, h!, solver)
142- return NonLinModel {NT, F, H, DS} (f!, h!, solver, Ts, nu, nx, ny, nd)
152+ F, H, P, DS = get_types (f!, h!, p , solver)
153+ return NonLinModel {NT, F, H, P, DS} (f!, h!, Ts, nu, nx, ny, nd, p, solver )
143154end
144155
145156function NonLinModel (
146- f:: Function , h:: Function , Ts:: Real , nu:: Int , nx:: Int , ny:: Int , nd:: Int = 0 ;
147- solver= RungeKutta (4 )
157+ f:: Function , h:: Function , Ts:: Real , nu:: Int , nx:: Int , ny:: Int , nd:: Int = 0 ;
158+ p = Float64[], solver= RungeKutta (4 )
148159)
149- return NonLinModel {Float64} (f, h, Ts, nu, nx, ny, nd; solver)
160+ return NonLinModel {Float64} (f, h, Ts, nu, nx, ny, nd; p, solver)
150161end
151162
152163" Get the types of `f!`, `h!` and `solver` to construct a `NonLinModel`."
153- get_types (:: F , :: H , :: DS ) where {F<: Function , H<: Function , DS<: DiffSolver } = F, H, DS
164+ function get_types (
165+ :: F , :: H , :: P , :: DS
166+ ) where {F<: Function , H<: Function , P<: Any , DS<: DiffSolver }
167+ return F, H, P, DS
168+ end
154169
155170"""
156171 validate_f(NT, f) -> ismutating
157172
158173Validate `f` function argument signature and return `true` if it is mutating.
159174"""
160175function validate_f (NT, f)
161- ismutating = hasmethod (f, Tuple{Vector{NT}, Vector{NT}, Vector{NT}, Vector{NT}})
162- if ! (ismutating || hasmethod (f, Tuple{Vector{NT}, Vector{NT}, Vector{NT}}))
176+ ismutating = hasmethod (f, Tuple{Vector{NT}, Vector{NT}, Vector{NT}, Vector{NT}, Any, NT })
177+ if ! (ismutating || hasmethod (f, Tuple{Vector{NT}, Vector{NT}, Vector{NT}, Any, NT }))
163178 error (
164179 " the state function has no method with type signature " *
165- " f(x::Vector{$(NT) }, u::Vector{$(NT) }, d::Vector{$(NT) }) or mutating form " *
166- " f!(xnext::Vector{$(NT) }, x::Vector{$(NT) }, u::Vector{$(NT) }, d::Vector{$(NT) })"
180+ " f(x::Vector{$(NT) }, u::Vector{$(NT) }, d::Vector{$(NT) }, p::Any, t::$(NT) ) or " *
181+ " mutating form f!(xnext::Vector{$(NT) }, x::Vector{$(NT) }, u::Vector{$(NT) }, " *
182+ " d::Vector{$(NT) }, p::Any, t::$(NT) )"
167183 )
168184 end
169185 return ismutating
@@ -175,12 +191,12 @@ end
175191Validate `h` function argument signature and return `true` if it is mutating.
176192"""
177193function validate_h (NT, h)
178- ismutating = hasmethod (h, Tuple{Vector{NT}, Vector{NT}, Vector{NT}})
179- if ! (ismutating || hasmethod (h, Tuple{Vector{NT}, Vector{NT}}))
194+ ismutating = hasmethod (h, Tuple{Vector{NT}, Vector{NT}, Vector{NT}, Any, NT })
195+ if ! (ismutating || hasmethod (h, Tuple{Vector{NT}, Vector{NT}, Any, NT }))
180196 error (
181197 " the output function has no method with type signature " *
182- " h(x::Vector{$(NT) }, d::Vector{$(NT) }) or mutating form " *
183- " h!(y::Vector{$(NT) }, x::Vector{$(NT) }, d::Vector{$(NT) })"
198+ " h(x::Vector{$(NT) }, d::Vector{$(NT) }, p::Any, t:: $(NT) ) or mutating form " *
199+ " h!(y::Vector{$(NT) }, x::Vector{$(NT) }, d::Vector{$(NT) }, p::Any, t:: $(NT) )"
184200 )
185201 end
186202 return ismutating
@@ -189,11 +205,11 @@ end
189205" Do nothing if `model` is a [`NonLinModel`](@ref)."
190206steadystate! (:: SimModel , _ , _ ) = nothing
191207
192- " Call `f!(xnext0, x0, u0, d0)` with `model.f!` method for [`NonLinModel`](@ref)."
193- f! (xnext0, model:: NonLinModel , x0, u0, d0) = model. f! (xnext0, x0, u0, d0)
208+ " Call `f!(xnext0, x0, u0, d0, p, k )` with `model.f!` method for [`NonLinModel`](@ref)."
209+ f! (xnext0, model:: NonLinModel , x0, u0, d0, p, k ) = model. f! (xnext0, x0, u0, d0, p, k )
194210
195- " Call `h!(y0, x0, d0)` with `model.h` method for [`NonLinModel`](@ref)."
196- h! (y0, model:: NonLinModel , x0, d0) = model. h! (y0, x0, d0)
211+ " Call `h!(y0, x0, d0, p, k )` with `model.h` method for [`NonLinModel`](@ref)."
212+ h! (y0, model:: NonLinModel , x0, d0, p, k ) = model. h! (y0, x0, d0, p, k )
197213
198214detailstr (model:: NonLinModel ) = " , $(typeof (model. solver). name. name) solver"
199- detailstr (:: NonLinModel{<:Real, <:Function, <:Function, <:EmptySolver} ) = " , empty solver"
215+ detailstr (:: NonLinModel{<:Real, <:Function, <:Function, <:Any, <: EmptySolver} ) = " , empty solver"
0 commit comments