File: Perfect_crystal.comp

package info (click to toggle)
mccode 3.5.19%2Bds5-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,113,256 kB
  • sloc: ansic: 40,697; python: 25,137; yacc: 8,438; sh: 5,405; javascript: 4,596; lex: 1,632; cpp: 742; perl: 296; lisp: 273; makefile: 226; fortran: 132
file content (297 lines) | stat: -rw-r--r-- 12,406 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
/*******************************************************************************
*
* McXtrace, X-ray tracing package
*         Copyright, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*         University of Copenhagen, Copenhagen, Denmark
*
* Component: PerfectCrystal
*
* %I
*
* Written by: Anette Vickery, Andrea Prodi, Erik Knudsen
* Date: April 2011
* Version: 1.0
* Release: McXtrace 1.0
* Origin: NBI
*
* Perfect crystal with diamond or zincblende structure 
* 
* %D
* Reads atomic formfactors from a data input file.
* The PerfectCrystal code reflects ray in an ideal geometry, does not include surface imperfections or mosaicity
*
* The crystal is positioned such that the long axis of the crystal surface coincides with
* z-axis. The angle between the Bragg planes and the crystal surface is alpha
* 
* %D
* The algorithm:
*  Incoming photon's coordinates and direction (k-vector) are transformed into an elliptical reference frame 
* (elliptical parameters are calculated according to the mirror's position and its focusing distances and the  * incident angle), the intersection point is then defined. 
* A new, reflected photon is then starting at the point of intersection.
* Notation follows Tadashi Matsushita and Hiro-O Hashizume, X-RAY MONOCHROMATORS. Handbook on Synchrotron Radiation,North-Holland Publishing Company, 1:263–274, 1983.
*
* %P
* Input parameters:
* length [m] 			length of the crystal (along z-axis)
* width [m] 			width of the crystal (along x-axis)
* Material 			Si, Ge (maybe also GaAs?)
* V [AA^3]			unit cell volum
* h [ ]                          Miller index of reflection
* k [ ]                          Miller index of reflection
* l [ ]                          Miller index of reflection
* alpha [rad]			asymmetry angle (alpha=0 for symmetric reflection, ie the Bragg planes are parallel to the crystal surface)
* R0 [ ]                         Reflectivity. Overrides the computed Darwin reflectivity. Probably only useful for debugging. 
* 
*
* %E
*******************************************************************************/

DEFINE COMPONENT Perfect_crystal

SETTING PARAMETERS (string form_factors="FormFactors.txt", string material="Si.txt",R0=0, length=0.05, width=0.02, V=160.1826, h=1, k=1, l=1, alpha=0.0)

/* X-ray parameters: (x,y,z,kx,ky,kz,phi,t,Ex,Ey,Ez,p) */ 

