This archive web page is obsolete!

Please refer to the new mailman archive! New component updates


[Date Prev][Date Next] [Chronological] [Thread] [Top]

New component updates



Hello McStas users,

I've updated my Monitor_nD component so that one can monitor correlations between one parameter in one place and the neutron reaching an other place (i.e. what was the characteristics of my neutron reaching the detector when it was at this position...?).
Ulrich will probably like it...

One just need to put a PreMonitor in a place where to look at the neutron, and the Monitor_nD will use that data if the "use premonitor" option was specified.

Typically, one can obtain guide acceptance diagrams with:

 MyPreMonitor = PreMonitor_nD(
  comp = MyMonitor)

(... for instance a curved Guide ...)

MyMonitor = Monitor_nD(
  xmin = -0.1, xmax = 0.1,
  ymin = -0.1, ymax = 0.1,
  options = "hdiv x, all bins=25, auto limits, use premonitor");

/* this is a phase-space monitor that determines automatically its dimensions */
/* uses 25 bins for each dimension, and gets the data from the PreMonitor position */

You may also obtain these components via the ILL web page <http://www.ill.fr/tas/mcstas/components/>
The Risoe page still provides the 0.13.3 that has an awful bug when using the automatic limits.
Get the Monitor_nD v0.13.7, it can do all the job you like.

I'm also working on monitoring any variable in the simulation (not only from the neutron parameters).
Cheers.

Emmanuel.
 
 

-- 
What's up Doc ?
--------------------------------------------
Emmanuel FARHI, http://www.ill.fr/tas/people/Farhi.html   \|/ ____ \|/
CS-Group ILL4/156, Institut Laue-Langevin (ILL) Grenoble  ~@-/ oO \-@~
6 rue J. Horowitz, BP 156, 38042 Grenoble Cedex 9,France /_( \__/ )_\
Work :Tel (33/0) 4 76 20 71 35. Fax (33/0) 4 76 48 39 06     \__U_/
 
/*******************************************************************************
*
* Component: Monitor_nD
*
* %Identification
* Written by: <a href="mailto:farhi@ill.fr">Emmanuel Farhi</a>
* Date: 14th Feb 2000.
* Origin: <a href="http://www.ill.fr">ILL (France)</a>
* Version: 0.13.7
* Modified by: EF, 29th Feb 2000 : added more options, monitor shape, theta, phi
* Modified by: EF, 10th Mar 2000 : use struct. 
* Modified by: EF, 25th May 2000 : correct Mon2D_Buffer alloc bug.
* Modified by: EF, 17th Oct 2000 : spin detector ok. (0.13.4)
* Modified by: EF, 19th Jan 2001 : 'auto limits' bug corrected (0.13.5)
* Modified by: EF, 01st Feb 2001 : PreMonitor for correlation studies (0.13.6)
* Modified by: EF, 02st Feb 2001 : user variable (0.13.7)
*
* This component is a general Monitor that can output 0/1/2D signals 
* (Intensity vs. [something] and vs. [something] ...)
*
* %Description
* This component is a general Monitor that can output 0/1/2D signals 
* It can produce many 1D signals (one for any variable specified in 
* option list), or a single 2D output (two variables related).
* Also, an additional 'list' of neutrons can be produced.
* By default, monitor is square (in x/y plane). disk is also possible
* The 'cylinder' option will change that for banana shaped detector
* The 'sphere' option simulates spherical detector.
* In normal configuration, the Monitor_nD measures the current parameters 
* of the neutron that is beeing detected. But a PreMonitor_nD component can 
* be used in order to study correlations between a neutron being detected in
* a Monitor_nD place, and given parameters that are monitored elsewhere 
* (at <b>PreMonitor_nD</b>).
* 
* <b>Possible options are</b>
* Variables to record:
*     kx ky kz k wavevector (Angs-1) [usually
*     vx vy vz v            (m/s)     x=horz., y=vert., z=on axis]
*     x y z radius          (m)      Distance, Position
*     t time                (s)      Time of Flight
*     energy omega          (meV)
*     lambda wavelength     (Angs)
*     p intensity flux      (n/s) or (n/cm^2/s)
*     ncounts               (1)
*     sx sy sz              (1)      Spin
*     vdiv                  (deg)    vertical divergence (y)
*     hdiv divergence       (deg)    horizontal divergence (x)
*     angle                 (deg)    divergence from <z> direction
*     theta longitude       (deg)    longitude (x/z) [for sphere and cylinder]
*     phi   lattitude       (deg)    lattitude (y/z) [for sphere and cylinder]
*
*     user user1            will monitor the <Mon_Name>_Vars.UserVariable{1|2}
*     user2                 to be assigned in an other component (see below)
*
* <b>Other options are:</b>
*     auto {limits}             Automatically set detector limits
*     all  {limits or bins}     To set all limits or bins values
*     bins=[bins=20]            Number of bins in the detector along dimension
*     borders                   To also count off-limits neutrons
*                               (X < min or X > max)
*     cylinder                  To get a cylindrical monitor (e.g. banana)
*                               (radius along x, height along y).
*     disk                      Disk flat xy monitor
*                               radius is max abs value of xmin xmax ymin ymax
*     file=string               Detector image file name. default is component
*                               name, plus date and variable extension.
*     square                    Square flat xy monitor
*     limits=[min max]          Lower/Upper limits for axes
*                               (see below for the variable unit)
*     list=[counts=1000] or all For a long file of neutron characteristics
*                               with [counts] events
*     multiple                  For 1D monitors into multiple independant files
*     no or not                 Revert next option
*     outgoing                  Monitor outgoing beam in non flat (sph/cyl) det
*                               (default is incoming beam)
*     per cm2                   Intensity will be per cm^2
*     slit or absorb            Absorb neutrons that are out detector
*     sphrere                   To get a spherical monitor (e.g. a 4PI)
*                               radius is max abs value of xmin xmax ymin ymax
*     unactivate                To unactivate detector (0D detector)
*     premonitor                Will monitor neutron parameters stored
*                               previously with <b>PreMonitor_nD</b>.
*     verbose                   To display additional informations
*
* <b>EXAMPLES:</b>
* Monitor_nD(
*   xmin = -0.1, xmax = 0.1,
*   ymin = -0.1, ymax = 0.1,
*   options = "intensity per cm2 angle,limits=[-5 5] bins=10,with
*              borders, file = mon1");
*                           will monitor neutron angle from [z] axis, between -5
*                        and 5 degrees, in 10 bins, into "mon1.A" output 1D file
*   options = "sphere theta phi outgoing"   for a sphere PSD detector (out beam)
*   options = "angle radius auto limits"   is a 2D monitor with automatic limits
*   options = "list kx ky kz energy" records each neutron contribution in 1 file
*   options = "multiple kx ky kz energy and list all neutrons" 
*          makes 4 output 1D files and produces a complete list for all neutrons
*
*
* How to monitor anything in my simulation: with the 'user' option
*  In a component, you will put for instance in INITIALIZE and/or
*  TRACE sections (same is valid with user2)
*
*  struct MonitornD_Variables *Vars = &(MC_GETPAR(Guide_Mon, Vars));
*               with name of monitor that you will use in instr 
*  strcpy(Vars->UserName1,"My variable label");
*  Vars->UserVariable1++;
*
*  and in the instrument description:
*
*  COMPONENT Guide_Mon = Monitor_nD(
*   xmin = -0.05, xmax = 0.05,
*   ymin = -0.1, ymax = 0.1,
*   options="user1, limits=[0 15], bins=15")
*  AT (0,0,0) RELATIVE GuideEnd
*
* See also the example in <a href="PreMonitor_nD.html">PreMonitor_nD</a>.
*
* %Parameters
* INPUT PARAMETERS:
*
* xmin:   (m)    Lower x bound of opening
* xmax:   (m)    Upper x bound of opening
* ymin:   (m)    Lower y bound of opening
* ymax:   (m)    Upper y bound of opening
* options:(str)  String that specify the configuration of the monitor</br>
*                 The general syntax is "[x] options..." (see <b>Descr.</b>)
*
* OUTPUT PARAMETERS:
*
* Nsum:  Number of neutron hits (counts)
* psum:  Sum of neutron weights (flux)
* p2sum: 2nd moment of neutron weights (error)
* Mon2D_N: output array containing detected signals counts (counts)
* Mon2D_p: (flux)
* Mon2D_p2: (error)
* Mon2D_Buffer: used for long lists and auto limits
* DEFS: structure containing Monitor_nD Defines (struct)
* Vars: structure containing Monitor_nD variables (struct)
*
* %Link 
* <a href="http://www.ill.fr/tas/mcstas/">McStas at ILL</a>
* <a href="PreMonitor_nD.html">PreMonitor_nD</a>
*
* %End
*******************************************************************************/

DEFINE COMPONENT Monitor_nD
DEFINITION PARAMETERS (options)
SETTING PARAMETERS (xmin, xmax, ymin, ymax)
/* these are protected C variables */
OUTPUT PARAMETERS (Nsum, psum, p2sum, Mon2D_N, Mon2D_p, Mon2D_p2, Mon2D_Buffer, DEFS, Vars)
STATE PARAMETERS (x,y,z,vx,vy,vz,t,s1,s2,p)
POLARISATION PARAMETERS (sx,sy,sz)

