Problem when passing numerical solution of an equation as model function to lsqcurvefit

2 views (last 30 days)
Hello everyone,
I'm trying to fit my data with a model function. One part of my model function is a numerical solution of a nonlinear equation that has no analytical solution. When I try to fit the data with lsqcurvefit, I obtain the folloqing error:
"
Error using lsqcurvefit (line 259)
LSQCURVEFIT requires all values returned by functions to be of data type double.
Error in TRPL_PG_shift (line 74)
[out,resnorm,residual,exitflag,output,lambda,J]=lsqcurvefit(prova,x0, T,en,lb,ub,options);
"
Here is the relevant part my code. I just checked the T, en and mpg(x0,T) have the same size.
x0=[2.104 5.97 83.6E-3 3.53E5 -61.8E-3 12.3E-3];
lb=[2.101 5.93 83.3E-3 3.51E5 -62.0E-3 12.0e-3];
ub=[2.108 5.99 83.9E-3 3.55E5 -61.6E-3 12.8e-3];
fun0=double(mpg(x0,T));
options=optimoptions(@lsqcurvefit,'TolX', 1e-7, 'TolFun', 1e-7,'MaxFunctionEvaluations',200000, 'MaxIterations', 200000,'PlotFcn','optimplotfval','display','iter');
[out,resnorm,residual,exitflag,output,lambda,J]=lsqcurvefit(@(pars,T)mpg(pars,T),x0, T,en,lb,ub,options);
%%%%%MODEL FUNCTION%%%%%
function out = mpg(pars,t)
kb=8.617e-5;
k(1) = pars(1);
k(2) = pars(2);
k(3) = pars(3);
k(4) = pars(4);
k(5) = pars(5);
k(6) = pars(6);
function output = sol(~,t)
x = sym('x');
kb=8.617e-5;
for i=1:length(t)
eq(i)=x.*exp(x)-k(4).*((k(5)./(kb.*t(i))).^2-x).*exp(k(6)./(kb.*t(i)));
sol_x(i)=vpasolve(eq(i),x);
end
output=sol_x;
end
out=k(1)-k(2).*k(3).*(coth(k(3)./(2.*kb.*t))-1)-kb.*t.*sol(pars,t);
end
Thank you very much for your kind help,
Eugenio

Answers (1)

Alan Weiss
Alan Weiss on 24 Nov 2020
You did not specify T or en so I cannot try to reproduce your results. But clearly, the error is due to a data type mismatch between your internal symbolic variables and the required doubles. I expect that creating symbolic variables inside your objective function is slow. I would rewrite the function not to use any symbolic variables.
That said, the easiest fix is probably to change your objective function to return double values. I mean, change the last line of your function out = mpg(pars,t) to:
out = double(k(1)-k(2).*k(3).*(coth(k(3)./(2.*kb.*t))-1)-kb.*t.*sol(pars,t));
Alan Weiss
MATLAB mathematical toolbox documentation
  2 Comments
Eugenio Luigi Cinquanta
Eugenio Luigi Cinquanta on 24 Nov 2020
Thank you Alan,
in this way it works, thank you very much.
The poin is that I have to solve numerically eq(i) becasue it has no analytical solution. Do you have any suggestion about this? It is very slow indeed, but I do not know ho to improve my code.
Thanks again,
Eugenio
Alan Weiss
Alan Weiss on 25 Nov 2020
I suggest that you NOT solve it symbolically. Instead, solve it numerically using fsolve. I am not sure, but it might be best to start fsolve from the previous solution. See Follow Equation Solution as a Parameter Changes.
Alan Weiss
MATLAB mathematical toolbox documentation

Sign in to comment.

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!