/*******************************************************************************
*         McStas instrument definition URL=http://www.mcstas.org
*
* Instrument: Reflectometer
*
* %Identification
* Written by: Anette Vickery, contact: anette.vickery@fys.ku.dk
* Date: November 2011
* Origin: KU
* %INSTRUMENT_SITE: Templates
*
* Horizontal reflectometer, multi-angle of incidence
*
* %Description
* A horizontal reflectometer. The instrument is built of a 2.5 m long mirror and an inclined elliptical guide. The grazing angle is defined by a set of
* slits. The sample size is 4cm x 4cm (horizontal sample).
* The role of the mirror is to provide an angle of incidence of up to 4 deg and at the same time avoid a direct line of sight to the source.
* The reflectivity is the ratio between the direct beam reflected beam intensities. Therefore two simulations are needed to get the reflectivity curve:
*
* Example: mcrun Reflectometer.instr -n1e10 directbeam=1,thetasample=0.4,Qmin=0,Qmax=0.15 -d directbeam
* Example: mcrun Reflectometer.instr -n1e10 directbeam=0,thetasample=0.4,Qmin=0,Qmax=0.15 -d reflectedbeam
*
* %Parameters
* directbeam: []        If 1, the sample is a mirror with reflectivity 1. If 0, the mirror reflects like a D2O surface with zero roughness
* Lam_min: [AA]        Minimum wavelength emitted by the cold moderator
* Lam_max: [AA]        Maximum wavelength emitted by the cold moderator
* deltatheta: [%]      The angular resolution
* theta_sample: [deg]  The grazing angle
* defineAngle: []       If 0, the angle defining slits are wide open. If 1 the angular resolution is deltatheta
* Qmin: [AA^-1]        The minimum value of the interesting Qrange
* Qmax: [AA^-1]        The maximum value of the interesting Qrange
* straight: []          If 1, the guide walls are straight
* width: [m]           The width of the guide in the case of straight guide walls
* directbeam: []       
* defineAngle: []      
* straight: []         
*******************************************************************************/
DEFINE INSTRUMENT Reflectometer( directbeam=1, Lam_min=2.0, Lam_max=10, deltatheta=2, theta_sample=1, defineAngle=1, Qmin=0, Qmax=0.5, straight=1, width=0.05 )
DECLARE
%{
double Y_sample=-0.000516, Y_mirror=-6e-3, Y_guide=-0.008385, MINDIV=-4.5,MAXDIV=-0.1;
double focus_inv=1.581542, focus_outv=1.957539, small_axis_h=0.25, T_mirror=1.136359, TT_guide=2.140996;
double focus_inh=1.582,focus_outh=1.958,small_axis_w=0.25;
double deltaLambda=1e-3;
double foot=40,fxw=0.13,fyh=0.1;
double sample_Z=0.0; // negative sample_Z: move monitor upstream
double zlos=0.59,cutoffguide=0,slitGravity=1,slitGravCor=7.2075 ;// the slit height are adjusted due to gravity. Mean displacements are as for 7.21AA neutrons
double vCor,deltaY_Grav1,deltaY_Grav2; // slitheight correction due to gravity.
double h[2], w[2];
double focus_s_w; double focus_e_w;
double focus_s_h; double focus_e_h;
double elength_h; double elength_w;
// parameters for guide calculation
double guide_start=1.27+1e-6;
double W_par=0.003, R0_par=0.99,Qcrit=0.0217,mvalue=6,alpha_par=6.07;

// parameters for slit settings
 double S1gap=2,S2gap=2;
double Y_Slit1,Y_Slit2;// relative to guideaxis

// parameters for the source
double Pulse_width=0.00286;
double frequency=14;
double guide_dist, Pulse_freq;

// Parametes for the mirror
double L_mirror=2.5;         //length
double h_mirror=0.12;        //width

double dist_moderator_detector=30, dist_moderator_mirrorbegin=2, dist_guide_S1=0.02, dist_S1_S2=1.5, dist_sample_detector=3;
double guide_length,dist_guide_S2,dist_guide_sample,dist_S2_sample;

double sampleposition=27-3.25;// distance mirror-arm--sample
// Parameters for defining source focusing:
double focus_yh; // height of focusing rectangle
char optionstring1 [128];
char optionstring2 [128];
char optionstring3 [128];
char optionstring4 [128];
char optionstring5 [128];
char optionstring51 [128];
char optionstring6 [128];
char optionstring6x [128];
double deltaTheta;
double LOSSlitheight;
%}