DECLARE
%{

#ifndef FLT_MAX
#define FLT_MAX 1E37
#endif
#ifndef Monitor_nD_Here

#define MONnD_COORD_NMAX  25  /* max number of variables to record */
  
  /* here we define some DEFINE constants */
  typedef struct MonitornD_Defines
  {
    char COORD_NONE  ;
    char COORD_X     ;
    char COORD_Y     ;
    char COORD_Z     ;
    char COORD_VX    ;
    char COORD_VY    ;
    char COORD_VZ    ;
    char COORD_T     ;
    char COORD_P     ;
    char COORD_SX    ;
    char COORD_SY    ;
    char COORD_SZ    ;
    char COORD_KX    ;
    char COORD_KY    ;
    char COORD_KZ    ;
    char COORD_K     ;
    char COORD_V     ; 
    char COORD_ENERGY; 
    char COORD_LAMBDA; 
    char COORD_RADIUS; 
    char COORD_HDIV  ; 
    char COORD_VDIV  ; 
    char COORD_ANGLE ; 
    char COORD_NCOUNT; 
    char COORD_THETA ; 
    char COORD_PHI   ; 
    char COORD_USER1 ; 
    char COORD_USER2 ;

    /* token modifiers */
    char COORD_VAR   ; /* next token should be a variable or normal option */
    char COORD_MIN   ; /* next token is a min value */
    char COORD_MAX   ; /* next token is a max value */
    char COORD_DIM   ; /* next token is a bin value */
    char COORD_FIL   ; /* next token is a filename */
    char COORD_EVNT  ; /* next token is a buffer size value */

    char TOKEN_DEL[32]; /* token separators */

    char SHAPE_SQUARE; /* shape of the monitor */
    char SHAPE_DISK  ; 
    char SHAPE_SPHERE; 
    char SHAPE_CYLIND; 
  } MonitornD_Defines_type;
  
  typedef struct MonitornD_Variables
  {
    double area;
    double Sphere_Radius     ;
    double Cylinder_Height   ;
    char   Flag_With_Borders ;   /* 2 means xy borders too */
    char   Flag_List         ;   /* 1 store 1 buffer, 2 is list all */
    char   Flag_Multiple     ;   /* 1 when n1D, 0 for 2D */
    char   Flag_Verbose      ;
    int    Flag_Shape        ;
    char   Flag_Auto_Limits  ;   /* get limits from first Buffer */
    char   Flag_Absorb       ;   /* monitor is also a slit */
    char   Flag_per_cm2      ;   /* flux is per cm2 */
    
    int    Coord_Number      ;   /* total number of variables to monitor, plus intensity (0) */
    long   Buffer_Block      ;   /* Buffer size for list or auto limits */
    long   Neutron_Counter   ;   /* event counter, simulation total counts is mcget_ncount() */
    long   Buffer_Counter    ;   /* index in Buffer size (for realloc) */
    long   Buffer_Size       ;
    char   Coord_Type[MONnD_COORD_NMAX];    /* type of variable */
    char   Coord_Label[MONnD_COORD_NMAX][30];       /* label of variable */
    char   Coord_Var[MONnD_COORD_NMAX][30]; /* short id of variable */
    int    Coord_Bin[MONnD_COORD_NMAX];             /* bins of variable array */
    double Coord_Min[MONnD_COORD_NMAX];             
    double Coord_Max[MONnD_COORD_NMAX];
    char   Monitor_Label[MONnD_COORD_NMAX*30];      /* Label for monitor */
    char   Mon_File[128];    /* output file name */

    double cx,cy,cz;
    double cvx, cvy, cvz;
    double csx, csy, csz;
    double cs1, cs2, ct, cp;
    char   Flag_UsePreMonitor    ;   /* use a previously stored neutron parameter set */
    char   UserName1[128];
    char   UserName2[128];
    double UserVariable1;
    double UserVariable2;

  } MonitornD_Variables_type;

  #define Monitor_nD_Here 
#endif

  int    Nsum;
  double psum, p2sum;
  int    **Mon2D_N;
  double **Mon2D_p;
  double **Mon2D_p2;
  double *Mon2D_Buffer;
  
  MonitornD_Defines_type DEFS;
  MonitornD_Variables_type Vars;

%}

