added interval for anneal stage
[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                                 ap.interval=atoi(word[4]);
521                                 add_stage(mdrun,STAGE_ANNEAL,&ap);
522                         }
523                         else if(!strncmp(word[1],"set_temp",8)) {
524                                 if(word[2][0]=='c') {
525                                         stp.type=SET_TEMP_CURRENT;
526                                         stp.val=0.0;
527                                 }
528                                 else {
529                                         stp.type=SET_TEMP_VALUE;
530                                         stp.val=atof(word[2]);
531                                 }
532                                 add_stage(mdrun,STAGE_SET_TEMP,&stp);
533                         }
534                         else if(!strncmp(word[1],"set_timestep",12)) {
535                                 stsp.tau=atof(word[2]);
536                                 add_stage(mdrun,STAGE_SET_TIMESTEP,&stsp);
537                         }
538                         else {
539                                 printf("%s unknown stage type: %s\n",
540                                        ME,word[1]);
541                                 return -1;
542                         }
543                 }
544                 else {
545                         printf("%s unknown keyword '%s', skipped!\n",
546                                ME,word[0]);
547                         continue;
548                 }
549         }
550
551         /* close file */
552         close(fd);
553
554         return 0;
555 }
556
557 int check_pressure(t_moldyn *moldyn,t_mdrun *mdrun) {
558
559         double delta;
560
561         if(!(mdrun->sattr&SATTR_PRELAX)) {
562                 return TRUE;
563         }
564
565         delta=moldyn->p_avg-moldyn->p_ref;
566
567         if(delta<0)
568                 delta=-delta;
569
570         if(delta>mdrun->dp)
571                 return FALSE;
572
573         return TRUE;
574 }
575
576 int check_temperature(t_moldyn *moldyn,t_mdrun *mdrun) {
577
578         double delta;
579
580         if(!(mdrun->sattr&SATTR_TRELAX))
581                 return TRUE;
582
583         delta=moldyn->t_avg-moldyn->t_ref;
584
585         if(delta<0)
586                 delta=-delta;
587
588         if(delta>mdrun->dt)
589                 return FALSE;
590
591         return TRUE;
592 }
593
594 int displace_atom(t_moldyn *moldyn,t_mdrun *mdrun) {
595
596         t_displace_atom_params *dap;
597         t_stage *stage;
598         t_atom *atom;
599
600         stage=mdrun->stage.current->data;
601         dap=stage->params;
602
603         atom=&(moldyn->atom[dap->nr]);
604         atom->r.x+=dap->dx;
605         atom->r.y+=dap->dy;
606         atom->r.z+=dap->dz;
607
608         return 0;
609 }
610
611 int insert_atoms(t_moldyn *moldyn,t_mdrun *mdrun) {
612
613         t_insert_atoms_params *iap;
614         t_stage *stage;
615         t_atom *atom;
616         t_3dvec r,v,dist;
617         double d,dmin,o;
618         int cnt,i;
619         double x,y,z;
620         double x0,y0,z0;
621         u8 cr_check,run;
622         
623         stage=mdrun->stage.current->data;
624         iap=stage->params;
625
626         cr_check=FALSE;
627
628         v.x=0.0; v.y=0.0; v.z=0.0;
629         x=0; y=0; z=0;
630         o=0; dmin=0;
631
632         switch(mdrun->lattice) {
633                 case CUBIC:
634                         o=0.5*mdrun->lc;
635                         break;
636                 case FCC:
637                         o=0.25*mdrun->lc;
638                         break;
639                 case DIAMOND:
640                 case ZINCBLENDE:
641                         o=0.125*mdrun->lc;
642                         break;
643                 default:
644                         break;
645         }
646
647         switch(iap->type) {
648                 case INS_TOTAL:
649                         x=moldyn->dim.x;
650                         x0=-x/2.0;
651                         y=moldyn->dim.y;
652                         y0=-y/2.0;
653                         z=moldyn->dim.z;
654                         z0=-z/2.0;
655                         cr_check=TRUE;
656                         break;
657                 case INS_REGION:
658                         x=iap->x1-iap->x0;
659                         x0=iap->x0;
660                         y=iap->y1-iap->y0;
661                         y0=iap->y0;
662                         z=iap->z1-iap->z0;
663                         z0=iap->z0;
664                         cr_check=TRUE;
665                         break;
666                 case INS_POS:
667                         x0=iap->x0;
668                         y0=iap->y0;
669                         z0=iap->z0;
670                         cr_check=FALSE;
671                         break;
672                 default:
673                         printf("%s unknown insertion mode: %02x\n",
674                                ME,iap->type);
675                         return -1;
676         }
677
678         cnt=0;
679         while(cnt<iap->ins_atoms) {
680                 run=1;
681                 while(run) {
682                         if(iap->type!=INS_POS) {
683                                 r.x=rand_get_double(&(moldyn->random))*x;
684                                 r.y=rand_get_double(&(moldyn->random))*y;
685                                 r.z=rand_get_double(&(moldyn->random))*z;
686                         }
687                         else {
688                                 r.x=0.0;
689                                 r.y=0.0;
690                                 r.z=0.0;
691                         }
692                         r.x+=x0;
693                         r.y+=y0;
694                         r.z+=z0;
695                         // offset
696                         if(iap->type!=INS_TOTAL) {
697                                 r.x+=o;
698                                 r.y+=o;
699                                 r.z+=o;
700                         }
701                         run=0;
702                         if(cr_check==TRUE) {
703                                 dmin=1000;      // for sure too high!
704                                 for(i=0;i<moldyn->count;i++) {
705                                         atom=&(moldyn->atom[i]);
706                                         v3_sub(&dist,&(atom->r),&r);
707                                         check_per_bound(moldyn,&dist);
708                                         d=v3_absolute_square(&dist);
709                                         if(d<(iap->cr*iap->cr)) {
710                                                 run=1;
711                                                 break;
712                                         }
713                                         if(d<dmin)
714                                                 dmin=d;
715                                 }
716                         }
717                 }
718                 add_atom(moldyn,iap->element,pse_mass[iap->element],
719                          iap->brand,iap->attr,&r,&v);
720                 printf("%s atom inserted (%d/%d): %f %f %f\n",
721                        ME,(iap->cnt_steps+1)*iap->ins_atoms,
722                        iap->ins_steps*iap->ins_atoms,r.x,r.y,r.z);
723                 printf("  -> d2 = %f/%f\n",dmin,iap->cr*iap->cr);
724                 cnt+=1;
725         }
726
727         return 0;
728 }
729
730 int insert_mixed_atoms(t_moldyn *moldyn,t_mdrun *mdrun) {
731
732         t_stage *stage;
733         t_insert_mixed_atoms_params *imp;
734         t_atom *atom;
735         double x,x0,y,y0,z,z0;
736         double dmin,d,cmin,cmax;
737         u8 retry;
738         t_3dvec r,v,dist;
739         int i;
740         
741
742         stage=mdrun->stage.current->data;
743         imp=stage->params;
744
745         x=moldyn->dim.x;
746         x0=-x/2.0;
747         y=moldyn->dim.y;
748         y0=-y/2.0;
749         z=moldyn->dim.z;
750         z0=-z/2.0;
751
752         v.x=0.0;
753         v.y=0.0;
754         v.z=0.0;
755
756         cmin=imp->crmin*imp->crmin;
757         cmax=imp->crmax*imp->crmax;
758
759         while(imp->amount1|imp->amount2) {
760                 if(imp->amount1) {
761                         retry=1;
762                         while(retry) {
763                                 retry=0;
764                                 r.x=rand_get_double(&(moldyn->random))*x;
765                                 r.y=rand_get_double(&(moldyn->random))*y;
766                                 r.z=rand_get_double(&(moldyn->random))*z;
767                                 r.x+=x0;
768                                 r.y+=y0;
769                                 r.z+=z0;
770                                 dmin=1000.0;    // for sure too high!
771                                 for(i=0;i<moldyn->count;i++) {
772                                         atom=&(moldyn->atom[i]);
773                                         v3_sub(&dist,&(atom->r),&r);
774                                         check_per_bound(moldyn,&dist);
775                                         d=v3_absolute_square(&dist);
776                                         if(d<cmin) {
777                                                 retry=1;
778                                                 break;
779                                         }
780                                         if(d<dmin)
781                                                 dmin=d;
782                                 }
783                                 if(dmin!=1000.0)
784                                         if(dmin>cmax)
785                                                 retry=1;
786                         }
787                         add_atom(moldyn,imp->element1,pse_mass[imp->element1],
788                                  imp->brand1,imp->attr1,&r,&v);
789                         printf("%s (mixed) atom inserted (%d): %f %f %f\n",
790                                ME,imp->amount1,r.x,r.y,r.z);
791                         printf("  -> d2 = %f/%f/%f\n",dmin,cmin,cmax);
792                         imp->amount1-=1;
793                 }
794                 if(imp->amount2) {
795                         retry=1;
796                         while(retry) {
797                                 retry=0;
798                                 r.x=rand_get_double(&(moldyn->random))*x;
799                                 r.y=rand_get_double(&(moldyn->random))*y;
800                                 r.z=rand_get_double(&(moldyn->random))*z;
801                                 r.x+=x0;
802                                 r.y+=y0;
803                                 r.z+=z0;
804                                 dmin=1000.0;    // for sure too high!
805                                 for(i=0;i<moldyn->count;i++) {
806                                         atom=&(moldyn->atom[i]);
807                                         v3_sub(&dist,&(atom->r),&r);
808                                         check_per_bound(moldyn,&dist);
809                                         d=v3_absolute_square(&dist);
810                                         if(d<cmin) {
811                                                 retry=1;
812                                                 break;
813                                         }
814                                         if(d<dmin)
815                                                 dmin=d;
816                                 }
817                                 if(dmin!=1000.0)
818                                         if(dmin>cmax)
819                                                 retry=1;
820                         }
821                         add_atom(moldyn,imp->element2,pse_mass[imp->element2],
822                                  imp->brand2,imp->attr2,&r,&v);
823                         printf("%s (mixed) atom inserted (%d): %f %f %f\n",
824                                ME,imp->amount2,r.x,r.y,r.z);
825                         printf("  -> d2 = %f/%f/%f\n",dmin,cmin,cmax);
826                         imp->amount2-=1;
827                 }
828         }
829
830         return 0;
831 }
832
833 int chaatr(t_moldyn *moldyn,t_mdrun *mdrun) {
834
835         t_stage *stage;
836         t_chaattr_params *cap;
837         t_atom *atom;
838         int i;
839
840         stage=mdrun->stage.current->data;
841         cap=stage->params;
842
843         for(i=0;i<moldyn->count;i++) {
844                 atom=&(moldyn->atom[i]);
845                 if(cap->type&CHAATTR_ELEMENT) {
846                         if(cap->element!=atom->element)
847                                 continue;
848                 }
849                 if(cap->type&CHAATTR_REGION) {
850                         if(cap->x0<atom->r.x)
851                                 continue;
852                         if(cap->y0<atom->r.y)
853                                 continue;
854                         if(cap->z0<atom->r.z)
855                                 continue;
856                         if(cap->x1>atom->r.x)
857                                 continue;
858                         if(cap->y1>atom->r.y)
859                                 continue;
860                         if(cap->z1>atom->r.z)
861                                 continue;
862                 }
863                 atom->attr=cap->attr;
864         }
865
866         return 0;
867 }
868
869 int chsattr(t_moldyn *moldyn,t_mdrun *mdrun) {
870
871         t_stage *stage;
872         t_chsattr_params *csp;
873
874         stage=mdrun->stage.current->data;
875         csp=stage->params;
876
877         if(csp->type&CHSATTR_PCTRL) {
878                 if(csp->ptau>0)
879                         set_p_scale(moldyn,P_SCALE_BERENDSEN,csp->ptau);
880                 else
881                         set_p_scale(moldyn,P_SCALE_BERENDSEN,csp->ptau);
882         }
883         if(csp->type&CHSATTR_TCTRL) {
884                 if(csp->ttau>0)
885                         set_t_scale(moldyn,T_SCALE_BERENDSEN,csp->ttau);
886                 else
887                         set_t_scale(moldyn,T_SCALE_BERENDSEN,csp->ttau);
888         }
889         if(csp->type&CHSATTR_PRELAX) {
890                 if(csp->dp<0)
891                         mdrun->sattr&=(~(SATTR_PRELAX));
892                 else
893                         mdrun->sattr|=SATTR_PRELAX;
894                 mdrun->dp=csp->dp;
895         }
896         if(csp->type&CHSATTR_TRELAX) {
897                 if(csp->dt<0)
898                         mdrun->sattr&=(~(SATTR_TRELAX));
899                 else
900                         mdrun->sattr|=SATTR_TRELAX;
901                 mdrun->dt=csp->dt;
902         }
903         if(csp->type&CHSATTR_AVGRST) {
904                 if(csp->avgrst)
905                         mdrun->sattr|=SATTR_AVGRST;
906                 else
907                         mdrun->sattr&=(~(SATTR_AVGRST));
908         }
909         if(csp->type&CHSATTR_RSTEPS) {
910                 mdrun->relax_steps=csp->rsteps;
911         }
912
913         return 0;
914 }
915
916 #define stage_print(m)  if(!(stage->executed)) \
917                                 printf("%s",m)
918
919 int mdrun_hook(void *ptr1,void *ptr2) {
920
921         t_moldyn *moldyn;
922         t_mdrun *mdrun;
923         t_stage *stage;
924         t_list *sl;
925         int steps;
926         u8 change_stage;
927
928         t_insert_atoms_params *iap;
929         t_insert_mixed_atoms_params *imp;
930         t_continue_params *cp;
931         t_anneal_params *ap;
932         t_set_temp_params *stp;
933         t_set_timestep_params *stsp;
934
935         moldyn=ptr1;
936         mdrun=ptr2;
937
938         sl=&(mdrun->stage);
939
940         change_stage=FALSE;
941
942         /* return immediately if there are no more stage */
943         if(sl->current==NULL)
944                 return 0;
945
946         /* get stage description */
947         stage=sl->current->data;
948
949         /* steps in next schedule */
950         steps=mdrun->relax_steps;
951
952         /* check whether relaxation steps are necessary */
953         if((check_pressure(moldyn,mdrun)==TRUE)&\
954            (check_temperature(moldyn,mdrun)==TRUE)) {
955         
956                 /* be verbose */
957                 stage_print("\n###########################\n");
958                 stage_print("# [mdrun] executing stage #\n");
959                 stage_print("###########################\n\n");
960                 
961                 /* stage specific stuff */
962                 switch(stage->type) {
963                         case STAGE_DISPLACE_ATOM:
964                                 stage_print("  -> displace atom\n\n");
965                                 displace_atom(moldyn,mdrun);
966                                 change_stage=TRUE;
967                                 break;
968                         case STAGE_INSERT_ATOMS:
969                                 stage_print("  -> insert atoms\n\n");
970                                 iap=stage->params;
971                                 if(iap->cnt_steps==iap->ins_steps) {
972                                         change_stage=TRUE;
973                                         break;
974                                 }
975                                 insert_atoms(moldyn,mdrun);
976                                 iap->cnt_steps+=1;
977                                 break;
978
979
980
981                         case STAGE_INSERT_MIXED_ATOMS:
982                                 stage_print("  -> insert mixed atoms\n\n");
983                                 imp=stage->params;
984                                 insert_mixed_atoms(moldyn,mdrun);
985                                 change_stage=TRUE;
986                                 break;
987
988
989
990                         case STAGE_CONTINUE:
991                                 stage_print("  -> continue\n\n");
992                                 if(stage->executed==TRUE) {
993                                         change_stage=TRUE;
994                                         break;
995                                 }
996                                 cp=stage->params;
997                                 steps=cp->runs;
998                                 break;
999                         case STAGE_ANNEAL:
1000                                 stage_print("  -> anneal\n\n");
1001                                 ap=stage->params;
1002                                 if(ap->count==ap->runs) {
1003                                         change_stage=TRUE;
1004                                         break;
1005                                 }
1006                                 if(moldyn->t_ref+ap->dt>=0.0)
1007                                         set_temperature(moldyn,
1008                                                         moldyn->t_ref+ap->dt);
1009                                 ap->count+=1;
1010                                 steps=ap->interval;
1011                                 break;
1012                         case STAGE_CHAATTR:
1013                                 stage_print("  -> change atom attributes\n\n");
1014                                 chaatr(moldyn,mdrun);
1015                                 change_stage=TRUE;
1016                                 break;
1017                         case STAGE_CHSATTR:
1018                                 stage_print("  -> change sys attributes\n\n");
1019                                 chsattr(moldyn,mdrun);
1020                                 change_stage=TRUE;
1021                                 break;
1022                         case STAGE_SET_TEMP:
1023                                 stage_print("  -> set temperature\n\n");
1024                                 stp=stage->params;
1025                                 if(stp->type&SET_TEMP_CURRENT) {
1026                                         set_temperature(moldyn,moldyn->t_avg);
1027                                 }
1028                                 else {
1029                                         set_temperature(moldyn,stp->val);
1030                                 }
1031                                 change_stage=TRUE;
1032                                 break;
1033                         case STAGE_SET_TIMESTEP:
1034                                 stage_print("  -> set timestep\n\n");
1035                                 stsp=stage->params;
1036                                 mdrun->timestep=stsp->tau;
1037                                 change_stage=TRUE;
1038                                 break;
1039                         default:
1040                                 printf("%s unknwon stage type\n",ME);
1041                                 break;
1042                 }
1043         
1044                 /* mark as executed */
1045                 stage->executed=TRUE;
1046         
1047                 /* change state */
1048                 if(change_stage==TRUE) {
1049                         printf("%s finished stage\n",ME);
1050                         if(list_next_f(sl)==L_NO_NEXT_ELEMENT) {
1051                                 printf("%s no more stages\n",ME);
1052                                 return 0;
1053                         }
1054                         steps=0;
1055                 }
1056
1057         }
1058         else {
1059
1060                 /* averages */
1061                 if(mdrun->sattr&SATTR_AVGRST)
1062                         average_reset(moldyn);
1063
1064         }
1065
1066         /* continue simulation */
1067         moldyn_add_schedule(moldyn,steps,mdrun->timestep);
1068
1069         return 0;
1070 }
1071
1072 int main(int argc,char **argv) {
1073
1074         t_mdrun mdrun;
1075         t_moldyn moldyn;
1076         t_3dvec o;
1077
1078         /* clear structs */
1079         memset(&mdrun,0,sizeof(t_mdrun));
1080         memset(&moldyn,0,sizeof(t_moldyn));
1081
1082         /* parse arguments */
1083         if(mdrun_parse_argv(&mdrun,argc,argv)<0)
1084                 return -1;
1085
1086         /* initialize list system */
1087         list_init_f(&(mdrun.stage));
1088
1089         /* parse config file */
1090         mdrun_parse_config(&mdrun);
1091
1092         /* reset the stage list */
1093         list_reset_f(&(mdrun.stage));
1094
1095         /* sanity check! */
1096
1097         /* prepare simulation */
1098
1099         if(mdrun.continue_file[0]) {
1100                 // read the save file
1101                 moldyn_read_save_file(&moldyn,mdrun.continue_file);
1102                 // manualaadjusting some stuff
1103                 moldyn.argc=argc;
1104                 moldyn.args=argv;
1105                 rand_init(&(moldyn.random),NULL,1);
1106                 moldyn.random.status|=RAND_STAT_VERBOSE;
1107         }
1108         else {
1109                 moldyn_init(&moldyn,argc,argv);
1110         }
1111         
1112         if(set_int_alg(&moldyn,mdrun.intalgo)<0)
1113                 return -1;
1114
1115         /* potential */
1116         set_cutoff(&moldyn,mdrun.cutoff);
1117         if(set_potential(&moldyn,mdrun.potential)<0)
1118                 return -1;
1119         switch(mdrun.potential) {
1120                 case MOLDYN_POTENTIAL_AM:
1121                         albe_mult_set_params(&moldyn,
1122                                              mdrun.element1,
1123                                              mdrun.element2);
1124                         break;
1125                 case MOLDYN_POTENTIAL_TM:
1126                         tersoff_mult_set_params(&moldyn,
1127                                                 mdrun.element1,
1128                                                 mdrun.element2);
1129                         break;
1130                 case MOLDYN_POTENTIAL_HO:
1131                         harmonic_oscillator_set_params(&moldyn,mdrun.element1);
1132                         break;
1133                 case MOLDYN_POTENTIAL_LJ:
1134                         lennard_jones_set_params(&moldyn,mdrun.element1);
1135                         break;
1136                 default:
1137                         printf("%s unknown potential: %02x\n",
1138                                ME,mdrun.potential);
1139                         return -1;
1140         }
1141
1142         /* if it is a continue run, reset schedule and skip lattice init */
1143         if(mdrun.continue_file[0]) {
1144                 memset(&(moldyn.schedule),0,sizeof(t_moldyn_schedule));
1145                 goto addsched;
1146         }
1147
1148         /* initial lattice and dimensions */
1149         set_dim(&moldyn,mdrun.dim.x,mdrun.dim.y,mdrun.dim.z,mdrun.vis);
1150         set_pbc(&moldyn,mdrun.pbcx,mdrun.pbcy,mdrun.pbcz);
1151         switch(mdrun.lattice) {
1152                 case FCC:
1153                         create_lattice(&moldyn,FCC,mdrun.lc,mdrun.element1,
1154                                        mdrun.m1,DEFAULT_ATOM_ATTR,0,mdrun.lx,
1155                                        mdrun.ly,mdrun.lz,NULL);
1156                         break;
1157                 case DIAMOND:
1158                         create_lattice(&moldyn,DIAMOND,mdrun.lc,mdrun.element1,
1159                                        mdrun.m1,DEFAULT_ATOM_ATTR,0,mdrun.lx,
1160                                        mdrun.ly,mdrun.lz,NULL);
1161                         break;
1162                 case ZINCBLENDE:
1163                         o.x=0.5*0.25*mdrun.lc; o.y=o.x; o.z=o.x;
1164                         create_lattice(&moldyn,FCC,mdrun.lc,mdrun.element1,
1165                                        mdrun.m1,DEFAULT_ATOM_ATTR,0,mdrun.lx,
1166                                        mdrun.ly,mdrun.lz,&o);
1167                         o.x+=0.25*mdrun.lc; o.y=o.x; o.z=o.x;
1168                         create_lattice(&moldyn,FCC,mdrun.lc,mdrun.element2,
1169                                        mdrun.m2,DEFAULT_ATOM_ATTR,1,mdrun.lx,
1170                                        mdrun.ly,mdrun.lz,&o);
1171                         break;
1172                 case NONE:
1173                         set_nn_dist(&moldyn,mdrun.nnd);
1174                         break;
1175                 default:
1176                         printf("%s unknown lattice type: %02x\n",
1177                                ME,mdrun.lattice);
1178                         return -1;
1179         }
1180         moldyn_bc_check(&moldyn);
1181
1182         /* temperature and pressure */
1183         set_temperature(&moldyn,mdrun.temperature);
1184         set_pressure(&moldyn,mdrun.pressure);
1185         thermal_init(&moldyn,TRUE);
1186
1187 addsched:
1188         /* first schedule */
1189         moldyn_add_schedule(&moldyn,mdrun.prerun,mdrun.timestep);
1190
1191         /* log */
1192         moldyn_set_log_dir(&moldyn,mdrun.sdir);
1193         moldyn_set_report(&moldyn,"CHANGE ME","CHANGE ME TOO");
1194         if(mdrun.elog)
1195                 moldyn_set_log(&moldyn,LOG_TOTAL_ENERGY,mdrun.elog);
1196         if(mdrun.tlog)
1197                 moldyn_set_log(&moldyn,LOG_TEMPERATURE,mdrun.tlog);
1198         if(mdrun.plog)
1199                 moldyn_set_log(&moldyn,LOG_PRESSURE,mdrun.plog);
1200         if(mdrun.vlog)
1201                 moldyn_set_log(&moldyn,LOG_VOLUME,mdrun.vlog);
1202         if(mdrun.visualize)
1203                 moldyn_set_log(&moldyn,VISUAL_STEP,mdrun.visualize);
1204         if(mdrun.save)
1205                 moldyn_set_log(&moldyn,SAVE_STEP,mdrun.save);
1206         moldyn_set_log(&moldyn,CREATE_REPORT,0);
1207         set_avg_skip(&moldyn,mdrun.avgskip);
1208
1209         /* prepare the hook function */
1210         moldyn_set_schedule_hook(&moldyn,&mdrun_hook,&mdrun);
1211
1212         /* run the simulation */
1213         moldyn_integrate(&moldyn);
1214
1215         /* shutdown */
1216         moldyn_shutdown(&moldyn);
1217         del_stages(&mdrun);
1218         list_destroy_f(&(mdrun.stage));
1219
1220         return 0;
1221 }