SHARE 
%{
  %include "read_table-lib"  
#include <complex.h>
/* something that would be relevant for ALL crystals */
  void DarwinReflectivity(double *R, double *Thetah, double *Theta0, double *DeltaTheta0,
			  double f00, double f0h, double fp, double fpp, double V, double alpha, double h, double k, double l, double M, double E, double Thetain, int pol )
  {

    double r0,lambda,theta,theta0,DeltaThetas,a,d,b,C,W,kappa,g,L;
    double F0r,F0i,Fhr,Fhi,psi0r,psi0i,psihr,psihi;

    r0 = 2.82e-5;				/* Thomson scattering length in AA */
    lambda = 12.398/E;  			/* wavelength in AA, E in keV    */
    a = cbrt(V); 				/* side length of unit cubic cell (AA)*/
    d = a/sqrt(h*h + k*k + l*l); 		/* d-spacing (AA)*/ 
    theta = asin(lambda/(2*d));  		/* kinematical bragg angle (rad) */
    b = sin(theta - alpha)/sin(theta + alpha);  /* asymmetry factor */

    *Theta0 = Thetain - alpha; 			/* (rad) angle between Bragg planes and incident ray */ 
    *Thetah = b*(*Theta0 - theta) + theta;   	/* (rad) Angle betweeb Bragg planes and reflected ray */
    /*check if Bragg angle is less than alpha. If so return 0 reflectivity*/
    if (theta<alpha) {
      *R=0;
      *DeltaTheta0 = -1; /*to mark it irrelevant*/
    }
    
    /* Define polarization factor: */
    switch(pol){
      case 0:
	C = (1 + fabs(cos(2*theta)))/2;         	/* unpolarized */
	break;
      case 1:
	C = fabs(cos(2*theta));  		/* polarization in the scattering plane */
	break;
      case 2:
	C = 1;                          	/* polarization perpendicular to the scattering plane*/
	break;
    }

    /* STRUCTURE FACTOR CALCULATION: */
    /* NOTE: these structurefactors are valid for single atom diamond lattice structures like Si or Ge only: */
    


    F0r = 8*(f00 + fp);				/* Q=0, real part of structure factor for forward scattering */
    F0i = 8*(fpp); 				/* Q=0, imag part of structure factor for forward scattering */

    if (h==1 && k==1 && l==1){ 		/* (111) reflection */
      Fhr = sqrt(17)*(f0h + fp); 	/* |(4-i)| = sqrt(17) */
      Fhi = sqrt(17)*(fpp); 		/* |(4-i)| = sqrt(17) */   
      }
    else if (h==2 && k==2 && l==0){ 		/* (220) reflection */
      Fhr = 8*(f0h + fp); 	
      Fhi = 8*(fpp); 		
      }
    else if (h==4 && k==0 && l==0){ 		/* (400) reflection */
      Fhr = 8*(f0h + fp); 	
      Fhi = 8*(fpp); 		
      }
    else {
      complex double f_hkl=(1+cexp(I*M_PI*(h+k))+cexp(I*M_PI*(k+l)) + cexp(I*M_PI*(h+l)))*(1+cexp(I*M_PI*(h/4.0 + k/4.0 + l/4.0)));
      Fhr = cabs(f_hkl)*(f0h + fp);
      Fhi = cabs(f_hkl)*(fpp);
      F0r = cabs(f_hkl)*(f00 + fp);				/* Q=0, real part of structure factor for forward scattering */
      F0i = cabs(f_hkl)*(fpp); 				/* Q=0, imag part of structure factor for forward scattering */
    }

    psi0r = fabs(F0r*exp(-M)*r0*lambda*lambda/(PI*V)); 
    psi0i = (-1)*fabs(F0i*exp(-M)*r0*lambda*lambda/(PI*V)); /* here multiplied by (1-) to compensate for the fabs throwing away the minus sign*/  
    psihr = fabs(Fhr*exp(-M)*r0*lambda*lambda/(PI*V));  /* Eq 23*/
    psihi = (-1)*fabs(Fhi*exp(-M)*r0*lambda*lambda/(PI*V));  /*here multiplied by (-1) to compensate for the fabs throwing away the minus sign...*/
    
    W = 0.5 * (sqrt(b) + 1/sqrt(b)) * psi0r/(C * psihr) +  sqrt(b)*sin(2*theta)*(theta - *Theta0)/(C * psihr); /* eq 28*/
    kappa = psihi/psihr;                                              	/* eq 22 */
    g = 0.5*(sqrt(b) + 1/sqrt(b))*psi0i/(C*psihr);               	/* eq 21 */
    L = (1/(1 + kappa*kappa))*( W*W + g*g + sqrt(SQR(W*W - g*g - 1 + kappa*kappa) + 4*SQR(g*W - kappa)));
    *R = L - sqrt(L*L - 1);
    DeltaThetas = r0*(lambda*lambda)*F0r/(sin(2*theta)*PI*V);               	/* eq 32 */
#ifdef MCDEBUG
    printf("E,lambda= %f , %f \n",E,lambda);
    printf("theta= %f \n",theta*180/PI);
    printf("Theta0= %f \n",*Theta0*180/PI);
    printf("theta = %g rad, alpha=%g rad.\n",theta,alpha);
    printf("b,sqrt(b)= %f %f\n",b,sqrt(b));
    printf("1/sqrt(b)= %f \n",1/sqrt(b));
    printf("Fhr, Fhi, F0r, F0i= %g %g %g %g\n",Fhr, Fhi, F0r, F0i);
    printf("psihr, psihi, psi0r, psi0i= %g %g %g %g\n",psihr, psihi, psi0r, psi0i);
    printf("sqrt(b)*sin(2*theta)= %g \n",sqrt(b)*sin(2*theta));
    printf("C, pis0r,C * psihr= %g %g %g\n",C, psi0r,C * psihr);
    printf("W= %f \n",W);
    printf("kappa= %f \n",kappa);
    printf("g= %f \n",g);
    printf("L= %f \n",L);
    printf("R= %f \n",*R);						
    printf("DeltaThetas %f \n",3600*DeltaThetas*180/PI);				
#endif
    *DeltaTheta0 = 0.5*(1 + 1/b)*DeltaThetas;                        	/* center of reflectivity curve is at theta + DeltaTheta0 eq 31 */ 
  }

%}

