How to plot (x-​1)/​(y+​2)^​1.8? - matlab

I tried to plot the equation (x-​1)/​(y+​2)^​1.8 in octave using surf() method. But the graph is something else.
Here's my code:
p = linspace(1,50, 100);
t = linspace(1,48,100);
ans = zeros(length(p), length(t));
ans = compute_z(p, t, ans);
figure;
surf(p, t, ans');
trying to compute z = (x-​1)/​(y+​2)^​1.8 using helper function compute_z
function [ans] = compute_z(ans, p, t)
for i = 1:length(p)
for j = 1:length(t)
ans(i,j) = (p(i) - 1) / (t(j)+2)^1.8;
end
end
I was trying to generate this graph.

There is no need for your compute_z-method as you can you meshgrid and vectorisation.
p = linspace(1,50, 100);
t = linspace(1,48,100);
[P, T] = meshgrid(p,t); Z = (P-1) ./ (T+2).^1.8;
figure;
surf(P, T, Z);
(Tested in Matlab, but should work in Octave as well)

Your problem is you define compute_z inputs as ans, p and t in that order. However, you call the function with p, t and ans in that order. Do you see the problem?
ans isn't an input to the function, just an output, so no need to list it as an input. Furthermore, don't call your variable ans, it's the default variable name MATLAB uses when no output variable name is specified, so is likely to be overwritten.
Here's my suggestion:
p = linspace(1,50, 100);
t = linspace(1,48,100);
z = zeros(length(p), length(t));
z = compute_z(p, t);
figure;
surf(p, t, z');
with compute_z defined as follows:
function z = compute_z(p, t)
for i = 1:length(p)
for j = 1:length(t)
z(i,j) = (p(i) - 1) / (t(j)+2)^1.8;
end
end

Related

Using interpolation outside function definition in solution using Runge-Kutta 4th order

I have written MATLAB code to solve the following systems of differential equations.
with
where
and z2 = x2 + (1+a)x1
a = 2;
k = 1+a;
b = 3;
ca = 5;
cb = 2;
theta1t = 0:.1:10;
theta1 = ca*normpdf(theta1t-5);
theta2t = 0:.1:10;
theta2 = cb*ones(1,101);
h = 0.05;
t = 1:h:10;
y = zeros(2,length(t));
y(1,1) = 1; % <-- The initial value of y at time 1
y(2,1) = 0; % <-- The initial value of y' at time 1
f = #(t,y) [y(2)+interp1(theta1t,theta1,t,'spline')*y(1)*sin(y(2));
interp1(theta2t,theta2,t,'spline')*(y(2)^2)+y(1)-y(1)-y(1)-(1+a)*y(2)-k*(y(2)+(1+a)*y(1))];
for i=1:(length(t)-1) % At each step in the loop below, changed y(i) to y(:,i) to accommodate multi results
k1 = f( t(i) , y(:,i) );
k2 = f( t(i)+0.5*h, y(:,i)+0.5*h*k1);
k3 = f( t(i)+0.5*h, y(:,i)+0.5*h*k2);
k4 = f( t(i)+ h, y(:,i)+ h*k3);
y(:,i+1) = y(:,i) + (1/6)*(k1 + 2*k2 + 2*k3 + k4)*h;
end
plot(t,y(:,:),'r','LineWidth',2);
legend('RK4');
xlabel('Time')
ylabel('y')
Now what is want to do is define the interpolations/extrapolations outside the function definition like
theta1_interp = interp1(theta1t,theta1,t,'spline');
theta2_interp = interp1(theta2t,theta2,t,'spline');
f = #(t,y) [y(2)+theta1_interp*y(1)*sin(y(2));
theta2_interp*(y(2)^2)+y(1)-y(1)-y(1)-(1+a)*y(2)-k*(y(2)+(1+a)*y(1))];
But this gives the error
Please suggest a solution to this issue.
Note that in your original code:
f = #(t,y) [y(2)+interp1(theta1t,theta1,t,'spline')*y(1)*sin(y(2));
interp1(theta2t,theta2,t,'spline')*(y(2)^2)+y(1)-y(1)-y(1)-(1+a)*y(2)-k*(y(2)+(1+a)*y(1))];
the call to interp1 uses the input variable t. t inside this anonymous function is not the same as the t outside of it, where it is defined as a vector.
This means that, when you do
theta1_interp = interp1(theta1t,theta1,t,'spline');
then theta1_interp is a vector containing interpolated values for all your ts, not just one. One way around this is to create more anonymous functions:
theta1_interp = #(t) interp1(theta1t,theta1,t,'spline');
theta2_interp = #(t) interp1(theta2t,theta2,t,'spline');
f = #(t,y) [y(2)+theta1_interp(t)*y(1)*sin(y(2));
theta2_interp(t)*(y(2)^2)+y(1)-y(1)-y(1)-(1+a)*y(2)-k*(y(2)+(1+a)*y(1))];
Though this doesn't really improve your code in any way over the original.

