/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright 1997-2002, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Component: ESS_moderator_short
*
* %I
* Written by: KL, February 2001
* Modified by: KL, 18 November 2001
* Origin: Risoe
*
* A parametrised pulsed source for modelling ESS short pulses.
*
* %D
* Produces a time-of-flight spectrum, from the ESS parameters
* Chooses evenly in lambda, exponentially decaying in time .
* Adapted from Moderator by: KN, M.Hagen, August 1998
*
* Units of flux: n/cm^2/s/AA/ster
* (McStas units are in general neutrons/second)
*
* Example general parameters (general):
*          size=0.12 Lmin=0.1 Lmax=10 dist=2 focus_xw=0.06 yh=0.12 nu=50
*          branchframe=0.5
*
* Example moderator specific parameters
* (From F. Mezei, "ESS reference moderator characteristics for ...", 4/12/00:
*  Defining the normalised Maxwelian
*     M(lam,T) = 2 a^2 lam^-5 exp(-a/lam^2); a=949/T; lam in AA; T in K,
*   and the normalised pulse shape function
*     F(t,tau,n) = ( exp(-t/tau) - exp(-nt/tau) ) n/(n-1)/tau,
*   the flux distribution is given as
*     Phi(t,lam) =  I0 M(lam,T) F(t,tau,n)
*                 + I2/(1+exp(chi2 lam-2.2))/lam*F(t,tau2*lam,n2)  )
*
*   a1: Ambient H20, short pulse, decoupled poisoned
*          T=325 tau=22e-6 tau1=0 tau2=7e-6 n=5 n2=5 chi2=2.5
*          I0=9e10 I2=4.6e10    branch1=0 branch2=0.5
*
*   a2: Ambient H20, short pulse, decoupled un-poisoned
*          T=325 tau=35e-6 tau1=0 tau2=12e-6 n=5 n2=5 chi2=2.5
*          I0=1.8e11 I2=9.2e10    branch1=0 branch2=0.5
*
*   a3: Ambient H20, short pulse, coupled
*          T=325 tau=80e-6 tau1=400e-6 tau2=12e-6 n=20 n2=5 chi2=2.5
*          I0=4.5e11 I2=9.2e10    branch1=0.5 branch2=0.5
*
*   b1: Liquid H2, short pulse, decoupled poisoned
*          T=50 tau=49e-6 tau1=0 tau2=7e-6 n=5 n2=5 chi2=0.9
*          I0=2.7e10 I2=4.6e10    branch1=0 branch2=0.5
*
*   b2: Liquid H2, short pulse, decoupled un-poisoned
*          T=50 tau=78e-6 tau1=0 tau2=12e-6 n=5 n2=5 chi2=0.9
*          I0=5.4e10 I2=9.2e10    branch1=0 branch2=0.5
*
*   b3: Liquid H2, short pulse, coupled
*          T=50 tau=287e-6 tau1=0 tau2=12e-6 n=20 n2=5 chi2=0.9
*          I0=2.3e11 I2=9.2e10    branch1=0 branch2=0.5
*
* %P
* Input parameters:
*
* size: [m]          Edge of cube shaped source
* Lmin: [AA]         Lower edge of wavelength distribution
* Lmax: [AA]         Upper edge of wavelength distribution
* dist: [m]          Distance from source to focusing rectangle; at (0,0,dist)
* focus_xw: [m]      Width of focusing rectangle
* focus_yh: [m]      Height of focusing rectangle
* target_index: [1]  relative index of component to focus at, e.g. next is +1 this is used to compute 'dist' automatically.
* nu: [Hz]           Frequency of pulses
* T: [K]             Temperature of source
* tau: [s]           long time decay constant for pulse, 1a
* tau1: [s]          long time decay constant for pulse, 1b (only for coupled water, else 0)
* tau2: [s/AA]       long time decay constant for pulse, 2
* n: [1]             pulse shape parameter 1
* n2: [1]            pulse shape parameter 2
* chi2: [1/AA]       lambda-distribution parameter in pulse 2
* I0: [flux]         integrated flux 1 (in flux units, see above) (default 9e10)
* I2: [flux*AA]      integrated flux 2 (default 4.6e10)
* branch1: [1]       limit for switching between distribution 1 and 2. (has effect only for coupled water, tau1>0)
* branch2: [1]       limit for switching between distribution 1 and 2. (default value 0.5)
* branchframe: [1]   limit for switching between 1st and 2nd pulse (if only one pulse wanted: 1)
*
* %E
*******************************************************************************/

