File: FermiChopper_ILL.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 (686 lines) | stat: -rw-r--r-- 24,057 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
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2008, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Component: FermiChopper_ILL
*
* %Identification
*
* Written by: M. Poehlmann, C. Carbogno, H. Schober, E. Farhi
* Date:       May 2002
* Origin:     ILL Grenoble / TU Muenchen
* Modified by: K.Lieutenant, June 2005: added phase parameter. Comp validation.
* Modified by: E. Farhi, Jul 2008: uniformize parameter names ()
* Modified by: EF, Oct 2008: fix chopper orientation
* Modified by: EF, Mar 2009: fixed infinite recursion which may cause SEGV. Cleanup of code.
*
* Fermi Chopper with rotating frame.
*
* %D
* Models a Fermi chopper with optional supermirror coated blades
* supermirror facilities may be disabled by setting m = 0, R0=0
* Slit packages are straight. Chopper slits are separated by an infinitely
* thin absorbing material. The effective transmission (resulting from fraction
* of the transparent material and its transmission) may be specified.
* The chopper slit package width may be specified through the total width 'xwidth'
* of the full package or the width 'w' of each single slit. The other parameter
* is calculated by: xwidth = nslit*w.
*
* Example:
* FermiChopper_ILL(phase=-50.0, radius=0.04, nu=100,
*   yheight=0.08, w=0.00022475, nslit=200.0, R0=0.0,
*   Qc=0.02176, alpha=2.33, m=0.0, length=0.012, eff=0.95,
*   zero_time=0)
*
* Markus Poehlmann     <Markus.Poehlmann@ph.tum.de>
* Christian Carbogno   <carbogno@ph.tum.de>
* and Helmut Schober   <schober@ill.fr>
*
* %VALIDATION
* Apr 2005: extensive external test, most problems solved (cf. 'Bugs')
* Validated by: K. Lieutenant
*
* limitations:
* no blade width used
*
* %BUGS
* - overestimates peak width for long wavelengths
* - does not give the right pulse position, shape and width for slit widths below 0.1 mm
* - fails sometimes when using MPI
*
* %Parameters
* INPUT PARAMETERS:
*
* Geometrical chopper constants:
* radius: [m]   chopper cylinder radius
* yheight: [m]  Height of chopper
* nslit: [1]    number of chopper slits
* length: [m]   channel length of the Fermi chopper
* w: [m]        width of one chopper slit
* xwidth: [m]   optional total width of slit package
* nu:      [Hz]     chopper frequency
* eff:     [1]      efficiency = transmission x fraction of transparent material
* verbose: [1]      optional flag to display component statistics, use 1 or 3 (debuging)
*
* Supermirror constants:
* m:       [1]      m-value of material. Zero means completely absorbing.
* alpha:   [AA]     slope of reflectivity
* Qc:      [AA-1]   critical scattering vector
* W:      [AA-1]   width of supermirror cut-off
* R0:      [1]      low-angle reflectivity
*
* Constants to reset time of flight:
* zero_time: [1]    set time to zero: 0: no  1: once per half cycle
* phase:   [deg]    chopper phase at t=0
*
*
* %End
*****************************************************************************/

/* NOTE:
*   The initial component version (McStas version <= 1.12) was written
*   with an inverted coordinate frame orientation. This corresponds
*   to inverting the frequency and phase sign.
*/

DEFINE COMPONENT FermiChopper_ILL

SETTING PARAMETERS (phase=0, radius=0.04, nu=100,
yheight=0.08, w=0.00022475, nslit=200.0, R0=0.0,
Qc=0.02176, alpha=2.33, m=0.0, W=2e-3, length=0.012, eff=0.95,
zero_time=0, xwidth=0, verbose=0)