Change the grid points of parametric splines in Matlab

My Code right now
% Create some example points x and y
t = pi*[0:.05:1,1.1,1.2:.02:2]; a = 3/2*sqrt(2);
for i=1:size(t,2)
x(i) = a*sqrt(2)*cos(t(i))/(sin(t(i)).^2+1);
y(i) = a*sqrt(2)*cos(t(i))*sin(t(i))/(sin(t(i))^2+1);
end
Please note: The points (x_i|y_i) are not necessarily equidistant, that's why t is created like this. Also t should not be used in further code as for my real problems it is not known, I just get a bunch of x, y and z values in the end. For this example I reduced it to 2D.
Now I'm creating ParametricSplines for the x and y values
% Spline
n=100; [x_t, y_t, tt] = ParametricSpline(x, y, n);
xref = ppval(x_t, tt); yref = ppval(y_t, tt);
with the function
function [ x_t, y_t, t_t ] = ParametricSpline(x,y,n)
m = length(x);
t = zeros(m, 1);
for i=2:m
arc_length = sqrt((x(i)-x(i-1))^2 + (y(i)-y(i-1))^2);
t(i) = t(i-1) + arc_length;
end
t=t./t(length(t));
x_t = spline(t, x);
y_t = spline(t, y);
t_t = linspace(0,1,n);
end
The plot generated by
plot(x,y,'ob',...
xref,yref,'xk',...
xref,yref,'-r'),...
axis equal;
looks like the follows: Plot Spline
The Question:
How do I change the code so I always have one of the resulting points (xref_i|yref_i) (shown as Black X in the plot) directly on the originally given points (x_j|y_j) (shown as Blue O) with additionally n points between (x_j|y_j) and (x_j+1|y_j+1)?
E.g. with n=2 I would like to get the following:
(xref_1|yref_1) = (x_1|y_1)
(xref_2|yref_2)
(xref_3|yref_3)
(xref_4|yref_4) = (x_2|y_2)
(xref_5|yref_5)
[...]
I guess the only thing I need is to change the definition of tt but I just can't figure out how... Thanks for your help!
Use this as your function:
function [ x_t, y_t, tt ] = ParametricSpline(x,y,nt)
arc_length = 0;
n = length(x);
t = zeros(n, 1);
mul_p = linspace(0,1,nt+2)';
mul_p = mul_p(2:end);
tt = t(1);
for i=2:n
arc_length = sqrt((x(i)-x(i-1))^2 + (y(i)-y(i-1))^2);
t(i) = t(i-1) + arc_length;
add_points = mul_p * arc_length + t(i-1);
tt = [tt ; add_points];
end
t=t./t(end);
tt = tt./tt(end);
x_t = spline(t, x);
y_t = spline(t, y);
end
The essence:
You have to construct tt in the same way as your distance vector t plus add additional nt points in between.

Plotting a 2d vector on 3d axes in matlab

