plotting from a loop - matlab

for t=0:0.1:10;
VS=3*exp(-t/3).*sin(t*pi);
if VS>0
VL(t+1)=VS;
else
VL(t+1)=0;
end
end
plot(0:100,VL);
xlabel('Time(s)')
ylabel('Across Voltage(V)')
title('Across Voltage Vs Time')
how to plot this figure based on VL (based on the relationship with VS whose expression shows above) versus t(from 0 to 10, increment 0.01)?
always got the error from matlab "Subscript indices must either be real positive integers or logicals."
Thanks.

There is a problem in your script. Note that t is defined in 0.1 intervals. Therefore, it is a real variable and can't be used as a subscript indice.
One way to solve that is
1) write cont=0; before the loop for.
2) write cont=cont+1 in the beginning of the loop
3) replace VL(t+1) by VL(cont)in both places inside the loop

Related

“Index exceeds the number of array elements” for piecewise function

I am trying to create piecewise functions V(t), D(t).
I try to find the piecewise, then I use the piecewise of t to construct functions and plot them.
But it shows "Index exceeds the number of array elements. Index must not exceed 51".
How can I fix it?
I put my code below and I really hope someone can answer it. Thaks!
z=zeros(1,50);
p_i=zeros(1);
p=0.023;
for i=1:50
z(i)=rand;
if z(i)>p
p_i(end+1)=i+z(i);
end
end
n=numel(p_i);
V=zeros(1,n);
w=zeros(1,n);
D=zeros(1,n);
V_op=zeros(1,n);
%get the number of pi
sigma_w0=0.2;
Q=5;
P=2;
Q_op=4;
for i=1:n
if i>1
w(i)=w(i-1)+normrnd(0,sigma_w0);
V(i)=Q*w(i);
D(i)=P*w(i);
V_op(i)=Q_op*w(i);
else
w(1)=2;
V(i)=Q*w(i);
D(i)=P*w(i);
V_op(i)=Q_op*w(i);
end
end
t=0:0.0002:50;
V_p=zeros(size(t));
D_p=zeros(size(t));
V_opp=zeros(size(t));
for m=1:length(t)
t(m)>=p_i(i)& t(m)<p_i(i+1)
V_p(m)=V(i);
D_p(m)=D(i);
V_opp(m)=V_op(i);
end
Yes, if you run your code you'll see it is functional before the last for loop since it is evaluating that in the 1 to 50 range (m=1:length(t)) but your line is printing 51 values so you need to check only the next part and reorganize the idea:
t(m)>=p_i(i)& t(m)<p_i(i+1)
If you print the first part (t(m)>=p_i(i)) it is okay, but check the other part and you'll notice the error. Maybe you can print all your results moving your increment value (+1) and prevent it from exceeding 1 to 51.

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.

Matlab not accepting whole number as index

I am using a while loop with an index t starting from 1 and increasing with each loop.
I'm having problems with this index in the following bit of code within the loop:
dt = 100000^(-1);
t = 1;
equi = false;
while equi==false
***some code that populates the arrays S(t) and I(t)***
t=t+1;
if (t>2/dt)
n = [S(t) I(t)];
np = [S(t-1/dt) I(t-1/dt)];
if sum((n-np).^2)<1e-5
equi=true;
end
end
First, the code in the "if" statement is accessed at t==200000 instead of at t==200001.
Second, the expression S(t-1/dt) results in the error message "Subscript indices must either be real positive integers or logicals", even though (t-1/dt) is whole and equals 1.0000e+005 .
I guess I can solve this using "round", but this worked before and suddenly doesn't work and I'd like to figure out why.
Thanks!
the expression S(t-1/dt) results in the error message "Subscript indices must either be real positive integers or logicals", even though (t-1/dt) is whole and equals 1.0000e+005
Is it really? ;)
mod(200000 - 1/dt, 1)
%ans = 1.455191522836685e-11
Your index is not an integer. This is one of the things to be aware of when working with floating point arithmetic. I suggest reading this excellent resource: "What every computer scientist should know about floating-point Arithmetic".
You can either use round as you did, or store 1/dt as a separate variable (many options exist).
Matlab is lying to you. You're running into floating point inaccuracies and Matlab does not have an honest printing policy. Try printing the numbers with full precision:
dt = 100000^(-1);
t = 200000;
fprintf('2/dt == %.12f\n',2/dt) % 199999.999999999971
fprintf('t - 1/dt == %.12f\n',t - 1/dt) % 100000.000000000015
While powers of 10 are very nice for us to type and read, 1e-5 (your dt) cannot be represented exactly as a floating point number. That's why your resulting calculations aren't coming out as even integers.
The statement
S(t-1/dt)
can be replaced by
S(uint32(t-1/dt))
And similarly for I.
Also you might want to save 1/dt hardcoded as 100000 as suggested above.
I reckon this will improve the comparison.

