00001 // -*- C++ -*- 00002 /*************************************************************************** 00003 * 00004 * The IPPL Framework 00005 * 00006 * 00007 * Visit http://people.web.psi.ch/adelmann/ for more details 00008 * 00009 ***************************************************************************/ 00010 00011 #ifndef PARTICLE_INTERACT_LAYOUT_H 00012 #define PARTICLE_INTERACT_LAYOUT_H 00013 00014 /* 00015 * ParticleInteractLayout - particle layout based on spatial decomposition, 00016 * with particle interaction (nearest-neighbor with cutoff) 00017 * 00018 * This is a specialized version of ParticleLayout, which places particles 00019 * on processors based on their spatial location relative to a fixed grid. 00020 * In particular, this can maintain particles on processors based on a 00021 * specified FieldLayout or RegionLayout, so that particles are always on 00022 * the same node as the node containing the Field region to which they are 00023 * local. This may also be used if there is no associated Field at all, 00024 * in which case a grid is selected based on an even distribution of 00025 * particles among processors. 00026 */ 00027 00028 // include files 00029 #include "Particle/ParticleSpatialLayout.h" 00030 #include "Particle/ParticleInteractAttrib.h" 00031 #include "Particle/ParticleBase.h" 00032 #include "Region/RegionLayout.h" 00033 00034 #ifdef IPPL_STDSTL 00035 #include <vector> 00036 using std::vector; 00037 #else 00038 #include <vector.h> 00039 #endif // IPPL_STDSTL 00040 00041 #ifdef IPPL_USE_STANDARD_HEADERS 00042 #include <iostream> 00043 using namespace std; 00044 #else 00045 #include <iostream.h> 00046 #endif 00047 00048 // forward declarations 00049 class UserList; 00050 template <unsigned Dim> class FieldLayout; 00051 template <unsigned Dim, class T> class UniformCartesian; 00052 template <class T, unsigned Dim, class Mesh> class ParticleInteractLayout; 00053 template <class T, unsigned Dim, class Mesh> 00054 ostream& operator<<(ostream&, const ParticleInteractLayout<T,Dim,Mesh>&); 00055 00056 00057 // ParticleInteractLayout class definition. Template parameters are the type 00058 // and dimension of the ParticlePos object used for the particles. The 00059 // dimension of the position must match the dimension of the FieldLayout 00060 // object used in this particle layout, if any. 00061 // Optional template parameter for the mesh type 00062 template < class T, unsigned Dim, class Mesh=UniformCartesian<Dim,T> > 00063 class ParticleInteractLayout : public ParticleSpatialLayout<T, Dim, Mesh> { 00064 00065 public: 00066 // a struct which holds data for a single pairwise interaction 00067 struct pair_t { 00068 unsigned first; // index of 2nd member of pair 00069 T second; // separation of particles 00070 pair_t(unsigned f, T s) : first(f), second(s) { } 00071 pair_t() { } 00072 }; 00073 00074 // type of iterator over pairs 00075 typedef typename vector<pair_t>::iterator pair_iterator; 00076 00077 typedef typename ParticleLayout<T, Dim>::SingleParticlePos_t 00078 SingleParticlePos_t; 00079 typedef typename ParticleLayout<T, Dim>::Index_t Index_t; 00080 00081 // type of attributes this layout should use for position, ID, and rad 00082 typedef ParticleInteractAttrib<SingleParticlePos_t> ParticlePos_t; 00083 typedef ParticleInteractAttrib<Index_t> ParticleIndex_t; 00084 typedef ParticleInteractAttrib<T> ParticleInterRadius_t; 00085 00086 public: 00087 // constructor: The Field layout to which we match our particle's 00088 // locations. 00089 ParticleInteractLayout(FieldLayout<Dim>&); 00090 00091 // constructor: this one also takes a Mesh 00092 ParticleInteractLayout(FieldLayout<Dim>&, Mesh&); 00093 00094 // a similar constructor, but this one takes a RegionLayout. 00095 ParticleInteractLayout(const RegionLayout<T,Dim,Mesh>&); 00096 00097 // a default constructor ... in this case, no layout will 00098 // be assumed by this class. A layout may be given later via the 00099 // 'setLayout' method, either as a FieldLayout or as a RegionLayout. 00100 ParticleInteractLayout(); 00101 00102 // destructor 00103 ~ParticleInteractLayout(); 00104 00105 // 00106 // Particle swapping/update routines 00107 // 00108 00109 // Update the location and indices of all atoms in the given ParticleBase 00110 // object. This handles swapping particles among processors if 00111 // needed, and handles create and destroy requests. When complete, 00112 // all nodes have correct layout information. 00113 void update(ParticleBase< ParticleInteractLayout<T,Dim,Mesh> >& p, 00114 const ParticleAttrib<char>* canSwap=0); 00115 00116 // 00117 // Nearest-neighbor interaction calculation routines 00118 // 00119 00120 // Retrieve a Forward-style iterator for the beginning and end of the 00121 // Nth (local) particle's nearest-neighbor pairlist. 00122 // If this is the first call of this 00123 // method after update(), this must make sure up-to-date info on particles 00124 // from neighboring nodes is available. 00125 void getPairlist(unsigned, pair_iterator&, pair_iterator&, 00126 ParticleBase< ParticleInteractLayout<T,Dim,Mesh> >&); 00127 00128 // specify the interaction radius ... two versions, one which gives a 00129 // single value for all atoms, the other giving a ParticleAttrib<T> 00130 // object with interaction radii for all the atoms in this object 00131 void setInteractionRadius(const T& r) { 00132 InterRadius = r; 00133 InterRadiusArray = 0; 00134 return; 00135 } 00136 void setInteractionRadius(ParticleInterRadius_t& rAttrib) { 00137 InterRadiusArray = &rAttrib; 00138 return; 00139 } 00140 00141 // Return the maximum interaction radius of the entire system. This is 00142 // the value from the most recent call to update() 00143 T getMaxInteractionRadius() { return MaxGlobalInterRadius; } 00144 00145 // Return the interaction radius of atom i. 00146 T getInteractionRadius(unsigned i) { 00147 return (InterRadiusArray != 0 ? (*InterRadiusArray)[i] : InterRadius); 00148 } 00149 00150 // directly set NeedGhostSwap flag to indicate whether this is needed 00151 // useful when a ParticleAttrib other than position R is modified and 00152 // we do not need to call update(). 00153 void setNeedGhostSwap(bool cond=true) { 00154 NeedGhostSwap = cond; 00155 } 00156 00157 // 00158 // virtual functions for FieldLayoutUser's (and other UserList users) 00159 // 00160 00161 // Repartition onto a new layout 00162 virtual void Repartition(UserList *); 00163 00164 private: 00165 // information needed to compute which ghost particles to send/receive 00166 bool NeedGhostSwap; 00167 bool* InterNodeList; 00168 bool* SentToNodeList; 00169 unsigned InteractionNodes; 00170 00171 // pairlist storage - a set of vectors 00172 vector< vector<pair_t>* > PairList; 00173 00174 // interaction radius data. If the attribute pointer is null, use the 00175 // scalar value instead. 00176 // also, the maximum interaction radius for the local particles, and for all 00177 // the particles 00178 T InterRadius, MaxGlobalInterRadius; 00179 ParticleInterRadius_t *InterRadiusArray; 00180 00181 // perform common constructor tasks 00182 void setup(); 00183 00184 // recalculate where we need to send ghost particles for building 00185 // nearest-neighbor interaction lists 00186 void rebuild_interaction_data(); 00187 00188 // recalculate where we need to send ghost particles for building 00189 // nearest-neighbor interaction lists 00190 // special version which accounts for periodic boundary conditions 00191 void rebuild_interaction_data(const bool periodicBC[2*Dim]); 00192 00193 // copy particles to other nodes for pairlist computation. The arguments 00194 // are the current number of local particles, and the ParticleBase object. 00195 // This will also calculate the pairlists if necessary. 00196 void swap_ghost_particles(unsigned, 00197 ParticleBase< ParticleInteractLayout<T,Dim,Mesh> >&); 00198 00199 // copy particles to other nodes for pairlist computation. The arguments 00200 // are the current number of local particles, and the ParticleBase object. 00201 // This will also calculate the pairlists if necessary. 00202 // special version to take account of periodic boundaries 00203 void swap_ghost_particles(unsigned, 00204 ParticleBase< ParticleInteractLayout<T,Dim,Mesh> >&, 00205 const bool periodicBC[2*Dim]); 00206 00207 // find the pairs between our local particles and particles a1 ... (a2 - 1). 00208 // if the last argument is true, initialize all the pairlists to be empty. 00209 void find_pairs(const unsigned LocalNum, const unsigned a1, 00210 const unsigned a2, const bool initLists, 00211 ParticleBase< ParticleInteractLayout<T,Dim,Mesh> >& PData); 00212 00213 // change the value of the maximum local interaction radius 00214 void setMaxInteractionRadius(T maxval) { MaxGlobalInterRadius = maxval; } 00215 00216 // Return the maximum interaction radius of the local particles. 00217 T getMaxLocalInteractionRadius(); 00218 }; 00219 00220 #include "Particle/ParticleInteractLayout.cpp" 00221 00222 #endif // PARTICLE_INTERACT_LAYOUT_H 00223 00224 /*************************************************************************** 00225 * $RCSfile: ParticleInteractLayout.h,v $ $Author: adelmann $ 00226 * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:29 $ 00227 * IPPL_VERSION_ID: $Id: ParticleInteractLayout.h,v 1.1.1.1 2003/01/23 07:40:29 adelmann Exp $ 00228 ***************************************************************************/