File: Source_lab.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 (390 lines) | stat: -rw-r--r-- 14,700 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
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
/*******************************************************************************
*
* McXtrace, X-ray tracing package
*         Copyright, All rights reserved
*         DTU Physics, Kgs. Lyngby, Denmark
*         Synchrotron SOLEIL, Saint-Aubin, France
*
* Component: Source_lab
*
* %Identification
* Written by: Erik Bergbaeck Knudsen 
* Date: May 2012
* Version: 1.0
* Origin: Kgs. Lyngby
*
* Laboratory x-ray source.
*
* %Description
* Model of a laboratory x-ray tube, generating x-rays by bombarding a target by electrons.
* Given a input energy E0 of the electron beam, x-rays are emitted from the accessible emission lines
* The geometry of the tube is assumed to be:
* # The electron beam hits a slab of surface material surface at a right angle illuminating an area of width by height,
* # where width is measured along the component X-axis.
* # The centre of the electron beam at the anode surface is the origin of the component.
* # The Z-axis of the component points at the centre of the exit window (focus_xw by focus yh) 
* placed at a distance dist from the origin.
* # The angle between the Z-axis and the anode surface is the take_off angle.
* For a detailed sketch of the geometry see the componnent manual.
* 
* The Bremsstrahlung emitted is modelled using the model of Kramer (1923) as restated in International
* Tables of Crystallography C 4.1
* Characteristic radiation is modelled by Lorentzian (default) or Gaussian energy profiles with
* line-energies from Bearden (1967), widths from Krause (1979) and intensity from Honkimäki (1990) and x-ray data booklet.
* Absoprtion of emitted x-rays while travelling through the target anode is included. 
* 
* Example: Source_lab(material_datafile="Cu.txt",Emin=1, E0=80)
*
* %Parameters
* width:      [m]    Width of electron beam impinging on the anode.
* height:     [m]    Height of electron beam impinging on the anode.
* xwidth:     [m]    Width of the anode material slab.
* yheight:    [m]    Height of the anode material slab.
* thickness:  [m]    Thickness of the anode material slab.
* take_off:   [deg]  Take off angle of beam centre.
* dist:       [m]    Distance between centre of illuminated target and exit window.
* E0:         [kV]   Acceleration voltage of xray tube.
* tube_current: [A]  Electron beam current.
* Emax:       [keV]  Maximum energy to sample. Default (Emax=0) is to set it to E0.
* Emin:       [keV]  Minimum energy to sample.
* focus_xw:   [m]    Width of exit window.
* focus_yh:   [m]    Height of exit window.
* frac:       [0-1]  Fraction of statistic to use for Bremsstrahlung.
* material_datafile: [string] Name of datafile which describes the target material.
* lorentzian: [0/1]  If nonzero Lorentzian (more correct) line profiles are used.
* exit_window_refpt: [m] If set, the AT position and exit window will coincide (legacy behaviour).
*
* %End
*************************************************************************/

DEFINE COMPONENT Source_lab

SETTING PARAMETERS (string material_datafile="Cu.txt", width=1e-3, height=1e-3, thickness=100e-6, E0=20, Emax=0, Emin=1, focus_xw=5e-3, focus_yh=5e-3,
    take_off=6, dist=1, tube_current=1e-3, frac=0.1, lorentzian=1, xwidth=0, yheight=0, exit_window_refpt=0 )

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

