/***************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright 1997-2002, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Component: He3_cell
*
* %Identification
* Written by: Trefor Roberts & Erik B Knudsen
* Date: March 1999
* Origin: ILL/DTU Physics
* version: $Revision$
*
* Polarised 3He cell
*
* %Description
* Simple cylindrical polarised 3He neutron spin filter cell.
* The glass container for the cell is not included in the model.
*
* This component has been validated against:
* Batz, M, Baessler, S, Heil, W, et al., J Res Natl Inst Stand Technol. 2005;110(3):293–298.
*
* Example: He3_cell(radius=0.1,length=.2,pressure=3,p3he=0.7,bx=0,by=1e-3,bz=0)
*
* %Parameters
* Input parameters:
*
* radius: [m]      radius of the cylinder 
* length: [m]      length of the cylinder 
* pressure: [bar]  pressure of the gas in the cell 
* p3he:      polarisation of the 3He gas [-1 to +1]
* bx: [tesla]      x component of field at the cell 
* by: [tesla]      y component of field at the cell 
* bz: [tesla]      z component of field at the cell 
*
* %End
***************************************************************************/

DEFINE COMPONENT He3_cell
DEFINITION PARAMETERS ()
SETTING PARAMETERS (radius,length,pressure=3,p3he=0.7,bx=0,by=1e-3,bz=0)
OUTPUT PARAMETERS ()
/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */

DECLARE
%{
%}

INITIALIZE
%{
%}

TRACE
%{

  double t0,t1;        /* time that neutron enters and leaves gas (s) */
  double v,lambda;      /* neutron velocity and wavelength (ms-1, Anstroms) */
  double l_full;       /* path length of neutron through gas (m) */
  double dt0;          /* time neutron spends in the gas (s) */
  double opacity;      /* opacity of the gas for this neutron (dimless) */
  double omega;        /* angle through which polarisation precesses
                          over the path through the cell (radians) */
  double px,py,pz;     /* auxilliary vector polarisation (-1 to +1) */
  double bnx,bny,bnz;  /* normal vector parallel to the magnetic field*/

  const double gyro = 1.832e8; /*absolute value of the gyromagnetic ratio of the neutron (1/(s.T))*/
  const double opac_cnv = 7.33; /*opacity conversion factor to express opacity in (bar.m.angstrom)*/


  /* calculate the intersection times with the volume of gas, if the neutron
     goes through the cell, continue with calculation otherwise all done.
     Note that y and z are swapped - this is because the cylindrical axis of
     a 3He cell lies along the beam. */

  if(cylinder_intersect(&t0,&t1,x,z,y,vx,vz,vy,radius,length))
  {
    /* Calculate the neutron velocity and wavelength */
    v=sqrt(vx*vx+vy*vy+vz*vz);
    lambda=2*PI/(V2K*v);

    /* Calculate the path length of the neutron through the gas */
    dt0=t1-t0;
    l_full=v*dt0;

    /* Calculate the opacity of the cell for the path length travelled */
    opacity=pressure*l_full*lambda*opac_cnv;

    /* propagate the polarisation accross the cell (assuming a constant
       magnetic field).  The actual interaction point is not taken into account
       as only the parallel and perpendicular components are important. */

    omega=dt0*gyro*sqrt(bx*bx+by*by+bz*bz);
    rotate(px,py,pz,sx,sy,sz,omega,bx,by,bz);
    sx=px;
    sy=py;
    sz=pz;

    /* adjust the neutron weight according to spin state relative to the
       3He nuclei - antiparallel spins are as good as absorbed, whereas parallel
       spins are transmitted (depending upon degree of polarisation of gas */
    bnx=bx;bny=by;bnz=bz;
    NORM(bnx,bny,bnz);
    double pm1=scalar_prod(sx,sy,sz,bnx,bny,bnz);
    double phiu,phid,T, Tup,Tdown;

    phiu=((pm1)+1)/2.0;
    phid=(1-(pm1))/2.0;
    Tup=exp(-opacity*(1.0-p3he));
    Tdown=exp(-opacity*(1.0+p3he));

    p*=phiu*Tup + phid*Tdown;

    /*set the outgoing polarization vector without touching the part perpendicular
      to the polarisation of the gas .
      Perpendicular comp: P_=S - P// = S - (S.b_n)b_n
      Parallel comp: P// = Pn bn, where Pn is the polarisation efficiency.*/
    px=sx - pm1*bnx;
    py=sy - pm1*bny;
    pz=sz - pm1*bnz;


    double Pn=(Tup-Tdown)/(Tup+Tdown);
    sx=px + Pn*bnx;
    sy=py + Pn*bny;
    sz=pz + Pn*bnz;

    SCATTER;
  }
%}

MCDISPLAY
%{
  
  circle("xy",0.0,0.0,-length/2.0,radius);
  circle("xy",0.0,0.0,length/2.0,radius);
  line(0.0,radius,-length/2.0,0.0,radius,length/2.0);
  line(radius,0.0,-length/2.0,radius,0.0,length/2.0);
  line(0.0,-radius,-length/2.0,0.0,-radius,length/2.0);
  line(-radius,0.0,-length/2.0,-radius,0.0,length/2.0);
%}

END
