/*******************************************************************************
*         McXtrace instrument definition URL=http://www.mcxtrace.org
*
* Instrument: NIST DBD with IBM (rename also the example and DEFINE lines below)
*
* %Identification
* Written by: Marcus H. Mendenhall (marcus.mendenhall@nist.gov)
* Date: May '17
* Origin: NIST
* Version: 0.2
* %INSTRUMENT_SITE: NIST
*
* Mockup of 219/B002 DBD
*
* %Description
* This is a preliminary setup of the DBD with the Ge111 Johansson IBM
*
* %Example: use_flat_source=0 -n1e7 Detector: lynxeye_I=3.39272e+07
*
* %Parameters
* a_distance_error: [m]          Logitudinal offset of source.
* figure_radius_multiplier: [ ]  Extra multiplicative factor to the crystal curvature.
* lattice_radius_multiplier: [ ] Extra factor to the lattice curvature. Currently IGNORED.
* beam_hor: [m]                  Beam width of source.
* beam_vert: [m]                 Unscaled Beam height of source. Will be scaled with take_off angle.
* tails_integral: [ ]            Integrated beam power in the source tails.
* tails_width: [m]               Width of the source tails.
* slit_1_vert: [m]               Vertical opening of 1st slit.
* slit_1_hor: [m]                Horizontal opening of 1st slit.
* slit_2_vert: [m]               Vertical opening of 2nd slit.
* slit_2_hor: [m]                Horizontal opening of 2nd slit.
* slit_3_vert: [m]               Vertical opening of 3rd slit.
* slit_3_hor: [m]                Horizontal opening of 3rd slit.
* ibm_offset: [m]                Offset (rotational) of optical arm.
* two_theta_si: [deg.]           Monochromator crystal scattering angle.
* emin: [keV]                    Lower energy to be simulated.
* emax: [keV]i                   Upper energy to be simulated.
* take_off: [deg]                Take off angle of source.
* use_flat_source: [ ]           Use a soimplified flat source approximation.
* use_si_crystal: [ ]            Activate the monochromator crystal.
* si_hh: [ ]                     1st Miller index (h) of monochromator crystal.
* si_kk: [ ]                     2nd index (k) of monochromator crystal.
* si_ll: [ ]                     3rd Miller index (l) of monochromator crystal.
*
* %Link
* <a href="https://www.nist.gov/programs-projects/diffraction-metrology-and-standards/divergent-beam-diffractometer-dbd-laboratory"></a>
* <a href="https://tsapps.nist.gov/publication/get_pdf.cfm?<pub_id=927309">"International Tables for Crystallography (2018). Vol. H, Chapter 3.1, pp. 224–251."</a>
* %End
*******************************************************************************/

/* Change name of instrument and input parameters with default values */

DEFINE INSTRUMENT DBD_IBM_Si_analyzer_BC(
  a_distance_error=0.0, figure_radius_multiplier=1.0, lattice_radius_multiplier=1.0,
  beam_hor=0.01, beam_vert=0.00004, tails_integral=0.05, tails_width=0.002,
  slit_1_vert=0.004, slit_1_hor=0.01, slit_2_vert=0.0002, slit_2_hor=0.02,
  slit_3_hor=0.02, slit_3_vert=0.01,
  ibm_offset=0.00, two_theta_si=94.963,
  emin=8.047, emax=8.0471, take_off=6.0, 
  int use_flat_source=0, int use_si_crystal=1,
  si_hh=3, si_kk=3, si_ll=3)

/* The DECLARE section allows us to declare variables or  small      */
/* functions in C syntax. These may be used in the whole instrument. */
DECLARE
%{
#define MCDEBUGxx
#include <math.h>
#include <stdio.h>
    const double ge_a0=5.65791; /* angstroms */
    double ge_volume;
    const double si_d_220=1.920155714; /* angstroms */
    double si_volume;
    double ge_cu_theta0, ge_cu_theta0_deg;
    double IBM_distance=0.119, focal_distance=0.218;
    double IBM_curvature_radius, alpha, theta_a, theta_b;
    double hc_eV_m=1.0/806554.429;
    double design_wavelength_angstroms;
    double take_off_beam_height_scale;
%}

