How fast does a model has to be for NMPC

All I am saying is that accurate force control is key for a reliable and efficient kite power system. The more accurate the controller the smaller you can choose the security margins. And the smaller these margins the more energy you can harvest with the same hardware.

Published 22 years ago, Biegler and co-workers managed to solve quite large problems, see Redirecting. I seem to recall that they considered a system with 200 inputs, 800 outputs, and updated this multiple times per second (or maybe my memory serves me poorly…). I seem to recall that they used some Schur decomposition algorithm in their optimization code. Also, I think they only considered problems with constraints in the control inputs, which greatly simplifies the problem (avoiding infeasibility).

1 Like

Linear quadratic MPC is much easier and more reliable than nonlinear MPC with arbitrary constraints.

2 Likes

Good overview. One more “constraint” wrt. how fast one can make the system – this may not apply for the case in question, of course:

  • Does the system have unstable zero dynamics/is it non-minimum phase?

The following response is typical in hydropower systems:

The inverse response is due to a transmission zero at s=+0.5 (time in seconds), and to get a stable closed loop with MPC, a minimum requirement is that the horizon goes beyond the dip/inverse response.

Multivariable systems may also have unstable zero dynamics, e.g., the Four Tank laboratory case developed at Lund University 2-3 decades ago.

[With “pole placement” type control, and generalizations to nonlinear systems, the closed loop system can be made arbitrarily fast, but then will have virtually zero robustness wrt. model error. For optimal control based systems, transmission zeros (or rather: some invariant zero types) put constraints on the closed loop system, see, e.g., H. Kwakernaak and R. Sivan’s classic book Linear Optimal Control Systems from 1972.]

1 Like

I coded up a bunch of rules-of-thumb as an automatic check for ControlSystems, maybe I should add a mention about prediction horizon for MPC in the verbose output here.

6 Likes

I did some testing here: GitHub - Albatross-Kite-Transport/KitePredictiveControl.jl

I found out the following:

The model is too slow for NMPC with the KiteModels.jl model combined with RungeKutta(4) with supersampling.

Luckily, linearizing the model solves the speed problem. And this can be combined easily with online linearization, like @franckgaga suggested. Linearizing the kite model takes around 5 seconds, so this would not be done every timestep. But it doesn’t look like it is needed every timestep.

2 Likes

How many states does your model have? I think my KPS4 model is a lot simpler, isn’t it? I need about 66 states for the 6 segment, one line version.

I have 70 states for the 2-segment version of the 3 line model.

1 Like

Please double check if there is a way to make the linearization faster. The second time should already be much faster than the first time.

@franckgaga should know this better than me, but I think it depends on the speed of the nonlinear solver. If so, will there be faster solvers anytime soon?

The 5s linearization time is when running linearize multiple times.

Edit: when using Profileview, I can see that linearize! spends a lot of time in calculating the jacobians with RungeKutta. Because the kite model is quite stiff, it needs a lot of supersampling, which makes RungeKutta slow. As I understand it, a solver better suited for stiff models would speed up linearization significantly.

You could try to use an integrator that handles stiff systems, like SeeToDee.SimpleColloc. If you do, make note of the tip

Info "Differentiation" For fast automatic differentiation through this solver
1 Like

Yes, you can try the to use a custom ODE solver (a.k.a integrator). You will need to define your system as a discrete one in MPC.jl, using the solver=nothing option.

1 Like

I don’t fully understand how. I get that I should do

model = setname!(NonLinModel(f!, h!, Ts, nu, nx, ny, solver=nothing); u=vu, x=vx, y=vy)

But where do I use the SeeToDee integrator? As an argument when running linearize?

You discretize f! with the integrator and then pass the discretize dynamics function instead of f!

2 Likes

Did you get it to work? If you did, did it get any faster?

I am getting this error when linearizing…

