Calling an element of a vector inside a function in Matlab - matlab

I am new to Matlab and trying to define a simple function but keep running into an error. Details are:
1) V is a 31x1 vector;
2) The function mypi takes one input, which is a scalar (between 0 to 30). It finds the corresponding element in V vector and saves it in z.
3) Matrix A is a row vector with two elements 0 and z-10.
4) y, which is what I am interested in calculating is a linear function of the max of vector A.
Matlab, however, gives an error and is not recognizing element x in vector V. Can anyone please guide me how I should fix this problem? I will be grateful. Thank you.
function y=mypi(x)
z=V(x);
A=[0, z-10];
y=500+50*max(A);
end

you must pass V to mypi or make it visible to this function by defining it as global. But why bother passing both V and index x to this function instead of passing V(x) or z directly?
function y=mypi(z)
A=[0, z-10];
y=500+50*max(A);
end
and call it by mypi(V(x))

Related

Vectorization of function in Matlab

I'm trying to vectorize one function in Matlab, but I have a problem with assigning values.
function [val] = clenshaw(coeffs,x)
b=zeros(1,length(coeffs)+2);
for k=length(coeffs):-1:2
b(k)=coeffs(k)-b(k+2)+2*b(k+1).*x;
end
val=coeffs(1)-b(3)+b(2).*x;
The purpose of this function is to use Clenshaw's algorithm to compute a value of one polynomial with coefficients "coeffs" at point x.
It work fine when x is a single value, but I'd like it to work with vector of arguments too.
When I try to pass a vector I get an error:
Unable to perform assignment because the left
and right sides have a different number of
elements.
Error in clenshaw (line 7)
b(k)=coeffs(k)-b(k+2)+2*b(k+1).*x;
I understand that there is a problem, because I'm trying to assign vector to a scalar variable b(k).
I tried making b a matrix instead of a vector, however I still cannot get the return output I'd like to have which would be a vector of values of this function at points from vector x.
Thank you for helping and sorry if something isn't entirely clear, because English is not my native language.
The vectorized version of your function looks like this:
function [val] = clenshaw(coeffs,x)
b=zeros(length(x),length(coeffs)+2);
for k=length(coeffs):-1:2
b(:,k)=coeffs(k)-b(:,k+2)+2*b(:,k+1).*transpose(x);
end
val=coeffs(1)-b(:,3)+b(:,2).*transpose(x);
end
b needs to be a matrix. In your loop, you have to perform every operation per row of b. So you need to write b(:,k) instead of b(k). Since b(:,k) is a vector and not a scalar, you also have to be careful with the dimensions when using the .* operator. To get the correct results, you need to transpose x. The same goes for the calculation of val. If you don't like the transposition, just swap the rows and cols of b and you get this:
function [val] = clenshaw(coeffs,x)
b=zeros(length(coeffs)+2, length(x));
for k=length(coeffs):-1:2
b(k,:)=coeffs(k)-b(k+2,:)+2*b(k+1,:).*x;
end
val=coeffs(1)-b(3,:)+b(2,:).*x;
end
However, the first version returns a column vector and the second a row vector. So you might need to transpose the result if the vector type is important.

Passing vector input into MATLAB function

I am trying to write a function in MATLAB that takes 1x3 vectors as input. My code looks something like this:
function myFunction=([x1, x2, x3], [y1, y2, y3], [z1, z2, z3])
where all inputs are numbers, and then in the body of the function I perform some calculations indexing through the numerical values in the vectors. i want the vectors to be user input, so the user will enter the vectors and their components (x1, x2, etc.) into the function argument. However, I am getting an error saying "Invalid expression. When calling a function or indexing a variable, use parentheses. Otherwise, check for mismatched delimiters." Therefore I believe I either have the syntax or something else wrong. I know MATLAB is supposed to be able to take vector input in functions, so please let me know what I am doing wrong. Thanks!
What you need to do is declare your function like this:
function myFunction(x,y,z)
% your function code here
end
Then within your function you can access the individual elements of the vectors using x(1), y(2), etc.
To call the function, including whatever number you like, you can enter on the Matlab command window (for example),
myFunction([1 2 3],[4 5 6],[7 8 9]) and the code in your function will be called with the x variable set to the vector [1,2,3], the y variable set to [4,5,6] and z to [7,8,9]. The use of commas to delineate values is optional. If your function then accesses y(2) it will get the second value of the y vector which will be 5 - it is important to note that indexing in Matlab is 1-based so the 1st element of x is obtained with x(1).
If you need to return values you can use:
function [a,b,c] = myFunction(x,y,z)
Then just assign the a, b or c in your code before the end statement.
See the offical Matlab documentation for more info.
I would add that much of the advantage of matlab is dealing with data in a vectorised form, so if you can avoid splitting out into separate elements I would do so. For example, if you need to add two vecors, you could do z = [x(1)+y(1), x(2)+y(2), x(3)+y(3)], but much better (more readable, more maintainable, faster) is z=x+y.

