NEL_Z
[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
309   c=gd3_l->max_x*gd3_l->max_y*gd3_l->max_z;
310
311   network_send_chan(gnet,0,&dc,1);
312   network_send_chan(gnet,0,(unsigned char *)gd3_l,sizeof(d3_lattice));
313   network_send_chan(gnet,0,(unsigned char *)gmy_info,sizeof(info));
314   network_send_chan(gnet,0,gd3_l->status,c*sizeof(unsigned char));
315   network_send_chan(gnet,0,(unsigned char *)gd3_l->extra,c*sizeof(int));
316   network_send_chan(gnet,0,(unsigned char *)gi,sizeof(int));
317 }
318
319
320 /*
321  * main program
322  */
323
324 int main(int argc,char **argv)
325 {
326
327   char server_ip[16];
328   int port;
329   t_net net;
330   t_event event;
331   unsigned char data[256];
332   int i;
333
334   gnet=&net;
335
336   /* default values */
337   strcpy(server_ip,"137.250.82.105");
338   strcpy(p_file,IMP_PROFILE);
339   strcpy(n_e_file,NEL_PROFILE);
340   strcpy(r_file,"");
341   port=1025;
342
343   /* parse/check argv */
344   for(i=1;i<argc;i++) {
345     if(argv[i][0]=='-') {
346       switch(argv[i][1]) {
347         case 'h':
348           usage(argv[0]);
349           return -1;
350         case 'i':
351           strncpy(server_ip,argv[++i],16);
352           break;
353         case 'r':
354           strcpy(r_file,argv[++i]);
355           break;
356         case 'P':
357           strcpy(p_file,argv[++i]);
358           break;
359         case 'n':
360           strcpy(n_e_file,argv[++i]);
361           break;
362         case 'p':
363           port=atoi(argv[++i]);
364           break;
365         default:
366           usage(argv[0]);
367           return -1;
368       }
369     }
370   }
371   if(!strcmp(server_ip,"")) {
372     usage(argv[0]);
373     return -1;
374   }
375
376   /* event init */
377   event_init(&event,1);
378   event_set_timeout(&event,0,0);
379
380   /* connect to server */
381   network_init(&net,1);
382   network_set_connection_info(&net,0,server_ip,port);
383   if(network_connect(&net,0)==N_E_CONNECT) {
384     printf("unable to connect to server, aborting ...\n");
385     return -1;
386   }
387   network_select(&net,0);
388
389   /* tell server: i am a client, i may work for you */
390   data[0]=NLSOP_CLIENT;
391   network_send(net.connection[0].fd,data,1);
392
393   /* wait for job */
394   event_math(net.connection[0].fd,&event,READ,ADD);
395   printf("idle, waiting for jobs ...\n");
396   event_start(&event,NULL,get_data_and_calc,nop);
397
398   return 1;
399 }
400
401 int nop(t_event *event,void *allineed) {
402
403   printf("\ni did a nop :)\n");
404
405   return 1;
406 }
407
408 int get_data_and_calc(t_event *event,void *allineed) {
409
410   d3_lattice d3_l;
411   info my_info;
412   u32 *c_profile;
413   u32 *n_e_loss;
414   u32 ne_max,ip_max;
415   u32 *nel_z;
416   u32 x_c,y_c,z_c;
417   int i,j;
418   int c_step;
419   unsigned char data;
420
421   t_net *net;
422
423   c_step=0;
424   ne_max=0;
425   ip_max=0;
426
427   net=gnet;
428   gd3_l=&d3_l;
429   gmy_info=&my_info;
430   gi=&i;
431   dc=0;
432
433   printf("got a new job ...\n");
434   
435   /* get info (+data) */
436   network_receive(net->connection[0].fd,&data,sizeof(unsigned char));
437   if(data==NLSOP_NJOB || data==NLSOP_CJOB) {
438     network_receive(net->connection[0].fd,(unsigned char *)&d3_l,
439                     sizeof(d3_lattice));
440     network_receive(net->connection[0].fd,(unsigned char *)&my_info,
441                     sizeof(info));
442     c_step=0;
443     j=d3_l.max_x*d3_l.max_y*d3_l.max_z;
444     d3_l.status=(unsigned char *)malloc(j*sizeof(unsigned char));
445     if(d3_l.status==NULL) {
446       printf("status alloc failed\n");
447       return -1;
448     }
449     d3_l.extra=(int *)malloc(j*sizeof(int));
450     if(d3_l.extra==NULL) {
451       printf("extra malloc failed\n");
452       return -1;
453     }
454     if(data==NLSOP_CJOB) {
455       data=DATA_OK;
456       network_receive(net->connection[0].fd,d3_l.status,
457                       j*sizeof(unsigned char));
458       network_send(net->connection[0].fd,&data,sizeof(unsigned char));
459       network_receive(net->connection[0].fd,(unsigned char *)d3_l.extra,
460                       j*sizeof(int));
461       network_send(net->connection[0].fd,&data,sizeof(unsigned char));
462       network_receive(net->connection[0].fd,(unsigned char *)&c_step,
463                       sizeof(int));
464       network_send(net->connection[0].fd,&data,sizeof(unsigned char));
465     }
466   }
467   else {
468     printf("unknown instruction, restarting ...\n");
469     return -1;
470   }
471
472   printf("starting simulation with following parameters:\n");
473   printf("b = %f | c = %f | s = %f\n",my_info.b,my_info.c,my_info.s);
474   printf("diff every %d steps | diff rate = %f\n",my_info.diff_rate,
475                                                   my_info.dr_ac);
476   printf("current step: %d | total steps: %d\n",c_step,my_info.steps);
477   printf("...\n");
478
479   /* care for signals */
480   dc=DC_QUIT;
481   signal(SIGTERM,send_data);
482
483   /* rand init */
484   if(!strcmp(r_file,"")) rand_init(NULL);
485   else rand_init(r_file);
486
487   /* compute graphs for random number rejection method */
488   if((c_profile=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int)))==NULL) {
489     puts("failed allocating memory for carbon profile graph");
490     return -1;
491   }
492   if((n_e_loss=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int)))==NULL) {
493     puts("failed allocating memory for nuclear energy loss graph");
494     return -1;
495   }
496   ip_max=get_reject_graph(&my_info,&d3_l,p_file,c_profile);
497   ne_max=get_reject_graph(&my_info,&d3_l,n_e_file,n_e_loss);
498
499   /* array nel_z[] keeping nuclear energy loss values scaled to URAND_MAX */
500   nel_z=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int));
501   if(nel_z==NULL) {
502     printf("failed allocating nel_z array mem\n");
503     return -1;
504   }
505   for(i=0;i<d3_l.max_z;i++) nel_z[i]=URAND_MAX*(1.0*n_e_loss[i]/ne_max);
506
507   /* this should be obsolete - z is high enough - we check now! */
508   if(c_profile[d3_l.max_z-1]!=0) {
509     printf("max_z (%d) too small - sputtering not possible\n",d3_l.max_z);
510     return -1;
511   }
512
513   /* sputtering really possible ?*/
514   if(n_e_loss[d3_l.max_z-1]!=0)
515     printf("warning: max_z (%d) too small, there may be amorphous volumes\n",
516            d3_l.max_z);
517
518   /*
519    * start of simulation
520    */
521
522   i=(c_step?c_step:0);
523   while(i<my_info.steps) {
524     for(j=0;j<my_info.cpi;j++) {
525       x_c=get_rand(d3_l.max_x);
526       y_c=get_rand(d3_l.max_y);
527 #ifdef NEL_Z
528       z_c=get_rand_reject(d3_l.max_z,ne_max,n_e_loss);
529 #else
530       z_c=get_rand(d3_l.max_z);
531 #fi
532       process_cell(&d3_l,x_c,y_c,z_c,&my_info,nel_z[z_c]);
533     }
534     distrib_c(&d3_l,&my_info,i,ip_max,c_profile);
535     i++;
536     if(i%my_info.save_rate==0) {
537       dc=DC_OK;
538       send_data(0);
539       dc=DC_QUIT;
540     }
541     if(i%my_info.s_rate==0) sputter(&d3_l);
542   }
543
544   /* finished */
545   dc=DC_END;
546   send_data(0);
547   dc=DC_QUIT;
548
549   /* shutdown/free/close everything now ... */
550   free(d3_l.status);
551   free(d3_l.extra);
552   free(c_profile);
553   free(n_e_loss);
554   free(nel_z);
555
556   return 1;
557 }