1 // Voronoi method to generate nanocrystalline grain boundaries
12 const double pi
=3.1415926535897932384626433832795;
15 const double x_min
=0,x_max
=81;
16 const double y_min
=0,y_max
=81;
17 const double z_min
=0,z_max
=81;
18 const double cvol
=(x_max
-x_min
)*(y_max
-y_min
)*(x_max
-x_min
);
20 // Total number of particles
21 const int particles
=24;
26 // Function for random double between 0 and 1
27 double rnd() {return double(rand())/RAND_MAX
;}
31 double x
,y
,z
,x1
,y1
,z1
,x2
,y2
,z2
,x3
,y3
,z3
,xt
,yt
,zt
,rx
,ry
,rz
;
32 double theta
,cth
,sth
,r
,v
,xc
,yc
,zc
,vx
,vy
,vz
;
34 // Create the container class
35 container
con(x_min
,x_max
,y_min
,y_max
,z_min
,z_max
,10,10,10,
38 // Add generators to the box
39 for(i
=1;i
<=particles
;i
++) {
40 x
=x_min
+rnd()*(x_max
-x_min
);
41 y
=y_min
+rnd()*(y_max
-y_min
);
42 z
=z_min
+rnd()*(z_max
-z_min
);
46 // Open the file for the particle positions
47 FILE *fp
=safe_fopen("lammps_input","w");
49 // Create a loop class to iterate over all of the generators
53 if(cl
.start()) do if(con
.compute_cell(c
,cl
)) {
55 // Generate the first vector of an orthonormal basis
56 x1
=2*rnd()-1;y1
=2*rnd()-1;z1
=2*rnd()-1;r
=1/sqrt(x1
*x1
+y1
*y1
+z1
*z1
);
59 // Construct a second perpendicular vector
60 if(abs(x1
)>0.5||abs(y1
)>0.5) {r
=1/sqrt(x1
*x1
+y1
*y1
);x2
=-y1
*r
;y2
=x1
*r
;z2
=0;}
61 else {r
=1/sqrt(x1
*x1
+z1
*z1
);x2
=-z1
*r
;y2
=0;z2
=x1
*r
;}
63 // Construct a third perpendicular vector using the vector product
64 x
=y2
*z1
-z2
*y1
;y
=z2
*x1
-x2
*z1
;z
=x2
*y1
-y2
*x1
;
66 // Take a random rotation of the second and third vectors
67 theta
=2*pi
*rnd();cth
=cos(theta
);sth
=sin(theta
);
68 x3
=x
*cth
+x2
*sth
;x2
=-x
*sth
+x2
*cth
;
69 y3
=y
*cth
+y2
*sth
;y2
=-y
*sth
+y2
*cth
;
70 z3
=z
*cth
+z2
*sth
;z2
=-z
*sth
+z2
*cth
;
72 // Get a bound on how far to search
73 r
=sqrt(0.25*c
.max_radius_squared());
76 // Add small random displacement to lattice positioning,
77 // so that it's not always perfectly aligned with the generator
78 vx
=-v
+h
*rnd();vy
=-v
+h
*rnd();vz
=-v
+h
*rnd();
80 // Print diagnostic information about this generator
81 c_id
=cl
.pid();cl
.pos(xc
,yc
,zc
);
82 printf("Generator %d at (%g,%g,%g), random basis:\n",c_id
,xc
,yc
,zc
);
83 printf("%g %g %g\n",x1
,y1
,z1
);
84 printf("%g %g %g\n",x2
,y2
,z2
);
85 printf("%g %g %g\n\n",x3
,y3
,z3
);
87 // Loop over a local region of points
88 for(z
=vx
;z
<=v
;z
+=h
) for(y
=vy
;y
<=v
;y
+=h
) for(x
=vz
;x
<=v
;x
+=h
) {
90 // Construct points rotated into the random basis
95 // Skip if this lies outside the container
96 if(xt
<x_min
||xt
>x_max
||yt
<y_min
||yt
>y_max
||zt
<z_min
||zt
>z_max
) continue;
98 // Find the nearest generator
99 con
.find_voronoi_cell(xt
,yt
,zt
,rx
,ry
,rz
,i
);
101 // If the nearest generator matches, then save this point
102 if(i
==c_id
) {fprintf(fp
,"%d %g %g %g\n",j
,xt
,yt
,zt
);j
++;}
106 // Close the output file
109 // Output files for diagnosic purposes
110 con
.draw_particles("lammps_generators");
111 con
.draw_cells_gnuplot("lammps_cells");