258770d5fcfae965135445c511b50df0685a955d
[alexxy/gromacs.git] / src / contrib / ionize.c
1 /*
2  * $Id$
3  * 
4  *       This source code is part of
5  * 
6  *        G   R   O   M   A   C   S
7  * 
8  * GROningen MAchine for Chemical Simulations
9  * 
10  *               VERSION 2.0
11  * 
12  * Copyright (c) 1991-1999
13  * BIOSON Research Institute, Dept. of Biophysical Chemistry
14  * University of Groningen, The Netherlands
15  * 
16  * Please refer to:
17  * GROMACS: A message-passing parallel molecular dynamics implementation
18  * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19  * Comp. Phys. Comm. 91, 43-56 (1995)
20  * 
21  * Also check out our WWW page:
22  * http://md.chem.rug.nl/~gmx
23  * or e-mail to:
24  * gromacs@chem.rug.nl
25  * 
26  * And Hey:
27  * Great Red Oystrich Makes All Chemists Sane
28  */
29 static char *SRCID_ionize_c = "$Id$";
30
31 #include <string.h>
32 #include "smalloc.h"
33 #include "typedefs.h"
34 #include "macros.h"
35 #include "random.h"
36 #include "physics.h"
37 #include "xvgr.h"
38 #include "vec.h"
39 #include "pbc.h"
40 #include "txtdump.h"
41 #include "ionize.h"
42 #include "names.h"
43 #include "futil.h"
44 #include "network.h"
45 #include "ion_data.h"
46
47 #define PREFIX "IONIZE: "
48
49 enum { eionCYL, eionSURF, eionGAUSS, eionNR };
50
51 enum { ecollPHOTO, ecollINELASTIC, ecollNR };
52
53 typedef struct {
54   int  z,n,k;
55   real fj,sigPh,sigIn,vAuger;
56 } t_cross_atom;
57
58 typedef struct {
59   int nelec,maxelec,elec0,elmin_type;
60 } t_electron_db;
61
62 /* BEGIN GLOBAL VARIABLES */
63 static int   Energies[] = { 6, 8, 10, 12, 15, 20 };
64 static int   ionize_seed = 1993;
65 #define NENER asize(Energies)
66
67 static t_electron_db edb;
68
69 /* END GLOBAL VARIABLES */
70
71 void dump_ca(FILE *fp,t_cross_atom *ca,int i,char *file,int line)
72 {
73   fprintf(fp,PREFIX"(line %d) atom %d, z = %d, n = %d, k = %d\n",
74           line,i,ca->z,ca->n,ca->k);
75 }
76
77 t_cross_atom *mk_cross_atom(FILE *log,t_mdatoms *md,
78                             char **atomname[],int Eindex)
79 {
80   int elem_index[] = { 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 5, 6 };
81   t_cross_atom *ca;
82   int  *elemcnt;
83   char *cc;
84   int  i,j;
85   
86   fprintf(log,PREFIX"Filling data structure for ionization\n");
87   fprintf(log,PREFIX"Warning: all fj values set to 0.95 for now\n");
88   snew(ca,md->nr);
89   snew(elemcnt,NELEM+1);
90   for(i=0; (i<md->nr); i++) {
91     ca[i].n = 0;
92     ca[i].k = 0;
93     cc = *(atomname[i]);
94     for(j=0; (j<NELEM); j++)
95       if (strncmp(cc,element[j].name,strlen(element[j].name)) == 0) {
96         ca[i].z = element[j].nel;
97         break;
98       }
99     if (j == NELEM) 
100       fatal_error(0,PREFIX"Don't know number of electrons for %s",
101                   *atomname[i]);
102     elemcnt[j]++;
103
104     ca[i].sigPh = element[elem_index[ca[i].z]].cross[Eindex].photo;
105     ca[i].sigIn = element[elem_index[ca[i].z]].cross[Eindex].incoh;
106     ca[i].fj    = recoil[ca[i].z].Prob_K;
107     switch (ca[i].z) {
108     case 6:
109       ca[i].vAuger  = 0.904;
110       break;
111     case 7:
112       ca[i].vAuger  = 0.920;
113       break;
114     case 8:
115       ca[i].vAuger  = 0.929;
116       break;
117     case 16:
118     case 20:
119       ca[i].vAuger = 1.0;
120       break;
121     default:
122       ca[i].vAuger= -1;
123     }
124   }
125   
126   fprintf(log,PREFIX"You have the following elements in your system (%d atoms):\n"PREFIX,md->nr);
127   for(j=0; (j<NELEM); j++)
128     if (elemcnt[j] > 0)
129       fprintf(log,"  %s: %d",element[j].name,elemcnt[j]);
130   fprintf(log," atoms\n");
131
132   sfree(elemcnt);
133   
134   return ca;
135 }
136
137 int number_K(t_cross_atom *ca)
138 {
139   if (ca->z <= 2)
140     return ca->z-ca->n;
141   else
142     return 2-ca->k;
143 }
144
145 int number_L(t_cross_atom *ca)
146 {
147   return ca->k-2+ca->z-ca->n;
148 }
149
150 real xray_cross_section(int eColl,t_cross_atom *ca)
151 {
152   real c=0;
153   int  nK,nL;
154   
155   switch (eColl) {
156   case ecollPHOTO:
157     nK = number_K(ca);
158     nL = number_L(ca);
159     if (ca->z == 1)
160       c = ca->sigPh;
161     else if (ca->z == 2)
162       c = ca->sigPh*0.5;
163     else
164       c = (nK*0.5*ca->fj + nL/(ca->z-2)*(1-ca->fj))*ca->sigPh;
165     break;
166   case ecollINELASTIC:
167     c = (ca->z-ca->n)*ca->sigIn/ca->z;
168     break;
169   default:
170     fatal_error(0,"No such collision type %d\n",eColl);
171   }
172   return c;
173 }
174
175 real prob_K(int eColl,t_cross_atom *ca)
176 {
177   real Pl,Pk,P=0;
178   
179   if ((ca->z <= 2) || (ca->z == ca->n))
180     return 0;
181
182   switch (eColl) {
183   case ecollPHOTO:
184     Pl = (ca->k-2+ca->z-ca->n)*(1-ca->fj)/(ca->z-2);
185     Pk = (2-ca->k)*ca->fj*0.5;
186     P  = Pk/(Pl+Pk);
187     break;
188   case ecollINELASTIC:
189     P = (2-ca->k)/(ca->z-ca->n);
190     break;
191   default:
192     fatal_error(0,"No such collision type %d\n",eColl);
193   } 
194   return P;
195 }
196
197 double myexp(double x)
198 {
199   if (x < -70)
200     return 0.0;
201   else
202     return exp(x);
203 }
204
205 real ptheta_incoh(int Eindex,real theta) 
206      /* theta should be in degrees */
207 {
208   /* These numbers generated by fitting 5 gaussians to the real function
209    * that describes the probability for theta.
210    * We use symmetry in the gaussian (see 180-angle) therefore there
211    * are fewer parameters (only 8 per energylevel).
212    */
213   static double ppp[NENER][8] = {
214     { -0.00295169, 10.4847, 0.0341099, /*-*/43.1963, 
215       -0.0164054,  30.2452, 71.0311,    2.50282 },
216     { -0.00370852, 9.02037, 0.100559,  /*-*/42.9962,
217       -0.0537891,  35.5077, 71.4305,    1.05515 },
218     { -0.00427039, 7.86831, 0.118042,  /*-*/45.9846,
219       -0.0634505,  38.6134, 70.3857,    0.240082 },
220     { -0.004514,   7.0728,  0.13464,  /*-*/48.213,
221       -0.0723,     41.06,   69.38,     -0.02 },
222     { -0.00488796, 5.87988, 0.159574,  /*-*/51.5556,
223       -0.0855767,  44.7307, 69.0251,   -0.414604 },
224     { -0.00504604, 4.56299, 0.201064,  /*-*/54.8599,
225       -0.107153,   48.7016, 68.8212,   -0.487699 }
226   };
227   double g1,g2,g3,g4,g5,ptheta;
228
229   g1 = myexp(-0.5*sqr((theta-ppp[Eindex][7])/ppp[Eindex][1]));
230   g2 = myexp(-0.5*sqr((theta-180+ppp[Eindex][7])/ppp[Eindex][1]));
231   g3 = myexp(-0.5*sqr((theta-90)/ppp[Eindex][3]));
232   g4 = myexp(-0.5*sqr((theta-ppp[Eindex][6])/ppp[Eindex][5]));
233   g5 = myexp(-0.5*sqr((theta-180+ppp[Eindex][6])/ppp[Eindex][5]));
234
235   ptheta = ppp[Eindex][0]*(g1+g2) + ppp[Eindex][2]*g3 + ppp[Eindex][4]*(g4+g5);
236
237   return ptheta;
238 }
239
240 real rand_theta_incoh(int Eindex,int *seed) 
241 {
242 #define NINTP 450
243 #define prev (1-cur)
244   static bool bFirst = TRUE;
245   static real **intp;
246   static int  i,j,cur=1;
247   real theta,sum,rrr,dx;
248   real g[NENER],y[2];
249   
250   dx = 90.0/(real)NINTP;
251   if (bFirst) {
252     /* Compute cumulative integrals of all probability distributions */
253     snew(intp,NENER);
254     for(i=0; (i<NENER); i++) {
255       snew(intp[i],NINTP+1);
256       y[prev]    = ptheta_incoh(i,0.0);
257       /*sum        = y[prev];*/
258       for(j=1; (j<=NINTP); j++) {
259         y[cur]     = ptheta_incoh(i,j*dx);
260         /*sum       += y[cur];*/
261         intp[i][j] = intp[i][j-1] + (y[cur]+y[prev])*dx;
262         cur        = prev;
263       }
264     }
265     if (debug) {
266       fprintf(debug,"Integrated probability functions for theta incoherent\n");
267       for(j=0; (j<NINTP); j++) {
268         fprintf(debug,"%10f",dx*j);
269         for(i=0; (i<NENER); i++) 
270           fprintf(debug,"  %10f",intp[i][j]);
271         fprintf(debug,"\n");
272       }
273     }
274     bFirst = FALSE;
275   }
276
277   rrr = rando(seed);
278   for(j=0; (j<NINTP) && (rrr > intp[Eindex][j]); j++)
279     ;
280
281   return (j-1+(rrr-intp[Eindex][j-1])/(intp[Eindex][j]-intp[Eindex][j-1]))*dx;
282 }
283
284 static void polar2cart(real phi,real theta,rvec v)
285 {
286   v[XX] = cos(phi)*sin(theta);
287   v[YY] = sin(phi)*sin(theta);
288   v[ZZ] = cos(theta);
289 }
290
291 void rand_vector(rvec v,int *seed)
292 {
293   real theta,phi;
294
295   theta = 180.0*rando(seed);
296   phi   = 360.0*rando(seed);
297   polar2cart(phi,theta,v);
298 }
299
300 real electron_cross_section(FILE *fp,rvec v,real mass,int nelec)
301 {
302   /* Compute cross section for electrons */
303   real T,B,U,S,Q,R,N,t,u,lnt,sigma;
304   real a0 = 0.05292; /* nm */
305   
306   /* Have to determine T (kinetic energy of electron) */
307   T = 0.5*mass*iprod(v,v);
308   
309   /* R is the binding energy of the electron in hydrogen */
310   R = 13.61*ELECTRONVOLT;
311   
312   /* Have to determine the binding energy B, differs per orbital of course */
313   B = R;
314   
315   /* Have to determine the orbital kinetic energy U */
316   U = R;
317   
318   /* Have to know number of electrons */
319   N = nelec;
320   
321   /* Magic constant Q */
322   Q = 1;
323   
324   /* Some help variables */
325   t     = T/B;
326   u     = U/B;
327   S     = 4*M_PI*sqr(a0)*N*sqr(R/B);
328   lnt   = log(t);
329   
330   /* Resulting variable */
331   sigma = (S/(t+u+1))*( 0.5*Q*lnt*(1-1/sqr(t)) + (2-Q)*(1-1/t-lnt/(t+1)) ); 
332   
333   return sigma;
334 }
335
336 static bool analyze_electrons(FILE *fp,t_electron_db *edb,
337                               int natom,char **atomname[])
338 {
339   int  i,etp;
340   char *cc;
341  
342   cc = getenv("GENERATE_ELECTRONS");
343   if (sscanf(cc,"%d",&etp) == 1) {
344     for(i=0; (i<natom); i++) {
345       if (strcmp(*atomname[i],"EL") == 0)
346         break;
347     }
348     edb->elec0      = i;
349     edb->nelec      = 0;
350     edb->maxelec    = natom-i;
351     edb->elmin_type = etp;
352     fprintf(fp,PREFIX"There are %d possible electrons\n",edb->maxelec);
353     
354     return TRUE;
355   }
356   else {
357     fprintf(fp,PREFIX"No electron features today.\n");
358     return FALSE;
359   }
360 }
361
362 void add_electron(FILE *fp,t_mdatoms *md,t_electron_db *edb,int ion,
363                   rvec x[],rvec v[],rvec dv,real dt)
364 {
365   int  m,ee;
366   real nv;
367   
368   if (edb->nelec < edb->maxelec) {
369     ee = edb->elec0+edb->nelec++;
370     md->chargeA[ee] = md->chargeB[ee] = md->chargeT[ee] = -1;
371     md->typeA[ee]   = md->typeB[ee]   = edb->elmin_type;
372
373     /* Velocity! */
374     svmul(-md->massA[ion]*md->invmass[ee],dv,v[ee]);
375     /* Do a first step to prevent the electron from being on top of the 
376      * nucleus, move it 0.05 nm from the nucleus 
377      */
378     nv = 1.0/norm(v[ee]);
379     for(m=0; (m<DIM); m++) 
380       x[ee][m] = x[ion][m] + v[ee][m]*nv*0.05;
381   } 
382   else
383     fatal_error(0,PREFIX"No more particles to turn into electrons\n");
384 }
385
386 bool khole_decay(FILE *fp,t_cross_atom *ca,rvec x[],rvec v[],int ion,
387                  int *seed,real dt,bool bElectron,
388                  t_mdatoms *md,t_electron_db *edb)
389 {
390   rvec dv;
391   real ndv,factor;
392   int  m;
393   
394   if ((ca->vAuger < 0) || (recoil[ca->z].tau == 0)) {
395     dump_ca(stderr,ca,ion,__FILE__,__LINE__);
396     exit(1);
397   }
398   if (rando(seed) < dt/recoil[ca->z].tau) {
399     if (debug)
400       fprintf(debug,"DECAY: Going to decay a k hole\n");
401     ca->n++;
402     ca->k--;
403     /* Generate random vector */
404     rand_vector(dv,seed);
405
406     factor = ca->vAuger;
407     if (debug)
408       fprintf(debug,"DECAY: factor=%10g, dv = (%8.3f, %8.3f, %8.3f)\n",
409               factor,dv[XX],dv[YY],dv[ZZ]);
410     svmul(factor,dv,dv);
411     rvec_inc(v[ion],dv);
412
413     /* Now put the electron in place */
414     if (bElectron)    
415       add_electron(fp,md,edb,ion,x,v,dv,dt);
416
417     return TRUE;
418   }
419   else
420     return FALSE;
421 }
422
423 real electron_atom_interactions(FILE *fp,t_mdatoms *md,t_inputrec *ir,
424                                 int start,int end,
425                                 rvec x[],rvec v[],rvec f[],matrix box)
426 {
427   /* Compute what the name says... */
428   int  i,j,m,elec1,e1;
429   rvec dx;
430   real mindist2,vc,vtot,fscal,fc,dx2,dx_1,qi,*q;
431   
432   mindist2 = sqr(0.05);
433   vtot     = 0;
434   
435   if (edb.nelec > 0) {
436     /* Do a search... */
437     q = md->chargeT;
438     if (ir->ePBC != epbcNONE) 
439       init_pbc(box,FALSE);
440     /* the end variable usually includes electrons */
441     e1 = min(end,edb.elec0);
442     for(i=start; (i<e1); i++) {
443       elec1 = edb.elec0 + edb.nelec;
444       qi = q[i]*ONE_4PI_EPS0;
445       for(j=edb.elec0; (j<elec1); j++) {
446         if (ir->ePBC == epbcNONE) 
447           rvec_sub(x[i],x[j],dx);
448         else
449           pbc_dx(x[i],x[j],dx);
450         dx2 = iprod(dx,dx);
451         if (dx2 < mindist2) {
452           /* Model collision */
453         }
454         else {
455           /* Do normal coulomb */
456           dx_1  = invsqrt(dx2);
457           vc    = qi*q[j]*dx_1;
458           vtot += vc;
459           fscal = vc*dx_1*dx_1;
460           for(m=0; (m<DIM); m++) {
461             fc       = fscal*dx[m];
462             f[i][m] += fc;
463             f[j][m] -= fc;
464           }
465         }
466       }
467     }
468   }
469   return vtot;
470 }
471
472 void ionize(FILE *fp,t_mdatoms *md,char **atomname[],real t,t_inputrec *ir,
473             rvec x[],rvec v[],int start,int end,matrix box,t_commrec *cr)
474 {
475   static FILE  *xvg,*ion;
476   static char  *leg[] = { "Probability", "Primary Ionization", "Integral over PI", "KHole-Decay", "Integral over KD" };
477   static bool  bFirst = TRUE,bElectron = FALSE;
478   static real  t0,imax,width,inv_nratoms,rho,nphot;
479   static real  interval;
480   static int   dq_tot,nkd_tot,ephot,mode;
481   static t_cross_atom *ca;
482   static int   Eindex=-1;
483     
484   real r,factor,ndv,E_lost=0,cross_atom,dvz,rrc;
485   real pt,ptot,pphot,pcoll[ecollNR],tmax;
486   real incoh,incoh_abs,sigmaPincoh,hboxx,hboxy,rho2;
487   rvec dv,ddv;
488   bool bIonize=FALSE,bKHole,bL,bDOIT;
489   char *cc;
490   int  i,j,k,kk,m,nK,nL,dq,nkh,nkdecay,elmin_type;
491   int  *nionize,*nkhole,*ndecay,nbuf[2];
492   
493   if (bFirst) {
494     /* Get parameters for gaussian photon pulse from inputrec */
495     t0       = ir->userreal1;  /* Peak of the gaussian pulse            */
496     nphot    = ir->userreal2;  /* Intensity                             */
497     width    = ir->userreal3;  /* Width of the peak (in time)           */
498     rho      = ir->userreal4;  /* Diameter of the focal spot (nm)       */
499     ionize_seed = ir->userint1;   /* Random seed for stochastic ionization */
500     ephot    = ir->userint2;   /* Energy of the photons                 */
501     mode     = ir->userint3;   /* Mode of ionizing                      */
502     interval = 0.001*ir->userint4;   /* Interval between pulses (ps)    */
503      
504     if ((width <= 0) || (nphot <= 0))
505       fatal_error(0,"Your parameters for ionization are not set properly\n"
506                   "width (userreal3) = %f,  nphot (userreal2) = %f",
507                   width,nphot);
508     
509     if ((mode < 0) || (mode >= eionNR))
510       fatal_error(0,"Ionization mode (userint3)"
511                   " should be in the range 0 .. %d",eionNR-1);
512     
513     switch (mode) {
514     case eionCYL:
515       imax  = (nphot/(M_PI*sqr(rho/2)))*1e-10*1.0/(width*sqrt(2.0*M_PI));
516       break;
517     case eionSURF:
518       imax  = (nphot/(M_PI*sqr(rho/2)))*1e-10*1.0/(width*sqrt(2.0*M_PI));
519       break;
520     }
521     if (ionize_seed == 0)
522       ionize_seed = make_seed();
523     if (PAR(cr)) {
524       for(i=0; (i<cr->nodeid); i++)
525         ionize_seed = INT_MAX*rando(&ionize_seed);
526       fprintf(fp,PREFIX"Modifying seed on parallel processor to %d\n",
527               ionize_seed);
528     }
529           
530     for(Eindex=0; (Eindex < NENER) && (Energies[Eindex] != ephot); Eindex++)
531       ;
532     if (Eindex == NENER)
533       fatal_error(0,PREFIX"Energy level of %d keV not supported",ephot);
534     
535     /* Initiate cross section data etc. */
536     ca      = mk_cross_atom(fp,md,atomname,Eindex);
537     
538     dq_tot  = 0;
539     nkd_tot = 0;
540     inv_nratoms = 1.0/md->nr;
541
542     xvg   = xvgropen("ionize.xvg","Ionization Events","Time (ps)","()");
543     xvgr_legend(xvg,asize(leg),leg);
544     ion   = ffopen("ionize.log","w");
545     
546     fprintf(fp,PREFIX"Parameters for ionization events:\n");
547     fprintf(fp,PREFIX"Imax = %g, t0 = %g, width = %g, seed = %d\n"
548             PREFIX"# Photons = %g, rho = %g, ephot = %d (keV), Electrons = %s\n",
549             imax,t0,width,ionize_seed,nphot,rho,ephot,yesno_names[bElectron]);
550     fprintf(fp,PREFIX"Electron_mass: %10.3e(keV) Atomic_mass: %10.3e(keV)\n"
551             PREFIX"Speed_of_light: %10.3e(nm/ps)\n",
552             ELECTRONMASS_keV,ATOMICMASS_keV,SPEED_OF_LIGHT);
553     fprintf(fp,PREFIX"Interval between shots: %g ps\n",interval);
554     fprintf(fp,PREFIX"Eindex = %d\n",Eindex);
555     fprintf(fp,PREFIX"Doing ionizations for atoms %d - %d\n",start,end);
556     
557     bElectron = analyze_electrons(fp,&edb,md->nr,atomname);
558     
559     fflush(fp);
560
561     bFirst = FALSE;
562   }
563
564   /******************************************************
565    *
566    *    H E R E    S T A R T S   I O N I Z A T I O N
567    *
568    ******************************************************/
569
570   /* Calculate probability */
571   tmax        = t0;
572   if (interval > 0)
573     while (t > (tmax+interval*0.5))
574       tmax += interval;
575   /*  End when t <= t0 + (N+0.5) interval */
576   
577   pt          = imax*ir->delta_t*exp(-0.5*sqr((t-tmax)/width));
578   dq          = 0;
579   nkdecay     = 0;
580
581   hboxx       = 0.5*box[XX][XX];
582   hboxy       = 0.5*box[YY][YY];
583   rho2        = sqr(rho);
584   
585   /* Width of gaussian for probability of incoherent scattering */
586   sigmaPincoh = 1/sqrt(44.0);
587
588   /* Arrays for ionization statistics */
589   snew(nionize,md->nr);
590   snew(nkhole,md->nr);
591   snew(ndecay,md->nr);
592     
593   /* Loop over atoms */
594   for(i=start; (i<end); i++) {
595     /* Loop over collision types */
596     bKHole = FALSE;
597     for(k=0; (k<ecollNR); k++) 
598       /* Determine cross section for this collision type */
599       pcoll[k]= pt*xray_cross_section(k,&(ca[i]));
600     
601     /* Total probability of ionisation */
602     ptot = 1 - (1-pcoll[ecollPHOTO])*(1-pcoll[ecollINELASTIC]);
603     if (debug && (i==0)) 
604       fprintf(debug,PREFIX"Ptot = %g, t = %g\n",ptot,t);
605     
606     /* Check whether to ionize this guy */
607     bDOIT = FALSE;
608     switch (mode) {
609     case eionCYL:
610       bDOIT = (((rando(&ionize_seed) < ptot) && (ca[i].n < ca[i].z)) && 
611                ((sqr(x[i][XX] - hboxx) + sqr(x[i][YY] - hboxy)) < rho2));
612       break;
613     case eionSURF:
614       bDOIT = FALSE;
615       break;
616     default:
617       fatal_error(0,"Unknown ionization mode %d (%s, line %d)",mode,
618                   __FILE__,__LINE__);
619     }
620       
621     if (bDOIT) {
622       clear_rvec(dv);
623       
624       /* The relative probability for a photoellastic event is given by: */
625       pphot = pcoll[ecollPHOTO]/(pcoll[ecollPHOTO]+pcoll[ecollINELASTIC]);
626       
627       if (rando(&ionize_seed) < pphot) 
628         k = ecollPHOTO;
629       else
630         k = ecollINELASTIC;
631       
632       /* If a random number is smaller than the probability for 
633        * an L ionization than do that. Note that the probability
634        * may be zero (H, He), but the < instead of <= covers that.
635        */
636       nK = number_K(&ca[i]);
637       nL = number_L(&ca[i]);
638       bL = (nK == 0) || ( (nL > 0) && (rando(&ionize_seed) > prob_K(k,&(ca[i]))));
639
640       switch (k) {
641       case ecollPHOTO: {
642         /* Select which one to take by yet another random numer */
643         real theta,phi;
644         
645         /* Get parameters for photoelestic effect */
646         /* Note that in the article this is called 2 theta */
647         theta = DEG2RAD*gauss(70.0,26.0,&ionize_seed);
648         phi   = 2*M_PI*rando(&ionize_seed);
649         
650         if (bL)
651           E_lost = ephot-recoil[ca[i].z].E_L*(ca[i].n+1);
652         else {
653           E_lost = ephot-recoil[ca[i].z].E_K;
654           if ((ca[i].z > 2) && (nL > 0))
655             bKHole = TRUE;
656         }
657         if (debug)
658           fprintf(debug,"i = %d, nK = %d, nL = %d, bL = %s, bKHole = %s\n",
659                   i,nK,nL,BOOL(bL),BOOL(bKHole));
660         if (E_lost < 0) {
661           E_lost  = 0.0;
662           bIonize = FALSE;
663           bKHole  = FALSE;
664         }
665         else {
666           /* Compute the components of the velocity vector */
667           factor = ((ELECTRONMASS_keV/(ATOMICMASS_keV*md->massT[i]))*
668                     (SPEED_OF_LIGHT*sqrt(2*E_lost/ELECTRONMASS_keV)));
669           
670           /* Subtract momentum of recoiling electron */
671           polar2cart(phi,theta,ddv);
672           for(m=0; (m<DIM); m++)
673             dv[m] -= factor*ddv[m];
674         
675           add_electron(fp,md,&edb,i,x,v,dv,ir->delta_t);
676           
677           if (debug)
678             pr_rvec(debug,0,"ELL",dv,DIM);
679           
680           bIonize = TRUE;
681         }
682         break;
683       }
684       case ecollINELASTIC: {
685         real theta,phi,Ebind,Eelec;
686         
687         if (bL)
688           Ebind = (ca[i].n+1)*recoil[ca[i].z].E_L;
689         else {
690           Ebind  = recoil[ca[i].z].E_K;
691           if ((ca[i].z > 2) && (nL > 0))
692             bKHole = TRUE;
693         }
694         theta      = DEG2RAD*rand_theta_incoh(Eindex,&ionize_seed);
695         Eelec      = (sqr(ephot)/512)*(1-cos(2*theta));
696         bIonize    = (Ebind <= Eelec);
697         bKHole     = bKHole && bIonize;
698         if (debug)
699           fprintf(debug,PREFIX"Ebind: %g, Eelectron: %g\n",Ebind,Eelec);
700         if (!bIonize) {
701           /* Subtract momentum of recoiling photon */
702           /*phi     = 2*M_PI*rando(&ionize_seed);
703             bKHole  = FALSE;  
704             factor  = ephot*438;  
705             dv[XX] -= factor*cos(phi)*sin(theta);
706             dv[YY] -= factor*sin(phi)*sin(theta);
707             dv[ZZ] -= factor*cos(theta);
708           */
709           if (debug)
710             pr_rvec(debug,0,"INELL",dv,DIM);
711         }
712         break;
713       }
714       default:
715         fatal_error(0,"Ga direct naar de gevangenis. Ga niet langs start");
716       }
717       if (bIonize) {
718         /* First increase the charge */
719         if (ca[i].n < ca[i].z) {
720           md->chargeA[i] += 1.0;
721           md->chargeB[i] += 1.0;
722           ca[i].n++;
723           dq ++;
724         }
725         if (debug) {
726           fprintf(debug,"Random-dv[%3d] = %10.3e,%10.3e,%10.3e,"
727                   " ephot = %d, Elost=%10.3e\n",
728                   i,dv[XX],dv[YY],dv[ZZ],ephot,E_lost);
729         }
730       }
731       /* Now actually add the impulse to the velocities */
732       for(m=0; (m<DIM); m++)
733         v[i][m] += dv[m];
734       if (bKHole) {
735         ca[i].k ++;
736         nkhole[i]++;
737       }
738       else if (bIonize)
739         nionize[i]++;
740     }
741     
742     /* Now check old event: Loop over k holes! */
743     nkh = ca[i].k;
744     for (kk = 0; (kk < nkh); kk++) 
745       if (khole_decay(fp,&(ca[i]),x,v,i,&ionize_seed,ir->delta_t,
746                       bElectron,md,&edb)) {
747         nkdecay ++;
748         ndecay[i]++;
749       }
750     
751     if (debug && (ca[i].n > 0))
752       dump_ca(debug,&(ca[i]),i,__FILE__,__LINE__);
753   }
754
755   /* Sum events for statistics if necessary */
756   if (PAR(cr)) {
757     gmx_sumi(md->nr,nionize,cr);
758     gmx_sumi(md->nr,nkhole,cr);
759     gmx_sumi(md->nr,ndecay,cr);
760     nbuf[0] = dq; nbuf[1] = nkdecay;
761     gmx_sumi(2,nbuf,cr);
762     dq = nbuf[0]; nkdecay = nbuf[1];
763   }
764   /* Now sum global events on this timestep to cumulative numbers */
765   dq_tot  += dq;
766   nkd_tot += nkdecay;
767   
768   /* Printing time */
769   if (MASTER(cr)) {
770     /* Print data to the file that holds ionization events per atom */
771     fprintf(ion,"%12.8f",t);
772     for(i=0; (i<md->nr); i++) {
773       if (nionize[i])
774         fprintf(ion,"  I:%d",i+1);
775       if (nkhole[i])
776         fprintf(ion,"  K:%d",i+1);
777       if (ndecay[i])
778         fprintf(ion,"  D:%d",i+1);
779     }
780     fprintf(ion,"\n");
781     if (debug)
782       fflush(ion);
783   
784     /* Print statictics to file */
785     fprintf(xvg,"%10.5f  %10.3e  %6d  %6d  %6d  %6d",
786             t,pt,dq,dq_tot,nkdecay,nkd_tot);
787     fprintf(xvg,"\n");
788     if (debug)
789       fflush(xvg);
790   }
791   sfree(nionize);
792   sfree(nkhole);
793   sfree(ndecay);
794 }
795