USERVARS
%{
    int source_selector_random;
%}
INITIALIZE
%{
    design_wavelength_angstroms=1e10*hc_eV_m/8047.8;

    ge_volume=ge_a0*ge_a0*ge_a0;
    ge_cu_theta0=asin(sqrt(3.0)*design_wavelength_angstroms/2.0/ge_a0); /* designed to pass Cu kalpha1 on Ge111 */
    ge_cu_theta0_deg=ge_cu_theta0*180/PI; /* designed to pass Cu kalpha1 on Ge111 */
    double si_a0=si_d_220*sqrt(8.0);
    si_volume=si_a0*si_a0*si_a0;
    take_off_beam_height_scale=1.0/sin(take_off*PI/180.0);

    /*
       For a Johansson optic with focal lengths a,b, x = a/b,
       a sin(θa) = b sin(θb)
       cos(θa) = (1 + x cos(2θ)) / sqrt(1 + x^2 + 2 x cos(2θ))
       sin(θa) =       x sin(2θ) / sqrt(1 + x^2 + 2 x cos(2θ))
       sin(θb) = sin(θa) / x

       and the tilt angle of the lattice alpha=θbragg-θa
     */

    { /* make a local block for calculation scoping */
        double x= IBM_distance/focal_distance;
        double cth2=cos(2*ge_cu_theta0);
        double sth2=sin(2*ge_cu_theta0);

        double ctha=(1 + x*cth2) / sqrt(1 + x*x + 2*x*cth2);
        double stha=(    x*sth2) / sqrt(1 + x*x + 2*x*cth2);

        theta_a=asin(stha);
        theta_b=asin(stha/x);
        alpha=(ge_cu_theta0-theta_a);
        IBM_curvature_radius=IBM_distance/stha/2;
        printf("INFO (%s): Johansson optic x=%f, tha=%f, thb=%f, R=%f\n", instrument_name, x, theta_a*180/PI, theta_b*180/PI, IBM_curvature_radius);
        fflush(NULL); // get messages in order
    }
%}

/* Here comes the TRACE section, where the actual      */
/* instrument is defined as a sequence of components.  */
TRACE

/* Progress_bar is an Arm displaying simulation progress.               */
COMPONENT Origin = Progress_bar()
AT (0,0,0) ABSOLUTE
EXTEND 
%{
    source_selector_random=rand01() > 0.25;
%}

COMPONENT DBD_tube = Source_lab(
    material_datafile = "Cu.txt", height = beam_vert*take_off_beam_height_scale, width = beam_hor,
    E0 = 40, Emin = emin, Emax=emax, focus_yh = slit_1_vert, focus_xw = slit_1_hor,
    take_off = take_off, dist = IBM_distance, tube_current = 0.03, lorentzian=1,exit_window_refpt=1)
WHEN  (use_flat_source == 0 && (source_selector_random || !tails_integral))
AT (0, 0, -a_distance_error) RELATIVE Origin
ROTATED (0, 0, 0) RELATIVE Origin

/* tube tails are about an integrated intensity of 5% of main peak i.e. 2 mm wide x 0.001 intensity vs. 0.040 x 1
  the extra factor of 3 in the tube current is because we are generating randoms on a 3:1 bias */
COMPONENT DBD_tube_tails = COPY(DBD_tube) (height = tails_width*take_off_beam_height_scale, tube_current = 0.03*tails_integral*3)
WHEN  (use_flat_source == 0 && (!source_selector_random && tails_integral))
AT (0, 0, -a_distance_error) RELATIVE Origin
ROTATED (0, 0, 0) RELATIVE Origin

COMPONENT flat_source = Source_flat(
    yheight = beam_vert, xwidth = beam_hor, dist = IBM_distance,
    focus_xw = slit_1_hor, focus_yh = slit_1_vert,
    E0 = (emax+emin)/2, dE = (emax-emin)/2)   WHEN (use_flat_source != 0)
