Combining multiple functions of derivatives - matlab

Working with trying to make an Olver's method, my code is working however I want to try and combine the 3 functions into multi output function with use of diff() but i'm struggling to manipulate the inputs without jeopardizing outputs.
% Defining the function in the equation f(x)=0
function y = f(x)
y = x-exp(1/x);
end
% Defining the derivative of the function in the equation f(x)=0
function y = fd(x)
y = 1+exp(1/x)/(x^2);
end
% Defining the second derivative of the function in the equation f(x)=0
function y = fdd(x)
y = exp(1/x)*(2*x+1)/(x^4);
end

It is not very clear but having all these as a single function (with the use of Symbolic Toolbox) can be done as follows:
function [y1, y2, y3] = getDerivatives(a)
syms f(x)
f(x) = x-exp(1/x);
fd = diff(f,x);
fdd = diff(f,x,2);
y1 = double(f(a));
y2 = double(fd(a));
y3 = double(fdd(a));
end
and you can run it as follows:
[y1, y2, y3] = getDerivatives(1)
y1 =
-1.7183
y2 =
3.7183
y3 =
-8.1548

Related

How do you use the numjac function in MATLAB?

The documentation online for this particular function is poor, and I was looking for an example on how to use it. It seems to take in 9+ arguments, but I'm not entirely sure what they even are. I am working on implementing function using the trapezoidal rule, however, I am missing the functions that compute the partial derivatives with respect to y and t. I believe that calculating one for t in MATLAB is another case, but here, I'm just trying to use MATLAB to compute it for y.
I'm using the following input initially:
func = #(t,y)(y.^2+y+t);
interval = [0 1];
y0 = 0;
[steps, derivY, derivJ, W, inverseW] = getTrapezoidalODEValues(func, interval, y0)
I set up the function like this:
function [h,J,T,W,iW] = getTrapezoidalODEValues(odefun,tspan,y0,options)
if (nargin==3)
options = odeset();
end
h = NaN; J(0) = NaN; T(0) = NaN; W(0) = NaN; iW = NaN;
[t,yy] = ode(odefun,tspan,y0,options);
[nstep,ndim] = size(yy);
d = 1/(2+sqrt(2));
for j=2:nsteps
h = t(j)-t(j-1);
I = eye(???,???); % identity matrix
quadpoly = ???; % the quadratic polynomial
J(j-1) = numjac(???); % <--partial derivative of odefun with respect to y
T(j-1) = ???; % partial derivative of odefun with respect to t
W(j-1) = I - h .* d .* J;
iW(j-1) = inv(W(j-1));
end
end

Finding solution to Cauchy prob. in Matlab

