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