modified nlsop_client.c + added nlsop_server 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 -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;
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 u32 get_reject_graph(info *my_info,d3_lattice *d3_l,char *file,u32 *graph) {
242  double a,b;
243  int i,j,k;
244  int fd;
245  char buf[32],*p;
246  unsigned char *flag;
247  u32 max;
248
249  max=0;
250  if((fd=open(file,O_RDONLY))<0)
251  {
252   puts("cannot open file to calculate rejection graph");
253   return -1;
254  }
255  if((flag=(unsigned char *)malloc(d3_l->max_z))==NULL)
256  {
257   puts("cannot malloc flag memory for rejection graph");
258   return -1;
259  }
260  memset(flag,0,d3_l->max_z);
261  memset(graph,0,d3_l->max_z*sizeof(u32));
262  /* get fixpoints */
263  k=1;
264  while(k)
265  {
266   for(i=0;i<32;i++)
267   {
268    k=read(fd,&buf[i],1);
269    if((buf[i]=='\n')||(k==0)) break;
270   }
271   if(k)
272   {
273    p=strtok(buf," ");
274    a=atof(p)/10; /* nm */
275    p=strtok(NULL," ");
276    b=atof(p);
277    if(a>d3_l->max_z*CELL_LENGTH) k=0;
278    else 
279    {
280     graph[(int)(a/CELL_LENGTH)]=(int)(URAND_MAX/100*b);
281     flag[(int)(a/CELL_LENGTH)]=1;
282    }
283   }
284  }
285  /* do (linear) interpolation here! */
286  i=0;
287  a=0;
288  while(i<d3_l->max_z)
289  {
290   /* graph[0] is 0! */
291   j=i;
292   i++;
293   while(flag[i]==0&&i<d3_l->max_z) i++;
294   for(k=j+1;k<i;k++) graph[k]=(int)((k-j)*((int)graph[i]-(int)graph[j])/(i-j))+graph[j];
295   if(graph[i]>max) max=graph[i];
296  }
297
298  free(flag);
299
300 #ifdef DEBUG_INTERPOL_PROFILE
301  printf("debug: %s (interpolated profile)\n",file);
302  for(i=0;i<d3_l->max_z;i++) printf("%d %d\n",i,graph[i]);
303 #endif
304
305  return max;
306 }
307
308 void send_data(int signum) {
309
310   int c;
311
312   c=gd3_l->max_x*gd3_l->max_y*gd3_l->max_z;
313
314   network_send(gnet->connection[0].fd,&dc,1);
315   /*
316   network_send(gnet->connection[0].fd,(unsigned char *)gd3_l,
317                sizeof(d3_lattice));
318   network_send(gnet->connection[0].fd,(unsigned char *)gmy_info,sizeof(info));
319   */
320   network_send(gnet->connection[0].fd,gd3_l->status,c*sizeof(unsigned char));
321   network_send(gnet->connection[0].fd,(unsigned char *)gd3_l->extra,
322                c*sizeof(int));
323   network_send(gnet->connection[0].fd,(unsigned char *)gi,sizeof(int));
324
325 }
326
327
328 /*
329  * main program
330  */
331
332 int main(int argc,char **argv)
333 {
334
335   char server_ip[16];
336   int port;
337   t_net net;
338   t_event event;
339   unsigned char data[256];
340   int i;
341
342   gnet=&net;
343
344   /* default values */
345   strcpy(server_ip,"");
346   strcpy(p_file,IMP_PROFILE);
347   strcpy(n_e_file,NEL_PROFILE);
348   strcpy(r_file,"");
349   port=1025;
350
351   /* parse/check argv */
352   for(i=1;i<argc;i++) {
353     if(argv[i][0]=='-') {
354       switch(argv[i][1]) {
355         case 'h':
356           usage(argv[0]);
357           return -1;
358         case 'i':
359           strncpy(server_ip,argv[++i],16);
360           break;
361         case 'r':
362           strcpy(r_file,argv[++i]);
363           break;
364         case 'P':
365           strcpy(p_file,argv[++i]);
366           break;
367         case 'n':
368           strcpy(n_e_file,argv[++i]);
369           break;
370         case 'p':
371           port=atoi(argv[++i]);
372           break;
373         default:
374           usage(argv[0]);
375           return -1;
376       }
377     }
378   }
379   if(!strcmp(server_ip,"")) {
380     usage(argv[0]);
381     return -1;
382   }
383
384   /* event init */
385   event_init(&event,1);
386   event_set_timeout(&event,0,0);
387
388   /* connect to server */
389   network_init(&net,1);
390   network_set_connection_info(&net,0,server_ip,port);
391   if(network_connect(&net,0)==N_E_CONNECT) {
392     printf("unable to connect to server, aborting ...\n");
393     return -1;
394   }
395   network_select(&net,0);
396
397   /* tell server: i am a client, i may work for you */
398   data[0]=NLSOP_CLIENT;
399   network_send(net.connection[0].fd,data,1);
400
401   /* wait for job */
402   event_math(net.connection[0].fd,&event,READ,ADD);
403   event_start(&event,NULL,get_data_and_calc,NULL);
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 resave;
419   int c_step;
420 #define DC_QUIT (1<<0)
421 #define DC_OK (1<<1)
422 #define DC_END (1<<2)
423   unsigned char data[256];
424
425   t_net *net;
426
427   resave=RESAVE;
428   c_step=0;
429   ne_max=0;
430   ip_max=0;
431
432   net=gnet;
433   gd3_l=&d3_l;
434   gmy_info=&my_info;
435   gi=&i;
436   dc=0;
437   
438   /* get info (+data) */
439   network_receive(net->connection[0].fd,data,1);
440   if(data[0]==NLSOP_NJOB || data[0]==NLSOP_CJOB) {
441     network_receive(net->connection[0].fd,(unsigned char *)&d3_l,
442                     sizeof(d3_lattice));
443     network_receive(net->connection[0].fd,(unsigned char *)&my_info,
444                     sizeof(info));
445     c_step=0;
446     j=d3_l.max_x*d3_l.max_y*d3_l.max_z;
447     d3_l.status=(unsigned char *)malloc(j*sizeof(unsigned char));
448     if(d3_l.status==NULL) {
449       printf("status alloc failed\n");
450       return -1;
451     }
452     d3_l.extra=(int *)malloc(j*sizeof(int));
453     if(d3_l.extra==NULL) {
454       printf("extra malloc failed\n");
455       return -1;
456     }
457     if(data[0]==NLSOP_CJOB) {
458       network_receive(net->connection[0].fd,d3_l.status,
459                       j*sizeof(unsigned char));
460       network_receive(net->connection[0].fd,(unsigned char *)d3_l.extra,
461                       j*sizeof(int));
462       network_receive(net->connection[0].fd,(unsigned char *)&c_step,
463                       sizeof(int));
464     }
465   }
466
467   /* care for signals */
468   dc=DC_QUIT;
469   signal(SIGTERM,send_data);
470
471   /* rand init */
472   if(!strcmp(r_file,"")) rand_init(NULL);
473   else rand_init(r_file);
474
475   /* compute graphs for random number rejection method */
476   if((c_profile=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int)))==NULL) {
477     puts("failed allocating memory for carbon profile graph");
478     return -1;
479   }
480   if((n_e_loss=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int)))==NULL) {
481     puts("failed allocating memory for nuclear energy loss graph");
482     return -1;
483   }
484   ip_max=get_reject_graph(&my_info,&d3_l,p_file,c_profile);
485   ne_max=get_reject_graph(&my_info,&d3_l,n_e_file,n_e_loss);
486
487   /* array nel_z[] keeping nuclear energy loss values scaled to URAND_MAX */
488   nel_z=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int));
489   if(nel_z==NULL) {
490     printf("failed allocating nel_z array mem\n");
491     return -1;
492   }
493   for(i=0;i<d3_l.max_z;i++) nel_z[i]=URAND_MAX*(1.0*n_e_loss[i]/ne_max);
494
495   /* this should be obsolete - z is high enough - we check now! */
496   if(c_profile[d3_l.max_z-1]!=0) {
497     printf("max_z (%d) too small - sputtering not possible\n",d3_l.max_z);
498     return -1;
499   }
500
501   /* sputtering really possible ?*/
502   if(n_e_loss[d3_l.max_z-1]!=0)
503     printf("warning: max_z (%d) too small, there may be amorphous volumes\n",
504            d3_l.max_z);
505
506   /*
507    * start of simulation
508    */
509
510   i=(c_step?c_step:0);
511   while(i<my_info.steps) {
512     for(j=0;j<my_info.cpi;j++) {
513       x_c=get_rand(d3_l.max_x);
514       y_c=get_rand(d3_l.max_y);
515       // z_c=get_rand_reject(d3_l.max_z,ne_max,n_e_loss);
516       z_c=get_rand(d3_l.max_z);
517       process_cell(&d3_l,x_c,y_c,z_c,&my_info,nel_z[z_c]);
518     }
519     distrib_c(&d3_l,&my_info,i,ip_max,c_profile);
520     if(i%resave==0 && i!=0) {
521       dc=DC_OK;
522       send_data(0);
523       dc=DC_QUIT;
524     }
525     i++;
526     if(i%my_info.s_rate==0) sputter(&d3_l);
527   }
528
529   /* finished */
530   dc=DC_END;
531   send_data(0);
532   dc=DC_QUIT;
533
534   /* shutdown/free/close everything now ... */
535
536   return 1;
537 }