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