INITIALIZE
%{
    long carg = 1;
    char *option_copy, *token;
    char Flag_New_Token = 1;
    char Flag_End       = 1;
    char Flag_All       = 0;
    char Flag_No        = 0;
    char Set_Vars_Coord_Type;
    char Set_Coord_Flag = 0;
    char Set_Vars_Coord_Label[30];
    char Set_Vars_Coord_Var[30];
    char Short_Label[MONnD_COORD_NMAX][30];
    char Set_Coord_Mode;
    long i=0;
    double lmin, lmax;
    long    t;
    
    t = (long)time(NULL);

    DEFS.COORD_NONE   =0;
    DEFS.COORD_X      =1;
    DEFS.COORD_Y      =2;
    DEFS.COORD_Z      =3;
    DEFS.COORD_VX     =4;
    DEFS.COORD_VY     =5;
    DEFS.COORD_VZ     =6;
    DEFS.COORD_T      =7;
    DEFS.COORD_P      =8;
    DEFS.COORD_SX     =9;
    DEFS.COORD_SY     =10;
    DEFS.COORD_SZ     =11;
    DEFS.COORD_KX     =12;
    DEFS.COORD_KY     =13;
    DEFS.COORD_KZ     =14;
    DEFS.COORD_K      =15;
    DEFS.COORD_V      =16;
    DEFS.COORD_ENERGY =17;
    DEFS.COORD_LAMBDA =18;
    DEFS.COORD_RADIUS =19;
    DEFS.COORD_HDIV   =20;
    DEFS.COORD_VDIV   =21;
    DEFS.COORD_ANGLE  =22;
    DEFS.COORD_NCOUNT =23;
    DEFS.COORD_THETA  =24;
    DEFS.COORD_PHI    =25;
    DEFS.COORD_USER1  =26;
    DEFS.COORD_USER2  =26;

/* token modifiers */
    DEFS.COORD_VAR    =0;    /* next token should be a variable or normal option */
    DEFS.COORD_MIN    =1;    /* next token is a min value */
    DEFS.COORD_MAX    =2;    /* next token is a max value */
    DEFS.COORD_DIM    =3;    /* next token is a bin value */
    DEFS.COORD_FIL    =4;    /* next token is a filename */
    DEFS.COORD_EVNT   =5;    /* next token is a buffer size value */

    strcpy(DEFS.TOKEN_DEL, " =,;[](){}:");	/* token separators */

    DEFS.SHAPE_SQUARE =0;    /* shape of the monitor */
    DEFS.SHAPE_DISK   =1;
    DEFS.SHAPE_SPHERE =2;
    DEFS.SHAPE_CYLIND =3;

    Vars.Sphere_Radius     = 0;
    Vars.Cylinder_Height   = 0;
    Vars.Flag_With_Borders = 0;   /* 2 means xy borders too */
    Vars.Flag_List         = 0;   /* 1 store 1 buffer, 2 is list all */
    Vars.Flag_Multiple     = 0;   /* 1 when n1D, 0 for 2D */
    Vars.Flag_Verbose      = 0;
    Vars.Flag_Shape        = DEFS.SHAPE_SQUARE;
    Vars.Flag_Auto_Limits  = 0;   /* get limits from first Buffer */
    Vars.Flag_Absorb       = 0;   /* monitor is also a slit */
    Vars.Flag_per_cm2      = 0;   /* flux is per cm2 */
    Vars.Coord_Number      = 0;   /* total number of variables to monitor, plus intensity (0) */
    Vars.Buffer_Block      = 1000;     /* Buffer size for list or auto limits */
    Vars.Neutron_Counter   = 0;   /* event counter, simulation total counts is mcget_ncount() */
    Vars.Buffer_Counter    = 0;   /* index in Buffer size (for realloc) */
    Vars.Buffer_Size       = 0;
    Vars.UserVariable1     = 0;
    Vars.UserVariable2     = 0;
    
    Set_Vars_Coord_Type = DEFS.COORD_NONE;
    Set_Coord_Mode = DEFS.COORD_VAR;

    /* parse option string */ 
    
    option_copy = (char*)malloc(strlen(options));
    if (option_copy == NULL)
    {
      printf("Monitor_nD: %s cannot allocate option_copy (%i). Fatal.\n", mccompcurname, strlen(options));
      exit(-1);
    }
    
    
    if (strlen(options))
    {
      Flag_End = 0;
      strcpy(option_copy, options);
    }
    
    if (strstr(options, "cm2") || strstr(options, "cm^2")) Vars.Flag_per_cm2 = 1;
  
    if (Vars.Flag_per_cm2) strcpy(Vars.Coord_Label[0],"Intensity [n/cm^2/s]");
	 else strcpy(Vars.Coord_Label[0],"Intensity [n/s]");
    strcpy(Vars.Coord_Var[0],"p");
    Vars.Coord_Type[0] = DEFS.COORD_P;
    Vars.Coord_Bin[0] = 1;
    Vars.Coord_Min[0] = 0;
    Vars.Coord_Max[0] = FLT_MAX;
    
    /* default file name is comp name+dateID */
    sprintf(Vars.Mon_File, "%s_%i", mccompcurname, t); 
  
    carg = 1;
    while((Flag_End == 0) && (carg < 128))
    {
      if (Flag_New_Token) /* to get the previous token sometimes */
      {
	if (carg == 1) token=(char *)strtok(option_copy,DEFS.TOKEN_DEL);
	else token=(char *)strtok(NULL,DEFS.TOKEN_DEL);
	if (token == NULL) Flag_End=1;
      }
      Flag_New_Token = 1;
      if ((token != NULL) && (strlen(token) != 0))
      {
      /* first handle option values from preceeding keyword token detected */
	if (Set_Coord_Mode == DEFS.COORD_MAX)
	{ 
	  if (!Flag_All) 
	    Vars.Coord_Max[Vars.Coord_Number] = atof(token); 
	  else
	    for (i = 0; i <= Vars.Coord_Number; Vars.Coord_Max[i++] = atof(token));
	  Set_Coord_Mode = DEFS.COORD_VAR; Flag_All = 0;
	}
	if (Set_Coord_Mode == DEFS.COORD_MIN)
	{ 
	  if (!Flag_All) 
	    Vars.Coord_Min[Vars.Coord_Number] = atof(token); 
	  else
	    for (i = 0; i <= Vars.Coord_Number; Vars.Coord_Min[i++] = atof(token));
	  Set_Coord_Mode = DEFS.COORD_MAX; 
	}
	if (Set_Coord_Mode == DEFS.COORD_DIM)
	{ 
	  if (!Flag_All) 
	    Vars.Coord_Bin[Vars.Coord_Number] = atoi(token); 
	  else
	    for (i = 0; i <= Vars.Coord_Number; Vars.Coord_Bin[i++] = atoi(token));
	  Set_Coord_Mode = DEFS.COORD_VAR; Flag_All = 0;
	}
	if (Set_Coord_Mode == DEFS.COORD_FIL)
	  { 
	    if (!Flag_No) strcpy(Vars.Mon_File,token); 
	    else { strcpy(Vars.Mon_File,""); Vars.Coord_Number = 0; Flag_End = 1;}
	    Set_Coord_Mode = DEFS.COORD_VAR;
	  }
	if (Set_Coord_Mode == DEFS.COORD_EVNT)
	{ 
	  if (!strcmp(token, "all") || Flag_All) Vars.Flag_List = 2;
	  else { i = atoi(token); if (i) Vars.Buffer_Counter = i; }
	  Set_Coord_Mode = DEFS.COORD_VAR; Flag_All = 0;
	}
	
	/* now look for general option keywords */
	if (!strcmp(token, "borders")) 
	{ if (Flag_No) { Vars.Flag_With_Borders = 0; Flag_No = 0; }
	  else Vars.Flag_With_Borders = 1; }
	if (!strcmp(token, "verbose")) 
	{ if (Flag_No) { Vars.Flag_Verbose = 0; Flag_No = 0; }
	  else Vars.Flag_Verbose      = 1; }
	if (!strcmp(token, "multiple")) 
	{ if (Flag_No) { Vars.Flag_Multiple = 0; Flag_No = 0; }
	  else Vars.Flag_Multiple = 1; }
	if (!strcmp(token, "list")) 
	{ if (Flag_No) { Vars.Flag_List = 0; Flag_No = 0; }
	  else Vars.Flag_List = 1; 
	  Set_Coord_Mode = DEFS.COORD_EVNT; }
	
	if (!strcmp(token, "limits") || !strcmp(token, "min")) Set_Coord_Mode = DEFS.COORD_MIN;
	if (!strcmp(token, "slit") || !strcmp(token, "absorb")) 
	{ if (Flag_No) { Vars.Flag_Absorb = 0; Flag_No = 0; }
	  else Vars.Flag_Absorb = 1; }
	if (!strcmp(token, "max")) Set_Coord_Mode = DEFS.COORD_MAX;
	if (!strcmp(token, "bins")) Set_Coord_Mode = DEFS.COORD_DIM;
	if (!strcmp(token, "file")) 
	{ Set_Coord_Mode = DEFS.COORD_FIL;
	  if (Flag_No) { strcpy(Vars.Mon_File,""); Vars.Coord_Number = 0; Flag_End = 1;}}
	if (!strcmp(token, "unactivate")) { Flag_End = 1; Vars.Coord_Number = 0; }
	if (!strcmp(token, "all")) 
	{ if (Flag_No) { Flag_All = 0; Flag_No = 0; }
	  else Flag_All = 1; }
	if (!strcmp(token, "sphere")) 
	{ if (Flag_No) { Vars.Flag_Shape = DEFS.SHAPE_SQUARE; Flag_No = 0; }
	  else Vars.Flag_Shape = DEFS.SHAPE_SPHERE; }
	if (!strcmp(token, "cylinder")) 
	{ if (Flag_No) { Vars.Flag_Shape = DEFS.SHAPE_SQUARE; Flag_No = 0; }
	  else Vars.Flag_Shape = DEFS.SHAPE_CYLIND; }
	if (!strcmp(token, "square")) Vars.Flag_Shape = DEFS.SHAPE_SQUARE; 
	if (!strcmp(token, "disk")) Vars.Flag_Shape = DEFS.SHAPE_DISK; 
	if (!strcmp(token, "auto")) 
	{ if (Flag_No) { Vars.Flag_Auto_Limits = 0; Flag_No = 0; }
	  else Vars.Flag_Auto_Limits = 1; }
	if (!strcmp(token, "premonitor"))
        { if (Flag_No) { Vars.Flag_UsePreMonitor = 0; Flag_No = 0; }
	  else Vars.Flag_UsePreMonitor == 1; } 
        if (!strcmp(token, "no") || !strcmp(token, "not")) Flag_No = 1;
	
	/* now look for variable names to monitor */
	Set_Vars_Coord_Type = DEFS.COORD_NONE; lmin = 0; lmax = 0;
	
	if (!strcmp(token, "x")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_X; strcpy(Set_Vars_Coord_Label,"x [m]"); strcpy(Set_Vars_Coord_Var,"x"); lmin = xmin; lmax = xmax; }
	if (!strcmp(token, "y")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_Y; strcpy(Set_Vars_Coord_Label,"y [m]"); strcpy(Set_Vars_Coord_Var,"y"); lmin = ymin; lmax = ymax; }
	if (!strcmp(token, "z")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_Z; strcpy(Set_Vars_Coord_Label,"z [m]"); strcpy(Set_Vars_Coord_Var,"z"); lmin = 0; lmax = 100; }
	if (!strcmp(token, "k") || !strcmp(token, "wavevector")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_K; strcpy(Set_Vars_Coord_Label,"|k| [Angs-1]"); strcpy(Set_Vars_Coord_Var,"k"); lmin = 0; lmax = 10; }
	if (!strcmp(token, "v"))
	  { Set_Vars_Coord_Type = DEFS.COORD_V; strcpy(Set_Vars_Coord_Label,"Velocity [m/s]"); strcpy(Set_Vars_Coord_Var,"v"); lmin = 0; lmax = 10000; }
	if (!strcmp(token, "t") || !strcmp(token, "time")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_T; strcpy(Set_Vars_Coord_Label,"TOF [s]"); strcpy(Set_Vars_Coord_Var,"t"); lmin = 0; lmax = .1; }
	if ((Vars.Coord_Number > 0) && (!strcmp(token, "p") || !strcmp(token, "intensity") || !strcmp(token, "flux")))
	  { Set_Vars_Coord_Type = DEFS.COORD_P;  
	    if (Vars.Flag_per_cm2) strcpy(Set_Vars_Coord_Label,"Intensity [n/cm^2/s]");
	    else strcpy(Set_Vars_Coord_Label,"Intensity [n/s]"); 
	    strcpy(Set_Vars_Coord_Var,"I"); 
	    lmin = 0; lmax = FLT_MAX; }

	if (!strcmp(token, "vx")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_VX; strcpy(Set_Vars_Coord_Label,"vx [m/s]"); strcpy(Set_Vars_Coord_Var,"vx"); lmin = -1000; lmax = 1000; }
	if (!strcmp(token, "vy")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_VY; strcpy(Set_Vars_Coord_Label,"vy [m/s]"); strcpy(Set_Vars_Coord_Var,"vy"); lmin = -1000; lmax = 1000; }
	if (!strcmp(token, "vz")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_VZ; strcpy(Set_Vars_Coord_Label,"vz [m/s]"); strcpy(Set_Vars_Coord_Var,"vz"); lmin = -10000; lmax = 10000; }
	if (!strcmp(token, "kx")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_KX; strcpy(Set_Vars_Coord_Label,"kx [Angs-1]"); strcpy(Set_Vars_Coord_Var,"kx"); lmin = -1; lmax = 1; }
	if (!strcmp(token, "ky")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_KY; strcpy(Set_Vars_Coord_Label,"ky [Angs-1]"); strcpy(Set_Vars_Coord_Var,"ky"); lmin = -1; lmax = 1; }
	if (!strcmp(token, "kz")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_KZ; strcpy(Set_Vars_Coord_Label,"kz [Angs-1]"); strcpy(Set_Vars_Coord_Var,"kz"); lmin = -10; lmax = 10; }
	if (!strcmp(token, "sx")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_SX; strcpy(Set_Vars_Coord_Label,"sx [1]"); strcpy(Set_Vars_Coord_Var,"sx"); lmin = -1; lmax = 1; }
	if (!strcmp(token, "sy")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_SY; strcpy(Set_Vars_Coord_Label,"sy [1]"); strcpy(Set_Vars_Coord_Var,"sy"); lmin = -1; lmax = 1; }
	if (!strcmp(token, "sz")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_SZ; strcpy(Set_Vars_Coord_Label,"sz [1]"); strcpy(Set_Vars_Coord_Var,"sz"); lmin = -1; lmax = 1; }
	
	if (!strcmp(token, "energy") || !strcmp(token, "omega")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_ENERGY; strcpy(Set_Vars_Coord_Label,"Energy [meV]"); strcpy(Set_Vars_Coord_Var,"E"); lmin = 0; lmax = 100; }
	if (!strcmp(token, "lambda") || !strcmp(token, "wavelength")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_LAMBDA; strcpy(Set_Vars_Coord_Label,"Wavelength [Angs]"); strcpy(Set_Vars_Coord_Var,"L"); lmin = 0; lmax = 100; }
	if (!strcmp(token, "radius")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_RADIUS; strcpy(Set_Vars_Coord_Label,"Radius [m]"); strcpy(Set_Vars_Coord_Var,"R"); lmin = 0; lmax = xmax; }
	if (!strcmp(token, "angle")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_ANGLE; strcpy(Set_Vars_Coord_Label,"Angle [deg]"); strcpy(Set_Vars_Coord_Var,"A"); lmin = -5; lmax = 5; }
	if (!strcmp(token, "hdiv")|| !strcmp(token, "divergence")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_HDIV; strcpy(Set_Vars_Coord_Label,"Hor. Divergence [deg]"); strcpy(Set_Vars_Coord_Var,"HD"); lmin = -5; lmax = 5; }
	if (!strcmp(token, "vdiv")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_VDIV; strcpy(Set_Vars_Coord_Label,"Vert. Divergence [deg]"); strcpy(Set_Vars_Coord_Var,"VD"); lmin = -5; lmax = 5; }
	if (!strcmp(token, "theta") || !strcmp(token, "longitude")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_THETA; strcpy(Set_Vars_Coord_Label,"Longitude [deg]"); strcpy(Set_Vars_Coord_Var,"th"); lmin = -180; lmax = 180; }
	if (!strcmp(token, "phi") || !strcmp(token, "lattitude")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_PHI; strcpy(Set_Vars_Coord_Label,"Lattitude [deg]"); strcpy(Set_Vars_Coord_Var,"ph"); lmin = -180; lmax = 180; }
	if (!strcmp(token, "ncounts")) 
	  { Set_Vars_Coord_Type = DEFS.COORD_NCOUNT; strcpy(Set_Vars_Coord_Label,"Neutrons [1]"); strcpy(Set_Vars_Coord_Var,"N"); lmin = 0; lmax = 1e10; }
        if (!strcmp(token, "user") || !strcmp(token, "user1"))
	  { Set_Vars_Coord_Type = DEFS.COORD_USER1; strncpy(Set_Vars_Coord_Label,Vars.UserName1,32); strcpy(Set_Vars_Coord_Var,"U1"); lmin = -1e10; lmax = 1e10; }
        if (!strcmp(token, "user2"))
	  { Set_Vars_Coord_Type = DEFS.COORD_USER2; strncpy(Set_Vars_Coord_Label,Vars.UserName2,32); strcpy(Set_Vars_Coord_Var,"U2"); lmin = -1e10; lmax = 1e10; }
	
	/* now stores variable keywords detected, if any */ 
	if (Set_Vars_Coord_Type != DEFS.COORD_NONE)
	{
	  if (Vars.Coord_Number < MONnD_COORD_NMAX) Vars.Coord_Number++;
	  else if (Vars.Flag_Verbose) printf("Monitor_nD: %s reached max number of variables (%i).\n", mccompcurname, MONnD_COORD_NMAX);
	  Vars.Coord_Type[Vars.Coord_Number] = Set_Vars_Coord_Type;
	  strcpy(Vars.Coord_Label[Vars.Coord_Number], Set_Vars_Coord_Label); 
	  strcpy(Vars.Coord_Var[Vars.Coord_Number], Set_Vars_Coord_Var);
	  Vars.Coord_Min[Vars.Coord_Number] = lmin;
	  Vars.Coord_Max[Vars.Coord_Number] = lmax;
	  Vars.Coord_Bin[Vars.Coord_Number] = 20;
	  Set_Coord_Mode = DEFS.COORD_VAR;
	  Flag_All = 0;
	  Flag_No = 0;
	}
	
	carg++;
      } /* end if token */
    } /* end while carg */
    free(option_copy);
    if (carg == 128) printf("Monitor_nD: %s reached max number of tokens (%i). Skipping.\n", mccompcurname, 128);
    
    if (strstr(options,"unactivate") && Vars.Flag_Verbose)  printf("Monitor_nD: %s is unactivated (0D)\n", mccompcurname);

    /* now setting Monitor Name from variable labels */
    strcpy(Vars.Monitor_Label,"");
    for (i = 0; i <= Vars.Coord_Number; i++)
    {
      Set_Vars_Coord_Type = Vars.Coord_Type[i];
      if ((Set_Vars_Coord_Type == DEFS.COORD_THETA)
       || (Set_Vars_Coord_Type == DEFS.COORD_PHI)
       || (Set_Vars_Coord_Type == DEFS.COORD_X)
       || (Set_Vars_Coord_Type == DEFS.COORD_Y)
       || (Set_Vars_Coord_Type == DEFS.COORD_Z)
       || (Set_Vars_Coord_Type == DEFS.COORD_RADIUS))
       strcpy(Short_Label[i],"Position"); 
      else
      if ((Set_Vars_Coord_Type == DEFS.COORD_VX)
       || (Set_Vars_Coord_Type == DEFS.COORD_VY)
       || (Set_Vars_Coord_Type == DEFS.COORD_VZ)
       || (Set_Vars_Coord_Type == DEFS.COORD_V))
       strcpy(Short_Label[i],"Velocity"); 
      else
      if ((Set_Vars_Coord_Type == DEFS.COORD_KX)
       || (Set_Vars_Coord_Type == DEFS.COORD_KY)
       || (Set_Vars_Coord_Type == DEFS.COORD_KZ)
       || (Set_Vars_Coord_Type == DEFS.COORD_K))
       strcpy(Short_Label[i],"Wavevector"); 
      else
      if ((Set_Vars_Coord_Type == DEFS.COORD_SX)
       || (Set_Vars_Coord_Type == DEFS.COORD_SY)
       || (Set_Vars_Coord_Type == DEFS.COORD_SZ))
       strcpy(Short_Label[i],"Spin");
      else
      if ((Set_Vars_Coord_Type == DEFS.COORD_HDIV)
       || (Set_Vars_Coord_Type == DEFS.COORD_VDIV)
       || (Set_Vars_Coord_Type == DEFS.COORD_ANGLE))
       strcpy(Short_Label[i],"Divergence");
      else
      if (Set_Vars_Coord_Type == DEFS.COORD_ENERGY)
       strcpy(Short_Label[i],"Energy"); 
      else
      if (Set_Vars_Coord_Type == DEFS.COORD_LAMBDA)
       strcpy(Short_Label[i],"Wavelength"); 
      else
      if (Set_Vars_Coord_Type == DEFS.COORD_NCOUNT)
       strcpy(Short_Label[i],"Neutron counts");
      else
      if (Set_Vars_Coord_Type == DEFS.COORD_T)
          strcpy(Short_Label[i],"Time Of Flight");
      else
      if (Set_Vars_Coord_Type == DEFS.COORD_P)
          strcpy(Short_Label[i],"Intensity");
      else
      if (Set_Vars_Coord_Type == DEFS.COORD_USER1)
          strncpy(Short_Label[i],Vars.UserName1,32);
      else
      if (Set_Vars_Coord_Type == DEFS.COORD_USER2)
          strncpy(Short_Label[i],Vars.UserName2,32);
      else
          strcpy(Short_Label[i],"Unknown"); 
          
      strcat(Vars.Monitor_Label, " ");
      strcat(Vars.Monitor_Label, Short_Label[i]);
    } /* end for Short_Label */
    strcat(Vars.Monitor_Label, " Monitor");
    if (Vars.Flag_Shape == DEFS.SHAPE_SQUARE) strcat(Vars.Monitor_Label, " (Square)");
    if (Vars.Flag_Shape == DEFS.SHAPE_DISK)   strcat(Vars.Monitor_Label, " (Disk)");
    if (Vars.Flag_Shape == DEFS.SHAPE_SPHERE) strcat(Vars.Monitor_Label, " (Sphere)");
    if (Vars.Flag_Shape == DEFS.SHAPE_CYLIND) strcat(Vars.Monitor_Label, " (Cylinder)");
    if (((Vars.Flag_Shape == DEFS.SHAPE_CYLIND) || (Vars.Flag_Shape == DEFS.SHAPE_SPHERE))
        && strstr(options, "outgoing"))
    {
      Vars.Flag_Shape *= -1;
      strcat(Vars.Monitor_Label, " [out]");
    }
    if (Vars.Flag_UsePreMonitor == 1)
    {
        strcat(Vars.Monitor_Label, " at ");
        strncat(Vars.Monitor_Label, Vars.UserName1,32);
    }
    
    /* Vars.Coord_Number  0   : intensity
     * Vars.Coord_Number  1:n : detector variables */
    
    /* now allocate memory to store variables in TRACE */
    if ((Vars.Coord_Number != 2) && !Vars.Flag_Multiple && !Vars.Flag_List) 
    { Vars.Flag_Multiple = 1; Vars.Flag_List = 0; } /* default is n1D */
    
    /* list and auto limits case : Vars.Flag_List or Vars.Flag_Auto_Limits 
     * -> Buffer to flush and suppress after Vars.Flag_Auto_Limits
     */
     if ((Vars.Flag_Auto_Limits || Vars.Flag_List) && Vars.Coord_Number)
     { /* Dim : (Vars.Coord_Number+2)*Vars.Buffer_Block matrix (for p, dp) */ 
       Mon2D_Buffer = (double *)malloc((Vars.Coord_Number+2)*Vars.Buffer_Block*sizeof(double));
       if (Mon2D_Buffer == NULL)
       { printf("Monitor_nD: %s cannot allocate Mon2D_Buffer (%li). No list and auto limits.\n", mccompcurname, Vars.Buffer_Block*(Vars.Coord_Number+2)*sizeof(double)); Vars.Flag_List = 0; Vars.Flag_Auto_Limits = 0; }
       Vars.Buffer_Size = Vars.Buffer_Block;
     }
    
    /* 1D and n1D case : Vars.Flag_Multiple */
    if (Vars.Flag_Multiple && Vars.Coord_Number)
    { /* Dim : Vars.Coord_Number*Vars.Coord_Bin[i] vectors */ 
      Mon2D_N  = (int **)malloc((Vars.Coord_Number)*sizeof(int *));
      Mon2D_p  = (double **)malloc((Vars.Coord_Number)*sizeof(double *));
      Mon2D_p2 = (double **)malloc((Vars.Coord_Number)*sizeof(double *));
      if ((Mon2D_N == NULL) || (Mon2D_p == NULL) || (Mon2D_p2 == NULL))
      { printf("Monitor_nD: %s n1D cannot allocate Mon2D_N/p/2p (%i). Fatal.\n", mccompcurname, (Vars.Coord_Number)*sizeof(double *)); exit(-1); }
      for (i= 1; i <= Vars.Coord_Number; i++)
      { 
        Mon2D_N[i-1]  = (int *)malloc(Vars.Coord_Bin[i]*sizeof(int));
        Mon2D_p[i-1]  = (double *)malloc(Vars.Coord_Bin[i]*sizeof(double));
        Mon2D_p2[i-1] = (double *)malloc(Vars.Coord_Bin[i]*sizeof(double));
	if ((Mon2D_N == NULL) || (Mon2D_p == NULL) || (Mon2D_p2 == NULL))
        { printf("Monitor_nD: %s n1D cannot allocate %s Mon2D_N/p/2p[%li] (%i). Fatal.\n", mccompcurname, Vars.Coord_Var[i], i, (Vars.Coord_Bin[i])*sizeof(double *)); exit(-1); }
      }
    }
    else /* 2D case : Vars.Coord_Number==2 and !Vars.Flag_Multiple and !Vars.Flag_List */
    if ((Vars.Coord_Number == 2) && !Vars.Flag_Multiple)
    { /* Dim : Vars.Coord_Bin[1]*Vars.Coord_Bin[2] matrix */ 
      Mon2D_N  = (int **)malloc((Vars.Coord_Bin[1])*sizeof(int *));
      Mon2D_p  = (double **)malloc((Vars.Coord_Bin[1])*sizeof(double *));
      Mon2D_p2 = (double **)malloc((Vars.Coord_Bin[1])*sizeof(double *));
      if ((Mon2D_N == NULL) || (Mon2D_p == NULL) || (Mon2D_p2 == NULL))
      { printf("Monitor_nD: %s 2D cannot allocate %s Mon2D_N/p/2p (%i). Fatal.\n", mccompcurname, Vars.Coord_Var[1], (Vars.Coord_Bin[1])*sizeof(double *)); exit(-1); }
      for (i= 0; i < Vars.Coord_Bin[1]; i++)
      { 
	Mon2D_N[i]  = (int *)malloc(Vars.Coord_Bin[2]*sizeof(int));
	Mon2D_p[i]  = (double *)malloc(Vars.Coord_Bin[2]*sizeof(double));
	Mon2D_p2[i] = (double *)malloc(Vars.Coord_Bin[2]*sizeof(double));
	if ((Mon2D_N == NULL) || (Mon2D_p == NULL) || (Mon2D_p2 == NULL))
	{ printf("Monitor_nD: %s 2D cannot allocate %s Mon2D_N/p/2p[%li] (%i). Fatal.\n", mccompcurname, Vars.Coord_Var[1], i, (Vars.Coord_Bin[2])*sizeof(double *)); exit(-1); }
      }
    }      
      /* no Mon2D allocated for 
       * (Vars.Coord_Number != 2) && !Vars.Flag_Multiple && Vars.Flag_List */
    
    psum  = 0;
    p2sum = 0;
    Nsum  = 0;
    
    Vars.area  = (xmax - xmin)*(ymax - ymin)*1E4; /* in cm**2 for square shapes */
    Vars.Sphere_Radius = 0;
    if (fabs(xmin) > Vars.Sphere_Radius) Vars.Sphere_Radius = fabs(xmin);
    if (fabs(xmax) > Vars.Sphere_Radius) Vars.Sphere_Radius = fabs(xmax);
    if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_DISK) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE))
    {
      if (fabs(ymin) > Vars.Sphere_Radius) Vars.Sphere_Radius = fabs(ymin);
      if (fabs(ymax) > Vars.Sphere_Radius) Vars.Sphere_Radius = fabs(ymax);
      Vars.area = PI*Vars.Sphere_Radius*Vars.Sphere_Radius; /* disk shapes */
    }
    Vars.Cylinder_Height = fabs(ymax-ymin);
  %}
