added nlsop_gui.c (not finished yet) + fixes to server and 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 #include "nlsop_general.h"
53
54 #define MAKE_AMORPH(N) *(N)|=AMORPH
55 #define MAKE_CRYST(N) *(N)&=~AMORPH
56
57 #define NLSOP_CLIENT 'c'
58 #define NLSOP_NJOB 'N'
59 #define NLSOP_CJOB 'C'
60
61 /* globals */
62
63 char p_file[MAX_CHARS];
64 char n_e_file[MAX_CHARS];
65 char r_file[MAX_CHARS];
66 t_net *gnet;
67 d3_lattice *gd3_l;
68 info *gmy_info;
69 int *gi;
70 unsigned char dc;
71
72 int get_data_and_calc(t_event *event,void *allineed);
73
74 int usage(char *prog)
75 {
76  puts("usage:");
77  printf("%s -i ip -p port -r/P/n random/profile/neloss file\n",prog);
78  return 1;
79 }
80
81 /*
82  * nlsop internal functions
83  */
84
85 int sputter(d3_lattice *d3_l)
86 {
87  int i,size;
88  int offh,offl;
89
90  size=d3_l->max_x*d3_l->max_y;
91  offl=0;
92  offh=size;
93
94  for(i=0;i<d3_l->max_z-1;i++)
95  {
96   memcpy(d3_l->status+offl,d3_l->status+offh,size);
97   memcpy(d3_l->extra+offl,d3_l->extra+offh,size*sizeof(int));
98   offl=offh;
99   offh+=size;
100  }
101  memset(d3_l->status+offl,0,size);
102  memset(d3_l->extra+offl,0,size);
103
104  return 1;
105 }
106
107 int process_cell(d3_lattice *d3_l,u32 x,u32 y,u32 z,info *my_info,u32 nel_z)
108 {
109  unsigned char *thiz;
110  int *conc;
111  int i,j;
112  int off;
113  double p,q;
114
115  thiz=d3_l->status+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y;
116  conc=d3_l->extra+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y;
117  p=my_info->b*nel_z;
118  for(i=-(my_info->range);i<=my_info->range;i++)
119  {
120   for(j=-(my_info->range);j<=my_info->range;j++)
121   {
122    if(!(i==0 && j==0))
123    {
124     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;
125     if(*(d3_l->status+off)&AMORPH) p+=my_info->s*(*(d3_l->extra+off))*URAND_MAX/(i*i+j*j);
126    } 
127   }
128  }
129  p+=*conc*my_info->c*URAND_MAX;
130  if(!(*thiz&AMORPH))
131  {
132   if(get_rand(URAND_MAX)<=p) MAKE_AMORPH(thiz);
133  } else
134  {
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(get_rand(URAND_MAX)>p) MAKE_CRYST(thiz);
148  }
149  
150  return 1;
151 }
152
153 int distrib_c(d3_lattice *d3_l,info *my_info,int step,u32 rj_m,u32 *rj_g)
154 {
155  u32 x,y,z;
156  int i,j,k,c;
157  int offset,off;
158  int carry;
159
160  /* put one c ion somewhere in the lattice */
161  x=get_rand(d3_l->max_x);
162  y=get_rand(d3_l->max_y);
163  z=get_rand_reject(d3_l->max_z,rj_m,rj_g);
164  *(d3_l->extra+x+y*d3_l->max_x+z*d3_l->max_x*d3_l->max_y)+=1;
165  (my_info->cc)++;
166
167  if(step%my_info->diff_rate==0)
168  {
169
170  for(i=0;i<d3_l->max_x;i++)
171  {
172   for(j=0;j<d3_l->max_y;j++)
173   {
174    for(k=0;k<d3_l->max_z;k++)
175    {
176     offset=i+j*d3_l->max_x+k*d3_l->max_x*d3_l->max_y;
177     /* case amorph: amorph <- cryst diffusion */
178     if(*(d3_l->status+offset)&AMORPH)
179     {
180      for(c=-1;c<=1;c++)
181      {
182       if(c!=0)
183       {
184        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;
185        carry=0;
186        if(!(*(d3_l->status+off)&AMORPH)) carry=(int)(my_info->dr_ac*(*(d3_l->extra+off)));
187        if(carry!=0)
188        {
189         *(d3_l->extra+offset)+=carry;
190         *(d3_l->extra+off)-=carry;
191        }
192       }
193      }
194      for(c=-1;c<=1;c++)
195      {
196       if(c!=0)
197       {
198        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;
199        carry=0;
200        if(!(*(d3_l->status+off)&AMORPH)) carry=(int)(my_info->dr_ac*(*(d3_l->extra+off)));
201        if(carry!=0)
202        {
203         *(d3_l->extra+offset)+=carry; 
204         *(d3_l->extra+off)-=carry; 
205        }
206       }
207      }
208      if(my_info->z_diff)
209      {
210       if(k!=0)
211       {
212        off=i+j*d3_l->max_x+(k-1)*d3_l->max_x*d3_l->max_y;
213        carry=0;
214        if(!*(d3_l->status+off)&AMORPH) carry=(int)(my_info->dr_ac*(*(d3_l->extra+off)));
215        if(carry!=0)
216        {
217         *(d3_l->extra+off)-=carry;
218         *(d3_l->extra+offset)+=carry;
219        }
220       }
221       if(k!=d3_l->max_z-1)
222       {
223        off=i+j*d3_l->max_x+(k+1)*d3_l->max_x*d3_l->max_y;
224        carry=0;
225        if(!*(d3_l->status+off)&AMORPH) carry=(int)(my_info->dr_ac*(*(d3_l->extra+off)));
226        if(carry!=0)
227        {
228         *(d3_l->extra+off)-=carry;
229         *(d3_l->extra+offset)+=carry;
230        }
231       }
232      }  
233     }
234    } /* for z */
235   } /* for y */
236  } /* for x */
237
238  } /* if step modulo diff_rate == 0 */
239
240  return 1;
241 }
242
243 u32 get_reject_graph(info *my_info,d3_lattice *d3_l,char *file,u32 *graph) {
244  double a,b;
245  int i,j,k;
246  int fd;
247  char buf[32],*p;
248  unsigned char *flag;
249  u32 max;
250
251  max=0;
252  if((fd=open(file,O_RDONLY))<0)
253  {
254   puts("cannot open file to calculate rejection graph");
255   return -1;
256  }
257  if((flag=(unsigned char *)malloc(d3_l->max_z))==NULL)
258  {
259   puts("cannot malloc flag memory for rejection graph");
260   return -1;
261  }
262  memset(flag,0,d3_l->max_z);
263  memset(graph,0,d3_l->max_z*sizeof(u32));
264  /* get fixpoints */
265  k=1;
266  while(k)
267  {
268   for(i=0;i<32;i++)
269   {
270    k=read(fd,&buf[i],1);
271    if((buf[i]=='\n')||(k==0)) break;
272   }
273   if(k)
274   {
275    p=strtok(buf," ");
276    a=atof(p)/10; /* nm */
277    p=strtok(NULL," ");
278    b=atof(p);
279    if(a>d3_l->max_z*CELL_LENGTH) k=0;
280    else 
281    {
282     graph[(int)(a/CELL_LENGTH)]=(int)(URAND_MAX/100*b);
283     flag[(int)(a/CELL_LENGTH)]=1;
284    }
285   }
286  }
287  /* do (linear) interpolation here! */
288  i=0;
289  a=0;
290  while(i<d3_l->max_z)
291  {
292   /* graph[0] is 0! */
293   j=i;
294   i++;
295   while(flag[i]==0&&i<d3_l->max_z) i++;
296   for(k=j+1;k<i;k++) graph[k]=(int)((k-j)*((int)graph[i]-(int)graph[j])/(i-j))+graph[j];
297   if(graph[i]>max) max=graph[i];
298  }
299
300  free(flag);
301
302 #ifdef DEBUG_INTERPOL_PROFILE
303  printf("debug: %s (interpolated profile)\n",file);
304  for(i=0;i<d3_l->max_z;i++) printf("%d %d\n",i,graph[i]);
305 #endif
306
307  return max;
308 }
309
310 void send_data(int signum) {
311
312   int c;
313
314   c=gd3_l->max_x*gd3_l->max_y*gd3_l->max_z;
315
316   network_send(gnet->connection[0].fd,&dc,1);
317   /*
318   network_send(gnet->connection[0].fd,(unsigned char *)gd3_l,
319                sizeof(d3_lattice));
320   network_send(gnet->connection[0].fd,(unsigned char *)gmy_info,sizeof(info));
321   */
322   network_send(gnet->connection[0].fd,gd3_l->status,c*sizeof(unsigned char));
323   network_send(gnet->connection[0].fd,(unsigned char *)gd3_l->extra,
324                c*sizeof(int));
325   network_send(gnet->connection[0].fd,(unsigned char *)gi,sizeof(int));
326
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,"");
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   event_start(&event,NULL,get_data_and_calc,NULL);
406
407   return 1;
408 }
409
410 int get_data_and_calc(t_event *event,void *allineed) {
411
412   d3_lattice d3_l;
413   info my_info;
414   u32 *c_profile;
415   u32 *n_e_loss;
416   u32 ne_max,ip_max;
417   u32 *nel_z;
418   u32 x_c,y_c,z_c;
419   int i,j;
420   int resave;
421   int c_step;
422   unsigned char data[256];
423
424   t_net *net;
425
426   resave=RESAVE;
427   c_step=0;
428   ne_max=0;
429   ip_max=0;
430
431   net=gnet;
432   gd3_l=&d3_l;
433   gmy_info=&my_info;
434   gi=&i;
435   dc=0;
436   
437   /* get info (+data) */
438   network_receive(net->connection[0].fd,data,1);
439   if(data[0]==NLSOP_NJOB || data[0]==NLSOP_CJOB) {
440     network_receive(net->connection[0].fd,(unsigned char *)&d3_l,
441                     sizeof(d3_lattice));
442     network_receive(net->connection[0].fd,(unsigned char *)&my_info,
443                     sizeof(info));
444     c_step=0;
445     j=d3_l.max_x*d3_l.max_y*d3_l.max_z;
446     d3_l.status=(unsigned char *)malloc(j*sizeof(unsigned char));
447     if(d3_l.status==NULL) {
448       printf("status alloc failed\n");
449       return -1;
450     }
451     d3_l.extra=(int *)malloc(j*sizeof(int));
452     if(d3_l.extra==NULL) {
453       printf("extra malloc failed\n");
454       return -1;
455     }
456     if(data[0]==NLSOP_CJOB) {
457       network_receive(net->connection[0].fd,d3_l.status,
458                       j*sizeof(unsigned char));
459       network_receive(net->connection[0].fd,(unsigned char *)d3_l.extra,
460                       j*sizeof(int));
461       network_receive(net->connection[0].fd,(unsigned char *)&c_step,
462                       sizeof(int));
463     }
464   }
465
466   /* care for signals */
467   dc=DC_QUIT;
468   signal(SIGTERM,send_data);
469
470   /* rand init */
471   if(!strcmp(r_file,"")) rand_init(NULL);
472   else rand_init(r_file);
473
474   /* compute graphs for random number rejection method */
475   if((c_profile=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int)))==NULL) {
476     puts("failed allocating memory for carbon profile graph");
477     return -1;
478   }
479   if((n_e_loss=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int)))==NULL) {
480     puts("failed allocating memory for nuclear energy loss graph");
481     return -1;
482   }
483   ip_max=get_reject_graph(&my_info,&d3_l,p_file,c_profile);
484   ne_max=get_reject_graph(&my_info,&d3_l,n_e_file,n_e_loss);
485
486   /* array nel_z[] keeping nuclear energy loss values scaled to URAND_MAX */
487   nel_z=(u32 *)malloc(d3_l.max_z*sizeof(unsigned int));
488   if(nel_z==NULL) {
489     printf("failed allocating nel_z array mem\n");
490     return -1;
491   }
492   for(i=0;i<d3_l.max_z;i++) nel_z[i]=URAND_MAX*(1.0*n_e_loss[i]/ne_max);
493
494   /* this should be obsolete - z is high enough - we check now! */
495   if(c_profile[d3_l.max_z-1]!=0) {
496     printf("max_z (%d) too small - sputtering not possible\n",d3_l.max_z);
497     return -1;
498   }
499
500   /* sputtering really possible ?*/
501   if(n_e_loss[d3_l.max_z-1]!=0)
502     printf("warning: max_z (%d) too small, there may be amorphous volumes\n",
503            d3_l.max_z);
504
505   /*
506    * start of simulation
507    */
508
509   i=(c_step?c_step:0);
510   while(i<my_info.steps) {
511     for(j=0;j<my_info.cpi;j++) {
512       x_c=get_rand(d3_l.max_x);
513       y_c=get_rand(d3_l.max_y);
514       // z_c=get_rand_reject(d3_l.max_z,ne_max,n_e_loss);
515       z_c=get_rand(d3_l.max_z);
516       process_cell(&d3_l,x_c,y_c,z_c,&my_info,nel_z[z_c]);
517     }
518     distrib_c(&d3_l,&my_info,i,ip_max,c_profile);
519     if(i%resave==0 && i!=0) {
520       dc=DC_OK;
521       send_data(0);
522       dc=DC_QUIT;
523     }
524     i++;
525     if(i%my_info.s_rate==0) sputter(&d3_l);
526   }
527
528   /* finished */
529   dc=DC_END;
530   send_data(0);
531   dc=DC_QUIT;
532
533   /* shutdown/free/close everything now ... */
534
535   return 1;
536 }