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
|