MatLab: Error checking for integers in a row vector

I have used MatLab to write the following code for Horner's Algorithm
function [answer ] = Simple( a,x )
%Simple takes two arguments that are in order and returns the value of the
%polynomial p(x). Simple is called by typing Simple(a,x)
% a is a row vector
%x is the associated scalar value
n=length(a);
result=a(n);
for j=n-1:-1:1 %for loop working backwards through the vector a
result=x*result+a(j);
end
answer=result;
end
I now need to add an error check to ensure the caller uses integer values in the row vector a.
For previous integer checks I have used
if(n~=floor(n))
error(...
But this was for a single value, I am unsure how to do this check for each of the elements in a.
You've got (at least) two options.
1) Use any:
if (any(n ~= floor(n)))
error('Bummer. At least one wasn''t an integer.')
end
Or even more succinctly...
assert(all(n == floor(n)), 'Bummer. At least one wasn''t an integer.')
2) Use the much more capable validateattributes:
validateattributes(n, {'double'}, {'integer'})
This function can check for more than a dozen other things, too.
Same math will work, but is now checking each element. Try this:
if any(n~=floor(n))
error(...

in matlab exit the entire loop and more

I am using this function to get a column vector in which every element is supposed to be 1,
but after n gets large, sometimes some element is not 1, this is due to the method constraint, I want to find out how large is n and return the value. the problem are: 1.it seems that 1 is stored as 1.0000, don't know how to convert it, and how to compare(location in comments) 2. don't know how to exit a loop completely. thank you.
function x = findn(n)
for m = 1:n
[a,b]=Hilbert(m);
m1 = GaussNaive(a,b);
m2 = size(m1,1);
% m1 is a n*1 matrix (a column vector) which every element is supposed
% to be 1, but when n gets large, some element is not 1.
for i = 1:m2
if (m1(i) ~= 1)
% this compare isn't really working, since 1 is stored as 1.0000 for whatever
% for whatever reason and they are not equal or not not equal.
% I doubt whether it really compared.
x = m;
break;
% it just exit the inner for loop, not entirely
end
end
end
In Matlab all numeric variables are, by default, double precision floating-point numbers. (Actually strings and logicals can look like f-p numbers too but forget that for the moment.) So, unless you take steps that your code doesn't show, you are working with f-p numbers. The sort of steps you can take include declaring your variables to have specific types, such as int32 or uint16, and taking care over the arithmetic operations you perform on them. Matlab's attraction to double-precision floating-point is very strong and it's easy to operate on ints (for example) and end up with floating-point numbers again. Start reading about those types in the documentation.
The reasons for avoiding (in-)equality tests on f-p numbers are explained on an almost daily basis here on SO, I won't repeat them, have a look around. The straightforward way to modify your code would be to replace the test with
if (m1(i) ~= 1)
with
if ((abs(m1(i)-1)>tol)
where tol is some small number such that any number larger than 1+tol (or smaller than 1-tol) is to be considered not equal to 1 for your purposes.
Unfortunately, as far as I know, Matlab lacks a statement to break from an inner loop to outside a containing loop. However, in this case, you can probably replace the break with a return which will return control to the function which called your function, or to the command-line if you invoked it from there.