File: Grating_reflect.comp

package info (click to toggle)
mccode 3.5.19%2Bds5-2
  • links: PTS, VCS
  • area: main
  • in suites: 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 (216 lines) | stat: -rw-r--r-- 8,905 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
/*******************************************************************************
*
* McXtrace, x-ray tracing package
*         Copyright, All rights reserved
*         DTU Physics, Kgs. Lyngby, Denmark
*         Synchrotron SOLEIL, Saint-Aubin, France
*
* Component: Grating_reflect
*
* %Identification
*
* Written by: Erik B Knudsen (erkn@fysik.dtu.dk), Kristian Sorensen and Philip Smith
* Date: June 2021
* Version: 1.6
* Origin: DTU
*
* A reflective grating.
*
* %Description
* A reflective grating that diffracts incident photons. 
* The grating is in the XZ-plane. It then reflects the incoming photon using a MC picked angle, 
* where the angle is picked from a uniform distribution of width d_phi, i.e. U[-d_phi/2,d_phi/2]
* The Monte Carlo wight of the ray is then adjusted wrt. to the grating interference pattern, and
* the diffraction pattern associated with each grating line. All lines are considered equal.
* For more efficient sampling of a particular direction the centre of the d_phi may be shifted
* using the parameters order or phi0. In the latter case a set angle is chosen as the centre of the
* sampled interval, in the former the centre angle is computed from the specified grating order.
* 
* In an upcoming release this grating model will also include a blazed grating.
*
* Example: Grating_reflect(
*   d_phi=1,order=0,rho_l=100,zdepth=102e-3,xwidth=102e-3) 
*
* %Parameters
* Input parameters:
* xwidth: [m]     The width of the grating.
* zdepth: [m]     The length of the grating.
* R0:     [0-1]   Constant reflecticity of the grating [0;1].
* rho_l:  [l/mm]  Number of lines pr mm of the grating. 
* b:      [AA]    Width of the spacing in Angstrom. If zero, default is found using rho_l/3.
* d:      [AA]    Width of the slits in Angstrom. If zero, default is found using rho_l.
* N:      [1]     Number of slits. If Zero, default is found using rho_l.
* d_phi:  [deg]   Range of diffraction angle that is to be simulated -d_phi/2 ; d_phi/2.
* order:  [1]     The target order of the grating. If non-zero d_phi will be centered around this scattering line.
* phi0:   [deg]   Target angle to center d_phi. If this is set to 0 the 0th (or any other chosen by the parameter order) order line will be used.
* verbose:[0/1]   If non-zero, more information will be displayed. Nb. generates much output.
*
*
* %End
*******************************************************************************/

DEFINE COMPONENT Grating_reflect
SETTING PARAMETERS (d_phi=1, R0=1, rho_l=800,
    order=0, phi0=0,
    zdepth=0.015, xwidth=0.136, int verbose=0)

SHARE
%{  
  #include <complex.h>
  %include "read_table-lib"
%}

/********************************************************************************************
In DECLARE section, small functions or variables can be defined and used in the entire grating.
********************************************************************************************/
DECLARE
%{
  double pdir;
  double d;
  double b;
  int nslits;
%}


/********************************************************************************************
The INITIALIZE section run each statement once. 
********************************************************************************************/
INITIALIZE
%{
    int status;
    if (R0<0 || R0>1){
      fprintf(stderr,"ERROR: (%s) reflectivity (%f) is specified but is not in [0:1]. \n",NAME_CURRENT_COMP,R0);
      exit(-1);
    }

    d=1e7/rho_l;/*grating pitch in Angstrom*/
    nslits=(zdepth*1e3)*rho_l; /*the relative width of openings*/
    
    if(!b){
      /* Approximated slit-width in Angstrom*/
      b=d/3;
    }

    if(verbose){      
      printf("INFO: (%s): Line width, d=%f [AA]. Number of slits,  N=%f. Slit width, b=%f [AA].\n \n",NAME_CURRENT_COMP,d,nslits,b);  
    }   

    /*We are not sampling the full 2pi range*/
    pdir=(((d_phi*DEG2RAD))/(2*M_PI));
%}

