/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright 1997-2002, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* %I
* Written by: Kim Lefmann
* Date: October 26, 2000
* Origin: Risoe
*
* A 2D Position-sensitive monitor. The shape is cylindrical with
* the axis vertical. The monitor covers the whole cylinder (360 degrees).
*
* %D
* An (n times m) pixel PSD monitor with cylinder shape,
* vertical axis, centered at (0,0,0).
*
* Example: PSDcyl_monitor(nr=20, ny=20, filename="Output.cyl", yheight=0.2, radius=0.1)
*
* %P
* INPUT PARAMETERS:
*
* yheight: [m]          Height of detector
* radius: [m]           Radius of detector
* nr: [1]               Number of pixel (radial) columns
* ny: [1]               Number of pixel rows
* thmin: [deg]          Minimum angle covered/measured
* thmax: [deg]          Maximum angle covered/measured
* tmin:  [s]            Minimum time measured
* tmax:  [s]            Maximum time measured
* nt:    [1]            Number of t-bins
* filename: [string]    Name of file in which to store the detector image
* restore_neutron: [1]  If set, the monitor does not influence the neutron state
* nowritefile: [1]      If set, monitor will skip writing to disk
*
* CALCULATED PARAMETERS:
*
* PSD_N: []             Array of neutron counts
* PSD_p: []             Array of neutron weight counts
* PSD_p2: []            Array of second moments
*
* %E
******************************************************************************/

DEFINE COMPONENT Cyl_monitor_TOF



SETTING PARAMETERS (int nr=20, string filename=0, yheight=10, radius=1, int restore_neutron=0,
		    thmin=-180, thmax=180, int nt=100, tmin, tmax, int nowritefile=0)


/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */

DECLARE
%{
  DArray2d PSD_N;
  DArray2d PSD_p;
  DArray2d PSD_p2;
%}

INITIALIZE
%{
  PSD_N =  create_darr2d(nr,nt);
  PSD_p =  create_darr2d(nr,nt);
  PSD_p2 = create_darr2d(nr,nt);

  // 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 t0, t1, phi;

  if(cylinder_intersect(&t0, &t1, x, y, z, vx, vy, vz, radius, yheight) == 1) {
    if(t0<0) {
      if(t1>0) {
	PROP_DT(t1);
	/* Calculate pixel */
	if (fabs(y) <= yheight/2.0) {
	  phi=atan2(x,z)*RAD2DEG;
	  
	  if (phi >= thmin && phi <= thmax) {
	    if (t >= tmin && t < tmax) {
	      i=floor((nr) * (phi-thmin)/(thmax-thmin));
	      j=floor((nt) * (t-tmin)/(tmax-tmin));
	      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;
	    }
	  }
	}
      }
    }
  }
  if (restore_neutron) {
    RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
  }
%}

SAVE
%{
if (!nowritefile) {   
  DETECTOR_OUT_2D(
      "Cylindrical TOF monitor",
      "radial position [deg]",
      "TOF [s]",
      thmin, thmax, tmin, tmax, nr, nt,
      &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("xz", 0, 0, 0, radius );
%}

END
