1 // Ellipsoidal wall example
3 // Author : Simon Konstandin (UMM Mannheim)
8 #include "quartic/quartic.hpp"
9 using namespace magnet::math
;
11 // Set up constants for the container geometry
12 const double x_min
=-6,x_max
=6;
13 const double y_min
=-6,y_max
=6;
14 const double z_min
=-6,z_max
=6;
16 // Golden ratio constants
17 const double Phi
=0.5*(1+sqrt(5.0));
18 const double phi
=0.5*(1-sqrt(5.0));
20 // Set up the number of blocks that the container is divided
22 const int n_x
=5,n_y
=5,n_z
=5;
24 // Set the number of particles that are going to be randomly introduced
25 const int particles
=500;
27 // This function returns a random double between 0 and 1
28 double rnd() {return double(rand())/RAND_MAX
;}
30 // Ellipsoidal wall object
31 class wall_ellipsoid
: public wall
{
43 wall_ellipsoid(double a_
,double r_
,double xc_
,double yc_
,double zc_
)
44 : a(a_
), aa(a_
*a_
), aa_inv(1/aa
), a_cal(2.0+2.0/aa
), rr(r_
*r_
),
45 rr_inv(1/rr
), xc(xc_
), yc(yc_
), zc(zc_
), w_id(99) {}
46 bool point_inside(double x
,double y
,double z
) {
47 return x
*x
+y
*y
+z
*z
*a
*a
<rr
;
49 virtual bool cut_cell(voronoicell
&c
,double x
,double y
,double z
) {
50 return cut_cell_base(c
,x
,y
,z
);
52 virtual bool cut_cell(voronoicell_neighbor
&c
,double x
,double y
,double z
) {
53 return cut_cell_base(c
,x
,y
,z
);
55 template<class v_cell
>
56 bool cut_cell_base(v_cell
&c
,double x
,double y
,double z
) {
58 double xx
=x
*x
,yy
=y
*y
,zz
=z
*z
,s
[4],
59 b_cal
=1.0-(xx
+yy
)*rr_inv
+(4.0-zz
*rr_inv
)*aa_inv
+aa_inv
*aa_inv
,
60 c_cal
=2.0*(1.0-(xx
+yy
+zz
)*rr_inv
)*aa_inv
+2.0*aa_inv
*aa_inv
,
61 d_cal
=(1.0-(xx
+yy
+zz
*aa
)*rr_inv
)*aa_inv
*aa_inv
,
62 xell
[4],yell
[4],zell
[4],d2
[4];
63 int i
,j
=0,q
=quarticSolve(a_cal
,b_cal
,c_cal
,d_cal
,s
[0],s
[1],s
[2],s
[3]);
68 zell
[i
]=z
/(1+s
[i
]*aa
);
69 d2
[i
]=(xell
[i
]-x
)*(xell
[i
]-x
)+(yell
[i
]-y
)*(yell
[i
]-y
)+(zell
[i
]-z
)*(zell
[i
]-z
);
72 for(i
=1;i
<4;i
++) if ((d2
[i
]<=d2
[j
])&&(abs(xell
[i
]*xell
[i
]+yell
[i
]*yell
[i
]+aa
*zell
[i
]*zell
[i
]-rr
)<1e-4)) j
=i
;
74 double xn
=xell
[j
]-x
,yn
=yell
[j
]-y
,zn
=zell
[j
]-z
,dn2
=xn
*xn
+yn
*yn
+zn
*zn
;
76 return c
.nplane(xn
,yn
,zn
,xx
+yy
+aa
*zz
<rr
?2*dn2
:0,w_id
);
84 // Create a container with the geometry given above. This is bigger
85 // than the particle packing itself.
86 container
con(x_min
,x_max
,y_min
,y_max
,z_min
,z_max
,n_x
,n_y
,n_z
,
89 // Create the "initial shape" wall class and add it to the container
90 wall_ellipsoid
we(1.5,5,0,0,0);
93 // Randomly add particles into the container
94 for(i
=0;i
<particles
;) {
95 x
=x_min
+rnd()*(x_max
-x_min
);
96 y
=y_min
+rnd()*(y_max
-y_min
);
97 z
=z_min
+rnd()*(z_max
-z_min
);
98 if(con
.point_inside(x
,y
,z
)) con
.put(i
++,x
,y
,z
);
101 // Save the particles and Voronoi cells in POV-Ray format
102 con
.draw_particles("ellipsoid_p.gnu");
103 con
.draw_cells_gnuplot("ellipsoid_v.gnu");