/*******************************************************************************
* Instrument: SOLEIL_MARS
*
* %Identification
* Written by: IGUILIZ Salah-Eddine, MENUT Denis and FARHI Emmanuel.
* Date: July 2022
* Origin: SOLEIL
* Version: 1.0
* %INSTRUMENT_SITE: SOLEIL
*
* The MARS beam-line at Synchrotron SOLEIL.
*
* %Description
* MARS beamline is aiming to extend the research capabilities on radioactive
* matter towards the use of synchrotron radiation in multidisciplinary fields
* biology, chemistry, physics) with respect to national and European safety law*.
*
* The design of MARS beamline (infrastructure and optics) is also optimized to
* alternatively run two experimental stations in orlder to perform
* characterizations with transmission and high resolution X-ray powder-diffraction
* (XRD), Wide Angle X-ray Scattering (WAXS), Small Angle X-ray scattering (SAXS),
* standard and high resolution X-ray absorption spectroscopy (XANES, EXAFS and
* HERFD-XANES) and microbeam techniques (microXRF, XAS, XRD).
*
* This model implements the XRD station for powders.
*
* %Example: E0=16.99 Detector: detector_diffraction_I=2.56e+09
*
* %Parameters
* E0: [keV]     Central energy to be emitted by the source
* dEr: [1]    Relative half width to emitted by the source, e.g. 1e-4
* alpha: [deg]  Asymmetry angle for the crystals.
* reflections: [str] Sample structure file, LAU/CIF format.
* reflec_material_M12: [str] reflecting coating on curved mirrors, e.g. Pt
*
* %Link
* https://www.synchrotron-soleil.fr/en/beamlines/mars
* 
* %End
*******************************************************************************/
DEFINE INSTRUMENT SOLEIL_MARS(E0=16.99,
  string reflec_material_M12="Pt.dat",
  string reflections="LaB6_660b_AVID2.hkl", 
  dEr=1e-4,alpha=0)

DECLARE
%{
	  //Slit 1
	double DistanceToPrimarySlit1 = 11.340;
	double DistanceToPrimarySlit2 = 11.440;
	double PrimarySlit1Width  = 0.02;
	double PrimarySlit1Height = 0.002;
	double PrimarySlit2Width  = 0.02;
	double PrimarySlit2Height = 0.002;

	//Mirror M1
	double DistanceSourceToM1 = 12.784;
	double M12_depth = 0.06;
	double M12_length = 2.1;
	double AngleM1 = 0.0031*RAD2DEG;

	//DCM
	double DistanceSourceToDCM = 14.395;
	double DcmGap = 0.101268;
	double AngleDCM = 10.59;
	double alpha = 0;
	double DcmHoriGap = 0.09863;
	double Ts=0.04506/(2*0.1832);
	double Tz=0.04506/(2*0.9830);
	//double DiagonaleDcmGap = sqrt(Ts*Ts+Tz*Tz);

	//BeamMonitor1
	double DistanceToPrimaryBeamMonitor = 15.678;
	double PrimaryBeamMonitorWidth = 0.05;
	double PrimaryBeamMonitorHeight = 0.05;

	//Mirror M2
	double DistanceSourceToM2 = 16.826;
	double AngleM2 = 0.0031*RAD2DEG;
	double RadiusM1 = 8248;
  double RadiusM2 = 6600;

	//Slit 2
	double DistanceToSecondarySlit1 = 18.231;
	double DistanceToSecondarySlit2 = 18.315;
	double SecondarySlit1Width  = 0.03; // 3x5
	double SecondarySlit1Height = 0.05;
	double SecondarySlit2Width  = 0.005;
	double SecondarySlit2Height = 0.03;

	//BeamMonitor2
	double DistanceToSecondaryBeamMonitor = 18.588;
	double SecondaryBeamMonitorWidth = 0.5;
	double SecondaryBeamMonitorHeight = 0.5;
	
	//Sample

	double DistanceToSample = 23.06;


	//cristal analyzor
	double DistanceCentreToCristal = 0.446;
	double AngleCa = 6.2267;
	
	//slit A1
	double distanceCristalslitA1 = 0.194;



	//slit A2
	double distanceCristalslitA2 = 0.224;


	//detector
	double distanceCristaldetector = 0.224;


	/* Declarations */
	
	double M12_width=0.05;
  double calculated_angle;
%}

INITIALIZE
%{
    calculated_angle=RAD2DEG*asin(12398.42*sqrt(8)/(2*5.4309*(E0*1e3)));
    fprintf(stdout,"%s: Energy %g [keV] Mono Angle %g [deg]\n", NAME_INSTRUMENT, E0, calculated_angle);
    
%}

