Hi everyone,
It’s a long shot as the problem is quite niche, but I would still appreciate any help/comments from the community.
Problem Description
To put it briefly, I am interested in fitting a nonlinear model S(\lambda; C^v; \boldsymbol{\theta}) to data pairs (S_i,\, \lambda_i). The other variable C^v is the solution of a nonlinear ODE
where \boldsymbol{\theta} are the parameters I am eventually interested in. It is basically a constitutive model from nonlinear solid mechanics. The most natural way is to integrate the ODE numerically, get C^v and then solve a nonlinear least-squares problem. I have hard-coded my own time-integrator (a 5th order RK) and it seems to work fine (I know \boldsymbol{\theta} beforehand and just ran the forward model to see if it was working fine). Using DifferentialEquations.jl is next on my list. For the fitting, I am trying to use LsqFit.jl and specifically it’s curve_fit function along with the RK5 integrator.
Data
1.000000000000000000e+00,0.000000000000000000e+00
1.080078125000000000e+00,1.007812500000000000e+01
1.157226562500000000e+00,1.660937500000000000e+01
1.255859375000000000e+00,2.221875000000000000e+01
1.336914062500000000e+00,2.584375000000000000e+01
1.452148437500000000e+00,2.982812500000000000e+01
1.618164062500000000e+00,3.306250000000000000e+01
1.771484375000000000e+00,3.612500000000000000e+01
1.945312500000000000e+00,3.881250000000000000e+01
2.111328125000000000e+00,4.153125000000000000e+01
2.302734375000000000e+00,4.421875000000000000e+01
2.515625000000000000e+00,4.743750000000000000e+01
2.716796875000000000e+00,5.050000000000000000e+01
2.996093750000000000e+00,5.446875000000000000e+01
2.923828125000000000e+00,5.156250000000000000e+01
2.800781250000000000e+00,4.721875000000000000e+01
2.664062500000000000e+00,4.343750000000000000e+01
2.535156250000000000e+00,3.962500000000000000e+01
2.400390625000000000e+00,3.584375000000000000e+01
2.259765625000000000e+00,3.168750000000000000e+01
2.156250000000000000e+00,2.879687500000000000e+01
2.054687500000000000e+00,2.553125000000000000e+01
1.956054687500000000e+00,2.118750000000000000e+01
1.845703125000000000e+00,1.757812500000000000e+01
1.743164062500000000e+00,1.304687500000000000e+01
1.584960937500000000e+00,6.894531250000000000e+00
1.469726562500000000e+00,7.329101562500000000e-01
Code (S11 is the function)
using LsqFit;
using Plots;
using DelimitedFiles;
using Optim;
function S11(λ, Cv11, params)
    mu1, mu2, alph1, alph2, m1, m2, a1, a2, K1, K2, bta1, bta2, eta0, etaInf = params
    l2 = λ^(-0.5)
    I1 = λ^2. + 2/λ
    Cv22 = Cv11^(-0.5)
    Ie1 = λ^2/Cv11 + 2*l2^2/Cv22
    p = ((mu1 * (I1/3.)^(alph1 - 1.) + mu2 * (I1/3.)^(alph2 - 1.)) * l2 + (m1 * (Ie1/3.)^(a1 - 1.) + m2 * (Ie1/3.)^(a2 - 1.)) * l2/Cv22) * l2
    s1 = ((mu1 * (I1/3.)^(alph1 - 1.) + mu2 * (I1/3.)^(alph2 - 1.)) * λ + (m1 * (Ie1/3.)^(a1 - 1.) + m2 * (Ie1/3.)^(a2 - 1.)) * λ/Cv11) - p/λ
    return s1;
