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 v_base.cc 00008 * \brief Function implementations for the base Voronoi container class. */ 00009 00010 #include "v_base.hh" 00011 #include "config.hh" 00012 00013 namespace voro { 00014 00015 /** This function is called during container construction. The routine scans 00016 * all of the worklists in the wl[] array. For a given worklist of blocks 00017 * labeled \f$w_1\f$ to \f$w_n\f$, it computes a sequence \f$r_0\f$ to 00018 * \f$r_n\f$ so that $r_i$ is the minimum distance to all the blocks 00019 * \f$w_{j}\f$ where \f$j>i\f$ and all blocks outside the worklist. The values 00020 * of \f$r_n\f$ is calculated first, as the minimum distance to any block in 00021 * the shell surrounding the worklist. The \f$r_i\f$ are then computed in 00022 * reverse order by considering the distance to \f$w_{i+1}\f$. */ 00023 voro_base::voro_base(int nx_,int ny_,int nz_,double boxx_,double boxy_,double boxz_) : 00024 nx(nx_), ny(ny_), nz(nz_), nxy(nx_*ny_), nxyz(nxy*nz_), boxx(boxx_), boxy(boxy_), boxz(boxz_), 00025 xsp(1/boxx_), ysp(1/boxy_), zsp(1/boxz_), mrad(new double[wl_hgridcu*wl_seq_length]) { 00026 const unsigned int b1=1<<21,b2=1<<22,b3=1<<24,b4=1<<25,b5=1<<27,b6=1<<28; 00027 const double xstep=boxx/wl_fgrid,ystep=boxy/wl_fgrid,zstep=boxz/wl_fgrid; 00028 int i,j,k,lx,ly,lz,q; 00029 unsigned int f,*e=const_cast<unsigned int*> (wl); 00030 double xlo,ylo,zlo,xhi,yhi,zhi,minr,*radp=mrad; 00031 for(zlo=0,zhi=zstep,lz=0;lz<wl_hgrid;zlo=zhi,zhi+=zstep,lz++) { 00032 for(ylo=0,yhi=ystep,ly=0;ly<wl_hgrid;ylo=yhi,yhi+=ystep,ly++) { 00033 for(xlo=0,xhi=xstep,lx=0;lx<wl_hgrid;xlo=xhi,xhi+=xstep,lx++) { 00034 minr=large_number; 00035 for(q=e[0]+1;q<wl_seq_length;q++) { 00036 f=e[q]; 00037 i=(f&127)-64; 00038 j=(f>>7&127)-64; 00039 k=(f>>14&127)-64; 00040 if((f&b2)==b2) { 00041 compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i-1,j,k); 00042 if((f&b1)==0) compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i+1,j,k); 00043 } else if((f&b1)==b1) compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i+1,j,k); 00044 if((f&b4)==b4) { 00045 compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j-1,k); 00046 if((f&b3)==0) compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j+1,k); 00047 } else if((f&b3)==b3) compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j+1,k); 00048 if((f&b6)==b6) { 00049 compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j,k-1); 00050 if((f&b5)==0) compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j,k+1); 00051 } else if((f&b5)==b5) compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j,k+1); 00052 } 00053 q--; 00054 while(q>0) { 00055 radp[q]=minr; 00056 f=e[q]; 00057 i=(f&127)-64; 00058 j=(f>>7&127)-64; 00059 k=(f>>14&127)-64; 00060 compute_minimum(minr,xlo,xhi,ylo,yhi,zlo,zhi,i,j,k); 00061 q--; 00062 } 00063 *radp=minr; 00064 e+=wl_seq_length; 00065 radp+=wl_seq_length; 00066 } 00067 } 00068 } 00069 } 00070 00071 /** Computes the minimum distance from a subregion to a given block. If this distance 00072 * is smaller than the value of minr, then it passes 00073 * \param[in,out] minr a pointer to the current minimum distance. If the distance 00074 * computed in this function is smaller, then this distance is 00075 * set to the new one. 00076 * \param[out] (xlo,ylo,zlo) the lower coordinates of the subregion being 00077 * considered. 00078 * \param[out] (xhi,yhi,zhi) the upper coordinates of the subregion being 00079 * considered. 00080 * \param[in] (ti,tj,tk) the coordinates of the block. */ 00081 void voro_base::compute_minimum(double &minr,double &xlo,double &xhi,double &ylo,double &yhi,double &zlo,double &zhi,int ti,int tj,int tk) { 00082 double radsq,temp; 00083 if(ti>0) {temp=boxx*ti-xhi;radsq=temp*temp;} 00084 else if(ti<0) {temp=xlo-boxx*(1+ti);radsq=temp*temp;} 00085 else radsq=0; 00086 00087 if(tj>0) {temp=boxy*tj-yhi;radsq+=temp*temp;} 00088 else if(tj<0) {temp=ylo-boxy*(1+tj);radsq+=temp*temp;} 00089 00090 if(tk>0) {temp=boxz*tk-zhi;radsq+=temp*temp;} 00091 else if(tk<0) {temp=zlo-boxz*(1+tk);radsq+=temp*temp;} 00092 00093 if(radsq<minr) minr=radsq; 00094 } 00095 00096 /** Checks to see whether "%n" appears in a format sequence to determine 00097 * whether neighbor information is required or not. 00098 * \param[in] format the format string to check. 00099 * \return True if a "%n" is found, false otherwise. */ 00100 bool voro_base::contains_neighbor(const char *format) { 00101 char *fmp=(const_cast<char*>(format)); 00102 00103 // Check to see if "%n" appears in the format sequence 00104 while(*fmp!=0) { 00105 if(*fmp=='%') { 00106 fmp++; 00107 if(*fmp=='n') return true; 00108 else if(*fmp==0) return false; 00109 } 00110 fmp++; 00111 } 00112 00113 return false; 00114 } 00115 00116 #include "v_base_wl.cc" 00117 00118 }