void getNeighbors( NeighborList& neighbors, const VoxelItem& referencePoint, const vector<set<int> >& exclusions, bool reportSymmetricPairs, double maxDistance, double minDistance) const { // Loop over neighboring voxels // TODO use more clever selection of neighboring voxels assert(maxDistance > 0); assert(minDistance >= 0); assert(voxelSizeX > 0); assert(voxelSizeY > 0); assert(voxelSizeZ > 0); const AtomIndex atomI = referencePoint.second; const RealVec& locationI = *referencePoint.first; double maxDistanceSquared = maxDistance * maxDistance; double minDistanceSquared = minDistance * minDistance; int dIndexX = int(maxDistance / voxelSizeX) + 1; // How may voxels away do we have to look? int dIndexY = int(maxDistance / voxelSizeY) + 1; int dIndexZ = int(maxDistance / voxelSizeZ) + 1; VoxelIndex centerVoxelIndex = getVoxelIndex(locationI); int lastx = centerVoxelIndex.x+dIndexX; int lasty = centerVoxelIndex.y+dIndexY; int lastz = centerVoxelIndex.z+dIndexZ; if (usePeriodic) { lastx = min(lastx, centerVoxelIndex.x-dIndexX+nx-1); lasty = min(lasty, centerVoxelIndex.y-dIndexY+ny-1); lastz = min(lastz, centerVoxelIndex.z-dIndexZ+nz-1); } for (int x = centerVoxelIndex.x - dIndexX; x <= lastx; ++x) { for (int y = centerVoxelIndex.y - dIndexY; y <= lasty; ++y) { for (int z = centerVoxelIndex.z - dIndexZ; z <= lastz; ++z) { VoxelIndex voxelIndex(x, y, z); if (usePeriodic) { voxelIndex.x = (x+nx)%nx; voxelIndex.y = (y+ny)%ny; voxelIndex.z = (z+nz)%nz; } if (voxelMap.find(voxelIndex) == voxelMap.end()) continue; // no such voxel; skip const Voxel& voxel = voxelMap.find(voxelIndex)->second; for (Voxel::const_iterator itemIter = voxel.begin(); itemIter != voxel.end(); ++itemIter) { const AtomIndex atomJ = itemIter->second; const RealVec& locationJ = *itemIter->first; // Ignore self hits if (atomI == atomJ) continue; // Ignore exclusions. if (exclusions[atomI].find(atomJ) != exclusions[atomI].end()) continue; double dSquared = compPairDistanceSquared(locationI, locationJ, periodicBoxSize, usePeriodic); if (dSquared > maxDistanceSquared) continue; if (dSquared < minDistanceSquared) continue; neighbors.push_back( AtomPair(atomI, atomJ) ); if (reportSymmetricPairs) neighbors.push_back( AtomPair(atomJ, atomI) ); } } } } }
void getNeighbors( ThreeNeighborList& neighbors, const VoxelItem& referencePoint, double maxDistance, double minDistance) const { // Loop over neighboring voxels // TODO use more clever selection of neighboring voxels assert(maxDistance > 0); assert(minDistance >= 0); assert(voxelSizeX > 0); assert(voxelSizeY > 0); assert(voxelSizeZ > 0); const AtomIndex atomI = referencePoint.second; const RealVec& locationI = *referencePoint.first; double maxDistanceSquared = maxDistance * maxDistance; double minDistanceSquared = minDistance * minDistance; int dIndexX = int(maxDistance / voxelSizeX) + 1; // How may voxels away do we have to look? int dIndexY = int(maxDistance / voxelSizeY) + 1; int dIndexZ = int(maxDistance / voxelSizeZ) + 1; VoxelIndex centerVoxelIndex = getVoxelIndex(locationI); int lastx = centerVoxelIndex.x+dIndexX; int lasty = centerVoxelIndex.y+dIndexY; int lastz = centerVoxelIndex.z+dIndexZ; if (usePeriodic) { lastx = min(lastx, centerVoxelIndex.x-dIndexX+nx-1); lasty = min(lasty, centerVoxelIndex.y-dIndexY+ny-1); lastz = min(lastz, centerVoxelIndex.z-dIndexZ+nz-1); } std::vector<AtomIndex> nearbyAtoms; std::vector<const RealVec*> nearbyAtomsLocation; // Loop through nearby Voxels and create vectors of nearby Atoms and their locations for (int x = centerVoxelIndex.x - dIndexX; x <= lastx; ++x) { for (int y = centerVoxelIndex.y - dIndexY; y <= lasty; ++y) { for (int z = centerVoxelIndex.z - dIndexZ; z <= lastz; ++z) { VoxelIndex voxelIndex(x, y, z); if (usePeriodic) { voxelIndex.x = (x+nx)%nx; voxelIndex.y = (y+ny)%ny; voxelIndex.z = (z+nz)%nz; } if (voxelMap.find(voxelIndex) == voxelMap.end()) continue; // no such voxel; skip const Voxel& voxel = voxelMap.find(voxelIndex)->second; for (Voxel::const_iterator itemIter = voxel.begin(); itemIter != voxel.end(); ++itemIter) { const AtomIndex atomJ = itemIter->second; const RealVec& locationJ = *itemIter->first; // Ignore self hits if (atomI == atomJ) continue; double dSquared = compPairDistanceSquared(locationI, locationJ, periodicBoxSize, usePeriodic); if (dSquared > maxDistanceSquared) continue; if (dSquared < minDistanceSquared) continue; nearbyAtoms.push_back( atomJ ); nearbyAtomsLocation.push_back( itemIter->first ); } // for atom indices } // for z } // for y } // for x if (nearbyAtoms.size() >= 2) { // Loop through each combination of the reference atom (atomI) with each pair of nearby atoms atomJ and atomQ for (unsigned int atomJindex=0; atomJindex<(nearbyAtoms.size()-1); atomJindex++) { for (unsigned int atomQindex=atomJindex+1; atomQindex<nearbyAtoms.size(); atomQindex++) { // check only distance Q-J, we checked I-J and I-Q in the previous loop double dSquared = compPairDistanceSquared(*nearbyAtomsLocation[atomJindex], *nearbyAtomsLocation[atomQindex], periodicBoxSize, usePeriodic); if (dSquared > maxDistanceSquared) continue; if (dSquared < minDistanceSquared) continue; AtomTriplet triplet = {atomI, nearbyAtoms[atomJindex], nearbyAtoms[atomQindex]}; neighbors.push_back(triplet); } } } }