1 // Voro++, a 3D cell-based Voronoi library
3 // Author : Chris H. Rycroft (LBL / UC Berkeley)
4 // Email : chr@alum.mit.edu
5 // Date : July 1st 2008
8 * \brief Header file for the dynamic extension classes, which add
9 * functionality for a variety of dynamic particle motions. */
13 template<class r_option
>
14 container_dynamic_base
<r_option
>::container_dynamic_base(fpoint xa
,fpoint xb
,fpoint ya
,
15 fpoint yb
,fpoint za
,fpoint zb
,int xn
,int yn
,int zn
,const bool xper
,const bool yper
,
16 const bool zper
,int memi
) : container_base
<r_option
> (xa
,xb
,ya
,yb
,za
,zb
,xn
,yn
,zn
,xper
,yper
,zper
,memi
), v_inter(ve
) {
19 for(int i
=0;i
<nxyz
;i
++) ve
[i
]=new fpoint
[3*memi
];
22 template<class r_option
>
23 container_dynamic_base
<r_option
>::~container_dynamic_base() {
24 for(int i
=0;i
<nxyz
;i
++) delete [] ve
[i
];
29 template<class r_option
>
30 void container_dynamic_base
<r_option
>::wall_diagnostic() {
31 fpoint x
,y
,z
,dx
,dy
,dz
;
33 for(k
=0;k
<nz
;k
++) for(j
=0;j
<ny
;j
++) for(i
=0;i
<nx
;i
++,ijk
++) {
34 for(l
=0;l
<co
[ijk
];l
++) {
35 x
=p
[ijk
][sz
*l
];y
=p
[ijk
][sz
*l
+1];z
=p
[ijk
][sz
*l
+2];
36 cout
<< id
[ijk
][l
] << " " << x
<< " " << y
<< " " << z
;
37 radius
.print(cout
,ijk
,l
);
38 for(w
=0;w
<wall_number
;w
++) {
39 walls
[w
]->min_distance(x
,y
,z
,dx
,dy
,dz
);
40 cout
<< " " << dx
<< " " << dy
<< " " << dz
<< "\n";
46 template<class r_option
>
47 int container_dynamic_base
<r_option
>::count(fpoint x
,fpoint y
,fpoint z
,fpoint r
) {
48 fpoint xx
,yy
,zz
,px
,py
,pz
;
51 s
=l1
.init(x
,y
,z
,r
,px
,py
,pz
);r
*=r
;
53 for(q
=0;q
<co
[s
];q
++) {
54 xx
=p
[s
][sz
*q
]+px
-x
;yy
=p
[s
][sz
*q
+1]+py
-y
;zz
=p
[s
][sz
*q
+2]+pz
-z
;
55 if (xx
*xx
+yy
*yy
+zz
*zz
<r
) cou
++;
57 } while((s
=l1
.inc(px
,py
,pz
))!=-1);
61 template<class r_option
>
62 void container_dynamic_base
<r_option
>::spot(fpoint cx
,fpoint cy
,fpoint cz
,fpoint dx
,fpoint dy
,fpoint dz
,fpoint rad
) {
63 velocity_constant
vcl(dx
,dy
,dz
);
64 local_move(vcl
,cx
,cy
,cz
,rad
);
67 template<class r_option
>
68 void container_dynamic_base
<r_option
>::gauss_spot(fpoint cx
,fpoint cy
,fpoint cz
,fpoint dx
,fpoint dy
,fpoint dz
,fpoint dec
,fpoint rad
) {
69 velocity_gaussian
vcl(cx
,cy
,cz
,dx
,dy
,dz
,dec
);
70 local_move(vcl
,cx
,cy
,cz
,rad
);
73 template<class r_option
>
74 template<class v_class
>
75 void container_dynamic_base
<r_option
>::local_move(v_class
&vcl
,fpoint cx
,fpoint cy
,fpoint cz
,fpoint rad
) {
77 fpoint x
,y
,z
,ex
,ey
,ez
,px
,py
,pz
;
79 s
=l1
.init(cx
,cy
,cz
,rad
,px
,py
,pz
);rad
*=rad
;
80 do {gh
[s
]=co
[s
];} while ((s
=l1
.inc(px
,py
,pz
))!=-1);
86 x
=p
[s
][sz
*l
]+px
;ex
=x
-cx
;
87 y
=p
[s
][sz
*l
+1]+py
;ey
=y
-cy
;
88 z
=p
[s
][sz
*l
+2]+pz
;ez
=z
-cz
;
89 if(ex
*ex
+ey
*ey
+ez
*ez
>=rad
) {l
++;continue;}
92 ni
=step_int((x
-ax
)*xsp
);
93 nj
=step_int((y
-ay
)*ysp
);
94 nk
=step_int((z
-az
)*zsp
);
96 if(ni
==l1
.ip
&&nj
==l1
.jp
&&nk
==l1
.kp
) {
102 if((xperiodic
||(ni
>=0&&ni
<nx
))
103 &&(yperiodic
||(nj
>=0&&nj
<ny
))
104 &&(zperiodic
||(nk
>=0&&nk
<nz
))) {
105 if(xperiodic
) {x
-=step_div(ni
,nx
)*(bx
-ax
);ni
=step_mod(ni
,nx
);}
106 if(yperiodic
) {y
-=step_div(nj
,ny
)*(by
-ay
);nj
=step_mod(nj
,ny
);}
107 if(zperiodic
) {z
-=step_div(nk
,nz
)*(bz
-az
);nk
=step_mod(nk
,nz
);}
109 if(co
[ni
]==mem
[ni
]) add_particle_memory(ni
);
110 id
[ni
][co
[ni
]]=id
[s
][l
];
112 p
[ni
][co
[ni
]*sz
+1]=y
;
113 p
[ni
][co
[ni
]*sz
+2]=z
;
114 if(sz
==4) p
[ni
][co
[ni
]*sz
+3]=p
[s
][l
*sz
+3];
118 id
[s
][l
]=id
[s
][co
[s
]];
119 for(ll
=0;ll
<sz
;ll
++) p
[s
][sz
*l
+ll
]=p
[s
][sz
*co
[s
]+ll
];
122 ve
[s
][3*l
]=ve
[s
][3*co
[s
]];
123 ve
[s
][3*l
+1]=ve
[s
][3*co
[s
]+1];
124 ve
[s
][3*l
+2]=ve
[s
][3*co
[s
]+2];
130 } while ((s
=l1
.inc(px
,py
,pz
))!=-1);
133 template<class r_option
>
134 void container_dynamic_base
<r_option
>::relax(fpoint cx
,fpoint cy
,fpoint cz
,fpoint rad
,fpoint alpha
) {
136 fpoint x
,y
,z
,ox
,oy
,oz
,px
,py
,pz
,ex
,ey
,ez
;
137 fpoint dx
,dy
,dz
,dd
,rr
,radsq
=rad
*rad
;
138 voropp_loop
l1(this),l2(this);
139 s1
=l1
.init(cx
,cy
,cz
,rad
,ox
,oy
,oz
);
141 for(l
=0;l
<3*co
[s1
];l
++) ve
[s1
][l
]=0;
142 } while ((s1
=l1
.inc(ox
,oy
,oz
))!=-1);
144 s1
=l1
.reset(ox
,oy
,oz
);
146 for(l
=0;l
<co
[s1
];l
++) {
147 ex
=p
[s1
][sz
*l
];if(xperiodic
) ex
+=ox
;dx
=ex
-cx
;
148 ey
=p
[s1
][sz
*l
+1];if(yperiodic
) ey
+=oy
;dy
=ey
-cy
;
149 ez
=p
[s1
][sz
*l
+2];if(zperiodic
) ez
+=oz
;dz
=ez
-cz
;
150 dd
=dx
*dx
+dy
*dy
+dz
*dz
;
151 if(dd
>=radsq
) {l
++;continue;}
153 s2
=l2
.init(ex
,ey
,ez
,1,px
,py
,pz
);
154 while(!l2
.reached(l1
.i
,l1
.j
,l1
.k
)) {
155 for(q
=0;q
<co
[s2
];q
++) {
156 x
=p
[s2
][sz
*q
]-ex
;if(xperiodic
) x
+=px
;
157 y
=p
[s2
][sz
*q
+1]-ey
;if(yperiodic
) y
+=py
;
158 z
=p
[s2
][sz
*q
+2]-ez
;if(zperiodic
) z
+=pz
;
161 if(dd
+rr
+2*(dx
*x
+dy
*y
+dz
*z
)<radsq
) {
162 rr
=alpha
*(0.5-0.5/sqrt(rr
));
166 } else rr
=alpha
*(1-1/sqrt(rr
));
175 x
=p
[s2
][sz
*q
]-ex
;if(xperiodic
) x
+=px
;
176 y
=p
[s2
][sz
*q
+1]-ey
;if(yperiodic
) y
+=py
;
177 z
=p
[s2
][sz
*q
+2]-ez
;if(zperiodic
) z
+=pz
;
180 if(dd
+rr
+2*(dx
*x
+dy
*y
+dz
*z
)<radsq
) {
181 rr
=alpha
*(0.5-0.5/sqrt(rr
));
185 } else rr
=alpha
*(1-1/sqrt(rr
));
193 x
=p
[s2
][sz
*q
]-ex
;if(xperiodic
) x
+=px
;
194 y
=p
[s2
][sz
*q
+1]-ey
;if(yperiodic
) y
+=py
;
195 z
=p
[s2
][sz
*q
+2]-ez
;if(zperiodic
) z
+=pz
;
198 if(dd
+rr
+2*(dx
*x
+dy
*y
+dz
*z
)>=radsq
) {
199 rr
=alpha
*(1-1/sqrt(rr
));
207 while((s2
=l2
.inc(px
,py
,pz
))!=-1) {
208 for(q
=0;q
<co
[s2
];q
++) {
209 x
=p
[s2
][sz
*q
]-ex
;if(xperiodic
) x
+=px
;
210 y
=p
[s2
][sz
*q
+1]-ey
;if(yperiodic
) y
+=py
;
211 z
=p
[s2
][sz
*q
+2]-ez
;if(zperiodic
) z
+=pz
;
214 if(dd
+rr
+2*(dx
*x
+dy
*y
+dz
*z
)>=radsq
) {
215 rr
=alpha
*(1-1/sqrt(rr
));
223 wall_contribution(s1
,l
,ex
,ey
,ez
,alpha
);
225 } while ((s1
=l1
.inc(ox
,oy
,oz
))!=-1);
227 local_move(v_inter
,cx
,cy
,cz
,rad
);
230 template<class r_option
>
231 inline void container_dynamic_base
<r_option
>::wall_contribution(int s
,int l
,fpoint cx
,fpoint cy
,fpoint cz
,fpoint alpha
) {
233 for(int q
=0;q
<wall_number
;q
++) {
234 walls
[q
]->min_distance(cx
,cy
,cz
,x
,y
,z
);
237 rr
=0.5*alpha
*(1-0.5/sqrt(rr
));
243 #ifdef VOROPP_AUTO_X_WALL
245 if(cx
-ax
<0.5) ve
[s
][3*l
]+=alpha
*(0.5+ax
-cx
);
246 if(bx
-cx
<0.5) ve
[s
][3*l
]+=alpha
*(bx
-cx
-0.5);
249 #ifdef VOROPP_AUTO_Y_WALL
251 if(cy
-ay
<0.5) ve
[s
][3*l
+1]+=alpha
*(0.5+ay
-cy
);
252 if(by
-cy
<0.5) ve
[s
][3*l
+1]+=alpha
*(by
-cy
-0.5);
255 #ifdef VOROPP_AUTO_Z_WALL
257 if(cz
-az
<0.5) ve
[s
][3*l
+2]+=alpha
*(0.5+az
-cz
);
258 if(bz
-cz
<0.5) ve
[s
][3*l
+2]+=alpha
*(bz
-cz
-0.5);
263 template<class r_option
>
264 inline int container_dynamic_base
<r_option
>::full_count() {
266 while(ijk
<nxyz
) count
+=co
[ijk
++];
270 template<class r_option
>
271 template<class cond_class
>
272 void container_dynamic_base
<r_option
>::neighbor_distribution(int *bb
,fpoint dr
,int max
) {
273 int i
,j
,k
,ijk
,l
,s
,q
,ll
;
275 voropp_loop
l1(this);
276 fpoint idr
=1/dr
,maxr
=dr
*max
,maxrsq
=maxr
*maxr
;
277 fpoint x
,y
,z
,px
,py
,pz
,cx
,cy
,cz
,rr
;
278 for(ijk
=k
=0;k
<nz
;k
++) for(j
=0;j
<ny
;j
++) for(i
=0;i
<nx
;i
++,ijk
++) {
279 for(l
=0;l
<co
[ijk
];l
++) {
283 if(c1
.test(cx
,cy
,cz
)) {
284 s
=l1
.init(cx
,cy
,cz
,maxr
,px
,py
,pz
);
286 for(q
=0;q
<co
[s
];q
++) {
288 y
=p
[s
][sz
*q
+1]+py
-cy
;
289 z
=p
[s
][sz
*q
+2]+pz
-cz
;
291 if(rr
<maxrsq
) {ll
=int(idr
*sqrt(rr
));if(ll
<max
) bb
[ll
]++;}
293 } while ((s
=l1
.inc(px
,py
,pz
))!=-1);
300 template<class r_option
>
301 template<class cond_class
>
302 fpoint container_dynamic_base
<r_option
>::packing_badness() {
305 voropp_loop
l1(this);
307 fpoint x
,y
,z
,px
,py
,pz
,cx
,cy
,cz
,rr
,badcount
=0;
308 for(ijk
=k
=0;k
<nz
;k
++) for(j
=0;j
<ny
;j
++) for(i
=0;i
<nx
;i
++,ijk
++) {
309 for(l
=0;l
<co
[ijk
];l
++) {
313 if(c1
.test(cx
,cy
,cz
)) {
315 s
=l1
.init(cx
,cy
,cz
,1,px
,py
,pz
);
317 for(q
=0;q
<co
[s
];q
++) {
319 y
=p
[s
][sz
*q
+1]+py
-cy
;
320 z
=p
[s
][sz
*q
+2]+pz
-cz
;
322 if(rr
<1&&rr
>tolerance
) badcount
+=1-2*sqrt(rr
)+rr
;
324 } while ((s
=l1
.inc(px
,py
,pz
))!=-1);
325 wall_badness(cx
,cy
,cz
,badcount
);
329 return pcount
==0?0:sqrt(badcount
/pcount
);
332 template<class r_option
>
333 inline void container_dynamic_base
<r_option
>::wall_badness(fpoint cx
,fpoint cy
,fpoint cz
,fpoint
&badcount
) {
335 for(int q
=0;q
<wall_number
;q
++) {
336 walls
[q
]->min_distance(cx
,cy
,cz
,x
,y
,z
);
338 if (rr
<0.25) badcount
+=0.25-sqrt(rr
)+rr
;
340 #ifdef VOROPP_AUTO_X_WALL
342 if(cx
-ax
<0.5) badcount
+=(0.5+ax
-cx
)*(0.5+ax
-cx
);
343 if(bx
-cx
<0.5) badcount
+=(bx
-cx
-0.5)*(bx
-cx
-0.5);
346 #ifdef VOROPP_AUTO_Y_WALL
348 if(cy
-ay
<0.5) badcount
+=(0.5+ay
-cy
)*(0.5+ay
-cy
);
349 if(by
-cy
<0.5) badcount
+=(by
-cy
-0.5)*(by
-cy
-0.5);
352 #ifdef VOROPP_AUTO_Z_WALL
354 if(cz
-az
<0.5) badcount
+=(0.5+az
-cz
)*(0.5+az
-cz
);
355 if(bz
-cz
<0.5) badcount
+=(bz
-cz
-0.5)*(bz
-cz
-0.5);
360 #ifdef YEAST_ROUTINES
361 /** An overloaded version of the draw_yeast_pov() routine, that outputs
362 * the particle positions to a file.
363 * \param[in] filename the file to write to. */
364 template<class r_option
>
365 void container_dynamic_base
<r_option
>::draw_yeast_pov(const char *filename
) {
367 os
.open(filename
,ofstream::out
|ofstream::trunc
);
372 /** Dumps all the particle positions in the POV-Ray format. */
373 template<class r_option
>
374 void container_dynamic_base
<r_option
>::draw_yeast_pov(ostream
&os
) {
376 for(l
=0;l
<nxyz
;l
++) {
377 for(c
=0;c
<co
[l
];c
++) {
378 os
<< "// id " << id
[l
][c
] << "\n";
379 os
<< "sphere{<" << p
[l
][sz
*c
] << "," << p
[l
][sz
*c
+1] << ","
380 << p
[l
][sz
*c
+2] << ">,";
382 if(id
[l
][c
]<stickycut
) {
383 os
<< " pigment{rgb <0.9,0.3,0.6>} finish{reflection 0.15 ambient 0.4 specular 0.3}}\n";
385 os
<< " pigment{rgb <0.9,0.85,0.35>} finish{reflection 0.15 specular 0.3 ambient 0.42}}\n";
391 template<class r_option
>
392 void container_dynamic_base
<r_option
>::stick(fpoint alpha
) {
394 fpoint bigrad
,smallrad
,currad
;
395 fpoint bigfac
,smallfac
,curfac
;
396 fpoint x
,y
,z
,px
,py
,pz
,cx
,cy
,cz
,rr
;
397 voropp_loop
l1(this);
399 for(ijk
=0;ijk
<nxyz
;ijk
++) for(l
=0;l
<3*co
[ijk
];l
++) ve
[ijk
][l
]=0;
401 for(ijk
=k
=0;k
<nz
;k
++) for(j
=0;j
<ny
;j
++) for(i
=0;i
<nx
;i
++,ijk
++) {
402 for(l
=0;l
<co
[ijk
];l
++) {
406 if(id
[ijk
][l
]<stickycut
) {
407 bigrad
=1.6;smallrad
=1.2;
408 bigfac
=1/0.8;smallfac
=1/0.4;
410 bigrad
=1.2;smallrad
=0.799999999;
411 bigfac
=1/0.4;smallfac
=0;
413 s
=l1
.init(cx
,cy
,cz
,bigrad
,px
,py
,pz
);
414 while(!l1
.reached(i
,j
,k
)) {
415 for(q
=0;q
<co
[s
];q
++) {
417 y
=p
[s
][sz
*q
+1]+py
-cy
;
418 z
=p
[s
][sz
*q
+2]+pz
-cz
;
420 if(id
[s
][q
]<stickycut
) {
421 currad
=bigrad
;curfac
=bigfac
;
423 currad
=smallrad
;curfac
=smallfac
;
425 if (rr
<currad
*currad
) {
426 if(rr
<0.8*0.8) rr
=0.5*alpha
*(1-0.8/sqrt(rr
));
427 else {rr
=sqrt(rr
);rr
=0.5*alpha
*(rr
-0.8)*(1-(rr
-0.8)*curfac
*(2-(rr
-0.8)*curfac
))/rr
;}
429 ve
[ijk
][3*l
+1]+=y
*rr
;
430 ve
[ijk
][3*l
+2]+=z
*rr
;
438 if (s
!=ijk
) throw fatal_error("s and ijk should be aligned and they're not");
441 y
=p
[s
][sz
*q
+1]+py
-cy
;
442 z
=p
[s
][sz
*q
+2]+pz
-cz
;
444 if(id
[s
][q
]<stickycut
) {
445 currad
=bigrad
;curfac
=bigfac
;
447 currad
=smallrad
;curfac
=smallfac
;
449 if (rr
<currad
*currad
) {
450 if(rr
<0.8*0.8) rr
=0.5*alpha
*(1-0.8/sqrt(rr
));
451 else {rr
=sqrt(rr
);rr
=0.5*alpha
*(rr
-0.8)*(1-(rr
-0.8)*curfac
*(2-(rr
-0.8)*curfac
))/rr
;}
453 ve
[ijk
][3*l
+1]+=y
*rr
;
454 ve
[ijk
][3*l
+2]+=z
*rr
;
460 wall_contribution(ijk
,l
,cx
,cy
,cz
,alpha
);
468 template<class r_option
>
469 inline void container_dynamic_base
<r_option
>::clear_velocities() {
470 for(int l
,ijk
=0;ijk
<nxyz
;ijk
++) for(l
=0;l
<3*co
[ijk
];l
++) ve
[ijk
][l
]=0;
473 template<class r_option
>
474 inline void container_dynamic_base
<r_option
>::damp_velocities(fpoint damp
) {
475 for(int l
,ijk
=0;ijk
<nxyz
;ijk
++) for(l
=0;l
<3*co
[ijk
];l
++) ve
[ijk
][l
]*=damp
;
478 template<class r_option
>
479 void container_dynamic_base
<r_option
>::full_relax(fpoint alpha
) {
481 fpoint x
,y
,z
,px
,py
,pz
,cx
,cy
,cz
,rr
;
482 voropp_loop
l1(this);
486 for(ijk
=k
=0;k
<nz
;k
++) for(j
=0;j
<ny
;j
++) for(i
=0;i
<nx
;i
++,ijk
++) {
487 for(l
=0;l
<co
[ijk
];l
++) {
491 s
=l1
.init(cx
,cy
,cz
,1,px
,py
,pz
);
492 while(!l1
.reached(i
,j
,k
)) {
493 for(q
=0;q
<co
[s
];q
++) {
495 y
=p
[s
][sz
*q
+1]+py
-cy
;
496 z
=p
[s
][sz
*q
+2]+pz
-cz
;
499 rr
=alpha
*(0.5-0.5/sqrt(rr
));
501 ve
[ijk
][3*l
+1]+=y
*rr
;
502 ve
[ijk
][3*l
+2]+=z
*rr
;
510 if (s
!=ijk
) throw fatal_error("s and ijk should be aligned and they're not");
513 y
=p
[s
][sz
*q
+1]+py
-cy
;
514 z
=p
[s
][sz
*q
+2]+pz
-cz
;
517 rr
=alpha
*(0.5-0.5/sqrt(rr
));
519 ve
[ijk
][3*l
+1]+=y
*rr
;
520 ve
[ijk
][3*l
+2]+=z
*rr
;
526 wall_contribution(ijk
,l
,cx
,cy
,cz
,alpha
);
533 /** Increase memory for a particular region. */
534 template<class r_option
>
535 void container_dynamic_base
<r_option
>::add_particle_memory(int i
) {
536 int *idp
;fpoint
*pp
,*vep
;
538 #if VOROPP_VERBOSE >=3
539 cerr
<< "Particle memory in region " << i
<< " scaled up to " << nmem
<< endl
;
541 if(nmem
>max_particle_memory
) throw fatal_error("Absolute maximum memory allocation exceeded");
543 for(l
=0;l
<co
[i
];l
++) idp
[l
]=id
[i
][l
];
544 pp
=new fpoint
[sz
*nmem
];
545 for(l
=0;l
<sz
*co
[i
];l
++) pp
[l
]=p
[i
][l
];
546 vep
=new fpoint
[3*nmem
];
547 for(l
=0;l
<3*co
[i
];l
++) vep
[l
]=ve
[i
][l
];
549 delete [] id
[i
];id
[i
]=idp
;
550 delete [] p
[i
];p
[i
]=pp
;
551 delete [] ve
[i
];ve
[i
]=vep
;
554 /** Custom int function, that gives consistent stepping for negative numbers.
555 * With normal int, we have (-1.5,-0.5,0.5,1.5) -> (-1,0,0,1).
556 * With this routine, we have (-1.5,-0.5,0.5,1.5) -> (-2,-1,0,1).*/
557 template<class r_option
>
558 inline int container_dynamic_base
<r_option
>::step_int(fpoint a
) {
559 return a
<0?int(a
)-1:int(a
);
562 /** Custom mod function, that gives consistent stepping for negative numbers. */
563 template<class r_option
>
564 inline int container_dynamic_base
<r_option
>::step_mod(int a
,int b
) {
565 return a
>=0?a
%b
:b
-1-(b
-1-a
)%b
;
568 /** Custom div function, that gives consistent stepping for negative numbers. */
569 template<class r_option
>
570 inline int container_dynamic_base
<r_option
>::step_div(int a
,int b
) {
571 return a
>=0?a
/b
:-1+(a
+1)/b
;
574 template<class r_option
>
575 template<class v_class
>
576 void container_dynamic_base
<r_option
>::move(v_class
&vcl
) {
577 int i
,j
,k
,ijk
,l
,ll
,ni
,nj
,nk
;
580 // For each block, introduce a second counter that counts the number of
581 // particles initially in this block, without including any that have
582 // moved into the block
583 for(ijk
=0;ijk
<nxyz
;ijk
++) gh
[ijk
]=co
[ijk
];
585 // Loop over the blocks within the counter
586 for(ijk
=k
=0;k
<nz
;k
++) for(j
=0;j
<ny
;j
++) for(i
=0;i
<nx
;i
++,ijk
++) {
589 // Scan over the particles that started within this block
592 // Get the particle's initial position
593 x
=p
[ijk
][sz
*l
];y
=p
[ijk
][sz
*l
+1];z
=p
[ijk
][sz
*l
+2];
595 // Call an external routine to compute where this
596 // particle should move to
597 vcl
.vel(ijk
,l
,x
,y
,z
);
599 // Calculate which block the particle's new position is
601 ni
=step_int((x
-ax
)*xsp
);
602 nj
=step_int((y
-ay
)*ysp
);
603 nk
=step_int((z
-az
)*zsp
);
605 // See if the particle is within the same block
606 if(ni
==i
&&nj
==j
&&nk
==k
) {
608 // If so, just update its position
611 p
[ijk
][sz
*l
+2]=z
;l
++;
614 // Check whether the particle's new position is
615 // within the container
616 if((xperiodic
||(ni
>=0&&ni
<nx
))&&(yperiodic
||(nj
>=0&&nj
<ny
))&&(zperiodic
||(nk
>=0&&nk
<nz
))) {
618 // If periodic boundary conditions are
619 // being used, then remap the particle
620 // back into the container
621 if(xperiodic
) {x
-=step_div(ni
,nx
)*(bx
-ax
);ni
=step_mod(ni
,nx
);}
622 if(yperiodic
) {y
-=step_div(nj
,ny
)*(by
-ay
);nj
=step_mod(nj
,ny
);}
623 if(zperiodic
) {z
-=step_div(nk
,nz
)*(bz
-az
);nk
=step_mod(nk
,nz
);}
625 // Calculate the index the new block
626 // where the particle is to be stored,
627 // and allocate memory if necessary
629 if(co
[ni
]==mem
[ni
]) add_particle_memory(ni
);
631 // Add the particle to the new block
632 id
[ni
][co
[ni
]]=id
[ijk
][l
];
634 p
[ni
][co
[ni
]*sz
+1]=y
;
635 p
[ni
][co
[ni
]*sz
+2]=z
;
637 // This class can support a velocity
638 // array. Move it too, if it is being
641 ve
[ni
][3*co
[ni
]]=ve
[ijk
][3*l
];
642 ve
[ni
][3*co
[ni
]+1]=ve
[ijk
][3*l
+1];
643 ve
[ni
][3*co
[ni
]+2]=ve
[ijk
][3*l
+2];
646 // Copy particle radius information if
647 // it being used, and add one to the
648 // number of particles in the block
649 if(sz
==4) p
[ni
][co
[ni
]*sz
+3]=p
[ijk
][l
*sz
+3];
653 // Delete the particle from the original block,
654 // by copying the final particle in the block's
655 // memory on top of it
657 id
[ijk
][l
]=id
[ijk
][co
[ijk
]];
658 for(ll
=0;ll
<sz
;ll
++) p
[ijk
][sz
*l
+ll
]=p
[ijk
][sz
*co
[ijk
]+ll
];
660 ve
[ijk
][3*l
]=ve
[ijk
][3*co
[ijk
]];
661 ve
[ijk
][3*l
+1]=ve
[ijk
][3*co
[ijk
]+1];
662 ve
[ijk
][3*l
+2]=ve
[ijk
][3*co
[ijk
]+2];
665 // If the copied particle was one that had
666 // initially started off in this block, then
667 // prepare to check that one next. If it was a
668 // particle that had moved into this block,
670 if(co
[ijk
]+1==gh
[ijk
]) gh
[ijk
]--;