I want to have a waitbar for an operation that takes quite a while. Here is my code:
h = waitbar(0,'Please wait...');
for i=1:counterend
waitbar(i/waitbarcounter)
Atemp = At+i*step;
handle = #(M) 1/M^2*((2/(gamma+1))*(1+(gamma-1)*M^2/2))^((gamma+1)/(gamma-1))-(Atemp/At)^2;
Mach = fzero(handle, 5);
Aplot(i) = Atemp/At;
Tplot(i) = Tc / (1+(gamma-1)*Mach^2/2);
Mplot(i) = Mach;
plot(Aplot, Tplot)
end
close(h)
The error Matlab gives is:
??? Error using ==> waitbar at 249
Improper arguments for waitbar
After investigation, I am sure that this error must occur because of the sorrounding code in the loop.
Note: The loop works fine without the waitbar.
Running
counterend = 10000;
>> h = waitbar(0,'Please wait...');
for i=1:counterend
waitbar(i/counterend)
end
close(h);
Works as expected on 2007a / Windows XP.
On a side note, it would help knowing what countered is defined as. Something quick to check would be to ensure that you are not passing it a CELL.
Running
counterend = {10000};
h = waitbar(0,'Please wait...');
for i=1:counterend
waitbar(i/counterend)
end
close(h);
Yields a different error (see below) in 2007a, but this error message may have changed in 2008.
??? Undefined function or method
'_colonobj' for input arguments of
type 'cell'.
My last bit of advice would be caution you on the use of waitbar for large arrays/data sets. While I think it is important to inform the user of the progress, to me there is also a concern for how much time is added to the loop. Working with arrays that have 100k+ entries, I became a religious user of the Profiler to see where the time was really being spent. I can tell you the time is not in the calculation of the i/X, it was all in updating the waitbar's display. To soften the blow of the update/drawnow, I only updated the waitbar every 100 to 1000 entry which helped tremendously.
EDIT: Updated response to match latest code
I first started to attack this problem at the anonymous function, having problems with them in the past it's a personal vendetta of mine. When looking into the function I found that you are using gamma, do you have this defined as a constant (constant to the loop / function)? The reason I ask is that 'gamma' is a Matlab function and was giving me errors when trying to run your function by itself. Below I have modified you code slightly and this does run fine here. If any of the assumptions I have made are wrong please let me know.
In addition, if you did intend to use the gamma function, your function is missing any arguments to it. Hope this helps!
clc
h = waitbar(0,'Please wait...');
counterend = 1000;
waitbarcounter = counterend;
g_amma = 7;
At = 34;
step = 2;
Tc = 42;
for i=1:counterend
waitbar(i/waitbarcounter)
Atemp = At+i*step;
handle = #(M) 1/M^2*((2/(g_amma+1))*(1+(g_amma-1)*M^2/2))^((g_amma+1)/(g_amma-1))-(Atemp/At)^2;
Mach = fzero(handle, 5);
Aplot(i) = Atemp/At;
Tplot(i) = Tc / (1+(g_amma-1)*Mach^2/2);
Mplot(i) = Mach;
plot(Aplot, Tplot)
end
close(h)
Regards,
Adam
I have checked waitbar on R2008b. So far, the only ways I was able to reproduce your error was by having i/counterend evaluate to an array with multiple rows (a 1x2 vector gives interesting results), and by closing the waitbar before calling waitbar(i/counterend).
I do not get any error running the following:
h = waitbar(0,'Please wait...');
counterend = 1000;
for i=1:counterend
waitbar(i/counterend)
end
close(h)
Could you make sure that the small example above runs without error? If yes, please check that the waitbar is not closed during the execution of the loop, and that counterend is a scalar (use dbstop if error to stop execution of your code at the time of the error).
If the above example does not work without error, you should use which waitbar to check that you are using Matlab's waitbar, and not any of the many updated version from the Matlab File Exchange.
Running
counterned=1000;
h = waitbar(0,'Please wait...');
for i=1:counterend
waitbar(i/counterend)
end
close(h)
works perfectly as expected on MATLAB R2009a on Windows XP.
The above runs fine on R2008a on XP also.
However, you get the error you describe if you kill the waitbar window before the next waitbar command comes around. If you want to be nice about it you should check if the handle h is still valid before issuing waitbar.
I prefer to use progressbar written by Steve Hoelzer on the MATLAB FEX. I haven't had any problems with it.
Your suppose to use the handle that you created with your first line of code when you want to update the waiter,
Waiter(it/itmax,h,'progress')
Related
I am using the Matlab parallel toolbox to do parallel computing. I've doubled check the variable definition of the code, and it follows the requirements of parfor command. However, Matlab still told me that "Transparency Violation Error," could you help me figure out this issue?
Here is the source code.
load Wind80.mat
Wspeed_80 = Wind80;
TotalLoc = 4000;
Nloc = 5; % no of loc of each run
maxrun = ceil(TotalLoc/Nloc);
StrInfo.Pstr = 1;
StrInfo.Tstr = 0:4:72;
tic
parfor run = 1:maxrun
WT1 = [];
WT2 = [];
[WT1, WT2] = CompWTGenFun(run, Nloc, TotalLoc, StrInfo);
filenm = ['ResultPara' num2str(StrInfo.Pstr) 'Run' num2str(run) '.mat' ];
save(filenm, 'WT1', 'WT2', '-mat');
clear WT1 WT2
end
toc
You cannot use the save function within a parfor loop, as this will result in a transparency violation. Transparency violations occur when a function needs to look into (or modify) its calling workspace. Unfortunately, save does this - in your code, you give the save command the names of the variables you want to save, and the save implementation attempts to extract the values from its calling workspace (i.e. the body of the parfor loop).
The workaround is to hide the call to save inside a separate function, in other words, you need something like this:
parfor ...
mySave(filenm, WT1, WT2);
end
# ...
function mySave(filenm, WT1, WT2)
save(filenm, 'WT1', 'WT2', '-mat');
end
This works because the transparency constraint only applies to the code directly present in the body of the parfor loop.
As mentioned in the comments, the clear command you have is not necessary, and would again cause a transparency violation.
I am using parfor for parallel computing in Matlab. I am not familiar with this command. If that is possible, please look at my code below and tell me if I can write it with parfor.
These errors and warnings are appear in Matlab Editor:
The parfor loop cannot be run due to the way variable Dat is used. (when I comment line Dat.normXpj = normXpj(pj,:); This error is solved and other errors similar to the following error is appeared.
The entire array or structure Bound is broadcast variable. This
might result in unnecessary communication overhead.
parfor pj = 1:size(normXpj,1)
Dat.normXpj = normXpj(pj,:);
if size(Dat.InitialGuess)==0
X = (Bound(:,1)+(Bound(:,2)-Bound(:,1)).*rand(Nvar,1))';
else
X = Dat.InitialGuess;
end
[Xsqp, ~, FLAG,Options] = mopOPT(X,Dat);
FEVALS = Options.funcCount;
FES = FES+FEVALS;
PSet(pj,:) = Xsqp;
PFront(pj,:) = mop(Xsqp,Dat,0);
if FLAG==-2
disp('.......... Algo paso...');
else
F = PFront(pj,:);
if Nobj==2
plot(F(1,1),F(1,2),'*r'); grid on; hold on;
elseif Nobj==3
end
end
end
The problem here is that it we can see that you're not using Dat in a way that is order-dependent, but the static analysis machinery of parfor cannot deduce that because of the way you're assigning into it. I think you can work around this by instead creating a whole new Dat for each iteration of the loop, like so:
Dat = struct('normXpj', rand(10,1), 'InitialGuess', 3);
normXpj = rand(10);
parfor idx = 1:10
tmpDat = struct('normXpj', normXpj(:,idx), 'InitialGuess', Dat.InitialGuess);
% use 'tmpDat'
disp(tmpDat);
end
The answer is no, unfortunately. At line:
Dat.normXpj = normXpj(pj,:);
you assign a value to Dat.normXpj, but you have to know that in a parfor loop there can be multiple iterations executing at the same time. So what value should be used for Dat.normXpj ? Matlab cannot decide, hence your error.
More generally, your code looks quite messy. I suppose you want to use parfor to increase execution speed. Probably a more efficient option would be to use the profiler (see profile) to detect the bottlenecks in your code, and apply a correction if that's possible.
Best,
First time post here. Pretty frustrated right now working on this assignment for class.
Basically, the idea is to use Euler's method to simulate and graph an equation of motion. The equation of motion is in the form of an ODE.
My professor has already put down some code for slightly similar system and would like us to derive the equation of motion using Lagrange. I believe that I have derived the EOM correctly, however I am running into problems on the Matlab side of things.
What's weird is that using a similar technique on another, seperate EOM, I have no issues. So I am unsure what I am doing wrong.
Here's the code for the part that is working correctly:
close all; clear all; clc;
% System parameters
w = 2*pi;
c = 0.02;
% Time vectors
dt = 1e-5;
t = 0:dt:4;
theta = zeros(size(t));
thetadot = zeros(size(t));
% Initial conditions
theta(1)=pi/2; %theta(0)
thetadot(1)=0; %thetadot(0)
for I = 1 : length(t)-1;
thetaddot = -c*thetadot(I)-w^2*sin(theta(I));
thetadot(I+1)=thetadot(I)+thetaddot*dt;
theta(I+1)=theta(I)+thetadot(I)*dt ;
end
figure(1);
plot(t,theta,'b');
xlabel('time(s)');
ylabel('theta');
title('Figure 1');
zoom on;
% Output the plot to a pdf file, and make it 6 inches by 4 inches
printFigureToPdf('fig1.pdf', [6,4],'in');
% Open the pdf for viewing
open fig1.pdf
Everything runs fine, except Matlab complains about the printFigureToPdf command.
Now, here is the code for the problem that I am having issues with.
close all; clear all; clc; clf
% System parameters
m=0.2;
g=9.81;
c=.2;
d=0.075;
L=0.001; %L is used for Gamma
B=0.001; %B is used for Beta
W=210*pi; %W is used for Omega
%Time vectors
dt = 1e-6; %Time Step
t=0:dt:10; %Range of times that simulation goes through
x=zeros(size(t));
xdot=zeros(size(t));
%Initialconditions
x(1)=0;%x(0)
xdot(1)=0; %xdot(0)
for I = 1 : length(t)-1;
xddot =-1/m*(c*xdot(I)-c*L*W*cos(W)+m*g-3*B*((d+x-L*W*sin(W*t)).^(-4)-(d-x-L*W*sin(W*t)).^(-4)));
xdot(I+1)=xdot(I)+xddot*dt;
x(I+1)=x(I)+xdot(I+1)*dt ;
end
figure(1);
plot(t,x,'b');
xlabel('time(s)');
ylabel('distance(m)');
title('Figure 2');
zoom on;
% Output the plot to a pdf file, and make it 6 inches by 4 inches
printFigureToPdf('fig1.pdf', [6,4],'in');
% Open the pdf for viewing
open fig1.pdf
With this code, I followed the same procedure and is giving an error on line 23: "In an assignment A(I) = B, the number of elements in B and I must be the same."
Like I said, I am confused because the other code worked okay, and this second set of code gives an error.
If anyone could give me a hand with this, I would greatly appreciate it.
Thanks in advance,
Dave
Edit: As suggested, I changed x(I+1)=x(I)+xdot(I+1)*dt to x(I+1)=x(I)+xdot(I)*dt. However, I am still getting an error for line 23: "In an assignment A(I) = B, the number of elements in B and I must be the same."
Line 23 is: xdot(I+1)=xdot(I)+xddot*dt;
So, I tried adjusting the code as suggested for the other line to xdot(I+1)=xdot(I)+xddot(I)*dt;
After making this change, Matlab gets stuck, I tried letting it run for a few minutes but won't execute. I ended up having to close and reopen the application.
The error In an assignment A(I) = B, the number of elements in B and I must be the same. is something you should understand because it may pop up frequently in Matlab if you are not careful.
In your case, you are trying to assign 1 element value xdot(I+1) with something which has more than 1 element xdot(I)+xddot*dt.
Indeed, if you step through the code line by line and observe your workspace, you will notice that xddot is not a scalar value as intended, but a full blown vector the size of t. This is because in the precedent line where you define xddot:
xddot =-1/m*(c*xdot(I)-c*L*W*cos(W)+m*g-3*B*((d+x-L*W*sin(W*t)).^(-4)-(d-x-L*W*sin(W*t)).^(-4)));
you still have many references to x (full vector) and t (full vector). You have to replace all these references to full vectors to only one index of them, i.e use x(I) and t(I). The line becomes:
xddot =-1/m*(c*xdot(I)-c*L*W*cos(W)+m*g-3*B*((d+x(I)-L*W*sin(W*t(I))).^(-4)-(d-x(I)-L*W*sin(W*t(I))).^(-4)));
With that your code runs just fine. However, it is far from optimized and it runs relatively slow. I have a powerful machine and it still takes a long time to run for me. I suggest you reduce your time step to something more sensible, at least when you are still trying your code. If you really need that kind of precision, first make sure your code runs fine then when it is ready let it run at full precision and go have a coffee while your computer is doing the work.
The snippet below is the loop part of your code with the correct assignment for xddot. I also added a simple progress bar so you can see that your code is doing something.
hw = waitbar(0,'Please wait...') ;
npt = length(t)-1 ;
for I = 1 : npt
xddot =-1/m*(c*xdot(I)-c*L*W*cos(W)+m*g-3*B*((d+x(I)-L*W*sin(W*t(I))).^(-4)-(d-x(I)-L*W*sin(W*t(I))).^(-4)));
xdot(I+1) = xdot(I)+xddot*dt;
x(I+1) = x(I)+xdot(I+1)*dt ;
pcdone = I / npt ;
waitbar(pcdone,hw,[num2str(pcdone*100,'%5.2f') '% done'])
end
close(hw)
I strongly suggest you reduce your time step to dt = 1e-3; until you are satisfied with everything else.
In the final version, you can remove or comment the calls to the waitbar as it slows down things too.
I want to stop solving a differential equation in Matlab if it takes more than a designated amount of time. I tried the following,but it doesn't work...
options = odeset('AbsTol',1e-8,'RelTol',1e-5);
RUNTIME=5;
timerID = tic;
while (toc(timerID) < RUNTIME)
[t_pae,x_th_pae] = ode15s(#prosomoiwsh,[0 t_end],[80*pi/180;0;130*pi/180;0;th_initial(1);th_initial(2);th_initial(3);th_initial(4)],options);
end
How can I solve this?
UPDATE :
I tried what horchler suggested and now my code looks like this :
interupt_time = 20;
outputFun= #(t,y,flag)interuptFun(t,y,flag,interupt_time);
options = odeset('AbsTol',1e-5,'RelTol',1e-5,'OutputFcn',outputFun);
try
[t_pae,x_b_th_pae] = ode15s(#prosomoiwsh,[0 t_end],[0;0;0;th_initial(1);th_initial(2);th_initial(3);th_initial(4);th_initial(5);th_initial(6);th_initial(7);th_initial(8);th_initial(9);th_initial(10);th_initial(11);th_initial(12)],options);
u_pae=compute_input(epsilon,ke,kv,dD,IwF,IwG,IwD,IbF,IbG,IbD,p,m,t_pae,x_b_th_pae);
catch ME
if strcmp(ME.identifier,'interuptFun:Interupt')
disp(ME.message);
input('got caught')
else
rethrow(ME); % It's possible the error was due to something else
end
end
function dx_b_th = prosomoiwsh(t,x_b_th)
...
end
The outputFun is exactly the same as the one horchler suggested. But now it times out every single time,while previously this only happened occasionally. What am I doing wrong?
First, you can't do anything like what you're trying. All that will happen is that ode15s will run for as long as it needs and return it's result as usual. You need a way of interrupting the ODE solver in the middle of its execution when a certain designated amount of time has been exceeded. Unfortunately, you didn't provide runnable code, so I'll have to provide general suggestions that you can adapt to your problem.
One way to do this is via an Output function. This is a function that gets called after every (successful) integration step of a Matlab solver. There are are several examples of Output functions that you can examine the code of to see what you can do: odeplot, odeprint, odephas2, and odephas3. Just type edit odeplot in your command window to see the code.
Below is an example of how you might use this capability using the built-in example function vdp1000 that's referred to in the help for ode15s. You need to create a persistent variable to save the initial time, initialize it, and then check the elapsed time relative to a parameter that you pass in. Then you throw an error to abort ode15s if the elapsed time exceeds the designated value. A try-catch statement can be used to catch the error.
function ode_interupt_demo
tspan = [0 3000]; y0 = [2;0];
interupt_time = 0.05;
outputFun= #(t,y,flag)interuptFun(t,y,flag,interupt_time);
opts = odeset('AbsTol',1e-8,'RelTol',1e-5,'OutputFcn',outputFun);
try
[t,y] = ode15s(#vdp1000,tspan,y0,opts);
catch ME
if strcmp(ME.identifier,'interuptFun:Interupt')
disp(ME.message);
% Do other things
else
rethrow(ME); % It's possible the error was due to something else
end
end
function status = interuptFun(t,y,flag,interupt_time) %#ok<INUSL>
persistent INIT_TIME;
status = 0;
switch(flag)
case 'init'
INIT_TIME = tic;
case 'done'
clear INIT_TIME;
otherwise
elapsed_time = toc(INIT_TIME);
if elapsed_time > interupt_time
clear INIT_TIME;
str = sprintf('%.6f',elapsed_time);
error('interuptFun:Interupt',...
['Interupted integration. Elapsed time is ' str ' seconds.']);
end
end
One disadvantage of this approach is that you will not get a return value from ode15s. This may or may not be desirable in your application. There are likely ways around this, but they'll require more code. One easy thing that you can do is have the error message return the last time and state of the system (when it was interrupted) using the t and y values passed into the output function. It's also possible that Event functions could be used to terminate integration based on elapsed time – those might allow you to still return output from ode15s.
Hey, I've got a problem plotting a function in Matlab.
I first run this:
format long
f = inline('-x.^2');
for i = 0:10
[I(i+1) h(i+1) tid(i+1)] = trapets(f,0,1,2^i);
end
trunk = I - log(2);
hold on
grid on
plot(log(h),log(trunk),'r+')
t = -7:0;
c = polyfit(log(h),log(trunk),1);
yy = polyval(c,t);
plot(t,yy)
grid off
hold off
koefficienter = real(c)
and after that I run this file:
hold on
plot(h,trunk,'r+:','linewidth',2)
axis([0 0.6 0 0.0014])
Thing is, I don't get any errors, and the plot windows pops up with axes and all, but there is no graph to be found. It's just an empty window with two axes.
Anyone got any ideas?
Edit:
Okay, so I'm new to this site and couldn't find the reply button, so I add a reply here instead.
#woodchips :
I just realized that I hadn't given you all the information for this problem.. Sorry about that, anyhow I would really appreciate it if someone had the time to help me with this, it would seriously make my week.
This is the part I accidentally left out:
function [ I,h,tid ] = trapets(
f,a,b,n )
h=(b-a)/n;
tic; I=(f(a)+f(b));
for k=2:2:n-2
I = I+2*f(a+k*h);
end
for k = 1:2:n-1
I = I + 4*f(a+k*h);
end
I = I * h/3;
tid = toc;
end
Edit 2: So, I think that the graph I'm seeking is actually getting plotted in the first code that I wrote, the problem is that the variabe 'I' is not changing, which I expect it to do, although the variabels 'n' and 'h' do change. If 'I' was working correctly, I would probably get the right graph (hopefully). Any ideas, anyone?
Unfortunately the home computer I had with Matlab on it died the other day so I can't test anything. First thing I can think of if to simply run step by step through the code and see if the results of the math are what you are expecting. For instance Matlab was primarily made and runs as a matrix calculator if I recall correctly. As such most of the simple math doesn't function as it would punching it in a calculator. An example would be that 2^i needs to be 2.^i to operate correctly in some cases. Same with .* and ./ to use the singular scalar verses the matrices math.
The best way to find out what is going wrong is to iterate through the math a few times to ensure that it is being performed as expected. Once that is verified then you can move on to looking at plotting formatting.