/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright 1997-2002, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Component: Collimator_linear
*
* %I
* Written by: Kristian Nielsen
* Date: August 1998
* Origin: Risoe
* Modified by: GA, June 1999, added transmission
*
* A simple analytical Soller collimator (with triangular transmission).
*
* %D
* Soller collimator with rectangular opening and specified length. The
* transmission function is an average and does not utilize knowledge of the
* actual neutron trajectory. A zero divergence disables collimation (then the
* component works as a double slit).
*
* Example: Collimator_linear(xmin=-0.1, xmax=0.1, ymin=-0.1, ymax=0.1, length=0.25, divergence=40,transmission=0.7)
*
* %P
* INPUT PARAMETERS:
*
* xmin: [m]                      Lower x bound on slits
* xmax: [m]                      Upper x bound on slits
* ymin: [m]                      Lower y bound on slits
* ymax: [m]                      Upper y bound on slits
* xwidth: [m]                    Width of slits
* yheight: [m]                   Height of slits
* length: [m]                    Distance between input and output slits
* divergence: [minutes of arc]   Divergence horizontal angle (calculated as atan(d/length), where d is the blade spacing)
* transmission: [1]              Transmission of Soller (0<=t<=1)
* divergenceV: [minutes of arc]  Divergence vertical angle
*
* %E
*******************************************************************************/


DEFINE COMPONENT Collimator_linear

SETTING PARAMETERS (xmin=-0.02, xmax=0.02, ymin=-0.05, ymax=0.05, xwidth=0, yheight=0, length=0.3, divergence=40,transmission=1, divergenceV=0)

/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */
DECLARE
%{
  double slope;
  double slopeV;
%}
INITIALIZE
%{
  slope = tan (MIN2RAD * divergence);
  slopeV = tan (MIN2RAD * divergenceV);
  if (xwidth > 0) {
    xmax = xwidth / 2;
    xmin = -xmax;
  }
  if (yheight > 0) {
    ymax = yheight / 2;
    ymin = -ymax;
  }

  if ((xmin >= xmax) || (ymin >= ymax)) {
    printf ("Collimator_linear: %s: Null slit opening area !\n"
            "ERROR              (xwidth,yheight,xmin,xmax,ymin,ymax). Exiting",
            NAME_CURRENT_COMP);
    exit (0);
  }
%}
TRACE
%{
  double phi, dt;

  PROP_Z0;
  if (x < xmin || x > xmax || y < ymin || y > ymax)
    ABSORB;
  dt = length / vz;
  PROP_DT (dt);
  if (x < xmin || x > xmax || y < ymin || y > ymax)
    ABSORB;

  if (slope > 0.0) {
    phi = fabs (vx / vz);
    if (phi > slope)
      ABSORB;
    else
      p *= transmission * (1.0 - phi / slope);
    SCATTER;
  }
  if (slopeV > 0) {
    phi = fabs (vy / vz);
    if (phi > slopeV)
      ABSORB;
    else
      p *= transmission * (1.0 - phi / slopeV);
    SCATTER;
  }
%}

MCDISPLAY
%{
  double x;
  int i;

  for (x = xmin, i = 0; i <= 3; i++, x += (xmax - xmin) / 3.0)
    multiline (5, x, (double)ymin, 0.0, x, (double)ymax, 0.0, x, (double)ymax, (double)length, x, (double)ymin, (double)length, x, (double)ymin, 0.0);
  line (xmin, ymin, 0, xmax, ymin, 0);
  line (xmin, ymax, 0, xmax, ymax, 0);
  line (xmin, ymin, length, xmax, ymin, length);
  line (xmin, ymax, length, xmax, ymax, length);
%}

END
