// -*- C++ -*- // NeighborCellLocator.h: Cell-based algorithm for finding neighbors. // // Copyright (C) 2008-2011 Jakob Schiotz and Center for Individual // Nanoparticle Functionality, Department of Physics, Technical // University of Denmark. Email: schiotz@fysik.dtu.dk // // This file is part of Asap version 3. // Asap is released under the GNU Lesser Public License (LGPL) version 3. // However, the parts of Asap distributed within the OpenKIM project // (including this file) are also released under the Common Development // and Distribution License (CDDL) version 1.0. // // This program is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License // version 3 as published by the Free Software Foundation. Permission // to use other versions of the GNU Lesser General Public License may // granted by Jakob Schiotz or the head of department of the // Department of Physics, Technical University of Denmark, as // described in section 14 of the GNU General Public License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // and the GNU Lesser Public License along with this program. If not, // see . #ifndef NEIGHBORCELLLOCATOR #define NEIGHBORCELLLOCATOR #include "AsapPython.h" #include "Asap.h" #include "Vec.h" #include "NeighborLocator.h" #include "IVec.h" #include "Templates.h" #include using std::vector; #include #include using std::pair; #include #include #define COMPACT_NBLIST namespace ASAPSPACE { typedef int translationsidx_t; // Could also be unsigned char // The datatpe neighboritem_t is mainly used in NeigbhorList.cpp // It is a combination of an index into the atoms and an index // into a list of translation vectors. #ifdef COMPACT_NBLIST // A neighborlist item is a single 32-bit unsigned integer, // the first 5 bits are the tranlation vector index, the last 27 are // the actual neighborlist index. typedef uint32_t neighboritem_t; #define NEIGHBOR_ITEM_MASK ((1 << 27) - 1) #define NEIGHBOR_XLAT_SHIFT 27 #define NEIGHBOR_INDEX(x) ((x) & NEIGHBOR_ITEM_MASK) #define NEIGHBOR_XLAT(x) ((x) >> NEIGHBOR_XLAT_SHIFT) #define NEIGHBORITEM_PACK(x,a,b) x = a | (b << NEIGHBOR_XLAT_SHIFT) #else // COMPACT_NBLIST // A neighborlist item is a pair of an int (the actual neighborlist // index) and a translationsidx_t, the translation vector index. typedef pair neighboritem_t; #define NEIGHBOR_INDEX(x) (x).first #define NEIGHBOR_XLAT(x) (x).second #define NEIGHBORITEM_PACK(x,a,b) x; (x).first = a; (x).second = b; #endif // COMPACT_NBLIST PyAsap_NeighborLocatorObject *PyAsap_NewNeighborCellLocator(Atoms *a, double rCut, double driftfactor = 0.05); class NeighborCellLocator : public NeighborLocator { protected: /// Generate a neighbor list for atoms a with cutoff rCut. /// The neighbor list will contain all neighbors within the distance /// rCut. The neighborlist can be reused until an atom has moved /// more than rCut*driftfactor. NeighborCellLocator(Atoms *a, double rCut, double driftfactor = 0.05); virtual ~NeighborCellLocator(); friend PyAsap_NeighborLocatorObject *PyAsap_NewNeighborCellLocator( Atoms *a, double rCut, double driftfactor); friend void PyAsap_Dealloc(PyObject *self); public: /// Enable neighbors of ghost atoms by calling this just after the constructor void EnableNeighborsOfGhosts(); /// Check if the neighbor list can still be reused, update if not. bool CheckAndUpdateNeighborList(); /// Check if the neighbor list can still be reused, update if not. /// /// This version is used when called from Python virtual bool CheckAndUpdateNeighborList(PyObject *atoms); /// Check the neighbor list. /// /// Check if the neighbor list can still be reused, return true if /// it should be updated. virtual bool CheckNeighborList(); /// Update neighbor list virtual void UpdateNeighborList(); /// Get wrapped positions of all the atoms const vector &GetWrappedPositions() const {ASSERT(wrappedPositionsValid); return wrappedPositions;} void GetWrappedPositions(vector &wp) const {ASSERT(wrappedPositionsValid); wp.insert(wp.begin(), wrappedPositions.begin(), wrappedPositions.end());} /// Get scaled positions of all the atoms const vector &GetScaledPositions() const; /// Get reference positions (used by NeighborList) const Vec *GetReferencePositions() const {return &referencePositions[0];} /// Get information about the neighbors of atom n ("half" neighbor list) /// /// Input values: n is the number of the atom. r (optional) is a /// cutoff, must be less than rCut in the constructor (not /// checked!). /// /// In-out values: size contains the maximum space in the arrays. /// It is decremented by the number of neighbors placed in the /// arrays. It is an error to call GetNeighbors with too small a /// value of size. /// /// Out values: neighbors[] contains the numbers of the atoms, /// diffs[] contains the \em relative positions of the atoms, /// diffs2[] contains the norms of the diffs vectors. /// /// Return value: The number of neighbors. int GetNeighbors(int n, int *neighbors, Vec *diffs, double *diffs2, int& size, double r = -1.0) const; /// Get information about the neighbors of atom n ("half" neighbor list) /// /// This version of GetNeighbors only returns the numbers of the neighbors. /// It is intended for the Python interface. void GetNeighbors(int n, vector &neighbors) const; int GetFullNeighbors(int n, int *neighbors, Vec *diffs, double *diffs2, int& size, double r = -1.0) const; /// Get information about the neighbors of atom n (full neighbor list) /// /// This version of GetNeighbors only returns the numbers of the neighbors. /// It is intended for the Python interface. void GetFullNeighbors(int n, vector &neighbors) const; /// Return the neighbors and the corresponding translations. /// /// The vectors are cleared before data is put into them. /// /// Return value: The number of neighbors. int GetListAndTranslations(int n, vector &neighbors) const; int GetComplementaryListAndTranslations(int n, vector &neighbors) const; /// Remake neighbor lists when a few atoms have been modified. /// /// This version, unlike NeighborList::RemakeList does /// not report back which other atoms have been affected. void RemakeLists_Simple(const set &modified); /// Return the guaranteed maximal length of a single atom's NB list. /// Call this before using GetNeighbors() to make sure the arrays /// are big enough. The value may change when the neighbor list is /// updated. int MaxNeighborListLength() const {return maxLength;} /// Get the number of atoms in the corresponding list of atoms. int GetNumberOfAtoms() const {return nAtoms;} // Used from swig. /// Return the cutoff distance (rCut) specified when creating this nblist. double GetCutoffRadius() const {return rCut;} /// Return the cutoff distance including twice the drift. /// /// For a NeighborCellLocator, the drift cannot be predicted and is ignored. double GetCutoffRadiusWithDrift() const {return rCut;} /// Get a copy of the table of translations (27 entries) void GetTranslationTable(vector &table) const; /// Normalize the positions and calculate scaled space version /// /// This is used when a neighbor list is updated void ScaleAndNormalizePositions(); /// Normalize some positions and calculate scaled space version /// /// The first argument is a set of atoms to be normalized, the /// corresponding scaled positions are placed in scaledpos. void ScaleAndNormalizePositions(const set &modified, vector &scaledpos); /// Normalizing new positions using the normalization already calculated. /// /// This is used when checking a neighborlist. void RenormalizePositions(); #if 0 /// Renormalize the old positions using old and new positions of the atoms. /// /// This is called by a master neighbor list when it has normalized /// the positions of the atoms. The argument is the positions of /// the atoms *before* renormalization, this method uses them /// together with the current positions to update its own list of /// old positions. void RenormalizeReferencePositions(const vector &oldpos); #endif /// Update reference positions of some atoms void UpdateReferencePositions(const set &modified); /// Return the atoms access object. Used by a few tool functions. virtual Atoms *GetAtoms() const {return atoms;} string GetName() const {return "NeighborCellLocator";} /// Print internal info about an atom virtual void print_info(int n); /// Print memory usage virtual long PrintMemory() const; protected: /// Generate a new neighbor list. virtual void MakeList(); /// Make the lists of neighboring cells. void MakeNeighboringCellLists(); /// Make translation table void MakeTranslationTable(); typedef vector< pair > nbcell_t; void makeNbCells(int thiscell); int CommonGetNeighbors(int n, int *neighbors, Vec *diffs, double *diffs2, int& size, double r, bool wantfull) const; void CommonGetNeighbors(int a1, vector &neighbors, bool wantfull) const; double get_drift() const; protected: Atoms *atoms; ///< A pointer to the atoms. int nAtoms; ///< The number of atoms excluding ghosts. int nAllAtoms; ///< The number of atoms including ghosts. double rCut; ///< The cutoff radius. double rCut2; ///< The square of the cutoff radius. double minboxsize; ///< The minimal box size bool periodic[3]; ///< The boundary conditions. bool oldperiodic[3]; ///< The boundary conditions at the last update. int maxLength; ///< The guaranteed max length of a neighbor list. int nCells[3]; ///< Number of cells int nTotalCells[4]; int nCellsTrue[3]; int nCellsGapStart[3]; int nCellsGapSize[3]; bool includeghostneighbors; ///< Include neighbors to ghost atoms. double size[3]; ///< Size of system in scaled space double minimum[3]; ///< Offset of system in scaled space vector referencePositions; ///< Positions at last update. vector wrappedPositions; ///< Wrapped positions. vector scaledPositions; ///< Scaled positions. vector offsetPositions; ///< wrappedPositions - positions. vector scaledOffsetPositions; bool scaledPositionsValid; bool wrappedPositionsValid; Vec old_inverse_cell[3]; ///< Inverse unit cell of last renormalization. int supercell_counter; ///< When was old_inverse_cell last updated? /// The list of cells containing the atoms vector< vector > cells; /// The number of the cell to which an atom belongs vector cellIndices; /// For each cell, a list of the neighboring cells, and their offset /// across the periodic boundaries. vector neighborCellOffsets; /// List of neighboring cells, valid for ... nbcell_t nbCells_inside; // ... a cell not touching the boundary. nbcell_t nbCells_left; // ... a cell touching a single boundary. nbcell_t nbCells_right; nbcell_t nbCells_top; nbcell_t nbCells_bottom; nbcell_t nbCells_front; nbcell_t nbCells_back; /// Lists of neighboring cells for all cells. Center and sides are /// pointers to the objects above, edges and corners are unique. std::map nbCells_all; vector nbCells_onthefly; // On-the-fly elements in nbCells_all // (for memory management). /// Table of possible translation vectors vector translationTable; }; } // end namespace #endif // NEIGHBORCELLLOCATOR