TRACE
  %{    
    double  XY=0;
    double  t0 = 0;
    double  t1 = 0;
    long    i,j;
    double  pp;
    double  Coord[MONnD_COORD_NMAX];
    long    Coord_Index[MONnD_COORD_NMAX];
    char    While_End   =0;
    long    While_Buffer=0;
    int     intersect = 0;
    char    Set_Vars_Coord_Type = DEFS.COORD_NONE;
    
    if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SQUARE) /* square xy */
      intersect = (x>=xmin && x<=xmax && y>=ymin && y<=ymax);
    if (abs(Vars.Flag_Shape) == DEFS.SHAPE_DISK)   /* disk xy */
      intersect = ((x*x + y*y) <= Vars.Sphere_Radius*Vars.Sphere_Radius);
    if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) /* sphere */
      intersect = (sphere_intersect(&t0, &t1, x, y, z, vx, vy, vz, Vars.Sphere_Radius) && t1 > 0);
    if (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) /* cylinder */
      intersect = (cylinder_intersect(&t0, &t1, x, y, z, vx, vy, vz, Vars.Sphere_Radius, Vars.Cylinder_Height) && t1 > 0);

    if (intersect)
    {
      if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND))
      {
	if(t0 < 0)
          t0 = t1;
	/* t0 is now time of intersection with the sphere. */
	if (Vars.Flag_Shape < 0)
      	  PROP_DT(t1); /* t1 outgoing beam */
	else
	  PROP_DT(t0); /* t0 incoming beam */
      }
      else
        PROP_Z0; 
      
      /* Now get the data to monitor: curent or keep from PreMonitor */
      if (Vars.Flag_UsePreMonitor != 1)
      {
        Vars.cp = p;
        Vars.cx = x;
        Vars.cvx = vx;
        Vars.csx = sx;
        Vars.cy = y;
        Vars.cvy = vy;
        Vars.csy = sy;
        Vars.cz = z;
        Vars.cvz = vz;
        Vars.csz = sz;
        Vars.ct = t;
      }
      
      pp = Vars.cp;
      
      if (Vars.Flag_per_cm2 && Vars.area != 0) pp /= Vars.area;
      Nsum++;
      psum += pp;
      p2sum += pp*pp;
      
      if (Vars.Coord_Number > 0)
      {
	
	/* Vars.Flag_Auto_Limits */
	if ((Vars.Buffer_Counter >= Vars.Buffer_Block) && (Vars.Flag_Auto_Limits == 1))
	{
	  /* auto limits case : get limits in Buffer for each variable */ 
          /* Dim : (Vars.Coord_Number+2)*Vars.Buffer_Block matrix (for p, dp) */ 
	  if (Vars.Flag_Verbose) printf("Monitor_nD: %s getting %i Auto Limits from List (%li).\n", mccompcurname, Vars.Coord_Number, Vars.Buffer_Counter);
	  for (i = 1; i <= Vars.Coord_Number; i++)
	  {
	    Vars.Coord_Min[i] = FLT_MAX;
	    Vars.Coord_Max[i] = -FLT_MAX;
	    for (j = 0; j < Vars.Buffer_Block; j++)
	    { 
              XY = Mon2D_Buffer[j*(Vars.Coord_Number+2) + (i-1)];	/* scanning variables in Buffer */
	      if (XY < Vars.Coord_Min[i]) Vars.Coord_Min[i] = XY;
	      if (XY > Vars.Coord_Max[i]) Vars.Coord_Max[i] = XY;
	    }
	  }
	  Vars.Flag_Auto_Limits = 2;	/* pass to 2nd auto limits step */
	}
	
	
	/* manage realloc for list all if Buffer size exceeded */
	if ((Vars.Buffer_Counter >= Vars.Buffer_Block) && (Vars.Flag_List == 2))
	{
	  Mon2D_Buffer  = (double *)realloc(Mon2D_Buffer, (Vars.Coord_Number+2)*(Vars.Neutron_Counter+Vars.Buffer_Block)*sizeof(double));
	  if (Mon2D_Buffer == NULL)
          { printf("Monitor_nD: %s cannot reallocate Mon2D_Buffer[%li] (%li). Skipping.\n", mccompcurname, i, (Vars.Neutron_Counter+Vars.Buffer_Block)*sizeof(double)); Vars.Flag_List = 1; }
	  else { Vars.Buffer_Counter = 0; Vars.Buffer_Size = Vars.Neutron_Counter+Vars.Buffer_Block; }
	  
	}
	  
	while (!While_End)
	{ /* we generate Coord[] and Coord_index[] from Buffer (auto limits) or passing neutron */
	  if (Vars.Flag_Auto_Limits == 2)
	  {
	    if (While_Buffer < Vars.Buffer_Block)
	    {
	      /* first while loops (While_Buffer) */
	      /* auto limits case : scan Buffer within limits and store in Mon2D */ 
	      for (i = 1; i <= Vars.Coord_Number; i++)
	      {
		/* scanning variables in Buffer */
		XY = (Vars.Coord_Max[i]-Vars.Coord_Min[i]);
		Coord[i] = Mon2D_Buffer[While_Buffer*(Vars.Coord_Number+2) + (i-1)];
		Coord[0] = Mon2D_Buffer[While_Buffer*(Vars.Coord_Number+2) + (Vars.Coord_Number)];
		pp = Coord[0];
		if (XY > 0) Coord_Index[i] = floor((Mon2D_Buffer[(i-1) + While_Buffer*(Vars.Coord_Number+2)]-Vars.Coord_Min[i])*Vars.Coord_Bin[i]/XY);
		else Coord_Index[i] = 0;
		if (Vars.Flag_With_Borders)
		{
		  if (Coord_Index[i] < 0) Coord_Index[i] = 0;
		  if (Coord_Index[i] >= Vars.Coord_Bin[i]) Coord_Index[i] = Vars.Coord_Bin[i] - 1;
		}
	      } /* end for */
	      While_Buffer++;
	    } /* end if in Buffer */
	    else /* (While_Buffer >= Vars.Buffer_Block) && (Vars.Flag_Auto_Limits == 2) */ 
	    {
	      Vars.Flag_Auto_Limits = 0;
	      if (!Vars.Flag_List) /* free Buffer not needed (no list to output) */
	      { /* Dim : (Vars.Coord_Number+2)*Vars.Buffer_Block matrix (for p, dp) */ 
		free(Mon2D_Buffer);
	      }
	    }
	  }
	  else /* Vars.Flag_Auto_Limits == 0 or 1 */
	  {
	    for (i = 0; i <= Vars.Coord_Number; i++)
	    { /* handle current neutron : last while */

	      pp = Vars.cp;

	      XY = 0;
              Set_Vars_Coord_Type = Vars.Coord_Type[i];
              if (Set_Vars_Coord_Type == DEFS.COORD_X) XY = Vars.cx; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_Y) XY = Vars.cy; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_Z) XY = Vars.cz; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_VX) XY = Vars.cvx; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_VY) XY = Vars.cvy; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_VZ) XY = Vars.cvz; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_KX) XY = V2K*Vars.cvx; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_KY) XY = V2K*Vars.cvy; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_KZ) XY = V2K*Vars.cvz; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_SX) XY = Vars.csx; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_SY) XY = Vars.csy; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_SZ) XY = Vars.csz; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_T) XY = Vars.ct; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_P) XY = pp; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_HDIV) XY = RAD2DEG*atan2(Vars.cvx,Vars.cvz); 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_VDIV) XY = RAD2DEG*atan2(Vars.cvy,Vars.cvz); 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_V) XY = sqrt(Vars.cvx*Vars.cvx+Vars.cvy*Vars.cvy+Vars.cvz*Vars.cvz); 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_RADIUS) XY = sqrt(Vars.cx*Vars.cx+Vars.cy*Vars.cy); 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_K) { XY = sqrt(Vars.cvx*Vars.cvx+Vars.cvy*Vars.cvy+Vars.cvz*Vars.cvz);  XY *= V2K; }
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_ENERGY) { XY = Vars.cvx*Vars.cvx+Vars.cvy*Vars.cvy+Vars.cvz*Vars.cvz;  XY *= VS2E; }
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_LAMBDA) { XY = sqrt(Vars.cvx*Vars.cvx+Vars.cvy*Vars.cvy+Vars.cvz*Vars.cvz);  XY *= V2K; if (XY != 0) XY = 2*PI/XY; }
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_NCOUNT) XY = Coord[i]+1; 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_ANGLE) 
	      {  XY = sqrt(Vars.cvx*Vars.cvx+Vars.cvy*Vars.cvy+Vars.cvz*Vars.cvz);
		if (Vars.cvz != 0) 
		{
		  XY= RAD2DEG*atan2(XY,Vars.cvz);
		} else XY = 0;
	      }
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_THETA)  { if (Vars.cz != 0) XY = RAD2DEG*atan2(Vars.cx,Vars.cz); } 
              else
	      if (Set_Vars_Coord_Type == DEFS.COORD_PHI) { if (Vars.cz != 0) XY = RAD2DEG*atan2(Vars.cy,Vars.cz); } 
              else
              if (Set_Vars_Coord_Type == DEFS.COORD_USER1) XY = Vars.UserVariable1;
              else
              if (Set_Vars_Coord_Type == DEFS.COORD_USER2) XY = Vars.UserVariable2;
              else
		XY = 0;
                  
	      Coord[i] = XY;
	      if (!Vars.Flag_Auto_Limits)
              
	      {
		XY = (Vars.Coord_Max[i]-Vars.Coord_Min[i]);
		if (XY > 0) Coord_Index[i] = floor((Coord[i]-Vars.Coord_Min[i])*Vars.Coord_Bin[i]/XY);
		else Coord_Index[i] = 0;
		if (Vars.Flag_With_Borders)
		{
		  if (Coord_Index[i] < 0) Coord_Index[i] = 0;
		  if (Coord_Index[i] >= Vars.Coord_Bin[i]) Coord_Index[i] = Vars.Coord_Bin[i] - 1;
		}
	      } /* else Auto_Limits will get Index later from Buffer */
	    } /* end for i */
	    While_End = 1;

	  } /* end else if Vars.Flag_Auto_Limits == 2 */
	   

	  if (Vars.Flag_Auto_Limits != 2) /* not when reading auto limits Buffer */
	  { /* now store Coord into Buffer (no index needed) if necessary */
	    if ((Vars.Buffer_Counter < Vars.Buffer_Block) && ((Vars.Flag_List) || (Vars.Flag_Auto_Limits == 1)))
	    {
	      for (i = 0; i < Vars.Coord_Number; i++)
	      {
        	Mon2D_Buffer[i + Vars.Neutron_Counter*(Vars.Coord_Number+2)] = Coord[i+1];
	      }
	      Mon2D_Buffer[Vars.Coord_Number + Vars.Neutron_Counter*(Vars.Coord_Number+2)]   = pp;
	      Mon2D_Buffer[(Vars.Coord_Number+1) + Vars.Neutron_Counter*(Vars.Coord_Number+2)] = pp*pp;
	      Vars.Buffer_Counter++;
	      if (Vars.Flag_Verbose && (Vars.Buffer_Counter >= Vars.Buffer_Block) && (Vars.Flag_List == 1)) printf("Monitor_nD: %s %li neutrons stored in List.\n", mccompcurname, Vars.Buffer_Counter);
	    }
	    Vars.Neutron_Counter++;
	  } /* end (Vars.Flag_Auto_Limits != 2) */

	  /* store n1d/2d section for Buffer or current neutron in while */
	  
	  if (Vars.Flag_Auto_Limits != 1) /* not when storing auto limits Buffer */
	  {
	  /* 1D and n1D case : Vars.Flag_Multiple */
	    if (Vars.Flag_Multiple)
	    { /* Dim : Vars.Coord_Number*Vars.Coord_Bin[i] vectors (intensity is not included) */ 
	      for (i= 0; i < Vars.Coord_Number; i++)
	      {
		j = Coord_Index[i+1];
		if (j >= 0 && j < Vars.Coord_Bin[i+1])
		{
		  Mon2D_N[i][j]++;
        	  Mon2D_p[i][j] += pp;
        	  Mon2D_p2[i][j] += pp*pp;
		}
	      }
	    }
	    else /* 2D case : Vars.Coord_Number==2 and !Vars.Flag_Multiple and !Vars.Flag_List */
            if ((Vars.Coord_Number == 2) && !Vars.Flag_Multiple)
            { /* Dim : Vars.Coord_Bin[1]*Vars.Coord_Bin[2] matrix */
	      i = Coord_Index[1];
	      j = Coord_Index[2];
	      if (i >= 0 && i < Vars.Coord_Bin[1] && j >= 0 && j < Vars.Coord_Bin[2])
	      {
		Mon2D_N[i][j]++;
        	Mon2D_p[i][j] += pp;
        	Mon2D_p2[i][j] += pp*pp;
	      }
	    }
	  } /* end (Vars.Flag_Auto_Limits != 1) */
	} /* end while */
      } /* end if Vars.Coord_Number */
    } /* end if intersection */
    else if (Vars.Flag_Absorb) ABSORB;
 %}
 
