Potential flow, define theta in matlab - matlab

I have made this matlab script for a potential flow around a cylinder and I would like to add a point source. See the definition of point source in picture. How can you define theta in matlab? And plot this its streamlines Psi?
clear
% make axes
xymax = 2;
x = linspace(-xymax,xymax,100);
y = linspace(-xymax,xymax,100);
% note that x and y don't include 0
[xmesh,ymesh] = meshgrid(x,y);
x_c=0;
y_c=0;
q=1;
U=1
r = sqrt((xmesh-x_c).^2+(ymesh-y_c).^2);
sin_th= ((ymesh-y_c)./r)
%(ymesh-y_c)./r = sin(teta)
%(xmesh-x_c)./r = cos(teta)
psi1 = -q./r.*((ymesh-y_c)./r);
psi2 = r.*sin_th;
psi=psi1+psi2;
figure
contour(xmesh,ymesh,psi,[-xymax:.25:xymax],'-b');

To plot the streamlines in potential flow you are correct that you have to plot contour lines of constant stream function.
In the case of a point source, if you are plotting in cartesian coordinates in MATLAB you have to convert theta to cartesian coordinates using arctangent as follows: theta = arctan(y/x). In MATLAB use the function atan2 which will limit the number of discontinuities to between -PI and PI: https://www.mathworks.com/help/matlab/ref/atan2.html
Your code should read: psi2 = ( m/(2*PI) ) * atan2(y,x)
For more information on plotting elements of potential flow in 2D cartesian coordinates, see more information here:
https://potentialflow.com/flow-elements
https://potentialflow.com/equations

Related

pchip for angular data

I'm trying to fit a shape perserving interpolation curve to my angular data (r/phi).
However, as I have repeated x-values when I transform the datapoints to (x/y), I can not simply use pchip.
I know for spline interpolation, there is cscvn and fnplt, is there anything similar for pchip?
Furthermore, there is an example of spline fitting to angular data in the matlab documentation of "spline", but I don't quite get it how I could adapt it to pchip and different data points.
I also found the interparc-function by John d'Errico, but I would like to keep my datapoints instead of having equally spaced ones.
To make it clearer, here a figure of my datapoints with linear (blue) and spline interpolation (black). The curve I'd like to get would be something in between this two, without the steep edges in the linear case but with less overshoot than in the spline case....
Thanks for your help!
use 1D parametric interpolation:
n = 20;
r = 1 + rand(n-1,1)*0.01;%noisy r's
theta = sort(2*pi*rand(n-1,1));
% closing the circle
r(end+1) = r(1);
theta(end+1) = theta(1);
% convert to cartesian
[x,y] = pol2cart(theta,r);
% interpolate with parameter t
t = (1:n)';
v = [x,y];
tt = linspace(1,n,100);
X = interp1(t,v,tt,'pchip');
% plot
plot(x,y,'o');
hold on
plot(X(:,1),X(:,2));

Smooth Contour Plot in matlab