USERVARS %{
  double mirflag;
  double guide1flag;
  double guide2flag;
  double reflectflag;
%}

INITIALIZE
%{

if (!Lam_max){
    Lam_max=Lam_min+deltaLambda;
}

 if (straight){
   focus_inh=1000;
   focus_outh=1000;
   small_axis_w=width;
 }
printf("-------sampleposition= %g m \n", sampleposition);
guide_length=30-(2+2.5+2+3);
printf("--------------------------guide_length= %g m \n", guide_length);
/* -------------------- square guide cross section: -------------------- */
/*  naming convention: focus_inh is the horizontal focus
    and focus_inv is the vertical focus. Distance from guide to focalpoints.
    The horizontal corrosponds to the width and vertical the height. */
    printf("-------------------------- focus_outh = %g m \n",focus_outh);


    focus_s_h=-focus_inv;
    focus_e_h=guide_length+focus_outv;

    focus_s_w=-focus_inh;
    focus_e_w=guide_length+focus_outh;

    printf("-------------------------- focus_s_h = %g m \n",focus_s_h);
    printf("-------------------------- focus_e_h = %g m \n",focus_e_h);

    elength_h=focus_e_h-focus_s_h;
    elength_w=focus_e_w-focus_s_w;

    h[0]=small_axis_w*sqrt(1-(((0-focus_s_h)-elength_h/2)/(elength_h/2))*(((0-focus_s_h)-elength_h/2)/(elength_h/2)));

    h[1]=small_axis_w*sqrt(1-(((1*guide_length-focus_s_h)-elength_h/2)/(elength_h/2))*(((1*guide_length-focus_s_h)-elength_h/2)/(elength_h/2)));

    w[0]=small_axis_h*sqrt(1-(((0-focus_s_w)-elength_w/2)/(elength_w/2))*(((0-focus_s_w)-elength_w/2)/(elength_w/2)));

    w[1]=small_axis_h*sqrt(1-(((1*guide_length-focus_s_w)-elength_w/2)/(elength_w/2))*(((1*guide_length-focus_s_w)-elength_w/2)/(elength_w/2)));

    printf("-------------------------- h0, h1 = %g, %g m \n",h[0],h[1]);
    printf("-------------------------- w0, w1 = %g, %g m \n",w[0],w[1]);

dist_S2_sample=sampleposition-(guide_start+guide_length+dist_S1_S2+dist_guide_S1);
deltaTheta= deltatheta*DEG2RAD*theta_sample/100;

if (defineAngle){
   S2gap= foot*sin(DEG2RAD*theta_sample)*1e-3; // slitheight to illuminate footprint only
   S1gap = sqrt((deltaTheta*dist_S1_S2*1e3/0.68)*(deltaTheta*dist_S1_S2*1e3/0.68)-S2gap*S2gap)*1e-3;
   }
printf("--------------------------deltaTheta= %g rad \n",deltaTheta);

printf("--------------------------dist_guide_S1= %g mm \n",dist_guide_S1*1e3);
printf("--------------------------dist_S1_S2= %g mm \n",dist_S1_S2*1e3);
printf("--------------------------dist_S2_sample= %g mm \n",dist_S2_sample*1e3);

printf("--------------------------sampleposition= %g mm \n",sampleposition*1e3);
printf("--------------------------S1gap= %g mm \n",S1gap*1e3);
printf("--------------------------S2gap= %g mm \n",S2gap*1e3);


//position of slits not taking gravity into account:
Y_Slit1=-((dist_S1_S2+dist_S2_sample)*(sin(TT_guide*PI/180)-cos(TT_guide*PI/180)*tan(theta_sample*PI/180))-Y_sample);// relative to guide_axis
Y_Slit2=-((dist_S2_sample)*(sin(TT_guide*PI/180)-cos(TT_guide*PI/180)*tan(theta_sample*PI/180))-Y_sample);// relative to guide_axis
printf("--------------------------Y_Slit1= %g m \n", Y_Slit1);
printf("--------------------------Y_Slit2= %g m \n", Y_Slit2);
vCor=3.956e3/slitGravCor; // m/s velocity for slitGravCor wavelength neutrons

//ys1 = g*(zs1^2)./(2.*(v(i).*cos(theta(h))).^2) + tan(theta(h))*zs1;
deltaY_Grav1= -9.81*(dist_S1_S2+dist_S2_sample)*cos(TT_guide*PI/180)*(dist_S1_S2+dist_S2_sample)*cos(TT_guide*PI/180)/(2*vCor*vCor*cos(theta_sample*PI/180)*cos(theta_sample*PI/180) );
deltaY_Grav2= -9.81*(dist_S2_sample)*cos(TT_guide*PI/180)*(dist_S2_sample)*cos(TT_guide*PI/180)/(2*vCor*vCor*cos(theta_sample*PI/180)*cos(theta_sample*PI/180) );
if (slitGravity){
 Y_Slit1=Y_Slit1+deltaY_Grav1; // updating to take gravity into account
 Y_Slit2=Y_Slit2+deltaY_Grav2;// updating to take gravity into account
}

printf("--------------------------deltaY_Grav1 = %g m \n", deltaY_Grav1*1e6);
printf("--------------------------deltaY_Grav2 = %g m \n", deltaY_Grav2*1e6);
printf("--------------------------Y_Slit1= %g m \n", Y_Slit1);
printf("--------------------------Y_Slit2= %g m \n", Y_Slit2);

focus_yh = L_mirror*sin(T_mirror*PI/180); // height of focusing rectangle
printf("--------------------------focus_yh= %g m \n", focus_yh);


printf("--------------------------focus_inh= %g m \n", focus_inh);
printf("--------------------------focus_outh= %g m \n", focus_outh);
printf("--------------------------focus_inv= %g m \n", focus_inv);
printf("--------------------------focus_outv= %g m \n", focus_outv);
printf("--------------------------guide_length= %g m \n",guide_length);
printf("--------------------------guide_start= %g m \n",guide_start);
printf("--------------------------widthOfEllipsev= %g m \n",small_axis_h*0.5);
printf("--------------------------widthOfEllipseh= %g m \n",small_axis_w*0.5);
printf("--------------------------R0=%g m \n",R0_par);
printf("--------------------------Qc=%g m \n",Qcrit);
printf("--------------------------alpha=%g m \n",alpha_par);
printf("--------------------------m=%g m \n",mvalue);
printf("--------------------------W=%g m \n",W_par);

%}

