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

# Content
1 #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 double t; // the temperature of the system
41 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 double XYNNDIST; // maximum distance of nearest neighbors in XY plane
56 };
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 state->kr = kb;
136 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 state->t = 300.0;
142 state->beta = 1.0 / (kb * state->t);
143
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 state->kr = state->kz;
241 done = 1;
242 break;
243
244 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 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 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 // 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 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 // 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 /* if (state->iCycle >= state->nCycles) {
617 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 */
622 // 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 double uxi, uyi, uzi, rxy, rij, r, r2, r3, r5, uxj, uyj, uzj, rcut;
742 double udotu, rdotui, rdotuj, vij, pre, vint;
743 double dx, dy, aLat, bLat;
744 double eni, dz;
745 double d[2];
746 int j;
747
748 vint = 0.0;
749
750 pre = 14.38362;
751
752 rcut = 30.0;
753
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
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
779
780 rxy = sqrt(pow(d[0], 2) + pow(d[1], 2));
781 r2 = pow(d[0], 2) + pow(d[1], 2) + pow(dz, 2);
782 r = sqrt(r2);
783
784 if (rxy < state->XYNNDIST) {
785 vint += 0.5 * state->kr * r2;
786 }
787
788 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 " -t t Sets the value of temperature in units of kelvin\n"
1015 " -q strength Sets the strength of the dipole\n"
1016 "\n",
1017
1018 program_name);
1019 exit(8);
1020 }