I have three vectors x,y,t. For each combination x,y,t there is a (u,v) value associated with it. How to plot this in matlab? Actually I'm trying to plot the solution of 2d hyperbolic equation
vt = A1vx + A2vy where A1 and A2 are 2*2 matrices and v is a 2*1 vector. I was trying scatter3 and quiver3 but being new to matlab I'm not able to represent the solution correctly.
In the below code I have plot at only a particular time-level. How to show the complete solution in just one plot? Any help?
A1 = [5/3 2/3; 1/3 4/3];
A2 = [-1 -2; -1 0];
M = 10;
N = 40;
delta_x = 1/M;
delta_y = delta_x;
delta_t = 1/N;
x_points = 0:delta_x:1;
y_points = 0:delta_y:1;
t_points = 0:delta_t:1;
u = zeros(M+1,M+1,N+1,2);
for i=1:M+1,
for j=1:M+1,
u(i,j,1,1) = (sin(pi*x_points(i)))*sin(2*pi*y_points(j)) ;
u(i,j,1,2) = cos(2*pi*x_points(i));
end
end
for j=1:M+1,
for t=1:N+1,
u(M+1,j,t,1) = sin(2*t);
u(M+1,j,t,2) = cos(2*t);
end
end
for i=1:M+1
for t=1:N+1
u(i,1,t,1) = sin(2*t);
u(i,M+1,t,2) = sin(5*t) ;
end
end
Rx = delta_t/delta_x;
Ry = delta_t/delta_y;
for t=2:N+1
v = zeros(M+1,M+1,2);
for i=2:M,
for j=2:M,
A = [(u(i+1,j,t-1,1) - u(i-1,j,t-1,1)) ; (u(i+1,j,t-1,2) - u(i-1,j,t-1,2))];
B = [(u(i+1,j,t-1,1) -2*u(i,j,t-1,1) +u(i-1,j,t-1,1)) ; (u(i+1,j,t-1,2) -2*u(i,j,t-1,2) +u(i-1,j,t-1,2))];
C = [u(i,j,t-1,1) ; u(i,j,t-1,2)];
v(i,j,:) = C + Rx*A1*A/2 + Rx*Rx*A1*A1*B/2;
end
end
for i=2:M,
for j=2:M,
A = [(v(i,j+1,1) - v(i,j-1,1)) ; (v(i,j+1,2) - v(i,j-1,2)) ];
B = [(v(i,j+1,1) - 2*v(i,j,1) +v(i,j-1,1)) ; (v(i,j+1,2) - 2*v(i,j,2) +v(i,j-1,2))];
C = [v(i,j,1) ; v(i,j,2)];
u(i,j,t,:) = C + Ry*A2*A/2 + Ry*Ry*A2*A2*B/2;
end
end
if j==2
u(i,1,t,2) = u(i,2,t,2);
end
if j==M
u(i,M+1,t,1) = u(i,M,t,1);
end
if i==2
u(1,j,t,:) = u(2,j,t,:) ;
end
end
time_level = 2;
quiver(x_points, y_points, u(:,:,time_level,1), u(:,:,time_level,2))
You can plot it in 3D, but personally I think it would be hard to make sense of.
There's a quiver3 equivalent for your plotting function. z-axis in this case would be time (say, equally spaced), and z components of the vectors would be zero. Unlike 2D version of this function, it does not support passing in coordinate vectors, so you need to create the grid explicitly using meshgrid:
sz = size(u);
[X, Y, Z] = meshgrid(x_points, y_points, 1:sz(3));
quiver3(X, Y, Z, u(:,:,:,1), u(:,:,:,2), zeros(sz(1:3)));
You may also color each timescale differently by plotting them one at a time, but it's still hard to make sense of the results:
figure(); hold('all');
for z = 1:sz(3)
[X, Y, Z] = meshgrid(x_points, y_points, z);
quiver3(X, Y, Z, u(:,:,z,1), u(:,:,z,2), zeros([sz(1:2),1]));
end

Matlab Differential Equations Euler’s method