FINALLY
 %{
    char   *fname;
    long     i,j;
    int    *p0m = NULL;
    double *p1m = NULL;
    double *p2m = NULL;
    char    Coord_X_Label[1024];
    double  min1d, max1d; 
    double  min2d, max2d;
    int     bin1d, bin2d;
    char    While_End = 0;
    long    While_Buffer = 0;
    double  XY, pp;
    double  Coord[MONnD_COORD_NMAX];
    long    Coord_Index[MONnD_COORD_NMAX];

    /* check Buffer flush when end of simulation reached */
    if ((Vars.Buffer_Counter < Vars.Buffer_Block) && Vars.Flag_Auto_Limits)
    {
      /* Get Auto Limits */
      if (Vars.Flag_Verbose) printf("Monitor_nD: %s getting %i Auto Limits from List (%li).\n", mccompcurname, Vars.Coord_Number, Vars.Buffer_Counter);
      for (i = 1; i <= Vars.Coord_Number; i++)
      {
        Vars.Coord_Min[i] = FLT_MAX;
	Vars.Coord_Max[i] = -FLT_MAX;
        
	for (j = 0; j < Vars.Buffer_Counter; j++)
	{ 
          XY = Mon2D_Buffer[j*(Vars.Coord_Number+2) + (i-1)];	/* scanning variables in Buffer */
	  if (XY < Vars.Coord_Min[i]) Vars.Coord_Min[i] = XY;
	  if (XY > Vars.Coord_Max[i]) Vars.Coord_Max[i] = XY;
          
	}
      }
      Vars.Flag_Auto_Limits = 2;	/* pass to 2nd auto limits step */
      Vars.Buffer_Block = Vars.Buffer_Counter;
	  
      while (!While_End)
      { /* we generate Coord[] and Coord_index[] from Buffer (auto limits) or passing neutron */
	if (While_Buffer < Vars.Buffer_Block)
	{
	  /* first while loops (While_Buffer) */
	  /* auto limits case : scan Buffer within limits and store in Mon2D */ 
	  for (i = 1; i <= Vars.Coord_Number; i++)
	  {
	    /* scanning variables in Buffer */
	    XY = (Vars.Coord_Max[i]-Vars.Coord_Min[i]);
	    Coord[i] = Mon2D_Buffer[While_Buffer*(Vars.Coord_Number+2) + (i-1)];
	    Coord[0] = Mon2D_Buffer[While_Buffer*(Vars.Coord_Number+2) + (Vars.Coord_Number)];
	    pp = Coord[0];
	    if (XY > 0) Coord_Index[i] = floor((Mon2D_Buffer[(i-1) + While_Buffer*(Vars.Coord_Number+2)]-Vars.Coord_Min[i])*Vars.Coord_Bin[i]/XY);
	    else Coord_Index[i] = 0;
	    if (Vars.Flag_With_Borders)
	    {
	      if (Coord_Index[i] < 0) Coord_Index[i] = 0;
	      if (Coord_Index[i] >= Vars.Coord_Bin[i]) Coord_Index[i] = Vars.Coord_Bin[i] - 1;
	    }
	  } /* end for */
	  While_Buffer++;
	} /* end if in Buffer */
	else /* (While_Buffer >= Vars.Buffer_Block) && (Vars.Flag_Auto_Limits == 2) */ 
	{
	  Vars.Flag_Auto_Limits = 0;
	  While_End = 1;
	  if (!Vars.Flag_List) /* free Buffer not needed (no list to output) */
	  { /* Dim : (Vars.Coord_Number+2)*Vars.Buffer_Block matrix (for p, dp) */ 
	    free(Mon2D_Buffer);
	  }
	}

	/* store n1d/2d section from Buffer */

	/* 1D and n1D case : Vars.Flag_Multiple */
	if (Vars.Flag_Multiple)
	{ /* Dim : Vars.Coord_Number*Vars.Coord_Bin[i] vectors (intensity is not included) */ 
	  for (i= 0; i < Vars.Coord_Number; i++)
	  {
	    j = Coord_Index[i+1];
	    if (j >= 0 && j < Vars.Coord_Bin[i+1])
	    {
	      Mon2D_N[i][j]++;
              Mon2D_p[i][j] += pp;
              Mon2D_p2[i][j] += pp*pp;
	    }
	  }
	}
	else /* 2D case : Vars.Coord_Number==2 and !Vars.Flag_Multiple and !Vars.Flag_List */
        if ((Vars.Coord_Number == 2) && !Vars.Flag_Multiple)
        { /* Dim : Vars.Coord_Bin[1]*Vars.Coord_Bin[2] matrix */
	  i = Coord_Index[1];
	  j = Coord_Index[2];
	  if (i >= 0 && i < Vars.Coord_Bin[1] && j >= 0 && j < Vars.Coord_Bin[2])
	  {
	    Mon2D_N[i][j]++;
            Mon2D_p[i][j] += pp;
            Mon2D_p2[i][j] += pp*pp;
	  }
	} /* end store 2D/1D */
      } /* end while */
    } /* end Force Get Limits */

    if (Vars.Flag_Verbose) 
    {
      printf("Monitor_nD: %s is a %s.\n", mccompcurname, Vars.Monitor_Label);
      printf("Monitor_nD: with options=%s\n", options);
    }

    /* write oputput files (sent to file as p[i*n + j] vectors) */
    if (Vars.Coord_Number == 0) 
    {
      DETECTOR_OUT_0D(Vars.Monitor_Label, Nsum, psum, p2sum);
    }
    else
    if (strlen(Vars.Mon_File) > 0) 
    { 
      fname = (char*)malloc(strlen(Vars.Mon_File)+10*Vars.Coord_Number);
      if (Vars.Flag_List) /* List */
      {
	if (Vars.Flag_List == 2) Vars.Buffer_Size = Vars.Neutron_Counter;
	strcpy(fname,Vars.Mon_File);
	if (strchr(Vars.Mon_File,'.') == NULL) strcat(fname, "_list");

	min1d = 1; max1d = Vars.Coord_Number+2;
	min2d = 0; max2d = Vars.Buffer_Size; 
	bin1d = Vars.Coord_Number+2; bin2d = Vars.Buffer_Size;
	strcpy(Coord_X_Label,"");
	for (i= 1; i <= Vars.Coord_Number; i++)
	{
	  if (min2d < Vars.Coord_Min[i]) min2d = Vars.Coord_Min[i];
	  if (max2d < Vars.Coord_Max[i]) max2d = Vars.Coord_Max[i];
	  strcat(Coord_X_Label, Vars.Coord_Var[i]);
	  strcat(Coord_X_Label, " ");
	  if (strchr(Vars.Mon_File,'.') == NULL)
            { strcat(fname, "."); strcat(fname, Vars.Coord_Var[i]); }
	}
	strcat(Coord_X_Label, "I I_err");
	if (Vars.Flag_Verbose) printf("Monitor_nD: %s write monitor file %s List (%ix%li).\n", mccompcurname, fname,(Vars.Coord_Number+2),Vars.Buffer_Size);
	p0m = (int *)malloc((Vars.Coord_Number+2)*Vars.Buffer_Size*sizeof(int));
	p1m = (double *)malloc((Vars.Coord_Number+2)*Vars.Buffer_Size*sizeof(double));
        if (min2d == max2d) max2d = min2d+1e-6;
        if (min1d == max1d) max1d = min1d+1e-6;
	if (p1m == NULL) /* use Raw Buffer line output */
	{
	  if (Vars.Flag_Verbose) printf("Monitor_nD: %s cannot allocate memory for transpose. Skipping.\n", mccompcurname);
	  if (p0m != NULL) free(p0m);
	  DETECTOR_OUT_2D(
            Vars.Monitor_Label,
            Vars.Coord_Label[0],
	    Coord_X_Label,
            min2d, max2d, 
	    min1d, max1d, 
	    bin2d,
	    bin1d,
            (int *)Mon2D_Buffer,Mon2D_Buffer,Mon2D_Buffer,
            fname); 
	}
	else /* transpose for column output */
	{
	  for (i=0; i < Vars.Coord_Number+2; i++) 
	    for (j=0; j < Vars.Buffer_Size; j++)
	    {
	      p1m[i*Vars.Buffer_Size+j] = Mon2D_Buffer[j*(Vars.Coord_Number+2) + i];
	      p0m[i*Vars.Buffer_Size+j] = 1;
	    }
	    DETECTOR_OUT_2D(
              Vars.Monitor_Label,
	      Coord_X_Label,
	      Vars.Coord_Label[0],
              min1d, max1d, 
	      min2d, max2d, 
	      bin1d,
	      bin2d,
              p0m,p1m,Mon2D_Buffer,
              fname); 
	  free(p0m);
	  free(p1m);
	}
      }
      if (Vars.Flag_Multiple) /* n1D */
      {
	for (i= 0; i < Vars.Coord_Number; i++)
	{
	  strcpy(fname,Vars.Mon_File);
	  if (strchr(Vars.Mon_File,'.') == NULL)
            { strcat(fname, "."); strcat(fname, Vars.Coord_Var[i+1]); }
	  sprintf(Coord_X_Label, "%s monitor", Vars.Coord_Label[i+1]);
	  if (Vars.Flag_Verbose) printf("Monitor_nD: %s write monitor file %s 1D (%i).\n", mccompcurname, fname, Vars.Coord_Bin[i+1]);
          min1d = Vars.Coord_Min[i+1];
          max1d = Vars.Coord_Max[i+1];
          if (min1d == max1d) max1d = min1d+1e-6;
	  DETECTOR_OUT_1D(
            Coord_X_Label,
            Vars.Coord_Label[i+1],
            Vars.Coord_Label[0],
	    Vars.Coord_Var[i+1],
            min1d, max1d, 
	    Vars.Coord_Bin[i+1],
            Mon2D_N[i],Mon2D_p[i],Mon2D_p2[i],
            fname); 
	}
      }
      else
      if (Vars.Coord_Number == 2)	/* 2D */
      {
        strcpy(fname,Vars.Mon_File);

	p0m = (int *)malloc(Vars.Coord_Bin[1]*Vars.Coord_Bin[2]*sizeof(int));
	p1m = (double *)malloc(Vars.Coord_Bin[1]*Vars.Coord_Bin[2]*sizeof(double));
	p2m = (double *)malloc(Vars.Coord_Bin[1]*Vars.Coord_Bin[2]*sizeof(double));

	if (p2m == NULL) 
	{
	  if (Vars.Flag_Verbose) printf("Monitor_nD: %s cannot allocate memory for 2D array (%i). Skipping.\n", mccompcurname, 3*Vars.Coord_Bin[1]*Vars.Coord_Bin[2]*sizeof(double));
	  if (p0m != NULL) free(p0m);
	  if (p1m != NULL) free(p1m);
	}
	else
	{
	  for (i= 0; i < Vars.Coord_Bin[1]; i++)
	  {
	    for (j= 0; j < Vars.Coord_Bin[2]; j++)
	    {
	      p0m[j + i*Vars.Coord_Bin[2]] = Mon2D_N[i][j];
	      p1m[j + i*Vars.Coord_Bin[2]] = Mon2D_p[i][j];
	      p2m[j + i*Vars.Coord_Bin[2]] = Mon2D_p2[i][j];
	    }
	  }
	  if (strchr(Vars.Mon_File,'.') == NULL)
            { strcat(fname, "."); strcat(fname, Vars.Coord_Var[1]);
	      strcat(fname, "_"); strcat(fname, Vars.Coord_Var[2]); }
	  if (Vars.Flag_Verbose) printf("Monitor_nD: %s write monitor file %s 2D (%ix%i).\n", mccompcurname, fname, Vars.Coord_Bin[1], Vars.Coord_Bin[2]);
	  
	  min1d = Vars.Coord_Min[1];
          max1d = Vars.Coord_Max[1];
          if (min1d == max1d) max1d = min1d+1e-6;
          min2d = Vars.Coord_Min[2];
          max2d = Vars.Coord_Max[2];
          if (min2d == max2d) max2d = min2d+1e-6;
          DETECTOR_OUT_2D(
              Vars.Monitor_Label,
	      Vars.Coord_Label[1],
	      Vars.Coord_Label[2],
              min1d, max1d,  
	      min2d, max2d,  
	      Vars.Coord_Bin[1],
	      Vars.Coord_Bin[2],
              p0m,p1m,p2m,
              fname); 

          if (p0m != NULL) free(p0m);
	  if (p1m != NULL) free(p1m);
	  if (p2m != NULL) free(p2m); 
	}
      }
      free(fname);
    }

    /* Now Free memory Mon2D.. */
    if ((Vars.Flag_Auto_Limits || Vars.Flag_List) && Vars.Coord_Number)
    { /* Dim : (Vars.Coord_Number+2)*Vars.Buffer_Block matrix (for p, dp) */ 
      if (Mon2D_Buffer != NULL) free(Mon2D_Buffer);
    }
       
    /* 1D and n1D case : Vars.Flag_Multiple */
    if (Vars.Flag_Multiple && Vars.Coord_Number)
    { /* Dim : Vars.Coord_Number*Vars.Coord_Bin[i] vectors */ 
      for (i= 0; i < Vars.Coord_Number; i++)
      { 
        free(Mon2D_N[i]);
        free(Mon2D_p[i]);
        free(Mon2D_p2[i]);
      }
      free(Mon2D_N);
      free(Mon2D_p);
      free(Mon2D_p2);
    }
    

    /* 2D case : Vars.Coord_Number==2 and !Vars.Flag_Multiple and !Vars.Flag_List */
    if ((Vars.Coord_Number == 2) && !Vars.Flag_Multiple)
    { /* Dim : Vars.Coord_Bin[1]*Vars.Coord_Bin[2] matrix */
      for (i= 0; i < Vars.Coord_Bin[1]; i++)
      { 
        free(Mon2D_N[i]);
        free(Mon2D_p[i]);
        free(Mon2D_p2[i]);
      }
      free(Mon2D_N); 
      free(Mon2D_p);
      free(Mon2D_p2);
    }
%}

