-
[physik/nlsop.git] / nlsop.c
1 /*
2  * nlsop.c 
3  *
4  * this program tries helping to understand the amorphous depuration
5  * and recrystallization of SiCx while ion implantation at temperatures
6  * below 400 degree celsius.
7  * hopefully the program will simulate the stabilization of the
8  * selforganizing lamella structure in the observed behaviour.
9  *
10  * refs: 
11  *  - J. K. N. Lindner. Habilationsschrift, Universitaet Augsburg.
12  *  - Maik Haeberlen. Diplomarbeit, Universitaet Augsburg.
13  */
14
15 #define _GNU_SOURCE
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23
24 #include "nlsop.h"
25
26 #include "dfbapi.h"
27 #include "random.h"
28
29 #define MAKE_AMORPH(N) *(N)|=AMORPH
30 #define MAKE_CRYST(N) *(N)&=~AMORPH
31
32 int usage(void)
33 {
34  puts("usage:");
35  puts("-h \t\t help");
36  puts("-n \t\t no user interaction");
37  puts("-Z \t\t cryst -> amorph c diffusion in z direction");
38  printf("-a <value> \t slope of nuclear energy loss (default %f)\n",A_EL);
39  printf("-b <value> \t nuclear energy loss offset (default %f)\n",B_EL);
40  printf("-x <value> \t # x cells (default %d)\n",X);
41  printf("-y <value> \t # y cells (default %d)\n",Y);
42  printf("-z <value> \t # z cells (default %d)\n",Z);
43  /*
44  printf("-X <value> \t display x (default %d)\n",X/2-1);
45  printf("-Y <value> \t display y (default %d)\n",Y/2-1);
46  printf("-Z <value> \t display z (default %d)\n",Z/2-1);
47  */
48  printf("-s <value> \t steps (default %d)\n",STEPS);
49  printf("-d <value> \t refresh display (default %d)\n",REFRESH);
50  printf("-r <value> \t amorphous influence range (default %d)\n",RANGE);
51  printf("-f <value> \t pressure = <value> * 1/distance^2 (default %f)\n",A_AP);
52  printf("-p <value> \t pressure offset (default %f)\n",B_AP);
53  printf("-A <value> \t slope of linear c distribution (default %f)\n",A_CD);
54  printf("-B <value> \t linear c distribution offset (default %f)\n",B_CD);
55  /*
56  printf("-C <value> \t initial c concentration (default %d)\n",CC);
57  */
58  printf("-D <value> \t diffusion rate from cryst to amorph cells (default %f)\n",DR_AC);
59  printf("-c <value> \t diffusion rate in cryst cells (default %f)\n",DR_CC);
60  printf("-W <value> \t write every <value> steps to save file (default %d)\n",RESAVE);
61  puts("-C <file> \t convert file to gnuplot format");
62  puts("-L <file> \t load from file");
63  puts("-S <file> \t save to file");
64  puts("-R <file> \t read from random file");
65  puts("-P <file> \t specify implantatin profile file");
66  
67  return 1;
68 }
69
70 int process_cell(d3_lattice *d3_l,u32 x,u32 y,u32 z,info *my_info)
71 {
72  unsigned char *thiz;
73  int *conc;
74  int i,j;
75  int off;
76  double p;
77
78  thiz=d3_l->status+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y;
79  conc=d3_l->extra+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y;
80  p=my_info->b_ap*URAND_MAX;
81  for(i=-(my_info->range);i<=my_info->range;i++)
82  {
83   for(j=-(my_info->range);j<=my_info->range;j++)
84   {
85    if(!(i==0 && j==0))
86    {
87     off=((x+d3_l->max_x+i)%d3_l->max_x)+((y+d3_l->max_y+j)%d3_l->max_x)*d3_l->max_x+z*d3_l->max_x*d3_l->max_y;
88     if(*(d3_l->status+off)&AMORPH) p+=my_info->a_ap*(*(d3_l->extra+off))*URAND_MAX/(i*i+j*j);
89    } 
90   }
91  }
92  p+=*conc*my_info->a_cp*URAND_MAX;
93  printf("debug: p = %f\n",p);
94  if(!(*thiz&AMORPH))
95  {
96   if(get_rand(URAND_MAX)<=p) MAKE_AMORPH(thiz);
97  } else
98  {
99   /* assume 1-p probability */
100   if(get_rand(URAND_MAX)>p) MAKE_CRYST(thiz);
101  }
102  
103  my_info->cc+=1;
104
105  return 1;
106 }
107
108 int distrib_c(d3_lattice *d3_l,info *my_info) /* double d_r,double a,double b,char z_diff) */
109 {
110  u32 x,y,z;
111  int i,j,k,c;
112  int offset,off;
113  int carry;
114
115  /* put one c ion somewhere in the lattice */
116  x=get_rand(d3_l->max_x);
117  y=get_rand(d3_l->max_y);
118  z=get_rand_lgp(d3_l->max_z,a,b);
119  *(d3_l->extra+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y)+=1;
120
121  /* diffusion in layer */
122  for(i=0;i<d3_l->max_x;i++)
123  {
124   for(j=0;j<d3_l->max_y;j++)
125   {
126    for(k=0;k<d3_l->max_z;k++)
127    {
128     offset=i+j*d3_l->max_x+k*d3_l->max_x*d3_l->max_y;
129     /* case amorph */
130     if(*(d3_l->status+offset)&AMORPH)
131     {
132      /* look at neighbours and move c ions */
133      for(c=-1;c<=1;c++)
134      {
135       if(c!=0)
136       {
137        off=((i+d3_l->max_x+c)%d3_l->max_x)+j*d3_l->max_x+k*d3_l->max_x*d3_l->max_y;
138        carry=0;
139        /* case neighbour not amorph */
140        if(!(*(d3_l->status+off)&AMORPH)) carry=(int)(d_r*(*(d3_l->extra+off)));
141        /* case neighbour amorph */
142        /*
143         * no diffusion between amorphous cells
144         *
145        else carry=(*(d3_l->extra+off)-*(d3_l->extra+offset))/2;
146         */
147        if(carry!=0)
148        {
149         *(d3_l->extra+offset)+=carry;
150         *(d3_l->extra+off)-=carry;
151        }
152       }
153      }
154      for(c=-1;c<=1;c++)
155      {
156       if(c!=0)
157       {
158        off=i+((j+c+d3_l->max_y)%d3_l->max_y)*d3_l->max_x+k*d3_l->max_x*d3_l->max_y;
159        carry=0;
160        /* case neighbour not amorph */  
161        if(!(*(d3_l->status+off)&AMORPH)) carry=(int)(d_r*(*(d3_l->extra+off)));                             
162        /* case neighbour amorph */
163        /*
164         *
165         * no diffusion between amorphous cells
166         *
167        else carry=(*(d3_l->extra+off)-*(d3_l->extra+offset))/2;
168         */
169        if(carry!=0)
170        {
171         *(d3_l->extra+offset)+=carry; 
172         *(d3_l->extra+off)-=carry; 
173        }
174       }
175      }
176     } else
177     /* case not amorph */
178     {
179      /* look at neighbours and move c ions */     
180      for(c=-1;c<=1;c++) 
181      {
182       if(c!=0)
183       {
184        off=i+((j+c+d3_l->max_y)%d3_l->max_y)*d3_l->max_x+k*d3_l->max_x*d3_l->max_y;
185        carry=0;
186        /* case neighbour not amorph */
187        if(!(*(d3_l->status+off)&AMORPH))
188        {
189         carry=(*(d3_l->extra+off)-*(d3_l->extra+offset))/2;
190         if(carry!=0)
191         {
192          *(d3_l->extra+offset)+=carry;
193          *(d3_l->extra+off)-=carry;
194         }
195        }
196       }
197      }
198      for(c=-1;c<=1;c++)
199      {
200       if(c!=0)
201       {
202        off=((i+c+d3_l->max_x)%d3_l->max_x)+j*d3_l->max_x+k*d3_l->max_x*d3_l->max_y;
203        carry=0;
204        /* case neighbour not amorph */
205        if(!(*(d3_l->status+off)&AMORPH))
206        {
207         carry=(*(d3_l->extra+off)-*(d3_l->extra+offset))/2;
208         if(carry!=0)
209         {
210          *(d3_l->extra+offset)+=carry;
211          *(d3_l->extra+off)-=carry;
212         }
213        }
214       }
215      }
216      /* cryst -> amorph diffusion in z direction */
217      if(z_diff)
218      {
219       for(c=1;c>=-1;c--)
220       {
221        off=i+j*d3_l->max_x+((k+c+d3_l->max_z)%d3_l->max_z)*d3_l->max_x*d3_l->max_y;
222        carry=0;
223        if(*(d3_l->status+off)&AMORPH) carry=(int)(d_r*(*(d3_l->extra+offset)));
224        if(carry!=0)
225        {
226         *(d3_l->extra+offset)-=carry;
227         *(d3_l->extra+off)+=carry;
228        }
229       }
230      } /* if z_diff */
231     }
232    } /* for z */
233   } /* for y */
234  } /* for x */
235
236  return 1;
237 }
238
239 int calc_pressure(d3_lattice *d3_l,int range)
240 {
241  int i,j,off;
242  double count;
243  int x,y,z;
244
245  for(x=0;x<d3_l->max_x;x++)
246  {
247   for(y=0;y<d3_l->max_y;y++)
248   {
249    for(z=0;z<d3_l->max_z;z++)
250    {
251     count=0;
252     for(i=-range;i<=range;i++)
253     {
254      for(j=-range;j<=range;j++)
255      {
256       if(i!=0 && j!=0)
257       {
258        off=((x+d3_l->max_x+i)%d3_l->max_x)+((y+d3_l->max_y+j)%d3_l->max_x)*d3_l->max_x+z*d3_l->max_x*d3_l->max_y;
259        if(*(d3_l->status+off)&AMORPH) count+=((double)*(d3_l->extra+off))/(i*i+j*j);
260       }
261      }
262     }
263     *(unsigned char *)(d3_l->v_ptr+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y)=(unsigned char)(count*255/MAX_VPTR);
264    }
265   }
266  }
267
268  return 1;
269 }
270
271 int save_to_file(char *sf,d3_lattice *d3_l,info *my_inf)
272 {
273  int sf_fd,c;
274
275  if((sf_fd=open(sf,O_WRONLY|O_CREAT))<0)
276  {
277   puts("cannot open save file");
278   return -1;
279  }
280  if(write(sf_fd,d3_l,sizeof(d3_lattice))<sizeof(d3_lattice))
281  {
282   puts("failed saving d3 lattice struct");
283   return -1;
284  }
285  if(write(sf_fd,my_inf,sizeof(info))<sizeof(info))
286  {
287   puts("failed saving info struct");
288   return-1;
289  }
290  c=d3_l->max_x*d3_l->max_y*d3_l->max_z;
291  if(write(sf_fd,d3_l->status,c*sizeof(unsigned char))<c*sizeof(unsigned char))
292  {
293   puts("failed saving status of d3 lattice sites");
294   return -1;
295  }
296  if(write(sf_fd,d3_l->extra,c*sizeof(int))<c*sizeof(int))
297  {
298   puts("failed saving sites concentration");
299   return -1;
300  }
301  close(sf_fd);
302
303  return 1;
304 }
305
306 int load_from_file(char *lf,d3_lattice *d3_l,info *my_inf)
307 {
308  int lf_fd,c;
309
310  if((lf_fd=open(lf,O_RDONLY))<0)
311  {
312   puts("cannot open load file");
313   return -1;
314  }
315  if(read(lf_fd,d3_l,sizeof(d3_lattice))<sizeof(d3_lattice))
316  {
317   puts("failed reading d3 lattice struct");
318   return -1;
319  }
320  if(read(lf_fd,my_inf,sizeof(info))<sizeof(info))
321  {
322   puts("failed reading info struct");
323   return-1;
324  }
325  c=d3_l->max_x*d3_l->max_y*d3_l->max_z;
326  if((d3_l->status=(unsigned char*)malloc(c*sizeof(unsigned char)))==NULL)
327  {
328   puts("cannot allocate status buffer");
329   return -1;
330  }
331  if((d3_l->extra=(int *)malloc(c*sizeof(int)))==NULL)
332  {
333   puts("cannot allocate concentration buffer");
334   return -1;
335  }
336  if(read(lf_fd,d3_l->status,c*sizeof(unsigned char))<c*sizeof(unsigned char))
337  {
338   puts("failed reading status of d3 lattice sites");
339   return -1;
340  }
341  if(read(lf_fd,d3_l->extra,c*sizeof(int))<c*sizeof(int))
342  {
343   puts("failed reading sites concentration");
344   return -1;
345  }
346  close(lf_fd);
347
348  return 1;
349 }
350
351 int convert_file(char *cf,d3_lattice *d3_l)
352 {
353  int x,y,z;
354  int c_fd;
355
356  if((c_fd=open(cf,O_WRONLY|O_CREAT))<0)
357  {
358   puts("cannot open convert file");
359   return -1;
360  }
361  dprintf(c_fd,"# created by nlsop (gnuplot format)\n");
362  for(x=0;x<d3_l->max_x;x++)
363  {
364   for(y=0;y<d3_l->max_y;y++)
365   {
366    for(z=0;z<d3_l->max_z;z++)
367    {
368     if(*(d3_l->status+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y)&AMORPH) dprintf(c_fd,"%d %d %d\n",x,y,z);
369    }
370   }
371  }
372  close(c_fd);
373
374  return 1;
375 }
376
377 int main(int argc,char **argv)
378 {
379  u32 x,y,z,x_c,y_c,z_c;
380  int i,quit,escape,switchmode,nowait;
381  int refresh,resave;
382  char s_file[MAX_CHARS];
383  char s_file_tmp[MAX_CHARS];
384  char l_file[MAX_CHARS];
385  char c_file[MAX_CHARS];
386  char p_file[MAX_CHARS];
387  char convert;
388  char r_file[MAX_CHARS];
389 #ifdef USE_DFB_API
390  char xyz_txt[MAX_TXT];
391  char status_txt[MAX_TXT];
392  char conc_txt[MAX_TXT];
393  char steps_txt[MAX_TXT];
394  char cc_txt[MAX_TXT];
395  char a_txt[MAX_TXT];
396  char s_txt[MAX_TXT];
397  char ap_txt[MAX_TXT];
398  char el_txt[MAX_TXT];
399  char cd_txt[MAX_TXT];
400  char r_txt[MAX_TXT];
401  char ap2_txt[MAX_TXT];
402  char cd2_txt[MAX_TXT];
403  char el2_txt[MAX_TXT];
404  char dr_ac_txt[MAX_TXT];
405  char dr_cc_txt[MAX_TXT];
406  char mode_txt[MAX_TXT];
407  char *arg_v[MAX_ARGV];
408 #endif
409  d3_lattice d3_l;
410  info my_info;
411  unsigned char mode;
412
413  d3_l.max_x=X;
414  d3_l.max_y=Y;
415  d3_l.max_z=Z;
416  my_info.steps=STEPS;
417  my_info.range=RANGE;
418  refresh=REFRESH;
419  resave=RESAVE;
420  my_info.z_diff=0;
421  my_info.a_el=A_EL;
422  my_info.b_el=B_EL;
423  my_info.a_cd=A_CD;
424  my_info.b_cd=B_CD;
425  my_info.a_ap=A_AP;
426  my_info.b_ap=B_AP;
427  my_info.cc=CC;
428  my_info.dr_ac=DR_AC;
429  my_info.dr_cc=DR_CC;
430  nowait=0;
431  quit=0;
432  escape=0;
433  switchmode=0;
434  strcpy(s_file,"");
435  strcpy(l_file,"");
436  strcpy(c_file,"");
437  strcpy(p_file,IMP_PROFILE);
438  convert=0;
439  strcpy(r_file,"");
440  mode=0;
441
442  for(i=1;i<argc;i++)
443  {
444   if(argv[i][0]=='-')
445   {
446    switch(argv[i][1])
447    {
448     case 'h':
449      usage();
450      return -1;
451     case 'n':
452      nowait=1;
453      break;
454     case 'a':
455      my_info.a_el=atof(argv[++i]);
456      break;
457     case 'b':
458      my_info.b_el=atof(argv[++i]);
459      break;
460     case 'x':
461      d3_l.max_x=atoi(argv[++i]);
462      break;
463     case 'y':
464      d3_l.max_y=atoi(argv[++i]);
465      break;
466     case 'z':
467      d3_l.max_z=atoi(argv[++i]);
468      break;
469     /*
470     case 'X':
471      x=atoi(argv[++i]);
472      break;
473     case 'Y':
474      y=atoi(argv[++i]);
475      break;
476     */
477     case 'Z':
478      my_info.z_diff=1;
479      break;
480     /* */
481     case 's':
482      my_info.steps=atoi(argv[++i]);
483      break;
484     case 'd':
485      refresh=atoi(argv[++i]);
486      break;
487     case 'r':
488      my_info.range=atoi(argv[++i]);
489      break;
490     case 'f':
491      my_info.a_ap=atof(argv[++i]);
492      break;
493     case 'p':
494      my_info.b_ap=atof(argv[++i]);
495      break;
496     case 'A':
497      my_info.a_cd=atof(argv[++i]);
498      break;
499     case 'B':
500      my_info.b_cd=atof(argv[++i]);
501      break;
502     /*
503     case 'C':
504      my_info.cc=atoi(argv[++i]);
505      break;
506     */
507     case 'W':
508      resave=atoi(argv[++i]);
509      break;
510     case 'C':
511      strcpy(l_file,argv[++i]);
512      if(i<argc-1) if(argv[i+1][0]!='-') strcpy(c_file,argv[++i]);
513      convert=1;
514      break;
515     case 'D':
516      my_info.dr_ac=atof(argv[++i]);
517      break;
518     case 'c':
519      my_info.dr_cc=atof(argv[++i]);
520      break;
521     case 'L':
522      strcpy(l_file,argv[++i]);
523      break;
524     case 'S':
525      strcpy(s_file,argv[++i]);
526      break;
527     case 'R':
528      strcpy(r_file,argv[++i]);
529      break;
530     case 'P':
531      strcpy(p_file,argv[++i]);
532      break;
533     default:
534      usage();
535      return -1;
536    }
537   } else usage();
538  }
539
540  x=d3_l.max_x/2-1;
541  y=d3_l.max_y/2-1;
542  z=d3_l.max_z/2-1;
543
544 #ifdef NODFB
545  if(!strcmp(s_file,""))
546  {
547   puts("NODFB defined, run with -S option");
548   return -1;
549  }
550 #endif
551
552  if(!strcmp(r_file,"")) rand_init(NULL);
553  else rand_init(r_file);
554
555  if(!strcmp(l_file,""))
556  {
557   i=d3_l.max_x*d3_l.max_y*d3_l.max_z;
558 #ifdef USE_DFB_API
559   d3_lattice_init(&argc,argv,&d3_l);
560 #endif
561   if((d3_l.status=(unsigned char *)malloc(i*sizeof(unsigned char)))==NULL)
562   {
563    puts("failed allocating status buffer");
564    return -1;
565   }
566   memset(d3_l.status,0,i*sizeof(unsigned char));
567   if((d3_l.extra=(int *)malloc(i*sizeof(int)))==NULL)
568   {
569    puts("failed allocating concentration buffer");
570    return -1;
571   }
572   memset(d3_l.extra,0,i*sizeof(int));
573  } else
574  {
575   load_from_file(l_file,&d3_l,&my_info);
576   if(convert) 
577   {   
578    if(!strcmp(c_file,"")) sprintf(c_file,"%s_gnuplot",l_file);
579    printf("converting file %s to %s\n",l_file,c_file);
580    convert_file(c_file,&d3_l);
581    puts("done");
582    return 1;
583   } 
584 #ifdef USE_DFB_API
585     else d3_lattice_init(&argc,argv,&d3_l);
586 #endif
587  }
588
589 #ifdef USE_DFB_API
590  d3_event_init(&d3_l);
591 #endif
592
593 #ifdef USE_DFB_API
594  strcpy(a_txt,"args:");
595  sprintf(s_txt,"steps: %d",my_info.steps);
596  sprintf(r_txt,"pressure range: %d",my_info.range);
597  sprintf(ap_txt,"pressure faktor: %.2f",my_info.a_ap);
598  sprintf(ap2_txt,"pressure offset: %.2f",my_info.b_ap);
599  sprintf(el_txt,"energy loss slope: %.2f",my_info.a_el);
600  sprintf(el2_txt,"energy loss offset: %.2f",my_info.b_el);
601  sprintf(cd_txt,"c distrib slope: %.2f",my_info.a_cd);
602  sprintf(cd2_txt,"c distrib offset: %.2f",my_info.b_cd);
603  sprintf(dr_ac_txt,"a/c diffusion rate: %.2f",my_info.dr_ac);
604  sprintf(dr_cc_txt,"c/c diffusion rate: %.2f",my_info-dr_cc);
605  strcpy(mode_txt,"view: a/c mode");
606  arg_v[1]=xyz_txt;
607  arg_v[2]=NULL;
608  arg_v[3]=status_txt;
609  arg_v[4]=conc_txt;
610  arg_v[5]=NULL;
611  arg_v[6]=mode_txt;
612  arg_v[7]=NULL;
613  arg_v[8]=steps_txt;
614  arg_v[9]=cc_txt;
615  arg_v[10]=NULL;
616  arg_v[11]=NULL;
617  arg_v[12]=NULL;
618  arg_v[13]=NULL;
619  arg_v[14]=a_txt;
620  arg_v[15]=s_txt;
621  arg_v[16]=r_txt;
622  arg_v[17]=ap_txt;
623  arg_v[18]=ap2_txt;
624  arg_v[19]=el_txt;
625  arg_v[20]=el2_txt;
626  arg_v[21]=cd_txt;
627  arg_v[22]=cd2_txt;
628  arg_v[23]=dr_ac_txt;
629  arg_v[24]=dr_cc_txt;
630 #endif
631
632  if(!strcmp(l_file,""))
633  {
634   i=0;
635   while((i<my_info.steps) && (quit==0) && (escape==0))
636   {
637    x_c=get_rand(d3_l.max_x);
638    y_c=get_rand(d3_l.max_y);
639    z_c=get_rand_lgp(d3_l.max_z,my_info.a_el,my_info.b_el);
640    distrib_c(&d3_l,my_info.d_r,my_info.a_cd,my_info.b_cd,z_diff);
641    process_cell(&d3_l,x_c,y_c,z_c,&my_info);
642 #ifdef USE_DFB_API
643    if(i%refresh==0)
644    {
645     sprintf(xyz_txt,"x: %d  y: %d  z: %d",x+1,y+1,z+1);
646     sprintf(status_txt,"status: %c",(*(d3_l.status+x+y*d3_l.max_x+z*d3_l.max_x*d3_l.max_y)&AMORPH)?'a':'c');
647     sprintf(conc_txt,"conc: %d",*(d3_l.extra+x+y*d3_l.max_x+z*d3_l.max_x*d3_l.max_y));
648     sprintf(steps_txt,"step: %d",i);
649     sprintf(cc_txt,"total c: %d",my_info.cc);
650     d3_lattice_draw(&d3_l,x,y,z,24,arg_v,mode);
651    }
652 #endif
653    if(i%resave==0 && strcmp(s_file,"") && resave!=0 && i!=0)
654    {
655     sprintf(s_file_tmp,"%s_%d_of_%d",s_file,i,my_info.steps);
656     save_to_file(s_file_tmp,&d3_l,&my_info);
657 #ifdef NODFB
658     printf("saved %s\n",s_file_tmp);
659 #endif
660    }
661    i++;
662   }
663  }
664
665  if(strcmp(s_file,""))
666  {
667    printf("saved %s\n",s_file);
668    save_to_file(s_file,&d3_l,&my_info);
669  }
670
671 #ifdef USE_DFB_API
672  /* allocating buffer for pressure values */
673  if((d3_l.v_ptr=malloc(d3_l.max_x*d3_l.max_y*d3_l.max_z*sizeof(unsigned char)))==NULL)
674  {
675   puts("cannot allocate buffer for pressure values");
676   return -1;
677  }
678  /* calc values */
679  calc_pressure(&d3_l,my_info.range);
680
681  while((quit==0) && (escape==0) && (nowait==0))
682  {
683   /* bahh! */
684   if(switchmode==0) mode=0;
685   if(switchmode==1) mode=1;
686   if(switchmode==2) mode=2;
687   /* end of bahh! */
688   sprintf(x_txt,"x: %d",x+1);
689   sprintf(y_txt,"y: %d",y+1);
690   sprintf(z_txt,"z: %d",z+1);
691   sprintf(status_txt,"status: %c",(*(d3_l.status+x+y*d3_l.max_x+z*d3_l.max_x*d3_l.max_y)&AMORPH)?'a':'c');
692   sprintf(conc_txt,"conc: %d",*(d3_l.extra+x+y*d3_l.max_x+z*d3_l.max_x*d3_l.max_y));
693   strcpy(steps_txt,"step: end!");
694   sprintf(cc_txt,"total c: %d",my_info.cc);
695   if(switchmode==0) strcpy(mode_txt,"view: a/c mode");
696   if(switchmode==1) strcpy(mode_txt,"view: c conc mode");
697   if(switchmode==2) strcpy(mode_txt,"view: a pressure mode");
698   d3_lattice_draw(&d3_l,x,y,z,24,arg_v,mode);
699   scan_event(&d3_l,&x,&y,&z,&quit,&escape,&switchmode);
700  }
701
702  d3_lattice_release(&d3_l);
703 #endif
704
705  return 1;
706 }