ESyS-Particle  4.0.1
pi_storage_e.hpp
00001 
00002 //                                                         //
00003 // Copyright (c) 2003-2011 by The University of Queensland //
00004 // Earth Systems Science Computational Centre (ESSCC)      //
00005 // http://www.uq.edu.au/esscc                              //
00006 //                                                         //
00007 // Primary Business: Brisbane, Queensland, Australia       //
00008 // Licensed under the Open Software License version 3.0    //
00009 // http://www.opensource.org/licenses/osl-3.0.php          //
00010 //                                                         //
00012 
00013 template<typename P,typename InteractionType>
00014 const int ParallelInteractionStorage_E<P,InteractionType>::m_exchg_tag=43;
00015 
00022 template<typename P,typename I>
00023 ParallelInteractionStorage_E<P,I>::ParallelInteractionStorage_E(
00024   AParallelParticleArray* PPA,
00025   const typename I::ParameterType& param
00026 )
00027   : TParallelInteractionStorage<I>(PPA),
00028     m_comm(PPA->getComm()),
00029     m_param(param)
00030 {
00031   m_unbreakable=false;
00032 }
00033 
00037 template<typename P,typename InteractionType>
00038 void ParallelInteractionStorage_E<P,InteractionType>::exchange()
00039 {
00040   for(int i=0;i<3;i++){
00041     if(m_comm.get_dim(i)>1){
00042       // -- up --
00043       exchange_boundary(i,1);
00044       // -- down --
00045       exchange_boundary(i,-1);
00046     }
00047   } 
00048 }
00049 
00056 template<typename P,typename InteractionType>
00057 void ParallelInteractionStorage_E<P,InteractionType>::exchange_boundary(int dim,int dir)
00058 { 
00059   console.XDebug() << "PIS_E::exchange_boundary(" << dim << "," << dir << ") at node " << m_comm.rank() << "\n";
00060   set<int> bdry_ids;
00061   vector<InteractionType> recv_buffer;
00062   vector<InteractionType> send_buffer;
00063 
00064   // get boundary
00065   bdry_ids = this->m_ppa->getBoundarySlabIds(dim,dir);
00066   // for all interactions
00067   for(
00068       typename list<InteractionType>::iterator iter = this->m_interactions.begin();
00069       iter != this->m_interactions.end();
00070       iter++
00071   ){
00072     vector<int> pids=iter->getAllID(); // get particle IDs
00073     bool flag=false;
00074     // check if any id is in boundary slab
00075     vector<int>::iterator it2=pids.begin();
00076     while(it2!=pids.end() && !flag){
00077       flag=(bdry_ids.find(*it2)!=bdry_ids.end());
00078       it2++;
00079     }
00080     if(flag){
00081       send_buffer.push_back(*iter);
00082     }
00083   }
00084   // shift 
00085   m_comm.shift_cont_packed(send_buffer,recv_buffer,dim,dir,m_exchg_tag);
00086   // try to insert the received interactions
00087   for(typename vector<InteractionType>::iterator iter=recv_buffer.begin();
00088       iter!=recv_buffer.end();
00089       iter++){
00090     tryInsert(*iter);
00091   }
00092   // clean buffers
00093   send_buffer.clear();
00094   recv_buffer.clear();
00095   console.XDebug() << "end PIS_E::exchange_boundary(" << dim << "," << dir << ") at node " << m_comm.rank() << "\n";
00096 }
00097 
00102 template<typename P,typename InteractionType>
00103 void ParallelInteractionStorage_E<P,InteractionType>::rebuild()
00104 {
00105   console.XDebug() << "PIS_E::rebuild at node " << m_comm.rank() << "\n";
00106   console.XDebug() << "size pre rebuild: " << this->m_interactions.size() << "\n";
00107 
00108   // -- DEBUG ---
00109   for(typename list<InteractionType>::iterator iter = this->m_interactions.begin();
00110       iter!=this->m_interactions.end();
00111       iter++){
00112     vector<int> pids=iter->getAllID();
00113     console.XDebug() << pids[0] << " - " << pids[1] << "\n";
00114   }
00115   // --- END DEBUG ---
00116   vector<P*> pptr;
00117   ParallelParticleArray<P>* t_ppa=(ParallelParticleArray<P>*)(this->m_ppa);
00118   typename list<InteractionType>::iterator iter = this->m_interactions.begin();
00119   while(iter != this->m_interactions.end()){
00120     vector<int> pids=iter->getAllID();
00121     vector<int>::const_iterator it2=pids.begin();
00122     bool flag=true;
00123     // check if the particles with the stored IDs are here
00124     while(it2!=pids.end() && flag){ 
00125       P* ptr=t_ppa->getParticlePtrByIndex(*it2);
00126       if(ptr!=NULL){
00127         pptr.push_back(ptr);
00128       } else {
00129         flag=false;
00130       }
00131       it2++;
00132     }
00133     if(flag){ // if all particle IDs are valid -> set particle pointers 
00134       iter->setPP(pptr);
00135       iter->checkIDs();
00136       iter++;
00137     } else { // if not -> erase interactions
00138       const typename list<InteractionType>::iterator er_iter=iter;
00139       iter++;
00140       this->m_interactions.erase(er_iter);
00141       m_set.erase(make_pair(pids[0],pids[1]));
00142     }
00143     pptr.clear();
00144   }
00145   console.XDebug() << "size post rebuild: " << this->m_interactions.size() << "\n";
00146   //  cout << "end PIS_E::rebuild at node " << m_comm.rank() << endl;
00147 }
00148 
00149 
00156 template<typename P,typename InteractionType>
00157 void ParallelInteractionStorage_E<P,InteractionType>::tryInsert(const InteractionType& In)
00158 {
00159   bool flag=true;
00160   
00161   ParallelParticleArray<P>* t_ppa=(ParallelParticleArray<P>*)(this->m_ppa);
00162   // check if interaction is already in 
00163   vector<int> pids=In.getAllID();
00164   flag=!isIn(pids);
00165   // try to get particle pointers from ppa 
00166   vector<int>::const_iterator iter=pids.begin();
00167   while(iter!=pids.end() && flag){
00168      P* ptr=t_ppa->getParticlePtrByIndex(*iter);
00169      if(ptr!=NULL){
00170        //pptr.push_back(ptr);
00171     } else {
00172       flag=false;
00173     }
00174     iter++;
00175   }
00176  
00177   if(flag){
00178     this->m_interactions.push_back(In);
00179     m_set.insert(make_pair(pids[0],pids[1]));
00180   } 
00181 }
00182 
00186 template<typename P,typename InteractionType>
00187 bool ParallelInteractionStorage_E<P,InteractionType>::isIn(const vector<int>& pids)
00188 {
00189   bool res;
00190 
00191   if(pids[0] > pids [1]){
00192     console.Debug()<< "flipped PIDS : " << pids[0] << "," << pids[1] << "\n";
00193   }
00194   res=m_set.find(make_pair(pids[0],pids[1]))!=m_set.end();
00195 
00196   return res;
00197 }
00198 
00199 
00207 template<typename P,typename InteractionType>
00208 void ParallelInteractionStorage_E<P,InteractionType>::tryInsert(const vector<int>& pids)
00209 {
00210   vector<P*> pptr;
00211   bool flag=true;
00212   
00213   ParallelParticleArray<P>* t_ppa=(ParallelParticleArray<P>*)(this->m_ppa);
00214   // check if interaction is already in 
00215   flag=!isIn(pids);
00216   // try to get particle pointers from ppa 
00217   vector<int>::const_iterator iter=pids.begin();
00218   while(iter!=pids.end() && flag){
00219      P* ptr=t_ppa->getParticlePtrByIndex(*iter);
00220      if(ptr!=NULL){
00221       pptr.push_back(ptr);
00222     } else {
00223       flag=false;
00224     }
00225     iter++;
00226   }
00227  
00228   if(flag){
00229     // initialize interaction from particle pointers and interaction parameters
00230     InteractionType new_interaction(pptr[0],pptr[1],m_param);
00231     vector<int> allid=new_interaction.getAllID();
00232     console.XDebug() << allid[0] << " , " << allid[1] << "\n"; 
00233     // insert interaction
00234     this->m_interactions.push_back(new_interaction);
00235     this->m_set.insert(make_pair(pids[0],pids[1]));
00236   } 
00237 }
00238 
00242 template<typename P,typename InteractionType>
00243 void ParallelInteractionStorage_E<P,InteractionType>::calcForces()
00244 {
00245   console.Debug()
00246     << "calculating "
00247     << this->m_interactions.size()
00248     << " interaction forces\n" ;
00249   
00250   for(
00251     typename list<InteractionType>::iterator it = this->m_interactions.begin();
00252     it != this->m_interactions.end();
00253     it++
00254   ){
00255     it->calcForces();
00256   }
00257 }
00258 
00264 template<typename P,typename InteractionType>
00265 void ParallelInteractionStorage_E<P,InteractionType>::setUnbreakable(bool b)
00266 {
00267   m_unbreakable=b;
00268 }