TRACE
%{
  /********************************************************************************************
    Initializing by simulating a perfectly reflecting mirror:
   ********************************************************************************************/

  /*Placing the grating along the Y-axis. */
  PROP_Y0;
  /*If the photon is passing the grating, it shouldn't be reflected. Instead, for book-keeping, it is restored to previoulsy state before the component using RESTORE_XRAY */
  if(x<-xwidth/2.0|| x>xwidth/2.0 || z<-zdepth/2.0 || z>zdepth/2.0){
    RESTORE_XRAY(INDEX_CURRENT_COMP, x,y,z, kx,ky,kz, phi,t, Ex,Ey,Ez, p);
  }else{
    double nx,ny,nz;
    double Gamma,gamma,psi_i,psi_o,spsi_i,spsi_o;
    double kx_notouch,ky_notouch,kz_notouch;    
    double delta_theta,pdiff;
    /* Normal vector for the grating*/
    nx=0;
    ny=1;
    nz=0;
    /* scalar-product, s and length of k.*/
    double s=scalar_prod(kx,ky,kz,nx,ny,nz);
    double k=sqrt(scalar_prod(kx,ky,kz,kx,ky,kz));
    /* Outgoing grazing angle for a perfectly reflecting mirror using angle between two vectors.*/
    psi_i = acos(s/k)-M_PI_2;
    
    /* outgoing vector for a perfectly reflecting mirror. Order 0.*/
    kx=kx-2*s*nx;
    ky=ky-2*s*ny;
    kz=kz-2*s*nz;
    // MC picked angle going from +- d_phi
    delta_theta=DEG2RAD*(rand01()*d_phi - (d_phi*0.5));
    double alpha,beta;
    alpha=M_PI_2-psi_i;
    
    /********************************************************************************************
      The grating is lamellar:
     ********************************************************************************************/        
    /* Lamellar grating is used.
         Thus finding outgoing angle only from ingoing angle.
         using old k and n and rotation matrix.*/
    beta=asin(-order*(2*M_PI/k)/d+sin(alpha));
    //Could have also used an angle convention where the angle between the grating's norm and the ray of order m is positive if it is on the samer side as the incident angle, negative otherwise.
    if(phi0){
      /*a target angle is specified*/
      psi_o=phi0*DEG2RAD;
    }else{
      psi_o=M_PI_2-fabs(beta);/*the fabs is necessary due to the sign convention of beta*/
    }

    kx_notouch=kx;
    ky_notouch=ky;
    kz_notouch=kz;
              
    kx=kx_notouch;
    
    if(!isnan(psi_o) && !isnan(psi_i)){    
        //Still need to take into account the case where the incident ray does not hit perpendicular to the grating
        if(beta>=0){
            if(kz>=0){
                ky=(ky_notouch*cos(-(psi_o-psi_i) + delta_theta) - kz_notouch*sin(-(psi_o-psi_i) + delta_theta)); 
                kz=(ky_notouch*sin(-(psi_o-psi_i) + delta_theta) + kz_notouch*cos(-(psi_o-psi_i) + delta_theta));
            }
            else{
                ky=(ky_notouch*cos((psi_o-psi_i) + delta_theta) - kz_notouch*sin((psi_o-psi_i) + delta_theta)); 
                kz=(ky_notouch*sin((psi_o-psi_i) + delta_theta) + kz_notouch*cos((psi_o-psi_i) + delta_theta));
            }
        }
        else{
            if(kz>=0){
                ky=(ky_notouch*cos((-2*alpha+(psi_o-psi_i)) + delta_theta) - kz_notouch*sin((-2*alpha+(psi_o-psi_i)) + delta_theta));
                kz=(ky_notouch*sin((-2*alpha+(psi_o-psi_i)) + delta_theta) + kz_notouch*cos((-2*alpha+(psi_o-psi_i)) + delta_theta));
            }
            else{
                ky=(ky_notouch*cos((2*alpha-(psi_o-psi_i)) + delta_theta) - kz_notouch*sin((2*alpha-(psi_o-psi_i)) + delta_theta));
                kz=(ky_notouch*sin((2*alpha-(psi_o-psi_i)) + delta_theta) + kz_notouch*cos((2*alpha-(psi_o-psi_i)) + delta_theta));
            }   
        }
        
        /*Finding the weight using diffraction theory.*/ 
        s=scalar_prod(kx,ky,kz,nx,ny,nz);
        psi_o = acos(s/k)-M_PI_2;

        /*pay attention to sign conventions here. We might cross to the "incoming" side of the normal.*/
        spsi_i = sin(M_PI_2-psi_i);
        spsi_o = sin(M_PI_2-psi_o);//+delta_theta)); // asin angle out

        /* Phase for interference pattern:  k = wave vector, d = lines/Angstrom, b=width in Angstrom */
        gamma = k*d*(spsi_o-spsi_i);
        /* Phase for diffraction pattern */
        Gamma = k*b*(spsi_o-spsi_i);
        pdiff=((sin(Gamma/2)/(Gamma/2))*(sin(Gamma/2)/(Gamma/2)))*((sin(nslits*gamma/2)/sin(gamma/2))*(sin(nslits*gamma/2)/sin(gamma/2)));
        p=p*pdir*(pdiff/(pow(nslits,2)));
        
    }else{
        p=0;
    }    
    
  }

%}

/************************************************************************************************************
  Making lines to illustrace with the TRACE option.
*************************************************************************************************************/ 
MCDISPLAY
%{
  magnify("");
  line(-xwidth/2.0,0,-zdepth/2.0, xwidth/2.0,0,-zdepth/2.0);
  line(-xwidth/2.0,0, zdepth/2.0, xwidth/2.0,0, zdepth/2.0);
  line(-xwidth/2.0,0,-zdepth/2.0,-xwidth/2.0,0, zdepth/2.0);
  line( xwidth/2.0,0,-zdepth/2.0, xwidth/2.0,0, zdepth/2.0);
%}

END