File: Pol_constBfield.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 (151 lines) | stat: -rw-r--r-- 3,830 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
/**************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright 1997-2006, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Component: Pol_constBfield
*
* %I
* Written by: Peter Christiansen
* Date: July 2006
* Origin: RISOE
*
* Constant magnetic field.
*
* %D
*
* Rectangular box with constant B field along y-axis (up). The
* component can be rotated to make either a guide field or a spin
* flipper. A neutron hitting outside the box opening or the box sides
* is absorbed.
*
* Example: Pol_constBfield(xwidth=0.1, yheight=0.1, zdepth=0.2, fliplambda=5.0)
*
* %P
* INPUT PARAMETERS:
*
* xwidth: [m]     Width of opening
* yheight: [m]    Height of opening
* zdepth: [m]     Length of field
* B: [Gauss]      Magnetic field along y-direction
* fliplambda: []  lambda for calculating B field
* flipangle: []   Angle flipped for lambda = fliplambda fliplambda and flipangle overrides B so a neutron with s= (1, 0, 0) and v = (0, 0, v(fliplambda)) will have s =(cos(flipangle), sin(flipangle), 0) after the section.
*
* CALCULATED PARAMETERS:
*
* %E
*******************************************************************************/
DEFINE COMPONENT Pol_constBfield



SETTING PARAMETERS (xwidth, yheight, zdepth, B=0, fliplambda=0, flipangle=180)


/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */

SHARE
%{
  double IntersectWall(double pos, double vel, double wallpos) {
    /* Function to calculate where the neutron hit the wall */
    if(vel==0)
      return -1;

    if(vel>0)
      return (wallpos-pos)/vel;
    else
      return (-wallpos-pos)/vel;
  }
%}

DECLARE
%{
  // Larmor frequency
  double omegaL;
%}

INITIALIZE
%{
  omegaL = 0;

  double velocity = 0, time = 0;

  if ((xwidth<=0) || (yheight<=0) || (zdepth<=0)) {
    fprintf(stderr, "Pol_filter: %s: Null or negative volume!\n"
	    "ERROR      (xwidth, yheight, zdepth). Exiting\n",
	    NAME_CURRENT_COMP);
    exit(1);
  }

  // neutron Larmor frequency: omegaL=29.16 MHz/Tesla * B(Neutron Data Booklet)
  // omegaL/B = -2*mu_n/hbar = -2.0*1.913*5.051e-27/1.055e-34
  omegaL = -2 * PI * 29.16e6 * B * 1e-4; // B is in Gauss

  if(fliplambda>0){
    velocity = K2V*2*PI/fliplambda;
    time = zdepth/velocity;

    // omegaL*time = flipangle
    omegaL = flipangle*DEG2RAD/time;

    // omegaL = 2*PI*29.16 MHz/T*B
    B = omegaL / -2 / 29.16e6 / PI / 1e-4; // Gauss

    printf("Pol_constBfield: %s: Magnetic field set to B=%f Gauss\n",
           NAME_CURRENT_COMP, B);
  }
%}

TRACE
%{
  double deltaT, deltaTx, deltaTy, sx_in, sz_in;

  PROP_Z0;
  if (!inside_rectangle(x, y, xwidth, yheight))
    ABSORB;

  // Time spent in B-field
  deltaT = zdepth/vz;

  // check that track goes throgh without hitting the walls
  if (!inside_rectangle(x+vx*deltaT, y+vy*deltaT, xwidth, yheight)) {

    // Propagate to the wall and absorb
    deltaTx = IntersectWall(x, vx, xwidth/2);
    deltaTy = IntersectWall(y, vy, yheight/2);

    if (deltaTx>=0 && deltaTx<deltaTy)
      deltaT = deltaTx;
    else
      deltaT = deltaTy;

    PROP_DT(deltaT);

    ABSORB;
  }

  PROP_DT(deltaT);

  // The solution to neutron precession in a constant field along the
  // z-axis is:
  // sx(deltaT) = cos(omegaL*deltaT)*sx(0) - sin(omegaL*deltaT)*sy(0)
  // sy(deltaT) = sin(omegaL*deltaT)*sx(0) + cos(omegaL*deltaT)*sy(0)
  // sz(deltaT) = sz(0)
  // see e.g. W. Gavin Willams "Polarized Neutrons", page 18.
  // In our geometry (x', y', z') where y' = z we get x' = y and z'= x

  sx_in = sx;
  sz_in = sz;

  sz = cos(omegaL*deltaT)*sz_in - sin(omegaL*deltaT)*sx_in;
  sx = sin(omegaL*deltaT)*sz_in + cos(omegaL*deltaT)*sx_in;
%}

MCDISPLAY
%{
  box(0, 0, zdepth/2, xwidth, yheight, zdepth,0, 0, 1, 0);
%}

END