我在openmp中非常新,我不确定我是否在代码中正确使用了并行块。我真的需要有经验的人使用openmp的帮助。我不确定的变量有:box_particles
,particles
和bx
。
以下代码中是否存在与openmp腭化有关的问题(因为这三个变量的用法)?
#include <iostream>
#include <math.h>
#include <vector>
#include <array>
#include <list>
#include <random>
#include <functional>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
#include <chrono>
#include <set>
using namespace std;
#define pi 3.141592
// function declarations
int getBoxID(double x, double y, double R0, int nbox);
vector<double> getBoxCoords(int boxID, double L, double R0, int nbox);
double dist(double x1, double y1, double x2, double y2, double L);
double PBC(double pos, double L);
std::minstd_rand gen(std::random_device{}());
std::uniform_real_distribution<double> unirnd(0, 1);
int getBoxID(double posx, double posy, double R0, int nbox)
{
int xID = ceil(posx/R0),
yID = ceil(posy/R0);
return (yID - 1) * nbox + xID - 1;
}
vector<double> getBoxCoords(int boxID, double L, double R0, int nbox)
{
vector<double> coords(4);
int yID = ceil((double)(boxID+1)/nbox);
int xID = fmod((boxID+1-(yID-1)*nbox), nbox);
if(xID==0)
xID = nbox;
coords[0] = (xID-1) * R0; // minX
coords[1] = (yID-1) * R0; // minY
coords[2] = min(xID * R0, L); // maxX
coords[3] = min(yID * R0, L); // maxY
return coords;
}
double dist(double x1, double y1, double x2, double y2, double L)
{
return pow(PBC(x1-x2,L),2.0) + pow(PBC(y1-y2,L),2.0);
}
double PBC(double pos, double L)
{
if(fabs(pos) > L / 2.0)
return L-fabs(pos);
else
return fabs(pos);
}
int main()
{
vector<vector<int>> box_neighbors;
vector<int> indices;
for(int i = 0; i < nbox * nbox; i++)
{
vector<double> ci = getBoxCoords(i, L, R0, nbox);
indices.clear();
for(int j = 0; j < nbox * nbox; j++)
{
vector<double> cj = getBoxCoords(j, L, R0, nbox);
bool xflag=false,
yflag=false;
if (PBC(ci[0]-cj[0],L)<R0 || PBC(ci[0]-cj[2],L)<R0 || PBC(ci[2]-cj[0],L)<R0 || PBC(ci[2]-cj[2],L)<R0)
xflag=true;
if (PBC(ci[1]-cj[1],L)<R0 || PBC(ci[1]-cj[3],L)<R0 || PBC(ci[3]-cj[1],L)<R0 || PBC(ci[3]-cj[3],L)<R0)
yflag=true;
if(xflag && yflag)
indices.push_back(j);
}
box_neighbors.push_back(indices);
}
double x[N],
y[N],
theta[N];
for (int i = 0; i < N; i++)
{ x[i] = unirnd(gen) * L;
y[i] = unirnd(gen) * L;
theta[i] = unirnd(gen) * pi / 2 - pi / 4 + pi / 2;
}
vector<vector<int>> box_particles;
vector<int> particles;
for(int i=0; i < nbox*nbox; i++)
{
box_particles.push_back(particles);
}
vector<int> bx;
for(int i = 0; i < N; i++)
{
bx.push_back(getBoxID(x[i],y[i],R0,nbox));
box_particles[bx[i]].push_back(i);
}
while (c < c_prod)
{
double dx[N], dy[N], theta_new[N];
c++;
#pragma omp parallel for
for(int i = 0; i < N; i++)
{
double sum_sin = 0.0, sum_cos = 0.0;
int count = 0;
for (vector<int>::iterator it = box_neighbors[bx[i]].begin(); it != box_neighbors[bx[i]].end(); ++it)
{
for (vector<int>::iterator itp = box_particles[*it].begin(); itp != box_particles[*it].end(); ++itp)
{
if(dist(x[i], y[i], x[*itp], y[*itp], L) < R0_two)
{
sum_sin+= sin(theta[*itp]);
sum_cos+= cos(theta[*itp]);
count++;
}
}
}
sum_sin/= count;
sum_cos/= count;
theta_new[i] = atan(sum_sin/sum_cos);
if (sum_cos < 0 && sum_sin < 0)
{
theta_new[i]-= pi;
}
else if (sum_cos < 0 && sum_sin > 0)
{
theta_new[i] = pi + theta_new[i];
}
dx[i] = cos(theta[i]);
dy[i] = sin(theta[i]);
double zeta = -eta / 2.0 + unirnd(gen) * eta;
theta_new[i] += zeta;
}
#pragma omp parallel for schedule(static) reduction(+ : Sum_sin,Sum_cos)
for(int i = 0; i < N; i++)
{
theta[i] = theta_new[i];
while(theta[i] > pi){
theta[i]-= 2 * pi;}
while(theta[i] < -pi){
theta[i]+= 2 * pi;}
x[i]+= dx[i];
y[i]+= dy[i];
int box_new = getBoxID(x[i],y[i],R0,nbox);
if(bx[i] != box_new)
{
vector<int>::iterator position = std::find(box_particles[bx[i]].begin(), box_particles[bx[i]].end(), i);
if (position != box_particles[bx[i]].end()) // .end() means the element was not found
box_particles[bx[i]].erase(position);
bx[i] = box_new;
box_particles[box_new].push_back(i);
}
}
}
return 0;
}