/*******************************************************************************
*
* McXtrace, x-ray tracing package
*         Copyright, All rights reserved
*         DTU Physics, Kgs. Lyngby, Denmark
*         Synchrotron SOLEIL, Saint-Aubin, France
*
* Component: PSD_monitor_4PI
*
* %Identification
* Written by: Erik Knudsen
* Date: June 23rd, 2009
* Origin: Risoe
* Release: McXtrace 0.1
*
* Spherical position-sensitive detector.
*
* %Description
* Based on neutron component by Kim Lefmann and Kristian Nielsen
* An (n times m) pixel spherical PSD monitor using a cylindrical projection.
* Mostly for test and debugging purposes.
*
* Example: PSD_monitor_4PI(radius=0.1,
*           nx=90, ny=90, filename="Output.psd")
*
* %Parameters
* INPUT PARAMETERS:
* radius:   [m] Radius of detector
* nx:       [1] Number of pixel columns
* ny:       [1] Number of pixel rows
* filename: [str] Name of file in which to store the detector image
* restore_xray: [1] If set, the monitor does not influence the xray state
*
* OUTPUT PARAMETERS:
*
* PSD_N:    Array of xray counts
* PSD_p:    Array of xray weight counts
* PSD_p2:   Array of second moments
*
* %End
*******************************************************************************/


DEFINE COMPONENT PSD_monitor_4PI
DEFINITION PARAMETERS ()
SETTING PARAMETERS (radius=1, restore_xray=0, int nx=90, int ny=90, string filename=0)
OUTPUT PARAMETERS (PSD_N, PSD_p, PSD_p2)
/* X-ray parameters: (x,y,z,kx,ky,kz,phi,t,Ex,Ey,Ez,p) */ 

DECLARE
%{
  DArray2d PSD_N;
  DArray2d PSD_p;
  DArray2d PSD_p2;
%}
INITIALIZE
%{
  int i,j;

  PSD_N = create_darr2d(nx, ny);
  PSD_p = create_darr2d(nx, ny);
  PSD_p2 = create_darr2d(nx, ny);

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

  if(sphere_intersect(&l0, &l1, x, y, z, kx, ky, kz, radius) && l1 > 0)
  {
    if(l0 < 0)
      l0 = l1;
    /* l0 is the intersection length with the sphere. */
    PROP_DL(l0);
    psi = atan2(x,z);
    i = floor(nx*(psi/(2*PI)+0.5));
    if(i >= nx)
      i = nx-1;                      /* Special case for psi = PI. */
    else if(i < 0)
      i = 0;
    theta=asin(y/radius);
    j = floor(ny*(theta+PI/2)/PI+0.5);
    if(j >= ny)
      j = ny-1;                      /* Special case for y = radius. */
    else if(j < 0)
      j = 0;
    double p2 = p*p;
#pragma acc atomic
    PSD_N[i][j] = PSD_N[i][j]+1 ;
#pragma acc atomic
    PSD_p[i][j] = PSD_p[i][j] + p;
#pragma acc atomic
    PSD_p2[i][j] = PSD_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
%{
  DETECTOR_OUT_2D(
    "4PI PSD monitor",
    "Longitude [deg]",
    "Lattitude [deg]",
    -180, 180, -90, 90,
    nx, ny,
    &PSD_N[0][0],&PSD_p[0][0],&PSD_p2[0][0],
    filename);
%}

FINALLY
%{
  destroy_darr2d(PSD_N);
  destroy_darr2d(PSD_p);
  destroy_darr2d(PSD_p2);
%}


MCDISPLAY
%{
  
  circle("xy",0,0,0,radius);
  circle("xz",0,0,0,radius);
  circle("yz",0,0,0,radius);
%}

END
