/*******************************************************************************
*
* McXtrace, x-ray tracing package
*         Copyright, All rights reserved
*         DTU Physics, Kgs. Lyngby, Denmark
*         Synchrotron SOLEIL, Saint-Aubin, France
*
* Component: Divergence_monitor
*
* %Identification
* Written by: Erik B Knudsen
* Based on neutron component by Kim Lefmann
* Date: Jun. '16
* Version: $Revision$
* Origin: DTU Physics
*
* Horizontal+vertical divergence monitor.
*
* %Description
* A 2D divergence sensitive monitor. The counts are distributed in
* (n times m) pixels.
*
* Example: Divergence_monitor(nh=20, nv=20, filename="Output.pos",
*           xwidth=0.1, yheight=0.1,
*           maxdiv_h=2, maxdiv_v=2)
*
* %Parameters
* INPUT PARAMETERS:
*
* xwidth: [m]           Width of detector. 
* yheight: [m]          Height of detector.
* nv: [1]               Number of pixel columns 
* nh: [1]               Number of pixel rows 
* nx: [1]               Vector definition of "forward" direction wrt. divergence, to be used e.g. when the monitor is rotated into the horizontal plane 
* ny: [1]               Vector definition of "forward" direction wrt. divergence, to be used e.g. when the monitor is rotated into the horizontal plane 
* nz: [1]               Vector definition of "forward" direction wrt. divergence, to be used e.g. when the monitor is rotated into the horizontal plane 
* maxdiv_v: [degrees]   Maximal vertical divergence detected 
* maxdiv_h: [degrees]   Maximal horizontal divergence detected 
* filename: [str]          Name of file in which to store the detector image text
* restore_xray: [1]     If set, the monitor does not influence the photon state 
* rad:  [1]             If set - divergence will be measured in radians.
* nowritefile: [1]      If set, monitor will skip writing to disk
*
* CALCULATED PARAMETERS:
*
* Div_N:    Array of photon ray counts
* Div_p:    Array of photon weight counts
* Div_p2:   Array of second moments
*
* %End
*******************************************************************************/
DEFINE COMPONENT Divergence_monitor

SETTING PARAMETERS (int nh=20, int nv=20, int rad=0, string filename=0, 
    xwidth=0.1, yheight=0.1, maxdiv_h=1, maxdiv_v=1, restore_xray=0, nx=0, ny=0, nz=1, int nowritefile=0)

    /* Xray  parameters: (x,y,z,kx,ky,kz,phi,t,Ex,Ey,Ez,p) */ 
DECLARE
  %{
  DArray2d Div_N;
  DArray2d Div_p;
  DArray2d Div_p2;
  double xmin;
  double xmax;
  double ymin;
  double ymax;
  %}
INITIALIZE
  %{
  int i, j;

  xmax = xwidth / 2;
  xmin = -xmax;
  ymax = yheight / 2;
  ymin = -ymax;

  if ((xmin >= xmax) || (ymin >= ymax)) {
    printf ("ERROR: (%s): Null detection area! Exiting.\n", NAME_CURRENT_COMP);
    exit (-1);
  }

  Div_N = create_darr2d (nh, nv);
  Div_p = create_darr2d (nh, nv);
  Div_p2 = create_darr2d (nh, nv);

  NORM (nx, ny, nz);

  // Use instance name for monitor output if no input was given
  if (!strcmp (filename, "\0"))
    sprintf (filename, "%s", NAME_CURRENT_COMP);
  %}
TRACE
  %{
  int i, j;
  double h_div, v_div;
  double k, kn;

  PROP_Z0;
  if (x > xmin && x < xmax && y > ymin && y < ymax) {
    /* Find length of projection onto the [nx ny nz] axis */
    kn = scalar_prod (kx, ky, kz, nx, ny, nz);
    if (rad) {
      h_div = atan2 (kx, kn);
      v_div = atan2 (ky, kn);
    } else {
      h_div = RAD2DEG * atan2 (kx, kn);
      v_div = RAD2DEG * atan2 (ky, kn);
    }
    if (h_div < maxdiv_h && h_div > -maxdiv_h && v_div < maxdiv_v && v_div > -maxdiv_v) {
      i = floor ((h_div + maxdiv_h) * nh / (2.0 * maxdiv_h));
      j = floor ((v_div + maxdiv_v) * nv / (2.0 * maxdiv_v));
      double p2 = p * p;
      #pragma acc atomic
      Div_N[i][j] = Div_N[i][j] + 1;
      #pragma acc atomic
      Div_p[i][j] = Div_p[i][j] + p;
      #pragma acc atomic
      Div_p2[i][j] = Div_p2[i][j] + p2;
      SCATTER;
    }
  }
  if (restore_xray) {
    RESTORE_XRAY (INDEX_CURRENT_COMP, x, y, z, kx, ky, kz, phi, t, Ex, Ey, Ez, p);
  }
  %}
SAVE
  %{
  if (!nowritefile) {
    if (rad) {
      DETECTOR_OUT_2D ("Divergence monitor", "X divergence [rad]", "Y divergence [rad]", -maxdiv_h, maxdiv_h, -maxdiv_v, maxdiv_v, nh, nv, &Div_N[0][0],
                       &Div_p[0][0], &Div_p2[0][0], filename);
    } else {
      DETECTOR_OUT_2D ("Divergence monitor", "X divergence [deg]", "Y divergence [deg]", -maxdiv_h, maxdiv_h, -maxdiv_v, maxdiv_v, nh, nv, &Div_N[0][0],
                       &Div_p[0][0], &Div_p2[0][0], filename);
    }
  }
  %}
FINALLY
  %{
  destroy_darr2d (Div_N);
  destroy_darr2d (Div_p);
  destroy_darr2d (Div_p2);
  %}
MCDISPLAY
  %{

  multiline (5, (double)xmin, (double)ymin, 0.0, (double)xmax, (double)ymin, 0.0, (double)xmax, (double)ymax, 0.0, (double)xmin, (double)ymax, 0.0, (double)xmin,
             (double)ymin, 0.0);
%}

END