/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */
SHARE
%{
#ifndef FCILL_TimeAccuracy
#define FCILL_TimeAccuracy 1e-8
#define FCILL_MAXITER      10
/* Definition of internal variable structure: all counters */
struct FermiChopper_ILL_struct {

/** other variables ********************************/
double omega, t0;  /* chopper rotation */
};


/**************** DECLARING FUNCTIONS ***************************************/

/*********** ORTHOGONAL TRANSFORMATION INTO ROTATING FRAME ******************/

/************ X - component ********************/
#pragma acc routine seq
double xstrich(double X, double Z, double T, double omega, double t0){
  return( X*cos(omega*(T-t0))+Z*sin(omega*(T-t0)) );
}

/************ Z - component ********************/
#pragma acc routine seq
double zstrich(double X, double Z, double T, double omega, double t0){
  return( Z*cos(omega*(T-t0))-X*sin(omega*(T-t0)) );
}

/*************************NUMERICAL METHODS *********************************/

/*************************** SECANT METHOD FOR... ***************************/

/****************************...X-component *********************************/
#pragma acc routine seq
double xsecant(double x, double z, double vx, double vz,
               double t, double dt, double d, double omega, double t0){

  double dt1     = 1;
  double counter = 0;
  double t1      = 0;
  double t2      = dt;
  double xr1     = xstrich(x,z,t, omega, t0)-d;
  double xr2     = xstrich(x+vx*t2,z+vz*t2,t+t2, omega, t0)-d;
  double sign;

  while ((fabs(dt1) > FCILL_TimeAccuracy) && (counter < FCILL_MAXITER) && (xr2-xr1)){
    counter++;
    dt1 = (t2-t1)*xr2/(xr2-xr1);
    t2  = t1;
    xr1 = xr2;
    t1 += dt1;
    xr2 = xstrich(x+vx*t1,z+vz*t1,t+t1, omega, t0)-d;
  }

  if(counter >= FCILL_MAXITER) t1 = -2;

  return(t1);
}


/****************************...Z-component *********************************/
#pragma acc routine seq
double zsecant(double x, double z, double vx, double vz,
               double t, double dt, double d, double omega, double t0) {

  double t1      = 0;
  double t2      = dt;
  double dt1     = 1;
  double counter = 0;
  double zr1     =  zstrich(x,z,t, omega, t0)-d;
  double zr2     =  zstrich(x+vx*t2,z+vz*t2,t+t2, omega, t0)-d;

  while ((fabs(dt1) > FCILL_TimeAccuracy) && (counter < FCILL_MAXITER) && (zr2-zr1)){
    counter++;
    dt1 = (t2-t1)*zr2/(zr2-zr1);
    t2  = t1;
    zr1 = zr2;
    t1 += dt1;
    zr2 = zstrich(x+vx*t1,z+vz*t1,t+t1, omega, t0)-d;
  }

  if(counter >= FCILL_MAXITER) t1=-1;

  return(t1);
}


/*************************** INTERPOLATION METHOD FOR... ********************/

/****************************...X-component *********************************/
#pragma acc routine seq
double xinterpolation(double x, double z, double vx, double vz,
                      double t, double dt, double d, double omega, double t0){

  double sign;
  double xr3=1, t3=0, t1=0, t2=dt, dt1=dt;
  double counter = 0;
  double xr1      =  xstrich(x,z,t, omega, t0)-d;
  double xr2      =  xstrich(x+vx*dt,z+vz*dt,t+dt, omega, t0)-d;

  while ((fabs(xr3) > FCILL_TimeAccuracy)&&(counter < FCILL_MAXITER)){
    counter++;
    t3 = (t1+t2)*0.5;
    xr3 = xstrich(x+(vx*(t3)),z+(vz*(t3)),t+t3, omega, t0)-d;
    xr2 = xstrich(x+(vx*(t2)),z+(vz*(t2)),t+t2, omega, t0)-d;
    if(xr2*xr3<0) t1=t3;
    else          t2=t3;
  }

  if(counter >= FCILL_MAXITER) t3=-1;

  return(t3);
}


/****************************...Z-component *********************************/
#pragma acc routine seq
double zinterpolation(double x, double z, double vx, double vz,
                      double t, double dt, double d, double omega, double t0){

  double counter = 0;
  double zr3=1,zr2=0,t3=0,t1=0,t2=dt;

  while ((fabs(zr3)>FCILL_TimeAccuracy)&&(counter<FCILL_MAXITER)) {
    counter++;
    t3 = (t1+t2)*0.5;
    zr3 = zstrich(x+(vx*(t3)),z+(vz*(t3)),t+t3, omega, t0)-d;
    zr2 = zstrich(x+(vx*(t2)),z+(vz*(t2)),t+t2, omega, t0)-d;
    if(zr2*zr3 < 0) t1=t3;
    else            t2=t3;
  }

  if(counter >= FCILL_MAXITER) t3=-1;

  return(t3);
}
#endif
%}

