/*******************************************************************************
*         McXtrace instrument definition for SIRIUS (SOLEIL)
*
* Instrument: SOLEIL_SIRIUS
*
* %Identification
* Written by: FARHI Emmanuel
* Date: September 2026
* Origin: SOLEIL
* Version: 0.1
* %INSTRUMENT_SITE: SOLEIL
*
* SOLEIL SIRIUS beamline: Soft Interfaces and Resonant Investigation on Undulator Source
*
* %Description
* SIRIUS is designed for Soft Matter research (1.4 - 13 keV). 
* It features vertical focusing primary mirrors, a fixed-exit Si(111) 
* monochromator, and a deflection mirror to enable grazing incidence 
* measurements on liquid/solid interfaces.
*
* Position | Element
* ---------|-------------------------------------------------------------
* 0        | Source: Undulator (U26)
* 14       | M1: Primary Mirror (Pd coated, vertical focusing)
* 16       | MDC1: 1st Crystal (Flat, Si 111)
* 16.01    | MDC2: 2nd Crystal (Sagittally bent, Si 111)
* 18       | Deflection Mirror (for grazing incidence)
* 30       | Sample Stage (XAS configuration)
* 35       | Sample Stage (SEXAFS configuration)
*
* %Example: E0=8 Detector: def_loc_I=2.14522e+10
*
* %Parameters
* E0:               [keV]  Central energy (1.4 - 13 keV)
* dE:               [keV]  Energy spread
* M1_angle:         [mrad] Incidence angle of M1
* M2_angle:         [mrad] Incidence angle of M2
* def_angle:        [mrad] Deflection mirror tilt (for grazing incidence)
* sample_pos:       [m]    Distance to sample (30 for XAS, 35 for SEXAFS)
* sample:           [str]  Sample structure file
*
* %Link
* Documentation: APS_BL20.pdf
*******************************************************************************/

DEFINE INSTRUMENT SOLEIL_SIRIUS(E0=8, dE=0.1, 
  M1_angle=3, M2_angle=3, def_angle=2.0,
  sample_pos=30,
  string sample="LaB6.cif")

DECLARE
%{
  double DCM_theta;
  double d_si;
  double M1_radius;
  double M2_radius;
  double def_mirror_radius;
  double dcm_gap;
%}

INITIALIZE
%{
  // 1. Monochromator Setup (Si 111)
  double DM= 5.4909;     // Si d-spacing
  double d = DM/sqrt(3); // <111> reflection |<111>|=3
  double sin_theta = 2*PI/E2K/E0 / 2 / d;
  DCM_theta = asin(sin_theta)*RAD2DEG;
  dcm_gap  = 0.01;       // gap between the 2 monochromator crystals

  // 2. Mirror Radii (Approximation based on typical vertical focusing)
  M1_radius = 1000.0; 
  M2_radius = 1000.0;
  def_mirror_radius = 1000.0;

  MPI_MASTER(
    printf("%s: E0=%g [keV] DCM_theta=%g [deg]\n", NAME_INSTRUMENT, E0, DCM_theta);
    printf("%s: M1_angle=%g [mrad] M2_angle=%g [mrad] Deflect=%g [mrad]\n", NAME_INSTRUMENT, M1_angle, M2_angle, def_angle);
  );
  
  M1_angle *= RAD2DEG/1000;
  M2_angle *= RAD2DEG/1000;
  def_angle *= RAD2DEG/1000;
%}

TRACE

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

// -----------------------------------------------------------------------------
// SOURCE: Undulator (U26 type)
// -----------------------------------------------------------------------------
COMPONENT source = Bending_magnet(
    E0 = E0, dE = dE,
    Ee = 2.75, Ie = 0.5, B = 1.72, sigex=60e-6, sigey=25e-6)
AT (0, 0, 0) RELATIVE origin

// -----------------------------------------------------------------------------
// OPTICS 1: Primary Mirrors (M1 & M2 - Vertically Focusing)
// -----------------------------------------------------------------------------
COMPONENT M1_loc = Monitor_nD(
  xwidth=0.02, yheight=0.02, options="x y", restore_xray=1)
AT (0, 0, 14) RELATIVE origin

COMPONENT M1_rot = Arm()
AT (0, 0, 0) RELATIVE M1_loc
ROTATED (-M1_angle, 0, 0) RELATIVE M1_loc

COMPONENT M1 = Mirror_curved(
    length=1.3, width=0.1,
    coating="Pd.txt", radius=M1_radius)
AT (0, 0, 0) RELATIVE M1_rot
ROTATED (0, 0, 90) RELATIVE M1_rot
EXTEND %{ 
  if (!SCATTERED) ABSORB; 
%}

