/*******************************************************************************
* 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: MARS_E0=16.99 Detector: MARS_detector_diffraction_I=2.56e+09
*
* %Parameters
* MARS_E0: [keV]     Central energy to be emitted by the source
* MARS_dEr: [1]    Relative half width to emitted by the source, e.g. 1e-4
* MARS_alpha: [deg]  Asymmetry angle for the crystals.
* MARS_reflections: [str] Sample structure file, LAU/CIF format.
* MARS_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(MARS_E0=16.99,
  string MARS_reflec_material_M12="Pt.dat",
  string MARS_reflections="LaB6_660b_AVID2.hkl", 
  MARS_dEr=1e-4,MARS_alpha=0, int splits=10)

DECLARE
%{
	  //Slit 1
	double MARS_DistanceToPrimarySlit1 = 11.340;
	double MARS_DistanceToPrimarySlit2 = 11.440;
	double MARS_PrimarySlit1Width  = 0.02;
	double MARS_PrimarySlit1Height = 0.002;
	double MARS_PrimarySlit2Width  = 0.02;
	double MARS_PrimarySlit2Height = 0.002;

	//Mirror M1
	double MARS_DistanceSourceToM1 = 12.784;
	double MARS_M12_depth = 0.06;
	double MARS_M12_length = 2.1;
	double MARS_AngleM1 = 0.0031*RAD2DEG;

	//DCM
	double MARS_DistanceSourceToDCM = 14.395;
	double MARS_DcmGap = 0.101268;
	double MARS_AngleDCM = 10.59;
	double MARS_alpha = 0;
	double MARS_DcmHoriGap = 0.09863;
	double MARS_Ts=0.04506/(2*0.1832);
	double MARS_Tz=0.04506/(2*0.9830);
	//double DiagonaleDcmGap = sqrt(MARS_Ts*MARS_Ts+MARS_Tz*MARS_Tz);

	//BeamMonitor1
	double MARS_DistanceToPrimaryBeamMonitor = 15.678;
	double MARS_PrimaryBeamMonitorWidth = 0.05;
	double MARS_PrimaryBeamMonitorHeight = 0.05;

	//Mirror M2
	double MARS_DistanceSourceToM2 = 16.826;
	double MARS_AngleM2 = 0.0031*RAD2DEG;
	double MARS_RadiusM1 = 8248;
  double MARS_RadiusM2 = 6600;

	//Slit 2
	double MARS_DistanceToSecondarySlit1 = 18.231;
	double MARS_DistanceToSecondarySlit2 = 18.315;
	double MARS_SecondarySlit1Width  = 0.03; // 3x5
	double MARS_SecondarySlit1Height = 0.05;
	double MARS_SecondarySlit2Width  = 0.005;
	double MARS_SecondarySlit2Height = 0.03;

	//BeamMonitor2
	double MARS_DistanceToSecondaryBeamMonitor = 18.588;
	double MARS_SecondaryBeamMonitorWidth = 0.5;
	double MARS_SecondaryBeamMonitorHeight = 0.5;
	
	//Sample

	double MARS_DistanceToSample = 23.06;


	//cristal analyzor
	double MARS_DistanceCentreToCristal = 0.446;
	double MARS_AngleCa = 6.2267;
	
	//slit A1
	double MARS_distanceCristalslitA1 = 0.194;



	//slit A2
	double MARS_distanceCristalslitA2 = 0.224;


	//detector
	double MARS_distanceCristaldetector = 0.224;


	/* Declarations */
	
	double MARS_M12_width=0.05;
  double MARS_calculated_angle;
%}

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

TRACE

// electronic beam spec along storage ring 354m diameter
// BeamLineName| Long_Pos(m)| RMS_H_Size(µm)| RMS_V_Size(µm)| RMS_H_div(µrad)| RMS_V_div(µrad)
// ----|-------|----|----|-----|--
// MARS|50,5573|79,6|25,3|124,9|2,2
REMOVABLE COMPONENT MARS_origin = Progress_bar()
AT (0, 0, 0) RELATIVE ABSOLUTE

COMPONENT MARS_Source = Bending_magnet(
    focus_xw=MARS_PrimarySlit1Width,
    focus_yh=MARS_PrimarySlit1Height,
    E0=MARS_E0, dE = MARS_dEr*MARS_E0,
    Ee = 2.75, Ie = 0.5, B = 1.71, sigex=79.6e-6, sigey=25.3e-6,
    dist=MARS_DistanceToPrimarySlit1
    )
AT (0, 0, 0) RELATIVE PREVIOUS

/*Wavelength*/
COMPONENT MARS_displaySourceLength = Monitor_nD(
  xwidth=0.2, yheight=0.2, options="energy",
  bins=512, min=MARS_E0*(1-MARS_dEr), max=MARS_E0*(1+MARS_dEr)
)
AT(0,0,2) RELATIVE MARS_Source

/*Visualise*/
COMPONENT MARS_displaySource = PSD_monitor(
	filename="MARS_emon_psd1"
)
AT(0,0,10) RELATIVE MARS_Source

/* ------------------------------------- Vertical slit 1 */
COMPONENT MARS_slit1 = Slit(
    xwidth=MARS_PrimarySlit1Width, 
    yheight=MARS_PrimarySlit1Height)
AT (0, 0, MARS_DistanceToPrimarySlit1) RELATIVE MARS_Source

/* -------------------------------------- Horizontal slit 1 */
COMPONENT MARS_slit2 = Slit(
    xwidth=MARS_PrimarySlit2Width, 
    yheight=MARS_PrimarySlit2Height)
AT (0, 0, MARS_DistanceToPrimarySlit2) RELATIVE MARS_Source

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

