HG-MD
1
|
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