some more bugfixes + testing
[physik/nlsop.git] / nlsop_client.c
1 /*
2  * client nlsop code
3  *
4  * author: frank zirkelbach (frank.zirkelbach@physik.uni-augsburg.de)
5  *
6  * this program tries helping to understand the amorphous depuration
7  * and recrystallization of SiCx while ion implantation at temperatures
8  * below 400 degree celsius.
9  * hopefully the program will simulate the stabilization of the
10  * selforganizing lamella structure in the observed behaviour.
11  *
12  * refs: 
13  *  - J. K. N. Lindner. Habil.Schrift, Universitaet Augsburg.
14  *  - Maik Haeberlen. Diplomarbeit, Universitaet Augsburg.
15  *
16  * Copyright (C) 2004 Frank Zirkelbach
17  *
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 2 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
31  *
32  */
33
34 #define _GNU_SOURCE
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42
43 #include <signal.h>
44
45 #include "nlsop.h"
46 #include "dfbapi.h"
47 #include "random.h"
48
49 #include "network.h"
50 #include "event.h"
51
52 #include "nlsop_general.h"
53
54 #define MAKE_AMORPH(N) *(N)|=AMORPH
55 #define MAKE_CRYST(N) *(N)&=~AMORPH
56
57 /* globals */
58
59 char p_file[MAX_CHARS];
60 char n_e_file[MAX_CHARS];
61 char r_file[MAX_CHARS];
62 t_net *gnet;
63 d3_lattice *gd3_l;
64 info *gmy_info;
65 int *gi;
66 unsigned char dc;
67
68 int get_data_and_calc(t_event *event,void *allineed);
69 int nop(t_event *event,void *allineed);
70
71 int usage(char *prog)
72 {
73  puts("usage:");
74  printf("%s -i ip -p port -r/P/n random/profile/neloss file\n",prog);
75  return 1;
76 }
77
78 /*
79  * nlsop internal functions
80  */
81
82 int sputter(d3_lattice *d3_l)
83 {
84  int i,size;
85  int offh,offl;
86
87  size=d3_l->max_x*d3_l->max_y;
88  offl=0;
89  offh=size;
90
91  for(i=0;i<d3_l->max_z-1;i++)
92  {
93   memcpy(d3_l->status+offl,d3_l->status+offh,size);
94   memcpy(d3_l->extra+offl,d3_l->extra+offh,size*sizeof(int));
95   offl=offh;
96   offh+=size;
97  }
98  memset(d3_l->status+offl,0,size);
99  memset(d3_l->extra+offl,0,size);
100
101  return 1;
102 }
103
104 int process_cell(d3_lattice *d3_l,u32 x,u32 y,u32 z,info *my_info,u32 nel_z)
105 {
106  unsigned char *thiz;
107  int *conc;
108  int i,j;
109  int off;
110  double p,q;
111
112  thiz=d3_l->status+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y;
113  conc=d3_l->extra+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y;
114  p=my_info->b*nel_z;
115  for(i=-(my_info->range);i<=my_info->range;i++)
116  {
117   for(j=-(my_info->range);j<=my_info->range;j++)
118   {
119    if(!(i==0 && j==0))
120    {
121     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;
122     if(*(d3_l->status+off)&AMORPH) p+=my_info->s*(*(d3_l->extra+off))*URAND_MAX/(i*i+j*j);
123    } 
124   }
125  }
126  p+=*conc*my_info->c*URAND_MAX;
127  if(!(*thiz&AMORPH))
128  {
129   if(get_rand(URAND_MAX)<=p) MAKE_AMORPH(thiz);
130  } else
131  {
132   /* assume 1-p probability */
133   /* also look for neighbours ! */
134   q=(URAND_MAX-p)>0?URAND_MAX-p:0;
135   j=0;
136   j+=(*(d3_l->status+((x+d3_l->max_x+1)%d3_l->max_x)+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y)&AMORPH)?1:0;
137   j+=(*(d3_l->status+((x+d3_l->max_x-1)%d3_l->max_x)+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y)&AMORPH)?1:0;
138   j+=(*(d3_l->status+x+((y+1+d3_l->max_y)%d3_l->max_y)*d3_l->max_x+z*d3_l->max_x*d3_l->max_y)&AMORPH)?1:0;
139   j+=(*(d3_l->status+x+((y-1+d3_l->max_y)%d3_l->max_y)*d3_l->max_x+z*d3_l->max_x*d3_l->max_y)&AMORPH)?1:0;
140   j+=(*(d3_l->status+x+y*d3_l->max_x+((z+1+d3_l->max_z)%d3_l->max_z)*d3_l->max_x*d3_l->max_y)&AMORPH)?1:0;
141   j+=(*(d3_l->status+x+y*d3_l->max_x+((z-1+d3_l->max_z)%d3_l->max_z)*d3_l->max_x*d3_l->max_y)&AMORPH)?1:0;
142
143   p+=((q/6)*j);
144   if(get_rand(URAND_MAX)>p) MAKE_CRYST(thiz);
145  }
146  
147  return 1;
148 }
149
150 int distrib_c(d3_lattice *d3_l,info *my_info,int step,u32 rj_m,u32 *rj_g)
151 {
152  u32 x,y,z;
153  int i,j,k,c;
154  int offset,off;
155  int carry;
156
157  /* put one c ion somewhere in the lattice */
158  x=get_rand(d3_l->max_x);
159  y=get_rand(d3_l->max_y);
160  z=get_rand_reject(d3_l->max_z,rj_m,rj_g);
161  *(d3_l->extra+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y)+=1;
162  (my_info->cc)++;
163
164  if(step%my_info->diff_rate==0)
165  {
166
167  for(i=0;i<d3_l->max_x;i++)
168  {
169   for(j=0;j<d3_l->max_y;j++)
170   {
171    for(k=0;k<d3_l->max_z;k++)
172    {
173     offset=i+j*d3_l->max_x+k*d3_l->max_x*d3_l->max_y;
174     /* case amorph: amorph <- cryst diffusion */
175     if(*(d3_l->status+offset)&AMORPH)
176     {
177      for(c=-1;c<=1;c++)
178      {
179       if(c!=0)
180       {
181        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;
182        carry=0;
183        if(!(*(d3_l->status+off)&AMORPH)) carry=(int)(my_info->dr_ac*(*(d3_l->extra+off)));
184        if(carry!=0)
185        {
186         *(d3_l->extra+offset)+=carry;
187         *(d3_l->extra+off)-=carry;
188        }
189       }
190      }
191      for(c=-1;c<=1;c++)
192      {
193       if(c!=0)
194       {
195        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;
196        carry=0;
197        if(!(*(d3_l->status+off)&AMORPH)) carry=(int)(my_info->dr_ac*(*(d3_l->extra+off)));
198        if(carry!=0)
199        {
200         *(d3_l->extra+offset)+=carry; 
201         *(d3_l->extra+off)-=carry; 
202        }
203       }
204      }
205      /* diff in z direction */
206      if(k!=0)
207      {
208       off=i+j*d3_l->max_x+(k-1)*d3_l->max_x*d3_l->max_y;
209       carry=0;
210       if(!*(d3_l->status+off)&AMORPH) carry=(int)(my_info->dr_ac*(*(d3_l->extra+off)));
211       if(carry!=0)
212       {
213        *(d3_l->extra+off)-=carry;
214        *(d3_l->extra+offset)+=carry;
215       }
216      }
217      if(k!=d3_l->max_z-1)
218      {
219       off=i+j*d3_l->max_x+(k+1)*d3_l->max_x*d3_l->max_y;
220       carry=0;
221       if(!*(d3_l->status+off)&AMORPH) carry=(int)(my_info->dr_ac*(*(d3_l->extra+off)));
222       if(carry!=0)
223       {
224        *(d3_l->extra+off)-=carry;
225        *(d3_l->extra+offset)+=carry;
226       }
227      }
228     }
229    } /* for z */
230   } /* for y */
231  } /* for x */
232
233  } /* if step modulo diff_rate == 0 */
234
235  return 1;
236 }
237
238 u32 get_reject_graph(info *my_info,d3_lattice *d3_l,char *file,u32 *graph) {
239  double a,b;
240  int i,j,k;
241  int fd;
242  char buf[32],*p;
243  unsigned char *flag;
244  u32 max;
245
246  max=0;
247  if((fd=open(file,O_RDONLY))<0)
248  {
249   puts("cannot open file to calculate rejection graph");
250   return -1;
251  }
252  if((flag=(unsigned char *)malloc(d3_l->max_z))==NULL)
253  {
254   puts("cannot malloc flag memory for rejection graph");
255   return -1;
256  }
257  memset(flag,0,d3_l->max_z);
258  memset(graph,0,d3_l->max_z*sizeof(u32));
259  /* get fixpoints */
260  k=1;
261  while(k)
262  {
263   for(i=0;i<32;i++)
264   {
265    k=read(fd,&buf[i],1);
266    if((buf[i]=='\n')||(k==0)) break;
267   }
268   if(k)
269   {
270    p=strtok(buf," ");
271    a=atof(p)/10; /* nm */
272    p=strtok(NULL," ");
273    b=atof(p);
274    if(a>d3_l->max_z*CELL_LENGTH) k=0;
275    else 
276    {
277     graph[(int)(a/CELL_LENGTH)]=(int)(URAND_MAX/100*b);
278     flag[(int)(a/CELL_LENGTH)]=1;
279    }
280   }
281  }
282  /* do (linear) interpolation here! */
283  i=0;
284  a=0;
285  while(i<d3_l->max_z)
286  {
287   /* graph[0] is 0! */
288   j=i;
289   i++;
290   while(flag[i]==0&&i<d3_l->max_z) i++;
291   for(k=j+1;k<i;k++) graph[k]=(int)((k-j)*((int)graph[i]-(int)graph[j])/(i-j))+graph[j];
292   if(graph[i]>max) max=graph[i];
293  }
294
295  free(flag);
296
297 #ifdef DEBUG_INTERPOL_PROFILE
298  printf("debug: %s (interpolated profile)\n",file);
299  for(i=0;i<d3_l->max_z;i++) printf("%d %d\n",i,graph[i]);
300 #endif
301
302  return max;
303 }
304
305 void send_data(int signum) {
306
307   int c;
308   unsigned char data;
309
310   c=gd3_l->max_x*gd3_l->max_y*gd3_l->max_z;
311
312   printf("%d <-\n",c);
313
314   network_send(gnet->connection[0].fd,&dc,1);
315   network_receive(gnet->connection[0].fd,&data,sizeof(unsigned char));
316   printf("debug: sent dc\n");
317
318   network_send(gnet->connection[0].fd,(unsigned char *)gd3_l,
319                sizeof(d3_lattice));
320   network_receive(gnet->connection[0].fd,&data,sizeof(unsigned char));
321   printf("debug: sent d3_lattice\n");
322
323   network_send(gnet->connection[0].fd,(unsigned char *)gmy_info,sizeof(info));
324   network_receive(gnet->connection[0].fd,&data,sizeof(unsigned char));
325   printf("debug: sent info\n");
326
327   network_send(gnet->connection[0].fd,gd3_l->status,c*sizeof(unsigned char));
328   network_receive(gnet->connection[0].fd,&data,sizeof(unsigned char));
329   printf("debug: sent ac\n");
330
331   network_send(gnet->connection[0].fd,(unsigned char *)gd3_l->extra,
332                c*sizeof(int));
333   network_receive(gnet->connection[0].fd,&data,sizeof(unsigned char));
334   printf("debug: sent cc\n");
335
336   network_send(gnet->connection[0].fd,(unsigned char *)gi,sizeof(int));
337   network_receive(gnet->connection[0].fd,&data,sizeof(unsigned char));
338   printf("debug: sent steps\n");
339
340 }
341
342
343 /*
344  * main program
345  */
346
347 int main(int argc,char **argv)
348 {
349
350   char server_ip[16];
351   int port;
352   t_net net;
353   t_event event;
354   unsigned char data[256];
355   int i;
356
357   gnet=&net;
358
359   /* default values */
360   strcpy(server_ip,"");
361   strcpy(p_file,IMP_PROFILE);
362   strcpy(n_e_file,NEL_PROFILE);
363   strcpy(r_file,"");
364   port=1025;
365
366   /* parse/check argv */
367   for(i=1;i<argc;i++) {
368     if(argv[i][0]=='-') {
369       switch(argv[i][1]) {
370         case 'h':
371           usage(argv[0]);
372           return -1;
373         case 'i':
374           strncpy(server_ip,argv[++i],16);
375           break;
376         case 'r':
377           strcpy(r_file,argv[++i]);
378           break;
379         case 'P':
380           strcpy(p_file,argv[++i]);
381           break;
382         case 'n':
383           strcpy(n_e_file,argv[++i]);
384           break;
385         case 'p':
386           port=atoi(argv[++i]);
387           break;
388         default:
389           usage(argv[0]);
390           return -1;
391       }
392     }
393   }
394   if(!strcmp(server_ip,"")) {
395     usage(argv[0]);
396     return -1;
397   }
398
399   /* event init */
400   event_init(&event,1);
401   event_set_timeout(&event,0,0);
402
403   /* connect to server */
404   network_init(&net,1);
405   network_set_connection_info(&net,0,server_ip,port);
406   if(network_connect(&net,0)==N_E_CONNECT) {
407     printf("unable to connect to server, aborting ...\n");
408     return -1;
409   }
410   network_select(&net,0);
411
412   /* tell server: i am a client, i may work for you */
413   data[0]=NLSOP_CLIENT;
414   network_send(net.connection[0].fd,data,1);
415
416   /* wait for job */
417   event_math(net.connection[0].fd,&event,READ,ADD);
418   printf("idle, waiting for jobs ...\n");
419   event_start(&event,NULL,get_data_and_calc,nop);
420
421   return 1;
422 }
423
424 int nop(t_event *event,void *allineed) {
425
426   return 1;
427 }
428
429 int get_data_and_calc(t_event *event,void *allineed) {
430
431   d3_lattice d3_l;
432   info my_info;
433   u32 *c_profile;
434   u32 *n_e_loss;
435   u32 ne_max,ip_max;
436   u32 *nel_z;
437   u32 x_c,y_c,z_c;
438   int i,j;
439   int c_step;
440   unsigned char data;
441
442   t_net *net;
443
444   c_step=0;
445   ne_max=0;
446   ip_max=0;
447
448   net=gnet;
449   gd3_l=&d3_l;
450   gmy_info=&my_info;
451   gi=&i;
452   dc=0;
453
454   printf("got a new job ...\n");
455   
456   /* get info (+data) */
457   network_receive(net->connection[0].fd,&data,sizeof(unsigned char));
458   if(data==NLSOP_NJOB || data==NLSOP_CJOB) {
459     network_receive(net->connection[0].fd,(unsigned char *)&d3_l,
460                     sizeof(d3_lattice));
461     network_receive(net->connection[0].fd,(unsigned char *)&my_info,
462                     sizeof(info));
463     c_step=0;
464     j=d3_l.max_x*d3_l.max_y*d3_l.max_z;
465     d3_l.status=(unsigned char *)malloc(j*sizeof(unsigned char));
466     if(d3_l.status==NULL) {
467       printf("status alloc failed\n");
468       return -1;
469     }
470     d3_l.extra=(int *)malloc(j*sizeof(int));
471     if(d3_l.extra==NULL) {
472       printf("extra malloc failed\n");
473       return -1;
474     }
475     if(data==NLSOP_CJOB) {
476       data=DATA_OK;
477       network_receive(net->connection[0].fd,d3_l.status,
478                       j*sizeof(unsigned char));
479       network_send(net->connection[0].fd,&data,sizeof(unsigned char));
480       network_receive(net->connection[0].fd,(unsigned char *)d3_l.extra,
481                       j*sizeof(int));
482       network_send(net->connection[0].fd,&data,sizeof(unsigned char));
483       network_receive(net->connection[0].fd,(unsigned char *)&c_step,
484                       sizeof(int));
485       network_send(net->connection[0].fd,&data,sizeof(unsigned char));
486     }
487   }
488   else {
489     printf("unknown instruction, restarting ...\n");
490     return -1;
491   }
492
493   printf("starting simulation with following parameters:\n");
494   printf("b = %f | c = %f | s = %f\n",my_info.b,my_info.c,my_info.s);
495   printf("diff every %d steps | diff rate = %f\n",my_info.diff_rate,
496                                                   my_info.dr_ac);
497   printf("current step: %d | total steps: %d\n",c_step,my_info.steps);
498   printf("...\n");
499
500   /* care for signals */
501   dc=DC_QUIT;
502   signal(SIGTERM,send_data);
503
504   /* rand init */
505   if(!strcmp(r_file,"")) rand_init(NULL);
506   else rand_init(r_file);
507
508   /* compute graphs for random number rejection method */
509   if((c_profile=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int)))==NULL) {
510     puts("failed allocating memory for carbon profile graph");
511     return -1;
512   }
513   if((n_e_loss=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int)))==NULL) {
514     puts("failed allocating memory for nuclear energy loss graph");
515     return -1;
516   }
517   ip_max=get_reject_graph(&my_info,&d3_l,p_file,c_profile);
518   ne_max=get_reject_graph(&my_info,&d3_l,n_e_file,n_e_loss);
519
520   /* array nel_z[] keeping nuclear energy loss values scaled to URAND_MAX */
521   nel_z=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int));
522   if(nel_z==NULL) {
523     printf("failed allocating nel_z array mem\n");
524     return -1;
525   }
526   for(i=0;i<d3_l.max_z;i++) nel_z[i]=URAND_MAX*(1.0*n_e_loss[i]/ne_max);
527
528   /* this should be obsolete - z is high enough - we check now! */
529   if(c_profile[d3_l.max_z-1]!=0) {
530     printf("max_z (%d) too small - sputtering not possible\n",d3_l.max_z);
531     return -1;
532   }
533
534   /* sputtering really possible ?*/
535   if(n_e_loss[d3_l.max_z-1]!=0)
536     printf("warning: max_z (%d) too small, there may be amorphous volumes\n",
537            d3_l.max_z);
538
539   /*
540    * start of simulation
541    */
542
543   i=(c_step?c_step:0);
544   while(i<my_info.steps) {
545     for(j=0;j<my_info.cpi;j++) {
546       x_c=get_rand(d3_l.max_x);
547       y_c=get_rand(d3_l.max_y);
548       // z_c=get_rand_reject(d3_l.max_z,ne_max,n_e_loss);
549       z_c=get_rand(d3_l.max_z);
550       process_cell(&d3_l,x_c,y_c,z_c,&my_info,nel_z[z_c]);
551     }
552     distrib_c(&d3_l,&my_info,i,ip_max,c_profile);
553     i++;
554     if(i%my_info.save_rate==0) {
555       dc=DC_OK;
556       send_data(0);
557       dc=DC_QUIT;
558     }
559     if(i%my_info.s_rate==0) sputter(&d3_l);
560   }
561
562   /* finished */
563   dc=DC_END;
564   send_data(0);
565   dc=DC_QUIT;
566
567   /* shutdown/free/close everything now ... */
568   free(d3_l.status);
569   free(d3_l.extra);
570
571   return 1;
572 }