end
function Cvdot11(λ, Cv11, params)
    mu1, mu2, alph1, alph2, m1, m2, a1, a2, K1, K2, bta1, bta2, eta0, etaInf = params
    @assert λ > 0 "Stretches can't be negative"
    l2 = λ^(-0.5) 
    # @assert Cv11 > 0 "Cv can't be negative" # this is where it fails
    Cv22 = Cv11^(-0.5)
    
    Ie1 = λ ^ 2. /Cv11 + 2.0 * l2^2. /Cv22
    A2 = (m1 * (Ie1/3.)^(a1 - 1.) + m2 * (Ie1/3.)^(a2 - 1.))
    Iv1 = Cv11 + 2. * Cv22
    Ie1 = λ^2/Cv11 + 2*l2^2/Cv22
    Cvinv_C_sq = λ^4/Cv11^2 + 2. * l2 ^4/Cv22^2
    Ie2 = 1/2. * (Ie1 ^ 2. - Cvinv_C_sq)
    J2NEq = (Ie1^2/3. - Ie2) * A2^2.
    
    
    etaK = etaInf + (eta0 - etaInf + K1 * (Iv1 ^ (bta1) - 3^(bta1)))/(1. + (K2 * J2NEq)^(bta2))
    cvd11 = A2/etaK * (λ^2. - 1/3. * Ie1 * Cv11)
    return cvd11;
end
function kterms(dt, Cv_n, λ, λ_n,  λ_half, λ_quarter, λ_three_quarter, params)
    G1 = Cvdot11(λ_n, Cv_n, params)
    # @assert G1 > 0.
    Cv_G2 = Cv_n + G1 * dt / 2.0
    G2 = Cvdot11(
        λ_half,
        Cv_G2, params)
    
    # @assert G2 > 1.
    Cv_G3 = Cv_n + (3.0 * G1 + G2) * dt / 16.0 
    G3 = Cvdot11(
        λ_quarter,
        Cv_G3,
        params)
    
    # @assert G3 > 1.
        Cv_G4 = Cv_n + G3 * dt / 2.0
    G4 = Cvdot11(
        λ_half,
        Cv_G4,
        params)
    
    # @assert G4 > 1.
    Cv_G5 = Cv_n + 3.0 * dt / 16.0 * (-G2 + 2.0 * G3 + 3.0 * G4)
    G5 = Cvdot11(
        λ_three_quarter,
        Cv_G5,
        params)
    
    # @assert G5 > 1.
    Cv_G6 = Cv_n + dt / 7.0 * (G1 + 4.0 * G2 + 6.0 * G3 - 12.0 * G4 + 8.0 * G5)
    G6 = Cvdot11(
        λ,
        Cv_G6,
        params)
    
    # @assert G6 > 1.
    Cv = Cv_n + dt / 90.0 * (7.0 * G1 + 32.0 * G3 + 12.0 * G4 + 32.0 * G5 + 7.0 * G6)
    return Cv;
end
function correct_params()
    params = [
    (13.54 * 10^3),
    (1.08 * 10^3),
    (1.),
    (-2.474),
    (5.42 * 10^3),
    (20.78 * 10^3),
    (-10.),
    (1.948),
    (3507 * 10^3),
    (10^(-6)),
    (1.852),
    (0.26),
    (7014 * 10^3),
    (0.1 * 10^3)];
    return params;
end
function fit(λvals, params)
    λdot = 0.01;
    S11v = zeros(size(λvals, 1));
    Cvvals = ones(size(λvals, 1));
    for i ∈ range(1, size(λvals, 1) - 1)
        Δt = abs(λvals[i+1] - λvals[i])/λdot;
        λn = λvals[i];
        λnp1 = λvals[i+1];
        l1half = λn + 0.5 * (λnp1 - λn);
        l1quarter = λn + 0.25 * (λnp1 - λn)
        l1three_quarter = λn + 0.75 * (λnp1 - λn)
        Cvvals[i+1] = kterms(Δt, Cvvals[i], λnp1, λn, l1half, l1quarter, l1three_quarter, params)
        S11v[i+1] = S11(λnp1, Cvvals[i+1], params)
    end
    return S11v;
