How to use lsqcurvefit to fit a rational function? - matlab

I want to fit a rational function using the curve fitting technique in MATLAB.
I am trying to use lsqcurvefit to reproduce a rational function M, which takes 5 inputs, with the data outputted from the exact function C. I think I am close to getting the plots; however, when I use lsqcurvefit, I keep getting an error saying:
LSQCURVEFIT requires the following inputs to be of data type double: 'YDATA'.
Below is my code:
% Define range for k
k= linspace(1E-10,1.5,100);
% Exact Function C(k)
C= #(k)(0.5*((1i*k+0.135).* (1i*k+0.651)))./((1i*k+0.0965).* (1i*k+0.4555));
% Cget function used to extract real and imaginary numbers and stacks the result
Cget= #(k)[real(C(k)); imag(C(k))];
%Call function Cget(k) to get stacked real and imaginary values
realimag =Cget(k);
% Create an initial guess
x0=[1,1];
% Define parameters
a1=0.2; a2=0.7; b1=0.1; b2=0.5;
% Define approximated function
M= #(a1,a2,b1,b2,k)(0.5*((1i*k+a1).* (1i*k+a2)))./((1i*k+b1).* (1i*k+b2));
Mget1= #(a1,a2,b1,b2,k)[real(M(a1,a2,b1,b2,k)); imag(M(a1,a2,b1,b2,k))];
T=Mget1(a1,a2,b1,b2,k);
%Find best fit curve
x=lsqcurvefit(M,x0,k,C)
How can I fit reproduce M, given the exact function C?

The variable C should be entered as a double array so that the function should get the input range and use it in the calculation.
% Exact Function C(k)- Bessel Function
C0 = (0.5*((1i*k+0.135).* (1i*k+0.651)))./((1i*k+0.0965).* (1i*k+0.4555));
and parameters of x could be entered as an array with 4 values.
M = #(x,k)(0.5*((1i*k+x(1)).* (1i*k+x(2))))./((1i*k+x(3)).* (1i*k+x(4)));
and x0 should have 4 values.
x0 = [1,1,1,1];
%Find best fit curve
x = lsqcurvefit(M,x0,k,C0)

Related

How to best-fit a rational function approximation to Theodorsen's function using the lsqcurvefit function in Matlab?

I am using a rational function (polynomial ratio) to approximate Theodorsen's function. I am having issues in guessing the correct (most optimal) initial guess parameters using the lsqcurvefit function in Matlab. Is there a way to know what would be the best initial guess parameters to get the best fit result?
My code is the following:
k = logspace(-10,1,300);
% Exact Theodorsen's Function C(k) in terms of Bessel Function
Ck= #(k)(besselh(1,2,k))./(besselh(1,2,k)+1i*besselh(0,2,k));
% Ckget function used to extract real and imaginary numbers and stacks the result
Ckget= #(k)[real(Ck(k)); imag(Ck(k))];
% Define 3rd order approximation function
x0= [.1,.1,.1,1,.1,.1,.1,.1]; % Create initial guess
U = 200;
b = 3;
s = 1i*k*(U/b);
Ck2 = #(x,k)((x(1)*s.^3 + x(2)*s.^2 + x(3)*s + x(4))./(x(5)*s.^3 + x(6)*s.^2 + x(7)*s + x(8)));
Ck2get= #(x,k)[real(Ck2(x,k)); imag(Ck2(x,k))]; %extract real & imaginary values
% Use curve fit function for best fit approximation
x2= lsqcurvefit(Ck2get,x0,k,Ckget(k))

Plot symbolic derivative of a built-in MATLAB function

I am trying to compute the second derivative of the airy function. Only its first derivative is a predefined function in MATLAB (airy(1,x))
Is there a way to compute its symbolic derivative? without resorting to finite differences, etc
I tried this
syms x
aiprime = #(x) airy(1,x);
aisecond = diff(airy(1,x));
plot(-10:0.01:10,aiprime,aisecond)
But didn't work.
Error using plot
Invalid second data argument
The problem is your plot statement. You specify the desired x-data, but did not evaluate your function in these points:
syms x
aiprime(x) = airy(1,x); % I would define it as a symbolic function instead of a function handle, although it works too.
aisecond(x) = diff(airy(1,x)); % Define as a function, to be able to evaluate the function easily
xs = -10:0.01:10; % define your desired x points
plot(xs,aiprime(xs),xs, aisecond(xs)) % evaluate your functions and plot data

