Code result fails to appear here in the table produced by it.
In essence only the fifth row fills up for some reason. Aim of this code is to calculate principal stresses with MATLAB. No clue what specifically went wrong.
syms
sigma_max sigma_min tau_max alpha primary_direction_x_x_value primary_direction_x_y_value primary_direction_y_x_value primary_direction_y_y_value
sigma_max=0.5*((sigma_xx)+(sigma_yy))+sqrt(0.25*(((sigma_xx)-(sigma_yy))^2)+(sigma_xy)^2); %physics
sigma_min=0.5*((sigma_xx)+(sigma_yy))-sqrt(0.25*(((sigma_xx)-(sigma_yy))^2)+(sigma_xy)^2);
tau_max=0.5*((sigma_max)-(sigma_min));
%physics
alpha=(180/pi)*0.5*(atan((2*sigma_xy)/(sigma_xx-sigma_yy)));
primary_direction_x_x_value=cosd(alpha);
primary_direction_x_y_value=sind(alpha);
%
primary_direction_y_x_value=-sind(alpha);
primary_direction_y_y_value=cosd(alpha);
%physics
xx=[60 200 900 400 0];
yy=[0 -200 100 800 240];
xy=[40 -200 200 600 120];
for n = 1:length(xx)
sigma_xx=xx(n);
sigma_yy=yy(n);
sigma_xy=xy(n);
A=zeros(1,5);
A(n)=sigma_max;
B=zeros(1,5);
B(n)=sigma_min;
H=zeros(1,5);
H(n)=tau_max;
C=zeros(1,5);
C(n)=alpha;
D=zeros(1,5);
D(n)=primary_direction_x_x_value;
E=zeros(1,5);
E(n)=primary_direction_x_y_value;
F=zeros(1,5);
F(n)=primary_direction_y_x_value;
G=zeros(1,5);
G(n)=primary_direction_y_y_value;
end
varNames = {'σ max [Mpa]';'σ min [Mpa]';'tau max [Mpa]';'alpha [°]';'primary direction x x value';'primary direction x y value';'primary direction y x value';'primary direction y y value'};
T=table(A',B',H',C',D',E',F',G','VariableNames',varNames)
Shouldn't the initialization statements like A=zeros(1,5); be outside of the loop?
Right now for each n the vectors A, B, C, D, E, F and G are cleared overwriting them with all zeros.
syms n
format bank
A=zeros(1,5);
B=zeros(1,5);
H=zeros(1,5);
C=zeros(1,5);
D=zeros(1,5);
E=zeros(1,5);
F=zeros(1,5);
G=zeros(1,5);
I=zeros(1,5);
J=zeros(1,5);
K=zeros(1,5);
Input=[60 200 900 400 0
0 -200 100 800 240
40 -200 200 600 120]';
for n = 1:5
sigma_xx=Input(n,1);
sigma_yy=Input(n,2);
sigma_xy=Input(n,3);
sigma_max=0.5*((sigma_xx)+(sigma_yy))+sqrt(0.25*(((sigma_xx)-(sigma_yy))^2)+(sigma_xy)^2);%physics
sigma_min=0.5*((sigma_xx)+(sigma_yy))-sqrt(0.25*(((sigma_xx)-(sigma_yy))^2)+(sigma_xy)^2);%physics
tau_max=0.5*((sigma_max)-(sigma_min)); %physics
alpha=(180/pi)*0.5*(atan((2*sigma_xy)/(sigma_xx-sigma_yy)));%physics
primary_direction_x_x_value=cosd(alpha);%physics
primary_direction_x_y_value=sind(alpha);%physics
primary_direction_y_x_value=-sind(alpha);%physics
primary_direction_y_y_value=cosd(alpha);%physics
sigma_xxRe= 0.5*((sigma_xx)+(sigma_yy))+0.5*(((sigma_xx)-(sigma_yy))*cosd(2*alpha))+(sigma_xy)*sind(2*alpha);%physics - Rotation of stress component.
sigma_yyRe= 0.5*((sigma_xx)+(sigma_yy))-0.5*(((sigma_xx)-(sigma_yy))*cosd(2*alpha))-(sigma_xy)*sind(2*alpha);%physics
sigma_xyRe=0.5*((-(sigma_xx)+(sigma_yy))*sind(2*alpha))+(sigma_xy)*cosd(2*alpha);%physics
A(n)=sigma_max;
B(n)=sigma_min;
H(n)=tau_max;
C(n)=alpha;
D(n)=primary_direction_x_x_value;
E(n)=primary_direction_x_y_value;
F(n)=primary_direction_y_x_value;
G(n)=primary_direction_y_y_value;
I(n)=sigma_xxRe;
J(n)=sigma_yyRe;
K(n)=sigma_xyRe;
end
varNames = {'σ max [Mpa]';'σ min [Mpa]';'tau max [Mpa]';'alpha [°]';'primary direction x x value';'primary direction x y value';'primary direction y x value';'primary direction y y value';'σ xx revolved';'σ yy revolved';'σ xy revolved'};
T=table(A',B',H',C',D',E',F',G',I',J',K','VariableNames',varNames)
This code solves the problem since
1.A=zeros(1,5) no longer annihlates all that was put into it when it was in the loop, but rather it SAVES it in proper cells.
2.The input was changed to one single matrix since for some reason it is much easier for the loop to deal with a whole coherent matrix rather than several vectors, each of which contains some part of input data necessary for calculation.
3. May this be useful to whomever might need to calculate principal stresses...
Example of Output
Related
I'm new to Matlab and want to write a program that chooses the value of a parameter (P) to minimize the difference between two vectors, where each vector is a variable in a dataframe. The first vector (call it A) is a predetermined vector of 1s and 0s, and the second vector (call it B) has each of its entries determined as an indicator function that depends on the value of the parameter P and other variables in the dataframe. For instance, let C be a third variable in the dataset, so
A = [1, 0, 0, 1, 0]
B = [x, y, z, u, v]
where x = 1 if (C[1]+10)^0.5 - P > (C[1])^0.5 and otherwise x = 0, and similarly, y = 1 if (C[2]+10)^0.5 - P > (C[2])^0.5 and otherwise y = 0, and so on.
I'm not really sure where to start with the code, except that it might be useful to use the fminsearch command. Any suggestions?
Edit: I changed the above by raising to a power, which is closer to the actual example that I have. I'm also providing a complete example in response to a comment:
Let A be as above, and let C = [10, 1, 100, 1000, 1]. Then my goal with the Matlab code would be to choose a value of P to minimize the differences between the coordinates of the vectors A and B, where B[1] = 1 if (10+10)^0.5 - P > (10)^0.5 and otherwise B[1] = 0, and similarly B[2] = 1 if (1+10)^0.5 - P > (1)^0.5 and otherwise B[2] = 0, etc. So I want to choose P to maximize the likelihood that A[1] = B[1], A[2] = B[2], etc.
I have the following setup in Matlab, where ds is the name of my dataset:
ds.B = zeros(size(ds,1),1); % empty vector to fill
for i = 1:size(ds,1)
if ((ds.C(i) + 10)^(0.5) - P > (ds.C(i))^(0.5))
ds.B(i) = 1;
else
ds.B(i) = 0;
end
end
Now I want to choose the value of P to minimize the difference between A and B. How can I do this?
EDIT: I'm also wondering how to do this when the inequality is something like (C[i]+10)^0.5 - P*D[i] > (C[i])^0.5, where D is another variable in my dataset. Now P is a scalar being multiplied rather than just added. This seems more complicated since I can't solve for P exactly. How can I solve the problem in this case?
EDIT 1: It seems fminbnd() isn't optimal, likely due to the stairstep nature of the indicator function. I've updated to test the midpoints of all the regions between indicator function flips, plus endpoints.
EDIT 2: Updated to include dataset D as a coefficient of P.
If you can package your distance calculation up in a single function based on P, you can then search for its minimum.
arraySize = 1000;
ds.A = double(rand([arraySize,1]) > 0.5);
ds.C = rand(size(ds.A));
ds.D = rand(size(ds.A));
B = #(P)double((ds.C+10).^0.5 - P.*ds.D > ds.C.^0.5);
costFcn = #(P)sqrt(sum((ds.A-B(P)).^2));
% Solving the equation (C+10)^0.5 - P*D = C^0.5 for P, and sorting the results
BCrossingPoints = sort(((ds.C+10).^0.5-ds.C.^0.5)./ds.D);
% Taking the average of each crossing point with its neighbors
BMidpoints = (BCrossingPoints(1:end-1)+BCrossingPoints(2:end))/2;
% Appending endpoints onto the midpoints
PsToTest = [BCrossingPoints(1)-0.1; BMidpoints; BCrossingPoints(end)+0.1];
% Calculate the distance from A to B at each P to test
costResult = arrayfun(costFcn,PsToTest);
% Find the minimum cost
[~,lowestCostIndex] = min(costResult);
% Find the optimum P
optimumP = PsToTest(lowestCostIndex);
ds.B = B(optimumP);
semilogx(PsToTest,costResult)
xlabel('P')
ylabel('Distance from A to B')
1.- x is assumed positive real only, because with x<0 then complex values show up.
Since no comment is made in the question it seems reasonable to assume x real and x>0 only.
As requested, P 'the parameter' a scalar, P only has 2 significant states >0 or <0, let's see how is this:
2.- The following lines generate kind-of random A and C.
Then a sweep of p is carried out and distances d1 and d2 are calculated.
d1 is euclidean distance and d2 is the absolute of the difference between A and and B converting both from binary to decimal:
N=10
% A=[1 0 0 1 0]
A=randi([0 1],1,N);
% C=[10 1 1e2 1e3 1]
C=randi([0 1e3],1,N)
p=[-1e4:1:1e4]; % parameter to optimize
B=zeros(1,numel(A));
d1=zeros(1,numel(p)); % euclidean distance
d2=zeros(1,numel(p)); % difference distance
for k1=1:1:numel(p)
B=(C+10).^.5-p(k1)>C.^.5;
d1(k1)=(sum((B-A).^2))^.5;
d2(k1)=abs(sum(A.*2.^[numel(A)-1:-1:0])-sum(B.*2.^[numel(A)-1:-1:0]));
end
figure;
plot(p,d1)
grid on
xlabel('p');title('d1')
figure
plot(p,d2)
grid on
xlabel('p');title('d2')
The only degree of freedom to optimise seems to be the sign of P regardless of |P| value.
3.- f(p,x) has either no root, or just one root, depending upon p
The threshold funtion is
if f(x)>0 then B(k)==1 else B(k)==0
this is
f(p,x)=(x+10)^.5-p-x^.5
Now
(x+10).^.5-p>x.^.5 is same as (x+10).^.5-x.^.5>p
There's a range of p that keeps f(p,x)=0 without any (real) root.
For the particular case p=0 then (x+10).^.5 and x.^.5 do not intersect (until Inf reached = there's no intersection)
figure;plot(x,(x+10).^.5,x,x.^.5);grid on
[![enter image description here][3]][3]
y2=diff((x+10).^.5-x.^.5)
figure;plot(x(2:end),y2);
grid on;xlabel('x')
title('y2=diff((x+10).^.5-x.^.5)')
[![enter image description here][3]][3]
% 005
This means the condition f(x)>0 is always true holding all bits of B=1. With B=1 then d(A,B) turns into d(A,1), a constant.
However, for a certain value of p then there's one root and f(x)>0 is always false keeping all bits of B=0.
In this case d(A,B) the cost function turns into d(A,0) and this is A itself.
4.- P as a vector
The optimization gains in degrees of freedom if instead of P scalar, P is considered as vector.
For a given x there's a value of p that switches B(k) from 0 to 1.
Any value of p below such threshold keeps B(k)=0.
Equivalently, inverting f(x) :
g(p)=(10-p^2)^2/(4*p^2)>x
Values of x below this threshold bring B closer to A because for each element of B it's flipped to the element value of A.
Therefore, it's convenient to consider P as a vector, not a ascalar, and :
For all, or as many (as possible) elements of C to meet c(k)<(10-p^2)^2/(4*p^2) in order to get C=A or
minimize d(A,C)
5.- roots of f(p,x)
syms t positive
p=[-1000:.1:1000];
zp=NaN*ones(1,numel(p));
sol=zeros(1,numel(p));
for k1=1:1:numel(p)
p(k1)
eq1=(t+10)^.5-p(k1)-t^.5-p(k1)==0;
s1=solve(eq1,t);
if ~isempty(s1)
zp(k1)=s1;
end
end
nzp=~isnan(zp);
zp(nzp)
returns
=
620.0100 151.2900 64.5344 34.2225 20.2500 12.7211
8.2451 5.4056 3.5260 2.2500 1.3753 0.7803
0.3882 0.1488 0.0278
I've made a plot of 10 points
10 10
248,628959661970 66,9462583977501
451,638770451973 939,398361884535
227,712826026548 18,1775336366957
804,449583613070 683,838613746355
986,104241895970 783,736480083219
29,9919502693899 534,137567882728
535,664190667238 885,359450931142
87,0772199008924 899,004898906140
990 990
With the first column as x-coordinates and the other column as y-coordinates
Leading to the following Plot:
Using the following code: scatter(Problem.Points(:,1),Problem.Points(:,2),'.b')
I then also calculated the euclidean distances using Problem.DistanceMatrix = pdist(Problem.Points);
Problem.DistanceMatrix = squareform(Problem.DistanceMatrix);
I replaced the distances by 1*10^6 when they are larger than a certain value.
This lead to the following table:
Then, I would like to plot the lines between the corresponding points, preferably with their distances, but only in case the distance < 1*10^6.
Specifically i want to plot the line [1,2] [1,4] [1,7] [2,4] etc.
My question is, can this be done and how?
Assuming one set of your data is in something called xdata and the other in ydata and then the distances in distances, the following code should accomplish what you want.
hold on
for k = 1:length(xdata)
for j = 1:length(ydata)
if(distances(k,j) < 1e6)
plot([xdata(k) xdata(j)], [ydata(k) ydata(j)]);
end
end
end
You just need to iterate through your matrix and then if the value is less than 1e6, then plot the line between the kth and jth index points. This will however double plot lines, so it will plot from k to j, and also from j to k, but it is quick to code and easy to understand. I got the following plot with this.
This should do the trick:
P = [
10.0000000000000 10.0000000000000;
248.6289596619700 66.9462583977501;
451.6387704519730 939.3983618845350;
227.7128260265480 18.1775336366957;
804.4495836130700 683.8386137463550;
986.1042418959700 783.7364800832190;
29.9919502693899 534.1375678827280;
535.6641906672380 885.3594509311420;
87.0772199008924 899.0048989061400;
990.0000000000000 990.0000000000000
];
P_len = size(P,1);
D = squareform(pdist(P));
D(D > 600) = 1e6;
scatter(P(:,1),P(:,2),'*b');
hold on;
for i = 1:P_len
pi = P(i,:);
for j = 1:P_len
pj = P(j,:);
d = D(i,j);
if ((d > 0) && (d < 1e6))
plot([pi(1) pj(1)],[pi(2) pj(2)],'-r');
end
end
end
hold off;
Final output:
On a side note, the part in which you replaces the distance values trespassing a certain treshold (it looks like it's 600 by looking at your distances matrix) with 1e6 can be avoided by just inserting that threshold into the loop for plotting the lines. I mean... it's not wrong, but I just think it's an unnecessary step.
D = squareform(pdist(P));
% ...
if ((d > 0) && (d < 600))
plot([pi(1) pj(1)],[pi(2) pj(2)],'-r');
end
A friend of mine suggested using gplot
gplot(Problem.AdjM, Problem.Points(:,:), '-o')
With problem.points as the coordinates and Problem.AdjM as the adjacency matrix. The Adjacency matrix was generated like this:
Problem.AdjM=Problem.DistanceMatrix;
Problem.AdjM(Problem.AdjM==1000000)=0;
Problem.AdjM(Problem.AdjM>0)=1;
Since the distances of 1*10^6 was the replacement of a distance that is too large, I put the adjacency there to 0 and all the other to 1.
This lead to the following plot, which was more or less what I wanted:
Since you people have been helping me in such a wonderful way, I just wanted to add this:
I added J. Mel's solution to my code, leading to two exactly the same figures:
Since the figures get the same outcome, both methods should be all right. Furthermore, since Tommasso's and J Mel's outcomes were equal earlier, Tommasso's code must also be correct.
Many thanks to both of you and all other people contributing!
I have a table with two sets of values.
And I want to create equally sized bins of x, count the number of values of y in each bin and then plot it.
How can I do it?
Data
x y
0 0.0023243872
815.54065 0.0021484715
1111.9492 0.0023388069
1378.9236 0.0021542402
1631.0813 0.0021254013
1927.4899 0.0023618778
2194.3323 0.0021484711
2223.8984 0.0023157364
2446.6221 0.0022868966
2490.8728 0.0023388073
2743.0305 0.0024801167
3009.7410 0.0021917303
3262.1626 0.0022955481
3306.2815 0.0021052146
3335.8479 0.0023330392
3558.5713 0.0024772326
3602.6660 0.0023474589
3825.1497 0.0022292205
4121.6904 0.0021023308
4374.1118 0.0024916520
4447.7969 0.0023935998
4640.5586 0.0022522912
4714.5371 0.0023705289
4937.0991 0.0022263369
5233.6396 0.0021773111
5262.8101 0.0024656970
5455.9673 0.0024339736
5559.7461 0.0024455092
5752.5078 0.0021167498
5752.5078 0.0027021724
5826.4863 0.0023936001
6019.4819 0.0027021721
6048.7842 0.0021686594
6271.3760 0.0024368572
6345.5889 0.0022321043
6567.9165 0.0021167498
6612.3291 0.0022205692
6835.0225 0.0027165920
7131.4312 0.0027483148
7160.6016 0.0023849490
7427.3418 0.0020042793
7457.5381 0.0022032652
7650.2212 0.0021109823
7724.2002 0.0023301556
7724.2783 0.0022090334
7724.2783 0.0021801949
7947.1040 0.0028059918
7947.1040 0.0027425468
8242.3545 0.0019927442
8243.3809 0.0029588358
8465.4980 0.0024455097
8465.4980 0.0022032652
8510.5107 0.0029213454
8539.2910 0.0022148010
8539.2910 0.0020734922
8762.1709 0.0021686594
8762.1709 0.0026070056
8762.7764 0.0028232955
8805.9531 0.0020042795
8806.0313 0.0020590730
I am not sure to understand how we need y.
Is this what you are looking for ?
N = 100 ;
x = rand(N, 1) ;
M = hist(x) ;
plot(M) ;
I don't think the y matters. You just want to count the number of references to the x, which represent the y. You can use the hist(x, bins) method where x is the vector of data, your x, and bins is the number of bins you would like to put them in.
See http://www.mathworks.com/help/matlab/ref/hist.html
So I am working on my Thesis and I need to calculate geometric characteristics of an airfoil.
To do this, I need to interpolate the horizontal and vertical coordinates of an airfoil. This is used for a tool which will calculate the geometric characteristics automatically which come from random airfoil geometry files.
Sometime the Y values of the airfoil are non monotonic. Hence, the interp1 command gives an error since some values in the Y vector are repeated.
Therefore, my question is: How do I recognize and subsequently interpolate non monotonic increasing data automatically in Matlab.
Here is a sample data set:
0.999974 0.002176
0.994846 0.002555
0.984945 0.003283
0.973279 0.004131
0.960914 0.005022
0.948350 0.005919
0.935739 0.006810
0.923111 0.007691
0.910478 0.008564
0.897850 0.009428
0.885229 0.010282
0.872617 0.011125
0.860009 0.011960
0.847406 0.012783
0.834807 0.013598
0.822210 0.014402
0.809614 0.015199
0.797021 0.015985
0.784426 0.016764
0.771830 0.017536
0.759236 0.018297
0.746639 0.019053
0.734038 0.019797
0.721440 0.020531
0.708839 0.021256
0.696240 0.021971
0.683641 0.022674
0.671048 0.023367
0.658455 0.024048
0.645865 0.024721
0.633280 0.025378
0.620699 0.026029
0.608123 0.026670
0.595552 0.027299
0.582988 0.027919
0.570436 0.028523
0.557889 0.029115
0.545349 0.029697
0.532818 0.030265
0.520296 0.030820
0.507781 0.031365
0.495276 0.031894
0.482780 0.032414
0.470292 0.032920
0.457812 0.033415
0.445340 0.033898
0.432874 0.034369
0.420416 0.034829
0.407964 0.035275
0.395519 0.035708
0.383083 0.036126
0.370651 0.036530
0.358228 0.036916
0.345814 0.037284
0.333403 0.037629
0.320995 0.037950
0.308592 0.038244
0.296191 0.038506
0.283793 0.038733
0.271398 0.038920
0.259004 0.039061
0.246612 0.039153
0.234221 0.039188
0.221833 0.039162
0.209446 0.039064
0.197067 0.038889
0.184693 0.038628
0.172330 0.038271
0.159986 0.037809
0.147685 0.037231
0.135454 0.036526
0.123360 0.035684
0.111394 0.034690
0.099596 0.033528
0.088011 0.032181
0.076685 0.030635
0.065663 0.028864
0.055015 0.026849
0.044865 0.024579
0.035426 0.022076
0.027030 0.019427
0.019970 0.016771
0.014377 0.014268
0.010159 0.012029
0.007009 0.010051
0.004650 0.008292
0.002879 0.006696
0.001578 0.005207
0.000698 0.003785
0.000198 0.002434
0.000000 0.001190
0.000000 0.000000
0.000258 -0.001992
0.000832 -0.003348
0.001858 -0.004711
0.003426 -0.005982
0.005568 -0.007173
0.008409 -0.008303
0.012185 -0.009379
0.017243 -0.010404
0.023929 -0.011326
0.032338 -0.012056
0.042155 -0.012532
0.052898 -0.012742
0.064198 -0.012720
0.075846 -0.012533
0.087736 -0.012223
0.099803 -0.011837
0.111997 -0.011398
0.124285 -0.010925
0.136634 -0.010429
0.149040 -0.009918
0.161493 -0.009400
0.173985 -0.008878
0.186517 -0.008359
0.199087 -0.007845
0.211686 -0.007340
0.224315 -0.006846
0.236968 -0.006364
0.249641 -0.005898
0.262329 -0.005451
0.275030 -0.005022
0.287738 -0.004615
0.300450 -0.004231
0.313158 -0.003870
0.325864 -0.003534
0.338565 -0.003224
0.351261 -0.002939
0.363955 -0.002680
0.376646 -0.002447
0.389333 -0.002239
0.402018 -0.002057
0.414702 -0.001899
0.427381 -0.001766
0.440057 -0.001656
0.452730 -0.001566
0.465409 -0.001496
0.478092 -0.001443
0.490780 -0.001407
0.503470 -0.001381
0.516157 -0.001369
0.528844 -0.001364
0.541527 -0.001368
0.554213 -0.001376
0.566894 -0.001386
0.579575 -0.001398
0.592254 -0.001410
0.604934 -0.001424
0.617614 -0.001434
0.630291 -0.001437
0.642967 -0.001443
0.655644 -0.001442
0.668323 -0.001439
0.681003 -0.001437
0.693683 -0.001440
0.706365 -0.001442
0.719048 -0.001444
0.731731 -0.001446
0.744416 -0.001443
0.757102 -0.001445
0.769790 -0.001444
0.782480 -0.001445
0.795173 -0.001446
0.807870 -0.001446
0.820569 -0.001446
0.833273 -0.001446
0.845984 -0.001448
0.858698 -0.001448
0.871422 -0.001451
0.884148 -0.001448
0.896868 -0.001446
0.909585 -0.001443
0.922302 -0.001445
0.935019 -0.001446
0.947730 -0.001446
0.960405 -0.001439
0.972917 -0.001437
0.984788 -0.001441
0.994843 -0.001441
1.000019 -0.001441
First column is X and the second column is Y. Notice how the last values of Y are repeated.
Maybe someone can provide me with a piece of code to do this? Or any suggestions are welcome as well.
Remember I need to automate this process.
Thanks for your time and effort I really appreciate it!
There is quick and dirty method if you do not know the exact function defining the foil profile. Split your data into 2 sets, top and bottom planes, so the 'x' data are monotonic increasing.
First I imported your data table in the variable A, then:
%// just reorganise your input in individual vectors. (this is optional but
%// if you do not do it you'll have to adjust the code below)
x = A(:,1) ;
y = A(:,2) ;
ipos = y > 0 ; %// indices of the top plane
ineg = y <= 0 ; %// indices of the bottom plane
xi = linspace(0,1,500) ; %// new Xi for interpolation
ypos = interp1( x(ipos) , y(ipos) , xi ) ; %// re-interp the top plane
yneg = interp1( x(ineg) , y(ineg) , xi ) ; %// re-interp the bottom plane
y_new = [fliplr(yneg) ypos] ; %// stiches the two half data set together
x_new = [fliplr(xi) xi] ;
%% // display
figure
plot(x,y,'o')
hold on
plot(x_new,y_new,'.r')
axis equal
As said on top, it is quick and dirty. As you can see from the detail figure, you can greatly improve the x resolution this way in the area where the profile is close to the horizontal direction, but you loose a bit of resolution at the noose of the foil where the profile is close to the vertical direction.
If it's acceptable then you're all set. If you really need the resolution at the nose, you could look at interpolating on x as above but do a very fine x grid near the noose (instead of the regular x grid I provided as example).
if your replace the xi definition above by:
xi = [linspace(0,0.01,50) linspace(0.01,1,500)] ;
You get the following near the nose:
adjust that to your needs.
To interpolate any function, there must be a function defined. When you define y=f(x), you cannot have the same x for two different values of y because then we are not talking about a function. In your example data, neither x nor y are monotonic, so anyway you slice it, you'll have two (or more) "y"s for the same "x". If you wish to interpolate, you need to divide this into two separate problems, top/bottom and define proper functions for interp1/2/n to work with, for example, slice it horizontally where x==0. In any case, you would have to provide additional info than just x or y alone, e.g.: x=0.5 and y is on top.
On the other hand, if all you want to do is to insert a few values between each x and y in your array, you can do this using finite differences:
%// transform your original xy into 3d array where x is in first slice and y in second
xy = permute(xy(85:95,:), [3,1,2]); %// 85:95 is near x=0 in your data
%// lets say you want to insert three additional points along each line between every two points on given airfoil
h = [0, 0.25, 0.5, 0.75].'; %// steps along each line - column vector
%// every interpolated h along the way between f(x(n)) and f(x(n+1)) can
%// be defined as: f(x(n) + h) = f(x(n)) + h*( f(x(n+1)) - f(x(n)) )
%// this is first order finite differences approximation in 1D. 2D is very
%// similar only with gradient (this should be common knowledge, look it up)
%// from here it's just fancy matrix play
%// 2D gradient of xy curve
gradxy = diff(xy, 1, 2); %// diff xy, first order, along the 2nd dimension, where x and y now run
h_times_gradxy = bsxfun(#times, h, gradxy); %// gradient times step size
xy_in_3d_array = bsxfun(#plus, xy(:,1:end-1,:), h_times_gradxy); %// addition of "f(x)" and there we have it, the new x and y for every step h
[x,y] = deal(xy_in_3d_array(:,:,1), xy_in_3d_array(:,:,2)); %// extract x and y from 3d matrix
xy_interp = [x(:), y(:)]; %// use Matlab's linear indexing to flatten x and y into columns
%// plot to check results
figure; ax = newplot; hold on;
plot(ax, xy(:,:,1), xy(:,:,2),'o-');
plot(ax, xy_interp(:,1), xy_interp(:,2),'+')
legend('Original','Interpolated',0);
axis tight;
grid;
%// The End
And these are the results, near x=0 for clarity of presentation:
Hope that helps.
Cheers.
How can I convert this code to a for loop so if I could add more forces and moments? This is a lot code and its basically computing the unit vector and finding the sum of the forces in the x direction, y direction and z direction and doing the same for the moments.
This is only for one particular case so I want to put it in a for loop so when new forces are applied they will be accounted for.
Any help or nudge in the right direction would be a huge help! Thanks in advance.
load ('inputdata.mat')
A= zeros(6,6);
B= zeros (6,1);
% Calculate Force in x,y,z direction, sums them and puts them in the B
% vector positions 1,2,3
NF1=((ForceDir(1,2))^2+(ForceDir(1,3))^2+(ForceDir(1,4))^2)^(1/2);
F1i=(ForceDir(1,2)/NF1)* ForceDir(1,1);
F1j=(ForceDir(1,3)/NF1)* ForceDir(1,1);
F1k=(ForceDir(1,4)/NF1)*ForceDir(1,1);
NF2= ((ForceDir(2,2))^2+(ForceDir(2,3))^2+(ForceDir(2,4))^2)^(1/2);
F2i=(ForceDir(2,2)/NF2)* ForceDir(2,1);
F2j=(ForceDir(2,3)/NF2)* ForceDir(2,1);
F2k=(ForceDir(2,4)/NF2)* ForceDir(2,1);
B(1,1)= F1i+F2i; %External Force in x
B(2,1)= F1j+F2j; %External Force in y
B(3,1)= F1k+F2k; %External Force in z
% Calculate Moments in x,y,z direction and puts them in B vector
% position 3,4,5
unitvectorForce1=[F1i F1j F1k];
MomentByForce1= cross(ForceCoor(1,:),unitvectorForce1);
unitvectorForce2= [F2i F2j F2k];
MomentByForce2= cross(ForceCoor(2,:),unitvectorForce2);
MomentNormal=((DirMoment(1,2))^2+(DirMoment(1,3))^2+(DirMoment(1,4))^2)^(1/2);
M1i= (DirMoment(1,2)/MomentNormal)*DirMoment(1,1);
M1j= (DirMoment(1,3)/MomentNormal)*DirMoment (1,1);
M1k= (DirMoment(1,4)/MomentNormal)*DirMoment(1,1);
unitvectorMoment= [M1i M1j M1k];
B(4,1)= MomentByForce1(1)+MomentByForce2(1)+ unitvectorMoment(1)
B(5,1)= MomentByForce1(2)+MomentByForce2(2)+ unitvectorMoment(2)
B(6,1)= MomentByForce1(3)+MomentByForce2(3)+ unitvectorMoment(3)
If I understand you correclty, this should do the trick:
for ii = 1:N
NF(ii) = ((ForceDir(ii,2))^2+(ForceDir(ii,3))^2+(ForceDir(ii,4))^2)^(1/2);
Fi(ii) = ForceDir(ii,2) / NF(ii) * ForceDir(ii,1);
Fj(ii) = ForceDir(ii,3) / NF(ii) * ForceDir(ii,1);
Fk(ii) = ForceDir(ii,4) / NF(ii) * ForceDir(ii,1);
%% Etc
end