File: Guide_wavy.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 (301 lines) | stat: -rw-r--r-- 10,061 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
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright 1997-2002, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Component: Guide_wavy
*
* %I
* Written by: Kim Lefmann
* Origin: Risoe
*
* Neutron guide with gaussian waviness.
*
* %D
* Models a rectangular guide tube centered on the Z axis. The entrance lies
* in the X-Y plane.
* For details on the geometry calculation see the description in the McStas
* reference manual.
*
* Example: m=2 Qc=0.0218 (nat. Ni) W=1/300 alpha=4.38 R0=0.995 (given by Daniel Clemens, PSI)
*
* %BUGS
* This component does not work with gravitation on. Use component Guide_gravity then.
*
* %P
* INPUT PARAMETERS:
*
* w1: [m]         Width at the guide entry
* h1: [m]         Height at the guide entry
* w2: [m]         Width at the guide exit
* h2: [m]         Height at the guide exit
* l: [m]          length of guide
* R0: [1]         Low-angle reflectivity
* Qc: [AA-1]      Critical scattering vector
* alpha: [AA]     Slope of reflectivity
* m: [1]          m-value of material. Zero means completely absorbing.
* W: [AA-1]       Width of supermirror cut-off for all mirrors
*
* alpha1: [AA]    Slope of reflectivity left
* m1: [1]         m-value of material, left
* W1: [AA-1]      Width of supermirror cut-off left
* alpha2: [AA]    Slope of reflectivity right
* m2: [1]         m-value of material, right.
* W2: [AA-1]      Width of supermirror cut-off right
* alpha3: [AA]    Slope of reflectivity top
* m3: [1]         m-value of material, top.
* W3: [AA-1]      Width of supermirror cut-off top
* alpha4: [AA]    Slope of reflectivity bottom
* m4: [1]         m-value of material, bottom.
* W4: [AA-1]      Width of supermirror cut-off bottom
*
* wavy_z: [deg]   Waviness in the z-(flight-)direction
* wavy_xy: [deg]  Waviness in the transverse direction
*
* %E
******************************************************************************/

DEFINE COMPONENT Guide_wavy

SETTING PARAMETERS (w1, h1, w2=0, h2=0, l,
  R0=0.995, Qc=0.0218, alpha=0, m=0, W=0,
  alpha1=4.38, m1=2, W1=0.003,
  alpha2=4.38, m2=2, W2=0.003,
  alpha3=4.38, m3=2, W3=0.003,
  alpha4=4.38, m4=2, W4=0.003,
  wavy_z=0, wavy_xy=0)

/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */
SHARE %{
  %include "ref-lib"
%}
DECLARE
%{
  double whalf;
  double hhalf;
  double lwhalf;
  double lhhalf;
  double norm_nv;
  double norm_nh;
  double f_h;
  double f_v;
  double eta_z;
  double eta_xy;
%}

INITIALIZE
%{
  if (m)     { m1=m2=m3=m4=m; }
  if (alpha) { alpha1=alpha2=alpha3=alpha4=alpha; }
  if (W)     { W1=W2=W3=W4=W; }

  if (!w2) w2=w1;
  if (!h2) h2=h1;
  f_h = 0.5*(w2 - w1), f_v = 0.5*(h2 - h1);
  whalf = 0.5*w1, hhalf = 0.5*h1;
  lwhalf = l*whalf, lhhalf = l*hhalf;
  norm_nv = sqrt(l*l+f_v*f_v);
  norm_nh = sqrt(l*l+f_h*f_h);
  eta_z = wavy_z/(sqrt(8*log(2)));   /* Convert from FWHM to Gaussian sigma */
  eta_xy = wavy_xy/(sqrt(8*log(2)));

  if (mcgravitation) fprintf(stderr,"WARNING: Guide_wavy: %s: "
    "This component produces wrong results with gravitation !\n"
    "Use Guide_gravity.\n",
    NAME_CURRENT_COMP);
%}