I need some help with finding solution to Cauchy problem in Matlab.
The problem:
y''+10xy = 0, y(0) = 7, y '(0) = 3
Also I need to plot the graph.
I wrote some code but, I'm not sure whether it's correct or not. Particularly in function section.
Can somebody check it? If it's not correct, where I made a mistake?
Here is separate function in other .m file:
function dydx = funpr12(x,y)
dydx = y(2)+10*x*y
end
Main:
%% Cauchy problem
clear all, clc
xint = [0,5]; % interval
y0 = [7;3]; % initial conditions
% numerical solution using ode45
sol = ode45(#funpr12,xint,y0);
xx = [0:0.01:5]; % vector of x values
y = deval(sol,xx); % vector of y values
plot(xx,y(1,:),'r', 'LineWidth',3)
legend('y1(x)')
xlabel('x')
ylabel('y(x)')
I get this graph:
ode45 and its related ilk are only designed to solve first-order differential equations which are of the form y' = .... You need to do a bit of work if you want to solve second-order differential questions.
Specifically, you'll have to represent your problem as a system of first-order differential equations. You currently have the following ODE:
y'' + 10xy = 0, y(0) = 7, y'(0) = 3
If we rearrange this to solve for y'', we get:
y'' = -10xy, y(0) = 7, y'(0) = 3
Next, you'll want to use two variables... call it y1 and y2, such that:
y1 = y
y2 = y'
The way you have built your code for ode45, the initial conditions that you specified are exactly this - the guess using y and its first-order guess y'.
Taking the derivative of each side gives:
y1' = y'
y2' = y''
Now, doing some final substitutions we get this final system of first-order differential equations:
y1' = y2
y2' = -10*x*y1
If you're having trouble seeing this, simply remember that y1 = y, y2 = y' and finally y2' = y'' = -10*x*y = -10*x*y1. Therefore, you now need to build your function so that it looks like this:
function dydx = funpr12(x,y)
y1 = y(2);
y2 = -10*x*y(1);
dydx = [y1 y2];
end
Remember that the vector y is a two element vector which represents the value of y and the value of y' respectively at each time point specified at x. I would also argue that making this an anonymous function is cleaner. It requires less code:
funpr12 = #(x,y) [y(2); -10*x*y(1)];
Now go ahead and solve it (using your code):
%%// Cauchy problem
clear all, clc
funpr12 = #(x,y) [y(2); -10*x*y(1)]; %// Change
xint = [0,5]; % interval
y0 = [7;3]; % initial conditions
% numerical solution using ode45
sol = ode45(funpr12,xint,y0); %// Change - already a handle
xx = [0:0.01:5]; % vector of x values
y = deval(sol,xx); % vector of y values
plot(xx,y(1,:),'r', 'LineWidth',3)
legend('y1(x)')
xlabel('x')
ylabel('y(x)')
Take note that the output when simulating the solution to the differential equation by deval will be a two column matrix. The first column is the solution to the system while the second column is the derivative of the solution. As such, you'll want to plot the first column, which is what the plot syntax is doing.
I get this plot now:

create anonymous scalar function from existing vector functions in file

I want to create an anonymous function which takes the first output variable of an existing vector function in file in Matlab. For example, the existing vector function in a separate M-file is
function [y1,y2] = myfun(x1)
y1 = x1;
y2 = x1^2;
end
Is it possible to create an anonymous scalar function from myfun() which takes the value of y1? Thank you for any suggestions.
P.S. I am doing this because actually my original function is more like
function [y1,y2] = myfun(x1,x2)
y1 = x1+x2;
y2 = x1^2+x2^2;
end
and I want to create a scalar function y1 with only one parameter x1 (pass a known value of x2 to the anonymous function).
I think I know what you're looking for, but it's a little unclear. If you're starting with a function like this:
function [y1,y2] = myfun(x1,x2)
y1 = x1+x2;
y2 = x1^2+x2^2;
end
You can make a wrapper anonymous function with a fixed value of x2 (fixed at whatever the variable is when the anonymous function is created) like this:
newFcn = #(x1) myfun(x1, x2);
Now, you can use this to get whichever of the two outputs from myfun you want. For example:
y1 = newFcn(x1); % Gets the first output
[~, y2] = newFcn(x1); % Gets the second output
[y1, y2] = newFcn(x1); % Gets both
Based on #David 's method I adjusted my code and it works well.
function y = myfun(x1,x2)
y1 = x1+x2;
y2 = x1^2+x2^2;
y = [y1 y2];
end
and the anonymous functions output1 and output2 return y1 and y2 respectively.
paren=#(y,varargin) y(varargin{:});
output1 = #(x1) paren(myfun(x1,x2), 1);
output2 = #(x1) paren(myfun(x1,x2), 2);

Taylor Method ODE

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)

How to calculate the values of non-explicit function for all points of a meshgrid?

Let's say I have a function
f = #(x,y) g(x,y)
g is not explicit. It should be calculated numerically after inputting x and y values.
How can I calculate and save all values of this function at points
[x,y] = meshgrid(0:0.1:1,0:pi/10:2*pi);
I call f[x,y], but it doesn't work.
You have two ways to do it. Your function g should work with matrices, or you should give the values one by one
function eval_on_mesh()
f1 = #(x,y) g1(x,y);
f2 = #(x,y) g2(x,y);
[x,y] = meshgrid(0:0.1:1,0:pi/10:2*pi);
%# If your function work with matrices, you can do it like here
figure, surf(f1(x,y));
%# If your function doesnt, you should give the values one by one
sol = zeros(size(x));
for i=1:size(x,1)
for j=1:size(x,2)
sol(i,j) = f2(x(i,j),y(i,j));
end
end
figure, surf(sol);
end
function res = g1(x, y)
res = x.^2 + y.^2;
end
function res = g2(x, y)
res = x^2 + y^2;
end