Vectorizing/Profiling Code with double for loops etc

2 views (last 30 days)
Hi,
Need help increasing the efficiency of the code below (getting rid of double for-loops etc.) I saw some topics relating to bsxfun, but im not too sure if thats applicable here. I appreciate all help in advance. Thank you.
EDIT: Tried changing some other things to vectorize this, but could not make it happen. END Edit
Here's the code:
if true
% code
end
clear;clc;close all
tic
cylgrid = ones(201,502);
init = 100:-1:-100;
i=1:201;
for j=1:502
cylgrid(:,j)=init;
end
%initialize circle
j=500;
for ii = -100:100 %fluctuate i
for jj= 1:502 %fluctuate j
if sqrt( (ii ).^2 +(jj - j./5).^2) < 25
cylgrid(ii+101,jj) = 0;%psi = 0 at surface and inside cylinder
end
end
end
psi = cylgrid;%just for notation
psinew= cylgrid;
error = 0.001;
t=0;dt=1;
while error < max(max(psinew-psi)) || t==0
psi=psinew;
for ii = 2:200
for jj = 2:500
psinew(ii,jj) = psi(ii,jj) +(1/4).*(psi(ii-1,jj)+psi(ii+1,jj)+psi(ii,jj-1)+psi(ii,jj+1)-4.*psi(ii,jj));
end
end
%making sure we begin with our circle again...
for ii = -100:100 %fluctuate i
for jj= 1:502 %fluctuate j
if sqrt( (ii ).^2 +(jj - j./5).^2) < 25
psinew(ii+101,jj) = 0;%psi = 0 at surface and inside cylinder
end
end
end
t=t+dt;
end
uprofile= abs(psinew);
for iii = 100:-1:1
for jjj=1:502
uprofile(101-iii,jjj) = uprofile(101-iii,jjj)./iii;
uprofile(iii+101,jjj) = uprofile(iii+101,jjj)./iii;
end
end
figure(1); title('Streamline Plot');
contourf(psinew,100);set(gca,'DataAspectRatio',[1 1 1]);
figure(2);title('Velocity Profile');
contourf(uprofile,10);set(gca,'DataAspectRatio',[1 1 1]);
toc

Accepted Answer

Geoff Hayes
Geoff Hayes on 3 May 2014
Hi E,
Within your while loop, there is the following chunk of code:
%making sure we begin with our circle again...
for ii = -100:100 %fluctuate i
for jj= 1:502 %fluctuate j
if sqrt( (ii ).^2 +(jj - j./5).^2) < 25
psinew(ii+101,jj) = 0;%psi = 0 at surface and inside cylinder
end
end
end
Unless I'm misreading something, the ii and jj that satisfy the condition sqrt( (ii ).^2 +(jj - j./5).^2) < 25 will always be the same (and are no different than those that were used in the similar block when the circle is initialized). If that is the case, then why not just keep track of these indices and re-use them, rather than doing this double loop again and again for the same set? When the circle is initialized, just add the following matrix to keep track of the indices that are being set to zero:
% initialize matrix to keep track of indices that should be reset to zero
indcsToReset = cast(zeros(size(cylgrid)),'logical');
%initialize circle
j=500;
for ii = -100:100 %fluctuate i
for jj= 1:502 %fluctuate j
if sqrt( (ii ).^2 +(jj - j./5).^2) < 25
cylgrid(ii+101,jj) = 0;%psi = 0 at surface and inside cylinder
% reset this index
indcsToReset(ii+101,jj) = true;
end
end
end
Then you can replace the first chunk above with the comment making sure we begin with our circle again with
psinew(indcsToReset)=0;
Hopefully the above is a start to improving performance…
Geoff
  8 Comments
E
E on 4 May 2014
I'd been trying to figure out how to do that "psinew" line of code for a long time now. I kept getting errors. I really appreciate this!

Sign in to comment.

More Answers (1)

Jan
Jan on 4 May 2014
A general hint: SQRT() is expensive, so try to avoid it:
sqrt( (ii ).^2 +(jj - j./5).^2) < 25
Faster:
ii.^2 + (jj - j ./ 5).^2 < 625

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!