COMPONENT MARS_M1_arm_translation = Arm()
AT(0,0,MARS_DistanceSourceToM1) RELATIVE MARS_Source


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

COMPONENT MARS_mirror_M1 = Mirror_curved(
    length = MARS_M12_length,
    width = MARS_M12_width,
    radius = MARS_RadiusM1,
    coating=MARS_reflec_material_M12)    
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (0,MARS_AngleM1, 0) RELATIVE PREVIOUS

COMPONENT MARS_M1_arm_rotation_2 = Arm()
AT(0,0,0) RELATIVE PREVIOUS
ROTATED (0,MARS_AngleM1, 0) RELATIVE PREVIOUS

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


COMPONENT MARS_beam_arm_before_crystal = Arm()
AT(0,0,MARS_DistanceSourceToDCM-MARS_DistanceSourceToM1) RELATIVE PREVIOUS

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

COMPONENT MARS_dcm0 = Arm()
AT(0,0,0) RELATIVE MARS_dcm_xtal0
ROTATED (-MARS_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 MARS_dcm_xtal1 = COPY(MARS_dcm_xtal0)(length=0.02)
AT(0,20e-3, MARS_calculated_angle ? 20e-3/tan(MARS_calculated_angle*DEG2RAD) : 0) RELATIVE MARS_dcm_xtal0
ROTATED (MARS_calculated_angle,0,0) RELATIVE MARS_dcm0

COMPONENT MARS_dcm1 =Arm()
AT(0,0,0) RELATIVE MARS_dcm_xtal1
ROTATED (MARS_calculated_angle,0,0) RELATIVE MARS_dcm_xtal1

/*---------------------------------------- BeamMonitor1 */
COMPONENT MARS_emon_dcm0 = E_monitor(
	xwidth=MARS_PrimaryBeamMonitorWidth, 
	yheight=MARS_PrimaryBeamMonitorHeight, 
	filename="MARS_emon_dcm0", 
	Emin=MARS_E0-MARS_dEr*MARS_E0, 
	Emax=MARS_E0+MARS_dEr*MARS_E0, 
	nE=101)
AT(0,0,MARS_DistanceToPrimaryBeamMonitor-MARS_DistanceSourceToDCM) RELATIVE MARS_dcm1


/*Visualise*/
COMPONENT MARS_displayMono = PSD_monitor(
	filename="MARS_emon_psd"
)
AT(0,0,0) RELATIVE PREVIOUS

/*Wavelength*/
COMPONENT MARS_displayMonoLength = E_monitor(
  xwidth=0.2, yheight=0.2,
  nE=512, filename="MARS_Output.E", Emin=MARS_E0*(1-MARS_dEr), Emax=MARS_E0*(1+MARS_dEr)
)
AT(0,0,0) RELATIVE PREVIOUS

/* -------------------------------------- Toroidal mirror M2 */   
COMPONENT MARS_M2_arm_translation = Arm()
AT(0,0,MARS_DistanceSourceToM2-MARS_DistanceToPrimaryBeamMonitor) RELATIVE PREVIOUS

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

COMPONENT MARS_mirror_M2 = Mirror_curved(
    length = MARS_M12_length,
    width = MARS_M12_width,
    radius = MARS_RadiusM2,
    coating=MARS_reflec_material_M12)    
AT (0, 0, 0) RELATIVE PREVIOUS   
ROTATED (0,MARS_AngleM2, 0) RELATIVE PREVIOUS


COMPONENT MARS_M2_arm_rotation_2 = Arm()
AT(0,0,0) RELATIVE PREVIOUS
ROTATED (0,MARS_AngleM2, 0) RELATIVE PREVIOUS

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


/* ------------------------------------- Vertical slit 2 */
COMPONENT MARS_slitSecon1 = Slit(
    xwidth=MARS_SecondarySlit1Width, 
    yheight=MARS_SecondarySlit1Height)
AT (0, 0, MARS_DistanceToSecondarySlit1-MARS_DistanceSourceToM2) RELATIVE PREVIOUS

/* -------------------------------------- Horizontal slit 2 */
COMPONENT MARS_slitSecon2 = Slit(
    xwidth=MARS_SecondarySlit2Width, 
    yheight=MARS_SecondarySlit2Height)
AT (0, 0, MARS_DistanceToSecondarySlit2-MARS_DistanceToSecondarySlit1) RELATIVE PREVIOUS

/*---------------------------------------- BeamMonitor2 */
COMPONENT MARS_emon_dcm1 = E_monitor(
	xwidth=MARS_SecondaryBeamMonitorWidth, 
	yheight=MARS_SecondaryBeamMonitorHeight, 
	filename="MARS_BeamMonitor2", 
	Emin=MARS_E0-MARS_dEr*MARS_E0, 
	Emax=MARS_E0+MARS_dEr*MARS_E0, 
	nE=101)
AT(0,0,MARS_DistanceToSecondaryBeamMonitor-MARS_DistanceToSecondarySlit2) RELATIVE PREVIOUS

/*Visualise*/
COMPONENT MARS_displaySlit2 = PSD_monitor(
	filename="MARS_emon_psd3"
)
AT(0,0,0) RELATIVE PREVIOUS


/*------------------------------------ Sample */
// The Rayleigh scattering at MARS_E0 is large, and creates massive background.
// We ignore it here.
SPLIT splits COMPONENT MARS_Sample = FluoPowder(
  material=MARS_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,
  d_phi=asin(0.02/0.670)*RAD2DEG,
  p_interact=0.99)
AT (0, 0, 0) RELATIVE PREVIOUS

/*------------------------------------- detector */
COMPONENT MARS_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 * MARS_E0 < K2E*sqrt(kx*kx+ky*ky+kz*kz)) // model detector energy discrimination
AT(0,0,0) RELATIVE MARS_Sample

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


END
