ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/ripple/dp.c
Revision: 1193
Committed: Mon May 24 21:14:07 2004 UTC (20 years, 1 month ago) by xsun
Content type: text/plain
File size: 28861 byte(s)
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 xsun 1185 #include <stdio.h>
2     #include <stdlib.h>
3     #include <string.h>
4     #include <math.h>
5     #include <unistd.h>
6     #include <sys/types.h>
7     #include <sys/stat.h>
8     #include <sys/time.h>
9     #include <time.h>
10     #include "mkl_vsl.h"
11    
12     // inlined functions (for periodic box wrapping)
13    
14     inline double roundMe( double x ){
15     return ( x >= 0 ) ? floor( x + 0.5 ) : ceil( x - 0.5 );
16     }
17    
18     // Structures to store our data:
19    
20     // coords holds the data for a single tethered dipole:
21     struct coords{
22     double pos[3]; // cartesian coords
23     double theta; // orientational angle relative to z axis
24     double phi; // orientational angle in x-y plane
25     double mu; // dipole strength
26     char name[30]; // an identifier for the type of atom
27     };
28    
29     // state holds the current "configuration" of the entire system
30     struct system {
31     int nAtoms; // Number of Atoms in this configuration
32     struct coords *r; // The set of coordinates for all atoms
33     double beta; // beta = 1 /(kb*T)
34     double strength; // strength of the dipoles (Debye)
35     double z0; // default z axis position
36     double theta0; // default theta angle
37     double kz; // force constant for z displacement
38 xsun 1191 double kr; // force constant for z displacement
39 xsun 1185 double ktheta; // force constant for theta displacement
40 xsun 1191 double t; // the temperature of the system
41 xsun 1185 int nCycles; // How many cycles to do in total
42     int iCycle; // How many cycles have we done?
43     int nMoves; // How many MC moves in each cycle
44     int nSample; // How many cycles between samples
45     double Hmat[2][2]; // The information about the size of the per. box
46     double HmatI[2][2]; // The inverse box
47     double energy; // The current Energy
48     double dtheta; // maximum size of a theta move
49     double deltaz; // maximum size of a z move
50     double deltaphi; // maximum size of a phi move
51     int nAttempts; // number of MC moves that have been attempted
52     int nAccepts; // number of MC moves that have been accepted
53     int nx; // number of unit cells in x direction
54     int ny; // number of unit cells in y direction
55 xsun 1191 double XYNNDIST; // maximum distance of nearest neighbors in XY plane
56 xsun 1185 };
57    
58     char *program_name; /* the name of the program */
59    
60     // Function prototypes:
61     void usage(void);
62     double toterg(struct system* state);
63     void getmag(struct system* state, double mag[3]);
64     double eneri(struct system* state, struct coords iTemp, int i, int jb);
65     void adjust(struct system* state);
66     void mcmove(struct system* state, VSLStreamStatePtr stream, double *en);
67     void store(struct system* state, FILE* out_file);
68     void invertMat2(double a[2][2], double b[2][2]);
69     void wrapVector( double thePos[2], double Hmat[2][2], double HmatI[2][2]);
70    
71     // Defines for the MKL random Number generator:
72     #define SEED 1
73     #define BRNG VSL_BRNG_MCG31
74     #define METHOD 0
75     #define N 1
76    
77     int main(argc, argv)
78     int argc;
79     char *argv[];
80     {
81    
82     FILE *in_file; /* the input file */
83     FILE *out_file; /* the output file */
84     char *out_prefix = NULL; /* the prefix of the output file
85     (if different from the root_name) */
86     char out_name[500]; /* the output name */
87     char in_name[500]; // the input file name
88     char *root_name = NULL; /* the root name */
89    
90     int have_outName = 0;
91     int have_inName = 0;
92     int have_rootName = 0;
93     int restart_from_file = 0;
94    
95     int i, j, k, imove;
96    
97     char temp_name[500];
98     int lineCount = 0; // the line number
99     char read_buffer[1000]; /* the line buffer for reading */
100     char *eof_test; /* ptr to see when we reach the end of the file */
101     char *foo; /* the pointer to the current string token */
102     char atomName[10];
103    
104     double aLat;
105     double bLat;
106     int cells;
107    
108     int haveAlat = 0;
109     int haveBlat = 0;
110     int haveCells = 0;
111    
112     struct system* state;
113     struct coords* r;
114    
115     int done;
116     char current_flag;
117    
118     double dx, dy, uxi, uyi, uzi, myran, en, ent, magmag;
119     double mag[3];
120     int which;
121    
122     // Other useful defines:
123    
124     double twopi = 2.0 * M_PI;
125     double kb = 0.0019872198;
126     strcpy(atomName, "Ar");
127    
128     state = (struct system *)malloc(sizeof(struct system));
129    
130     // The parameters for the simulation:
131    
132     state->strength = 7.0;
133     state->z0 = 0.0;
134     state->kz = kb;
135 xsun 1191 state->kr = kb;
136 xsun 1185 state->theta0 = M_PI / 2.0;
137     state->ktheta = 0.0;
138     state->dtheta = 0.3;
139     state->deltaz = 1.0;
140     state->deltaphi = 0.5;
141 xsun 1193 state->t = 300.0;
142 xsun 1191 state->beta = 1.0 / (kb * state->t);
143 xsun 1185
144     // these three should really be given as command line arguments, but we'll
145     // set defaults here just in case:
146    
147     state->nCycles = 1000000;
148     state->nMoves = 100;
149    
150     // Store roughly 100 frames while we are testing
151     state->nSample = state->nCycles / 100;
152    
153     // Stuff for initializing the random number generator:
154     struct timeval now_time_val;
155     struct timezone time_zone;
156     struct tm *now_tm;
157     time_t now;
158     int mySeed;
159     VSLStreamStatePtr stream;
160    
161     // First, initialize the random number generator:
162     gettimeofday(&now_time_val, &time_zone); /* get the time now */
163     now = now_time_val.tv_sec; /* convert to epoch time */
164     mySeed = (int) now;
165     vslNewStream(&stream, BRNG, mySeed);
166    
167     // Now handle the arguments to the program:
168    
169     program_name = argv[0]; // save the program name in case we need it
170    
171     for( i = 1; i < argc; i++){
172    
173     if(argv[i][0] =='-'){
174    
175     // parse single character options
176    
177     done =0;
178     j = 1;
179     current_flag = argv[i][j];
180     while( (current_flag != '\0') && (!done) ){
181    
182     switch(current_flag){
183    
184     case 'o':
185     // -o <filename> => the output
186    
187     i++;
188     strcpy( out_name, argv[i] );
189     have_outName = 1;
190     done = 1;
191     break;
192    
193     case 'i':
194     // -i <filename> => the input
195    
196     i++;
197     strcpy( in_name, argv[i] );
198     have_inName = 1;
199     done = 1;
200     break;
201    
202     case 'r':
203     // -r <root> => root Name
204    
205     i++;
206     strcpy( root_name, argv[i] );
207     have_rootName = 1;
208     done = 1;
209     break;
210    
211     case 'n':
212     // -n <#> => do Cycle MC cycles
213    
214     i++;
215     state->nCycles = atoi(argv[i]);
216     done = 1;
217     break;
218    
219     case 's':
220     // -s <#> => write out every nSample MC cycles
221     printf("setting nSample\n");
222     i++;
223     state->nSample = atoi(argv[i]);
224     printf("setting nSample to %d\n", state->nSample);
225     done = 1;
226     break;
227    
228     case 'm':
229     // -m <#> => each MC cycle consists of nMoves atomic moves
230    
231     i++;
232     state->nMoves = atoi(argv[i]);
233     done = 1;
234     break;
235    
236     case 'k':
237     // -k kz sets the value of kz in units of kb
238     i++;
239     state->kz = kb * atof( argv[i] );
240 xsun 1191 state->kr = state->kz;
241 xsun 1185 done = 1;
242     break;
243    
244 xsun 1191 case 'q':
245     // -q mu set the strength of the dipole
246     i++;
247     state->strength = atof( argv[i] );
248     done = 1;
249     break;
250    
251     case 't':
252     // -t set the temperature of the system
253     i++;
254     state->t = atof( argv[i] );
255     state->beta = 1.0 / (kb * state->t);
256     done = 1;
257     break;
258    
259 xsun 1185 case 'h':
260     // -h hexSpace set the inter-atomic spacing for a regular
261     // hexagonal lattice
262     haveAlat = 1;
263     haveBlat = 1;
264     i++;
265     bLat = atof( argv[i] );
266     aLat = sqrt(3.0) * bLat;
267     done = 1;
268     break;
269    
270     case 'a':
271     // -a aLat set the x lattice spacing for the distorted hexagonal
272     // lattice
273     haveAlat = 1;
274     i++;
275     aLat = atof( argv[i] );
276     done = 1;
277     break;
278    
279     case 'b':
280     // -b bLat set the y lattice spacing for the distorted hexagonal
281     // lattice when initializing the system
282     haveBlat = 1;
283     i++;
284     bLat = atof( argv[i] );
285     done = 1;
286     break;
287    
288     case 'c':
289     // -c cells sets the number of unit cells along the x axis
290     // to use when initializing the system
291     haveCells = 1;
292     i++;
293     cells = atoi( argv[i] );
294     done = 1;
295     break;
296    
297     case 'x':
298     usage();
299     done = 1;
300     break;
301    
302     default:
303    
304     (void)fprintf(stderr, "Bad option \"-%s\"\n", current_flag);
305     usage();
306     }
307     j++;
308     current_flag = argv[i][j];
309     }
310     } else {
311    
312     if( root_name != NULL ){
313     fprintf( stderr,
314     "The root name has already been set with an argument to -r\n"
315     "But another argument looks like the root name. Whassup?\n");
316     usage();
317     }
318    
319     root_name = argv[i];
320     }
321     }
322    
323     if ( !have_outName && root_name == NULL) {
324     fprintf( stderr, "No output or root filename was set, so look for your data in dp.dump!\n");
325     strcpy(out_name, "dp.dump");
326     have_outName=1;
327     }
328    
329    
330     // Figure out if we are starting from an input file:
331    
332     if (have_inName) {
333    
334     restart_from_file = 1;
335    
336     in_file = fopen(in_name, "r");
337     if(in_file == NULL){
338     printf("Cannot open file \"%s\" for reading.\n", in_name);
339     exit(8);
340     }
341    
342     // start reading the first frame
343     eof_test = fgets(read_buffer, sizeof(read_buffer), in_file);
344     lineCount++;
345    
346     while(eof_test != NULL){
347    
348     (void)sscanf(read_buffer, "%d", &state->nAtoms);
349     state->r =
350     (struct coords *)calloc(state->nAtoms, sizeof(struct coords));
351    
352     // read and the comment line and grab the time and box dimensions
353    
354     eof_test = fgets(read_buffer, sizeof(read_buffer), in_file);
355     lineCount++;
356     if(eof_test == NULL){
357     printf("error in reading file at line: %d\n", lineCount);
358     exit(8);
359     }
360    
361     foo = strtok( read_buffer, " ,;\t" );
362     (void)sscanf( read_buffer, "%d", &state->iCycle );
363    
364     foo = strtok(NULL, " ,;\t");
365     if(foo == NULL){
366     printf("error in reading file at line: %d\n", lineCount);
367     exit(8);
368     }
369     (void)sscanf(foo, "%d", &state->nx);
370    
371     foo = strtok(NULL, " ,;\t");
372     if(foo == NULL){
373     printf("error in reading file at line: %d\n", lineCount);
374     exit(8);
375     }
376     (void)sscanf(foo, "%d", &state->ny);
377    
378     foo = strtok(NULL, " ,;\t");
379     if(foo == NULL){
380     printf("error in reading file at line: %d\n", lineCount);
381     exit(8);
382     }
383     (void)sscanf(foo, "%lf",&state->Hmat[0][0]);
384    
385     foo = strtok(NULL, " ,;\t");
386     if(foo == NULL){
387     printf("error in reading file at line: %d\n", lineCount);
388     exit(8);
389     }
390     (void)sscanf(foo, "%lf",&state->Hmat[1][0]);
391    
392    
393     foo = strtok(NULL, " ,;\t");
394     if(foo == NULL){
395     printf("error in reading file at line: %d\n", lineCount);
396     exit(8);
397     }
398     (void)sscanf(foo, "%lf",&state->Hmat[0][1]);
399    
400     foo = strtok(NULL, " ,;\t");
401     if(foo == NULL){
402     printf("error in reading file at line: %d\n", lineCount);
403     exit(8);
404     }
405     (void)sscanf(foo, "%lf",&state->Hmat[1][1]);
406    
407     // Length of the two box vectors:
408    
409     dx = sqrt(pow(state->Hmat[0][0], 2) + pow(state->Hmat[1][0], 2));
410     dy = sqrt(pow(state->Hmat[0][1], 2) + pow(state->Hmat[1][1], 2));
411    
412     aLat = dx / (double)(state->nx);
413     bLat = dy / (double)(state->ny);
414    
415 xsun 1191 if (0.5*sqrt(pow(aLat,2.0) + pow(bLat,2.0)) > bLat) {
416     state->XYNNDIST = 0.5*sqrt(pow(aLat,2.0) + pow(bLat,2.0));
417     } else {
418     state->XYNNDIST = bLat;
419     }
420     // slightly larger so we can use < as a comparison
421     state->XYNNDIST = state->XYNNDIST * 1.01;
422    
423 xsun 1185 // Find HmatI:
424    
425     invertMat2(state->Hmat, state->HmatI);
426    
427     for( i=0; i < state->nAtoms; i++){
428    
429     eof_test = fgets(read_buffer, sizeof(read_buffer), in_file);
430     lineCount++;
431     if(eof_test == NULL){
432     printf("error in reading file at line: %d\n", lineCount);
433     exit(8);
434     }
435    
436     foo = strtok(read_buffer, " ,;\t");
437     (void)strcpy(state->r[i].name, foo); //copy the atom name
438    
439     // next we grab the positions
440    
441     foo = strtok(NULL, " ,;\t");
442     if(foo == NULL){
443     printf("error in reading postition x from %s\n"
444     "natoms = %d, line = %d\n",
445     in_name, state->nAtoms, lineCount );
446     exit(8);
447     }
448     (void)sscanf( foo, "%lf", &state->r[i].pos[0] );
449    
450     foo = strtok(NULL, " ,;\t");
451     if(foo == NULL){
452     printf("error in reading postition y from %s\n"
453     "natoms = %d, line = %d\n",
454     in_name, state->nAtoms, lineCount );
455     exit(8);
456     }
457     (void)sscanf( foo, "%lf", &state->r[i].pos[1] );
458    
459     foo = strtok(NULL, " ,;\t");
460     if(foo == NULL){
461     printf("error in reading postition z from %s\n"
462     "natoms = %d, line = %d\n",
463     in_name, state->nAtoms, lineCount );
464     exit(8);
465     }
466     (void)sscanf( foo, "%lf", &state->r[i].pos[2] );
467    
468     foo = strtok(NULL, " ,;\t");
469     if(foo == NULL){
470     printf("error in reading angle phi from %s\n"
471     "natoms = %d, line = %d\n",
472     in_name, state->nAtoms, lineCount );
473     exit(8);
474     }
475     (void)sscanf( foo, "%lf", &state->r[i].phi );
476    
477     foo = strtok(NULL, " ,;\t");
478     if(foo == NULL){
479     printf("error in reading unit vector x from %s\n"
480     "natoms = %d, line = %d\n",
481     in_name, state->nAtoms, lineCount );
482     exit(8);
483     }
484     (void)sscanf( foo, "%lf", &uxi );
485    
486     foo = strtok(NULL, " ,;\t");
487     if(foo == NULL){
488     printf("error in reading unit vector y from %s\n"
489     "natoms = %d, line = %d\n",
490     in_name, state->nAtoms, lineCount );
491     exit(8);
492     }
493     (void)sscanf( foo, "%lf", &uyi );
494    
495     foo = strtok(NULL, " ,;\t");
496     if(foo == NULL){
497     printf("error in reading unit vector z from %s\n"
498     "natoms = %d, line = %d\n",
499     in_name, state->nAtoms, lineCount );
500     exit(8);
501     }
502     (void)sscanf( foo, "%lf", &uzi );
503    
504     state->r[i].theta = acos(uzi);
505    
506     // The one parameter not stored in the dump file is the dipole strength
507     state->r[i].mu = state->strength;
508    
509     }
510     eof_test = fgets(read_buffer, sizeof(read_buffer), in_file);
511     lineCount++;
512     }
513     (void)fclose(in_file);
514    
515     } else {
516    
517     // not restarting from file, so use data we've got!
518    
519     if (!haveAlat) {
520     printf("aLat has not been set!\n");
521     exit(8);
522     }
523    
524     if (!haveBlat) {
525     printf("bLat has not been set!\n");
526     exit(8);
527     }
528    
529     if (!haveCells) {
530     printf("The number of cells has not been set!\n");
531     exit(8);
532     }
533    
534     // Create lattice here:
535    
536     // Domains should be roughly square:
537    
538     state->nx = cells;
539     state->ny = (int) ((double)cells * aLat / bLat );
540    
541 xsun 1191 if (0.5*sqrt(pow(aLat,2.0) + pow(bLat,2.0)) > bLat) {
542     state->XYNNDIST = 0.5*sqrt(pow(aLat,2.0) + pow(bLat,2.0));
543     } else {
544     state->XYNNDIST = bLat;
545     }
546     // slightly larger so we can use < as a comparison
547     state->XYNNDIST = state->XYNNDIST * 1.01;
548    
549 xsun 1185 // each cell has 2 atoms (one at (0,0) and one at (a/2 , b/2))
550     state->nAtoms = 2 * state->nx * state->ny;
551    
552     state->r =
553     (struct coords *)calloc(state->nAtoms, sizeof(struct coords));
554    
555     which = 0;
556     for(i=0; i < state->nx; i++) {
557     for(j=0; j < state->ny; j++) {
558    
559     // First atom is at (0,0)
560    
561     (void)strcpy(state->r[which].name, atomName);
562     state->r[which].pos[0] = i * aLat;
563     state->r[which].pos[1] = j * bLat;
564    
565     vdRngUniform( METHOD, stream, N, &myran, 0.0, 1.0);
566     state->r[which].phi = myran * twopi;
567    
568     vdRngUniform( METHOD, stream, N, &myran, 0.0, 1.0);
569     state->r[which].theta = acos(2.0*myran - 1.0);
570    
571     vdRngUniform( METHOD, stream, N, &myran, 0.0, 1.0);
572     state->r[which].pos[2] = state->z0 + (2.0*myran-1.0) * state->deltaz;
573    
574     state->r[which].mu = state->strength;
575    
576     which++;
577     // Second atom is at (a/2, b/2)
578    
579     state->r[which].pos[0] = aLat * (2.0 * i + 1.0) / 2.0;
580     state->r[which].pos[1] = bLat * (2.0 * j + 1.0) / 2.0;
581    
582     vdRngUniform( METHOD, stream, N, &myran, 0.0, 1.0);
583     state->r[which].phi = myran * twopi;
584    
585     vdRngUniform( METHOD, stream, N, &myran, 0.0, 1.0);
586     state->r[which].theta = acos(2.0*myran - 1.0);
587    
588     vdRngUniform( METHOD, stream, N, &myran, 0.0, 1.0);
589     state->r[which].pos[2] = state->z0 + (2.0*myran-1.0)*state->deltaz;
590    
591     state->r[which].mu = state->strength;
592     which++;
593     }
594     }
595     state->Hmat[0][0] = state->nx * aLat;
596     state->Hmat[0][1] = 0.0;
597     state->Hmat[1][0] = 0.0;
598     state->Hmat[1][1] = state->ny * bLat;
599    
600     // Find HmatI:
601    
602     invertMat2(state->Hmat, state->HmatI);
603    
604     }
605    
606     // Open the dump file for writing:
607    
608     if( !have_outName ) sprintf( out_name, "%s.dump", root_name );
609    
610     out_file = fopen( out_name, "w" );
611     if( out_file == NULL ){
612     printf("Cannot open file \"%s\" for writing.\n", out_name);
613     exit(8);
614     }
615    
616 xsun 1191 /* if (state->iCycle >= state->nCycles) {
617 xsun 1185 printf("This configuration has already gone past the requested number\n"
618     "of MC cycles! Use the -n flag to request more MC cycles!\n");
619     exit(8);
620     }
621 xsun 1191 */
622 xsun 1185 // Do the MC simulation (finally!)
623    
624     en = toterg(state);
625    
626     printf("MC simulation starting for %d cycles\n", state->nCycles);
627     printf("MC simulation starting with %d moves per cycle\n", state->nMoves);
628     printf("MC simulation starting with sampling done every %d cycles\n", state->nSample);
629    
630     printf("The initial Energy is : \t%f\n\n", en);
631    
632     state->nAttempts = 0;
633     state->nAccepts = 0;
634    
635     adjust(state);
636    
637     for(state->iCycle = 0; state->iCycle < state->nCycles; state->iCycle++) {
638     for(imove=0; imove < state->nMoves; imove++) {
639     mcmove(state, stream, &en);
640     }
641    
642     if(((state->iCycle)%state->nSample) == 0) {
643     store(state, out_file);
644     /* Don't bother with the magnetization for now */
645     /*
646     getmag(state, mag);
647     magmag = sqrt(pow(mag[0],2) + pow(mag[1],2) + pow(mag[2],2));
648     printf("mag=%f\t%f\t%f\t%f\n", mag[0], mag[1], mag[2], magmag);
649     */
650     }
651    
652     if( ((state->iCycle+1)%(state->nCycles / 5)) ==0) {
653     printf("\n=====> Completed\t%d\tout of\t%d cycles\n",
654     state->iCycle + 1,
655     state->nCycles);
656     adjust(state);
657     }
658     }
659    
660     if(state->nCycles != 0) {
661     if(state->nAttempts !=0) {
662     printf("Number of attempts to modify a particle :%d\n"
663     "Number of successful modifications: %d (=%lf%)\n\n",
664     state->nAttempts, state->nAccepts,
665     100*(double)(state->nAccepts)/(double)(state->nAttempts));
666     }
667    
668     ent = toterg(state);
669    
670     if ( fabs(ent-en) > 1e-6) {
671     printf("\n###### ENERGY PROBLEMS ###############\n\n");
672     printf("Total Energy end of simulation : %lf\n"
673     "Running Energy : %lf\n"
674     "Energy Difference : %lf\n\n", ent, en, ent-en);
675     }
676     }
677     fclose(out_file);
678     vslDeleteStream( &stream );
679     return 0;
680     }
681    
682     double toterg(struct system* state) {
683    
684     struct coords iTemp;
685    
686     int i, jb;
687     double ener;
688     double eni;
689    
690     ener = 0.0;
691    
692     for(i = 0; i < state->nAtoms; i++) {
693    
694     // Copy atom i's values into iTemp:
695    
696     iTemp.pos[0] = state->r[i].pos[0];
697     iTemp.pos[1] = state->r[i].pos[1];
698     iTemp.pos[2] = state->r[i].pos[2];
699     iTemp.phi = state->r[i].phi;
700     iTemp.theta = state->r[i].theta;
701     iTemp.mu = state->r[i].mu;
702    
703     // Pointer for eneri loop start is set to i
704     // We'll skip the i->i pairing in the eneri routine
705    
706     jb = i;
707    
708     eni = eneri(state, iTemp, i, jb);
709     ener += eni;
710     }
711     state->energy = ener;
712     return ener;
713     }
714    
715     void getmag(struct system* state, double mag[3]) {
716    
717     double thetai, phii, mui, magmag;
718     int i;
719    
720     mag[0] = 0.0;
721     mag[1] = 0.0;
722     mag[2] = 0.0;
723    
724     for(i = 0; i < state->nAtoms; i++) {
725     phii = state->r[i].phi;
726     thetai = state->r[i].theta;
727     mui = state->r[i].mu;
728     mag[0] += mui * cos(phii) * sin(thetai);
729     mag[1] += mui * sin(phii) * sin(thetai);
730     mag[2] += mui * cos(thetai);
731     }
732    
733     mag[0] /= (double)(state->nAtoms);
734     mag[1] /= (double)(state->nAtoms);
735     mag[2] /= (double)(state->nAtoms);
736    
737     }
738    
739     double eneri(struct system *state, struct coords iTemp, int i, int jb) {
740    
741 xsun 1191 double uxi, uyi, uzi, rxy, rij, r, r2, r3, r5, uxj, uyj, uzj, rcut;
742 xsun 1185 double udotu, rdotui, rdotuj, vij, pre, vint;
743 xsun 1191 double dx, dy, aLat, bLat;
744 xsun 1185 double eni, dz;
745     double d[2];
746     int j;
747 xsun 1191
748     vint = 0.0;
749 xsun 1185
750     pre = 14.38362;
751    
752     rcut = 30.0;
753 xsun 1191
754     dx = sqrt(pow(state->Hmat[0][0], 2) + pow(state->Hmat[1][0], 2));
755     dy = sqrt(pow(state->Hmat[0][1], 2) + pow(state->Hmat[1][1], 2));
756    
757     aLat = dx / (double)(state->nx);
758     bLat = dy / (double)(state->ny);
759 xsun 1185
760     eni = 0.0;
761     uxi = iTemp.mu * cos(iTemp.phi) * sin(iTemp.theta);
762     uyi = iTemp.mu * sin(iTemp.phi) * sin(iTemp.theta);
763     uzi = iTemp.mu * cos(iTemp.theta);
764    
765     for(j = jb; j < state->nAtoms; j++) {
766     if(j != i) {
767    
768     // 2-d wrapping on x and y:
769    
770     d[0] = state->r[j].pos[0] - iTemp.pos[0];
771     d[1] = state->r[j].pos[1] - iTemp.pos[1];
772    
773     wrapVector(d, state->Hmat, state->HmatI);
774    
775     // z is unwrapped!
776    
777     dz = state->r[j].pos[2] - iTemp.pos[2];
778 xsun 1191
779    
780     rxy = sqrt(pow(d[0], 2) + pow(d[1], 2));
781 xsun 1185 r2 = pow(d[0], 2) + pow(d[1], 2) + pow(dz, 2);
782     r = sqrt(r2);
783    
784 xsun 1191 if (rxy < state->XYNNDIST) {
785     vint += 0.5 * state->kr * r2;
786     }
787    
788 xsun 1185 if(r < rcut) {
789    
790     r3 = r2*r;
791     r5 = r2*r3;
792    
793     uxj = state->r[j].mu * cos(state->r[j].phi) * sin(state->r[j].theta);
794     uyj = state->r[j].mu * sin(state->r[j].phi) * sin(state->r[j].theta);
795     uzj = state->r[j].mu * cos(state->r[j].theta);
796     udotu = uxi*uxj + uyi*uyj + uzi*uzj;
797     rdotui = d[0]*uxi + d[1]*uyi + dz*uzi;
798     rdotuj = d[0]*uxj + d[1]*uyj + dz*uzj;
799    
800     vij = pre*(udotu/r3 - 3.0*rdotui*rdotuj/r5);
801     eni += vij;
802     }
803     }
804     }
805    
806     vint += 0.5 * state->ktheta * pow((iTemp.theta - state->theta0), 2);
807     eni += vint;
808     return eni;
809     }
810    
811     void adjust(struct system* state) {
812    
813     static int attempp, naccp;
814     double dzo, dphio, dthetao, frac;
815    
816     if((state->nAttempts == 0) || (attempp >= state->nAttempts)) {
817     naccp = state->nAccepts;
818     attempp = state->nAttempts;
819     } else {
820     frac = (double)(state->nAccepts - naccp) /
821     (double)(state->nAttempts - attempp);
822    
823     dthetao = state->dtheta;
824     dzo = state->deltaz;
825     dphio = state->deltaphi;
826    
827     state->dtheta *= fabs(frac/0.5);
828     state->deltaz *= fabs(frac/0.5);
829     state->deltaphi *= fabs(frac/0.5);
830    
831     if((state->dtheta/dthetao)>1.5) state->dtheta = dthetao*1.5;
832     if((state->dtheta/dthetao)<0.5) state->dtheta = dthetao*0.5;
833    
834     if((state->deltaz/dzo)>1.5) state->deltaz = dzo * 1.5;
835     if((state->deltaz/dzo)<0.5) state->deltaz = dzo * 0.5;
836     if((state->deltaphi/dphio)>1.5) state->deltaphi = dphio * 1.5;
837     if((state->deltaphi/dphio)<0.5) state->deltaphi = dphio * 0.5;
838     printf("Max. displ. set to :\t%lf\t%lf\t%lf\n"
839     " (old was:\t%lf\t%lf\t%lf)\n"
840     "Fractional acceptance:\t%lf\n"
841     "nAttempts:\t%d\n"
842     "nSuccesses:\t%d\n\n",
843     state->deltaz, state->deltaphi, state->dtheta,
844     dzo, dphio, dthetao,
845     frac,
846     state->nAttempts - attempp,
847     state->nAccepts - naccp);
848     naccp = state->nAccepts;
849     attempp=state->nAttempts;
850     }
851     }
852    
853     void mcmove(struct system* state, VSLStreamStatePtr stream, double *en) {
854    
855     int o, jb;
856     struct coords oTemp;
857     double eno, enn, myran;
858    
859     state->nAttempts++;
860    
861     jb = 0;
862    
863     vdRngUniform( METHOD, stream, N, &myran, 0.0, 1.0);
864    
865     o = (int)(state->nAtoms * myran);
866     oTemp.pos[0] = state->r[o].pos[0];
867     oTemp.pos[1] = state->r[o].pos[1];
868     oTemp.pos[2] = state->r[o].pos[2];
869     oTemp.phi = state->r[o].phi;
870     oTemp.theta = state->r[o].theta;
871     oTemp.mu = state->r[o].mu;
872    
873     eno = eneri(state, oTemp, o, jb);
874    
875     vdRngUniform( METHOD, stream, N, &myran, 0.0, 1.0);
876    
877     oTemp.pos[2] += (2.0*myran-1.0) * state->deltaz;
878    
879     vdRngUniform( METHOD, stream, N, &myran, 0.0, 1.0);
880    
881     oTemp.phi += (2.0*myran-1.0) * state->deltaphi;
882    
883     vdRngUniform( METHOD, stream, N, &myran, 0.0, 1.0);
884    
885     oTemp.theta += (2.0*myran-1.0) * state->dtheta;
886    
887     enn = eneri(state, oTemp, o, jb);
888    
889    
890     vdRngUniform( METHOD, stream, N, &myran, 0.0, 1.0);
891    
892     if(myran <= (exp(- state->beta * (enn-eno)))) {
893     state->nAccepts++;
894     *en += (enn-eno);
895     state->r[o].pos[2] = oTemp.pos[2];
896     state->r[o].phi = oTemp.phi;
897     state->r[o].theta = oTemp.theta;
898     }
899     }
900    
901    
902     void store(struct system* state, FILE* out_file) {
903    
904     double uxi, uyi, uzi;
905     int i;
906    
907     fprintf(out_file,"%d\n",state->nAtoms);
908    
909     fprintf(out_file, "%d;\t%d\t%d;\t%f\t%f;\t%f\t%f;\n",
910     state->iCycle,
911     state->nx,
912     state->ny,
913     state->Hmat[0][0],
914     state->Hmat[1][0],
915     state->Hmat[0][1],
916     state->Hmat[1][1]);
917    
918     for(i=0; i < state->nAtoms; i++) {
919     uxi = cos(state->r[i].phi)*sin(state->r[i].theta);
920     uyi = sin(state->r[i].phi)*sin(state->r[i].theta);
921     uzi = cos(state->r[i].theta);
922     fprintf(out_file, "%s\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n",
923     "Ar",
924     state->r[i].pos[0],
925     state->r[i].pos[1],
926     state->r[i].pos[2],
927     state->r[i].phi,
928     uxi,
929     uyi,
930     uzi);
931     }
932    
933     fflush(out_file);
934     }
935    
936     double matDet2(double a[2][2]) {
937    
938     double determinant;
939    
940     determinant = (a[0][0] * a[1][1]) - (a[0][1] * a[1][0]);
941    
942     return determinant;
943     }
944    
945    
946     void invertMat2(double a[2][2], double b[2][2]) {
947    
948     double determinant;
949    
950     determinant = matDet2( a );
951    
952     if (determinant == 0.0) {
953     printf("Can't invert a matrix with a zero determinant!\n");
954     }
955    
956     b[0][0] = a[1][1] / determinant;
957     b[0][1] = -a[0][1] / determinant;
958     b[1][0] = -a[1][0] / determinant;
959     b[1][1] = a[0][0] / determinant;
960     }
961    
962     void matVecMul2(double m[2][2], double inVec[2], double outVec[2]) {
963     double a0, a1, a2;
964    
965     a0 = inVec[0]; a1 = inVec[1];
966    
967     outVec[0] = m[0][0]*a0 + m[0][1]*a1;
968     outVec[1] = m[1][0]*a0 + m[1][1]*a1;
969     }
970    
971     void wrapVector( double thePos[2], double Hmat[2][2], double HmatInv[2][2]){
972    
973     int i;
974     double scaled[2];
975    
976     // calc the scaled coordinates.
977    
978     matVecMul2(HmatInv, thePos, scaled);
979    
980     for(i=0; i<2; i++)
981     scaled[i] -= roundMe(scaled[i]);
982    
983     // calc the wrapped real coordinates from the wrapped scaled coordinates
984    
985     matVecMul2(Hmat, scaled, thePos);
986    
987     }
988    
989     /***************************************************************************
990     * prints out the usage for the command line arguments, then exits.
991     ***************************************************************************/
992    
993     void usage(){
994     (void)fprintf(stderr,
995     "The proper usage is: %s [options]\n"
996     "\n"
997     "Options:\n"
998     "\n"
999     " -x Display this message\n"
1000     " -o <out_name> The output file (Defaults to <root>.dump)\n"
1001     " -i <in_name> The input file (no default)\n"
1002     " -r <root> The root (Defaults to dp)\n"
1003     " -n nCycles The number of MC cycles to do\n"
1004     " -s nSample The number of MC cycles between samples\n"
1005     " -m nMoves The number of particle moves in each MC cycle\n"
1006     " -a aLat Set the lattice spacing along x axis\n"
1007     " -b bLat Set the lattice spacing along y axis\n"
1008     " -c cells Set the number of cells along x direction\n"
1009     " (Domains are kept nearly square)\n"
1010     " -h hexSpace Set up a hexagonal lattice\n"
1011     " aLat = sqrt(3) hexSpace\n"
1012     " bLat = hexSpace\n"
1013     " -k kz Sets the value of kz in units of kb\n"
1014 xsun 1191 " -t t Sets the value of temperature in units of kelvin\n"
1015     " -q strength Sets the strength of the dipole\n"
1016 xsun 1185 "\n",
1017    
1018     program_name);
1019     exit(8);
1020     }