linearize
┌ Warning: Potential Rank Deficient Matrix Detected. Attempting to solve using Pivoted QR Factorization.
└ @ NonlinearSolve ~/.julia/packages/NonlinearSolve/sBl1H/src/internal/linear_solve.jl:156
ERROR: LoadError: SingularException(350)
Stacktrace:
  [1] generic_trimatdiv!(C::SubArray{…}, uploc::Char, isunitc::Char, tfun::typeof(identity), A::SubArray{…}, B::SubArray{…})
    @ LinearAlgebra ~/.julia/juliaup/julia-1.10.5+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/triangular.jl:1141
  [2] _ldiv!
    @ ~/.julia/juliaup/julia-1.10.5+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/triangular.jl:752 [inlined]
  [3] ldiv!
    @ ~/.julia/juliaup/julia-1.10.5+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/triangular.jl:757 [inlined]
  [4] ldiv!(A::QR{ForwardDiff.Dual{…}, Matrix{…}, Vector{…}}, B::Matrix{ForwardDiff.Dual{…}})
    @ LinearAlgebra ~/.julia/juliaup/julia-1.10.5+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/qr.jl:669
  [5] ldiv!
    @ ~/.julia/juliaup/julia-1.10.5+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/qr.jl:673 [inlined]
  [6] ldiv!(A::QRPivoted{ForwardDiff.Dual{…}, Matrix{…}, Vector{…}, Vector{…}}, b::Vector{ForwardDiff.Dual{…}})
    @ LinearAlgebra ~/.julia/juliaup/julia-1.10.5+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/qr.jl:678
  [7] ldiv!(Y::Vector{…}, A::QRPivoted{…}, B::Base.ReinterpretArray{…})
    @ LinearAlgebra ~/.julia/juliaup/julia-1.10.5+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/factorization.jl:168
  [8] _ldiv!
    @ ~/.julia/packages/LinearSolve/0Q5jw/src/factorization.jl:11 [inlined]
  [9] macro expansion
    @ ~/.julia/packages/LinearSolve/0Q5jw/src/LinearSolve.jl:167 [inlined]
 [10] solve!(cache::LinearSolve.LinearCache{…}, alg::LinearSolve.QRFactorization{…}; kwargs::@Kwargs{})
    @ LinearSolve ~/.julia/packages/LinearSolve/0Q5jw/src/LinearSolve.jl:151
 [11] solve!
    @ ~/.julia/packages/LinearSolve/0Q5jw/src/LinearSolve.jl:151 [inlined]
 [12] #solve!#8
    @ ~/.julia/packages/LinearSolve/0Q5jw/src/common.jl:274 [inlined]
 [13] solve!(::LinearSolve.LinearCache{…})
    @ LinearSolve ~/.julia/packages/LinearSolve/0Q5jw/src/common.jl:273
 [14] (::NonlinearSolve.LinearSolverCache{…})(; A::Matrix{…}, b::Base.ReinterpretArray{…}, linu::Vector{…}, du::Vector{…}, p::Nothing, weight::Nothing, cachedata::Nothing, reuse_A_if_factorization::Bool, verbose::Bool, kwargs::@Kwargs{})
    @ NonlinearSolve ~/.julia/packages/NonlinearSolve/sBl1H/src/internal/linear_solve.jl:173
 [15] LinearSolverCache
    @ ~/.julia/packages/NonlinearSolve/sBl1H/src/internal/linear_solve.jl:120 [inlined]
 [16] __internal_solve!(cache::NonlinearSolve.NewtonDescentCache{…}, J::Matrix{…}, fu::Base.ReinterpretArray{…}, u::Base.ReinterpretArray{…}, idx::Val{…}; skip_solve::Bool, new_jacobian::Bool, kwargs::@Kwargs{})
    @ NonlinearSolve ~/.julia/packages/NonlinearSolve/sBl1H/src/descent/newton.jl:84
 [17] __internal_solve! (repeats 2 times)
    @ ~/.julia/packages/NonlinearSolve/sBl1H/src/descent/newton.jl:74 [inlined]
 [18] __step!(cache::NonlinearSolve.GeneralizedFirstOrderAlgorithmCache{…}; recompute_jacobian::Nothing, kwargs::@Kwargs{})
    @ NonlinearSolve ~/.julia/packages/NonlinearSolve/sBl1H/src/core/generalized_first_order.jl:245
 [19] __step!
    @ ~/.julia/packages/NonlinearSolve/sBl1H/src/core/generalized_first_order.jl:226 [inlined]
 [20] #step!#131
    @ ~/.julia/packages/NonlinearSolve/sBl1H/src/core/generic.jl:50 [inlined]
 [21] step!
    @ ~/.julia/packages/NonlinearSolve/sBl1H/src/core/generic.jl:45 [inlined]
 [22] solve!(cache::NonlinearSolve.GeneralizedFirstOrderAlgorithmCache{…})
    @ NonlinearSolve ~/.julia/packages/NonlinearSolve/sBl1H/src/core/generic.jl:13
 [23] __solve(::NonlinearProblem{…}, ::GeneralizedFirstOrderAlgorithm{…}; stats::SciMLBase.NLStats, kwargs::@Kwargs{…})
    @ NonlinearSolve ~/.julia/packages/NonlinearSolve/sBl1H/src/core/generic.jl:4
 [24] solve_call(_prob::NonlinearProblem{…}, args::GeneralizedFirstOrderAlgorithm{…}; merge_callbacks::Bool, kwargshandle::Nothing, kwargs::@Kwargs{…})
    @ DiffEqBase ~/.julia/packages/DiffEqBase/vscDj/src/solve.jl:612
 [25] solve_up(prob::NonlinearProblem{…}, sensealg::Nothing, u0::Base.ReinterpretArray{…}, p::Tuple{…}, args::GeneralizedFirstOrderAlgorithm{…}; kwargs::@Kwargs{…})
    @ DiffEqBase ~/.julia/packages/DiffEqBase/vscDj/src/solve.jl:1076
 [26] solve(prob::NonlinearProblem{…}, args::GeneralizedFirstOrderAlgorithm{…}; sensealg::Nothing, u0::Nothing, p::Nothing, wrap::Val{…}, kwargs::@Kwargs{…})
    @ DiffEqBase ~/.julia/packages/DiffEqBase/vscDj/src/solve.jl:1064
 [27] (::SimpleColloc{…})(x0::Vector{…}, u::Vector{…}, p::Vector{…}, t::Float64; abstol::Float64)
    @ SeeToDee ~/.julia/packages/SeeToDee/t9mPJ/src/SeeToDee.jl:259
 [28] (::SimpleColloc{…})(x0::Vector{…}, u::Vector{…}, p::Vector{…}, t::Float64)
    @ SeeToDee ~/.julia/packages/SeeToDee/t9mPJ/src/SeeToDee.jl:249
 [29] (::var"#f!#21"{SimpleColloc{…}, Vector{…}})(dx::Vector{ForwardDiff.Dual{…}}, x::Vector{ForwardDiff.Dual{…}}, u::Vector{Float64}, ::Vector{Float64}, ::Vector{Float64})
    @ Main ~/Code/KitePredictiveControl.jl/src/mtk_interface.jl:19
 [30] f!(xnext0::Vector{…}, model::NonLinModel{…}, x0::Vector{…}, u0::Vector{…}, d0::Vector{…}, p::Vector{…})
    @ ModelPredictiveControl ~/.julia/packages/ModelPredictiveControl/0rhFm/src/model/nonlinmodel.jl:208
 [31] (::ModelPredictiveControl.var"#myf_x0!#35"{Float64, NonLinModel{…}, Vector{…}, Vector{…}, NonLinModel{…}})(xnext0::Vector{ForwardDiff.Dual{…}}, x0::Vector{ForwardDiff.Dual{…}})
    @ ModelPredictiveControl ~/.julia/packages/ModelPredictiveControl/0rhFm/src/model/linearization.jl:124
 [32] chunk_mode_jacobian!(result::Matrix{…}, f!::ModelPredictiveControl.var"#myf_x0!#35"{…}, y::Vector{…}, x::Vector{…}, cfg::ForwardDiff.JacobianConfig{…})
    @ ForwardDiff ~/.julia/packages/ForwardDiff/PcZ48/src/jacobian.jl:183
 [33] jacobian!(result::Matrix{Float64}, f!::Function, y::Vector{Float64}, x::Vector{Float64}, cfg::ForwardDiff.JacobianConfig{ForwardDiff.Tag{…}, Float64, 12, Tuple{…}}, ::Val{true})
    @ ForwardDiff ~/.julia/packages/ForwardDiff/PcZ48/src/jacobian.jl:80
 [34] jacobian!(result::Matrix{Float64}, f!::Function, y::Vector{Float64}, x::Vector{Float64}, cfg::ForwardDiff.JacobianConfig{ForwardDiff.Tag{…}, Float64, 12, Tuple{…}})
    @ ForwardDiff ~/.julia/packages/ForwardDiff/PcZ48/src/jacobian.jl:76
 [35] linearize!(linmodel::LinModel{…}, model::NonLinModel{…}; x::Vector{…}, u::Vector{…}, d::Vector{…})
    @ ModelPredictiveControl ~/.julia/packages/ModelPredictiveControl/0rhFm/src/model/linearization.jl:129
 [36] linearize!
    @ ~/.julia/packages/ModelPredictiveControl/0rhFm/src/model/linearization.jl:110 [inlined]
 [37] linearize(model::NonLinModel{Float64, var"#f!#21"{…}, var"#h!#22"{…}, Vector{…}, ModelPredictiveControl.EmptySolver}; kwargs::@Kwargs{})
    @ ModelPredictiveControl ~/.julia/packages/ModelPredictiveControl/0rhFm/src/model/linearization.jl:87
 [38] linearize(model::NonLinModel{Float64, var"#f!#21"{…}, var"#h!#22"{…}, Vector{…}, ModelPredictiveControl.EmptySolver})
    @ ModelPredictiveControl ~/.julia/packages/ModelPredictiveControl/0rhFm/src/model/linearization.jl:75
 [39] macro expansion
    @ ./timing.jl:279 [inlined]
 [40] top-level scope
    @ ~/Code/KitePredictiveControl.jl/src/KitePredictiveControl.jl:269
 [41] include(fname::String)
    @ Base.MainInclude ./client.jl:489
 [42] top-level scope
    @ REPL[30]:1
