I have solved the heat equation in octave via finite difference and produced the following 3-D plot whose point colors correspond to the temperatures in each element of my three dimensional hamburger.
My computational resources limit the resolution at which I may solve my burger. Thus the only way to get the plot I want is to make my scatter3 points huge blobs of color and it looks kind of bad.
[x,y,z] = meshgrid(1:nx,1:ny,1:nz) % Defines a grid to plot on
scatter3(x(:), y(:), z(:), 40, burgermatrix(:), 's', 'filled')% Point color=value
What I want is a nice gorgeous smooth rectangular prism like this:
So I figure I need to somehow interpolate between the 3D points that I have. Can anyone help me figure out how to do this?
I might be missing something obvious, but here's the example from octave's help slice:
[x, y, z] = meshgrid (linspace (-8, 8, 32));
v = sin (sqrt (x.^2 + y.^2 + z.^2)) ./ (sqrt (x.^2 + y.^2 + z.^2));
slice (x, y, z, v, [], 0, []);
[xi, yi] = meshgrid (linspace (-7, 7));
zi = xi + yi;
slice (x, y, z, v, xi, yi, zi);
shading interp; %addition by me
Isn't this exactly what you need? You have your grid (x,y,z), your solutions (T), so you just need to plot it slicing along [0 0 1] etc. Something like
[xi yi]=meshgrid(unique(x),unique(y));
slice (x, y, z, T, xi, yi, max(z(:))*ones(size(xi)));
and the same for cuts along the two other axes. (Obviously the unique calls should be substituted with the vectors you already have from which you constructed the 3d mesh in the first place.)
NOTE: By the way, you should really consider changing the default (jet) colormap. I was yesterday enlightened by a colleague about the viridis colormap made by the SciPy people, see for instance this post and video link therein. Their reasoning is overwhelming, and their colormap is beautiful. This should define it: viridis, although I haven't tried it myself yet.
(If it wasn't for jet, I'd tell you that your temperature profile seems strongly 1d. Do you happen to have periodic boundary conditions along the vertical walls and homogeneous (i.e. constant) boundary conditions along the horizontal ones?)
Related
I need to plot a parabola and ellipse. However the ellipse is giving me trouble. Can anyone help? The equations are: y = -5*x^2 + 2 and (x^2/16) + (y^2/2) = 4
I've tried this code but obviously I feel like like it isn't right.
x = linspace(-5, 5);
y1 = (x.^2/16) + (y.^2/2) - 1;
y2 = -5*x.^2 +2;
figure(1)
plot(x, y1)
hold on
plot(x, y2)
hold off
Firstly, you did not define a range variable x. Secondly, the ellipse won't pass the vertical line test and can't be plotted like a regular function f(x). Thirdly, your equation y1 = (x.^2/16) + (y.^2/2) - 1; is non-sensical because you have y on each side.
You could correct your method by defining a range variable x1 and x2 that each have appropriate ranges for the functions your plotting. What I mean by this is that you probably don't want the same range for each function, because the ellipse is undefined over most of the range that the parabola is defined. To plot the ellipse using f(x) you could observe that there are + and - values that are identical, using this fact you could plot your ellipse by two functions one to represent the top half and one to represent the bottom half, each of these would pass the vertical line test.
OR
You could utilize ezplot and have a nice time with it because it makes your life easier. Here is a solution.
ezplot('x^2/16+y^2/2-4'); axis equal; hold on
ezplot('-5*x^2+2-y')
There are multiple ways to plot an ellipse, e.g. you could also use a parametric representation of the equation.
In your approach though, when plotting functions using plot(x,y) command, you need to express your dependent variable (y) through independent variable (x). You defined the range for x, which is what you substitute into your equations in order to find y's. While for the parabola, the dependency of y from x is obvious, you forgot to derive such a relationship for the ellipse. In this case it will be +-sqrt((1 - x^2/16)*2). So in your approach, you'll have to take into account both negative and positive y's for the same value of x. Also there's discrepancy in your written equation for the ellipse (=4) and the one in Matlab code (=1).
x = linspace(-5, 5);
y1 = sqrt((1 - x.^2/16)*2);
y2 = -5*x.^2 +2;
figure(1)
plot(x, real(y1), 'r', x, -real(y1), 'r')
hold on
plot(x, y2)
hold off
Since the ellipse has real y's not on the whole x domain, if you want to plot only real parts, specify real(y1) or abs(y1) (even though Matlab does it for you, too). You can also dismiss complex numbers for certain x when computing y1, but you'll need a for-loop for that.
In order to make things simpler, you can check the function fimplicit, ezplot is not recommended according to Matlab's documentation. Or if you want to plot the ellipse in a parametric way, fplot will work, too.
Another (more classic) approach for parametric plotting is given here already, then you don't need any other functions than what you already use. I think it is the simplest and most elegant way to plot an ellipse.
You will not be able to generate points for the ellipse using a function f(x) from a Cartesian linspace range. Instead, you can still use linspace but for the angle in a polar notation, from 0 to 2*pi. You should also be able to easily adjust radius and offset on both axis on the cos and sin expressions.
x = linspace(-5, 5);
y2 = -5*x.^2 +2;
figure(1)
clf;
plot(x, y2)
hold on
a = linspace(0,2*pi);
x2 = 4*cos(a);
y2 = sqrt(2)*sin(a);
plot(x2, y2)
xlim([-5,5]);
ylim([-5,5]);
hold off
I have three different surfaces and I want to display all of them in one figure.
The problem is, that I have one surface defined in terms of z (means that I got x and y values and a grid which specifies the z-values for each combination) and two other ones which are defined in terms of x. This means that there exist various z-values for one x,y-pair.
My idea was:
figure
surf(x,y,zgrid)
hold on
surf(x,ygrid,z)
surf(x,ygrid2,z)
hold off
I hoped MATLAB would manage it by itself but it doesn't.
Do you have any ideas how to get the wanted results? I want to display all of them in one plot to show the cross-sections.
Here is an image of how it should more or less look like:
If there is a more beautiful method to display this, please let me know.
You didn't specify what exactly was going wrong, but I'll hazard an educated guess that you got an error like the following when you tried to plot your second surface:
Error using surf (line 82)
Z must be a matrix, not a scalar or vector.
I'm guessing your x, y, and z variables are vectors, instead of matrices. The surf function allows for the X and Y inputs to be vectors, which it then expands into matrices using meshgrid. It doesn't do this for the Z input, though.
It's best practice, in my opinion, to just use matrices for all your inputs anyway. Here's an example where I do this (using meshgrid) to plot three surfaces of a cube:
% Top surface (in z plane):
[x, y] = meshgrid(1:10, 1:10);
surf(x, y, 10.*ones(10), 'FaceColor', 'r');
hold on;
% Front surface (in y plane):
[x, z] = meshgrid(1:10, 1:10);
surf(x, ones(10), z, 'FaceColor', 'b');
% Side surface (in x plane):
[y, z] = meshgrid(1:10, 1:10);
surf(ones(10), y, z, 'FaceColor', 'g');
axis equal
And here's the plot:
I have the following function (z) that should output a graphic which if sliced at f(x,y) = 0.001 the result image should be a message.
I wrote this code but I`m unable to slice it right
[x,y] = meshgrid(-1.5:0.3:1.5,-2.5:0.5:2.5) ;
z=exp(-4*x.^2-2*y.^2)*cos(8*x)+exp(-3*((2*x+1)/2).^2-6*y.^2);
% meshc (x,y,z, [0.001 0.001]);
meshc (x,y,z);
What did i miss?
You are likely looking for the countour function instead of meshc. meshc plots a contour plot under a mesh plot, but you don't need a mesh plot to view the message. In fact, the countour docs show an example of how to only plot a specific level:
contour(x, y, z, [0.001 0.001])
I also suspect that your function is not defined correctly. exp(...) * cos(...) should probably read exp(...) .* cos(...):
The poor granularity leads me to believe that the sample spacing should be decreased (i.e., the grid should be made finer):
[x,y] = meshgrid(-1.5:0.003:1.5,-2.5:0.005:2.5);
Contouring the original function with the finer spacing also shows why I think * should probably be .* in the expression:
[x,y] = meshgrid(-1.5:0.003:1.5,-2.5:0.005:2.5);
z=exp(-4*x.^2-2*y.^2)*cos(8*x)+exp(-3*((2*x+1)/2).^2-6*y.^2);
contour(x, y, z, [0.001 0.001])
Unless the message is a count of sausage shapes, I think that the .* version is more likely to contain useful information (looks like HI).
You'll want to use contour rather than meshc to plot the intersection of your mesh with 0.001 so that you can specify exactly at what value you'd like to compute the contour.
contour(x, y, z, [0.001 0.001]);
If you do want to use meshc, you can use the output which contains a handle to the contour plot to set the LevelList property to your desired value
h = meshc(x, y, z);
set(findobj(h, 'type', 'contour'), 'LevelList', [0.001 0.001])
As far as getting an intelligible message out, I guess intelligent is in the eye of the beholder
I have an issue where I have my data formatted such that I have n data points in the Z axis, and every Z data point has m corresponding x & y points. I essentially want to have n 2D m-point plots, but merged into one surface.
My data takes the following form:
z = [0 1 2 3]
data(:, :, 1) = [0 1 2; 2 2 2] (the first row corresponds to the x points, second to the y; the page (the 1) corresponds to the respective z point at which I am plotting said x and y points)
So essentially, at z(i), I would like to have data(:, :, i) plotted. Then finally all merged together into one surface. How would I accomplish this?
An example that might help imagine the situation is if data(:, :, i) for all i was uniform, like the above sample, then a cube surface (of volume 12) would be drawn.
So essentially, at z(i), I would like to have data(:, :, i) plotted. Then finally all merged together into one surface. How would I accomplish this?
Use scatter3 to plot 3-D scatter plot, for every points with a set of x,y,z value.
Alternatively, use plot3 to make 3-D line plot. Be careful with the argument formats.
You can use code like
for ii = 1:length(z)
x = data(1, :, ii);
y = data(2, :, ii);
scatter3(x, y, z*ones(1, length(x));
end
Finally, rotate your angle of view using view([0,0,-1]) to the direction facing the z axis. By this, all layers of different z values are squeezed into one layer.
If you really mean you want to ignore the z-values, but only want to see an overlayed plot of all the points,
for ii = 1:length(z)
x = data(1, :, ii);
y = data(2, :, ii);
scatter(x, y);
end
An example that might help imagine the situation is if data(:, :, i) for all i was uniform, like the above sample, then a cube surface (of volume 12) would be drawn.
As #rayryeng commented, I found this difficult to imagine. What do you mean by "a cube surface of volume 12"? This part looks different than descriptions above it.
I have this function:
and I want plot it, I think the result is a periodic function...
I tried this but got only one point :(
x1=-50:0.1:50;
x2=-50:0.1:50;
plot(cos(sqrt(power(x1,2)+power(x2,2)))/(power(x1,2)+power(x2,2)));
where is my problem and what is the correct way?
appreciate any help.
You need to plot it as a 3-D surface. For example, use surf:
[X1, X2] = meshgrid(-5:0.25:5, -5:0.25:5);
F = cos(sqrt(X1 .^ 2 + X2 .^ 2)) ./ (X1 .^ 2 + X2 .^ 2 + 1);
surf(X1, X2, F)
Note two things:
You forgot the "+1" in the denominator.
I've reduced the range of x1 and x2 coordinates, for better visualization.
If the black edges look annoying and seem to clutter the plot, you can remove the edge lines by disabling the EdgeColor property (as user Shai pointed out):
surf(X1, X2, F, 'EdgeColor', 'None')
The final result should look something like this:
That's a 3d plot, since there are two inputs x1 and x2. So you've got to use plot3 (or surf as #EitanT points out, or any 3d plotting function).
You're now only plotting the pairs (-50;-50), (-49.9;-49.9),...,(50;50), because you start from two vectors, you probably want to cover all the combinations. Therefore, use meshgrid (for higher dimensions, there is also ndgrid):
x1=-50:0.1:50;
x2=-50:0.1:50;
[X1, X2] = meshgrid(x1,x2);
You now use matrix operations, read through this link and you'll see that you need elementwise operations: a.*b instead of a*b, etc. power(a,b) is already the element-wise operation (the same as a.^b), matrix equivalent is mpower(a,b) or a^b.
f = cos(sqrt(power(X1,2)+power(X2,2)))./(power(X1,2)+power(X2,2)+1);
plot3(X1,X2,f);