/*******************************************************************************
*         McStas instrument definition URL=http://www.mcstas.org
*
* Instrument: Test_Fermi
*
* %Identification
* Written by: E. Farhi [farhi@ill.fr]
* Date: Sept 1st, 2008
* Origin: ILL
* %INSTRUMENT_SITE: Tests_optics
*
* Cross comparison of Fermi Chopper components
*
* %Description
* Cross comparison of Fermi Chopper components, using McStas and
* contributed components, as well as rotating collimator approximations. It
* shows that all implementations are equivalent. However, approximating rotating
* guide are 30% faster than McStas Fermi chopper.
*
* %Example: Fermi=1 Detector: Monitor2_xt_I=0.00051256
* %Example: Fermi=3 Detector: Monitor2_xt_I=0.00051377
* %Example: Fermi=4 Detector: Monitor2_xt_I=0.000572427
* %Example: Fermi=5 Detector: Monitor2_xt_I=0.00058003
*
* %Parameters
* Fermi: [1]      Choice of Fermi chopper component to test, with 1=FermiChopper, 3=FermiChopper_ILL, 4=rotating Guide_gravity, 5=rotating Guide_channeled
* width_FC: [m]   total slit pack width
* height_FC: [m]  height of FC slit pack
* length_FC: [m]  length of FC slit pack
* FC_Hz: [Hz]     rotation speed. Omega=2*PI*nu in rad/s, nu*60 in rpm
* d_SF: [m]       distance from Source to FC center
* d_FD: [m]       distance from FC center to Detector
* phase: [deg]    FC phase. Use -0 for automatic
* lambda: [AA]    Mean wavelength from source
* Nslit_FC: []    Number of slits in FC slit package
* time_to_arrival:  
*
* %End
*******************************************************************************/
DEFINE INSTRUMENT Test_Fermi(int Fermi=1, lambda=3.39, width_FC=0.044, height_FC=0.064,length_FC=0.012, FC_Hz=100, Nslit_FC=120,d_SF=3, d_FD=3, phase=271.92, time_to_arrival=0, time_window_width=0)

DECLARE %{
  double Time_window_width;
  #pragma acc declare create(Time_window_width)
%}

INITIALIZE
%{
  printf("\nTest_Fermi: ");
  switch (Fermi) {
  case 1:
    printf("Using FermiChopper\n"); break;
  case 2:
    printf("Using Vitess_ChopperFermi - unsupported.\n"); exit(0);
  case 3:
    printf("Using FermiChopper_ILL\n"); break;
  case 4:
    printf("Using rotating Guide_gravity\n"); break;
  case 5:
    printf("Using rotating Guide_channeled\n"); break;
  }

  double w = width_FC/Nslit_FC;
  double v = 3956/lambda;

  printf("\nTheor: Lambda=%g [Angs]\n",
    3956*w/2/PI/FC_Hz/length_FC/length_FC/2);

  printf("Theor: Time from source  t=%g [s]\n", d_SF/v);
  printf("Theor: Time to detection t=%g [s]\n", d_FD/v);
  printf("       Time period      dt=%g [s]\n", 1/FC_Hz);
  printf("       Slit pack div       %g [deg] (full width)\n", 2*atan2(w,length_FC)/PI*180);
  printf("       Time window width  =%g [s] (pulse width)\n",
    atan2(w,length_FC)/PI/FC_Hz);
  printf("       Phase           phi=%g [deg]\n", (d_SF/v)/(1/FC_Hz)*360);

  time_to_arrival  = (d_SF/v);
  time_window_width = atan2(w,length_FC)/PI/FC_Hz;
  if (phase == -0) phase=(d_SF/v)/(1/FC_Hz)*360; /* assumes time at source is centered on 0 */
  Time_window_width = time_window_width;
  #pragma acc update device(Time_window_width)
%}

TRACE

COMPONENT Origin = Progress_bar()
  AT (0,0,0) ABSOLUTE


COMPONENT Source = Source_gen(
   focus_xw = width_FC, focus_yh = height_FC, lambda0 = lambda, dlambda = 0.3,
   yheight = height_FC, xwidth = width_FC)
  AT (0, 0, 0) RELATIVE PREVIOUS
EXTEND %{
  /* 1 ms triangle time window */
  // t = randtriangle()*1e-3;  /* trianglular distribution */
  // t = randpm1()*time_window_width-time_to_arrival;          /* rectangular distribution */
  t = randpm1()*Time_window_width;
  vx=vy=0;
%}

COMPONENT Monitor1_xt = Monitor_nD(
    options = "multiple x y time limits=[2.1e-3 2.8e-3] bins=40 ", xwidth = width_FC, yheight = height_FC)
  AT (0, 0, d_SF-0.1) RELATIVE PREVIOUS

COMPONENT FC_Position = Arm( )
  AT (0, 0, 0.1) RELATIVE PREVIOUS

COMPONENT FC_GuideG = Guide_gravity(
    w1 = width_FC, h1 = height_FC, l = length_FC, R0 = 0.0, nslit=Nslit_FC, d=0, nu=FC_Hz,phase=phase)
  WHEN (Fermi == 4)
  AT (0, 0, -length_FC/2.0) RELATIVE FC_Position
EXTEND %{
  if (!SCATTERED) ABSORB;
%}

COMPONENT FC_GuideC = Guide_channeled(
    w1 = width_FC, h1 = height_FC, l = length_FC, R0 = 0.0, nslit=Nslit_FC, d=0, nu=FC_Hz,phase=phase)
  WHEN (Fermi == 5)
  AT (0, 0, -length_FC/2.0) RELATIVE FC_Position
EXTEND %{
  if (!SCATTERED) ABSORB;
%}

COMPONENT FC_McStas = FermiChopper(
    radius = 0.1, nu = FC_Hz, xwidth = width_FC, yheight = height_FC, nslit=Nslit_FC, length=length_FC,
    verbose=1, phase=phase)
  WHEN (Fermi == 1)
  AT (0, 0, 0) RELATIVE FC_Position

COMPONENT FC_ILL = FermiChopper_ILL(
    radius = 0.1, nu = FC_Hz, yheight = height_FC,
    nslit = Nslit_FC, length = length_FC, xwidth = width_FC,phase=phase)
  WHEN (Fermi ==3)
  AT (0, 0, 0) RELATIVE FC_Position

COMPONENT Fake_Origin = Arm()
  AT (0,0,0) ABSOLUTE

COMPONENT Monitor2_xt = Monitor_nD(
    options = "multiple x y time limits=[4.7e-3 5.1e-3] bins=40",
    restore_neutron=1,
    xwidth = width_FC, yheight = height_FC)
  AT (0, 0, d_FD) RELATIVE FC_Position

END