SHARE
%{
  %include "read_table-lib"
#ifndef MX_SOURCE_LAB
#define MX_SOURCE_LAB
  /*here are some material data- currently only for Cu, Mo, W, and Ag*/
  struct xray_em_data{
    int _Z;/*atom number*/
    double Ek;/*ionazation energy*/
    double w_k;/*flourescence yield*/
    int linec;
    double e[6];/*line energy*/
    double w[6];/*natural width of line FWHM*/
    double i[6];/*relative intensity*/
  };
  struct xray_em_data xray_mat_data[8]={
    {24, 5.989 ,0.265, 3, {5.41472,5.40551,5.94671,0,0,0}, {1.97e-3,2.39e-3,3.05e-3,0,0,0}, {100,50,15,0,0,0}},
    {27, 7.709 ,0.391, 3, {6.93032,6.9153,7.6494,0,0,0}, {2.26e-3,3.08e-3,4.36e-3,0,0,0}, {100,51,17,0,0,0}},
    {29, 8.979 ,0.407,2,{8.02783,8.04778,0,0,0,0},{2.11e-3,2.17e-3,0,0,0,0},{0.51,1.0,0,0,0,0}},
    {31, 10.367,0.0  ,2,{9.22482,9.25174,0,0,0,0},{2.59e-3,2.66e-3,0,0,0,0},{0.51,1.0,0,0,0,0}},
    {42, 20.00 ,0.770,5,{17.3743,17.47934,19.5903, 19.6083, 19.965,0},{6.31e-3,6.49e-3,12e-3, 12e-3, 12e-3,0},{0.52,1.0,0.08,0.15,0.03,0}},
    {47, 25.52, 0.8,2,{21.99030,22.162917, 0,0,0,0},{9.32e-3,9.16e-3,0,0,0,0}, {0.53, 1, 0,0,0,0}}, /* Ag fluorscence yield just guessed */
    {74, 69.525,0.945,5,{57.9817,59.31824,66.9514,67.2443,69.067,0},{44.9e-3,45.2e-3, 51.1e-3, 50.8e-3 , 50.2,0},{0.58,1.0,0.11,0.22,0.08,0}},
    {0,0.0,0.0,0,{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}}

  };
#pragma acc declare create(xray_mat_data)
#endif

%}

DECLARE
%{
  Rotation R_xray_gen;
  Rotation R_xray_geni;
  Coords O_xray_gen;
  int Z;
  double At;
  double rho;
  t_Table T;
  int em_idx;
  double Icont;
  double Ichar;
  int linemin;
  int linemax;
  double p_continous;
  double pmul_c;
  double mu_electron;

  double BKRAMER;
%}