DECLARE
%{
  struct FermiChopper_ILL_struct FCVars;
%}

INITIALIZE
%{

/************************* INITIALIZE COUNTERS ******************************/

  int i;

/************************ CALCULATION CONSTANTS *****************************/
  FCVars.omega    = 2*PI*nu;
  if (nu && phase) FCVars.t0 = -phase/360.0/nu;

  /* check of input parameters */
  if (m < 0) m == 0;
  if (radius <= 0) {
    printf("FermiChopper_ILL: %s: FATAL: unrealistic cylinder radius radius=%g [m]\n", NAME_CURRENT_COMP, radius);
    exit(-1);
  }
  if (yheight <= 0) 
  	exit(printf("FermiChopper_ILL: %s: FATAL: unrealistic cylinder yheight =%g [m]\n", NAME_CURRENT_COMP, yheight));
  if (xwidth > 0 && xwidth < radius*2 && nslit > 0) {
    w = xwidth/nslit;
  }
  if (w <= 0) {
    printf("FermiChopper_ILL: %s: FATAL: Slits in the package have unrealistic width w=%g [m]\n", NAME_CURRENT_COMP, w);
    exit(-1);
  }
  if (nslit*w > radius*2) {
    nslit = floor(radius/w);
    printf("FermiChopper_ILL: %s: Too many slits to fit in the cylinder\n"
           "Adjusting nslit=%f\n", NAME_CURRENT_COMP, nslit);
  }
  if (length > radius*2) {
    length = sqrt(radius*radius - nslit*w*nslit*w/4);
    printf("FermiChopper_ILL: %s: Slit package is longer than the whole\n"
           "chopper cylinder. Adjusting length=%g [m]\n", NAME_CURRENT_COMP, length);
  }

  if (eff <= 0 || eff > 1) {
    eff = 0.95;
    printf("FermiChopper_ILL: %s: Efficiency is unrealistic\n"
           "Adjusting eff=%f\n", NAME_CURRENT_COMP, eff);
  }
  if (Qc <= 0) { Qc = 0.02176; m = 0; R0=0; }
  if (W <= 0) W=1e-6;
  
  if (verbose && nu)
    printf("FermiChopper_ILL: %s: frequency nu=%g [Hz] %g [rpm], time frame=%g [s] phase=%g [deg]\n"
      , NAME_CURRENT_COMP, nu, nu*60, 2/nu, -FCVars.t0*360*nu);
  
  /* fix for the wrong coordinate frame orientation to come back to McStas XYZ system */
  FCVars.omega *= -1;
%}