COMPONENT M1_out = Arm()
AT (0, 0, 0) RELATIVE M1_rot
ROTATED (-M1_angle, 0, 0) RELATIVE M1_loc

// -----------------------------------------------------------------------------
// OPTICS 2: Fixed-exit Double Crystal Monochromator (DCM)
// -----------------------------------------------------------------------------

COMPONENT DCM_location = COPY(M1_loc)
AT (0, 0, 2) RELATIVE M1_out // 14 + 2 = 16m

// the M1 mirror should reduce the divergence so that the beam is parallel
// when hitting the monochromators, to reduce the energy spread
COMPONENT bragg_crystal = Bragg_crystal(
    length=0.2, 
    width=0.1,
    material = "Si.txt",
    h = 1, k = 1, l = 1,
    crystal_type = 2
)
AT (0, 0, 0)               RELATIVE DCM_location
ROTATED (-DCM_theta, 0, 0) RELATIVE DCM_location
EXTEND
%{ 
	if (!SCATTERED) ABSORB;
%}

COMPONENT arm_crystal1 = Arm()
AT (0, 0, 0)               RELATIVE PREVIOUS
ROTATED (-DCM_theta, 0, 0) RELATIVE PREVIOUS

/* -------------------------------------------------- CC crystal 2 */
COMPONENT bragg_crystal_two = COPY(bragg_crystal)(
    length=0.2) 
AT (0, dcm_gap, DCM_theta ? dcm_gap/tan(DCM_theta*DEG2RAD) : 0) RELATIVE bragg_crystal
ROTATED (DCM_theta, 0, 0) RELATIVE arm_crystal1
EXTEND
%{ 
	if (!SCATTERED) ABSORB;
%}

COMPONENT arm_crystal2 = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (DCM_theta, 0, 0) RELATIVE PREVIOUS

/* -------------------------------------------------- Horizontal slit 5 */
// the beam is positioned at Y=+dy*sin(2*DCM_theta*DEG2RAD)/sin(DCM_theta*DEG2RAD) 
// with dy=0.01 (CC gap) wrt the CC entry
COMPONENT DCM_out = COPY(DCM_location)(yheight=0.02)
AT (0, 0, 0.2) RELATIVE arm_crystal2
ROTATED (0,0,0) RELATIVE arm_crystal2          // TODO: small rotation to move beam at 0 divergence

COMPONENT DCM_out_div = COPY(DCM_location)(options="dx limits=[-0.5 0.5], dy limits=[-0.5 0.5]", yheight=0.2)
AT (0, 0,0) RELATIVE DCM_out

COMPONENT DCM_out_e = Monitor_nD(
   options="energy", xwidth=0.1, yheight=0.2, bins=512, min=E0-dE, max=E0+dE)
AT (0, 0,0) RELATIVE DCM_out

// -----------------------------------------------------------------------------
// OPTICS 3: Deflection Mirror (for Grazing Incidence)
// -----------------------------------------------------------------------------
COMPONENT def_loc = COPY(M1_loc)
AT (0, 0, 2) RELATIVE DCM_out // 16 + 2 = 18m

COMPONENT def_rot = Arm()
AT (0, 0, 0) RELATIVE def_loc
ROTATED (-def_angle, 0, 0) RELATIVE def_loc

COMPONENT def_mirror = Mirror(
    xwidth=0.1, yheight=0.05)
AT (0, 0, 0) RELATIVE def_rot
EXTEND %{ 
  if (!SCATTERED) ABSORB; 
%}

COMPONENT def_out = Arm()
AT (0, 0, 0) RELATIVE def_rot
ROTATED (-def_angle, 0, 0) RELATIVE def_loc

// -----------------------------------------------------------------------------
// SAMPLE STAGE
// -----------------------------------------------------------------------------
COMPONENT sample_stage = COPY(M1_loc)
AT (0, 0, sample_pos - 18) RELATIVE def_out 
EXTEND
%{ 
	if (!SCATTERED) ABSORB;
%}

SPLIT COMPONENT fluo = FluoPowder(
    material=sample,
    xwidth=0.002, yheight=0.002, zdepth=1e-5,
    p_interact=1, target_z=1)
AT (0, 0, 0) RELATIVE sample_stage

// -----------------------------------------------------------------------------
// DETECTORS
// -----------------------------------------------------------------------------
// 2D Detector (CCD/Pilatus style)
COMPONENT det_2d = Monitor_nD(
    radius=0.5, xwidth=0.1, yheight=0.1,
    options="theta bins=256, phi bins=256")
AT (0, 0, 1.0) RELATIVE sample_stage

// Fluorescence Monitor
COMPONENT det_fluo = Monitor_nD(
    radius=0.1, options="energy", bins=128)
AT (0, 0, 1.0) RELATIVE sample_stage

END