INITIALIZE
%{
  BKRAMER=2e-6; /*photons /keV /electron*/
#pragma acc update device(xray_mat_data[0:6])

  int status,ii;
  if (E0<=0){
    fprintf(stderr,"Error %s: Impinging electron energy (E0) must be >0, was %g\n",NAME_CURRENT_COMP, E0);
    exit(-1);
  }

  if (!Emax){/*if Emax is not set use the impinging electron energy*/
    Emax=E0;
  }
  if(Emin<=0){
    fprintf(stderr,"Error (%s): Emin must be > 0 (%g)\n",NAME_CURRENT_COMP,Emin);exit(-1);
  }
  if(Emax<Emin){
    fprintf(stderr,"Error (%s): Nonsensical emission energy interval [Emin,Emax]=[%g %g] at E0=%g\n",NAME_CURRENT_COMP,Emin,Emax,E0);
    exit(-1);
  }
 
  if ( (status=Table_Read(&(T),material_datafile,0))==-1){
    fprintf(stderr,"Error %s: Could not parse file \"%s\"\n",NAME_CURRENT_COMP,material_datafile?material_datafile:"");
    exit(-1);
  }
  char **header_parsed;
  header_parsed=Table_ParseHeader(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);}

  /*use the atom number to get at the right data structure*/  
  int idx=0;
  while (Z!=xray_mat_data[idx]._Z){
    idx++;
    if ((xray_mat_data[idx]._Z)==0){
      fprintf(stderr,"Error: %s (Z=%d) anode not implemented yet. Please contact the McXtrace team to fix this. Aborting.\n",material_datafile,Z);
      exit(-1);
    }
  }
  em_idx=idx;
  struct xray_em_data *em_p = &(xray_mat_data[em_idx]);
  
  /*Integrate the continuous spectrum and the characteristic so as to get the relative intenisities right*/
  Icont=tube_current/CELE*BKRAMER*Z*(E0*log(Emax)-E0*log(Emin) - Emax + Emin);
  /*check if E0 >Ek. If not, no characteristic emission can take place*/
  if (E0>em_p->Ek){
    double Bk=1.2e-5*pow(em_p->Ek,1.67)*exp(-0.077*Z);
    Ichar=tube_current/CELE*4*M_PI*(E0/em_p->Ek-1)*Bk;
    double Ichar_tot=0;
    int linec=0;
    linemin=0;
    linemax=em_p->linec;
    for (ii=0;ii<em_p->linec;ii++){
      /*if the interval [Emin,Emax] contains 5 sigma of the characteristic peak - use full peak.*/
      if (Emin>em_p->e[ii]+5*em_p->w[ii] ){
        /*way below of energy limit - do not use.*/
        linemin=ii;
      }else if ( Emax<em_p->e[ii]-5*em_p->w[ii]){
        /*way above of energy limit - do not use.*/
        linemax= linemax<ii?linemax:ii;
      }else{
        linec++;
      }
      if(Emax>em_p->e[ii]+5*em_p->w[ii] && Emin<em_p->e[ii]-5*em_p->w[ii]){
        Ichar_tot+=em_p->i[ii];
      }else{
        if(!lorentzian){
	  /*We only partially use the peak - so update the relative intensity to reflect that*/
          Ichar_tot+=em_p->i[ii]*0.5*( erf(Emax-em_p->e[ii]/em_p->w[ii]/M_SQRT2) - erf( Emin-em_p->e[ii]/em_p->w[ii]/M_SQRT2) );
          em_p->i[ii]= em_p->i[ii]*0.5*( erf((Emax-em_p->e[ii]/M_SQRT2)/em_p->w[ii]/M_SQRT2) - erf((Emin-em_p->e[ii])/em_p->w[ii]/M_SQRT2) );
        }else{
	  /* 1/pi atan(2x/w)) is integrated lorentzian of fwhm w, MHM, April 2015 */
          Ichar_tot+=em_p->i[ii]*(1.0/M_PI)*( atan(2*(Emax-em_p->e[ii])/em_p->w[ii]) - atan(2*(Emin-em_p->e[ii])/em_p->w[ii]) );
        }
      }
    }

    p_continous=Icont/(Ichar*Ichar_tot+Icont);
  }else{
    /*characteristic K-emission is not possible*/
    p_continous=1;
    frac=1;
  }
  O_xray_gen=coords_set(0,0,0);
  rot_set_rotation(R_xray_gen,-take_off*DEG2RAD,0,0);
  rot_set_rotation(R_xray_geni,take_off*DEG2RAD,0,0);

  pmul_c=1.0/(mcget_ncount());

  mu_electron=0;

%}