TRACE

COMPONENT Origin = Progress_bar()
  AT (0,0,0) ABSOLUTE
EXTEND %{
guide1flag=0;
guide2flag=0;
reflectflag=0;
mirflag=0;
%}

COMPONENT cold_source = ESS_butterfly(
    Lmin = Lam_min, Lmax = Lam_max, dist = 2,
    focus_xw = fxw, focus_yh =fyh)
  AT (0, 0, 0) RELATIVE Origin


//Position of mirror
  COMPONENT mirror_pos1=Arm()
  AT (0,Y_mirror+(1.25-zlos*0.5)*tan(T_mirror*PI/180), 2+zlos*0.5) RELATIVE Origin
ROTATED (90+T_mirror,0,0) RELATIVE Origin

COMPONENT mirror1 = Mirror(
    xwidth = h_mirror, yheight = zlos, center = 1, m=6, alpha=3.5,
    transmit = 0)
  AT (0, 0, 0) RELATIVE mirror_pos1
EXTEND
   %{
   if (SCATTERED) {
      mirflag=1;
      reflectflag=1;
    }
    %}

COMPONENT mirror_pos0=Arm()
AT (0,Y_mirror, 3.25) RELATIVE Origin
ROTATED (90+T_mirror,0,0) RELATIVE Origin
COMPONENT mirror0 = Mirror(
			   xwidth = h_mirror, yheight = 2*(1.25-zlos), center = 1, m=6, alpha=3.5,
    transmit = 0)
  AT (0, 0, 0) RELATIVE mirror_pos0
EXTEND
   %{
   if (SCATTERED) {
      mirflag=1;
      reflectflag=1;
    }
    %}

  COMPONENT mirror_pos2=Arm()
  AT (0,Y_mirror-(1.25-zlos*0.5)*tan(T_mirror*PI/180), 4.5-zlos*0.5) RELATIVE Origin
ROTATED (90+T_mirror,0,0) RELATIVE Origin

COMPONENT mirror2 = Mirror(
    xwidth = h_mirror, yheight = zlos, center = 1, m=6, alpha=3.5,
    transmit = 0)
  AT (0, 0, 0) RELATIVE mirror_pos2
EXTEND
   %{
   if (SCATTERED) {
      mirflag=1;
      reflectflag=1;
    }
    %}

COMPONENT guide_TT=Arm()
AT (0,Y_guide, 3.25) RELATIVE Origin
ROTATED (TT_guide,0,0) RELATIVE Origin


