MatLab Want function to take in multiple values and output multiple values - matlab

I have an equation r that I want to take in values from Ex and Vt. Ex and Vt give multiple values when run, but r does not. I need r to give values for each number in x1 and xL1.
Thanks.
Es= 1.01911;
Vab= 1.6;
s= 75.5;
x1= [93.5, 93.1, 92.0, 91.9, 92.2];
xL1= [49.0, 46.2, 48.6, 46.3, 48.9];
Ex= x1*(Vab/100);
Vt= Es*(xL1/s);
r=(20*(Ex-Vt))/Vt

I think what you are after might be element-wise operation, i.e.,
r=(20*(Ex-Vt))./Vt
such that
r =
25.237 27.773 24.877 27.055 24.699

Related

How to run a for loop using two variables at the same time in Matlab

I am using this command in Matlab:
grazAng = grazingang(H,R)
If i fix H, I can treat R as a vector:
z=[];
for i=1:1000
z(i)=abs(grazingang(1,i));
end
Now I would like to have both H and R to by dynamic. For example:
H=[0,0.25,0.5]
R=[1,2,3]
And I would like my loop to run three times, each time selecting a pair of (H,R) values with the same indexes, i.e. (0,1),(0.25,2),(0.5,3) and then store the result in z. Could anyone help me out with this?
Remember, everything in MATLAB is an array. To do this with a loop, you need to index into the arrays:
H = [0,0.25,0.5];
R = [1,2,3];
z = zeros(size(H)); % Pre-allocation is generally advised
for i = 1:1000
z(i) = abs(grazingang(H(i),R(i)));
end
But MATLAB functions generally accept vectors and do this for you, so all you need to do is:
H=[0,0.25,0.5];
R=[1,2,3];
z = abs(grazingang(H,R));

MATLAB: How to plot a cubic expression for certain range of input pressure

I have a cubic expression here
I am trying to determine and plot δ𝛿 in the expression for P values of 0.0 to 5000. I'm really struggling to get the expression for δ in terms of the pressure P.
clear all;
close all;
t = 0.335*1e-9;
r = 62*1e-6;
delta = 1.2*1e+9;
E = 1e+12;
v = 0.17;
P = 0:100:5000
P = (4*delta*t)*w/r^2 + (2*E*t)*w^3/((1-v)*r^4);
I would appreciate if anyone could provide pointers.
I suggest two simple methods.
You evaluate P as a function of delta then you plot(P,delta). This is quick and dirty but if all you need is a plot it will do. The inconvenience is that you may to do some guess-and-trial to find the correct interval of P values, but you can also take a large enough value of delta_max and then restrict the x-axis limit of the plot.
Your function is a simple cubic, which you can solve analytically (see here if you are lost) to invert P(delta) into delta(P).
What you want is the functional inverse of your expression, i.e., δ𝛿 as a function of P. Since it's a cubic polynomial, you can expect up to three solutions (roots) for a give value of P. However, I'm guessing that you're only interested in real-valued solutions and nonnegative values of P. In that case there's just one real root for each value of P.
Given the values of your parameters, it makes most sense to solve this numerically using fzero. Using the parameter names in your code (different from equations):
t = 0.335*1e-9;
r = 62*1e-6;
delta = 1.2*1e9;
E = 1e12;
v = 0.17;
f = #(w,p)2*E*t*w.^3/((1-v)*r^4)+4*delta*t*w/r^2-p;
P = 0:100:5000;
w0 = [0 1]; % Bounded initial guess, valid up to very large values of P
w_sol = zeros(length(P),1);
for i = 1:length(P)
w_sol(i) = fzero(#(w)f(w,P(i)),w0); % Find solution for each P
end
figure;
plot(P,w_sol);
You could also solve this using symbolic math:
syms w p
t = 0.335*sym(1e-9);
r = 62*sym(1e-6);
delta = 1.2*sym(1e9);
E = sym(1e12);
v = sym(0.17);
w_sol = solve(p==2*E*t*w^3/((1-v)*r^4)+4*delta*t*w/r^2,w);
P = 0:100:5000;
w_sol = double(subs(w_sol(1),p,P)); % Plug in P values and convert to floating point
figure;
plot(P,w_sol);
Because of your numeric parameter values, solve returns an answer in terms of three RootOf objects, the first of which is the real one you want.

Is it possible to compute all the values at the same time when writing a script?

When defining a function, say TEST = #(t) t.^2. If the input is a vector, say [1,2,3,4], TEST([1,2,3,4]) = [1,4,9,16].
Can we do similar thing if the function defined is in script form? What I mean is that if I have a script, say TEST.m such that ret = TEST(x,y,z) which outputs a value when knowing numerical values of x, y and z. Suppose I want to calculate 100 different values of z ranging from 1 to 100 when x, y are fixed, say at 0, 1 respectively. Is it possible to output TEST(0,1,1:1:100) without writing a for loop or changing any contents of the script TEST.m?
The reason to ask such question comes from the computation time. Usually, the script I have may be a little complicated so that the calculate of a single value may take few minutes to go. Writing for-loop to output it can be very time-consuming. I think of writing parfor loop, but the computation time is still long to me for further uses. I wonder if I can calculate all the 100 values at a time. I am a starter of programmer, and I hope I can get satisfactory answers after this post. Thanks for all your help.
You cab define a new anonymous function to get the fixed values as parameters, and the vector as input. Then use arrayfun to compute it on all values of the array.
Say you have this functions:
function ret = TEST(x,y,z)
ret = f(x)+g(y)+h(z);
end
function r = f(x)
r = x^2;
end
function r = g(y)
r = y^3;
end
function r = h(z)
r = z^4;
end
And you call it from:
x = 2;
y = 3;
z = 1:5;
T = #(z) TEST(x,y,z);
arrayfun(T,z)
So T is a new function that treat x and y as constants, and only have z as input. Then arrayfun takes T and compute it for every element in z, and you get:
ans =
32 47 112 287 656
Now, you can use arrayfun with more vectors, like [a,b,c] = arrayfun(T,z,w,v), if x and y can stay constant.
Hopes it answers your question ;)

