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