使用并行块中定义的variabled

时间:2017-11-21 13:21:31

标签: c++ openmp

我在openmp中非常新,我不确定我是否在代码中正确使用了并行块。我真的需要有经验的人使用openmp的帮助。我不确定的变量有:box_particlesparticlesbx

以下代码中是否存在与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;
}

0 个答案:

没有答案