/*******************************************************************************
*
* Mcstas, neutron ray-tracing package
*         Copyright (C) 1997-2008, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Component: Moderator
*
* %I
* Written by: KN, M.Hagen
* Date: August 1998
* Origin: Risoe
*
* A simple pulsed source for time-of-flight.
*
* %D
* Produces a simple time-of-flight spectrum, with a flat energy distribution
*
* Example: Moderator(radius = 0.0707, dist = 9.035, focus_xw = 0.021, focus_yh = 0.021, Emin = 10, Emax = 15, Ec = 9.0, t0 = 37.15, gamma = 39.1)
*
* %P
* Input parameters:
*
* radius: [m]                Radius of source
* Emin: [meV]                Lower edge of energy distribution
* Emax: [meV]                Upper edge of energy distribution
* target_index: [1]          relative index of component to focus at, e.g. next is +1 this is used to compute 'dist' automatically.
* dist: [m]                  Distance from source to the focusing rectangle
* focus_xw: [m]              Width of focusing rectangle
* focus_yh: [m]              Height of focusing rectangle
* t0: [mus]                  decay constant for low-energy neutrons
* Ec: [meV]                  Critical energy, below which the flux decay is constant
* gamma: [meV]               energy dependence of decay time
* flux: [1/(s cm 2 st meV)]  flux
*
* %E
*******************************************************************************/

DEFINE COMPONENT Moderator

SETTING PARAMETERS (radius=0.07, Emin, Emax, dist=0, focus_xw=0.02, focus_yh=0.02, t0=37.15, Ec=9.0, gamma=39.1, int target_index=+1, flux=1)

/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */
DECLARE
%{
double p_in;
%}
INITIALIZE
%{
p_in = flux*1e4*PI*radius*radius/mcget_ncount();
  if (Emin < Emax) p_in *= Emax-Emin;
  if (target_index && !dist)
  {
    Coords ToTarget;
    double tx,ty,tz;
    ToTarget = coords_sub(POS_A_COMP_INDEX(INDEX_CURRENT_COMP+target_index),POS_A_CURRENT_COMP);
    ToTarget = rot_apply(ROT_A_CURRENT_COMP, ToTarget);
    coords_get(ToTarget, &tx, &ty, &tz);
    dist=sqrt(tx*tx+ty*ty+tz*tz);
  }
  if (radius < 0 || Emin < 0 || Emax < 0 || dist <= 0 || focus_xw < 0 || focus_yh < 0 || Ec < 0 || gamma <= 0 || Emin>=Emax ) {
      printf("Moderator: %s: Error in input parameter values!\n"
             "ERROR          Exiting\n",
           NAME_CURRENT_COMP);
      exit(0);
  }
%}
TRACE
%{
   double chi,v,r,tauv,E, xf, yf, rf, dx, dy, pdir;

   z=0;

   chi = 2*PI*rand01();          /* Choose point on source */
   r = sqrt(rand01())*radius;    /* with uniform distribution. */
   x = r*cos(chi);
   y = r*sin(chi);

   randvec_target_rect_real(&xf, &yf, &rf, &pdir,
		       0, 0, dist, focus_xw, focus_yh, ROT_A_CURRENT_COMP, x, y, z, 2);

   dx = xf-x;
   dy = yf-y;
   rf = sqrt(dx*dx+dy*dy+dist*dist);

   p = pdir*p_in;

   E = Emin+(Emax-Emin)*rand01();      /* Assume linear distribution */
   v = SE2V*sqrt(E);

   vz=v*dist/rf;
   vy=v*dy/rf;
   vx=v*dx/rf;

   if(E < Ec)
   {
     tauv = t0;
   }
   else
   {
     double tmp = ((E - Ec) / gamma);
     tauv = t0 / (1 + (tmp*tmp));
   }
   t = -tauv*log(rand01())*1E-6;
   SCATTER;
%}

MCDISPLAY
%{
  
  circle("xy",0,0,0,radius);
  if (dist) {
    dashed_line(0,0,0, -focus_xw/2,-focus_yh/2,dist, 4);
    dashed_line(0,0,0,  focus_xw/2,-focus_yh/2,dist, 4);
    dashed_line(0,0,0,  focus_xw/2, focus_yh/2,dist, 4);
    dashed_line(0,0,0, -focus_xw/2, focus_yh/2,dist, 4);
  }
%}

END
