# How to fix some parameters when least-squares-fitting using \`NonlinearSolve\`?

**URL:** <https://discourse.julialang.org/t/how-to-fix-some-parameters-when-least-squares-fitting-using-nonlinearsolve/124451>\
**Category:** General Usage\
**Tags:** question\
**Created:** [January 5, 2025, 4:05pm UTC](https://discourse.julialang.org/t/how-to-fix-some-parameters-when-least-squares-fitting-using-nonlinearsolve/124451 "2025-01-05T16:05:01Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![thudjx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thudjx/32/15231_2.png) [@thudjx](https://discourse.julialang.org/u/thudjx)\
**Post date:** [January 5, 2025, 4:05pm UTC](https://discourse.julialang.org/t/how-to-fix-some-parameters-when-least-squares-fitting-using-nonlinearsolve/124451/1 "2025-01-05T16:05:01Z")

</div>

I have 2 questions:

1. I find there are two different practices when performing lsqfit. One defines a function without a sideeffect, as done [here](https://discourse.julialang.org/t/curve-fitting-with-nonlinearsolve-jl/119238/10); the other defines a function that mutates a predefined variable, examplified [here](https://discourse.julialang.org/t/least-squares-with-sciml-nonlinearsolve-jl-how-to/113074/14). I think there are some performance differences. Except this, is there some other differences I should know before using any of them?
2. In the syntax of `LsqFit`, I can easily fix some of the parameters of the model I have defined, e.g., [through a template lambda](https://discourse.julialang.org/t/how-to-pass-additional-parameters-to-curve-fit-in-julia/103031/3). Is there similar syntax of `NonlinearSolve` to avoid redefine the form the model?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 5, 2025, 7:05pm UTC](https://discourse.julialang.org/t/how-to-fix-some-parameters-when-least-squares-fitting-using-nonlinearsolve/124451/2 "2025-01-05T19:05:22Z")

</div>

> [@thudjx](#):
>
> the other defines a function that mutates a predefined variable, examplified [here](https://discourse.julialang.org/t/least-squares-with-sciml-nonlinearsolve-jl-how-to/113074/14)

~~This example does not mutate a pre-defined variable~~ Sorry, I was looking at the wrong link.

Avoiding allocations (i.e. allocating your temporary arrays once, and using an API where the caller passes in a buffer to mutate) often helps performance.

> [@thudjx](#):
>
> In the syntax of `LsqFit`, I can easily fix some of the parameters of the model I have defined, e.g., [through a template lambda](https://discourse.julialang.org/t/how-to-pass-additional-parameters-to-curve-fit-in-julia/103031/3). Is there similar syntax of `NonlinearSolve` to avoid redefine the form the model?

This syntax is not specific to LsqFit — you can pass a closure (an anonymous function) to any higher-order function, and use it to capture additional parameters or fix some fo the parameters of the model.

However, if you want to use the caller-supplied buffer in-place API, your closure will need to be a little more complicated in order to change the number of parameters. (You will need to pre-allocate a buffer of the correct size, and your closure will need to copy to/from the buffer.)

---

<div class="post-metadata">

**Author:** ![thudjx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thudjx/32/15231_2.png) [@thudjx](https://discourse.julialang.org/u/thudjx)\
**Post date:** [January 6, 2025, 2:04am UTC](https://discourse.julialang.org/t/how-to-fix-some-parameters-when-least-squares-fitting-using-nonlinearsolve/124451/3 "2025-01-06T02:04:32Z")

</div>

Thanks for you reply!

In fact, what I am trying to do is as following:

```julia
# -- define the model --
function expmodel(x, u)
    y0, a, τ, t₀ = u
    return y0 + a * exp(-(x-t₀)/τ)
end
# and unified residual function
function residualfn!(du, u, data)
    (xs, ys) = data   
    du .= expmodel.(xs, Ref(u)) .- ys
    return nothing
end

# -- so that I can fix arbitary parameter at ease --
# -- generate data --
Random.seed!(3465)
y0, a, τ, t₀ = 0.0, 1.0, 2.0, 0
xs = 0:0.1:3;
ys0 = expmodel.(xs, Ref([y0, a, τ, t₀])) # ideal data
ys = ys0 .+ randn(size(ys0)) .* 0.02 # add noise
# -- fit --
prob1 = NonlinearLeastSquaresProblem(
        NonlinearFunction((du, u, data) -> residualfn!([du; 0.0], [u; t₀], data), resid_prototype = similar(ys)), [y0, a, τ], (xs, ys))

prob2 = NonlinearLeastSquaresProblem(
        NonlinearFunction((du, u, data) -> residualfn!([du[1:2]; 0.0; du[3]], [u[1:2]; t₀; u[3]], data), resid_prototype = similar(ys)), [y0, a, t₀], (xs, ys))

prob3 = NonlinearLeastSquaresProblem(
        NonlinearFunction((du, u, data) -> residualfn!([du; 0.0; 0.0], [u[1:2]; τ; t₀], data), resid_prototype = similar(ys)), [y0, a], (xs, ys))

```

But as you see, all three trials won’t work. And I couldn’t figure it out. Would you please have a look on that?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [January 6, 2025, 10:30am UTC](https://discourse.julialang.org/t/how-to-fix-some-parameters-when-least-squares-fitting-using-nonlinearsolve/124451/4 "2025-01-06T10:30:32Z")

</div>

> [@thudjx](#):
>
> `(du, u, data) -> residualfn!([du; 0.0], [u; t₀], data)`

You go through all of this work to make your `residualfn!` be non-allocating, and that’s all well and good. But this anonymous function you put on top of it is allocating, specifically you’re making two arrays, `[du; 0.0], [u; t₀]`. You may want to allocate these vectors once and instead just reuse the cache memory, or rewrite `residualfn!` so that it uses `du` and `u` directly, like `du .= expmodel.(xs, Ref(u), t₀) .- ys` where you just keep that `t₀` separate.

---

<div class="post-metadata">

**Author:** ![thudjx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thudjx/32/15231_2.png) [@thudjx](https://discourse.julialang.org/u/thudjx)\
**Post date:** [January 7, 2025, 9:28am UTC](https://discourse.julialang.org/t/how-to-fix-some-parameters-when-least-squares-fitting-using-nonlinearsolve/124451/5 "2025-01-07T09:28:03Z")

</div>

Not sure if I understand you correctly.  
`residualfn!` only modify `du` in-place, so if `du` is preallocated, it is easy to be retrieved from the cache and thus have a performance gain. But I am bit confused, if no parameter in the model is fixed, the problem is defined as `prob = NonlinearLeastSquaresProblem(NonlinearFunction(lossfn!, resid_prototype = similar(ydata)), u0, data)` (as [here](https://discourse.julialang.org/t/least-squares-with-sciml-nonlinearsolve-jl-how-to/113074/14), and `du` is not preallocated but a performance gain is expected.  
Here in my case, where some parameters of `u` are transfered by closure:  
`prob = NonlinearLeastSquaresProblem(NonlinearFunction((dp, p, data) -> residual!(dp, [p; t₀], data), resid_prototype = similar(ys)), [y0, a, τ], (xs, ys))`  
I don’t get how I lose the performance gain.  
Would you please demonstrate more? I would really appreciate that!
