The following code runs fine and gives the accurate result.
c1...c5 are known constants, and x(1)...x(5) (anonymous vector) are unknown variables which to be fitted by fminsearch using the least square method. (t,y) is the given data (curve) to fit the equation, myfunc is a ode45 function saved in a separate .m file.
% run the solver
options = optimset('MaxFunEvals',10000,'MaxIter',10000,'Display','iter');
[x,fval,exitflag,output] = fminsearch(#(x) Obj(x,initial_p,c1,c2,c3,c4,c5,c6,t,y),x0,options);
function F = Obj(x,initial_p,c1,c2,c3,c4,c5,c6,t,y)
p = myfunc(x(2:end),initial_p,t,c1,c4);
yt = mainfunc(x,p,c1,c2,c3,c4,c5,c6);
F = sqrt(sum((yt-y).^2));
disp(x);
end
function yt = mainfunc(x,p,c1,c2,c3,c4,~,~)
yf = c1*c2*c3*c4*sqrt(p);
yt = x(1)+yf;
end
But error occurs (Assignment has more non-singleton rhs dimensions than non-singleton subscripts) when I rewrite mainfunc (all else being same):
function yt = mainfunc(x,p,c1,c2,c3,c4,c5,c6)
ys = c1*c3*(c5/(c6*sqrt(p)));
yf = c1*c2*c3*c4*sqrt(p);
yt = x(1)+ys+yf;
end
p is a curve (t,p) coming from ode45 in myfunc, it is working fine in the first version of code so no problem there. Is having two terms with sqrt(p) in mainfunc causing the problem?
Related
I'm working in MATLAB and I have a problem with a system of differential equations. My system is dvdt = (-2*T)-4*v and dTdt = 6*T+v and I want to resolve it using Runge-Kutta of 4th order. I wrote the following code:
If I run only the function odefun, my code works! But my code didn't work if I run the complete program:
clear all
yy=#(t,y)[dvdt;dTdt]
[t,y]= ode45(#(t,y)yy,[0 1.5],[1 1/2 ]);
function res = odefun(t , y )
% i define two variable i will use: v and TT
v = y(1,:);
T = y(2,:);
% i define the two partial derivative:
res(1,:) = dvdt
res(2,:) = dTdt
dvdt = (-2*T)-4*v
dTdt = 6*T+v;
end
This is my results. I don't know to write a vector of a correct length:
Error using odearguments (line 95)
#(T,Y)YY returns a vector of length 1, but the length of initial conditions vector is 2. The vector returned by #(T,Y)YY and the initial conditions vector must have
the same number of elements.
Error in ode45 (line 115)
odearguments(FcnHandlesUsed, solver_name, ode, tspan, y0, options, varargin);
Error in sys_ode (line 4)
[t,y]= ode45(#(t,y)yy,[0 1.5],[1 1/2 ]);
y as passed from ode45 to odefun is a flat, one-dimensional array. Your variable assignment like you were dealing with a 2-dimensional array makes no sense. It should be v=y(1); T=y(2);.
In a code block, you need to observe causality. You need to declare/define a variable before you can use it in another code line.
Without calling odefun you will not get an error as each line in odefun is syntactically correct. However you get an error in its execution as the semantic is wrong.
Try
clear all
[t,y]= ode45(odefun,[0 1.5],[1 1/2 ]);
function res = odefun(t , y )
% i define two variable i will use: v and T
v = y(1);
T = y(2);
% i define the two derivatives:
dvdt = (-2*T)-4*v
dTdt = 6*T+v;
res = [ dvdt dTdt ]
end
Trying to get the integral of some experimentally collected data.
After using the envelope and abs functions I'm using the fit function to get the equation I wish to integrate (unfortunately 'poly' isn't giving a close enough fit to the data):
[yupper,ylower] = envelope(signal,1000,'peak');
dat = abs(yupper);
f = fit(x,dat,'linearinterp');
Then when I try
q = integral(f,3e4,9e4);
I get the error:
Error using integral (line 82) First input argument must be a function
handle.
Error in findenergyfromfitcurve (line 10) q = integral(f,3e4,9e4);
I thought f was a (mathematical) function, don't understand what the error is telling me. When I try using 'poly3' incase it's the linearinterp messing things up I still get that error.
TIA
f is a function but its type is cfit not function handle.
integral() function requires function handle, what you can do
is transform cfit into function handle before taking the
integral
The code is as follows
x = rand(5,1);
dat = rand(5,1);
f = fit(x,dat,'linearinterp');
% Create a new function handle
f = #(x)f(x);
q = integral(f, 3e4,9e4, 'ArrayValued', 1)
2) What does the ... 'Array valued', 1) do as well? It didn't work
till I put that in so it must do something
f is a piecewise function, the following illustration is based on the assumption that f is a 2-piecewise linear function, but it can be used for n-piecewise function as well.
The task for fit() function is finding the parameters :
a
b
c
d
k
In terms of code f looks like
function y = f(x,a,b,c,d,k)
% PIECEWISELINE A line made of two pieces
% that is not continuous.
y = zeros(size(x));
% This example includes a for-loop and if statement
% purely for example purposes.
for i = 1:length(x)
if x(i) < k
y(i) = a.* x(i) + b;
else
y(i) = c.* x(i) + d;
end
end
end
To plot a function handle, just use fplot(f)
Here is the graph for f
To sum up, f probably has more than one expression, that's why I set
'ArrayValued' to true so that integral() function knowns f
has more than one expression, omitting it means f has a single
expression which is not true.
I am trying to solve a system of n coupled ODE in MATLAB. The code:
clear all
n = 21;
dx = 1./(n-1);
x = [0:dx:1];
u0 = sin(0.5*n*pi*x);
f1 = #(t,u) [0, u(1:n-2)-2*u(2:n-1)-u(3:n), 2*(u(n-1)-u(n))]'/dx^2;
% f1 = #(t,u) [0; u(1:n-2)'-2*u(2:n-1)'-u(3:n)'; 2*(u(n-1)-u(n))]/dx^2;
[t,U] = ode45(f1, [0,2.5], u0');
gives the error:
Dimensions of matrices being concatenated are not consistent.
Error in t1>#(t,u)[0,u(1:n-2)-2*u(2:n-1)-u(3:n),2*(u(n-1)-u(n))]'/dx^2
I get errors from both forms (one commented out) of the anonymous function when u is a column vector, as it is when the function is called through ode45.
The u passed to f1 by ode45 is a column vector. The concatenation must reflect this:
f1 = #(t,u) [0 ; u(1:n-2)-2*u(2:n-1)-u(3:n) ; 2*(u(n-1)-u(n))]/dx^2;
I'm new on matlab.
How can I integrate this line of code ? ?
p2= polyfit(x,y,length(x));
from= x(1);
to= x(length(x));
I need the integration of p2.
I tried a lot with the Integration function:
value = integral(p2,from,to);
but I got
Error using integral (line 82) First input argument must be a function
handle.
Error in poly_integral (line 5)
value = integral(p2,from,to);
That is because p2, in your code, is not a function. It is just a vector of coefficients. The first argument for integral needs to be handle to the function that you want to integrate.
Judging from your code, it seems that you would want to define a function that evaluates the polynomial p2. If so, you could do something like the following example:
% take an example set of x and y
x = linspace(0, pi, 1000); % uniform samples between 0 to pi
y = sin(x); % assume, for sake of example, output is sine function of input
% polynomial fit
p2 = polyfit(x,y,4); % 4th order polynomial
% Note that, in general, the order should be much smaller than length(x).
% So you probably should review this part of your code as well.
% define a function to evaluate the polynomial
fn = #(x) polyval(p2, x);
% this means: fn(x0) is same as polyval(p2, x0)
% compute integral
value = integral(fn,x(1),x(end));
You can use the polyint function to get the polynomial coefficients for exact integration of the polynomial:
p2 = polyfit(x,y,length(x));
int = diff(polyval(polyint(p2),x([1 end])));
I am trying to implement the Taylor method for ODEs in MatLab:
My code (so far) looks like this...
function [x,y] = TaylorEDO(f, a, b, n, y0)
% syms t
% x = sym('x(t)'); % x(t)
% f = (t^2)*x+x*(1-x);
h = (b - a)/n;
fprime = diff(f);
f2prime = diff(fprime);
y(0) = y0,
for i=1:n
T((i-1)*h, y(i-1), n) = double(f((i-1)*h, y(i-1)))+(h/2)*fprime((i-1)*h, y(i-1))
y(i+1) = w(i) + h*T(t(i), y(i), n);
I was trying to use symbolic variables, but I donĀ“t know if/when I have to use double.
I also tried this other code, which is from a Matlab function, but I do not understand how f should enter the code and how this df is calculated.
http://www.mathworks.com/matlabcentral/fileexchange/2181-numerical-methods-using-matlab-2e/content/edition2/matlab/chap_9/taylor.m
As error using the function from this link, I got:
>> taylor('f',0,2,0,20)
Error using feval
Undefined function 'df' for input arguments of type 'double'.
Error in TaylorEDO (line 28)
D = feval('df',tj,yj)
The f I used here was
syms t
x = sym('x(t)'); % x(t)
f = (t^2)*x+x*(1-x);
This is a numerical method, so it needs numerical functions. However, some of them are computed from the derivatives of the function f. For that, you need symbolic differentiation.
Relevant Matlab commands are symfun (create a symbolic function) and matlabFunction (convert a symbolic function to numerical).
The code you have so far doesn't seem salvageable. You need to start somewhere closer to basics, e.g., "Matlab indices begin at 1". So I'll fill the gap (computation of df) in the code you linked to. The comments should explain what is going on.
function [T,Y] = taylor(f,a,b,ya,m)
syms t y
dfs(1) = symfun(f, [t y]); % make sure that the function has 2 arguments, even if the user passes in something like 2*y
for k=1:3
dfs(k+1) = diff(dfs(k),t)+f*diff(dfs(k),y); % the idea of Taylor method: calculate the higher derivatives of solution from the ODE
end
df = matlabFunction(symfun(dfs,[t y])); % convert to numerical function; again, make sure it has two variables
h = (b - a)/m; % the rest is unchanged except one line
T = zeros(1,m+1);
Y = zeros(1,m+1);
T(1) = a;
Y(1) = ya;
for j=1:m
tj = T(j);
yj = Y(j);
D = df(tj,yj); % syntax change here; feval is unnecessary with the above approach to df
Y(j+1) = yj + h*(D(1)+h*(D(2)/2+h*(D(3)/6+h*D(4)/24)));
T(j+1) = a + h*j;
end
end
Example of usage:
syms t y
[T, Y] = taylor(t*y, 0, 1, 2, 100);
plot(T,Y)