TRACE
%{
  double t_min,t_tmp;                           /* Intersection times. */
  double av,ah,bv,bh,cv1,cv2,ch1,ch2,d;         /* Intermediate values */
  double vdotn_v1,vdotn_v2,vdotn_h1,vdotn_h2;   /* Dot products. */
  double vdotn;
  double d_xy, d_z;                             /* Random angles */
  double m0, alpha0, w;
  int i;                                        /* Which mirror hit? */
  double q;                                     /* Q [1/AA] of reflection */
  double dvx, dvy, dvz;                         /* Velocity change */
  double vlen2,nlen2, norm_n2;                  /* Vector lengths squared */
  double nperp,pz,nxy;                          /* for dot products */
  double R;                                     /* Reflectivity */

  /* Propagate neutron to guide entrance. */
  PROP_Z0;
  /* Scatter here to ensure that fully transmitted neutrons will not be
     absorbed in a GROUP construction, e.g. all neutrons - even the
     later absorbed ones are scattered at the guide entry. */
  SCATTER;
  if(x <= -whalf || x >= whalf || y <= -hhalf || y >= hhalf)
    ABSORB;
  for(;;)
  {
    /* Compute the dot products of v and n for the four mirrors. */
    av = -l*vx ; bv = f_h*vz;
    ah = -l*vy ; bh = f_v*vz;
    vdotn_v1 = bv + av;         /* Left vertical */
    vdotn_v2 = bv - av;         /* Right vertical */
    vdotn_h1 = bh + ah;         /* Lower horizontal */
    vdotn_h2 = bh - ah;         /* Upper horizontal */
    /* Compute the dot products of (O - r) and n as c1+c2 and c1-c2 */
    cv1 = -whalf*l - z*f_h; cv2 = x*l;
    ch1 = -hhalf*l - z*f_v; ch2 = y*l;
    /* Compute intersection times. */
    t_min = (l - z)/vz;
  /*  printf(" (x,y,z)=(%g %g %g) (vx,vy,vz)=(%g %g %g) Exit time : %g \n",
       x,y,z,vx,vy,vz,t_min); */
    i = 0;
    if(vdotn_v1 < 0 && (t_tmp = (cv1 + cv2)/vdotn_v1) < t_min)
    {
      t_min = t_tmp;
      i = 1;
/*      printf("Left vertical: t=%g \n",t_min); */
    }
    if(vdotn_v2 < 0 && (t_tmp = (cv1 - cv2)/vdotn_v2) < t_min)
    {
      t_min = t_tmp;
      i = 2;
/*      printf("Right vertical: t=%g \n",t_min); */
    }
    if(vdotn_h1 < 0 && (t_tmp = (ch1 + ch2)/vdotn_h1) < t_min)
    {
      t_min = t_tmp;
      i = 3;
/*      printf("Lower horizontal: t=%g \n",t_min); */
    }
    if(vdotn_h2 < 0 && (t_tmp = (ch1 - ch2)/vdotn_h2) < t_min)
    {
      t_min = t_tmp;
      i = 4;
/*      printf("Upper horizontal: t=%g \n",t_min); */
    }
    if(i == 0)
      break;                    /* Neutron left guide. */
    PROP_DT(t_min);

/* ******* Recalculate dot products ********* */

    d_z=DEG2RAD*eta_z*randnorm();
    d_xy=DEG2RAD*eta_xy*randnorm();

/* Now the normal vector is rotated. To 1st order in waviness and 2nd order
  in f=(w2-w1)/l and (f times waviness) the rotation matrix for
  the left vertical mirror is:

  {  1     d_xy      d_z      }
  { -d_xy  1         d_xy f_h }   (for the right vertical mirror the )
  {  d_z  -d_xy f_h  1        }   (terms d_xy f_h changes sign )

the left vertical normal vector is  { -l,  0,  f_h }

giving the rotated normal vector  { -l + f_h d_z,  l d_xy,  f_h - l d_z }

for the right vertical mirror the normal vector is { l,  0,  f_h }

and the rotated right normal vector is { l + f_h d_z,  -l d_xy,  f_h + l d_z }


The top horizontal mirror must be (something like)

  {  1        -d_xy  d_xy f_h }
  {  d_xy      1     d_z      }   (for the bottom horizontal mirror the )
  { -d_xy f_h  d_z   1        }   (terms d_xy f_h changes sign )

The top horizontal normal vector is { 0,  -l,  f_v}

giving the rotated normal vector  { l d_xy,  -l + f_v d_z,  f_v - l d_z }

for the bottom mirror the normal vector is { 0,  l,  f_h }

and the rotated bottom normal vector is { -l d_xy,  l + f_v d_z,  f_v + l d_z }

*/

    switch(i)
    {
      case 1:                   /* Left vertical mirror */
        m0=m1; w=W1; alpha0=alpha1;
        norm_n2 =  (-l+d_z*f_h)*(-l+d_z*f_h)+(d_xy*l)*(d_xy*l)
                  +(f_h-d_z*l)*(f_h-d_z*l); /* Square of length of n vector */
        vdotn = (vx*(-l+f_h*d_z)+ vy*(l*d_xy)+ vz*(f_h-l*d_z) );
        q = 2 * V2Q * fabs(vdotn) / sqrt(norm_n2);
        dvx = -2*(-l+f_h*d_z)*vdotn/norm_n2;
        dvy = -2*(l*d_xy)*vdotn/norm_n2;
        dvz = -2*(f_h-l*d_z)*vdotn/norm_n2;
        break;
      case 2:                   /* Right vertical mirror */
        m0=m2; w=W2; alpha0=alpha2;
        norm_n2 =  (l+d_z*f_h)*(l+d_z*f_h)+(-d_xy*l)*(-d_xy*l)
                  +(f_h+d_z*l)*(f_h+d_z*l); /* Square of length of n vector */
        vdotn = (vx*(l+f_h*d_z)+ vy*(-l*d_xy)+ vz*(f_h+l*d_z) );
        q = 2 * V2Q * fabs(vdotn) / sqrt(norm_n2);
        dvx = -2*(l+f_h*d_z)*vdotn/norm_n2;
        dvy = -2*(-l*d_xy)*vdotn/norm_n2;
        dvz = -2*(f_h+l*d_z)*vdotn/norm_n2;
        break;
      case 3:                   /* Lower horizontal mirror */
        m0=m3; w=W3; alpha0=alpha3;
        norm_n2 =  (d_xy*l)*(d_xy*l)+(-l+d_z*f_v)*(-l+d_z*f_v)
                  +(f_v-d_z*l)*(f_v-d_z*l); /* Square of length of n vector */
        vdotn = (vx*(l*d_xy)+ vy*(-l+f_v*d_z)+ vz*(f_v-l*d_z) );
        q = 2 * V2Q * fabs(vdotn) / sqrt(norm_n2);
        dvx = -2*(l*d_xy)*vdotn/norm_n2;
        dvy = -2*(-l+f_v*d_z)*vdotn/norm_n2;
        dvz = -2*(f_v-l*d_z)*vdotn/norm_n2;
        break;
      case 4:                   /* Upper horizontal mirror */
        m0=m4; w=W4; alpha0=alpha4;
        norm_n2 =  (-d_xy*l)*(-d_xy*l)+(l+d_z*f_v)*(l+d_z*f_v)
                  +(f_v+d_z*l)*(f_v+d_z*l); /* Square of length of n vector */
        vdotn = (vx*(-l*d_xy)+ vy*(l+f_v*d_z)+ vz*(f_v+l*d_z) );
        q = 2 * V2Q * fabs(vdotn) / sqrt(norm_n2);
        dvx = -2*(-l*d_xy)*vdotn/norm_n2;
        dvy = -2*(l+f_v*d_z)*vdotn/norm_n2;
        dvz = -2*(f_v+l*d_z)*vdotn/norm_n2;
        break;
      default:
        printf("Fatal error: No guide wall hit");
        exit(1);
    }
    /* Now compute reflectivity. */
    {
        double par[] = {R0, Qc, alpha0, m0, w};
        StdReflecFunc(q, par, &R);
        if (R > 0)
          p *= R;
        else ABSORB;
    }
    vx += dvx;
    vy += dvy;
    vz += dvz;
    SCATTER;
  }
%}

MCDISPLAY
%{
  double x;
  int i;

  
  multiline(5,
            -w1/2.0, -h1/2.0, 0.0,
             w1/2.0, -h1/2.0, 0.0,
             w1/2.0,  h1/2.0, 0.0,
            -w1/2.0,  h1/2.0, 0.0,
            -w1/2.0, -h1/2.0, 0.0);
  multiline(5,
            -w2/2.0, -h2/2.0, (double)l,
             w2/2.0, -h2/2.0, (double)l,
             w2/2.0,  h2/2.0, (double)l,
            -w2/2.0,  h2/2.0, (double)l,
            -w2/2.0, -h2/2.0, (double)l);
  line(-w1/2.0, -h1/2.0, 0, -w2/2.0, -h2/2.0, (double)l);
  line( w1/2.0, -h1/2.0, 0,  w2/2.0, -h2/2.0, (double)l);
  line( w1/2.0,  h1/2.0, 0,  w2/2.0,  h2/2.0, (double)l);
  line(-w1/2.0,  h1/2.0, 0, -w2/2.0,  h2/2.0, (double)l);
%}

END