TRACE
%{
  double x1,y1,z1,x2,y2,z2,r,e,k,pdir,pmul;
  /* pick a point in the generating volume*/
  x1=rand01()*width-width/2.0;
  z1=rand01()*height-height/2.0;
  /* y is the absorption depth of the electron getting converted to an xray*/
  y1=log(rand01())*mu_electron;

  double px,py,pz; 
  Coords P;

  /* transform initial coords to ones in a frame with origin at the center of e-beam with optical axis pointing towards exit window*/
  P=coords_set(x1,y1,z1);
  P=coords_add(rot_apply(R_xray_gen,P),O_xray_gen);
  coords_get(P,&x,&y,&z);

  /*randvec_target_rect_real computes a target point and a solid angle correction factor, hence the k-vector has to be computed from
    generation point and target point. The (0,0,1) location of the target is due to a silent assumption in randvec() that
    the target cannot be situated in the origin.*/
  randvec_target_rect_real(&px,&py,&pz,&pdir,0,0,dist,focus_xw,focus_yh, R_xray_gen,x1,y1,z1,2);
  /*k is parallell to the line between generation and target points*/
  kx=px-x1;
  ky=py-y1;
  kz=pz-z1;

  /*Now for wavelength selection*/
  r=rand01();
  if(r<frac){
    /*bremsstrahlung*/
    e=rand01()*(Emax-Emin)+Emin;
    k=e*E2K;
    pmul=tube_current/CELE*BKRAMER*Z*(E0/e-1);
    /*correct for not having the full E-window*/
    pmul*=(Emax-Emin)/E0;
    /*correct for monte-carlo statistics*/
    pmul*=p_continous/frac;
  }else{
    struct xray_em_data *pt=&(xray_mat_data[em_idx]);
    /*characteristic radiation*/
    /*first pick a possible line*/
    r=rand01()*(linemax-linemin) + linemin;
    int lineno=(int)floor(r);
    if (lineno==pt->linec) {
      lineno--;/*we might get overflow*/
    }

    if(!lorentzian){
      pmul=pt->i[lineno]*Ichar;
      e=(randnorm()*pt->w[lineno]+pt->e[lineno]);
      /*this can be very inefficient*/
      while (e<Emin || e>Emax){
        e=(randnorm()*pt->w[lineno]+pt->e[lineno]);
      }
    }else{/* tan((rand-0.5)/pi) is Lorentzian with FWHM of 2, MHM April 2015 */
      /* compute upper and lower random range to map onto energy bounds such that a*tan(u)+b = energy. Note -0.5<u<0.5 */
      double umin=atan(2*(Emin-pt->e[lineno])/pt->w[lineno])/M_PI;
      double umax=atan(2*(Emax-pt->e[lineno])/pt->w[lineno])/M_PI;
      pmul=pt->i[lineno]*Ichar*(umax-umin); /* weight intensity for partial line strength */
      e=tan(((umax-umin)*rand01()+umin)*M_PI)*pt->w[lineno]/2+pt->e[lineno];
    }
    k=E2K*e;
    pmul*=(1-p_continous)/frac;
  }

  /*scale k accordingly*/
  NORM(kx,ky,kz);
  kx*=k;ky*=k;kz*=k;
  
  /*set the x-ray weight to whatever we computed just before and correct for only sampling the exit window, and correct for number of issued photons*/
  p=pmul*pmul_c;
    

  int ie;
  /*Correct for absorption*/
  double mu_abs,l0,l1,lx,ly,lz,klx,kly,klz,xw,yh;
  l0=0;l1=0;
  /*if dimensions are set the anode has a limited size - otherwise use a
    practically infinite slab*/
  if(!xwidth) xw=FLT_MAX;
  if(!yheight) yh=FLT_MAX;
  coords_get(rot_apply(R_xray_geni,coords_set(x,y,z)),&lx,&ly,&lz);
  coords_get(rot_apply(R_xray_geni,coords_set(kx,ky,kz)),&klx,&kly,&klz);
  /*find path length inside anode material*/
  ie=box_intersect(&l0,&l1,lx,ly+thickness/2.0,lz,klz,kly,klz,xw,thickness,yh);
  if(!ie || l0>0){
    /*photon is somehow outside the anode - this should not happen*/
    ABSORB;
  }

  mu_abs=Table_Value(T, k*K2E, 5)*rho*1e2; /*mu_abs in m^-1*/
  p*=exp(-l1*mu_abs);
  /*set a random phase*/
  phi=rand01()*2*M_PI;

  /*Finally, if exit_window_refpt is set revert to legacy behaviour where the centre of the exit window is the
    reference point of the component*/
  if(exit_window_refpt){
    z=z-dist;
  }
  /*set a scatter pt at the generation pt*/
  SCATTER;
%}

