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