COMPONENT guide1 = Elliptic_guide_gravity(
    l=guide_length*0.5-1e-6,
    linxw = focus_inh,
    loutxw = focus_outh+guide_length*0.5,
    linyh = focus_inv,
    loutyh= focus_outv+guide_length*0.5,
    minorAxisxw=small_axis_h*0.5,
    minorAxisyh=small_axis_w*0.5,
    R0=R0_par,
    Qc=Qcrit,
    alpha=alpha_par,
    m=mvalue,
    W=W_par)
AT (0, 0,guide_start) RELATIVE guide_TT
EXTEND
   %{
   if (SCATTERED) {
      guide1flag=1;
      reflectflag=1;
   }
    %}


COMPONENT guide2 = Elliptic_guide_gravity(
    l=guide_length*0.5-1e-6-cutoffguide,
    linxw = focus_inh+guide_length*0.5,
    loutxw= focus_outh+cutoffguide,
    linyh = focus_inv+guide_length*0.5,
    loutyh= focus_outv+cutoffguide,
    minorAxisxw=small_axis_h*0.5,
    minorAxisyh=small_axis_w*0.5,
    R0=R0_par,
    Qc=Qcrit,
    alpha=alpha_par,
    m=mvalue,
    W=W_par)
AT (0, 0,guide_start+guide_length*0.5) RELATIVE guide_TT
EXTEND
   %{
   if (SCATTERED) {
      reflectflag=1;
      guide2flag=1;
    }
    %}

/* Insert vertical slits:*/
COMPONENT Slit1Arm=Arm()
  AT (0, 0, guide_start+guide_length+dist_guide_S1) RELATIVE guide_TT
ROTATED (0,0,0) RELATIVE ABSOLUTE

COMPONENT Slit11Arm=Arm()
  AT (0, Y_Slit1, 0) RELATIVE Slit1Arm

COMPONENT Slit1 = Slit(
    xwidth = 0.2, yheight=S1gap)
    AT (0,0,1e-5) RELATIVE Slit11Arm

COMPONENT Slit2Arm=Arm()
  AT (0, 0, guide_start+guide_length+dist_guide_S1+dist_S1_S2) RELATIVE guide_TT
ROTATED (0,0,0) RELATIVE ABSOLUTE

COMPONENT Slit22Arm=Arm()
  AT (0, Y_Slit2, 0) RELATIVE Slit2Arm

COMPONENT Slit2 = Slit(
    xwidth = 1, yheight=S2gap)
    AT (0,0,1e-5) RELATIVE Slit22Arm

//----------------position sample :
COMPONENT Hor_sampleArm=Arm()
  AT (0, 0, sampleposition) RELATIVE guide_TT
ROTATED (-(TT_guide),0,0) RELATIVE guide_TT

COMPONENT Ver_sampleArm=Arm()
  AT  (0,Y_sample,0) RELATIVE Hor_sampleArm
ROTATED (90,0,0) RELATIVE Hor_sampleArm

COMPONENT mirrorDirect = Mirror(
    reflect = "Reflectometer_directbeam.txt", xwidth = 4e-2, yheight = 4e-2,center=1,
    transmit = 0) WHEN (directbeam)
  AT (0, sample_Z, 0) RELATIVE Ver_sampleArm
ROTATED (0,0,90) RELATIVE Ver_sampleArm
EXTEND
   %{
   if (!SCATTERED) {
	ABSORB;
    }
    %}

COMPONENT mirror = Mirror(
    reflect = "Reflectometer_reffile.txt", xwidth = 4e-2, yheight = 4e-2,center=1,
    transmit = 0) WHEN (!directbeam)
  AT (0, sample_Z, 0) RELATIVE Ver_sampleArm
ROTATED (0,0,90) RELATIVE Ver_sampleArm
EXTEND
   %{
   if (!SCATTERED) {
	ABSORB;
    }
    %}

COMPONENT TOF2QcylPSD = TOF2Q_cylPSD_monitor(
    nQ = 100, filename = "TOF2QcylPSD_1", ny = 1, radius = 3,
    yheight = 1, Qmin=Qmin, Qmax=Qmax, T_zero=0.5*2.86*1e-3, L_flight=30, restore_neutron = 1,theta=DEG2RAD*theta_sample)
  AT (0, 0, 0) RELATIVE  Hor_sampleArm
ROTATED (0,0,90) RELATIVE ABSOLUTE

FINALLY
%{
%}
END
