1 // Voro++, a 3D cell-based Voronoi library
3 // Author : Chris H. Rycroft (LBL / UC Berkeley)
4 // Email : chr@alum.mit.edu
5 // Date : August 30th 2011
7 /** \file pre_container.cc
8 * \brief Function implementations for the pre_container and related classes.
14 #include "pre_container.hh"
18 /** The class constructor sets up the geometry of container, initializing the
19 * minimum and maximum coordinates in each direction. It allocates an initial
20 * chunk into which to store particle information.
21 * \param[in] (ax_,bx_) the minimum and maximum x coordinates.
22 * \param[in] (ay_,by_) the minimum and maximum y coordinates.
23 * \param[in] (az_,bz_) the minimum and maximum z coordinates.
24 * \param[in] (xperiodic_,yperiodic_,zperiodic_ ) flags setting whether the
25 * container is periodic in each
26 * coordinate direction.
27 * \param[in] ps_ the number of floating point entries to store for each
29 pre_container_base::pre_container_base(double ax_
,double bx_
,double ay_
,double by_
,double az_
,double bz_
,
30 bool xperiodic_
,bool yperiodic_
,bool zperiodic_
,int ps_
) :
31 ax(ax_
), bx(bx_
), ay(ay_
), by(by_
), az(az_
), bz(bz_
),
32 xperiodic(xperiodic_
), yperiodic(yperiodic_
), zperiodic(zperiodic_
), ps(ps_
),
33 index_sz(init_chunk_size
), pre_id(new int*[index_sz
]), end_id(pre_id
),
34 pre_p(new double*[index_sz
]), end_p(pre_p
) {
35 ch_id
=*end_id
=new int[pre_container_chunk_size
];
36 l_id
=end_id
+index_sz
;e_id
=ch_id
+pre_container_chunk_size
;
37 ch_p
=*end_p
=new double[ps
*pre_container_chunk_size
];
40 /** The destructor frees the dynamically allocated memory. */
41 pre_container_base::~pre_container_base() {
44 while (end_id
!=pre_id
) {
54 /** Makes a guess at the optimal grid of blocks to use, computing in
56 * \param[out] (nx,ny,nz) the number of blocks to use. */
57 void pre_container_base::guess_optimal(int &nx
,int &ny
,int &nz
) {
58 double dx
=bx
-ax
,dy
=by
-ay
,dz
=bz
-az
;
59 double ilscale
=pow(total_particles()/(optimal_particles
*dx
*dy
*dz
),1/3.0);
65 /** Stores a particle ID and position, allocating a new memory chunk if
66 * necessary. For coordinate directions in which the container is not periodic,
67 * the routine checks to make sure that the particle is within the container
68 * bounds. If the particle is out of bounds, it is not stored.
69 * \param[in] n the numerical ID of the inserted particle.
70 * \param[in] (x,y,z) the position vector of the inserted particle. */
71 void pre_container::put(int n
,double x
,double y
,double z
) {
72 if((xperiodic
||(x
>=ax
&&x
<=bx
))&&(yperiodic
||(y
>=ay
&&y
<=by
))&&(zperiodic
||(z
>=az
&&z
<=bz
))) {
73 if(ch_id
==e_id
) new_chunk();
75 *(ch_p
++)=x
;*(ch_p
++)=y
;*(ch_p
++)=z
;
77 #if VOROPP_REPORT_OUT_OF_BOUNDS ==1
78 else fprintf(stderr
,"Out of bounds: (x,y,z)=(%g,%g,%g)\n",x
,y
,z
);
82 /** Stores a particle ID and position, allocating a new memory chunk if necessary.
83 * \param[in] n the numerical ID of the inserted particle.
84 * \param[in] (x,y,z) the position vector of the inserted particle.
85 * \param[in] r the radius of the particle. */
86 void pre_container_poly::put(int n
,double x
,double y
,double z
,double r
) {
87 if((xperiodic
||(x
>=ax
&&x
<=bx
))&&(yperiodic
||(y
>=ay
&&y
<=by
))&&(zperiodic
||(z
>=az
&&z
<=bz
))) {
88 if(ch_id
==e_id
) new_chunk();
90 *(ch_p
++)=x
;*(ch_p
++)=y
;*(ch_p
++)=z
;*(ch_p
++)=r
;
92 #if VOROPP_REPORT_OUT_OF_BOUNDS ==1
93 else fprintf(stderr
,"Out of bounds: (x,y,z)=(%g,%g,%g)\n",x
,y
,z
);
97 /** Transfers the particles stored within the class to a container class.
98 * \param[in] con the container class to transfer to. */
99 void pre_container::setup(container
&con
) {
100 int **c_id
=pre_id
,*idp
,*ide
,n
;
101 double **c_p
=pre_p
,*pp
,x
,y
,z
;
103 idp
=*(c_id
++);ide
=idp
+pre_container_chunk_size
;
106 n
=*(idp
++);x
=*(pp
++);y
=*(pp
++);z
=*(pp
++);
113 n
=*(idp
++);x
=*(pp
++);y
=*(pp
++);z
=*(pp
++);
118 /** Transfers the particles stored within the class to a container_poly class.
119 * \param[in] con the container_poly class to transfer to. */
120 void pre_container_poly::setup(container_poly
&con
) {
121 int **c_id
=pre_id
,*idp
,*ide
,n
;
122 double **c_p
=pre_p
,*pp
,x
,y
,z
,r
;
124 idp
=*(c_id
++);ide
=idp
+pre_container_chunk_size
;
127 n
=*(idp
++);x
=*(pp
++);y
=*(pp
++);z
=*(pp
++);r
=*(pp
++);
134 n
=*(idp
++);x
=*(pp
++);y
=*(pp
++);z
=*(pp
++);r
=*(pp
++);
139 /** Transfers the particles stored within the class to a container class, also
140 * recording the order in which particles were stored.
141 * \param[in] vo the ordering class to use.
142 * \param[in] con the container class to transfer to. */
143 void pre_container::setup(particle_order
&vo
,container
&con
) {
144 int **c_id
=pre_id
,*idp
,*ide
,n
;
145 double **c_p
=pre_p
,*pp
,x
,y
,z
;
147 idp
=*(c_id
++);ide
=idp
+pre_container_chunk_size
;
150 n
=*(idp
++);x
=*(pp
++);y
=*(pp
++);z
=*(pp
++);
157 n
=*(idp
++);x
=*(pp
++);y
=*(pp
++);z
=*(pp
++);
162 /** Transfers the particles stored within the class to a container_poly class,
163 * also recording the order in which particles were stored.
164 * \param[in] vo the ordering class to use.
165 * \param[in] con the container_poly class to transfer to. */
166 void pre_container_poly::setup(particle_order
&vo
,container_poly
&con
) {
167 int **c_id
=pre_id
,*idp
,*ide
,n
;
168 double **c_p
=pre_p
,*pp
,x
,y
,z
,r
;
170 idp
=*(c_id
++);ide
=idp
+pre_container_chunk_size
;
173 n
=*(idp
++);x
=*(pp
++);y
=*(pp
++);z
=*(pp
++);r
=*(pp
++);
174 con
.put(vo
,n
,x
,y
,z
,r
);
180 n
=*(idp
++);x
=*(pp
++);y
=*(pp
++);z
=*(pp
++);r
=*(pp
++);
181 con
.put(vo
,n
,x
,y
,z
,r
);
185 /** Import a list of particles from an open file stream into the container.
186 * Entries of four numbers (Particle ID, x position, y position, z position)
187 * are searched for. If the file cannot be successfully read, then the routine
188 * causes a fatal error.
189 * \param[in] fp the file handle to read from. */
190 void pre_container::import(FILE *fp
) {
193 while((j
=fscanf(fp
,"%d %lg %lg %lg",&i
,&x
,&y
,&z
))==4) put(i
,x
,y
,z
);
194 if(j
!=EOF
) voro_fatal_error("File import error",VOROPP_FILE_ERROR
);
197 /** Import a list of particles from an open file stream, also storing the order
198 * of that the particles are read. Entries of four numbers (Particle ID, x
199 * position, y position, z position) are searched for. If the file cannot be
200 * successfully read, then the routine causes a fatal error.
201 * \param[in] fp the file handle to read from. */
202 void pre_container_poly::import(FILE *fp
) {
205 while((j
=fscanf(fp
,"%d %lg %lg %lg %lg",&i
,&x
,&y
,&z
,&r
))==5) put(i
,x
,y
,z
,r
);
206 if(j
!=EOF
) voro_fatal_error("File import error",VOROPP_FILE_ERROR
);
209 /** Allocates a new chunk of memory for storing particles. */
210 void pre_container_base::new_chunk() {
212 if(end_id
==l_id
) extend_chunk_index();
213 ch_id
=*end_id
=new int[pre_container_chunk_size
];
214 e_id
=ch_id
+pre_container_chunk_size
;
215 ch_p
=*end_p
=new double[ps
*pre_container_chunk_size
];
218 /** Extends the index of chunks. */
219 void pre_container_base::extend_chunk_index() {
221 if(index_sz
>max_chunk_size
)
222 voro_fatal_error("Absolute memory limit on chunk index reached",VOROPP_MEMORY_ERROR
);
223 #if VOROPP_VERBOSE >=2
224 fprintf(stderr
,"Pre-container chunk index scaled up to %d\n",index_sz
);
226 int **n_id
=new int*[index_sz
],**p_id
=n_id
,**c_id
=pre_id
;
227 double **n_p
=new double*[index_sz
],**p_p
=n_p
,**c_p
=pre_p
;
232 delete [] pre_id
;pre_id
=n_id
;end_id
=p_id
;l_id
=pre_id
+index_sz
;
233 delete [] pre_p
;pre_p
=n_p
;end_p
=p_p
;