end
data = readdlm("VHBdataJulia.txt", ',');
function plot_correct_plot(data)
    λdot = 0.01;
    timevals = [0.0];
    for i ∈ 1:length(data[:, 1])-1
        Δt = abs(data[i+1, 1] - data[i, 1])/λdot;
        push!(timevals, timevals[i] + Δt);
    end
    length(timevals)
    size(data[:, 1])
    plot(timevals, data[:, 1]);
    savefig("time.png");
    size(data[:, 1])
    
    # trial figure
    params = correct_params();
    Δtf = 0.01;
    λdotf = 0.01;
    λfinal = 3.0;
    Tf = (λfinal - 1.0)/λdotf;
    nsteps = Tf/Δtf + 1;
    λvals = LinRange(1.0, λfinal, Int(nsteps));
    λvals = vcat(λvals, LinRange(λfinal-λdotf * Δtf, 1.0, Int(nsteps)));
    λvals
    plot(λvals)
    savefig("λvals.png");
    
    plot(λvals, fit(λvals, params)./1E3, label="Correct Parameters");
    scatter!(data[:, 1], data[:, 2], label="Data", legend=:bottomright);
    savefig("correct_params.png");
end
plot_correct_plot(data);
p0 = [13E3, 1E3, 0.9, -3., 5E3, 20E3, -12., -10., 5E6, 1.5E-6, 2., 1., 1E7, 5E1];
ib = [1E2, 1E2, 0.5, -3.5, 1E2, 1E2, -15., -15., 1E6, 1E-7, 0.5, 0.1, 1E6, 1E1];
ub = [2E4, 2E4, 1.5, 2.5, 1E5, 1E5, 3., 3., 1E8, 3E-6, 2.5, 1.0, 1E7, 2E2];
myfit = curve_fit(fit, data[:, 1], data[:, 2] .* 1E3, p0, lower=ib, upper=ub);
Result
If I run plot_correct_data above, nothing goes wrong (which led me to believe that the time-integrator was OK). Because I am calling the same function (which does the time-integration) but with the right set of parameters.

Error
But If I run curve_fit on the data, it seems to throw an error specifically at the assertion statement I had (I was getting a DomainError before and I traced it back to the second @assert statement inside the Cvdot11 function). Here is the earlier stacktrace
ERROR: LoadError: DomainError with -0.30365595683307434:
Exponentiation yielding a complex result requires a complex argument.
Replace x^y with (x+0im)^y, Complex(x)^y, or similar.
Stacktrace:
  [1] throw_exp_domainerror(x::Float64)
    @ Base.Math .\math.jl:37
  [2] ^
    @ .\math.jl:909 [inlined]
  [3] Cvdot11(λ::Float64, Cv11::Float64, params::Vector{Float64})
    @ Main d:\curveFit\curveFit.jl:22
  [4] kterms(dt::Float64, Cv_n::Float64, λ::Float64, λ_n::Float64, λ_half::Float64, λ_quarter::Float64, λ_three_quarter::Float64, params::Vector{Float64})
    @ Main d:\curveFit\curveFit.jl:70
  [5] fit(λvals::Vector{Float64}, params::Vector{Float64})
    @ Main d:\curveFit\curveFit.jl:110
Now, if I try to do something like (Cv + 0im)^(-0.5) I get an InexactError, namely
ERROR: LoadError: InexactError: Float64(0.5141891571782113 - 1.6389735916551083e-6im)
Stacktrace:
  [1] Real
    @ .\complex.jl:44 [inlined]
  [2] convert
    @ .\number.jl:7 [inlined]
  [3] setindex!
    @ .\array.jl:903 [inlined]
  [4] fit(λvals::Vector{Float64}, params::Vector{Float64})
    @ Main d:\curveFit\curveFit.jl:112
which seems really weird since line 112 is
Cvvals[i+1] = kterms(Δt, Cvvals[i], λnp1, λn, l1half, l1quarter, l1three_quarter, params).
It would be great if you could point me to what could be going wrong and where. Thanks in advance!

