ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/ripple/dp7.c
Revision: 1185
Committed: Fri May 21 20:07:10 2004 UTC (20 years, 1 month ago) by xsun
Content type: text/plain
File size: 28615 byte(s)
Log Message:
this is the ripple codes

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