MCDISPLAY
%{
  double radius, h;
  
  radius = Vars.Sphere_Radius;
  h = Vars.Cylinder_Height;
  
  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE)
  {
    magnify("");
    circle("xy",0,0,0,radius);
    circle("xz",0,0,0,radius);
    circle("yz",0,0,0,radius);
  }
  else
  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_DISK)
  {
    magnify("");
    circle("xy",0,0,0,radius);
  }
  else
  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SQUARE)
  {
    magnify("xy");
    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);
  }
  else
  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND)
  {
    magnify("xyz");
    circle("xz", 0,  h/2.0, 0, radius);
    circle("xz", 0, -h/2.0, 0, radius);
    line(-radius, -h/2.0, 0, -radius, +h/2.0, 0);
    line(+radius, -h/2.0, 0, +radius, +h/2.0, 0);
    line(0, -h/2.0, -radius, 0, +h/2.0, -radius);
    line(0, -h/2.0, +radius, 0, +h/2.0, +radius);
  }
%}

END
/*******************************************************************************
*
* Component: PreMonitor_nD
*
* %Identification
* Written by: <a href="mailto:farhi@ill.fr">Emmanuel Farhi</a>
* Date: 01st Feb 2001.
* Origin: <a href="http://www.ill.fr">ILL (France)</a>
* Version: 0.1
*
* This component is a PreMonitor that is to be used with one Monitor_nD, in
* order to record some neutron parameters 

* 
*
* %Description
* Neutron parameters are stored when passing in the PreMonitor. 
* If this neutron then reaches the associated Monitor_nD, this latter component
* will measure the previously stored parameters. This enables to study
* correlations between a given parameter in one place of the instrument
* and an other position in the instrument.
*
* <b>EXAMPLES:</b>
* Here follows a Phase-Space diagram detector (used for guides for instance)
*
*  MyPreMonitor = PreMonitor_nD(
*   comp = MyMonitor)
*
* (... for instance a Guide ...)
*
* MyMonitor = Monitor_nD(
*   xmin = -0.1, xmax = 0.1,
*   ymin = -0.1, ymax = 0.1,
*   options = "hdiv x, auto limits, use premonitor");
*
* %Parameters
* INPUT PARAMETERS:
*
* comp: name of the associated Monitor_nD where the detection should take place
*
* OUTPUT PARAMETERS:
*
* %Link 
* <a href="http://www.ill.fr/tas/mcstas/">McStas at ILL</a>
* <a href="Monitor_nD.html">Monitor_nD</a>
*
* %End
*******************************************************************************/