DECLARE
%{
  int Z;
  double rho;
  double At;
  double f_rel;
  double f_nt;
  t_Table m_t;
  t_Table f0_t;
%}

INITIALIZE
%{
  int status;
  if (material){
    if (status=Table_Read(&(m_t),material,0)==-1){
      fprintf(stderr,"Error(%s): Could not parse file \"%s\"\n",NAME_CURRENT_COMP,material);
      exit(-1);
    }
    char **header_parsed;
    header_parsed=Table_ParseHeader(m_t.header,"Z","A[r]","rho","Z/A","sigma[a]",NULL);
    if(header_parsed[2]){rho=strtod(header_parsed[2],NULL);}
    if(header_parsed[0]){Z=strtod(header_parsed[0],NULL);}
    if(header_parsed[1]){At=strtod(header_parsed[1],NULL);}
  }else{
    fprintf(stderr,"Error(%s): No material file specified\n",NAME_CURRENT_COMP,material);
  }
  if(form_factors){
    if (status=Table_Read(&(f0_t),form_factors,0)==-1){
      fprintf(stderr,"Error(%s): Could not parse file \"%s\"\n",NAME_CURRENT_COMP,form_factors);
      exit(-1);
    }
  }
%}

TRACE
%{
  int pol;                              // beam polarization:: pol=0, umpolarized; pol=1, vert pol; pol=2 
  double E;				// (keV) x-ray energy 
  double K; 				// length of k-vector
  double kxout,kyout,kzout;		// unit vector in the direction of the reflected ray
  double kxu,kyu,kzu;			// unit vector in the direction of k-vector.
  double tin;				// 'time' of intersection of ray with y=0 plane (which include the crystal surface)
  double x_int,y_int,z_int;		// intersection with the y=0 plane
  double dist;				// distance from position at t=0 to the y=0 plane
  double M;		// volume of unit cell (AA^3), asymmetry angle (rad), indices of reflection and a temperature factor
  double f00, f0h, fp, fpp;		// atomic form factors for Q=0 is (f00 + fp + i*fpp) and for Q= ha*+kb*+lc* it is (f0h + fp + i*fpp).
  double Thetain;			// (rad) angle between the crystal surface and the incident ray
  double Theta0;			// (rad) angle between the Bragg planes and the incident ray
  double Thetah;			// (rad) angle between the Bragg planes and the reflected ray
  double Thetaout;			// (rad) angle between the crystal surface and the reflected ray
  double DeltaTheta0;			// (rad) the center of the reflectivity curve is at asin(n*lambda/(2*d)) + DeltaTheta0
  double R;                             // Reflectivity value calculated by DarwinReflectivity() function for each incoming photon

  /* let's assume umpolarized beam */
  pol = 0;
  /* temperature factor for perfect crystal */
  M = 0.0;


  /* get the photon's kvector and energy */
  K=sqrt(kx*kx+ky*ky+kz*kz);
  E = 12.398/(2*PI/K);  
  /* make unit vector in the direction of k :*/
  kxu = kx; kyu = ky; kzu = kz;
  NORM(kxu,kyu,kzu);
  
  /*intersection calculation*/
  tin = -y/kyu;
  if (tin>=0){
    /* check whether our intersection lies within the boundaries of the crystal*/
    x_int=x+kxu*tin;
    y_int=y+kyu*tin;V,
    z_int=z+kzu*tin;
    
    if (fabs(x_int)<=width/2 && fabs(z_int)<=length/2){
        dist=sqrt(SQR(x-x_int)+SQR(y-y_int)+SQR(z-z_int));
	PROP_DL(dist); 			/* now the photon is on the crystal surface, ready to be reflected... */ 
        SCATTER;
        /*Check which quadrant the k vector is in to determine sense of alpha. This to allow for hitting the crystal from behind.*/
        int quadrant;
        Thetain=fabs(atan(ky/kz));
        double d=cbrt(V)/(sqrt(h*h+k*k+l*l));/*this is valid only for cubic structures*/
        f00 = Z;
        f0h = Table_Value(f0_t,1/(2*d),Z);
        fp  = Table_Value(m_t,E,1)-Z;
        fpp = Table_Value(m_t,E,2);
        
        if (ky<0 && kz>0){
          /*4th quadrant - forward hit from above. No change.*/ 
          DarwinReflectivity(&R, &Thetah, &Theta0, &DeltaTheta0, f00, f0h, fp, fpp, V, alpha, h, k, l, M, E, Thetain,pol);
        }else if(ky<0 && kz<0){
          /*3rd quadrant - backward hit from above. Sense of alpha is reversed.*/
          DarwinReflectivity(&R, &Thetah, &Theta0, &DeltaTheta0, f00, f0h, fp, fpp, V, -alpha, h, k, l, M, E, Thetain,pol);
        }else if(ky>0 && kz>0){
          /*1st quadrant - forward hit from below. Sense of alpha is reversed.*/
          DarwinReflectivity(&R, &Thetah, &Theta0, &DeltaTheta0, f00, f0h, fp, fpp, V, -alpha, h, k, l, M, E, Thetain,pol);
        }else if(ky>0 && kz<0){
          /*2nd quadrant - backward hit from below. No change.*/
          DarwinReflectivity(&R, &Thetah, &Theta0, &DeltaTheta0, f00, f0h, fp, fpp, V, alpha, h, k, l, M, E, Thetain,pol);
        }
	Thetaout = Thetah - alpha; 	/* (rad) the angle between the crystal surface and the reflected ray */
        
        /*reflect ray in normal to crystal planes*/
        do {
          double ax,ay,az,vnx,vny,vnz;
          ax=0;ay=-sin(alpha);az=cos(alpha);
          vnx=kx-scalar_prod(kx,ky,kz,ax,ay,az)*ax;
          vny=ky-scalar_prod(kx,ky,kz,ax,ay,az)*ay;
          vnz=kz-scalar_prod(kx,ky,kz,ax,ay,az)*az;
          //printf("a=[ %g %g %g ] vn=[ %g %g %g ]\n",ax,ay,az,vnx,vny,vnz);
          kx=kx-2*vnx;
          ky=ky-2*vny;
          kz=kz-2*vnz;
        }while(0);

        /* apply Darwin reflectivity if not is supplied from outside*/
        if (!R0){
          p*=R;
        }else{
          p*=R0;
        } 
        /*catch dead rays*/
        if (p==0) ABSORB;
    } else {
      RESTORE_XRAY(INDEX_CURRENT_COMP, x, y, z, kx, ky, kz, phi, t, Ex, Ey, Ez, p);
    } 
  }
  
  
%}

MCDISPLAY
%{
  
  rectangle("xz",0,0,0,width,length); 
%}

END