ELECTRIC POTENTIAL - How to speed up the code? (COMPLETE CODE INCLUDED)
Show older comments
Hi.
I have a code which calculates an electrical potential around stormy cloud, which is placed above the lighthouse. I compute this using "Finite difference method". A "box" is an 320x320 matrix with known boundary conditions (V=0) and V of a cloud is also known (V1). V of a lighthouse is 0.
Now I have 2 nested "for" loops which go from left to right side of a matrix and from top to bottom. Every round I compare new and old value of matrix. When they differentiate for less than 0.01 I am happy and quit.
That method works OK, except it is very slow. It needs more than 4 hours to complete. Do you have any idea how to speed it up? Is possible not to use nested "for" loops? I read a lot about vectorization, but still don't know how to put this into my code.
I include a complete code, so you are welcome to look at it.
Thanks
clc; clear;
% Cloud Potential
V1 = 6500;
% Cloud Radius
CloudRad = 20;
% Cloud Height
CloudHeight = 40;
% Number of points (vertically * horizontally)
n = 320;
% Height and Radius of a Space (width is 2 * rho)
h = 80;
rho = 40;
% Space Width - Cloud Width
Width = 2*rho - 2*CloudRad;
% Lighthouse measurements
rad1 = 6;
rad2 = 7;
h1 = 22;
h2 = 17;
r = linspace(0,2*rho,n);
z = linspace(h,0,n);
% Mesh
[rr,zz] = meshgrid(r,z);
% Cloud measurements based on mesh
RelCloudHeight = round(((h-CloudHeight)/h) * n);
if RelCloudHeight == 0
RelCloudHeight = 1;
end
RelCloudWidth = round(((2*rho-Width)/(2*rho))*n);
% Matrix of calculated Potential
V = zeros(n);
% Cloud is always on V1
V(RelCloudHeight,(n/2-RelCloudWidth/2)+1:(n/2+RelCloudWidth/2)) = V1;
% Boundary conditions - Potential there is 0
V(1:n,1) = zeros(n,1);
V(1:n,n) = zeros(n,1);
% Lighthouse measurements based on mesh
UpperHight = (round(((h-h1)/h)*n));
MiddleHight = (round((h-h2)/h*n));
ExtremeLeft = round(((rho-rad1)/(2*rho))*n)+1;
ExtremeRight = round(((rho+rad1)/(2*rho))*n);
Left = round(((rho-rad2)/(2*rho))*n);
Right = round(((rho+rad2)/(2*rho))*n);
Finite difference method
difference = 100;
while difference > 0.01 % Desired final accuracy
VV = V;
for i = 2:n-1 % Along the rows of matrix V
for j = 2:n-1 % Along the columns of matrix V
% Lighthouse is always on V=0
V(UpperHight:MiddleHight,ExtremeLeft:ExtremeRight) = 0;
V(MiddleHight:n,Left:Right) = 0;
% Cloud is always on V1
V(RelCloudHeight,(n/2-RelCloudWidth/2)+1:(n/2+RelCloudWidth/2)) = V1;
% Iteration equation
V(i,j) = (1/6)*(2*V(i,j+1)+2*V(i,j-1)+V(i+1,j)+V(i-1,j));
end
end
% Watching the difference between old and new value of V
difference = max(max(abs(V-VV)));
end
% At the end I set the predetermined elements of V to the required value
% for the last time
V(UpperHight:MiddleHight,ExtremeLeft:ExtremeRight) = 0;
V(MiddleHight:n,Left:Right) = 0;
V(RelCloudHeight,(n/2-RelCloudWidth/2)+1:(n/2+RelCloudWidth/2)) = V1;
save LighthouseOUT.mat
PLOTTING
figure;
EkvNum = 150; % Number of equipotential contours
contour(rr,zz,V,EkvNum); axis equal;
% Plotting area
xlim([0 2*rho]); ylim([0 h]);
set(gca,'fontsize',14,'fontname','Times','box','on');
title(['Equipotentials (' num2str(EkvNum) ')']);
xlabel('{\itWidth} / m');
ylabel('{\itHeight} / m');
% Plotting lighthouse:
line([rho-rad2 rho-rad2],[0 h2],'LineWidth',2,'Color','black');
line([rho+rad2 rho+rad2],[0 h2],'LineWidth',2,'Color','black');
line([rho-rad2 rho-rad1],[h2 h2],'LineWidth',2,'Color','black');
line([rho+rad2 rho+rad1],[h2 h2],'LineWidth',2,'Color','black');
line([rho-rad1 rho-rad1],[h2 h1],'LineWidth',2,'Color','black');
line([rho+rad1 rho+rad1],[h2 h1],'LineWidth',2,'Color','black');
line([rho-rad1 rho+rad1],[h1 h1],'LineWidth',2,'Color','black');
% Plotting cloud:
line([rho-CloudRad rho+CloudRad],[CloudHeight CloudHeight],...
'LineWidth',2,'Color','black');
Accepted Answer
More Answers (0)
Categories
Find more on Descriptive Statistics and Visualization 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!