care for corrupted data, improved client termination behaviour
[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 unsigned char shut_down;
68
69 int get_data_and_calc(t_event *event,void *allineed);
70 int nop(t_event *event,void *allineed);
71
72 int usage(char *prog)
73 {
74  puts("usage:");
75  printf("%s -i ip -p port -r/P/n random/profile/neloss file\n",prog);
76  return 1;
77 }
78
79 /*
80  * nlsop internal functions
81  */
82
83 int sputter(d3_lattice *d3_l)
84 {
85  int i,size;
86  int offh,offl;
87
88  size=d3_l->max_x*d3_l->max_y;
89  offl=0;
90  offh=size;
91
92  for(i=0;i<d3_l->max_z-1;i++)
93  {
94   memcpy(d3_l->status+offl,d3_l->status+offh,size);
95   memcpy(d3_l->extra+offl,d3_l->extra+offh,size*sizeof(int));
96   offl=offh;
97   offh+=size;
98  }
99  memset(d3_l->status+offl,0,size);
100  memset(d3_l->extra+offl,0,size);
101
102  return 1;
103 }
104
105 int process_cell(d3_lattice *d3_l,u32 x,u32 y,u32 z,info *my_info,u32 nel_z)
106 {
107  unsigned char *thiz;
108  int *conc;
109  int i,j;
110  int off;
111  double p,q;
112
113  thiz=d3_l->status+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y;
114  conc=d3_l->extra+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y;
115  //p=my_info->b*nel_z; // energieuebertrag prop zu nukl. bk
116  p=my_info->b*URAND_MAX; // konstanter energieuebertrag
117  for(i=-(my_info->range);i<=my_info->range;i++)
118  {
119   for(j=-(my_info->range);j<=my_info->range;j++)
120   {
121    if(!(i==0 && j==0))
122    {
123     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;
124     if(*(d3_l->status+off)&AMORPH) p+=my_info->s*(*(d3_l->extra+off))*URAND_MAX/(i*i+j*j);
125    } 
126   }
127  }
128  p+=*conc*my_info->c*URAND_MAX;
129  if(p>=URAND_MAX) MAKE_AMORPH(thiz);
130  else {
131   if(!(*thiz&AMORPH)) {
132    if(get_rand(URAND_MAX)<=p) MAKE_AMORPH(thiz);
133   }
134   else {
135    /* assume 1-p probability */
136    /* also look for neighbours ! */
137    q=(URAND_MAX-p)>0?URAND_MAX-p:0;
138    j=0;
139    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;
140    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;
141    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;
142    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;
143    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;
144    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;
145  
146    p+=((q/6)*j);
147    if(p<=URAND_MAX) {
148     if(get_rand(URAND_MAX)>p) MAKE_CRYST(thiz);
149    }
150   }
151  }
152  
153  return 1;
154 }
155
156 int distrib_c(d3_lattice *d3_l,info *my_info,int step,u32 rj_m,u32 *rj_g)
157 {
158  u32 x,y,z;
159  int i,j,k,c;
160  int offset,off;
161  int carry;
162
163  /* put one c ion somewhere in the lattice */
164  x=get_rand(d3_l->max_x);
165  y=get_rand(d3_l->max_y);
166  z=get_rand_reject(d3_l->max_z,rj_m,rj_g);
167  *(d3_l->extra+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y)+=1;
168  (my_info->cc)++;
169
170  if(step%my_info->diff_rate==0)
171  {
172
173  for(i=0;i<d3_l->max_x;i++)
174  {
175   for(j=0;j<d3_l->max_y;j++)
176   {
177    for(k=0;k<d3_l->max_z;k++)
178    {
179     offset=i+j*d3_l->max_x+k*d3_l->max_x*d3_l->max_y;
180     /* case amorph: amorph <- cryst diffusion */
181     if(*(d3_l->status+offset)&AMORPH)
182     {
183      for(c=-1;c<=1;c++)
184      {
185       if(c!=0)
186       {
187        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;
188        carry=0;
189        if(!(*(d3_l->status+off)&AMORPH)) carry=(int)(my_info->dr_ac*(*(d3_l->extra+off)));
190        if(carry!=0)
191        {
192         *(d3_l->extra+offset)+=carry;
193         *(d3_l->extra+off)-=carry;
194        }
195       }
196      }
197      for(c=-1;c<=1;c++)
198      {
199       if(c!=0)
200       {
201        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;
202        carry=0;
203        if(!(*(d3_l->status+off)&AMORPH)) carry=(int)(my_info->dr_ac*(*(d3_l->extra+off)));
204        if(carry!=0)
205        {
206         *(d3_l->extra+offset)+=carry; 
207         *(d3_l->extra+off)-=carry; 
208        }
209       }
210      }
211      /* diff in z direction */
212      if(k!=0)
213      {
214       off=i+j*d3_l->max_x+(k-1)*d3_l->max_x*d3_l->max_y;
215       carry=0;
216       if(!*(d3_l->status+off)&AMORPH) carry=(int)(my_info->dr_ac*(*(d3_l->extra+off)));
217       if(carry!=0)
218       {
219        *(d3_l->extra+off)-=carry;
220        *(d3_l->extra+offset)+=carry;
221       }
222      }
223      if(k!=d3_l->max_z-1)
224      {
225       off=i+j*d3_l->max_x+(k+1)*d3_l->max_x*d3_l->max_y;
226       carry=0;
227       if(!*(d3_l->status+off)&AMORPH) carry=(int)(my_info->dr_ac*(*(d3_l->extra+off)));
228       if(carry!=0)
229       {
230        *(d3_l->extra+off)-=carry;
231        *(d3_l->extra+offset)+=carry;
232       }
233      }
234     }
235    } /* for z */
236   } /* for y */
237  } /* for x */
238
239  } /* if step modulo diff_rate == 0 */
240
241  return 1;
242 }
243
244 u32 get_reject_graph(info *my_info,d3_lattice *d3_l,char *file,u32 *graph) {
245  double a,b;
246  int i,j,k;
247  int fd;
248  char buf[32],*p;
249  unsigned char *flag;
250  u32 max;
251
252  max=0;
253  if((fd=open(file,O_RDONLY))<0)
254  {
255   puts("cannot open file to calculate rejection graph");
256   return -1;
257  }
258  if((flag=(unsigned char *)malloc(d3_l->max_z))==NULL)
259  {
260   puts("cannot malloc flag memory for rejection graph");
261   return -1;
262  }
263  memset(flag,0,d3_l->max_z);
264  memset(graph,0,d3_l->max_z*sizeof(u32));
265  /* get fixpoints */
266  k=1;
267  while(k)
268  {
269   for(i=0;i<32;i++)
270   {
271    k=read(fd,&buf[i],1);
272    if((buf[i]=='\n')||(k==0)) break;
273   }
274   if(k)
275   {
276    p=strtok(buf," ");
277    a=atof(p)/10; /* nm */
278    p=strtok(NULL," ");
279    b=atof(p);
280    if(a>d3_l->max_z*CELL_LENGTH) k=0;
281    else 
282    {
283     graph[(int)(a/CELL_LENGTH)]=(int)(URAND_MAX/100*b);
284     flag[(int)(a/CELL_LENGTH)]=1;
285    }
286   }
287  }
288  /* do (linear) interpolation here! */
289  i=0;
290  a=0;
291  while(i<d3_l->max_z)
292  {
293   /* graph[0] is 0! */
294   j=i;
295   i++;
296   while(flag[i]==0&&i<d3_l->max_z) i++;
297   for(k=j+1;k<i;k++) graph[k]=(int)((k-j)*((int)graph[i]-(int)graph[j])/(i-j))+graph[j];
298   if(graph[i]>max) max=graph[i];
299  }
300
301  free(flag);
302
303 #ifdef DEBUG_INTERPOL_PROFILE
304  printf("debug: %s (interpolated profile)\n",file);
305  for(i=0;i<d3_l->max_z;i++) printf("%d %d\n",i,graph[i]);
306 #endif
307
308  return max;
309 }
310
311 void send_data(int signum) {
312
313   int c;
314   unsigned char ack=DATA_OK;
315
316   c=gd3_l->max_x*gd3_l->max_y*gd3_l->max_z;
317
318   network_send_chan(gnet,0,&dc,1);
319   network_send_chan(gnet,0,(unsigned char *)gd3_l,sizeof(d3_lattice));
320   network_send_chan(gnet,0,(unsigned char *)gmy_info,sizeof(info));
321   network_send_chan(gnet,0,gd3_l->status,c*sizeof(unsigned char));
322   network_send_chan(gnet,0,(unsigned char *)gd3_l->extra,c*sizeof(int));
323   network_send_chan(gnet,0,(unsigned char *)gi,sizeof(int));
324   network_send_chan(gnet,0,&ack,sizeof(unsigned char));
325
326   if(dc==DC_QUIT) shut_down=1;
327 }
328
329
330 /*
331  * main program
332  */
333
334 int main(int argc,char **argv)
335 {
336
337   char server_ip[16];
338   int port;
339   t_net net;
340   t_event event;
341   unsigned char data[256];
342   int i;
343
344   gnet=&net;
345
346   /* default values */
347   strcpy(server_ip,"137.250.82.105");
348   strcpy(p_file,IMP_PROFILE);
349   strcpy(n_e_file,NEL_PROFILE);
350   strcpy(r_file,"");
351   port=1025;
352
353   /* parse/check argv */
354   for(i=1;i<argc;i++) {
355     if(argv[i][0]=='-') {
356       switch(argv[i][1]) {
357         case 'h':
358           usage(argv[0]);
359           return -1;
360         case 'i':
361           strncpy(server_ip,argv[++i],16);
362           break;
363         case 'r':
364           strcpy(r_file,argv[++i]);
365           break;
366         case 'P':
367           strcpy(p_file,argv[++i]);
368           break;
369         case 'n':
370           strcpy(n_e_file,argv[++i]);
371           break;
372         case 'p':
373           port=atoi(argv[++i]);
374           break;
375         default:
376           usage(argv[0]);
377           return -1;
378       }
379     }
380   }
381   if(!strcmp(server_ip,"")) {
382     usage(argv[0]);
383     return -1;
384   }
385
386   /* event init */
387   event_init(&event,1);
388   event_set_timeout(&event,0,0);
389
390   /* connect to server */
391   network_init(&net,1);
392   network_set_connection_info(&net,0,server_ip,port);
393   if(network_connect(&net,0)==N_E_CONNECT) {
394     printf("unable to connect to server, aborting ...\n");
395     return -1;
396   }
397   network_select(&net,0);
398
399   /* tell server: i am a client, i may work for you */
400   data[0]=NLSOP_CLIENT;
401   network_send(net.connection[0].fd,data,1);
402
403   /* wait for job */
404   event_math(net.connection[0].fd,&event,READ,ADD);
405   printf("idle, waiting for jobs ...\n");
406   event_start(&event,NULL,get_data_and_calc,nop);
407
408   network_shutdown(&net);
409
410   return 1;
411 }
412
413 int nop(t_event *event,void *allineed) {
414
415   printf("\ni did a nop :)\n");
416
417   return 1;
418 }
419
420 int get_data_and_calc(t_event *event,void *allineed) {
421
422   d3_lattice d3_l;
423   info my_info;
424   u32 *c_profile;
425   u32 *n_e_loss;
426   u32 ne_max,ip_max;
427   u32 *nel_z;
428   u32 x_c,y_c,z_c;
429   int i,j;
430   int c_step;
431   unsigned char data;
432
433   t_net *net;
434
435   c_step=0;
436   ne_max=0;
437   ip_max=0;
438
439   net=gnet;
440   gd3_l=&d3_l;
441   gmy_info=&my_info;
442   gi=&i;
443   dc=0;
444   shut_down=0;
445
446   printf("got a new job ...\n");
447   
448   /* get info (+data) */
449   network_receive(net->connection[0].fd,&data,sizeof(unsigned char));
450   if(data==NLSOP_NJOB || data==NLSOP_CJOB) {
451     network_receive(net->connection[0].fd,(unsigned char *)&d3_l,
452                     sizeof(d3_lattice));
453     network_receive(net->connection[0].fd,(unsigned char *)&my_info,
454                     sizeof(info));
455     c_step=0;
456     j=d3_l.max_x*d3_l.max_y*d3_l.max_z;
457     d3_l.status=(unsigned char *)malloc(j*sizeof(unsigned char));
458     if(d3_l.status==NULL) {
459       printf("status alloc failed\n");
460       return -1;
461     }
462     d3_l.extra=(int *)malloc(j*sizeof(int));
463     if(d3_l.extra==NULL) {
464       printf("extra malloc failed\n");
465       return -1;
466     }
467     if(data==NLSOP_CJOB) {
468       data=DATA_OK;
469       network_receive(net->connection[0].fd,d3_l.status,
470                       j*sizeof(unsigned char));
471       network_send(net->connection[0].fd,&data,sizeof(unsigned char));
472       network_receive(net->connection[0].fd,(unsigned char *)d3_l.extra,
473                       j*sizeof(int));
474       network_send(net->connection[0].fd,&data,sizeof(unsigned char));
475       network_receive(net->connection[0].fd,(unsigned char *)&c_step,
476                       sizeof(int));
477       network_send(net->connection[0].fd,&data,sizeof(unsigned char));
478     }
479     if(c_step==0) {
480       printf("important: clear status/conc data!\n");
481       memset(d3_l.status,0,j*sizeof(unsigned char));
482       memset(d3_l.extra,0,j*sizeof(int));
483     }
484   }
485   else {
486     printf("unknown instruction, restarting ...\n");
487     return -1;
488   }
489
490   printf("starting simulation with following parameters:\n");
491   printf("b = %f | c = %f | s = %f\n",my_info.b,my_info.c,my_info.s);
492   printf("diff every %d steps | diff rate = %f\n",my_info.diff_rate,
493                                                   my_info.dr_ac);
494   printf("current step: %d | total steps: %d\n",c_step,my_info.steps);
495   printf("...\n");
496
497   /* care for signals */
498   dc=DC_QUIT;
499   signal(SIGTERM,send_data);
500
501   /* rand init */
502   if(!strcmp(r_file,"")) rand_init(NULL);
503   else rand_init(r_file);
504
505   /* compute graphs for random number rejection method */
506   if((c_profile=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int)))==NULL) {
507     puts("failed allocating memory for carbon profile graph");
508     return -1;
509   }
510   if((n_e_loss=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int)))==NULL) {
511     puts("failed allocating memory for nuclear energy loss graph");
512     return -1;
513   }
514   ip_max=get_reject_graph(&my_info,&d3_l,p_file,c_profile);
515   ne_max=get_reject_graph(&my_info,&d3_l,n_e_file,n_e_loss);
516
517   /* array nel_z[] keeping nuclear energy loss values scaled to URAND_MAX */
518   nel_z=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int));
519   if(nel_z==NULL) {
520     printf("failed allocating nel_z array mem\n");
521     return -1;
522   }
523   for(i=0;i<d3_l.max_z;i++) nel_z[i]=URAND_MAX*(1.0*n_e_loss[i]/ne_max);
524
525   /* this should be obsolete - z is high enough - we check now! */
526   if(c_profile[d3_l.max_z-1]!=0) {
527     printf("max_z (%d) too small - sputtering not possible\n",d3_l.max_z);
528     return -1;
529   }
530
531   /* sputtering really possible ?*/
532   if(n_e_loss[d3_l.max_z-1]!=0)
533     printf("warning: max_z (%d) too small, there may be amorphous volumes\n",
534            d3_l.max_z);
535
536   /*
537    * start of simulation
538    */
539
540   i=(c_step?c_step:0);
541   while(i<my_info.steps) {
542     for(j=0;j<my_info.cpi;j++) {
543       x_c=get_rand(d3_l.max_x);
544       y_c=get_rand(d3_l.max_y);
545       z_c=get_rand_reject(d3_l.max_z,ne_max,n_e_loss);
546       //z_c=get_rand(d3_l.max_z);
547       process_cell(&d3_l,x_c,y_c,z_c,&my_info,nel_z[z_c]);
548     }
549     distrib_c(&d3_l,&my_info,i,ip_max,c_profile);
550     i++;
551     if(i%my_info.save_rate==0) {
552       dc=DC_OK;
553       send_data(0);
554       dc=DC_QUIT;
555     }
556     if(i%my_info.s_rate==0) sputter(&d3_l);
557     if(shut_down) {
558       free(d3_l.status);
559       free(d3_l.extra);
560       free(c_profile);
561       free(n_e_loss);
562       free(nel_z);
563       event_stop(event); 
564     }
565   }
566
567   /* finished */
568   dc=DC_END;
569   send_data(0);
570   dc=DC_QUIT;
571
572   /* shutdown/free/close everything now ... */
573   free(d3_l.status);
574   free(d3_l.extra);
575   free(c_profile);
576   free(n_e_loss);
577   free(nel_z);
578
579   return 1;
580 }