/*******************************************************************************
* Instrument: SOLEIL_PX2a
*
* %Identification
* Written by: M. Savko and E. Farhi
* Date: 2022-03-23
* Origin: Synchrotron SOLEIL
* %INSTRUMENT_SITE: SOLEIL
*
* The PROXIMA-2a MX beam-line at Synchrotron SOLEIL.
*
* %Description
* PROXIMA 2A (PX2-A) is a microfocus beamline dedicated to biological
* crystallography and innovative micro-beam methodologies. Opened to the
* scientific community since 2013, the topics treated on the beamline go beyond
* standard protein crystallography and include drug discovery, membrane proteins,
* virus crystallography, small molecule crystallography, powder diffraction and
* even crystalluria. The beamline is highly automated and designed to help
* scientists tackle the most challenging structural targets and biological
* systems. The X-ray energy is rapidly tunable over a wide range (6-18 keV) making
* the most commonly used absorption edges accessible for anomalous diffraction
* experiments. The end station is equipped with a high capacity sample-changing
* system (148 SPINE pins), a high performance micro-diffractometer with a
* mini-kappa (MD2), an X-ray fluorescence detector (KETEK), and a fast, low-noise,
* photon-counting, area detector - the EIGER X 9M (238 fps in 9M mode, 750 fps in
* 4M mode).
*
* This is a simplified model with an Undulator, mirrors, a double crystal 
* monochromator, a sample stage and a detector.
*
* %Example: PX2a_E0=12.65 sample="Mo.lau" PX2a_SPLITs=1500 PX2a_sample_monitor_I=1.53453e+20
*
* %Parameters
* PX2a_E0:    [keV] Energy selected at the Undulator.
* PX2a_hfm_radius: [m] horizontally focusing mirror radius
* PX2a_vfm_radius: [m] vertically focusing mirror radius
* PX2a_mirror_grazing_angle: [deg] Tilt angle of the mirrors.
* PX2a_sample:[str] Sample structure file, LAU/CIF format.
* PX2a_rotX:  [deg] Sample rotation around X
* PX2a_rotY:  [deg] Sample rotation around Y
* PX2a_rotZ:  [deg] Sample rotation around Z
* splits: [1] Number of SPLIT repetitions at the sample
* 
* %Link
* https://www.synchrotron-soleil.fr/en/beamlines/proxima-2a
*
* %End
*******************************************************************************/

DEFINE INSTRUMENT SOLEIL_PX2a(
  PX2a_E0=12.65, PX2a_hfm_radius=495, PX2a_vfm_radius=859,
  PX2a_mirror_grazing_angle=4e-3,
  string PX2a_sample="adrenaline.lau",
  PX2a_rotX=0, PX2a_rotY=0, PX2a_rotZ=0, int splits=10)
DEPENDENCY " -DMCSX_REFL_SLIST_SIZE=1024 "
DECLARE
%{
    double PX2a_calculated_angle;
%}

USERVARS %{
    int    PX2a_flag_hfm;
    int    PX2a_flag_vfm;
%}

INITIALIZE
%{
  {
    double arg=  12398.42*sqrt(3)/(2*5.4309*PX2a_E0*1e3);
    if (fabs(arg) > 1)
      exit(fprintf(stderr, "ERROR: Monochromator can not reach this energy (arg=%g > 1)\n",
        arg));
    PX2a_calculated_angle = RAD2DEG*asin(arg);
    /* Ensure that we are running with at least 1e7 neutrons/core if not 'displaying' */
    #ifndef USE_MPI
    #define mpi_node_count 1
    #endif
    if (!mcdotrace) {
      if (mcget_ncount()<=1e7) {
        MPI_MASTER(printf("WARNING: This instrument needs at least %llu statistics to converge. Currently ncount=%llu to ",mpi_node_count*1e7, mcget_ncount()));
      }
    }
  }
%}

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)
// -----|--------|-----|---|----|--
// PX2sp|222,8306|219,1|9,8|31,6|3,7
REMOVABLE COMPONENT PX2a_Origin = Progress_bar()
AT (0,0,0) ABSOLUTE

// Undulator U24
COMPONENT PX2a_undulator = Undulator(
    E0=PX2a_E0, 
    dE=.1, 
    Ee=2.75, 
    dEe=0.001, 
    Ie=0.5, 
    K=1.788, 
    Nper=80, 
    lu=2.4e-2, 
    sigey=9.8e-6, 
    sigex=219.1e-6, 
    sigepx=31.6e-6, 
    sigepy=3.7e-6, 
    dist=29.5, 
    E1st=12.400)
AT (0, 0, 0) RELATIVE PREVIOUS



// Channel_cut Si(111) ---------------------------------------------------------
// gap 6 mm
COMPONENT PX2a_bragg_crystal_location = Arm()
AT (0,0,29.5) RELATIVE PREVIOUS

COMPONENT PX2a_bragg_crystal = Bragg_crystal(
    crystal_type=2)
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (-PX2a_calculated_angle, 0, 0) RELATIVE PREVIOUS

COMPONENT PX2a_arm = Arm()
AT (0, 0, 0) RELATIVE PREVIOUS
ROTATED (-PX2a_calculated_angle, 0, 0) RELATIVE PREVIOUS

COMPONENT PX2a_bragg_crystal_two = Bragg_crystal(
    crystal_type=2)
AT (0, 0.006, PX2a_calculated_angle ? 0.006/tan(PX2a_calculated_angle*DEG2RAD) : 0) RELATIVE PX2a_bragg_crystal
ROTATED (PX2a_calculated_angle, 0, 0) RELATIVE PREVIOUS