MCDISPLAY
%{
  _class_particle p1,p2;
  
  double x1,y1,z1,x2,y2,z2,width_2,height_2;
  double dx,dy,dz;
  /*these are just dummies*/
  double d1,d2,d3,d4,d5,d6;  

  width_2=width/2.0;
  height_2=height/2.0;
  p1.x=-width_2;p1.y=0;p1.z=-height_2;
  p2.x=-width_2;p2.y=0;p2.z= height_2;

  mccoordschange(O_xray_gen,R_xray_gen,&p1);
  mccoordschange(O_xray_gen,R_xray_gen,&p2);
  line(p1.x,p1.y,p1.z,p2.x,p2.y,p2.z);

  p1.x=width_2;p1.y=0;p1.z=height_2;
  mccoordschange(O_xray_gen,R_xray_gen,&p1);
  line(p2.x,p2.y,p2.z,p1.x,p1.y,p1.z);
  
  p2.x=width_2;p2.y=0;p2.z=-height_2;
  mccoordschange(O_xray_gen,R_xray_gen,&p2);
  line(p1.x,p1.y,p1.z,p2.x,p2.y,p2.z);

  p1.x=-width_2;p1.y=0;p1.z=-height_2;
  mccoordschange(O_xray_gen,R_xray_gen,&p1);
  line(p2.x,p2.y,p2.z,p1.x,p1.y,p1.z);

  /*this is the mean penetration depth of electron that get converted to x-rays*/  
  p1.x=-width_2;p1.y=-mu_electron;p1.z=-height_2;
  p2.x=-width_2;p2.y=-mu_electron;p2.z= height_2;
  mccoordschange(O_xray_gen,R_xray_gen,&p1);
  mccoordschange(O_xray_gen,R_xray_gen,&p2);
  dashed_line(p1.x,p1.y,p1.z,p2.x,p2.y,p2.z,5);
  p1.x=width_2;p1.y=-mu_electron;p1.z=height_2;
  mccoordschange(O_xray_gen,R_xray_gen,&p1);
  dashed_line(p2.x,p2.y,p2.z,p1.x,p1.y,p1.z,5);
  p2.x= width_2;p2.y=-mu_electron;p2.z=-height_2;
  mccoordschange(O_xray_gen,R_xray_gen,&p2);
  dashed_line(p1.x,p1.y,p1.z,p2.x,p2.y,p2.z,5);
  p1.x=-width_2;p1.y=-mu_electron;p1.z=-height_2;
  mccoordschange(O_xray_gen,R_xray_gen,&p1);
  dashed_line(p2.x,p2.y,p2.z,p1.x,p1.y,p1.z,5);
  
  p1.x=-width_2;p1.y=-mu_electron;p1.z=-height_2;
  p2.x=-width_2;p2.y=0;p2.z=-height_2;
  mccoordschange(O_xray_gen,R_xray_gen,&p1);
  mccoordschange(O_xray_gen,R_xray_gen,&p2);
  line(p2.x,p2.y,p2.z,p1.x,p1.y,p1.z);
  p1.x=width_2;p1.y=-mu_electron;p1.z=-height_2;
  p2.x=width_2;p2.y=0;p2.z=-height_2;
  mccoordschange(O_xray_gen,R_xray_gen,&p1);
  mccoordschange(O_xray_gen,R_xray_gen,&p2);
  line(p2.x,p2.y,p2.z,p1.x,p1.y,p1.z);
  p1.x=-width_2;p1.y=-mu_electron;p1.z=height_2;
  p2.x=-width_2;p2.y=0;p2.z=height_2;
  mccoordschange(O_xray_gen,R_xray_gen,&p1);
  mccoordschange(O_xray_gen,R_xray_gen,&p2);
  line(p2.x,p2.y,p2.z,p1.x,p1.y,p1.z);
  p1.x=width_2;p1.y=-mu_electron;p1.z=height_2;
  p2.x=width_2;p2.y=0;p2.z=height_2;
  mccoordschange(O_xray_gen,R_xray_gen,&p1);
  mccoordschange(O_xray_gen,R_xray_gen,&p2);
  line(p2.x,p2.y,p2.z,p1.x,p1.y,p1.z);


  /*now draw "exit" window*/
  rectangle("xy",0,0,0,focus_xw,focus_yh);
%}

END