Voro++
|
00001 // Voro++, a 3D cell-based Voronoi library 00002 // 00003 // Author : Chris H. Rycroft (LBL / UC Berkeley) 00004 // Email : chr@alum.mit.edu 00005 // Date : August 30th 2011 00006 00007 /** \file c_loops.cc 00008 * \brief Function implementations for the loop classes. */ 00009 00010 #include "c_loops.hh" 00011 00012 namespace voro { 00013 00014 /** Initializes a c_loop_subset object to scan over all particles within a 00015 * given sphere. 00016 * \param[in] (vx,vy,vz) the position vector of the center of the sphere. 00017 * \param[in] r the radius of the sphere. 00018 * \param[in] bounds_test whether to do detailed bounds checking. If this is 00019 * false then the class will loop over all particles in 00020 * blocks that overlap the given sphere. If it is true, 00021 * the particle will only loop over the particles which 00022 * actually lie within the sphere. 00023 * \return True if there is any valid point to loop over, false otherwise. */ 00024 void c_loop_subset::setup_sphere(double vx,double vy,double vz,double r,bool bounds_test) { 00025 if(bounds_test) {mode=sphere;v0=vx;v1=vy;v2=vz;v3=r*r;} else mode=no_check; 00026 ai=step_int((vx-ax-r)*xsp); 00027 bi=step_int((vx-ax+r)*xsp); 00028 aj=step_int((vy-ay-r)*ysp); 00029 bj=step_int((vy-ay+r)*ysp); 00030 ak=step_int((vz-az-r)*zsp); 00031 bk=step_int((vz-az+r)*zsp); 00032 setup_common(); 00033 } 00034 00035 /** Initializes the class to loop over all particles in a rectangular subgrid 00036 * of blocks. 00037 * \param[in] (ai_,bi_) the subgrid range in the x-direction, inclusive of both 00038 * ends. 00039 * \param[in] (aj_,bj_) the subgrid range in the y-direction, inclusive of both 00040 * ends. 00041 * \param[in] (ak_,bk_) the subgrid range in the z-direction, inclusive of both 00042 * ends. 00043 * \return True if there is any valid point to loop over, false otherwise. */ 00044 void c_loop_subset::setup_intbox(int ai_,int bi_,int aj_,int bj_,int ak_,int bk_) { 00045 ai=ai_;bi=bi_;aj=aj_;bj=bj_;ak=ak_;bk=bk_; 00046 mode=no_check; 00047 setup_common(); 00048 } 00049 00050 /** Sets up all of the common constants used for the loop. 00051 * \return True if there is any valid point to loop over, false otherwise. */ 00052 void c_loop_subset::setup_common() { 00053 if(!xperiodic) { 00054 if(ai<0) {ai=0;if(bi<0) bi=0;} 00055 if(bi>=nx) {bi=nx-1;if(ai>=nx) ai=nx-1;} 00056 } 00057 if(!yperiodic) { 00058 if(aj<0) {aj=0;if(bj<0) bj=0;} 00059 if(bj>=ny) {bj=ny-1;if(aj>=ny) aj=ny-1;} 00060 } 00061 if(!zperiodic) { 00062 if(ak<0) {ak=0;if(bk<0) bk=0;} 00063 if(bk>=nz) {bk=nz-1;if(ak>=nz) ak=nz-1;} 00064 } 00065 ci=ai;cj=aj;ck=ak; 00066 di=i=step_mod(ci,nx);apx=px=step_div(ci,nx)*sx; 00067 dj=j=step_mod(cj,ny);apy=py=step_div(cj,ny)*sy; 00068 dk=k=step_mod(ck,nz);apz=pz=step_div(ck,nz)*sz; 00069 inc1=di-step_mod(bi,nx); 00070 inc2=nx*(ny+dj-step_mod(bj,ny))+inc1; 00071 inc1+=nx; 00072 ijk=di+nx*(dj+ny*dk); 00073 q=0; 00074 } 00075 00076 /** Starts the loop by finding the first particle within the container to 00077 * consider. 00078 * \return True if there is any particle to consider, false otherwise. */ 00079 bool c_loop_subset::start() { 00080 while(co[ijk]==0) {if(!next_block()) return false;} 00081 while(mode!=no_check&&out_of_bounds()) { 00082 q++; 00083 while(q>=co[ijk]) {q=0;if(!next_block()) return false;} 00084 } 00085 return true; 00086 } 00087 00088 /** Initializes the class to loop over all particles in a rectangular box. 00089 * \param[in] (xmin,xmax) the minimum and maximum x coordinates of the box. 00090 * \param[in] (ymin,ymax) the minimum and maximum y coordinates of the box. 00091 * \param[in] (zmin,zmax) the minimum and maximum z coordinates of the box. 00092 * \param[in] bounds_test whether to do detailed bounds checking. If this is 00093 * false then the class will loop over all particles in 00094 * blocks that overlap the given box. If it is true, the 00095 * particle will only loop over the particles which 00096 * actually lie within the box. 00097 * \return True if there is any valid point to loop over, false otherwise. */ 00098 void c_loop_subset::setup_box(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax,bool bounds_test) { 00099 if(bounds_test) {mode=box;v0=xmin;v1=xmax;v2=ymin;v3=ymax;v4=zmin;v5=zmax;} else mode=no_check; 00100 ai=step_int((xmin-ax)*xsp); 00101 bi=step_int((xmax-ax)*xsp); 00102 aj=step_int((ymin-ay)*ysp); 00103 bj=step_int((ymax-ay)*ysp); 00104 ak=step_int((zmin-az)*zsp); 00105 bk=step_int((zmax-az)*zsp); 00106 setup_common(); 00107 } 00108 00109 /** Computes whether the current point is out of bounds, relative to the 00110 * current loop setup. 00111 * \return True if the point is out of bounds, false otherwise. */ 00112 bool c_loop_subset::out_of_bounds() { 00113 double *pp=p[ijk]+ps*q; 00114 if(mode==sphere) { 00115 double fx(*pp+px-v0),fy(pp[1]+py-v1),fz(pp[2]+pz-v2); 00116 return fx*fx+fy*fy+fz*fz>v3; 00117 } else { 00118 double f(*pp+px);if(f<v0||f>v1) return true; 00119 f=pp[1]+py;if(f<v2||f>v3) return true; 00120 f=pp[2]+pz;return f<v4||f>v5; 00121 } 00122 } 00123 00124 /** Returns the next block to be tested in a loop, and updates the periodicity 00125 * vector if necessary. */ 00126 bool c_loop_subset::next_block() { 00127 if(i<bi) { 00128 i++; 00129 if(ci<nx-1) {ci++;ijk++;} else {ci=0;ijk+=1-nx;px+=sx;} 00130 return true; 00131 } else if(j<bj) { 00132 i=ai;ci=di;px=apx;j++; 00133 if(cj<ny-1) {cj++;ijk+=inc1;} else {cj=0;ijk+=inc1-nxy;py+=sy;} 00134 return true; 00135 } else if(k<bk) { 00136 i=ai;ci=di;j=aj;cj=dj;px=apx;py=apy;k++; 00137 if(ck<nz-1) {ck++;ijk+=inc2;} else {ck=0;ijk+=inc2-nxyz;pz+=sz;} 00138 return true; 00139 } else return false; 00140 } 00141 00142 /** Extends the memory available for storing the ordering. */ 00143 void particle_order::add_ordering_memory() { 00144 int *no=new int[size<<2],*nop=no,*opp=o; 00145 while(opp<op) *(nop++)=*(opp++); 00146 delete [] o; 00147 size<<=1;o=no;op=nop; 00148 } 00149 00150 }