I want to plot smooth contour plot from X Y Z matrix.
sf = fit([X Y] Z, 'poly23');
plot(sf);
I have not enought smooth curve..
What I need?
You can use the functions such as griddata and csaps. Together they will lead you to the result as smooth as you wish. The first function adds additional points to your data matrix set. The second one makes the result smoother. The example of the code is below. In the example smoothing is done first in X direction and then in Y direction. Try to play around with the resolution and smoothing_parameter (the current set of these parameters should be OK though).
x = min_x:step_x:max_x;
y = min_y:step_y:max_y;
resolution = 10;
xg = min_x:(step_x/resolution):max_x;
yg = min_y:(step_y/resolution):max_y;
[X,Y] = meshgrid(x,y);
[XG,YG] = meshgrid(xg,yg);
smoothing_parameter = 0.02;
fitted = griddata(X,Y,Z,XG,YG,'cubic');
fitted_smoothed_x = csaps(xg,fitted,smoothing_parameter,xg);
fitted_smoothed_xy = csaps(yg,fitted_smoothed_x',smoothing_parameter,yg);
surf(XG,YG,fitted_smoothed_xy');
EDIT: If you want to get just a contour plot, you can do, for example, as presented below. As I don't have the real data, I will use build-in function peaks to generate some.
[X,Y,Z] = peaks(30);
figure
surfc(X,Y,Z)
view([0 90])
zlim([-10 -8])
Here you just look at your contour plot from above being below the surface.

Draw a line with non-Cartesian coordinates in MATLAB

MATLAB's surf command allows you to pass it optional X and Y data that specify non-cartesian x-y components. (they essentially change the basis vectors). I desire to pass similar arguments to a function that will draw a line.
How do I plot a line using a non-cartesian coordinate system?
My apologies if my terminology is a little off. This still might technically be a cartesian space but it wouldn't be square in the sense that one unit in the x-direction is orthogonal to one unit in the y-direction. If you can correct my terminology, I would really appreciate it!
EDIT:
Below better demonstrates what I mean:
The commands:
datA=1:10;
datB=1:10;
X=cosd(8*datA)'*datB;
Y=datA'*log10(datB*3);
Z=ones(size(datA'))*cosd(datB);
XX=X./(1+Z);
YY=Y./(1+Z);
surf(XX,YY,eye(10)); view([0 0 1])
produces the following graph:
Here, the X and Y dimensions are not orthogonal nor equi-spaced. One unit in x could correspond to 5 cm in the x direction but the next one unit in x could correspond to 2 cm in the x direction + 1 cm in the y direction. I desire to replicate this functionality but drawing a line instead of a surf For instance, I'm looking for a function where:
straightLine=[(1:10)' (1:10)'];
my_line(XX,YY,straightLine(:,1),straightLine(:,2))
would produce a line that traced the red squares on the surf graph.
I'm still not certain of what your input data are about, and what you want to plot. However, from how you want to plot it, I can help.
When you call
surf(XX,YY,eye(10)); view([0 0 1]);
and want to get only the "red parts", i.e. the maxima of the function, you are essentially selecting a subset of the XX, YY matrices using the diagonal matrix as indicator. So you could select those points manually, and use plot to plot them as a line:
Xplot = diag(XX);
Yplot = diag(YY);
plot(Xplot,Yplot,'r.-');
The call to diag(XX) will take the diagonal elements of the matrix XX, which is exactly where you'll get the red patches when you use surf with the z data according to eye().
Result:
Also, if you're just trying to do what your example states, then there's no need to use matrices just to take out the diagonal eventually. Here's the same result, using elementwise operations on your input vectors:
datA = 1:10;
datB = 1:10;
X2 = cosd(8*datA).*datB;
Y2 = datA.*log10(datB*3);
Z2 = cosd(datB);
XX2 = X2./(1+Z2);
YY2 = Y2./(1+Z2);
plot(Xplot,Yplot,'rs-',XX2,YY2,'bo--','linewidth',2,'markersize',10);
legend('original','vector')
Result:
Matlab has many built-in function to assist you.
In 2D the easiest way to do this is polar that allows you to make a graph using theta and rho vectors:
theta = linspace(0,2*pi,100);
r = sin(2*theta);
figure(1)
polar(theta, r), grid on
So, you would get this.
There also is pol2cart function that would convert your data into x and y format:
[x,y] = pol2cart(theta,r);
figure(2)
plot(x, y), grid on
This would look slightly different
Then, if we extend this to 3D, you are only left with plot3. So, If you have data like:
theta = linspace(0,10*pi,500);
r = ones(size(theta));
z = linspace(-10,10,500);
you need to use pol2cart with 3 arguments to produce this:
[x,y,z] = pol2cart(theta,r,z);
figure(3)
plot3(x,y,z),grid on
Finally, if you have spherical data, you have sph2cart:
theta = linspace(0,2*pi,100);
phi = linspace(-pi/2,pi/2,100);
rho = sin(2*theta - phi);
[x,y,z] = sph2cart(theta, phi, rho);
figure(4)
plot3(x,y,z),grid on
view([-150 70])
That would look this way

Matlab - How can I get the expression of the level curves of a function?

I would like to obtain the level curves of a given function z=f(x,y) without using the countours function in the Matlab environment.
By letting Z equal to some constant 'c' we get a single level curve. I would like to obtain an expression of the resulting function of the form y=f(x) to be able to study other properties of it.
Basic: Example 1: Easy game
Let's consider the problem of plotting level curves of z=-x^2-y^2+100 for x,y:-10;10 and z=1.
[X,Y] = meshgrid(-10:.1:10);
Z = -X.^2+-(Y).^2+100;
surf(X,Y,Z)
we obtain the following figure:
The countour function gives me what I was looking for:
h=[1,1]
contour(X,Y,Z,h)
I can get the same result by solving the equation with respect to x
syms x y;
soly = solve(1==-x.^2-y^2+100, y)
t=soly(1)
x=-10:0.1:10;
figure;
plot(x,(99-x.^2).^(1/2));
hold on
plot(x,-(99-x.^2).^(1/2));
soly =
(99 - x^2)^(1/2)
-(99 - x^2)^(1/2)
The Problem: Example 2
Let's consider the following 3D function.
This function is the sum of guassians with random centers, variances and peaks. You can get it with the following code:
%% Random Radial Basis functions in space
disp('3D case with random path - 10 rbf:');
N = 10 % number of random functions
stepMesh = 0.1;
Z = zeros((XMax-XMin)/stepMesh+1,(XMax-XMin)/stepMesh+1);
[X,Y] = meshgrid(XMin:stepMesh:XMax);
% random variance in [a;b] = [0.3;1.5]
variances = 0.3 + (1.5-0.3).*rand(N,1);
% random amplitude [0.1;1]
amplitudes = 0.1 + (1-0.1).*rand(N,1);
% Random Xcenters in [-XMin;xMax]
Xcenters = XMin+ (XMax-XMin).*rand(N,1);
Ycenters = YMin+ (YMax-YMin).*rand(N,1);
esp=zeros(N,1);
esp=1./(2*(variances).^2);
for i=1:1:N
disp('step:')
disp(i)
Xci=Xcenters(i,1)*ones((XMax-XMin)/stepMesh+1,((XMax-XMin)/stepMesh+1)*2);
Yci=Ycenters(i,1)*ones((YMax-YMin)/stepMesh+1,((YMax-YMin)/stepMesh+1)*2);
disp('Radial Basis Function: [amplitude,variance,center]');
disp(amplitudes(i,1))
disp(variances(i,1))
disp(Xcenters(i,1))
disp(Ycenters(i,1))
Z = Z + 1*exp(-((X-Xci(:,1:((XMax-XMin)/stepMesh+1))).^2+(Y-Yci(:,((XMax-XMin)/stepMesh+2):((YMax-YMin)/stepMesh+1)*2)).^2)*esp(i,1).^2);
end
surf(X,Y,Z)
The countour3 function draws a contour plot of matrix Z in a 3-D view, which is really nice, but it doesn't give me the expression of these functions in 2D.
figure;
contour3(X,Y,Z);
grid on
box on
view([130,30])
xlabel('x-axis')
ylabel('y-axis')
zlabel('z-axis')
The Question:
How can I get an explicit expression of the level curves of the second example?

Direct 2D FFT from sinogram. Polar to cartesian grid interpolation in Matlab

In the theory of tomography imaging a sinogram is recorderded, which is series of projections at different angles of the sample. Taking FFT of this projections gives a slice in polar coordinates of the sample in the frequency space.
The command [X,Y] = pol2cart(THETA,RHO) will not do it automatically. So, how is the polar to cartesian grid interpolation implemented numerically in 2D in Matlab?
You need to do a phase transformation:
theta = 0:0.1:2*pi;
rho = linspace(0,1,numel(theta));
[x,y] = pol2cart(-theta+pi/2,rho);
figure;
subplot(1,2,1);
polar(theta,rho);
subplot(1,2,2);
plot(y,x);
axis([-1 1 -1 1]);
grid on;
The function [X,Y] = pol2cart(THETA,RHO) only performs the coordinate value conversion, i.e., X = RHO * cos(THETA) and Y = RHO * sin(THETA). However, what you need is the conversion of the data array, thus pol2cart() can do nothing to your problem.
You can refer to the function interp2(). On the other hand, since this problem is the interpolation with COMPLEX data, I am NOT sure whether interp2() could do the job directly. I also need the theory for complex interpolation.