matlab inline function with argument conditions

folks,
I am wondering if it is possible to write the following function of r as an inline function in matlab. I tried to include the condition as a separate factor such as *(r>a) and I got NaN due to the division of 1/r^3 when r is 0.
I fould a simple way out. It's basically what Shai and Jigg suggested, i.e. using an extra multiplicative factor of (r>a).
To get rid of NaN, we just need to add eps to the denominator of 1/r3, i.e.
1/(r+eps)^3 *(r>a)
First, you haven't stated what should actually happen if r = 0. Mathematically the term gets infinity. I assumed you rather want to set it to zero. And what should happen for r = a? Just another ill-defined case, are you sure your formula is correct?
If you have the Statistics Toolbox you can use nansum. If not, I'd say there is no way around to write your own function similar to nansum, which can't be done inline.
r = -5:1:5;
a = 1;
R = 42; %// rest of your function
%// not working, or removing of nan afterwards required
X = #( r ) (r>=a).*(a./r).^3*R;
%// inline solution with statistics toolbox
Y = #( r ) arrayfun(#(x) nansum( (x>=a)*(a/x)^3*R ), r);
output = [X(r)' Y(r)']
nansum is not vectorized, if you still want to use it for vectors wrap it into arrayfun.
The code of nansum does exactly what was suggested in the comments (output(isnan(output))=0), I'm probably not allowed to copy&paste it here. It filters out all NaN and then sums the input. Use open nansum to have insight.
As pointed out by Jigg, similar functions like nanmean would do the trick as well.
You can try
chi = 1; %// arbitrary value
a = 1; %// arbitrary value
theta = pi/3; %// arbitrary value
nu = #( r ) (r>a).*( (chi/3).*((a.^3)./(r.^3)).*(3*cos(theta).^2 -1);

Error: Matrix dimensions must agree for plot

having a problem with my "new love", matlab: I wrote a function to calculate an integral using the trapz-method: `
function [L]=bogenlaenge_innen(schwingungen)
R = 1500; %Ablegeradius
OA = 1; %Amplitude
S = schwingungen; %Schwingungszahl
B = 3.175; %Tapebreite
phi = 0:2.*pi./10000:2.*pi;
BL = sqrt((R-B).^2+2.*(R-B).*OA.*sin(S.*phi)+OA.^2.*(sin(S.*phi)).^2+OA.^2.*S.^2.*(cos(S.*phi)).^2);
L = trapz(phi,BL)`
this works fine when i start it with one specific number out of the command-window. Now I want to plot the values of "L" for several S.
I did the following in a new *.m-file:
W = (0:1:1500);
T = bogenlaenge_innen(W);
plot(W,T)
And there it is:
Error using .*
Matrix dimensions must agree.
What is wrong? Is it just a dot somewhere? I am using matlab for the second day now, so please be patient.... ;) Thank you so much in advance!
PS: just ignore the german part of the code, it does not really matter :)
In your code, the arrays S and phi in the expression sin(S.*phi) should have same size or one of them should be a constant in order the code works
The error is most likely because you have made it so that the number of elements in schwingungen, i.e. W in your code, must be equal to the number of elements in phi. Since size(W) gives you a different result from size(0:2.*pi./10000:2.*pi), you get the error.
The way .* works is that is multiplies each corresponding elements of two matrices provided that they either have the same dimensions or that one of them is a scalar. So your code will work when schwingungen is a scalar, but not when it's a vector as chances are it has a different number of elements from the way you hard coded phi.
The simplest course of action (not necessarily the most Matlabesque though) for you is to loop through the different values of S:
W = (0:1:1500);
T = zeros(size(W); %Preallocate for speed)
for ii = 1:length(W)
T(ii) = bogenlaenge_innen(W(ii));
end
plot(W,T)
In your function you define phi as a vector of 10001 elements.
In this same function you do S.*phi, so if S is not the same length as phi, you will get the "dimensions must agree" error.
In your call to the function you are doing it with a vector of length 1501, so there is your error.
Regards