DEFINE COMPONENT PreMonitor_nD
DEFINITION PARAMETERS (comp)
SETTING PARAMETERS ()
STATE PARAMETERS (x,y,z,vx,vy,vz,t,s1,s2,p)
POLARISATION PARAMETERS (sx,sy,sz)

/* Flag will be set to 1 automatically */
/* unset by user in Monitor_nD if required (with 'not') */
/* Monitor_nD with premonitor should check that a PreMonitor exists */
/* if Flag==0 in option parsing -> no pre monitor -> warning, normal monitor */

DECLARE
%{
%}

INITIALIZE
%{
    
%}

TRACE
%{ 
    struct MonitornD_Variables *Vars = &(MC_GETPAR(comp, Vars));
    
    
    PROP_Z0; 
    
    if (Vars->Flag_UsePreMonitor == 1)
    {
        Vars->cp = p;
        Vars->cx = x;
        Vars->cvx = vx;
        Vars->csx = sx;
        Vars->cy = y;
        Vars->cvy = vy;
        Vars->csy = sy;
        Vars->cz = z;
        Vars->cvz = vz;
        Vars->csz = sz;
        Vars->ct = t;
    }
%}
  

MCDISPLAY
%{
  /* A bit ugly; hard-coded dimensions. 0.1 m */
  magnify("");
  line(0,0,0,0.1,0,0);
  line(0,0,0,0,0.1,0);
  line(0,0,0,0,0,0.1);
%}

END