TRACE
%{

  /** local CALCULATION VARIABLES**************************************/

  /** Interaction with slitpacket ***************************/
  double slit_input;   /* length of the slits */
  double zr1,zr2;       /* distance to slitpacket entrance/exit in rotating frame */
  double xr1,xr2;       /* X entrance/exit position in rotating frame */

  /** Variables for calculating interaction with blades ***************/
  double m1,m2;    /* slope of the tangents */
  double b1,b2;    /* y-intersection of tangent */

  /**  Reflections ***********************************************/
  double t3a, t3b, distance_Wa, distance_Wb;
  double n1,n2,n3,n4;

  /** variables used for calculating new velocities after reflection **/
  double q;
  double vper, vpar;
  double arg;

  /**  Multiple Reflections  ******************************/
  int loopcounter=0;   /* How many reflections happen? */

  /** Time variables *********************************/
  double t3;      /* interaction time */
  double dt;      /* interaction intervals */
  double t1,t2;   /* cylinder intersection time */


/************** test, if the neutron interacts with the cylinder ***/
  if (cylinder_intersect (&t1, &t2, x, y, z, vx, vy, vz, radius, yheight)) {

    if (t1 <= 0) {
      if (verbose > 2) 
      	printf("FermiChopper_ILL: %s: ABSORB Neutron started inside the cylinder, t1=%g (enter)\n", 
          NAME_CURRENT_COMP, t1);
      ABSORB;    /* Neutron started inside the cylinder */
    }

    dt=t2-t1;     /* total time of flight inside the cylinder  */
    PROP_DT(t1);  /* Propagates neutron to entrance of the cylinder */
    
    if (verbose > 2)
      printf("FermiChopper_ILL: %s: PROP_DT t1=%8.3g t2=%8.3g xyz=[%8.3g %8.3g %8.3g] v=[%8.3g %8.3g %8.3g] t=%8.3g (IN cyl).\n",
             NAME_CURRENT_COMP, t1, t2, x,y,z,vx,vy,vz,t);

    if(dt > fabs(0.5/FCVars.omega*2*PI) && verbose) {
      printf("FermiChopper_ILL: %s: Frequency too low. Method will fail.\n"
             "              Absorbing neutron\n", NAME_CURRENT_COMP);
      ABSORB;
    }

  /* Checks if neutron enters or leaves from top or bottom of cylinder. */
    if ( fabs(y) > yheight/2 ||
        fabs(y+vy*dt) > yheight/2 ) {
      if (verbose > 2) 
      	printf("FermiChopper_ILL: %s: ABSORB Neutron hits top/bottom of cylinder, y=%8.3g (enter)\n", 
          NAME_CURRENT_COMP, y);
      ABSORB;
    }

  /*  checking wether the neutron can enter the chopper (slit channel) */
    xr1 = xstrich(x,z,t, FCVars.omega, FCVars.t0);
    if(fabs(xr1)>=nslit*w/2) {
      if (verbose > 2) 
      	printf("FermiChopper_ILL: %s: ABSORB Neutron X is outside cylinder aperture, xp1=%8.3g (enter)\n", 
          NAME_CURRENT_COMP, xr1);
      ABSORB;
    }

  /*********************** PROPAGATE TO SLIT PACKAGE **************************/


    /* Checking on which side of the Chopper the Neutron enters******/
    slit_input = 0.5*length;
    zr1 = zstrich(x,z,t, FCVars.omega, FCVars.t0);
    zr2 = zstrich(x+vx*dt,z+vz*dt,t+dt, FCVars.omega, FCVars.t0);
    if(zr1 < 0) slit_input *= -1;

    /*  Checking if the Neutron will hit the slits (Z) */
    zr1  -=  slit_input;
    zr2  -=  slit_input;

    if (zr2*zr1>0) {
      if (verbose > 2) 
      	printf("FermiChopper_ILL: %s: ABSORB Neutron Z does not change sign, zr1=%8.3g zr2=%8.3g (enter)\n", 
          NAME_CURRENT_COMP, zr1,zr2);
      ABSORB;
    }

    /* Calculating where/when Neutron hits the slits (Z) */
    t3 = zsecant(x,z,vx,vz,t,dt,slit_input, FCVars.omega, FCVars.t0);

    if((t3 < 0)||(t3 > dt)) {
      t3 = zinterpolation(x,z,vx,vz,t,dt,slit_input, FCVars.omega, FCVars.t0);
    }
    if((t3 < 0)||(t3 > dt)) {
      if (verbose) 
      	printf("FermiChopper_ILL: %s: Can not reach entrance of slits. dt=%g t3=%g\n", NAME_CURRENT_COMP, dt, t3);
      ABSORB;
    }

    /* Propagating whole system to that point */
    PROP_DT(t3);
    dt -= t3;
    SCATTER;
    
    if (verbose > 2)
      printf("FermiChopper_ILL: %s: PROP_DT t3=%8.3g dt=%8.3g xyz=[%8.3g %8.3g %8.3g] length=%g (slit enter).\n",
             NAME_CURRENT_COMP, t3, dt, x,y,z, slit_input);

    /* Checking if neutron hits the slits entrance window (X) */
    xr1 = xstrich(x,z,t, FCVars.omega, FCVars.t0);
    if(fabs(xr1) >= nslit*w/2) {
      if (verbose > 2) 
      	printf("FermiChopper_ILL: %s: ABSORB Neutron X is outside slit package, xp1=%8.3g (enter)\n", 
        NAME_CURRENT_COMP, xr1);
      ABSORB;
    }

    /* Calculating where/when Neutron leaves the slits (Z) */
    t3 = zsecant(x,z,vx,vz,t,dt,-slit_input, FCVars.omega, FCVars.t0);
    if((t3 < 0) || (t3 > dt)){
      t3 = zinterpolation(x,z,vx,vz,t,dt,-slit_input, FCVars.omega, FCVars.t0);
    }
    if((t3 <= 0) || (t3 > dt)){
      if (verbose) 
      	printf("FermiChopper_ILL: %s: Can not reach exit of slits. dt=%8.3g t3=%8.3g\n", NAME_CURRENT_COMP, dt, t3);
      ABSORB;
    } else dt=t3;

  /********************* PROPAGATION INSIDE THE SLIT PACKET *******************/

    /* Which slit was hit ? */
    n1 = floor(xr1/w);


  /******************* BEGIN LOOP FOR MULTIPLE REFLECTIONS ********************/

    for(loopcounter; loopcounter<=FCILL_MAXITER;loopcounter++){
    	double dt_to_tangent=0; /* time shift to go to tangent intersection */

  /* Calculate most probable time for interaction with blades by using tangents */
      m1 = xstrich(vx,vz,t, FCVars.omega, FCVars.t0)
         + FCVars.omega * zstrich(x,z,t, FCVars.omega, FCVars.t0);
      m2 = xstrich(vx,vz,t+dt, FCVars.omega, FCVars.t0)
         + FCVars.omega * zstrich(x+vx*dt,z+vz*dt,t+dt,FCVars.omega,FCVars.t0);

      b1 = xstrich(x,z,t, FCVars.omega, FCVars.t0) - m1*t;
      b2 = xstrich(x+vx*dt,z+vz*dt,t+dt, FCVars.omega, FCVars.t0) - m2*(t+dt);

      if (m1-m2) dt_to_tangent = ((b2-b1)/(m1-m2))-t;
      else       dt_to_tangent = -1;

      /* If method with tangents doesn't succeed, just take the middle of the interval */
      if((dt_to_tangent < 0)||(dt_to_tangent > dt)) dt_to_tangent=dt*0.5;

      /* Calculate different positions for the neutron to determine interaction. */

      /*...at the end of the slit: */
      n2 = floor(xstrich(x+(vx*dt),z+(vz*dt),t+dt, FCVars.omega, FCVars.t0)/w);

      /*...at the before calculated t3: tangent intersection point */
      n3 = floor(xstrich(x+(vx*dt_to_tangent),z+(vz*dt_to_tangent),t+dt_to_tangent, FCVars.omega, FCVars.t0)/w);

      if (verbose > 2)
        printf("FermiChopper_ILL: %s: t3=%8.3g n=[%g %g %g] (time at tangent intersection).\n",
             NAME_CURRENT_COMP, dt_to_tangent, n1, n2, n3);

      /* Does the neutron stay in the same slit ? */
      if((n2!=n1)||(n3!=n1)){

        /* Choosing the first time it isn't in the slit anymore */
        if(n3!=n1){
          n2 = n3;
        }

      /************ABSORB to save calculation time ******************/
        if (m == 0 || R0 == 0) {
          if (verbose > 2) 
          	printf("FermiChopper_ILL: %s: ABSORB Neutron hits absorbing coating (change slit).\n", 
              NAME_CURRENT_COMP);
          ABSORB;
        }


  /********************** WHEN DOES IT HIT THE BLADE? *************************/

        /*********** SECANT METHOD ****************************/
        /* get position of slit wall towards which neutron is propagating */
        if (n2 > n1) {     /* X' positive side of slit is in principle the first intersection to test*/
          distance_Wa = n1*w+w;
          distance_Wb = n1*w;
        } else {           /* X' negative side of slit */
        	distance_Wb = n1*w+w;
          distance_Wa = n1*w;
        }

        /* time shift to reach slit wall point in [0,dt_to_tangent]: X'=distance_W slit_wall */
        t3a = xsecant(x,z,vx,vz,t,dt,distance_Wa, FCVars.omega, FCVars.t0);
        t3b = xsecant(x,z,vx,vz,t,dt,distance_Wb, FCVars.omega, FCVars.t0);
        if (t3b < 0) t3 = t3a;
        else if (t3a < 0 && t3b > 0) t3 = t3b;
        else t3 = (t3a < t3b ? t3a : t3b);

        /***** INTERPOLATION USED WHEN SECANT METHOD FAILS ****/
        /* try second intersection method in case of failure */
        if ((t3 < 0) || (t3 > dt)) {
        	t3a = xinterpolation(x,z,vx,vz,t,dt,distance_Wa, FCVars.omega, FCVars.t0);
        	t3b = xinterpolation(x,z,vx,vz,t,dt,distance_Wb, FCVars.omega, FCVars.t0);
        	if (t3b < 0) t3 = t3a;
		      else if (t3a < 0 && t3b > 0) t3 = t3b;
		      else t3 = (t3a < t3b ? t3a : t3b);
        }

        /* Check for errors in calculation*******/
        if ((t3 < 0) || (t3 > dt)) {
          if (verbose) 
          	printf("FermiChopper_ILL: %s: Reflecting interpolation Problem. dt=%8.3g t3=%8.3g\n", 
          	NAME_CURRENT_COMP, dt, t3);
          ABSORB;
        }
        /* Propagate whole system to that point */
        PROP_DT(t3); dt -= t3;
        if (verbose > 2)
          printf("FermiChopper_ILL: %s: PROP_DT t3=%8.3g dt=%8.3g xyz=[%8.3g %8.3g %8.3g] (on wall).\n",
             NAME_CURRENT_COMP, t3, dt, x,y,z);

        /* Check if this point is inside the slit packet */
        if(fabs(zstrich(x,z,t, FCVars.omega, FCVars.t0)) > fabs(slit_input)){
          if (verbose > 2) 
          	printf("FermiChopper_ILL: %s: Neutron is outside slit pack (on slit wall).\n", 
                NAME_CURRENT_COMP);
          break;
        }

  /******************** REFLECTION ALGORITHM ********************************/
        vper    = xstrich(vx,vz,t, FCVars.omega, FCVars.t0); /* perpendicular velocity (to blade) */
        vpar    = zstrich(vx,vz,t, FCVars.omega, FCVars.t0);  /* parallel velocity (to blade) */
        q       = 2*MS2AA*(fabs(vper));

        if (q > Qc && W){
          arg = (q-m*Qc)/W;
          if (arg < 10.0) p *= 0.5*(1-tanh(arg))*(1-alpha*(q-Qc));
          else {
            if (verbose > 2) 
            	printf("FermiChopper_ILL: %s: ABSORB Neutron hits absorbing coating (on slit wall).\n", 
                NAME_CURRENT_COMP);
            ABSORB;
          }
        }

        if (R0 != 0.0){
          p *= R0;

          vper *= (-1);   /* Mirroring perpendicular velocity */

          /**************SET NEW VELOCITIES***********/
          vx =  vper*cos(FCVars.omega*(t-FCVars.t0))
             -  vpar*sin(FCVars.omega*(t-FCVars.t0));
          vz =  vper*sin(FCVars.omega*(t-FCVars.t0))
             +  vpar*cos(FCVars.omega*(t-FCVars.t0));
          SCATTER;
        } else {
          if (verbose > 2) 
          	printf("FermiChopper_ILL: %s: ABSORB Neutron hits absorbing coating (R0=0).\n", 
              NAME_CURRENT_COMP);
         ABSORB;
        }


        /* Recalculating when Neutron will leave the slitpacket */
        t3 = zsecant(x,z,vx,vz,t,dt,-slit_input,FCVars.omega,FCVars.t0);
        if((t3 < 0) || (t3 > dt)) {
          t3=zinterpolation(x,z,vx,vz,t,dt,-slit_input,
                             FCVars.omega,FCVars.t0);
        }
        /* Check for errors in calculation*******/
        if ((t3 < 0) || (t3 > dt)) {
          if (verbose) 
          	printf("FermiChopper_ILL: %s: Reflecting interpolation Problem. dt=%8.3g t3=%8.3g\n", 
          	NAME_CURRENT_COMP, dt, t3);
          ABSORB;
        } else  dt=t3;
      } /* end if n2 != n2 != n3 */
      else break;
    } /* end for */
  /********************* END OF THE FOR LOOP **********************************/

    /****New time of cylinder intersection will be calculated**********/
    if (!cylinder_intersect (&t1, &t2, x, y, z, vx, vy, vz, radius, yheight)) {
    	if (verbose > 2) 
    		printf("FermiChopper_ILL: %s: ABSORB Neutron has unexpectidely exited cylinder ! (exiting)\n", 
    			NAME_CURRENT_COMP);
    	ABSORB; 
    }

    if (t1 > 0 && verbose) {
      printf("FermiChopper_ILL: %s: Neutrons are leaving chopper in the wrong direction! \n", NAME_CURRENT_COMP);
    }

    if (t2 <= 0 && verbose) {
      printf("FermiChopper_ILL: %s: Neutrons are leaving chopper without any control\n", NAME_CURRENT_COMP);
    }

  /*********** PROPAGATE TO CYLINDER SURFACE ***********************************/
    PROP_DT(t2);
    SCATTER;
    
    if (verbose > 2)
      printf("FermiChopper_ILL: %s: t1=%8.3g PROP_DT t2=%8.3g xyz=[%8.3g %8.3g %8.3g] (OUT cyl).\n",
             NAME_CURRENT_COMP, t1, t2, x,y,z);

    /*****Checking if the neutron left the cylinder by his top or bottom **/
    if  ( fabs(y) > yheight/2 ){
      if (verbose > 2) 
      	printf("FermiChopper_ILL: %s: ABSORB Neutron hits top/bottom of cylinder, y=%8.3g (exiting)\n", 
          NAME_CURRENT_COMP, y);
      ABSORB;
    }


    /*****Checking if neutron hits chopper exit ***/
    if(fabs(xstrich(x,z,t,FCVars.omega,FCVars.t0))>=nslit*w/2){
      if (verbose > 2) 
      	printf("FermiChopper_ILL: %s: ABSORB Neutron X is outside slit package cylinder, xp1=%8.3g (exiting)\n", 
          NAME_CURRENT_COMP, xstrich(x,z,t,FCVars.omega,FCVars.t0));
      ABSORB;
    }

    /**** Transmission coefficent******/
    p = p*eff;          //finite cross section + transmission

  } /* end if cylinder_intersect */
  else {
    if (verbose > 2 && 0) 
    	printf("FermiChopper_ILL: %s: ABSORB Neutron has not interacted with FC\n", 
        NAME_CURRENT_COMP);
    ABSORB;
  }

/************************ TIME OF FLIGHT RESET ************************/
  if (zero_time && nu)
    t -= (((int)((t+1/(4*nu))/(1/(2*nu))))*(1/(2*nu)));
%}

