use of parfor in matlab for a lattice boltzmann code - matlab

i'm working on lattice boltzmann method and i've written a matlab code.
I would like to parallelize some parts of the code but i'm new to this so i'd appreciate your help.
I'd like to know if it's possible to use the parfor for this part(collision operator):
for i=1:lx
for j=1:ly
fork=1:9
f(k,i,j)=f(k,i,j) .* (1 - omega) + omega .* feq(k,i,j);
end
end
end
I've tried to replace the outermost for loop with a parfor but the code seems to be slower.
any suggestions?
thanks in advance

You should be able to do this whole operation with a single line of code without the loops:
f = f.*(1 - omega) + omega .* feq;
On my computer with 2 cores and starting with:
f = rand(9,400,400);
feq = rand(9,400,400);
[lx,ly,lz] = size(f);
omega = rand(1);
your loop takes 0.087933 seconds, the parfor loop takes 1.166662 seconds, and this method takes 0.009388 seconds. If you can, always vectorize your code.

Related

How to find argmin/best fit/optimize for an overdetermined quadratic system for multiple variables in Matlab

I have 100 equations with 5 variables. Is there a function in Matlab which I can use to find the optimal solution of these equations?
My problem is to find argmin ||(a-ic)^2 + (b-jd)^2 + e - h(i,j)|| over all i, j from -10 to 10. ie.
%% Note: not Matlab code. Just showing the Math.
for i = -10:10
for j = -10:10
(a-ic)^2 + (b-jd)^2 + e = h(i,j)
known: h(i,j) is a 10*10 matrix,and i,j are indexes
expected: the optimal result of a,b,c,d,e
You can try using lsqnonlin as follows.
%% define a helper function in your .m file
function f = fun(x)
a=x(1); b=x(2); c=x(3); d=x(4); e=x(5); % Using variable names from your question. In other situations, be careful when overwriting e.
f=zeros(21*21,0); % size(f) is taken from your question. You should make this a variable for good practice.
for i = -10:10
for j = -10:10
f(10*(i+10+1)+(j+10+1)) = (a-i*c)^2 + (b-j*d)^2 + e - h(i,j); % 10 is taken from your question.
end
end
end
(Aside, why is your h(i,j) taking negative indices??)
In your main function you can simply write
function out=myproblem(x0)
out=lsqnonlin(#fun,x0);
end
In your cmd, you can call with specific initial try such as
myproblem([0,0,0,0,0])
Helper function over anonymous because in my experience helpers get sped up by JIT while anonymous do not. I also opted to reshape in the loops as an opposed to actually call reshape after because I expect reshape to cost significant extra time. Remember that O(1) in fun is not O(1) in lsqnonlin.
(As always, a solution to a nonlinear problem is not guaranteed.)

generate periodic function from given function

let say that from given function f(t), we want to construct new function which is given from existed function by this way
where T is some constant let say T=3; of course k can't be from -infinity to infinity in reality because we can't do infinity summation using computer,so it is first my afford
first let us define our function
function y=f(t);
y=-1/(t^2);
end
and second program
k=-1000:1:999;
F=zeros(1,length(k));
T=3;
for t=1:length(k)
F(t)=sum(f(t+k*T));
end
but when i am running second program ,i am getting
>> program
Error using ^
Inputs must be a scalar and a square matrix.
To compute elementwise POWER, use POWER (.^) instead.
Error in f (line 2)
y=-1/(t^2);
Error in program (line 5)
F(t)=sum(f(t+k*T));
so i have two question related to this program :
1.first what is error why it shows me mistake
how can i do it in excel? can i simplify it somehow? thanks in advance
EDITED :
i have changed my code by this way
k=-1000:1:999;
F=zeros(1,length(k));
T=3;
for t=1:length(k)
result=0;
for l=1:length(k)
result=result+f(t+k(l)*T);
end
F(t)=result;
end
is it ok?
To solve your problem in a vectorized way, you'll have to change the function f such that it can be called with vectors as input. This is, as #patrik suggested, achieved by using the element-wise operators .* ./ .^ (Afaik, no .+ .- exist). Unfortunately the comment of #rayryeng is not entirely correct, which may have lead to confusion. The correct way is to use the element-wise operators for both the division ./ and the square .^:
function y = f(t)
y = -1 ./ (t.^2);
end
Your existing code (first version)
k = -1000:1:999;
F = zeros(1,length(k));
T = 3;
for t=1:length(k)
F(t) = sum(f(t+k*T));
end
then works as expected (and is much faster then the version you posted in the edit).
You can even eliminate the for loop and use arrayfun instead. For simple functions f, you can also use function handles instead of creating a separate file. This gives
f = #(t) -1 ./ (t.^2);
k = -1000:1:999;
t = 1:2000;
T = 3;
F = arrayfun(#(x)sum(f(x+k*T)), t);
and is even faster and a simple one-liner. arrayfun takes any function handle as first input. We create a function handle which takes an argument x and does the sum over all k: #(x) sum(f(x+k*T). The second argument, the vector t, contains all values for which the function handle is evaluated.
As proposed by #Divakar in comments, you can also use the bsxfun function:
f = #(t) -1 ./ (t.^2);
k = -1000:1:999;
t = 1:2000;
T = 3;
F = sum(f(bsxfun(#plus,k*T,t.')),2);
where bsxfun creates a matrix containing all combinations between t and k*T, they are all evaluated using f(...) and last, the sum along the second dimension sums over all k's.
Benchmarking
Lets compare these solutions:
Combination of for loop and sum (original question):
Elapsed time is 0.043969 seconds.
Go through all combinations in 2 for loops (edited question):
Elapsed time is 1.367181 seconds.
Vectorized approach with arrayfun:
Elapsed time is 0.063748 seconds.
Vectorized approach with bsxfun as proposed by #Divakar:
Elapsed time is 0.099399 seconds.
So (sadly) the first solution including a for loop beats both vectorized approaches. For larger k vectors (-10000:1:9999), this behavior can be reproduced. The conclusion seems to be that MATLAB has indeed learned how to optimize for loops.

Slicing Variable in Parfor loop

Hi I want to run the code as below using PARFOR.
When I try it says that :
Valid indices for 'A_x' and 'A_y' are restricted in PARFOR loops.
Explanation For MATLAB to execute parfor loops efficiently, the
amount of data sent to the MATLAB workers must be minimal. One of the
ways MATLAB achieves this is by restricting the way variables can be
indexed in parfor iterations. The indicated variable is indexed in a
way that is incompatible with parfor. Suggested Action
Fix the indexing. For a description of the indexing restrictions, see “Sliced Variables” in the >Parallel Computing Toolbox documentation:
N=eveninteger;
H=zeros(N);
V=zeros(N);
A_x=zeros(N);
A_y=zeros(N);
parfor i=1:N;
for j=1:N;
if H(i,j)==-2;
t=0.3;
As_x=t*(j-i)/a;
As_y=t*(j-i)/a;
elseif H(i,j)==-3;
t=0.8;
As_x=t*(j-i)/(a*sqrt3);
As_y=t*(j-i)/(a*sqrt3);
elseif i==j
As_x=i;
As_y=i;
else
t=0;
As_x=0;
As_y=0;
end
for p=1:N/2
for q=N/2+1:N
A_x(p,q)=A_x(p,q)+As_x*(V(i,p)*V(j,q));
A_y(p,q)=A_y(p,q)+As_y*(V(i,p)*V(j,q));
end
end
end
end
I could not find solution. Could you offer me a solution.
Thanks in advance.
Erico
It looks like you're trying to perform a "reduction" on A_x and A_y using +. You might be able to work around this by doing something like the following:
parfor i = 1:N
A_x_tmp = zeros(N);
A_y_tmp = zeros(N);
for p=1:N/2
for q=N/2+1:N
A_x_tmp(p,q) = A_x_tmp(p,q) + ...
A_y_tmp(p,q) = A_y_tmp(p,q) + ...
end
end
A_x = A_x + A_x_tmp;
A_y = A_y + A_y_tmp;
end
In that way, PARFOR will understand the reduction operations on A_x and A_y.

Might be growing inside the loop. Consider Prealocating for Speed

clear all
k_1 = 37.6;
miu_1 = 41;
Den = 2.7;
N = 100;
n=1;
phi(1)=1;
for n=1:N
phi(n)= 0.3*(n/N);
K_s(n)= K_1*(1-(1+(3*k_1)/(4*miu_1))*phi(n));
miu_s(n)= miu_1*(1-(1+(3*k_1)/(4*miu_1))*phi(n));
den1(n)=Den*(1-phi(n));
vp(n)=sqrt((k_s(n)+(4/3)*miu_s(n))/den1(n));
end
figure(1);
plot(phi,miu_s);
figure(2);
plot (phi,vp)
i am new on matlab and do not know what is problem with my code when i run my program only a beep buzz and nothing happens. guide me
The reason your code doesn't work is case sensitivity. You are using k_1 and K_1, and k_s and K_s (unless that is intentional). When I change that, your code compiles ok.
clear all
k_1 = 37.6;
miu_1 = 41;
Den = 2.7;
N = 100;
n=1;
phi(1)=1;
for n=1:N
phi(n)= 0.3*(n/N);
k_s(n)= k_1*(1-(1+(3*k_1)/(4*miu_1))*phi(n));
miu_s(n)= miu_1*(1-(1+(3*k_1)/(4*miu_1))*phi(n));
den1(n)=Den*(1-phi(n));
vp(n)=sqrt((k_s(n)+(4/3)*miu_s(n))/den1(n));
end
figure(1);
plot(phi,miu_s);
figure(2);
plot (phi,vp)
when programming in MatLab, is usually a good practice to prealocate variables instead of declaring them in a loop. In this way, MatLab creates the object just once and changes each of it's values once in the loop. Otherwise you will be declaring a new variable and writing all its contents every loop iteration which is a costly process. Your Code might be working but be extreeeeemly slow, leading you to think nothing is happening. Try prealocating all the variables inside the loop with the zeros() function like this:
phi=zeros(N,1);
phi(1)=1;
K_s=zeros(N,1);
%... and so on for all your variables inside the loop
for n=1:N
phi(n)= 0.3*(n/N);
K_s(n)= k_1*(1-(1+(3*k_1)/(4*miu_1))*phi(n));
miu_s(n)= miu_1*(1-(1+(3*k_1)/(4*miu_1))*phi(n));
den1(n)=Den*(1-phi(n));
vp(n)=sqrt((k_s(n)+(4/3)*miu_s(n))/den1(n));
end
Hope that helps
You are doing a lot of unnecessary things here, including that entire loop.
For example:
N = 100;
n=1; %this value is never used
phi(1)=1; % this is overwritten in loop
for n=1:N
phi(n)= 0.3*(n/N);
... (loop continues)
You don't need a loop here. Instead, work on whole vectors
N = 100;
n = 1:100; %predefine vector
phi = 0.3*(n/N); % outputs vector of phi from 0.003 to 0.3
For cases when you are combining multiple vectors remember to use ./ and .* for element-wise divison and multiplication, e.g. the last equation will end up being:
vp=sqrt((k_s+(4/3)*miu_s)./den1);

Matlab: Optimizing speed of function call and cosine sign-finding in a loop

The code in question is here:
function k = whileloop(odefun,args)
...
while (sign(costheta) == originalsign)
y=y(:) + odefun(0,y(:),vars,param)*(dt); % Line 4
costheta = dot(y-normpt,normvec);
k = k + 1;
end
...
end
and to clarify, odefun is F1.m, an m-file of mine. I pass it into the function that contains this while-loop. It's something like whileloop(#F1,args). Line 4 in the code-block above is the Euler method.
The reason I'm using a while-loop is because I want to trigger upon the vector "y" crossing a plane defined by a point, "normpt", and the vector normal to the plane, "normvec".
Is there an easy change to this code that will speed it up dramatically? Should I attempt learning how to make mex files instead (for a speed increase)?
Edit:
Here is a rushed attempt at an example of what one could try to test with. I have not debugged this. It is to give you an idea:
%Save the following 3 lines in an m-file named "F1.m"
function ydot = F1(placeholder1,y,placeholder2,placeholder3)
ydot = y/10;
end
%Run the following:
dt = 1.5e-12 %I do not know about this. You will have to experiment.
y0 = [.1,.1,.1];
normpt = [3,3,3];
normvec = [1,1,1];
originalsign = sign(dot(y0-normpt,normvec));
costheta = originalsign;
y = y0;
k = 0;
while (sign(costheta) == originalsign)
y=y(:) + F1(0,y(:),0,0)*(dt); % Line 4
costheta = dot(y-normpt,normvec);
k = k + 1;
end
disp(k);
dt should be sufficiently small that it takes hundreds of thousands of iterations to trigger.
Assume I must use the Euler method. I have a stochastic differential equation with state-dependent noise if you are curious as to why I tell you to take such an assumption.
I would focus on your actual ODE integration. The fewer steps you have to take, the faster the loop will run. I would only worry about the speed of the sign check after you've optimized the actual integration method.
It looks like you're using the first-order explicit Euler method. Have you tried a higher-order integrator or an implicit method? Often you can increase the time step significantly.