/*******************************************************************************
*         McStas instrument definition URL=http://www.mcstas.org
*
* Instrument: Mirror_validation
*
* %Identification
* Written by: Mads Bertelsen (mads.bertelsen@ess.eu)
* Date: October 2025
* Origin: ESS
* %INSTRUMENT_SITE: ESS
*
* Comparison of Mirror component and Union version
*
* %Description
* Comparison of Mirror component and a similar system made with Union components
* though with a key difference that a substrate is simulated which results in two
* effects: At large angles where no reflection occur, there will be some intensity
* from the scattering in the substrate. At very small angles, the reflectivity can
* exceed the R0 of the mirror coating, as the ray can be reflected by the Ni
* substrate. NCrystal is used to simulate the Ni substrate.
* The instrument includes a detector that ignores scattered rays, which should
* produce identical results for large angles, though there can still be a tiny
* discrepancy at small angles especially if R0 of the mirror coating is lowered.
*
* Example: mcrun Mirror_validation.instr angle=0.7 
*
* %Parameters
*
* angle: [deg]       Rotation of sample
* ref_component: [1] 0 to use Union components, 1 for reference Mirror component
* R0_value: [1]      Low-angle reflectivity
* Qc_value: [AA-1]   Critical scattering vector
* alpha_value: [AA]  Slope of reflectivity
* m_value: [1]       m-value of material
* W_value: [AA-1]    Width of supermirror cut-off
*
* %Example: angle=0.7 ref_component=0 Detector: detector_reflected_not_scattered_I=0.0178
* %Example: angle=0.7 ref_component=1 Detector: detector_reflected_not_scattered_I=0.0178
*
* %Link
* A reference/HTML link for more information
*
* %End
*******************************************************************************/

DEFINE INSTRUMENT Mirror_validation(
  angle = 0.4,
  int ref_component = 0,
  R0_value = 0.99, 
  m_value = 3, 
  Qc_value = 0.0219, 
  alpha_value = 6.07, 
  W_value = 0.003
)

DECLARE 
%{
%}

USERVARS
%{
int scattered;
%}

INITIALIZE 
%{
%}

TRACE 
COMPONENT init = Union_init()
AT (0,0,0) ABSOLUTE

// Union materials	
COMPONENT Ni_total = NCrystal_process(
  cfg = "Ni_sg225.ncmat;temp=10C")
AT (0,0,0) ABSOLUTE

COMPONENT Ni = Union_make_material(
  process_string = "Ni_total", my_absorption = 41.0437,
  refraction_SLD = 9.41537E-06)
AT (0,0,0) ABSOLUTE
	  
// Union Mirror surface
COMPONENT mirror = Mirror_surface(
  R0 = R0_value, Qc = Qc_value,
  alpha = alpha_value, m = m_value,
  W = W_value)
AT (0,0,0) ABSOLUTE

COMPONENT source = Source_simple(
 yheight = 1E-08, xwidth = 0.01,
 dist = 1, focus_xw = 0.01,
 focus_yh = 1E-08, lambda0 = 4,
 dlambda = 0.01, flux = 1E+16)
AT (0,0,0) ABSOLUTE

COMPONENT detector_source = PSD_monitor(
 nx = 50, ny = 60,
 filename = "PSD_source.dat", xwidth = 0.02,
 yheight = 0.002, restore_neutron = 1)
AT (0,0,0.01) RELATIVE source

COMPONENT sample_position = Arm()
AT (0,0,1) RELATIVE source

COMPONENT sample_arm = Arm()
AT (0,0,0) RELATIVE sample_position
ROTATED (-angle,0,0) RELATIVE sample_position

COMPONENT sample = Union_box(
 material_string = "Ni", priority = 4,
 xwidth = 0.1, yheight = 0.004,
 zdepth = 0.3, plus_y_surface = "mirror")
AT (0,-0.002,0) RELATIVE sample_arm

// Reference sample with same dimensions as the union box and rotated to match 
COMPONENT ref_mirror = Mirror(
 xwidth = 0.1, yheight = 0.3,
 R0 = R0_value, Qc = Qc_value,
 alpha = alpha_value, m = m_value,
 W = W_value, center = 1,
 transmit = 1)
WHEN (ref_component==1)
AT (0,0,0) RELATIVE sample_arm
ROTATED (90,0,0) RELATIVE sample_arm
EXTEND %{
scattered = 0;
%}

COMPONENT master = Union_master(enable_reflection=1)
WHEN (ref_component==0)
AT (0,0,0) ABSOLUTE
EXTEND %{
scattered = number_of_scattering_events;
%}

COMPONENT stop = Union_stop()
AT (0,0,0) ABSOLUTE

COMPONENT detector_dir = Arm()
AT (0,0,0) RELATIVE sample_position
ROTATED (-2.0*angle,0,0) RELATIVE sample_position

COMPONENT detector = PSD_monitor(
 nx = 400, ny = 300,
 filename = "PSD.dat", xwidth = 0.02,
 yheight = 0.02, restore_neutron = 1)
AT (0,0,0.16) RELATIVE sample_position

// This monitor will measure both reflected rays and scattered rays 
COMPONENT detector_reflected = PSD_monitor(
 nx = 50, ny = 60,
 filename = "PSD_reflected.dat", xwidth = 0.02,
 yheight = 0.002, restore_neutron = 1)
AT (0,0,0.2) RELATIVE detector_dir
	 
// This monitor ignores rays scattered from the substrate 
COMPONENT detector_reflected_not_scattered = PSD_monitor(
  nx = 50, ny = 60,
  filename = "PSD_reflected_not_scattered.dat", xwidth = 0.02,
  yheight = 0.002, restore_neutron = 1)
WHEN(scattered == 0)
AT (0,0,0.2) RELATIVE detector_dir

FINALLY 
%{
%}

END
