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