DEFINE COMPONENT ESS_moderator_short

SETTING PARAMETERS (size, Lmin, Lmax, dist, focus_xw, focus_yh,
nu=50, T=325, tau=22e-6, tau1=0, tau2=7e-6, n=5, n2=5,
chi2=2.5, I0=9e10, I2=4.6e10, branch1=0, branch2=0.5 ,
branchframe=0, int target_index=+1)

SHARE
%{
double Mezei_M_fct(double l, double temp)
  {
    double a=949.0/temp;
    return 2*a*a*exp(-a/(l*l))/(l*l*l*l*l);
  }

  double Mezei_F_fct(double t, double tau, int n)
  {
    return (exp(-t/tau)-exp(-n*t/tau))*n/(n-1)/tau;
  }
%}

DECLARE
%{
  double l_range;
  double w_mult;
  double Delta_t;
%}

INITIALIZE
%{
  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 (n == 1 || n2 == 1 || Lmin<=0 || Lmax <=0 || dist == 0
    || branch1 == 1 || branch2 == 1 || tau == 0)
  {
    printf("ESS_moderator_short: %s: Check parameters (lead to Math Error).\n Avoid 0 value for {Lmin Lmax dist tau} and 1 value for {n n2 branch1/2/frame}\n", NAME_CURRENT_COMP);
    exit(-1);
  }

  Delta_t = 1.0/(double)nu;
  l_range = Lmax-Lmin;
  w_mult = size*size*1.0e4;     /* source area correction */
  w_mult *= l_range;            /* wavelength range correction */
  w_mult *= 1.0/mcget_ncount();  /* Flux value */
%}

TRACE
%{
  double v,tau_l,E,lambda,k,r,xf,yf,dx,dy,w_focus;

  z=0;

  x = 0.5*size*randpm1();
  y = 0.5*size*randpm1();         /* Choose initial position */

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

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

  lambda = Lmin+l_range*rand01();    /* Choose from uniform distribution */
  k = 2*PI/lambda;
  v = K2V*k;

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


/*  printf("pos0 (%g %g %g), pos1 (%g %g %g), r: %g, v (%g %g %g), v %g\n",
  x,y,z,xf,yf,dist,r,vx,vy,vz, v);
  printf("l %g, w_focus %g \n", lambda, w_focus);  */

  if (rand01() < branch2)
  {
    if (tau1>0)  /* coupled water */
      if (rand01() < branch1)
      {  /* FIRST CASE a */
        tau_l = tau;
        p = 1/(branch1*branch2);            /* Correct for switching prob. */
      }
      else
      {  /* FIRST CASE b */
        tau_l = tau1;
        p = 1/((1-branch1)*branch2);        /* Correct for switching prob. */
      }
    else /* all other moderators */
      {
        tau_l = tau;
        p = 1/branch2;            /* Correct for switching prob. */
      }
    t = -tau_l*log(1e-12+rand01());       /* Sample from long-time tail a */
    p *= n/(n-1)*(1-exp(-(n-1)*t/tau_l)); /* Correct for true pulse shape */
    p *= w_focus;                         /* Correct for target focusing */
    p *= I0*w_mult*Mezei_M_fct(lambda,T);           /* Calculate true intensity */
  }
  else
  {
    /* SECOND CASE */
    tau_l = tau2*lambda;  /* CHECK THIS */
    t = -tau_l*log(1e-12+rand01());       /* Sample from long-time tail */
    p = n2/(n2-1)*(1-exp(-(n2-1)*t/tau_l));/* Correct for true pulse shape */
    p /= (1-branch2);                     /* Correct for switching prob. */
    p *= w_focus;                         /* Correct for target focusing */
    p *= I2*w_mult/(1+exp(chi2*lambda-2.2))/lambda;
                                          /* Calculate true intensity */
  }

 if (branchframe > 0 && rand01() <= branchframe)
  {
   p /= branchframe;
  }
 else
  {
   if (rand01() < 0.5)
     t += Delta_t;
   else
     t -= Delta_t;
   p *= 2.0/(1-branchframe);
  }

 /* Go to per-second units */
 p*=nu;

%}

MCDISPLAY
%{
  
  rectangle("xy", 0, 0, 0, size, size);
  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