f_disc = SimpleColloc(f_ip, Ts, nx, 0, nu; n = 5, abstol = 1.0e-4, solver=NewtonRaphson(), residual=true)
@time linmodel = ModelPredictiveControl.linearize(model)

Edit: and when trying to simulate, I get another error:

@time res = sim!(model, 10, zeros(3))
ERROR: LoadError: Failed to automatically detect ForwardDiff compatability of
the parameter object.

Any idea how to fix this?

You should most likely use residual = false since your function f! computes \dot x and not

0 = F(\dot x, x, u, p, t)

I would also use a tighter tolerance, abstol = 1.0e-4 may not be tight enough.

2 Likes

With residual=false and tighter tolerance I am getting the following error when trying to linearize using either the SeeToDee.linearize or MPC.linearize.

julia> SeeToDee.linearize(f_disc, x_0, ones(3), par, 10.0);
ERROR: MethodError: Cannot `convert` an object of type Vector{ForwardDiff.Dual{ForwardDiff.Tag{SeeToDee.var"#1#3"{SimpleColloc{typeof(f_oop), Float64, UnitRange{Int64}, UnitRange{Int64}, Matrix{Float64}, Vector{Float64}, Tuple{PreallocationTools.DiffCache{Vector{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}}, NonlinearProblem{Matrix{Float64}, false, SciMLBase.NullParameters, NonlinearFunction{false, SciMLBase.FullSpecialize, typeof(SeeToDee.coldyn), UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED_NO_TIME), Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardNonlinearProblem}, GeneralizedFirstOrderAlgorithm{nothing, :NewtonRaphson, NoLineSearch{Bool}, Missing, NewtonDescent{Nothing, typeof(NonlinearSolve.DEFAULT_PRECS)}, Nothing, Nothing, Nothing}}, Vector{Float64}, Tuple{Vector{Float64}, Float64}}, Float64}, Float64, 12}} to an object of type Base.ReinterpretArray{ForwardDiff.Dual{ForwardDiff.Tag{SeeToDee.var"#1#3"{SimpleColloc{typeof(f_oop), Float64, UnitRange{Int64}, UnitRange{Int64}, Matrix{Float64}, Vector{Float64}, Tuple{PreallocationTools.DiffCache{Vector{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}}, NonlinearProblem{Matrix{Float64}, false, SciMLBase.NullParameters, NonlinearFunction{false, SciMLBase.FullSpecialize, typeof(SeeToDee.coldyn), UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED_NO_TIME), Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardNonlinearProblem}, GeneralizedFirstOrderAlgorithm{nothing, :NewtonRaphson, NoLineSearch{Bool}, Missing, NewtonDescent{Nothing, typeof(NonlinearSolve.DEFAULT_PRECS)}, Nothing, Nothing, Nothing}}, Vector{Float64}, Tuple{Vector{Float64}, Float64}}, Float64}, Float64, 12}, 1, Float64, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, false}

And still getting the same error when trying to simulate using the nonlinear model:

ERROR: Failed to automatically detect ForwardDiff compatability of
the parameter object. In order for ForwardDiff.jl automatic
differentiation to work on a solution object, the state of
the differential equation or nonlinear solve (`u0`) needs to
be converted to a Dual type which matches the values being
differentiated. For example, for a loss function loss(p)
where `p`` is a `Vector{Float64}`, this conversion is
equivalent to:

\```
# Convert u0 to match the new Dual element type of `p`
_prob = remake(prob, u0 = eltype(p).(prob.u0))
\```

Is it correct that I set na to zero in SimpleColloc()?

It seems to be related to NonlinearSolve.jl calls that cannot be differentiated through ForwardDiff.jl. Normally there is additional informations in the stacktrace after the

ERROR: MethodError: Cannot `convert` an object of type Vector{ForwardDiff.Dual{ForwardDiff.Tag{SeeToDee.var"#1#3"{SimpleColloc{typeof(f_oop), Float64, UnitRange{Int64}, UnitRange{Int64}, Matrix{Float64}, Vector{Float64}, Tuple{PreallocationTools.DiffCache{Vector{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}}, NonlinearProblem{Matrix{Float64}, false, SciMLBase.NullParameters, NonlinearFunction{false, SciMLBase.FullSpecialize, typeof(SeeToDee.coldyn), UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED_NO_TIME), Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardNonlinearProblem}, GeneralizedFirstOrderAlgorithm{nothing, :NewtonRaphson, NoLineSearch{Bool}, Missing, NewtonDescent{Nothing, typeof(NonlinearSolve.DEFAULT_PRECS)}, Nothing, Nothing, Nothing}}, Vector{Float64}, Tuple{Vector{Float64}, Float64}}, Float64}, Float64, 12}} to an object of type Base.ReinterpretArray{ForwardDiff.Dual{ForwardDiff.Tag{SeeToDee.var"#1#3"{SimpleColloc{typeof(f_oop), Float64, UnitRange{Int64}, UnitRange{Int64}, Matrix{Float64}, Vector{Float64}, Tuple{PreallocationTools.DiffCache{Vector{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}}, NonlinearProblem{Matrix{Float64}, false, SciMLBase.NullParameters, NonlinearFunction{false, SciMLBase.FullSpecialize, typeof(SeeToDee.coldyn), UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED_NO_TIME), Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardNonlinearProblem}, GeneralizedFirstOrderAlgorithm{nothing, :NewtonRaphson, NoLineSearch{Bool}, Missing, NewtonDescent{Nothing, typeof(NonlinearSolve.DEFAULT_PRECS)}, Nothing, Nothing, Nothing}}, Vector{Float64}, Tuple{Vector{Float64}, Float64}}, Float64}, Float64, 12}, 1, Float64, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, false}

line. Can you paste the rest of the stacktrace here?

edit: yes na should be 0.

1 Like
julia> SeeToDee.linearize(f_disc, x_0, ones(3), par, 10.0);
ERROR: MethodError: Cannot `convert` an object of type Vector{ForwardDiff.Dual{ForwardDiff.Tag{SeeToDee.var"#1#3"{SimpleColloc{typeof(f_oop), Float64, UnitRange{Int64}, UnitRange{Int64}, Matrix{Float64}, Vector{Float64}, Tuple{PreallocationTools.DiffCache{Vector{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}}, NonlinearProblem{Matrix{Float64}, false, SciMLBase.NullParameters, NonlinearFunction{false, SciMLBase.FullSpecialize, typeof(SeeToDee.coldyn), UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED_NO_TIME), Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardNonlinearProblem}, GeneralizedFirstOrderAlgorithm{nothing, :NewtonRaphson, NoLineSearch{Bool}, Missing, NewtonDescent{Nothing, typeof(NonlinearSolve.DEFAULT_PRECS)}, Nothing, Nothing, Nothing}}, Vector{Float64}, Tuple{Vector{Float64}, Float64}}, Float64}, Float64, 12}} to an object of type Base.ReinterpretArray{ForwardDiff.Dual{ForwardDiff.Tag{SeeToDee.var"#1#3"{SimpleColloc{typeof(f_oop), Float64, UnitRange{Int64}, UnitRange{Int64}, Matrix{Float64}, Vector{Float64}, Tuple{PreallocationTools.DiffCache{Vector{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}, PreallocationTools.DiffCache{Matrix{Float64}, Vector{Float64}}}, NonlinearProblem{Matrix{Float64}, false, SciMLBase.NullParameters, NonlinearFunction{false, SciMLBase.FullSpecialize, typeof(SeeToDee.coldyn), UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED_NO_TIME), Nothing, Nothing, Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}, SciMLBase.StandardNonlinearProblem}, GeneralizedFirstOrderAlgorithm{nothing, :NewtonRaphson, NoLineSearch{Bool}, Missing, NewtonDescent{Nothing, typeof(NonlinearSolve.DEFAULT_PRECS)}, Nothing, Nothing, Nothing}}, Vector{Float64}, Tuple{Vector{Float64}, Float64}}, Float64}, Float64, 12}, 1, Float64, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, false}

Closest candidates are:
  convert(::Type{T}, ::T) where T
   @ Base Base.jl:84
  convert(::Type{T}, ::Factorization) where T<:AbstractArray
   @ LinearAlgebra ~/.julia/juliaup/julia-1.10.5+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/factorization.jl:108
  convert(::Type{T}, ::T) where T<:AbstractArray
   @ Base abstractarray.jl:16
  ...

Stacktrace:
  [1] setproperty!(x::NonlinearSolve.GeneralizedFirstOrderAlgorithmCache{…}, f::Symbol, v::Vector{…})
    @ Base ./Base.jl:40
  [2] set_u!(cache::NonlinearSolve.GeneralizedFirstOrderAlgorithmCache{…}, u::Vector{…})
    @ NonlinearSolve ~/.julia/packages/NonlinearSolve/sBl1H/src/abstract_types.jl:240
  [3] update_from_termination_cache!(tc_cache::DiffEqBase.NonlinearTerminationModeCache{…}, cache::NonlinearSolve.GeneralizedFirstOrderAlgorithmCache{…}, ::AbsSafeBestTerminationMode{…}, u::Base.ReinterpretArray{…})
    @ NonlinearSolve ~/.julia/packages/NonlinearSolve/sBl1H/src/internal/termination.jl:57
  [4] check_and_update!
    @ ~/.julia/packages/NonlinearSolve/sBl1H/src/internal/termination.jl:37 [inlined]
  [5] check_and_update!
    @ ~/.julia/packages/NonlinearSolve/sBl1H/src/internal/termination.jl:30 [inlined]
  [6] check_and_update!
    @ ~/.julia/packages/NonlinearSolve/sBl1H/src/internal/termination.jl:26 [inlined]
  [7] __step!(cache::NonlinearSolve.GeneralizedFirstOrderAlgorithmCache{…}; recompute_jacobian::Nothing, kwargs::@Kwargs{})
    @ NonlinearSolve ~/.julia/packages/NonlinearSolve/sBl1H/src/core/generalized_first_order.jl:317
  [8] __step!
    @ ~/.julia/packages/NonlinearSolve/sBl1H/src/core/generalized_first_order.jl:226 [inlined]
  [9] #step!#131
    @ ~/.julia/packages/NonlinearSolve/sBl1H/src/core/generic.jl:50 [inlined]
 [10] step!
    @ ~/.julia/packages/NonlinearSolve/sBl1H/src/core/generic.jl:45 [inlined]
 [11] solve!(cache::NonlinearSolve.GeneralizedFirstOrderAlgorithmCache{…})
    @ NonlinearSolve ~/.julia/packages/NonlinearSolve/sBl1H/src/core/generic.jl:13
 [12] __solve(::NonlinearProblem{…}, ::GeneralizedFirstOrderAlgorithm{…}; stats::SciMLBase.NLStats, kwargs::@Kwargs{…})
    @ NonlinearSolve ~/.julia/packages/NonlinearSolve/sBl1H/src/core/generic.jl:4
 [13] solve_call(_prob::NonlinearProblem{…}, args::GeneralizedFirstOrderAlgorithm{…}; merge_callbacks::Bool, kwargshandle::Nothing, kwargs::@Kwargs{…})
    @ DiffEqBase ~/.julia/packages/DiffEqBase/uqSeD/src/solve.jl:612
 [14] solve_up(prob::NonlinearProblem{…}, sensealg::Nothing, u0::Base.ReinterpretArray{…}, p::Tuple{…}, args::GeneralizedFirstOrderAlgorithm{…}; kwargs::@Kwargs{…})
    @ DiffEqBase ~/.julia/packages/DiffEqBase/uqSeD/src/solve.jl:1084
 [15] solve(prob::NonlinearProblem{…}, args::GeneralizedFirstOrderAlgorithm{…}; sensealg::Nothing, u0::Nothing, p::Nothing, wrap::Val{…}, kwargs::@Kwargs{…})
    @ DiffEqBase ~/.julia/packages/DiffEqBase/uqSeD/src/solve.jl:1072
 [16] (::SimpleColloc{…})(x0::Vector{…}, u::Vector{…}, p::Vector{…}, t::Float64; abstol::Float64)
    @ SeeToDee ~/.julia/packages/SeeToDee/t9mPJ/src/SeeToDee.jl:259
 [17] (::SimpleColloc{…})(x0::Vector{…}, u::Vector{…}, p::Vector{…}, t::Float64)
    @ SeeToDee ~/.julia/packages/SeeToDee/t9mPJ/src/SeeToDee.jl:249
 [18] (::SeeToDee.var"#1#3"{SimpleColloc{…}, Vector{…}, Tuple{…}})(x::Vector{ForwardDiff.Dual{…}})
    @ SeeToDee ~/.julia/packages/SeeToDee/t9mPJ/src/SeeToDee.jl:17
 [19] chunk_mode_jacobian(f::SeeToDee.var"#1#3"{SimpleColloc{…}, Vector{…}, Tuple{…}}, x::Vector{Float64}, cfg::ForwardDiff.JacobianConfig{ForwardDiff.Tag{…}, Float64, 12, Vector{…}})
    @ ForwardDiff ~/.julia/packages/ForwardDiff/PcZ48/src/jacobian.jl:183
 [20] jacobian(f::Function, x::Vector{Float64}, cfg::ForwardDiff.JacobianConfig{ForwardDiff.Tag{SeeToDee.var"#1#3"{…}, Float64}, Float64, 12, Vector{ForwardDiff.Dual{…}}}, ::Val{true})
    @ ForwardDiff ~/.julia/packages/ForwardDiff/PcZ48/src/jacobian.jl:23
 [21] jacobian(f::Function, x::Vector{Float64}, cfg::ForwardDiff.JacobianConfig{ForwardDiff.Tag{SeeToDee.var"#1#3"{…}, Float64}, Float64, 12, Vector{ForwardDiff.Dual{…}}})
    @ ForwardDiff ~/.julia/packages/ForwardDiff/PcZ48/src/jacobian.jl:19
 [22] linearize(::SimpleColloc{…}, ::Vector{…}, ::Vector{…}, ::Vector{…}, ::Vararg{…})
    @ SeeToDee ~/.julia/packages/SeeToDee/t9mPJ/src/SeeToDee.jl:17
 [23] top-level scope
    @ REPL[59]:1
Some type information was truncated. Use `show(err)` to see complete types.