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