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
8 * \brief Function implementations for the loop classes. */
14 /** Initializes a c_loop_subset object to scan over all particles within a
16 * \param[in] (vx,vy,vz) the position vector of the center of the sphere.
17 * \param[in] r the radius of the sphere.
18 * \param[in] bounds_test whether to do detailed bounds checking. If this is
19 * false then the class will loop over all particles in
20 * blocks that overlap the given sphere. If it is true,
21 * the particle will only loop over the particles which
22 * actually lie within the sphere.
23 * \return True if there is any valid point to loop over, false otherwise. */
24 void c_loop_subset::setup_sphere(double vx
,double vy
,double vz
,double r
,bool bounds_test
) {
25 if(bounds_test
) {mode
=sphere
;v0
=vx
;v1
=vy
;v2
=vz
;v3
=r
*r
;} else mode
=no_check
;
26 ai
=step_int((vx
-ax
-r
)*xsp
);
27 bi
=step_int((vx
-ax
+r
)*xsp
);
28 aj
=step_int((vy
-ay
-r
)*ysp
);
29 bj
=step_int((vy
-ay
+r
)*ysp
);
30 ak
=step_int((vz
-az
-r
)*zsp
);
31 bk
=step_int((vz
-az
+r
)*zsp
);
35 /** Initializes the class to loop over all particles in a rectangular subgrid
37 * \param[in] (ai_,bi_) the subgrid range in the x-direction, inclusive of both
39 * \param[in] (aj_,bj_) the subgrid range in the y-direction, inclusive of both
41 * \param[in] (ak_,bk_) the subgrid range in the z-direction, inclusive of both
43 * \return True if there is any valid point to loop over, false otherwise. */
44 void c_loop_subset::setup_intbox(int ai_
,int bi_
,int aj_
,int bj_
,int ak_
,int bk_
) {
45 ai
=ai_
;bi
=bi_
;aj
=aj_
;bj
=bj_
;ak
=ak_
;bk
=bk_
;
50 /** Sets up all of the common constants used for the loop.
51 * \return True if there is any valid point to loop over, false otherwise. */
52 void c_loop_subset::setup_common() {
54 if(ai
<0) {ai
=0;if(bi
<0) bi
=0;}
55 if(bi
>=nx
) {bi
=nx
-1;if(ai
>=nx
) ai
=nx
-1;}
58 if(aj
<0) {aj
=0;if(bj
<0) bj
=0;}
59 if(bj
>=ny
) {bj
=ny
-1;if(aj
>=ny
) aj
=ny
-1;}
62 if(ak
<0) {ak
=0;if(bk
<0) bk
=0;}
63 if(bk
>=nz
) {bk
=nz
-1;if(ak
>=nz
) ak
=nz
-1;}
66 di
=i
=step_mod(ci
,nx
);apx
=px
=step_div(ci
,nx
)*sx
;
67 dj
=j
=step_mod(cj
,ny
);apy
=py
=step_div(cj
,ny
)*sy
;
68 dk
=k
=step_mod(ck
,nz
);apz
=pz
=step_div(ck
,nz
)*sz
;
69 inc1
=di
-step_mod(bi
,nx
);
70 inc2
=nx
*(ny
+dj
-step_mod(bj
,ny
))+inc1
;
76 /** Starts the loop by finding the first particle within the container to
78 * \return True if there is any particle to consider, false otherwise. */
79 bool c_loop_subset::start() {
80 while(co
[ijk
]==0) {if(!next_block()) return false;}
81 while(mode
!=no_check
&&out_of_bounds()) {
83 while(q
>=co
[ijk
]) {q
=0;if(!next_block()) return false;}
88 /** Initializes the class to loop over all particles in a rectangular box.
89 * \param[in] (xmin,xmax) the minimum and maximum x coordinates of the box.
90 * \param[in] (ymin,ymax) the minimum and maximum y coordinates of the box.
91 * \param[in] (zmin,zmax) the minimum and maximum z coordinates of the box.
92 * \param[in] bounds_test whether to do detailed bounds checking. If this is
93 * false then the class will loop over all particles in
94 * blocks that overlap the given box. If it is true, the
95 * particle will only loop over the particles which
96 * actually lie within the box.
97 * \return True if there is any valid point to loop over, false otherwise. */
98 void c_loop_subset::setup_box(double xmin
,double xmax
,double ymin
,double ymax
,double zmin
,double zmax
,bool bounds_test
) {
99 if(bounds_test
) {mode
=box
;v0
=xmin
;v1
=xmax
;v2
=ymin
;v3
=ymax
;v4
=zmin
;v5
=zmax
;} else mode
=no_check
;
100 ai
=step_int((xmin
-ax
)*xsp
);
101 bi
=step_int((xmax
-ax
)*xsp
);
102 aj
=step_int((ymin
-ay
)*ysp
);
103 bj
=step_int((ymax
-ay
)*ysp
);
104 ak
=step_int((zmin
-az
)*zsp
);
105 bk
=step_int((zmax
-az
)*zsp
);
109 /** Computes whether the current point is out of bounds, relative to the
110 * current loop setup.
111 * \return True if the point is out of bounds, false otherwise. */
112 bool c_loop_subset::out_of_bounds() {
113 double *pp
=p
[ijk
]+ps
*q
;
115 double fx(*pp
+px
-v0
),fy(pp
[1]+py
-v1
),fz(pp
[2]+pz
-v2
);
116 return fx
*fx
+fy
*fy
+fz
*fz
>v3
;
118 double f(*pp
+px
);if(f
<v0
||f
>v1
) return true;
119 f
=pp
[1]+py
;if(f
<v2
||f
>v3
) return true;
120 f
=pp
[2]+pz
;return f
<v4
||f
>v5
;
124 /** Returns the next block to be tested in a loop, and updates the periodicity
125 * vector if necessary. */
126 bool c_loop_subset::next_block() {
129 if(ci
<nx
-1) {ci
++;ijk
++;} else {ci
=0;ijk
+=1-nx
;px
+=sx
;}
132 i
=ai
;ci
=di
;px
=apx
;j
++;
133 if(cj
<ny
-1) {cj
++;ijk
+=inc1
;} else {cj
=0;ijk
+=inc1
-nxy
;py
+=sy
;}
136 i
=ai
;ci
=di
;j
=aj
;cj
=dj
;px
=apx
;py
=apy
;k
++;
137 if(ck
<nz
-1) {ck
++;ijk
+=inc2
;} else {ck
=0;ijk
+=inc2
-nxyz
;pz
+=sz
;}
142 /** Extends the memory available for storing the ordering. */
143 void particle_order::add_ordering_memory() {
144 int *no
=new int[size
<<2],*nop
=no
,*opp
=o
;
145 while(opp
<op
) *(nop
++)=*(opp
++);
147 size
<<=1;o
=no
;op
=nop
;