I need help plotting a differential equation ... it keeps coming out all funky and the graph is not what it's supposed to look like.
function [dydt] = diff(y,t)
dydt = (-3*y)+(t*(exp(-3*t)));
end
tI = 0;
yI = -0.1;
tEnd = 5;
dt = 0.5;
t = tI:dt:tEnd;
y = zeros(size(t));
y(1) = yI;
for k = 2:numel(y)
yPrime = diff(t(k-1),y(k-1));
y(k) = y(k-1) + dt*yPrime;
end
plot(t,y)
grid on
title('Engr')
xlabel('Time')
ylabel('y(t)')
legend(['dt = ' num2str(dt)])
That's my code, but the graph is not anything like what it's supposed to look like. Am I missing something like an index for the for statement?
Edit
I am getting an error:
Error using diff
Difference order N must be a positive integer scalar.
Error in diff3 (line 12)
yPrime = diff(t(k-1),y(k-1));
After fixing the errors pointed out by Danil Asotsky and horchler in the comments:
avoiding name conflict with built-in function 'diff'
changing the order of arguments to t,y.
decreasing the time-step dt to 0.1
converting ODE right-hand side to an anonymous function
(and removing unnecessary parentheses in the function definition), your code could look like this:
F = #(t,y) -3*y+t*exp(-3*t);
tI = 0;
yI = -0.1;
tEnd = 5;
dt = 0.1;
t = tI:dt:tEnd;
y = zeros(size(t));
y(1) = yI;
for k = 2:numel(y)
yPrime = F(t(k-1),y(k-1));
y(k) = y(k-1) + dt*yPrime;
end
plot(t,y)
grid on
title('Engr')
xlabel('Time')
ylabel('y(t)')
legend(['dt = ' num2str(dt)])
which performs as expected:

vectorizing a non-explicit function in Matlab and Octave

I want to vectorize a 3D function, but the function does not have an analytical expression. For instance, I can vectorize the function
F(x, y, z) = (sin(y)*x, z*y, x*y)
by doing something like
function out = Vect_fn(x, y,z)
out(1) = x.*sin(y);
out(2) = z.*y;
out(3) = x.*y;
end
And then running the script
a = linspace(0,1,10);
[xx, yy, zz] = meshgrid(a, a, a);
D = Vect_fn(xx, yy, zz)
However, suppose the function does not have an analytical expression, for example
function y = Vect_Nexplicit(y0)
%%%%%%y0 is a 3x1 vector%%%%%%%%%%%%%%
t0 = 0.0;
tf = 3.0;
[t, z] = ode45('ODE_fn', [t0,tf], y0);
sz = size(z);
n = sz(1);
y = z(n, :);
end
where ODE_fn is just some function that spits out the right-hand side of a an ODE. Thus the function simply solves an ODE and so the function is not known explicitly. Of course I can use a for loop, but those are slower (esp. in Octave, which I prefer since it has lsode for solving ODEs)
Trying something like
a = linspace(0,1,10);
[xx, yy, zz] = meshgrid(a, a, a);
D = Vect_Nexplicit(xx, yy, zz)
does not work. Also here is the code for ODF_fn:
function ydot = ODE_fn(t, yin)
A = sqrt(3.0);
B = sqrt(2.0);
C = 1.0;
x = yin(1, 1);
y = yin(2,1);
z = yin(3, 1);
M = reshape(yin(4:12), 3, 3);
ydot(1,1) = A*sin(yin(3)) + C*cos(yin(2));
ydot(2,1) = B*sin(yin(1)) + A*cos(yin(3));
ydot(3,1) = C*sin(yin(2)) + B*cos(yin(1));
DV = [0 -C*sin(y) A*cos(z); B*cos(x) 0 -A*sin(z); -B*sin(x) C*cos(y) 0];
Mdot = DV*M;
ydot(4:12,1) = reshape(Mdot, 9, 1);
end
You can solve systems of differential equations with ode45, so if ODE_fn is vectorised you can use your approach. y0 just needs to be a vector too.
You can create a y0 that is [x1, ..., xn, y1, ..., yn, z1, ..., zn, M1_1-9, ... ,Mn_1-9] and then use for x, y, z just the appropriate indexes i.e. 1:n, n+1:2*n, 2*n+1:3n. Then use reshape(yin(3*n+1:end),3,3,n). But I am not sure how to vectorize the matrix multiplication.