added set_temp and set_timestep stages
[physik/posic.git] / mdrun.c
1 /*
2  * mdrun.c - main code to run a md simulation
3  *
4  * author: Frank Zirkelbach <frank.zirkelbach@physik.uni-augsburg.de>
5  *
6  */
7
8 #include "mdrun.h"
9
10 /* potential */
11 #include "potentials/harmonic_oscillator.h"
12 #include "potentials/lennard_jones.h"
13 #include "potentials/albe.h"
14 #ifdef TERSOFF_ORIG
15 #include "potentials/tersoff_orig.h"
16 #else
17 #include "potentials/tersoff.h"
18 #endif
19
20 #define ME      "[mdrun]"
21
22 /*
23  * parse function
24  */
25
26 int mdrun_usage(void) {
27
28         printf("%s usage:\n",ME);
29
30         return 0;
31 }
32
33 int mdrun_parse_argv(t_mdrun *mdrun,int argc,char **argv) {
34
35         int i;
36
37         for(i=1;i<argc;i++) {
38
39                 if(argv[i][0]!='-') {
40                         printf("%s unknown switch: %s\n",ME,argv[i]);
41                         return -1;
42                 }
43
44                 switch(argv[i][1]) {
45                         case 'c':
46                                 strncpy(mdrun->cfile,argv[++i],128);
47                                 break;
48                         case 's':
49                                 strncpy(mdrun->sdir,argv[++i],128);
50                                 break;
51                         case 'h':
52                                 mdrun_usage();
53                                 break;
54                         default:
55                                 printf("%s unknown option: %s\n",ME,argv[i]);
56                                 mdrun_usage();
57                                 return -1;
58                 }
59
60         }
61
62         return 0;
63 }
64
65 int del_stages(t_mdrun *mdrun) {
66
67         t_list *sl;
68         t_stage *stage;
69
70         sl=&(mdrun->stage);
71
72         list_reset_f(sl);
73
74         if(sl->start==NULL)
75                 return 0;
76
77         do {
78                 stage=sl->current->data;
79                 free(stage->params);
80                 free(stage);
81         } while(list_next_f(sl)!=L_NO_NEXT_ELEMENT);
82
83         return 0;
84 }
85
86 int add_stage(t_mdrun *mdrun,u8 type,void *params) {
87
88         int psize;
89
90         t_stage *stage;
91
92         switch(type) {
93                 case STAGE_DISPLACE_ATOM:
94                         psize=sizeof(t_displace_atom_params);
95                         break;
96                 case STAGE_INSERT_ATOMS:
97                         psize=sizeof(t_insert_atoms_params);
98                         break;
99                 case STAGE_INSERT_MIXED_ATOMS:
100                         psize=sizeof(t_insert_mixed_atoms_params);
101                         break;
102                 case STAGE_CONTINUE:
103                         psize=sizeof(t_continue_params);
104                         break;
105                 case STAGE_ANNEAL:
106                         psize=sizeof(t_anneal_params);
107                         break;
108                 case STAGE_CHAATTR:
109                         psize=sizeof(t_chaattr_params);
110                         break;
111                 case STAGE_CHSATTR:
112                         psize=sizeof(t_chsattr_params);
113                         break;
114                 case STAGE_SET_TEMP:
115                         psize=sizeof(t_set_temp_params);
116                         break;
117                 case STAGE_SET_TIMESTEP:
118                         psize=sizeof(t_set_timestep_params);
119                         break;
120                 default:
121                         printf("%s unknown stage type: %02x\n",ME,type);
122                         return -1;
123         }
124
125         stage=malloc(sizeof(t_stage));
126         if(stage==NULL) {
127                 perror("[mdrun] malloc (add stage)");
128                 return -1;
129         }
130
131         stage->type=type;
132         stage->executed=FALSE;
133
134         stage->params=malloc(psize);
135         if(stage->params==NULL) {
136                 perror("[mdrun] malloc (stage params)");
137                 return -1;
138         }
139
140         memcpy(stage->params,params,psize);
141
142         list_add_immediate_f(&(mdrun->stage),stage);
143
144         return 0;
145 }
146
147 int mdrun_parse_config(t_mdrun *mdrun) {
148
149         int fd,ret;
150         char error[128];
151         char line[128];
152         char *wptr;
153         char word[16][64];
154         int wcnt;
155         int i,o;
156
157         t_displace_atom_params dap;
158         t_insert_atoms_params iap;
159         t_insert_mixed_atoms_params imp;
160         t_continue_params cp;
161         t_anneal_params ap;
162         t_chaattr_params cap;
163         t_chsattr_params csp;
164         t_set_temp_params stp;
165         t_set_timestep_params stsp;
166
167         /* open config file */
168         fd=open(mdrun->cfile,O_RDONLY);
169         if(fd<0) {
170                 snprintf(error,128,"%s open cfile %s",ME,mdrun->cfile);
171                 perror(error);
172                 return fd;
173         }
174
175         /* read, parse, set */
176         ret=1;
177         while(ret>0) {
178
179                 /* read */
180                 ret=get_line(fd,line,128);
181
182                 /* parse */
183
184                 // ignore # lines and \n
185                 if((line[0]=='#')|(ret==1))
186                         continue;
187
188                 // reset
189                 memset(&iap,0,sizeof(t_insert_atoms_params));
190                 memset(&imp,0,sizeof(t_insert_mixed_atoms_params));
191                 memset(&cp,0,sizeof(t_continue_params));
192                 memset(&ap,0,sizeof(t_anneal_params));
193                 memset(&cap,0,sizeof(t_chaattr_params));
194                 memset(&csp,0,sizeof(t_chsattr_params));
195                 memset(&stp,0,sizeof(t_set_temp_params));
196                 memset(&stsp,0,sizeof(t_set_timestep_params));
197
198                 // get command + args
199                 wcnt=0;
200                 while(1) {
201                         if(wcnt)
202                                 wptr=strtok(NULL," \t");
203                         else
204                                 wptr=strtok(line," \t");
205                         if(wptr==NULL)
206                                 break;
207                         strncpy(word[wcnt],wptr,64);
208                         wcnt+=1;
209                 }
210
211                 if(!strncmp(word[0],"potential",9)) {
212                         if(!strncmp(word[1],"albe",4))
213                                 mdrun->potential=MOLDYN_POTENTIAL_AM;
214                         if(!strncmp(word[1],"tersoff",7))
215                                 mdrun->potential=MOLDYN_POTENTIAL_TM;
216                         if(!strncmp(word[1],"ho",2))
217                                 mdrun->potential=MOLDYN_POTENTIAL_HO;
218                         if(!strncmp(word[1],"lj",2))
219                                 mdrun->potential=MOLDYN_POTENTIAL_LJ;
220                 }
221                 else if(!strncmp(word[0],"continue",8))
222                         strncpy(mdrun->continue_file,word[1],128);
223                 else if(!strncmp(word[0],"cutoff",6))
224                         mdrun->cutoff=atof(word[1]);
225                 else if(!strncmp(word[0],"nnd",3))
226                         mdrun->nnd=atof(word[1]);
227                 else if(!strncmp(word[0],"intalgo",7)) {
228                         if(!strncmp(word[1],"verlet",5))
229                                 mdrun->intalgo=MOLDYN_INTEGRATE_VERLET;
230                 }
231                 else if(!strncmp(word[0],"timestep",8))
232                         mdrun->timestep=atof(word[1]);
233                 else if(!strncmp(word[0],"volume",6)) {
234                         mdrun->dim.x=atof(word[1]);
235                         mdrun->dim.y=atof(word[2]);
236                         mdrun->dim.z=atof(word[3]);
237                         if(strncmp(word[4],"0",1))
238                                 mdrun->vis=TRUE;
239                 }
240                 else if(!strncmp(word[0],"pbc",3)) {
241                         if(strncmp(word[1],"0",1))
242                                 mdrun->pbcx=TRUE;
243                         else
244                                 mdrun->pbcx=FALSE;
245                         if(strncmp(word[2],"0",1))
246                                 mdrun->pbcy=TRUE;
247                         else
248                                 mdrun->pbcy=FALSE;
249                         if(strncmp(word[3],"0",1))
250                                 mdrun->pbcz=TRUE;
251                         else
252                                 mdrun->pbcz=FALSE;
253                 }
254                 else if(!strncmp(word[0],"temperature",11))
255                         mdrun->temperature=atof(word[1]);
256                 else if(!strncmp(word[0],"pressure",8))
257                         mdrun->pressure=atof(word[1]);
258                 else if(!strncmp(word[0],"lattice",7)) {
259                         if(!strncmp(word[1],"zincblende",10))
260                                 mdrun->lattice=ZINCBLENDE;
261                         if(!strncmp(word[1],"fcc",3))
262                                 mdrun->lattice=FCC;
263                         if(!strncmp(word[1],"diamond",7))
264                                 mdrun->lattice=DIAMOND;
265                         if(!strncmp(word[1],"none",4))
266                                 mdrun->lattice=NONE;
267                 }
268                 else if(!strncmp(word[0],"element1",8)) {
269                         mdrun->element1=atoi(word[1]);
270                         mdrun->m1=pse_mass[mdrun->element1];
271                 }
272                 else if(!strncmp(word[0],"element2",8)) {
273                         mdrun->element2=atoi(word[1]);
274                         mdrun->m2=pse_mass[mdrun->element2];
275                 }
276                 else if(!strncmp(word[0],"fill",6)) {
277                         // only lc mode by now
278                         mdrun->lx=atoi(word[2]);
279                         mdrun->ly=atoi(word[3]);
280                         mdrun->lz=atoi(word[4]);
281                         mdrun->lc=atof(word[5]);
282                 }
283                 else if(!strncmp(word[0],"aattr",5)) {
284                         // for aatrib line we need a special stage
285                         // containing one schedule of 0 loops ...
286                         for(i=0;i<strlen(word[1]);i++) {
287                                 switch(word[1][i]) {
288                                         case 't':
289                                                 cap.type|=CHAATTR_TOTALV;
290                                                 break;
291                                         case 'r':
292                                                 cap.type|=CHAATTR_REGION;
293                                                 break;
294                                         case 'e':
295                                                 cap.type|=CHAATTR_ELEMENT;
296                                                 break;
297                                         default:
298                                                 break;
299                                 }
300                         }
301                         i=2;
302                         if(cap.type&CHAATTR_REGION) {
303                                 cap.x0=atof(word[1]);   
304                                 cap.y0=atof(word[2]);   
305                                 cap.z0=atof(word[3]);   
306                                 cap.x1=atof(word[4]);   
307                                 cap.y1=atof(word[5]);   
308                                 cap.z1=atof(word[6]);
309                                 i+=6;
310                         }
311                         if(cap.type&CHAATTR_ELEMENT) {
312                                 cap.element=atoi(word[i]);
313                                 i+=1;
314                         }
315                         for(o=0;o<strlen(word[i]);o++) {
316                                 switch(word[i][o]) {
317                                         case 'b':
318                                                 cap.attr|=ATOM_ATTR_VB;
319                                                 break;
320                                         case 'h':
321                                                 cap.attr|=ATOM_ATTR_HB;
322                                                 break;
323                                         case 'v':
324                                                 cap.attr|=ATOM_ATTR_VA;
325                                                 break;
326                                         case 'f':
327                                                 cap.attr|=ATOM_ATTR_FP;
328                                                 break;
329                                         case '1':
330                                                 cap.attr|=ATOM_ATTR_1BP;
331                                                 break;
332                                         case '2':
333                                                 cap.attr|=ATOM_ATTR_2BP;
334                                                 break;
335                                         case '3':
336                                                 cap.attr|=ATOM_ATTR_3BP;
337                                                 break;
338                                         default:
339                                                 break;
340                                 }
341                         }
342                         add_stage(mdrun,STAGE_CHAATTR,&cap);
343                 }
344                 else if(!strncmp(word[0],"sattr",5)) {
345                         // for satrib line we need a special stage
346                         // containing one schedule of 0 loops ...
347                         csp.type=0;
348                         for(i=1;i<wcnt;i++) {
349                                 if(!strncmp(word[i],"pctrl",5)) {
350                                         csp.ptau=0.01/(atof(word[++i])*GPA);
351                                         csp.type|=CHSATTR_PCTRL;
352                                 }
353                                 if(!strncmp(word[i],"tctrl",5)) {
354                                         csp.ttau=atof(word[++i]);
355                                         csp.type|=CHSATTR_TCTRL;
356                                 }
357                                 if(!strncmp(word[i],"prelax",6)) {
358                                         csp.dp=atof(word[++i])*BAR;
359                                         csp.type|=CHSATTR_PRELAX;
360                                 }
361                                 if(!strncmp(word[i],"trelax",6)) {
362                                         csp.dt=atof(word[++i]);
363                                         csp.type|=CHSATTR_TRELAX;
364                                 }
365                                 if(!strncmp(word[i],"rsteps",6)) {
366                                         csp.rsteps=atoi(word[++i]);
367                                         csp.type|=CHSATTR_RSTEPS;
368                                 }
369                                 if(!strncmp(word[i],"avgrst",6)) {
370                                         csp.avgrst=atoi(word[++i]);
371                                         csp.type|=CHSATTR_AVGRST;
372                                 }
373                         }
374                         add_stage(mdrun,STAGE_CHSATTR,&csp);
375                 }
376                 else if(!strncmp(word[0],"prerun",6))
377                         mdrun->prerun=atoi(word[1]);
378                 else if(!strncmp(word[0],"avgskip",7))
379                         mdrun->avgskip=atoi(word[1]);
380                 else if(!strncmp(word[0],"elog",4))
381                         mdrun->elog=atoi(word[1]);
382                 else if(!strncmp(word[0],"tlog",4))
383                         mdrun->tlog=atoi(word[1]);
384                 else if(!strncmp(word[0],"plog",4))
385                         mdrun->plog=atoi(word[1]);
386                 else if(!strncmp(word[0],"vlog",4))
387                         mdrun->vlog=atoi(word[1]);
388                 else if(!strncmp(word[0],"save",4))
389                         mdrun->save=atoi(word[1]);
390                 else if(!strncmp(word[0],"visualize",9))
391                         mdrun->visualize=atoi(word[1]);
392                 else if(!strncmp(word[0],"stage",5)) {
393                         // for every stage line, add a stage
394                         if(!strncmp(word[1],"displace",8)) {
395                                 dap.nr=atoi(word[2]);   
396                                 dap.dx=atof(word[3]);
397                                 dap.dy=atof(word[4]);
398                                 dap.dz=atof(word[5]);
399                                 add_stage(mdrun,STAGE_DISPLACE_ATOM,&dap);
400                         }
401                         else if(!strncmp(word[1],"ins_atoms",9)) {
402                                 iap.ins_steps=atoi(word[2]);
403                                 iap.ins_atoms=atoi(word[3]);
404                                 iap.element=atoi(word[4]);
405                                 iap.brand=atoi(word[5]);
406                                 for(i=0;i<strlen(word[6]);i++) {
407                                         switch(word[6][i]) {
408                                                 case 'b':
409                                                         iap.attr|=ATOM_ATTR_VB;
410                                                         break;
411                                                 case 'h':
412                                                         iap.attr|=ATOM_ATTR_HB;
413                                                         break;
414                                                 case 'v':
415                                                         iap.attr|=ATOM_ATTR_VA;
416                                                         break;
417                                                 case 'f':
418                                                         iap.attr|=ATOM_ATTR_FP;
419                                                         break;
420                                                 case '1':
421                                                         iap.attr|=ATOM_ATTR_1BP;
422                                                         break;
423                                                 case '2':
424                                                         iap.attr|=ATOM_ATTR_2BP;
425                                                         break;
426                                                 case '3':
427                                                         iap.attr|=ATOM_ATTR_3BP;
428                                                         break;
429                                                 default:
430                                                         break;
431                                         }
432                                 }
433                                 switch(word[7][0]) {
434                                         // insertion types
435                                         case 'p':
436                                                 iap.type=INS_POS;
437                                                 iap.x0=atof(word[8]);
438                                                 iap.y0=atof(word[9]);
439                                                 iap.z0=atof(word[10]);
440                                                 break;
441                                         case 'r':
442                                                 if(word[8][0]=='t') {
443                                                         iap.type=INS_TOTAL;
444                                                         iap.cr=atof(word[9]);
445                                                 }
446                                                 else {
447                                                         iap.type=INS_REGION;
448                                                         iap.x0=atof(word[8]);
449                                                         iap.y0=atof(word[9]);
450                                                         iap.z0=atof(word[10]);
451                                                         iap.x1=atof(word[11]);
452                                                         iap.y1=atof(word[12]);
453                                                         iap.z1=atof(word[13]);
454                                                         iap.cr=atof(word[14]);
455                                                 }
456                                         default:
457                                                 break;
458                                 }
459                                 add_stage(mdrun,STAGE_INSERT_ATOMS,&iap);
460                         }
461
462
463                         // HERE WE GO ...
464
465                         else if(!strncmp(word[1],"ins_m_atoms",11)) {
466                                 imp.element1=atoi(word[2]);
467                                 imp.element2=atoi(word[3]);
468                                 imp.amount1=atoi(word[4]);
469                                 imp.amount2=atoi(word[5]);
470                                 imp.brand1=atoi(word[6]);
471                                 imp.brand2=atoi(word[7]);
472                                 imp.crmin=atof(word[8]);
473                                 imp.crmax=atof(word[9]);
474                                 /* do this later ...
475                                 for(i=0;i<strlen(word[8]);i++) {
476                                         switch(word[8][i]) {
477                                                 case 'b':
478                                                         imp.attr|=ATOM_ATTR_VB;
479                                                         break;
480                                                 case 'h':
481                                                         imp.attr|=ATOM_ATTR_HB;
482                                                         break;
483                                                 case 'v':
484                                                         imp.attr|=ATOM_ATTR_VA;
485                                                         break;
486                                                 case 'f':
487                                                         imp.attr|=ATOM_ATTR_FP;
488                                                         break;
489                                                 case '1':
490                                                         imp.attr|=ATOM_ATTR_1BP;
491                                                         break;
492                                                 case '2':
493                                                         imp.attr|=ATOM_ATTR_2BP;
494                                                         break;
495                                                 case '3':
496                                                         imp.attr|=ATOM_ATTR_3BP;
497                                                         break;
498                                                 default:
499                                                         break;
500                                         }
501                                 }
502                                 */
503                                 imp.attr1=ATOM_ATTR_HB|ATOM_ATTR_VA|ATOM_ATTR_1BP|ATOM_ATTR_2BP|ATOM_ATTR_3BP|ATOM_ATTR_FP;
504                                 imp.attr2=ATOM_ATTR_HB|ATOM_ATTR_VA|ATOM_ATTR_1BP|ATOM_ATTR_2BP|ATOM_ATTR_3BP|ATOM_ATTR_FP;
505                                 add_stage(mdrun,STAGE_INSERT_MIXED_ATOMS,&imp);
506                         }
507
508
509
510
511
512                         else if(!strncmp(word[1],"continue",8)) {
513                                 cp.runs=atoi(word[2]);
514                                 add_stage(mdrun,STAGE_CONTINUE,&cp);
515                         }
516                         else if(!strncmp(word[1],"anneal",6)) {
517                                 ap.count=0;
518                                 ap.runs=atoi(word[2]);
519                                 ap.dt=atof(word[3]);
520                                 add_stage(mdrun,STAGE_ANNEAL,&ap);
521                         }
522                         else if(!strncmp(word[1],"set_temp",8)) {
523                                 if(word[2][0]=='c') {
524                                         stp.type=SET_TEMP_CURRENT;
525                                         stp.val=0.0;
526                                 }
527                                 else {
528                                         stp.type=SET_TEMP_VALUE;
529                                         stp.val=atof(word[2]);
530                                 }
531                                 add_stage(mdrun,STAGE_SET_TEMP,&stp);
532                         }
533                         else if(!strncmp(word[1],"set_timestep",12)) {
534                                 stsp.tau=atof(word[2]);
535                                 add_stage(mdrun,STAGE_SET_TIMESTEP,&stsp);
536                         }
537                         else {
538                                 printf("%s unknown stage type: %s\n",
539                                        ME,word[1]);
540                                 return -1;
541                         }
542                 }
543                 else {
544                         printf("%s unknown keyword '%s', skipped!\n",
545                                ME,word[0]);
546                         continue;
547                 }
548         }
549
550         /* close file */
551         close(fd);
552
553         return 0;
554 }
555
556 int check_pressure(t_moldyn *moldyn,t_mdrun *mdrun) {
557
558         double delta;
559
560         if(!(mdrun->sattr&SATTR_PRELAX)) {
561                 return TRUE;
562         }
563
564         delta=moldyn->p_avg-moldyn->p_ref;
565
566         if(delta<0)
567                 delta=-delta;
568
569         if(delta>mdrun->dp)
570                 return FALSE;
571
572         return TRUE;
573 }
574
575 int check_temperature(t_moldyn *moldyn,t_mdrun *mdrun) {
576
577         double delta;
578
579         if(!(mdrun->sattr&SATTR_TRELAX))
580                 return TRUE;
581
582         delta=moldyn->t_avg-moldyn->t_ref;
583
584         if(delta<0)
585                 delta=-delta;
586
587         if(delta>mdrun->dt)
588                 return FALSE;
589
590         return TRUE;
591 }
592
593 int displace_atom(t_moldyn *moldyn,t_mdrun *mdrun) {
594
595         t_displace_atom_params *dap;
596         t_stage *stage;
597         t_atom *atom;
598
599         stage=mdrun->stage.current->data;
600         dap=stage->params;
601
602         atom=&(moldyn->atom[dap->nr]);
603         atom->r.x+=dap->dx;
604         atom->r.y+=dap->dy;
605         atom->r.z+=dap->dz;
606
607         return 0;
608 }
609
610 int insert_atoms(t_moldyn *moldyn,t_mdrun *mdrun) {
611
612         t_insert_atoms_params *iap;
613         t_stage *stage;
614         t_atom *atom;
615         t_3dvec r,v,dist;
616         double d,dmin,o;
617         int cnt,i;
618         double x,y,z;
619         double x0,y0,z0;
620         u8 cr_check,run;
621         
622         stage=mdrun->stage.current->data;
623         iap=stage->params;
624
625         cr_check=FALSE;
626
627         v.x=0.0; v.y=0.0; v.z=0.0;
628         x=0; y=0; z=0;
629         o=0; dmin=0;
630
631         switch(mdrun->lattice) {
632                 case CUBIC:
633                         o=0.5*mdrun->lc;
634                         break;
635                 case FCC:
636                         o=0.25*mdrun->lc;
637                         break;
638                 case DIAMOND:
639                 case ZINCBLENDE:
640                         o=0.125*mdrun->lc;
641                         break;
642                 default:
643                         break;
644         }
645
646         switch(iap->type) {
647                 case INS_TOTAL:
648                         x=moldyn->dim.x;
649                         x0=-x/2.0;
650                         y=moldyn->dim.y;
651                         y0=-y/2.0;
652                         z=moldyn->dim.z;
653                         z0=-z/2.0;
654                         cr_check=TRUE;
655                         break;
656                 case INS_REGION:
657                         x=iap->x1-iap->x0;
658                         x0=iap->x0;
659                         y=iap->y1-iap->y0;
660                         y0=iap->y0;
661                         z=iap->z1-iap->z0;
662                         z0=iap->z0;
663                         cr_check=TRUE;
664                         break;
665                 case INS_POS:
666                         x0=iap->x0;
667                         y0=iap->y0;
668                         z0=iap->z0;
669                         cr_check=FALSE;
670                         break;
671                 default:
672                         printf("%s unknown insertion mode: %02x\n",
673                                ME,iap->type);
674                         return -1;
675         }
676
677         cnt=0;
678         while(cnt<iap->ins_atoms) {
679                 run=1;
680                 while(run) {
681                         if(iap->type!=INS_POS) {
682                                 r.x=rand_get_double(&(moldyn->random))*x;
683                                 r.y=rand_get_double(&(moldyn->random))*y;
684                                 r.z=rand_get_double(&(moldyn->random))*z;
685                         }
686                         else {
687                                 r.x=0.0;
688                                 r.y=0.0;
689                                 r.z=0.0;
690                         }
691                         r.x+=x0;
692                         r.y+=y0;
693                         r.z+=z0;
694                         // offset
695                         if(iap->type!=INS_TOTAL) {
696                                 r.x+=o;
697                                 r.y+=o;
698                                 r.z+=o;
699                         }
700                         run=0;
701                         if(cr_check==TRUE) {
702                                 dmin=1000;      // for sure too high!
703                                 for(i=0;i<moldyn->count;i++) {
704                                         atom=&(moldyn->atom[i]);
705                                         v3_sub(&dist,&(atom->r),&r);
706                                         check_per_bound(moldyn,&dist);
707                                         d=v3_absolute_square(&dist);
708                                         if(d<(iap->cr*iap->cr)) {
709                                                 run=1;
710                                                 break;
711                                         }
712                                         if(d<dmin)
713                                                 dmin=d;
714                                 }
715                         }
716                 }
717                 add_atom(moldyn,iap->element,pse_mass[iap->element],
718                          iap->brand,iap->attr,&r,&v);
719                 printf("%s atom inserted (%d/%d): %f %f %f\n",
720                        ME,(iap->cnt_steps+1)*iap->ins_atoms,
721                        iap->ins_steps*iap->ins_atoms,r.x,r.y,r.z);
722                 printf("  -> d2 = %f/%f\n",dmin,iap->cr*iap->cr);
723                 cnt+=1;
724         }
725
726         return 0;
727 }
728
729 int insert_mixed_atoms(t_moldyn *moldyn,t_mdrun *mdrun) {
730
731         t_stage *stage;
732         t_insert_mixed_atoms_params *imp;
733         t_atom *atom;
734         double x,x0,y,y0,z,z0;
735         double dmin,d,cmin,cmax;
736         u8 retry;
737         t_3dvec r,v,dist;
738         int i;
739         
740
741         stage=mdrun->stage.current->data;
742         imp=stage->params;
743
744         x=moldyn->dim.x;
745         x0=-x/2.0;
746         y=moldyn->dim.y;
747         y0=-y/2.0;
748         z=moldyn->dim.z;
749         z0=-z/2.0;
750
751         v.x=0.0;
752         v.y=0.0;
753         v.z=0.0;
754
755         cmin=imp->crmin*imp->crmin;
756         cmax=imp->crmax*imp->crmax;
757
758         while(imp->amount1|imp->amount2) {
759                 if(imp->amount1) {
760                         retry=1;
761                         while(retry) {
762                                 retry=0;
763                                 r.x=rand_get_double(&(moldyn->random))*x;
764                                 r.y=rand_get_double(&(moldyn->random))*y;
765                                 r.z=rand_get_double(&(moldyn->random))*z;
766                                 r.x+=x0;
767                                 r.y+=y0;
768                                 r.z+=z0;
769                                 dmin=1000.0;    // for sure too high!
770                                 for(i=0;i<moldyn->count;i++) {
771                                         atom=&(moldyn->atom[i]);
772                                         v3_sub(&dist,&(atom->r),&r);
773                                         check_per_bound(moldyn,&dist);
774                                         d=v3_absolute_square(&dist);
775                                         if(d<cmin) {
776                                                 retry=1;
777                                                 break;
778                                         }
779                                         if(d<dmin)
780                                                 dmin=d;
781                                 }
782                                 if(dmin!=1000.0)
783                                         if(dmin>cmax)
784                                                 retry=1;
785                         }
786                         add_atom(moldyn,imp->element1,pse_mass[imp->element1],
787                                  imp->brand1,imp->attr1,&r,&v);
788                         printf("%s (mixed) atom inserted (%d): %f %f %f\n",
789                                ME,imp->amount1,r.x,r.y,r.z);
790                         printf("  -> d2 = %f/%f/%f\n",dmin,cmin,cmax);
791                         imp->amount1-=1;
792                 }
793                 if(imp->amount2) {
794                         retry=1;
795                         while(retry) {
796                                 retry=0;
797                                 r.x=rand_get_double(&(moldyn->random))*x;
798                                 r.y=rand_get_double(&(moldyn->random))*y;
799                                 r.z=rand_get_double(&(moldyn->random))*z;
800                                 r.x+=x0;
801                                 r.y+=y0;
802                                 r.z+=z0;
803                                 dmin=1000.0;    // for sure too high!
804                                 for(i=0;i<moldyn->count;i++) {
805                                         atom=&(moldyn->atom[i]);
806                                         v3_sub(&dist,&(atom->r),&r);
807                                         check_per_bound(moldyn,&dist);
808                                         d=v3_absolute_square(&dist);
809                                         if(d<cmin) {
810                                                 retry=1;
811                                                 break;
812                                         }
813                                         if(d<dmin)
814                                                 dmin=d;
815                                 }
816                                 if(dmin!=1000.0)
817                                         if(dmin>cmax)
818                                                 retry=1;
819                         }
820                         add_atom(moldyn,imp->element2,pse_mass[imp->element2],
821                                  imp->brand2,imp->attr2,&r,&v);
822                         printf("%s (mixed) atom inserted (%d): %f %f %f\n",
823                                ME,imp->amount2,r.x,r.y,r.z);
824                         printf("  -> d2 = %f/%f/%f\n",dmin,cmin,cmax);
825                         imp->amount2-=1;
826                 }
827         }
828
829         return 0;
830 }
831
832 int chaatr(t_moldyn *moldyn,t_mdrun *mdrun) {
833
834         t_stage *stage;
835         t_chaattr_params *cap;
836         t_atom *atom;
837         int i;
838
839         stage=mdrun->stage.current->data;
840         cap=stage->params;
841
842         for(i=0;i<moldyn->count;i++) {
843                 atom=&(moldyn->atom[i]);
844                 if(cap->type&CHAATTR_ELEMENT) {
845                         if(cap->element!=atom->element)
846                                 continue;
847                 }
848                 if(cap->type&CHAATTR_REGION) {
849                         if(cap->x0<atom->r.x)
850                                 continue;
851                         if(cap->y0<atom->r.y)
852                                 continue;
853                         if(cap->z0<atom->r.z)
854                                 continue;
855                         if(cap->x1>atom->r.x)
856                                 continue;
857                         if(cap->y1>atom->r.y)
858                                 continue;
859                         if(cap->z1>atom->r.z)
860                                 continue;
861                 }
862                 atom->attr=cap->attr;
863         }
864
865         return 0;
866 }
867
868 int chsattr(t_moldyn *moldyn,t_mdrun *mdrun) {
869
870         t_stage *stage;
871         t_chsattr_params *csp;
872
873         stage=mdrun->stage.current->data;
874         csp=stage->params;
875
876         if(csp->type&CHSATTR_PCTRL) {
877                 if(csp->ptau>0)
878                         set_p_scale(moldyn,P_SCALE_BERENDSEN,csp->ptau);
879                 else
880                         set_p_scale(moldyn,P_SCALE_BERENDSEN,csp->ptau);
881         }
882         if(csp->type&CHSATTR_TCTRL) {
883                 if(csp->ttau>0)
884                         set_t_scale(moldyn,T_SCALE_BERENDSEN,csp->ttau);
885                 else
886                         set_t_scale(moldyn,T_SCALE_BERENDSEN,csp->ttau);
887         }
888         if(csp->type&CHSATTR_PRELAX) {
889                 if(csp->dp<0)
890                         mdrun->sattr&=(~(SATTR_PRELAX));
891                 else
892                         mdrun->sattr|=SATTR_PRELAX;
893                 mdrun->dp=csp->dp;
894         }
895         if(csp->type&CHSATTR_TRELAX) {
896                 if(csp->dt<0)
897                         mdrun->sattr&=(~(SATTR_TRELAX));
898                 else
899                         mdrun->sattr|=SATTR_TRELAX;
900                 mdrun->dt=csp->dt;
901         }
902         if(csp->type&CHSATTR_AVGRST) {
903                 if(csp->avgrst)
904                         mdrun->sattr|=SATTR_AVGRST;
905                 else
906                         mdrun->sattr&=(~(SATTR_AVGRST));
907         }
908         if(csp->type&CHSATTR_RSTEPS) {
909                 mdrun->relax_steps=csp->rsteps;
910         }
911
912         return 0;
913 }
914
915 #define stage_print(m)  if(!(stage->executed)) \
916                                 printf("%s",m)
917
918 int mdrun_hook(void *ptr1,void *ptr2) {
919
920         t_moldyn *moldyn;
921         t_mdrun *mdrun;
922         t_stage *stage;
923         t_list *sl;
924         int steps;
925         u8 change_stage;
926
927         t_insert_atoms_params *iap;
928         t_insert_mixed_atoms_params *imp;
929         t_continue_params *cp;
930         t_anneal_params *ap;
931         t_set_temp_params *stp;
932         t_set_timestep_params *stsp;
933
934         moldyn=ptr1;
935         mdrun=ptr2;
936
937         sl=&(mdrun->stage);
938
939         change_stage=FALSE;
940
941         /* return immediately if there are no more stage */
942         if(sl->current==NULL)
943                 return 0;
944
945         /* get stage description */
946         stage=sl->current->data;
947
948         /* steps in next schedule */
949         steps=mdrun->relax_steps;
950
951         /* check whether relaxation steps are necessary */
952         if((check_pressure(moldyn,mdrun)==TRUE)&\
953            (check_temperature(moldyn,mdrun)==TRUE)) {
954         
955                 /* be verbose */
956                 stage_print("\n###########################\n");
957                 stage_print("# [mdrun] executing stage #\n");
958                 stage_print("###########################\n\n");
959                 
960                 /* stage specific stuff */
961                 switch(stage->type) {
962                         case STAGE_DISPLACE_ATOM:
963                                 stage_print("  -> displace atom\n\n");
964                                 displace_atom(moldyn,mdrun);
965                                 change_stage=TRUE;
966                                 break;
967                         case STAGE_INSERT_ATOMS:
968                                 stage_print("  -> insert atoms\n\n");
969                                 iap=stage->params;
970                                 if(iap->cnt_steps==iap->ins_steps) {
971                                         change_stage=TRUE;
972                                         break;
973                                 }
974                                 insert_atoms(moldyn,mdrun);
975                                 iap->cnt_steps+=1;
976                                 break;
977
978
979
980                         case STAGE_INSERT_MIXED_ATOMS:
981                                 stage_print("  -> insert mixed atoms\n\n");
982                                 imp=stage->params;
983                                 insert_mixed_atoms(moldyn,mdrun);
984                                 change_stage=TRUE;
985                                 break;
986
987
988
989                         case STAGE_CONTINUE:
990                                 stage_print("  -> continue\n\n");
991                                 if(stage->executed==TRUE) {
992                                         change_stage=TRUE;
993                                         break;
994                                 }
995                                 cp=stage->params;
996                                 steps=cp->runs;
997                                 break;
998                         case STAGE_ANNEAL:
999                                 stage_print("  -> anneal\n\n");
1000                                 ap=stage->params;
1001                                 if(ap->count==ap->runs) {
1002                                         change_stage=TRUE;
1003                                         break;
1004                                 }
1005                                 if(moldyn->t_ref+ap->dt>=0.0)
1006                                         set_temperature(moldyn,
1007                                                         moldyn->t_ref+ap->dt);
1008                                 ap->count+=1;
1009                                 break;
1010                         case STAGE_CHAATTR:
1011                                 stage_print("  -> change atom attributes\n\n");
1012                                 chaatr(moldyn,mdrun);
1013                                 change_stage=TRUE;
1014                                 break;
1015                         case STAGE_CHSATTR:
1016                                 stage_print("  -> change sys attributes\n\n");
1017                                 chsattr(moldyn,mdrun);
1018                                 change_stage=TRUE;
1019                                 break;
1020                         case STAGE_SET_TEMP:
1021                                 stage_print("  -> set temperature\n\n");
1022                                 stp=stage->params;
1023                                 if(stp->type&SET_TEMP_CURRENT) {
1024                                         set_temperature(moldyn,moldyn->t_avg);
1025                                 }
1026                                 else {
1027                                         set_temperature(moldyn,stp->val);
1028                                 }
1029                                 change_stage=TRUE;
1030                                 break;
1031                         case STAGE_SET_TIMESTEP:
1032                                 stage_print("  -> set timestep\n\n");
1033                                 stsp=stage->params;
1034                                 mdrun->timestep=stsp->tau;
1035                                 change_stage=TRUE;
1036                                 break;
1037                         default:
1038                                 printf("%s unknwon stage type\n",ME);
1039                                 break;
1040                 }
1041         
1042                 /* mark as executed */
1043                 stage->executed=TRUE;
1044         
1045                 /* change state */
1046                 if(change_stage==TRUE) {
1047                         printf("%s finished stage\n",ME);
1048                         if(list_next_f(sl)==L_NO_NEXT_ELEMENT) {
1049                                 printf("%s no more stages\n",ME);
1050                                 return 0;
1051                         }
1052                         steps=0;
1053                 }
1054
1055         }
1056         else {
1057
1058                 /* averages */
1059                 if(mdrun->sattr&SATTR_AVGRST)
1060                         average_reset(moldyn);
1061
1062         }
1063
1064         /* continue simulation */
1065         moldyn_add_schedule(moldyn,steps,mdrun->timestep);
1066
1067         return 0;
1068 }
1069
1070 int main(int argc,char **argv) {
1071
1072         t_mdrun mdrun;
1073         t_moldyn moldyn;
1074         t_3dvec o;
1075
1076         /* clear structs */
1077         memset(&mdrun,0,sizeof(t_mdrun));
1078         memset(&moldyn,0,sizeof(t_moldyn));
1079
1080         /* parse arguments */
1081         if(mdrun_parse_argv(&mdrun,argc,argv)<0)
1082                 return -1;
1083
1084         /* initialize list system */
1085         list_init_f(&(mdrun.stage));
1086
1087         /* parse config file */
1088         mdrun_parse_config(&mdrun);
1089
1090         /* reset the stage list */
1091         list_reset_f(&(mdrun.stage));
1092
1093         /* sanity check! */
1094
1095         /* prepare simulation */
1096
1097         if(mdrun.continue_file[0]) {
1098                 // read the save file
1099                 moldyn_read_save_file(&moldyn,mdrun.continue_file);
1100                 // manualaadjusting some stuff
1101                 moldyn.argc=argc;
1102                 moldyn.args=argv;
1103                 rand_init(&(moldyn.random),NULL,1);
1104                 moldyn.random.status|=RAND_STAT_VERBOSE;
1105         }
1106         else {
1107                 moldyn_init(&moldyn,argc,argv);
1108         }
1109         
1110         if(set_int_alg(&moldyn,mdrun.intalgo)<0)
1111                 return -1;
1112
1113         /* potential */
1114         set_cutoff(&moldyn,mdrun.cutoff);
1115         if(set_potential(&moldyn,mdrun.potential)<0)
1116                 return -1;
1117         switch(mdrun.potential) {
1118                 case MOLDYN_POTENTIAL_AM:
1119                         albe_mult_set_params(&moldyn,
1120                                              mdrun.element1,
1121                                              mdrun.element2);
1122                         break;
1123                 case MOLDYN_POTENTIAL_TM:
1124                         tersoff_mult_set_params(&moldyn,
1125                                                 mdrun.element1,
1126                                                 mdrun.element2);
1127                         break;
1128                 case MOLDYN_POTENTIAL_HO:
1129                         harmonic_oscillator_set_params(&moldyn,mdrun.element1);
1130                         break;
1131                 case MOLDYN_POTENTIAL_LJ:
1132                         lennard_jones_set_params(&moldyn,mdrun.element1);
1133                         break;
1134                 default:
1135                         printf("%s unknown potential: %02x\n",
1136                                ME,mdrun.potential);
1137                         return -1;
1138         }
1139
1140         /* if it is a continue run, reset schedule and skip lattice init */
1141         if(mdrun.continue_file[0]) {
1142                 memset(&(moldyn.schedule),0,sizeof(t_moldyn_schedule));
1143                 goto addsched;
1144         }
1145
1146         /* initial lattice and dimensions */
1147         set_dim(&moldyn,mdrun.dim.x,mdrun.dim.y,mdrun.dim.z,mdrun.vis);
1148         set_pbc(&moldyn,mdrun.pbcx,mdrun.pbcy,mdrun.pbcz);
1149         switch(mdrun.lattice) {
1150                 case FCC:
1151                         create_lattice(&moldyn,FCC,mdrun.lc,mdrun.element1,
1152                                        mdrun.m1,DEFAULT_ATOM_ATTR,0,mdrun.lx,
1153                                        mdrun.ly,mdrun.lz,NULL);
1154                         break;
1155                 case DIAMOND:
1156                         create_lattice(&moldyn,DIAMOND,mdrun.lc,mdrun.element1,
1157                                        mdrun.m1,DEFAULT_ATOM_ATTR,0,mdrun.lx,
1158                                        mdrun.ly,mdrun.lz,NULL);
1159                         break;
1160                 case ZINCBLENDE:
1161                         o.x=0.5*0.25*mdrun.lc; o.y=o.x; o.z=o.x;
1162                         create_lattice(&moldyn,FCC,mdrun.lc,mdrun.element1,
1163                                        mdrun.m1,DEFAULT_ATOM_ATTR,0,mdrun.lx,
1164                                        mdrun.ly,mdrun.lz,&o);
1165                         o.x+=0.25*mdrun.lc; o.y=o.x; o.z=o.x;
1166                         create_lattice(&moldyn,FCC,mdrun.lc,mdrun.element2,
1167                                        mdrun.m2,DEFAULT_ATOM_ATTR,1,mdrun.lx,
1168                                        mdrun.ly,mdrun.lz,&o);
1169                         break;
1170                 case NONE:
1171                         set_nn_dist(&moldyn,mdrun.nnd);
1172                         break;
1173                 default:
1174                         printf("%s unknown lattice type: %02x\n",
1175                                ME,mdrun.lattice);
1176                         return -1;
1177         }
1178         moldyn_bc_check(&moldyn);
1179
1180         /* temperature and pressure */
1181         set_temperature(&moldyn,mdrun.temperature);
1182         set_pressure(&moldyn,mdrun.pressure);
1183         thermal_init(&moldyn,TRUE);
1184
1185 addsched:
1186         /* first schedule */
1187         moldyn_add_schedule(&moldyn,mdrun.prerun,mdrun.timestep);
1188
1189         /* log */
1190         moldyn_set_log_dir(&moldyn,mdrun.sdir);
1191         moldyn_set_report(&moldyn,"CHANGE ME","CHANGE ME TOO");
1192         if(mdrun.elog)
1193                 moldyn_set_log(&moldyn,LOG_TOTAL_ENERGY,mdrun.elog);
1194         if(mdrun.tlog)
1195                 moldyn_set_log(&moldyn,LOG_TEMPERATURE,mdrun.tlog);
1196         if(mdrun.plog)
1197                 moldyn_set_log(&moldyn,LOG_PRESSURE,mdrun.plog);
1198         if(mdrun.vlog)
1199                 moldyn_set_log(&moldyn,LOG_VOLUME,mdrun.vlog);
1200         if(mdrun.visualize)
1201                 moldyn_set_log(&moldyn,VISUAL_STEP,mdrun.visualize);
1202         if(mdrun.save)
1203                 moldyn_set_log(&moldyn,SAVE_STEP,mdrun.save);
1204         moldyn_set_log(&moldyn,CREATE_REPORT,0);
1205         set_avg_skip(&moldyn,mdrun.avgskip);
1206
1207         /* prepare the hook function */
1208         moldyn_set_schedule_hook(&moldyn,&mdrun_hook,&mdrun);
1209
1210         /* run the simulation */
1211         moldyn_integrate(&moldyn);
1212
1213         /* shutdown */
1214         moldyn_shutdown(&moldyn);
1215         del_stages(&mdrun);
1216         list_destroy_f(&(mdrun.stage));
1217
1218         return 0;
1219 }