Problems

CurveFit defines two primary problem types: CurveFitProblem and NonlinearCurveFitProblem. These types encapsulate the data to be fitted, along with optional model definitions and initial parameter guesses. The data and the initial guess are subtypes of AbstractArray.

A CurveFitProblem represents a general curve fitting problem and requires only input data x and output data y. When no model is specified, both x and y must be one-dimensional arrays.

NonlinearCurveFitProblem is a convenience constructor for defining nonlinear fitting problems. It returns a CurveFitProblem object with a user-provided model function and an initial guess u0 for the model parameters. The model is supplied as a standard Julia function and is internally wrapped as a NonlinearFunction. For details, see the documentation for NonlinearFunction. If the output data y is not provided, it is treated as a zero vector.

Constructors

CurveFit.CurveFitProblemType
CurveFitProblem(x, y; nlfunc=nothing, u0=nothing, sigma=nothing)

Represents a curve fitting problem where x and y are the data points to fit.

Certain algorithms may require an initial guess u0 for the coefficients to fit. See specific solver documentation for more details.

Weights can be passed through sigma, which should be an array with the same dimensions as y. As with curve_fit() from scipy, the elements should be the standard deviation of y. Note that currently sigma is not supported for all kinds of fits, check the problem or algorithm docstring to see if sigma is supported.

See also NonlinearCurveFitProblem.

source
CurveFit.NonlinearCurveFitProblemFunction
NonlinearCurveFitProblem(f, u0, x, y=nothing, sigma=nothing)

Nonlinear curve fitting problem where f is a nonlinear function to fit, u0 is the initial guess for the coefficients, x and y are the data points to fit, and sigma is the standard deviation associated with y. The following optimization problem is solved:

\[\argmin_u ~ \left\| f(u, x) - y \right\|_2\]

If y is nothing, then it is treated as a zero vector. f is a generic Julia function or ideally a NonlinearFunction from SciMLBase.jl.

Function Signature

The model function f should have the signature f(params, x) where:

  • params is a vector of parameters to be fitted
  • x is the input data (can be a vector or matrix)

The function should return predictions for all input data points. For vectorized operations over arrays, use Julia's broadcasting syntax with the @. macro:

# Vectorized function using @.
fn(a, x) = @. a[1] + a[2] * x^a[3]

For users who prefer to define scalar functions (e.g., those migrating from LsqFit.jl), use the ScalarModel wrapper:

# Scalar function (operates on single x value)
fn_scalar(a, x) = a[1] + a[2] * x^a[3]
prob = NonlinearCurveFitProblem(ScalarModel(fn_scalar), u0, x, y)

See also ScalarModel.

source

Scalar models

For convenience when creating a model CurveFit provides a helper ScalarModel type that allows defining scalar models.

CurveFit.ScalarModelType
ScalarModel(f)

Wraps a scalar function f(params, x_i) that operates on a single data point x_i into a vectorized form suitable for CurveFit.jl.

This is useful for users migrating from LsqFit.jl or those who prefer defining scalar model functions without explicit broadcasting via the @. macro.

Why is @. Typically Required?

In CurveFit.jl, model functions receive the entire data array x at once and must return predictions for all data points. This vectorized design enables:

  • Better GPU performance when using GPU arrays
  • More efficient compilation with tools like Reactant.jl
  • User control over array types

Using ScalarModel

Instead of writing a vectorized function:

# Vectorized function (uses @.)
fn(a, x) = @. a[1] + a[2] * x^a[3]
prob = NonlinearCurveFitProblem(fn, u0, x, y)

You can write a simpler scalar function:

# Scalar function (no @. needed)
fn_scalar(a, x) = a[1] + a[2] * x^a[3]
prob = NonlinearCurveFitProblem(ScalarModel(fn_scalar), u0, x, y)

Migration from LsqFit.jl

For users coming from LsqFit.jl, note that the parameter order is reversed:

  • LsqFit.jl: model(x, p) (data first, then parameters)
  • CurveFit.jl: model(p, x) (parameters first, then data)

Example migration:

# LsqFit.jl style (does NOT work directly)
lsqfit_model(x, p) = p[1] * exp(-x * p[2])

# CurveFit.jl with ScalarModel
curvefit_model(p, x) = p[1] * exp(-x * p[2])
prob = NonlinearCurveFitProblem(ScalarModel(curvefit_model), u0, x, y)
source