How to 3D plot? - matlab

I'm having trouble letting the xi and yi ranges include anything but positive integer values because of the way I am storing data in the matrix (x and y values corresponding to the slot they are stored in), but I can't figure out a more clever way of doing it. Could someone please help me out? I'd like to be able to let xi = -30:30 and yi = -30:30.
function test3
f = #(x,y) y*sin(x) + sqrt(y);
function p
xi = 1:30;
yi = 1:30;
pts = zeros(size(xi,2),size(yi,2));
for x = xi
for y = yi
pts(x,y) = pts(x,y) + f(x,y);
end
end
surf(xi,yi,pts)
end
p
end
Actual code that I'm working on:
function Eplot(z, w, R, Psi)
ni = 0:2:4;
mi = 0;
xi = -30:30;
yi = -30:30;
pts = zeros(size(xi,2),size(yi,2));
for n = ni
for m = mi
for x = xi
for y = yi
pts(x,y) = pts(x,y) + utot(z, x/10^4, y/10^4, n, m, w, R, Psi);
end
end
end
end
surf(xi,yi,pts)
end
Eplot(zi, wi, Ri, Psii)

Use meshgrid (as stated in the documentation for surf) and write your function f to use element-by-element operations so that it can take matrix input.
f = #(x,y) y.*sin(x) + sqrt(y);
xi = -30:30;
yi = -30:30;
[x,y]=meshgrid(xi,yi);
surf(xi,yi,f(x,y))
(Also, I hope you don'y really want to plot sqrt(y) for negative values of y)
If you can't write your function in such a way that allows you to give it vector arguments, then your for loop is a reasonable method, but I would write it like this:
f = #(x,y) y.*sin(x) + sqrt(y);
xi = -30:30;
yi = -30:30;
pts=zeros(length(xi),length(yi));
for ii=1:length(xi)
for jj=1:length(yi)
pts(ii,jj)=f(xi(ii),yi(jj));
%// If `f` has more variables to iterate over (n, m, etc.) and sum,
%// do those loops inside the ii and jj loops
%// I think it makes the code easier to follow
end
end
surf(xi,yi,pts)

Related

How to evaluate function of two variables with different x and y vectors

I've been trying to evaluate a function in matlab. I want my x vector to go from 0 to 1000 and my y vector to go from 0 to 125. They should both have a length of 101.
The equation to be evaluated is z(x,y) = ay + bx, with a=10 and b=20.
a = 10;
b = 20;
n = 101;
dx = 10; % Interval length
dy = 1.25;
x = zeros(1,n);
y = zeros(1,n);
z = zeros(n,n);
for i = 1:n;
x(i) = dx*(i-1);
y(i) = dy*(i-1);
for j = 1:n;
z(i,j) = a*dy*(j-1) + b*dx*(j-1);
end
end
I get an answer, but I don't know if I did it correctly with the indices in the nested for loop?
See MATLAB's linspace function.
a=10;
b=20;
n=101;
x=linspace(0,1000,n);
y=linspace(0,125,n);
z=a*y+b*x;
This is easier and takes care of the interval spacing for you. From the linspace documentation,
y = linspace(x1,x2,n) generates n points. The spacing between the points is (x2-x1)/(n-1).
Edit:
As others have pointed out, my solution above makes a vector, not a matrix which the OP seems to want. As #obchardon pointed out, you can use meshgrid to make that 2D grid of x and y points to generate a matrix of z. Updated approached would be:
a=10;
b=20;
n=101;
x=linspace(0,1000,n);
y=linspace(0,125,n);
[X,Y] = meshgrid(x,y);
z=a*Y+b*X;
(you may swap the order of x and y depending on if you want each variable along the row or column of z.)

Issue with Lagrange interpolation in Matlab

I'm having an issue completing this Lagrange function and I'm not sure where I'm going wrong.
I keep getting 'Index exceeds matrix dimensions' error. I assume this is because I'm not moving through the array correctly. I've tried a combination of things but seem to continue coming back to this error.
function y = lagrange(X, Y, x)
n = length(X);
if n ~= length(Y)
error('X and Y must have the same length.');
end
y = zeros(size(x));
for i = 1:n
L = ones(size(x));
for j = [1:i-1 i+1:n]
if (i~=j)
L(1:i-1, i+1:n) = L(1:i-1, i+1:n).*(x-X(j))/(X(i)-X(j));
end
end
y = y+Y(i)*L(1:i-1);
end
I think the function below is what you need.
function y = lagrangian(X, Y, x)
if length(X) ~= length(Y); error('X and Y must have the same length.'); end
y = zeros(size(x));
for i = 1:length(X)
L = ones(size(x));
for j = [1:i-1 i+1:length(X)]
L = L.*(x-X(j))/(X(i)-X(j));
end
y = y+Y(i)*L;
end

Plot solution of second order equation in MATLAB

Could you please help me with the following question:
I want to solve a second order equation with two unknowns and use the results to plot an ellipse.
Here is my function:
fun = #(x) [x(1) x(2)]*V*[x(1) x(2)]'-c
V is 2x2 symmetric matrix, c is a positive constant and there are two unknowns, x1 and x2.
If I solve the equation using fsolve, I notice that the solution is very sensitive to the initial values
fsolve(fun, [1 1])
Is it possible to get the solution to this equation without providing an exact starting value, but rather a range? For example, I would like to see the possible combinations for x1, x2 \in (-4,4)
Using ezplot I obtain the desired graphical output, but not the solution of the equation.
fh= #(x1,x2) [x1 x2]*V*[x1 x2]'-c;
ezplot(fh)
axis equal
Is there a way to have both?
Thanks a lot!
you can take the XData and YData from ezplot:
c = rand;
V = rand(2);
V = V + V';
fh= #(x1,x2) [x1 x2]*V*[x1 x2]'-c;
h = ezplot(fh,[-4,4,-4,4]); % plot in range
axis equal
fun = #(x) [x(1) x(2)]*V*[x(1) x(2)]'-c;
X = fsolve(fun, [1 1]); % specific solution
hold on;
plot(x(1),x(2),'or');
% possible solutions in range
x1 = h.XData;
x2 = h.YData;
or you can use vector input to fsolve:
c = rand;
V = rand(2);
V = V + V';
x1 = linspace(-4,4,100)';
fun2 = #(x2) sum(([x1 x2]*V).*[x1 x2],2)-c;
x2 = fsolve(fun2, ones(size(x1)));
% remove invalid values
tol = 1e-2;
x2(abs(fun2(x2)) > tol) = nan;
plot(x1,x2,'.b')
However, the easiest and most straight forward approach is to rearrange the ellipse matrix form in a quadratic equation form:
k = rand;
V = rand(2);
V = V + V';
a = V(1,1);
b = V(1,2);
c = V(2,2);
% rearange terms in the form of quadratic equation:
% a*x1^2 + (2*b*x2)*x1 + (c*x2^2) = k;
% a*x1^2 + (2*b*x2)*x1 + (c*x2^2 - k) = 0;
x2 = linspace(-4,4,1000);
A = a;
B = (2*b*x2);
C = (c*x2.^2 - k);
% solve regular quadratic equation
dicriminant = B.^2 - 4*A.*C;
x1_1 = (-B - sqrt(dicriminant))./(2*A);
x1_2 = (-B + sqrt(dicriminant))./(2*A);
x1_1(dicriminant < 0) = nan;
x1_2(dicriminant < 0) = nan;
% plot
plot(x1_1,x2,'.b')
hold on
plot(x1_2,x2,'.g')
hold off

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

Plotting a function of x over a range of D

I am trying to plot this function in MATLAB:
f(x) = (1./(2*b))*((erf(1./(2*D)+((x/b)-2*n)/D)+ erf(1./(2*D)-((x/b)-2*n)/D)));
The function is to plotted as a sum of n values from 0 to N, where N is a real number and b is a constant; for a range of D values. I am supposed to have different plots for each value in range D representing the function. How can I go about this please?
The different ranges of D can be done like this:
f = #(x, D)(x + D);
x = -10:10; %// pick a good range
D = 1:5; %// pick a good range
figure()
hold all
for d = D
plot(x, f(x, d))
end
I'm not 100% sure what you mean about the summing 0:N bit but maybe it's something of this form:
figure()
hold all
x= -10:10;
for d = 1:5
y = zeros(size(x)); %// Preallocation of memory for speed
for n = 0:10
y = y + n*x + d
end
plot(x, y)
end