void Neighbor::build(Atom &atom) { ncalls++; const int nlocal = atom.nlocal; const int nall = atom.nlocal + atom.nghost; /* extend atom arrays if necessary */ #pragma omp master if(nall > nmax) { nmax = nall; #ifdef ALIGNMALLOC if(numneigh) _mm_free(numneigh); numneigh = (int*) _mm_malloc(nmax * sizeof(int) + ALIGNMALLOC, ALIGNMALLOC); if(neighbors) _mm_free(neighbors); neighbors = (int*) _mm_malloc(nmax * maxneighs * sizeof(int) + ALIGNMALLOC, ALIGNMALLOC); #else if(numneigh) free(numneigh); if(neighbors) free(neighbors); numneigh = (int*) malloc(nmax * sizeof(int)); neighbors = (int*) malloc(nmax * maxneighs * sizeof(int)); #endif } #pragma omp barrier /* bin local & ghost atoms */ binatoms(atom); count = 0; /* loop over each atom, storing neighbors */ const MMD_float* const x = atom.x; const int* const type = atom.type; int ntypes = atom.ntypes; resize = 1; #pragma omp barrier while(resize) { #pragma omp barrier int new_maxneighs = maxneighs; resize = 0; #pragma omp barrier OMPFORSCHEDULE for(int i = 0; i < nlocal; i++) { int* neighptr = &neighbors[i * maxneighs]; /* if necessary, goto next page and add pages */ int n = 0; const MMD_float xtmp = x[i * PAD + 0]; const MMD_float ytmp = x[i * PAD + 1]; const MMD_float ztmp = x[i * PAD + 2]; const int type_i = type[i]; /* loop over atoms in i's bin, */ const int ibin = coord2bin(xtmp, ytmp, ztmp); for(int k = 0; k < nstencil; k++) { const int jbin = ibin + stencil[k]; int* loc_bin = &bins[jbin * atoms_per_bin]; if(ibin == jbin) for(int m = 0; m < bincount[jbin]; m++) { const int j = loc_bin[m]; //for same bin as atom i skip j if i==j and skip atoms "below and to the left" if using halfneighborlists if(((j == i) || (halfneigh && !ghost_newton && (j < i)) || (halfneigh && ghost_newton && ((j < i) || ((j >= nlocal) && ((x[j * PAD + 2] < ztmp) || (x[j * PAD + 2] == ztmp && x[j * PAD + 1] < ytmp) || (x[j * PAD + 2] == ztmp && x[j * PAD + 1] == ytmp && x[j * PAD + 0] < xtmp))))))) continue; const MMD_float delx = xtmp - x[j * PAD + 0]; const MMD_float dely = ytmp - x[j * PAD + 1]; const MMD_float delz = ztmp - x[j * PAD + 2]; const int type_j = type[j]; const MMD_float rsq = delx * delx + dely * dely + delz * delz; if((rsq <= cutneighsq[type_i*ntypes+type_j])) neighptr[n++] = j; } else { for(int m = 0; m < bincount[jbin]; m++) { const int j = loc_bin[m]; if(halfneigh && !ghost_newton && (j < i)) continue; const MMD_float delx = xtmp - x[j * PAD + 0]; const MMD_float dely = ytmp - x[j * PAD + 1]; const MMD_float delz = ztmp - x[j * PAD + 2]; const int type_j = type[j]; const MMD_float rsq = delx * delx + dely * dely + delz * delz; if((rsq <= cutneighsq[type_i*ntypes+type_j])) neighptr[n++] = j; } } } numneigh[i] = n; if(n >= maxneighs) { resize = 1; if(n >= new_maxneighs) new_maxneighs = n; } } // #pragma omp barrier if(resize) { #pragma omp master { maxneighs = new_maxneighs * 1.2; #ifdef ALIGNMALLOC _mm_free(neighbors); neighbors = (int*) _mm_malloc(nmax* maxneighs * sizeof(int) + ALIGNMALLOC, ALIGNMALLOC); #else free(neighbors); neighbors = (int*) malloc(nmax* maxneighs * sizeof(int)); #endif } #pragma omp barrier } } #pragma omp barrier }
void Neighbor::build(Atom &atom) { ncalls++; const int nlocal = atom.nlocal; const int nall = atom.nlocal + atom.nghost; /* extend atom arrays if necessary */ #pragma omp master if(nall > nmax) { nmax = nall; if(numneigh) free(numneigh); if(neighbors) free(neighbors); numneigh = (int*) malloc(nmax * sizeof(int)); neighbors = (int*) malloc(nmax * maxneighs * sizeof(int*)); } int omp_me = omp_get_thread_num(); int num_omp_threads = threads->omp_num_threads; int master = -1; #pragma omp master master = omp_me; #pragma omp barrier /* bin local & ghost atoms */ binatoms(atom); count = 0; /* loop over each atom, storing neighbors */ const MMD_float* x = &atom.x[0][0]; resize = 1; #pragma omp barrier while(resize) { #pragma omp barrier int new_maxneighs = maxneighs; resize = 0; #pragma omp barrier #pragma omp for schedule(static,CHUNKSIZE) for(int i = 0; i < nlocal; i++) { int* neighptr = &neighbors[i * maxneighs]; /* if necessary, goto next page and add pages */ int n = 0; const MMD_float xtmp = x[3 * i + 0]; const MMD_float ytmp = x[3 * i + 1]; const MMD_float ztmp = x[3 * i + 2]; /* loop over atoms in i's bin, */ const int ibin = coord2bin(xtmp, ytmp, ztmp); for(int k = 0; k < nstencil; k++) { const int jbin = ibin + stencil[k]; int* loc_bin = &bins[jbin * atoms_per_bin]; if(ibin == jbin) for(int m = 0; m < bincount[jbin]; m++) { const int j = loc_bin[m]; //for same bin as atom i skip j if i==j and skip atoms "below and to the left" if using halfneighborlists if(((j == i) || (halfneigh && !ghost_newton && (j < i)) || (halfneigh && ghost_newton && ((j < i) || ((j >= nlocal) && ((x[3 * j + 2] < ztmp) || (x[3 * j + 2] == ztmp && x[3 * j + 1] < ytmp) || (x[3 * j + 2] == ztmp && x[3 * j + 1] == ytmp && x[3 * j + 0] < xtmp))))))) continue; const MMD_float delx = xtmp - x[3 * j + 0]; const MMD_float dely = ytmp - x[3 * j + 1]; const MMD_float delz = ztmp - x[3 * j + 2]; const MMD_float rsq = delx * delx + dely * dely + delz * delz; if((rsq <= cutneighsq)) neighptr[n++] = j; } else { for(int m = 0; m < bincount[jbin]; m++) { const int j = loc_bin[m]; if(halfneigh && !ghost_newton && (j < i)) continue; const MMD_float delx = xtmp - x[3 * j + 0]; const MMD_float dely = ytmp - x[3 * j + 1]; const MMD_float delz = ztmp - x[3 * j + 2]; const MMD_float rsq = delx * delx + dely * dely + delz * delz; if((rsq <= cutneighsq)) neighptr[n++] = j; } } } numneigh[i] = n; if(n >= maxneighs) { resize = 1; if(n >= new_maxneighs) new_maxneighs = n; } } #pragma omp barrier if(resize) { #pragma omp master { free(neighbors); maxneighs = new_maxneighs * 1.2; neighbors = (int*) malloc(nmax* maxneighs * sizeof(int)); } #pragma omp barrier } } #pragma omp barrier }