Curve fitting with 5 parameters in Matlab

I am working on a curve fitting problem with the input function of the form
n=((xi-xa)-a*cos(theta))^2+(h-a*sin(theta))^2;
d=((xi-xa)+a*cos(theta))^2+(h+a*sin(theta))^2;
v=k*log(n/d) : Input function
Here xa,a,theta,h and k are parameters and we are required to compute v(xi)
The plot looks like this
Here blue dots represent observed value and red line is the theoretical curve obtained from the input function.
This fitting process was done by manually varying the parameters and matching the curves using hit and trial.
Could this be accomplished using any optimization technique in Matlab. if so how ?
You can try to use lsqcurvefit (http://nl.mathworks.com/help/optim/ug/lsqcurvefit.html), e.g.
function F = myfun(x,xdata)
%your parameters xa,a,theta,h,k
%map to parameter vector x(1),x(2),x(3),x(4),x(5)
n = ((xdata-x(1))-x(2)*cos(x(3)))^2+(x(4)-x(2)*sin(x(3)))^2;
d = ((xdata-x(1))+acos(x(3)))^2+(x(4)+asin(x(3)))^2;
F = x(5)*log(n/d);
end
and a call to solver
x0 = [1;1;1;1;1]; % your guess for starting values of the x vector of parameters
x = lsqcurvefit(#myfun,x0,xdata,ydata);

Returning original mathematical function values from ode45 in Matlab?

My intention is to plot the original mathematical function values from the differential equation of the second order below:
I(thetadbldot)+md(g-o^2asin(ot))sin(theta)=0
where thetadbldot is the second derivative of theta with respect to t and m,d,I,g,a,o are given constants. Initial conditions are theta(0)=pi/2 and thetadot(0)=0.
My issue is that my knowledge and tutoring is limited to storing the values of the derivatives and returning them, not values from the original mathematical function in the equation. Below you can see a code that calculates the differential in Cauchy-form and gives me the derivatives. Does anyone have suggestions what to do? Thanks!
function xdot = penduluma(t,x)
% The function penduluma(t,x) calculates the differential
% I(thetadbldot)+md(g-o^2asin(ot))sin(theta)=0 where thetadbldot is the second
% derivative of theta with respect to t and m,d,I,g,a,o are given constants.
% For the state-variable form, x1=theta and x2=thetadot. x is a 2x1 vector on the form
% [theta,thetadot].
m=1;d=0.2;I=0.1;g=9.81;a=0.1;o=4;
xdot = [x(2);m*d*(o^2*a*sin(o*t)-g)*sin(x(1))/I];
end
options=odeset('RelTol', 1e-6);
[t,xa]=ode45(#penduluma,[0,20],[pi/2,0],options);
% Then the desired vector from xa is plotted to t. As it looks now the desired
% values are not found in xa however.
Once you have the angle, you can calculate the angular velocity and acceleration using diff:
options=odeset('RelTol', 1e-6);
[t,xa]=ode45(#penduluma,[0,20],[pi/2,0],options);
x_ddot = zeros(size(t));
x_ddot(2:end) = diff(xa(:,2))./diff(t);
plot(t,xa,t,x_ddot)
legend('angle','angular velocity','angular acceleration')
which gives the following plot in Octave (should be the same in MATLAB):
Alternatively, you can work it out using your original differential equation:
x_ddot = -m*d*(o^2*a*sin(o*t)-g).*sin(xa(:,1))/I;
which gives a similar result:

plot matlab function handle that outputs vector

So I have a matlab function I wrote that takes in a number and returns an array of numbers (transposed). I need to plot this function. I was trying to use fplot but it was giving me errors:
Error in fplot (line 105)
x = xmin+minstep; y(2,:) = feval(fun,x,args{4:end});
Am I using the wrong plot function?
the function solves an equation of motion problem. I have this diff eq:
Mx'' + Cx'+ Kx = 0
where M, C, and K are 4x4 matrices and my function solves the general solution and outputs a vector of 4 values.
I fixed my problem by changing my function to accept an array of t values and then I used the plot function instead of fplot