TRACE

COMPONENT origin = Progress_bar()
AT (0, 0, 0) RELATIVE ABSOLUTE

COMPONENT Source = Bending_magnet(
    focus_xw=PrimarySlit1Width,
    focus_yh=PrimarySlit1Height,
    E0=E0, dE = dEr*E0,
    Ee = 2.75, Ie = 0.5, B = 1.71, sigex=79.6e-6, sigey=25.3e-6,
    dist=DistanceToPrimarySlit1
    )
AT (0, 0, 0) RELATIVE origin

/*Wavelength*/
COMPONENT displaySourceLength = Monitor_nD(
  xwidth=0.2, yheight=0.2, options="energy",
  bins=512, min=E0*(1-dEr), max=E0*(1+dEr)
)
AT(0,0,2) RELATIVE Source

/*Visualise*/
COMPONENT displaySource = PSD_monitor(
	filename="emon_psd1"
)
AT(0,0,10) RELATIVE Source

/* ------------------------------------- Vertical slit 1 */
COMPONENT slit1 = Slit(
    xwidth=PrimarySlit1Width, 
    yheight=PrimarySlit1Height)
AT (0, 0, DistanceToPrimarySlit1) RELATIVE Source

/* -------------------------------------- Horizontal slit 1 */
COMPONENT slit2 = Slit(
    xwidth=PrimarySlit2Width, 
    yheight=PrimarySlit2Height)
AT (0, 0, DistanceToPrimarySlit2) RELATIVE Source

/* -------------------------------------- Mirror M1 */  

COMPONENT M1_arm_translation = Arm()
AT(0,0,DistanceSourceToM1) RELATIVE Source


COMPONENT M1_arm_rotation_1 = Arm()
AT(0,0,0) RELATIVE PREVIOUS
ROTATED (0,0, -90) RELATIVE PREVIOUS

COMPONENT mirror_M1 = Mirror_curved(
    length = M12_length,
    width = M12_width,
    radius = RadiusM1,
    coating=reflec_material_M12)    
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (0,AngleM1, 0) RELATIVE PREVIOUS

COMPONENT M1_arm_rotation_2 = Arm()
AT(0,0,0) RELATIVE PREVIOUS
ROTATED (0,AngleM1, 0) RELATIVE PREVIOUS

COMPONENT M1_arm_rotation_2_undo = Arm()
AT(0,0,0) RELATIVE PREVIOUS
ROTATED (0,0, 90) RELATIVE PREVIOUS


COMPONENT beam_arm_before_crystal = Arm()
AT(0,0,DistanceSourceToDCM-DistanceSourceToM1) RELATIVE PREVIOUS

/*----------------------------------------Monochromator (fixed offset)*/
COMPONENT dcm_xtal0 = Bragg_crystal(
    length=0.04, width=0.05,
    alpha=alpha, h=2, k=2, l=0, material="Si.txt",crystal_type=2)    
AT(0,0,0) RELATIVE PREVIOUS
ROTATED (-calculated_angle,0,0) RELATIVE PREVIOUS

COMPONENT dcm0 = Arm()
AT(0,0,0) RELATIVE dcm_xtal0
ROTATED (-calculated_angle,0,0) RELATIVE PREVIOUS

//this dcm is a fixed offset dcm, the second crystal translates itself
//The  double  crystal  monochromator  (DCM),  manufactured  by  FMB  Oxford,  is  equipped  with  14 independent motorized stages in order to optimize its alignment and then to assure a fixed exit beam over the entire energy range with a constant upward offset of 20 mm with respect to the primary beam. https://iopscience.iop.org/article/10.1088/1742-6596/190/1/012042/pdf
COMPONENT dcm_xtal1 = COPY(dcm_xtal0)(length=0.02)
AT(0,20e-3, calculated_angle ? 20e-3/tan(calculated_angle*DEG2RAD) : 0) RELATIVE dcm_xtal0
ROTATED (calculated_angle,0,0) RELATIVE dcm0

COMPONENT dcm1 =Arm()
AT(0,0,0) RELATIVE dcm_xtal1
ROTATED (calculated_angle,0,0) RELATIVE dcm_xtal1

/*---------------------------------------- BeamMonitor1 */
COMPONENT emon_dcm0 = E_monitor(
	xwidth=PrimaryBeamMonitorWidth, 
	yheight=PrimaryBeamMonitorHeight, 
	filename="emon_dcm0", 
	Emin=E0-dEr*E0, 
	Emax=E0+dEr*E0, 
	nE=101)
AT(0,0,DistanceToPrimaryBeamMonitor-DistanceSourceToDCM) RELATIVE dcm1