MCDISPLAY
%{
  double index=0;
  double xpos, zpos;
  double ymax = yheight/2; 
  double ymin = -ymax;
  
  /* cylinder top/center/bottom  */
  circle("xz", 0,ymax,0,radius);
  circle("xz", 0,0   ,0,radius);
  circle("xz", 0,ymin,0,radius);
  /* vertical lines to make a kind of volume */
  line( 0  ,ymin,-radius, 0  ,ymax,-radius);
  line( 0  ,ymin, radius, 0  ,ymax, radius);
  line(-radius,ymin, 0  ,-radius,ymax, 0  );
  line( radius,ymin, 0  , radius,ymax, 0  );
  /* slit package */
  index = -nslit/2;
  zpos  = length/2;
  for (index = -nslit/2; index < nslit/2; index++) {
    xpos = index*w;
    multiline(5, xpos, ymin, -zpos,
                 xpos, ymax, -zpos,
                 xpos, ymax, +zpos,
                 xpos, ymin, +zpos,
                 xpos, ymin, -zpos);
  }
  /* cylinder inner sides containing slit package */
  xpos = nslit*w/2;
  zpos = sqrt(radius*radius - xpos*xpos);
  multiline(5,   xpos, ymin, -zpos,
                 xpos, ymax, -zpos,
                 xpos, ymax, +zpos,
                 xpos, ymin, +zpos,
                 xpos, ymin, -zpos);
  xpos *= -1;
  multiline(5,   xpos, ymin, -zpos,
                 xpos, ymax, -zpos,
                 xpos, ymax, +zpos,
                 xpos, ymin, +zpos,
                 xpos, ymin, -zpos);
%}
END