COMPONENT PX2a_arm_two = Arm()
AT (0, 0, 0) RELATIVE PX2a_bragg_crystal_two
ROTATED (PX2a_calculated_angle, 0, 0) RELATIVE PX2a_bragg_crystal_two

COMPONENT PX2a_bragg_crystal_out = E_monitor(Emin=PX2a_E0-.1, Emax=PX2a_E0+.1, nE=512,
  xwidth=0.1, yheight=0.1)
AT(0,0,0.2) RELATIVE PREVIOUS


// horizontal pre-focusing curved mirror (XZ -> YZ plane) ----------------------
COMPONENT PX2a_hpm_location = Arm()
AT (0,0,32.1-29.5-0.05) RELATIVE PX2a_arm_two

COMPONENT PX2a_hpm_in_yz_plane = Arm()
AT (0,0,0) RELATIVE PX2a_hpm_location
ROTATED (0,0,90) RELATIVE PX2a_hpm_location

COMPONENT PX2a_hpm = Mirror_toroid(
  coating   = "Ir.dat", //This needs to be Rh.dat, will need to generate the file with xraydb
  zdepth   = 150e-3,
  xwidth   = 15e-3,
  radius   = 495,
  radius_o = 1000)
AT (0,0,0) RELATIVE PX2a_hpm_in_yz_plane
ROTATED (PX2a_mirror_grazing_angle, 0, 0) RELATIVE PX2a_hpm_in_yz_plane

COMPONENT PX2a_hpm_takeoff = Arm()
AT (0,0,0) RELATIVE PX2a_hpm_location
ROTATED (0, 2*PX2a_mirror_grazing_angle, 0) RELATIVE PX2a_hpm_location

// KB pair ---------------------------------------------------------------------
// could use Mirror_elliptic
// incidence angle 4 mrad

// KB 1st mirror (XZ plane) at 1.6m from sample
// must be shifted by -2 mm  on Y else beam flies underneath the mirror.
COMPONENT PX2a_vfm_location = Monitor_nD(xwidth=0.01, yheight=0.01, options="x y", bins=100)
AT (0,0,33.9-32.1) RELATIVE PX2a_hpm_takeoff

COMPONENT PX2a_vfm_in_xz_plane = Arm()
AT (0,0,0) RELATIVE PX2a_vfm_location
ROTATED(0,0,-90) RELATIVE PX2a_vfm_location // YZ -> XZ

COMPONENT PX2a_vfm = Mirror_curved(
  coating="Rh.txt",
  length=450e-3,
  width=0.1,
  radius=PX2a_vfm_radius)
AT (0,0,0) RELATIVE PX2a_vfm_location
ROTATED(0,-PX2a_mirror_grazing_angle,0) RELATIVE PX2a_vfm_in_xz_plane
EXTEND %{
  PX2a_flag_vfm=SCATTERED;
%}

COMPONENT PX2a_vfm_takeoff = COPY(PX2a_vfm_location)
AT (0,0,0) RELATIVE PX2a_vfm_in_xz_plane
ROTATED (-2*PX2a_mirror_grazing_angle, 0, 0) RELATIVE PX2a_vfm_location

// KB 2nd mirror (YZ) at 1m from sample, shift height=4.8 mm 
COMPONENT PX2a_hfm_location = COPY(PX2a_vfm_location)
AT (0,0,34.5-33.9) RELATIVE PX2a_vfm_takeoff

// 859 m tangential; sagital > 1 km, in YZ plane
COMPONENT PX2a_hfm = Mirror_curved(
  coating="Rh.txt",
  length=450e-3,
  width=0.1,
  radius=PX2a_hfm_radius)
AT (0,0,0) RELATIVE PX2a_hfm_location
ROTATED (0,-PX2a_mirror_grazing_angle,0) RELATIVE PX2a_hfm_location
EXTEND %{
  PX2a_flag_hfm=SCATTERED;
%}

COMPONENT PX2a_hfm_takeoff = COPY(PX2a_vfm_location)
AT (0,0,0) RELATIVE PX2a_hfm_location
ROTATED (0,-2*PX2a_mirror_grazing_angle,0) RELATIVE PX2a_hfm_location

// Sample ----------------------------------------------------------------------
// we centre the beam after the KB.
COMPONENT PX2a_sample_stage = Arm()
AT (1e-3,-1.1e-3,1) RELATIVE PX2a_hfm_takeoff
EXTEND %{
  if (!PX2a_flag_hfm || !PX2a_flag_vfm) ABSORB;
%}

COMPONENT PX2a_sample_monitor = Monitor_nD(
  xwidth = 0.01, yheight = 0.01,
  options = "x y", bins=100)
  AT (0, 0, 0) RELATIVE PX2a_sample_stage

SPLIT splits COMPONENT PX2a_sample = Single_crystal(reflections=PX2a_sample, material_datafile="NULL",
  radius = .5e-4, yheight = 5e-3, p_transmit = 0, mosaic=0.1, order=1)
  AT (0, 0, 0) RELATIVE PX2a_sample_stage
  ROTATED (PX2a_rotX,PX2a_rotY,PX2a_rotZ) RELATIVE PX2a_sample_stage
EXTEND %{
  if (!SCATTERED) ABSORB;
%}

COMPONENT PX2a_psd4pi = PSD_monitor_4PI(
    nx = 180, ny = 180, filename = "psd4pi", radius = 0.1, restore_xray = 1)
AT (0, 0, 0) RELATIVE PX2a_sample

// Detector
COMPONENT PX2a_Eiger9M = PSD_monitor(
  nx=3108, ny=3262,
  xwidth = 233.1e-3,
  yheight= 244.7e-3,
  filename="PX2a_Eiger9M.dat"
)
AT (0,0,0.12) RELATIVE PX2a_sample_stage

END