/*Visualise*/
COMPONENT displayMono = PSD_monitor(
	filename="emon_psd"
)
AT(0,0,0) RELATIVE PREVIOUS

/*Wavelength*/
COMPONENT displayMonoLength = E_monitor(
  xwidth=0.2, yheight=0.2,
  nE=512, filename="Output.E", Emin=E0*(1-dEr), Emax=E0*(1+dEr)
)
AT(0,0,0) RELATIVE PREVIOUS

/* -------------------------------------- Toroidal mirror M2 */   
COMPONENT M2_arm_translation = Arm()
AT(0,0,DistanceSourceToM2-DistanceToPrimaryBeamMonitor) RELATIVE PREVIOUS

COMPONENT M2_arm_rotation_1 = Arm()
AT(0,0,0) RELATIVE PREVIOUS
ROTATED (0,0, 90) RELATIVE PREVIOUS

COMPONENT mirror_M2 = Mirror_curved(
    length = M12_length,
    width = M12_width,
    radius = RadiusM2,
    coating=reflec_material_M12)    
AT (0, 0, 0) RELATIVE PREVIOUS   
ROTATED (0,AngleM2, 0) RELATIVE PREVIOUS


COMPONENT M2_arm_rotation_2 = Arm()
AT(0,0,0) RELATIVE PREVIOUS
ROTATED (0,AngleM2, 0) RELATIVE PREVIOUS

COMPONENT M2_arm_rotation_2_undo = Arm()
AT(0,0,0) RELATIVE PREVIOUS
ROTATED (0,0,-90) RELATIVE PREVIOUS


/* ------------------------------------- Vertical slit 2 */
COMPONENT slitSecon1 = Slit(
    xwidth=SecondarySlit1Width, 
    yheight=SecondarySlit1Height)
AT (0, 0, DistanceToSecondarySlit1-DistanceSourceToM2) RELATIVE PREVIOUS

/* -------------------------------------- Horizontal slit 2 */
COMPONENT slitSecon2 = Slit(
    xwidth=SecondarySlit2Width, 
    yheight=SecondarySlit2Height)
AT (0, 0, DistanceToSecondarySlit2-DistanceToSecondarySlit1) RELATIVE PREVIOUS

/*---------------------------------------- BeamMonitor2 */
COMPONENT emon_dcm1 = E_monitor(
	xwidth=SecondaryBeamMonitorWidth, 
	yheight=SecondaryBeamMonitorHeight, 
	filename="BeamMonitor2", 
	Emin=E0-dEr*E0, 
	Emax=E0+dEr*E0, 
	nE=101)
AT(0,0,DistanceToSecondaryBeamMonitor-DistanceToSecondarySlit2) RELATIVE PREVIOUS

/*Visualise*/
COMPONENT displaySlit2 = PSD_monitor(
	filename="emon_psd3"
)
AT(0,0,0) RELATIVE PREVIOUS


/*------------------------------------ Sample */
SPLIT 10 COMPONENT Sample = PowderN(
  reflections = reflections,
  xwidth = 0.005,
  yheight = 0.05,
  zdepth = 0.0001,
  d_phi=asin(0.02/0.670)*RAD2DEG,
  p_interact=0.5
)
AT (0, 0, DistanceToSample-DistanceToSecondaryBeamMonitor) RELATIVE PREVIOUS
GROUP samples

// The Rayleigh scattering at E0 is large, and creates massive background.
// We ignore it here.
COMPONENT SampleF = Fluorescence(
  material=reflections,
  xwidth = 0.005,
  yheight = 0.05,
  zdepth = 0.0001,
  focus_ah=asin(0.02/0.670)*RAD2DEG,
  focus_aw=180, target_z=1, flag_rayleigh=0,
  p_interact=0.99)
AT (0, 0, 0) RELATIVE PREVIOUS
GROUP samples



/*------------------------------------- detector */
COMPONENT detector_diffraction = Monitor_nD(
  bins=90000, options="abs theta",
  min=5,max=90, radius= 0.670, yheight = 0.02, restore_xray=1
)
WHEN (0.75 * E0 < K2E*sqrt(kx*kx+ky*ky+kz*kz)) // model detector energy discrimination
AT(0,0,0) RELATIVE Sample

COMPONENT detector_fluo = Monitor_nD(
  bins=1024, options="energy", min=0, max=E0*1.2,
  radius= 0.670, yheight = 0.02
)
WHEN (K2E*sqrt(kx*kx+ky*ky+kz*kz) < 0.95*E0)
AT(0,0,0) RELATIVE Sample


END