AT (0, 0, -a_distance_error) RELATIVE Origin
ROTATED (0, 0, 0) RELATIVE Origin

COMPONENT IBM_arm = Arm()
AT (0,0,IBM_distance) RELATIVE Origin
ROTATED (ibm_offset+theta_a*180/PI, 0, 0) RELATIVE Origin

COMPONENT ibm_crystal = Bragg_crystal_bent_BC(
    x_a=0,
    y_b=IBM_curvature_radius*figure_radius_multiplier,
    z_c=IBM_curvature_radius*figure_radius_multiplier,
    lattice_x_a=0,
    lattice_y_b=2*IBM_curvature_radius*lattice_radius_multiplier,
    lattice_z_c=2*IBM_curvature_radius*lattice_radius_multiplier,
    alpha=alpha,
    material = "Ge.txt", length = 0.02, width = 0.01,
    V=ge_volume,  debye_waller_B=0.47,
    h=1, k=1, l=1, crystal_type=Mx_crystal_diamond)
AT (0, 0, 0) RELATIVE IBM_arm
ROTATED (180, 0, 0) RELATIVE IBM_arm

COMPONENT sample_arm = Arm()
AT (0,0,0.0) RELATIVE IBM_arm
ROTATED (2*ge_cu_theta0_deg, 0, 0) RELATIVE Origin

COMPONENT mirror_monitor = PSD_monitor(
    nx = 100, ny = 100, xwidth = .01, yheight = 0.01,
    filename="mirror_monitor", restore_xray = 1)
AT (0,0,0.02) RELATIVE sample_arm
ROTATED (0,0,0) RELATIVE sample_arm

COMPONENT slit_2 = Slit(
    xwidth = slit_2_hor, yheight = slit_2_vert)
AT (0, 0, focal_distance) RELATIVE sample_arm
ROTATED (0, 0, 0) RELATIVE sample_arm

COMPONENT focus_monitor = PSD_monitor(
    nx = 100, ny = 100, xwidth = .01, yheight = 0.0002,
    filename="focus_monitor", restore_xray = 1)
AT (0,0,0.00001) RELATIVE slit_2
ROTATED (0,0,0) RELATIVE sample_arm

COMPONENT slit_3 = Slit(
    xwidth = slit_3_hor, yheight = slit_3_vert)
AT (0, 0, 0.1) RELATIVE slit_2
ROTATED (0, 0, 0) RELATIVE sample_arm

COMPONENT si_crystal = Bragg_crystal_BC(
    material = "Si.txt", length = 0.05, width = 0.05,
   V=si_volume,  debye_waller_B=0.4632,
   alphax=0, alphay=1, alphaz=0,
   h=si_hh, k=si_kk, l=si_ll, crystal_type=Mx_crystal_diamond) WHEN (use_si_crystal != 0)
AT (0, 0, 2*focal_distance) RELATIVE sample_arm
ROTATED (-two_theta_si/2.0, 0 ,0) RELATIVE sample_arm

COMPONENT twotheta_arm = Arm()
AT (0,0,0) RELATIVE si_crystal
ROTATED (-two_theta_si, 0, 0 ) RELATIVE sample_arm

COMPONENT spectrum_mon = E_monitor(
    nE = 700, filename = "emon", xwidth = 0.05, yheight = 0.05,
    Emin = (emin+emax)/2-(emax-emin), Emax = (emin+emax)/2+(emax-emin), restore_xray = 1)
  AT (0, 0, 0.216) RELATIVE twotheta_arm
  ROTATED (0, 0, 0) RELATIVE twotheta_arm

COMPONENT lynxeye = PSD_monitor(
    nx = 1, ny = 192, xwidth = .01, yheight = 0.0144,
    filename="lynxeye", restore_xray = 0)
AT (0,0,0.217) RELATIVE twotheta_arm
ROTATED (0,0,0) RELATIVE twotheta_arm


/* This section is executed when the simulation ends (C code). Other    */
/* optional sections are : SAVE                                         */
FINALLY
%{
%}
/* The END token marks the instrument definition end */
END