How to use "fsolve" for optimizing the objective function?

How can I optimize the below function using "fsolve". It only takes input argument in the form of vectors but I have to pass input arguments to the below function in the form of matrix.
I am getting the below error while using the optimization toolbox
Error running optimization. Inner matrix dimensions must agree.
function f = object(w)
k=10;
B=20;
f = sum ((w(1,:)/(w(2,:).^w(3,:)*k)+((w(3,:)-1)*w(4,:)/B*w(3,:))));
end
You're very brief in your problem description about the outer circumstances but from your function it looks like the function might expect a w argument of size 4 x N. Did I guess correctly? If so, try
w_initial = rand(4*N,1); % resonable initialization. maybe random? maybe zeros?
fsolve(#(w) object(reshape(w,4,N)), w_initial, ...)

Vectorizing a symbol with more than one value in a for loop in MATLAB

I would like to export the answers of an equation with the order of 2 into a vector. The input is R01and the variable is n.
The problem is where I want to "double" the symbol for each step of i, I get the following error:
In an assignment A(I)=B, the number of elements in B and I must be the
same.
There will be no error if I do not use a for loop. What is my mistake and how can I modify it that I could get the data as a matrix or vector.
R01=[0.07941 0.07942 0.07952 0.07946 0.07951 0.07947]
syms n
for i=1:length(R01)
eq3=((1+n)^2)*R01(i)-(n-1)^2
sol1=solve([eq3]);
nsol(i)=double(sol1);
end
The efficient way to solve the problem (by Daniel):
syms n
for i=1:length(R01)
eq3=((1+n)^2)*R01(i)-(n-1)^2
sol1=solve([eq3]);
nsol(i,:)=double(sol1);
end

MATLAB: Using FZERO on a function which has a vector output

I am working on my thesis and running in some programming problems in Matlab. I am trying to implement the ''golden Bisection Method'' to speed up my code. To this end, I've consulted the build in function FZERO.
So I am determining the difference between two vectors which are both (1x20).
Difference = Clmax_dist-cl_vec;
Clmax_dist comes from a semi-empirical method and cl_vec comes from the excecution of an external AVL.exe file.
Essentially, this difference depends only on one single variable AOA because the Clmax_dist vector is a constant. Hence, I am constantly feeding a new AOA value to the AVL.exe to obtain a new cl_vec and compare this again to the constant Clmax_dist.
I am iterating this until one of the element in the vector becomes either zero or negative. My loop stops and reveals the final AOA. This is a time consuming method and I wanted to use FZERO to speed this up.
However, the FZERO documentation reveals that it only works on function which has a scalar as input. Hence, my question is: How can I use FZERO with a function which has a vector as an output. Or do i need to do something totally different?
I've tried the following:
[Difference] = obj.DATCOMSPANLOADING(AOA);
fun=#obj.DATCOMSPANLOADING;
AOA_init = [1 20];
AOA_root = fzero(fun,AOA_init,'iter');
this gave me the following error:
Operands to the || and && operators must be convertible to logical scalar values.
Error in fzero (line 423)
while fb ~= 0 && a ~= b
Error in CleanCLmax/run (line 11)
AOA_root = fzero(fun,AOA_init,'iter');
Error in InitiatorController/moduleRunner (line 11)
ModuleHandle.run;
Error in InitiatorController/runModule (line 95)
obj.moduleRunner(ModuleHandle);
Error in RunSteps (line 7)
C.runModule('CleanCLmax');
The DATCOMSPANDLOADING function contains the following:
function [Difference] = DATCOMSPANLOADING(obj,AOA)
[Input]= obj.CLmaxInput; % Creates Input structure and airfoil list
obj.writeAirfoils(Input); % Creates airfoil coordinate files in AVL directory
[Clmax_dist,YClmax,Cla_mainsections] = obj.Clmax_spanwise(Input); % Creates spanwise section CLmax with ESDU method
[CLa] = obj.WingLiftCurveSlope(Input,Cla_mainsections); % Wing lift curve slope
[Yle_wing,cl_vec] = obj.AVLspanloading(Input,CLa,AOA); % Creates spanloading with AVL
Difference = Clmax_dist-cl_vec;
end
If I need to elaborate further, feel free to ask. And of course, Thank you very much.
fzero indeed only works on scalars. However, you can turn your criterion into a scalar: You are interested in AOA where any of the elements in the vector becomes zero, in which case you rewrite your objective function to return two output arguments: minDifference, which is min(Difference), and Difference. The first output, minDifference is the minimum of the difference, i.e. what fzero should try to optimize (from your question, I'm assuming all values start positive). The second output you'd use to inspect your difference vector in the end.