HG-MD  1
HGRID_base.h
Go to the documentation of this file.
00001 #ifndef HGRID_H
00002 #define HGRID_H
00003 
00004 #include <ostream>
00005 #include <iostream>
00006 #include <stdlib.h>
00007 using std::cout;
00008 using std::cerr;
00009 
00010 #include "CParticle.h"
00011 #include "MD.h"
00012 
00013 
00014 
00018 class Cell 
00019 {
00020 public:
00021 Cell () { }
00022 Cell(int px, int py, int pz, int pl) { x = px; y = py; z = pz; l = pl; }
00023 
00024 int x, y, z, l;
00025 
00026 
00027 friend inline std::ostream& operator<<(std::ostream& os, const Cell &cell)
00028         {
00029         os << cell.x << ' ' << cell.y << ' ' << cell.z << ' ' << cell.l;
00030         return os;
00031         }
00032 };
00033 
00034 
00038 class HGrid
00039 {
00040 public:
00041         
00042         HGrid() {
00043                 objectBucket = NULL; 
00044                 bucketIsChecked = NULL;
00045                 //minCellPos = NULL; 
00046                 //maxCellPos = NULL; 
00047                 inv_size = NULL; 
00048         }
00049         
00051         /*void print(std::ostream& os) {
00052                 os << "HGRID" << endl;
00053                 for (int i=0; i<NUM_BUCKETS; i++)
00054                 {
00055                         if (objectBucket[i]!=-1) {
00056                                 os << i << " ";
00057                                 for (int p=objectBucket[i]; p!=-1; p=Particles[p]->pNextObject)
00058                                         os << p << " ";
00059                                 os << endl;
00060                         }
00061                 }
00062         }*/
00063         
00064         
00065         //----- parameters ------
00067         int NUM_BUCKETS; 
00068         
00070         int HGRID_MAX_LEVELS; 
00071         
00073         Mdouble MIN_CELL_SIZE; 
00074         
00076         Mdouble SPHERE_TO_CELL_RATIO; 
00077                 
00079         Mdouble CELL_TO_CELL_RATIO; 
00080         
00081         //----- internal variables ----------
00083         int occupiedLevelsMask; 
00084         
00086         Particle **objectBucket; 
00087         
00089         bool *bucketIsChecked; 
00090         
00092         //Cell *minCellPos; 
00093         
00095         //Cell *maxCellPos; 
00096         
00098         Mdouble *inv_size; 
00099         
00100         //-------------------------------------------------
00102         HGrid(int num_buckets, int hgrid_max_levels, Mdouble min_cell_size, Mdouble sphere_to_cell_ratio, Mdouble cell_to_cell_ratio)
00103         {
00104                 NUM_BUCKETS = num_buckets;
00105                 
00106                 objectBucket = new Particle*[NUM_BUCKETS];
00107                 bucketIsChecked = new bool[NUM_BUCKETS];
00108                 
00109                 HGRID_MAX_LEVELS = hgrid_max_levels;
00110                 
00111                 //minCellPos = new Cell[HGRID_MAX_LEVELS];
00112                 //maxCellPos = new Cell[HGRID_MAX_LEVELS];
00113                 inv_size = new Mdouble[HGRID_MAX_LEVELS];
00114                 
00115                 
00116                 MIN_CELL_SIZE = min_cell_size;
00117                 
00118                 SPHERE_TO_CELL_RATIO = sphere_to_cell_ratio;
00119                 
00120                 CELL_TO_CELL_RATIO = cell_to_cell_ratio;
00121         }
00122 
00124         ~HGrid() {
00125                 if (objectBucket) { delete [] objectBucket; objectBucket=NULL; }
00126                 if (bucketIsChecked) { delete [] bucketIsChecked; bucketIsChecked=NULL; }
00127                 //if (minCellPos) { delete [] minCellPos; minCellPos=NULL; }
00128                 //if (maxCellPos) { delete [] maxCellPos; maxCellPos=NULL; }
00129                 if (inv_size) { delete [] inv_size; inv_size=NULL; } 
00130         }
00131         
00132         //-------------------------------------------------
00133         void Initialize_inv_size()
00134         {
00135                 Mdouble size = MIN_CELL_SIZE;
00136                 
00137                 for (int level = 0; level<HGRID_MAX_LEVELS; level++)
00138                 {
00139                         // initialize inv_size
00140                         this->inv_size[level] = 1.0f/size;
00141                                                 
00142                         size *= CELL_TO_CELL_RATIO;
00143                 }
00144         }
00145         
00146         //-------------------------------------------------
00147         /*void InitializeMaxMinCellPos(Mdouble wx0, Mdouble wy0, Mdouble wz0, Mdouble wx1, Mdouble wy1, Mdouble wz1)
00148         {
00149                 Mdouble inv_size;
00150                                         
00151                 for (int level = 0; level<HGRID_MAX_LEVELS; level++)
00152                 {
00153                         inv_size = this->inv_size[level];
00154                                         
00155                         this->minCellPos[level] = Cell((int)(wx0 * inv_size), (int)(wy0 * inv_size), (int)(wz0 * inv_size), level);
00156                         this->maxCellPos[level] = Cell((int)(wx1 * inv_size), (int)(wy1 * inv_size), (int)(wz1 * inv_size), level);
00157                 }
00158         
00159         }*/
00160         
00164         void InsertParticleToHgrid(Particle *obj)
00165         {
00166                 // Find lowest level where object fully fits inside cell, taking RATIO into account
00167                 int level;
00168                 Mdouble size = MIN_CELL_SIZE;
00169                 Mdouble diameter = obj->get_Radius() * 2.0f;
00170                 
00171                 for (level = 0; size  < SPHERE_TO_CELL_RATIO*diameter; level++)
00172                 {
00173                         size *= CELL_TO_CELL_RATIO;
00174                 }
00175 
00176                 if (level >= HGRID_MAX_LEVELS) 
00177                 { 
00178                         cerr << "ATTENTION !!! Object is larger (d=" << diameter << ") than largest grid cell (" << size << ")!" << std::endl; 
00179                         cerr << "Please lower minimum cell size (" << MIN_CELL_SIZE << ") for HGRID and rerun" << std::endl;
00180                         //cerr << "HGRID_MAX_LEVELS" << HGRID_MAX_LEVELS << "CELL_TO_CELL_RATIO" << CELL_TO_CELL_RATIO << endl;
00181                         exit(-1);
00182                 }
00183                         
00184                 obj->set_HGRID_Level(level);
00185                         
00186                 // indicate level is in use - not levels with no particles no collision detection is performed
00187                 this->occupiedLevelsMask |= (1 << level);
00188         }
00189         
00190                                                 //-------------------------------------------------
00191                 
00193         int ComputeHashBucketIndex(Cell cellPos)
00194         {
00195                 const int h1 = 0x8da6b343; // Large multiplicative constants;
00196                 const int h2 = 0xd8163841; // here arbitrarily chosen primes
00197                 const int h3 = 0xcb1ab31f;
00198                 const int h4 = 0x165667b1;
00199                         
00200                 int n = h1 * cellPos.x + h2 * cellPos.y + h3 * cellPos.z + h4 * cellPos.l;
00201                 n = n % NUM_BUCKETS;
00202                         
00203                 if (n < 0) n += NUM_BUCKETS;
00204                                                                                                                         
00205                 return n;
00206         }
00207 
00209         void reset_num_buckets(int new_num_buckets){
00210                 NUM_BUCKETS=new_num_buckets;
00211                 objectBucket = (Particle**)realloc(objectBucket, NUM_BUCKETS*sizeof(Particle*));
00212                 bucketIsChecked = (bool*)realloc(bucketIsChecked, NUM_BUCKETS*sizeof(bool));
00213         }
00214 };
00215 //(-)********** class HGrid *****************************************
00216         
00217         
00222 class HGRID_base : public virtual MD
00223 {
00224 
00225 public:
00226         
00228         HGRID_base()
00229         {
00230                 constructor();
00231                 #ifdef CONSTUCTOR_OUTPUT
00232                         cerr << "HGRID_base() finished"<<endl;
00233                 #endif
00234         }
00235 
00236         ~HGRID_base() { 
00237                 if (grid) { delete grid; grid=NULL; } 
00238         }
00239         
00241         HGRID_base(MD& other) : MD(other)
00242         {
00243                 constructor();
00244                 #ifdef CONSTUCTOR_OUTPUT
00245                         cerr << "HGRID_base(MD& other) finished " << endl;
00246                 #endif
00247         }
00248         
00250         void constructor();
00251         
00253         void HGRID_actions_before_time_loop(){InitBroadPhase();}
00254         
00256         void HGRID_actions_before_time_step();
00257         
00259         void set_HGRID_num_buckets(unsigned int new_num_buckets){if (new_num_buckets>0) NUM_BUCKETS=new_num_buckets; else {cerr << "Error in set_HGRID_num_buckets" << endl; exit(-1);}}
00260         
00262         void set_HGRID_num_buckets_to_power(){ set_HGRID_num_buckets_to_power(get_ParticleHandler().get_NumberOfParticles());   }
00263         
00265         void set_HGRID_num_buckets_to_power(unsigned int N){
00266                 unsigned int NUM_BUCKETS = 32;
00267                 while (NUM_BUCKETS<2*N) NUM_BUCKETS *= 2;
00268                 set_HGRID_num_buckets(NUM_BUCKETS);
00269         }
00270 
00272         void set_HGRID_max_levels(int new_max_levels){if (new_max_levels>0){HGRID_MAX_LEVELS=new_max_levels;}}
00273         
00275         void set_HGRID_sphere_to_cell_ratio(Mdouble new_ratio){if (new_ratio>0){SPHERE_TO_CELL_RATIO=new_ratio;}}
00276         
00278         void set_HGRID_cell_to_cell_ratio(Mdouble new_ratio){if (new_ratio>0){CELL_TO_CELL_RATIO=new_ratio;}}
00279         
00281         void read(std::istream& is)
00282         { 
00283                 MD::read(is); 
00284 
00285 
00286                 //read out the full line first, so if there is an error it does not affect the read of the next line
00287                 string line_string;
00288                 getline(is,line_string);
00289                 stringstream line (stringstream::in | stringstream::out);
00290                 line << line_string;
00291 
00292                 if (get_restart_version()==1) {
00293                 line >> NUM_BUCKETS >> HGRID_MAX_LEVELS >> MIN_CELL_SIZE >> SPHERE_TO_CELL_RATIO >> CELL_TO_CELL_RATIO;
00294                 } else {
00295       string dummy;
00296         line>> dummy >> NUM_BUCKETS 
00297         >> dummy >> HGRID_MAX_LEVELS 
00298         >> dummy >> MIN_CELL_SIZE 
00299         >> dummy >> SPHERE_TO_CELL_RATIO 
00300         >> dummy >> CELL_TO_CELL_RATIO;
00301     }
00302         }
00303         
00305         void write(std::ostream& os)
00306         { 
00307                 MD::write(os); 
00308                 os      << "NUM_BUCKETS " << NUM_BUCKETS << " "
00309                         << "HGRID_MAX_LEVELS " << HGRID_MAX_LEVELS << " "
00310                         << "MIN_CELL_SIZE " << MIN_CELL_SIZE << " "
00311                         << "SPHERE_TO_CELL_RATIO " << SPHERE_TO_CELL_RATIO  << " "
00312                         << "CELL_TO_CELL_RATIO " << CELL_TO_CELL_RATIO << endl;
00313         }
00314         
00316   void print(std::ostream& os, bool print_all=false)
00317   {
00318                 MD::print(os,print_all);
00319                 os << " NUM_BUCKETS:" << NUM_BUCKETS << ", HGRID_MAX_LEVELS:" << HGRID_MAX_LEVELS << ", MIN_CELL_SIZE:" << MIN_CELL_SIZE << ", " << endl
00320                    << " SPHERE_TO_CELL_RATIO:" << SPHERE_TO_CELL_RATIO << ", CELL_TO_CELL_RATIO:" << CELL_TO_CELL_RATIO << endl;
00321   }
00322   
00323         Mdouble get_CurrentMaxRelativeDisplacement(){return currentMaxRelativeDisplacement;}
00324         Mdouble get_TotalCurrentMaxRelativeDisplacement(){return totalCurrentMaxRelativeDisplacement;}
00325         
00326         void set_UpdateEachTimeStep(bool _new){updateEachTimeStep=_new;}
00327         bool get_HGRID_UpdateEachTimeStep(){return updateEachTimeStep;}   
00328 
00329         protected:
00330         
00332         void InitBroadPhase();
00333         
00335         void HGRID_InsertParticleToHgrid(Particle *obj);
00336                         
00338         void broad_phase(Particle *i){CheckObjAgainstGrid(grid, i);}
00339         
00341         virtual void CheckObjAgainstGrid(HGrid *grid, Particle *obj)=0;
00342         
00344         virtual bool TestObject(Particle *pI, Particle *pJ) {
00345                 //PI==PJ check is required because this function is called for all possible close Particle combination (even itself)
00346                 return pI->get_Index()==pJ->get_Index() || GetDistance2(pI->get_Position(),pJ->get_Position())>=sqr(pI->get_Radius()+pJ->get_Radius());
00347         }
00348 
00349 
00350         void HGRID_update_move(Particle * iP, Mdouble move)
00351         {
00352                 Mdouble currentRelativeDisplacement=move/(grid->MIN_CELL_SIZE*pow(grid->CELL_TO_CELL_RATIO,iP->get_HGRID_Level()));
00353                 if(currentRelativeDisplacement>currentMaxRelativeDisplacement) currentMaxRelativeDisplacement=currentRelativeDisplacement;
00354         };
00355         
00356         void HGRID_actions_before_integration(){currentMaxRelativeDisplacement=0;}
00357         void HGRID_actions_after_integration(){totalCurrentMaxRelativeDisplacement+=2.0*currentMaxRelativeDisplacement;}
00358         
00359         private:
00360         
00362         void set_HGRID_min_cell_size(Mdouble new_min_cell_size){if (new_min_cell_size>0){MIN_CELL_SIZE=new_min_cell_size;}}
00363         void set_CELL_TO_CELL_RATIO(Mdouble new_CELL_TO_CELL_RATIO){if (new_CELL_TO_CELL_RATIO>0){CELL_TO_CELL_RATIO=new_CELL_TO_CELL_RATIO;}}
00364         
00365         Mdouble currentMaxRelativeDisplacement, totalCurrentMaxRelativeDisplacement;
00366         bool updateEachTimeStep;
00367         int NUM_BUCKETS;
00368         int HGRID_MAX_LEVELS;
00369         Mdouble MIN_CELL_SIZE;
00370         Mdouble SPHERE_TO_CELL_RATIO;
00371         Mdouble CELL_TO_CELL_RATIO;
00372         
00373         
00374         
00375         protected:
00376         
00377         
00378         
00379         HGrid* grid;
00380         
00381         void fix_hgrid (){
00382                 set_HGRID_min_cell_size(2.00001*get_SmallestParticle()->get_Radius());
00383                 set_HGRID_max_levels(2);
00384                 set_CELL_TO_CELL_RATIO(get_LargestParticle()->get_Radius()/get_SmallestParticle()->get_Radius());
00385                 set_HGRID_num_buckets_to_power(get_ParticleHandler().get_NumberOfParticles());
00386         }
00387 };
00388 
00389 
00390 
00391 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines