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 pre_container.cc 00008 * \brief Function implementations for the pre_container and related classes. 00009 */ 00010 00011 #include <cstdio> 00012 #include <cmath> 00013 using namespace std; 00014 00015 #include "config.hh" 00016 #include "pre_container.hh" 00017 00018 namespace voro { 00019 00020 /** The class constructor sets up the geometry of container, initializing the 00021 * minimum and maximum coordinates in each direction. It allocates an initial 00022 * chunk into which to store particle information. 00023 * \param[in] (ax_,bx_) the minimum and maximum x coordinates. 00024 * \param[in] (ay_,by_) the minimum and maximum y coordinates. 00025 * \param[in] (az_,bz_) the minimum and maximum z coordinates. 00026 * \param[in] (xperiodic_,yperiodic_,zperiodic_ ) flags setting whether the 00027 * container is periodic in each 00028 * coordinate direction. 00029 * \param[in] ps_ the number of floating point entries to store for each 00030 * particle. */ 00031 pre_container_base::pre_container_base(double ax_,double bx_,double ay_,double by_,double az_,double bz_, 00032 bool xperiodic_,bool yperiodic_,bool zperiodic_,int ps_) : 00033 ax(ax_), bx(bx_), ay(ay_), by(by_), az(az_), bz(bz_), 00034 xperiodic(xperiodic_), yperiodic(yperiodic_), zperiodic(zperiodic_), ps(ps_), 00035 index_sz(init_chunk_size), pre_id(new int*[index_sz]), end_id(pre_id), 00036 pre_p(new double*[index_sz]), end_p(pre_p) { 00037 ch_id=*end_id=new int[pre_container_chunk_size]; 00038 l_id=end_id+index_sz;e_id=ch_id+pre_container_chunk_size; 00039 ch_p=*end_p=new double[ps*pre_container_chunk_size]; 00040 } 00041 00042 /** The destructor frees the dynamically allocated memory. */ 00043 pre_container_base::~pre_container_base() { 00044 delete [] *end_p; 00045 delete [] *end_id; 00046 while (end_id!=pre_id) { 00047 end_p--; 00048 delete [] *end_p; 00049 end_id--; 00050 delete [] *end_id; 00051 } 00052 delete [] pre_p; 00053 delete [] pre_id; 00054 } 00055 00056 /** Makes a guess at the optimal grid of blocks to use, computing in 00057 * a way that 00058 * \param[out] (nx,ny,nz) the number of blocks to use. */ 00059 void pre_container_base::guess_optimal(int &nx,int &ny,int &nz) { 00060 double dx(bx-ax),dy(by-ay),dz(bz-az); 00061 double ilscale(pow(total_particles()/(optimal_particles*dx*dy*dz),1/3.0)); 00062 nx=int(dx*ilscale+1); 00063 ny=int(dx*ilscale+1); 00064 nz=int(dx*ilscale+1); 00065 } 00066 00067 /** Stores a particle ID and position, allocating a new memory chunk if 00068 * necessary. For coordinate directions in which the container is not periodic, 00069 * the routine checks to make sure that the particle is within the container 00070 * bounds. If the particle is out of bounds, it is not stored. 00071 * \param[in] n the numerical ID of the inserted particle. 00072 * \param[in] (x,y,z) the position vector of the inserted particle. */ 00073 void pre_container::put(int n,double x,double y,double z) { 00074 if((xperiodic||(x>=ax&&x<=bx))&&(yperiodic||(y>=ay&&y<=by))&&(zperiodic||(z>=az&&z<=bz))) { 00075 if(ch_id==e_id) new_chunk(); 00076 *(ch_id++)=n; 00077 *(ch_p++)=x;*(ch_p++)=y;*(ch_p++)=z; 00078 } 00079 #if VOROPP_REPORT_OUT_OF_BOUNDS ==1 00080 else fprintf(stderr,"Out of bounds: (x,y,z)=(%g,%g,%g)\n",x,y,z); 00081 #endif 00082 } 00083 00084 /** Stores a particle ID and position, allocating a new memory chunk if necessary. 00085 * \param[in] n the numerical ID of the inserted particle. 00086 * \param[in] (x,y,z) the position vector of the inserted particle. 00087 * \param[in] r the radius of the particle. */ 00088 void pre_container_poly::put(int n,double x,double y,double z,double r) { 00089 if((xperiodic||(x>=ax&&x<=bx))&&(yperiodic||(y>=ay&&y<=by))&&(zperiodic||(z>=az&&z<=bz))) { 00090 if(ch_id==e_id) new_chunk(); 00091 *(ch_id++)=n; 00092 *(ch_p++)=x;*(ch_p++)=y;*(ch_p++)=z;*(ch_p++)=r; 00093 } 00094 #if VOROPP_REPORT_OUT_OF_BOUNDS ==1 00095 else fprintf(stderr,"Out of bounds: (x,y,z)=(%g,%g,%g)\n",x,y,z); 00096 #endif 00097 } 00098 00099 /** Transfers the particles stored within the class to a container class. 00100 * \param[in] con the container class to transfer to. */ 00101 void pre_container::setup(container &con) { 00102 int **c_id=pre_id,*idp,*ide,n; 00103 double **c_p=pre_p,*pp,x,y,z; 00104 while(c_id<end_id) { 00105 idp=*(c_id++);ide=idp+pre_container_chunk_size; 00106 pp=*(c_p++); 00107 while(idp<ide) { 00108 n=*(idp++);x=*(pp++);y=*(pp++);z=*(pp++); 00109 con.put(n,x,y,z); 00110 } 00111 } 00112 idp=*c_id; 00113 pp=*c_p; 00114 while(idp<ch_id) { 00115 n=*(idp++);x=*(pp++);y=*(pp++);z=*(pp++); 00116 con.put(n,x,y,z); 00117 } 00118 } 00119 00120 /** Transfers the particles stored within the class to a container_poly class. 00121 * \param[in] con the container_poly class to transfer to. */ 00122 void pre_container_poly::setup(container_poly &con) { 00123 int **c_id=pre_id,*idp,*ide,n; 00124 double **c_p=pre_p,*pp,x,y,z,r; 00125 while(c_id<end_id) { 00126 idp=*(c_id++);ide=idp+pre_container_chunk_size; 00127 pp=*(c_p++); 00128 while(idp<ide) { 00129 n=*(idp++);x=*(pp++);y=*(pp++);z=*(pp++);r=*(pp++); 00130 con.put(n,x,y,z,r); 00131 } 00132 } 00133 idp=*c_id; 00134 pp=*c_p; 00135 while(idp<ch_id) { 00136 n=*(idp++);x=*(pp++);y=*(pp++);z=*(pp++);r=*(pp++); 00137 con.put(n,x,y,z,r); 00138 } 00139 } 00140 00141 /** Transfers the particles stored within the class to a container class, also 00142 * recording the order in which particles were stored. 00143 * \param[in] vo the ordering class to use. 00144 * \param[in] con the container class to transfer to. */ 00145 void pre_container::setup(particle_order &vo,container &con) { 00146 int **c_id=pre_id,*idp,*ide,n; 00147 double **c_p=pre_p,*pp,x,y,z; 00148 while(c_id<end_id) { 00149 idp=*(c_id++);ide=idp+pre_container_chunk_size; 00150 pp=*(c_p++); 00151 while(idp<ide) { 00152 n=*(idp++);x=*(pp++);y=*(pp++);z=*(pp++); 00153 con.put(vo,n,x,y,z); 00154 } 00155 } 00156 idp=*c_id; 00157 pp=*c_p; 00158 while(idp<ch_id) { 00159 n=*(idp++);x=*(pp++);y=*(pp++);z=*(pp++); 00160 con.put(vo,n,x,y,z); 00161 } 00162 } 00163 00164 /** Transfers the particles stored within the class to a container_poly class, 00165 * also recording the order in which particles were stored. 00166 * \param[in] vo the ordering class to use. 00167 * \param[in] con the container_poly class to transfer to. */ 00168 void pre_container_poly::setup(particle_order &vo,container_poly &con) { 00169 int **c_id=pre_id,*idp,*ide,n; 00170 double **c_p=pre_p,*pp,x,y,z,r; 00171 while(c_id<end_id) { 00172 idp=*(c_id++);ide=idp+pre_container_chunk_size; 00173 pp=*(c_p++); 00174 while(idp<ide) { 00175 n=*(idp++);x=*(pp++);y=*(pp++);z=*(pp++);r=*(pp++); 00176 con.put(vo,n,x,y,z,r); 00177 } 00178 } 00179 idp=*c_id; 00180 pp=*c_p; 00181 while(idp<ch_id) { 00182 n=*(idp++);x=*(pp++);y=*(pp++);z=*(pp++);r=*(pp++); 00183 con.put(vo,n,x,y,z,r); 00184 } 00185 } 00186 00187 /** Import a list of particles from an open file stream into the container. 00188 * Entries of four numbers (Particle ID, x position, y position, z position) 00189 * are searched for. If the file cannot be successfully read, then the routine 00190 * causes a fatal error. 00191 * \param[in] fp the file handle to read from. */ 00192 void pre_container::import(FILE *fp) { 00193 int i,j; 00194 double x,y,z; 00195 while((j=fscanf(fp,"%d %lg %lg %lg",&i,&x,&y,&z))==4) put(i,x,y,z); 00196 if(j!=EOF) voro_fatal_error("File import error",VOROPP_FILE_ERROR); 00197 } 00198 00199 /** Import a list of particles from an open file stream, also storing the order 00200 * of that the particles are read. Entries of four numbers (Particle ID, x 00201 * position, y position, z position) are searched for. If the file cannot be 00202 * successfully read, then the routine causes a fatal error. 00203 * \param[in] fp the file handle to read from. */ 00204 void pre_container_poly::import(FILE *fp) { 00205 int i,j; 00206 double x,y,z,r; 00207 while((j=fscanf(fp,"%d %lg %lg %lg %lg",&i,&x,&y,&z,&r))==5) put(i,x,y,z,r); 00208 if(j!=EOF) voro_fatal_error("File import error",VOROPP_FILE_ERROR); 00209 } 00210 00211 /** Allocates a new chunk of memory for storing particles. */ 00212 void pre_container_base::new_chunk() { 00213 end_id++;end_p++; 00214 if(end_id==l_id) extend_chunk_index(); 00215 ch_id=*end_id=new int[pre_container_chunk_size]; 00216 e_id=ch_id+pre_container_chunk_size; 00217 ch_p=*end_p=new double[ps*pre_container_chunk_size]; 00218 } 00219 00220 /** Extends the index of chunks. */ 00221 void pre_container_base::extend_chunk_index() { 00222 index_sz<<=1; 00223 if(index_sz>max_chunk_size) 00224 voro_fatal_error("Absolute memory limit on chunk index reached",VOROPP_MEMORY_ERROR); 00225 #if VOROPP_VERBOSE >=2 00226 fprintf(stderr,"Pre-container chunk index scaled up to %d\n",index_sz); 00227 #endif 00228 int **n_id=new int*[index_sz],**p_id=n_id,**c_id=pre_id; 00229 double **n_p=new double*[index_sz],**p_p=n_p,**c_p=pre_p; 00230 while(c_id<end_id) { 00231 *(p_id++)=*(c_id++); 00232 *(p_p++)=*(c_p++); 00233 } 00234 delete [] pre_id;pre_id=n_id;end_id=p_id;l_id=pre_id+index_sz; 00235 delete [] pre_p;pre_p=n_p;end_p=p_p; 00236 } 00237 00238 }