/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2007, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
* Component: Virtual_output
*
* %I
* Written by: <a href="mailto:farhi@ill.fr">E. Farhi</a>
* Date: Dec 17th, 2002
* Origin: <a href="http://www.ill.fr">ILL</a>
* Modified by: E. Farhi, Dec 17th, 2002: based on Vitess_output and Monitor_nD lib.
*
* Detector-like component that writes neutron state parameters into an ascci-format
* 'virtual source' neutron file.
*
* %D
* Detector-like component writing neutron state parameters to a
* virtual source neutron filename. The component geometry is the full
* plane, and saves the neutron state as it exits from the previous
* component.
*
*   It is particularly useful to generate a virtual source at a point that few
* neutron reach. A long simulation will then only be performed once, to create
* the upstream 'source' file. Further simulations are much faster if they start
* from this low flux position with the 'source' filename.
*
* The output file format is:
* text column formatted with lines containing 11 values in the order:
*       p x y z vx vy vz t sx sy sz stored into about 83 bytes/n.
*
* Beware the size of generated files ! When saving all events (bufsize=0) the
* required memory has been optimized and remains very small. On the other hand
* using large bufsize values (not recommended) requires huge storage memory.
* Moreover, using the 'bufsize' parameter will often lead to wrong intensities.
* Both methods will generate huge files.
*
* A Vitess file may be obtained from the 'Vitess_output' component or from a
* Vitess simulation (104 bytes per neutron) and read with Vitess_input.
*
* Example: Virtual_output(filename="MySource.dat")
*   will generate a 9 Mo text file for 1e5 events stored.
*
* %BUGS
* Using bufsize non-zero may generate a virtual source with wrong intensity. This
* component works with MPI (parallel execution mode).
*
* %P
* INPUT PARAMETERS
*
* filename: [str]  Name of neutron file to write. Default is standard output [string]. If not given, a unique name will be used.
* bufsize: [1]     Size of neutron output buffer default is 0, i.e. save all - recommended.
*
* %E
*******************************************************************************/


DEFINE COMPONENT Virtual_output
DEFINITION PARAMETERS ()
SETTING PARAMETERS (string filename=0, bufsize=0)
OUTPUT PARAMETERS ()
/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */
NOACC

SHARE
%{
%include "monitor_nd-lib"
%}

DECLARE
%{
  MonitornD_Defines_type DEFS;
  MonitornD_Variables_type Vars;
%}

INITIALIZE
%{

  long element_size=85; /* mean size per neutron for ascii storing */

  strcpy(Vars.compcurname, NAME_CURRENT_COMP);

  if (bufsize > 0) sprintf(Vars.option, "list=%g borders", bufsize);
  else strcpy(Vars.option, "list all borders");

  strcat(Vars.option,", x y z vx vy vz t sx sy sz");
  Monitor_nD_Init(&DEFS, &Vars, 0.1, 0.1, 0, 0,0,0,0,0,0,0); /* dims for mcdisplay */
  Vars.compcurpos = POS_A_CURRENT_COMP;

  if (filename && strlen(filename) && strcmp(filename,"NULL") && strcmp(filename,"0"))
    strncpy(Vars.Mon_File, filename, 128);

  if (bufsize > 0)
    printf("Warning: Virtual_output: %s: buffer size=%g not recommended\n", NAME_CURRENT_COMP, bufsize);
  if (bufsize > 0) printf(
           "Virtual_output: %s: Beware virtual output generated file size (max %g Mo)\n"
           "WARNING         Memory required is %g Mo\n", NAME_CURRENT_COMP,
           bufsize*element_size/1e6, bufsize*sizeof(double)/1e6);
%}

TRACE
%{
  double pp=0;

  /* PROP_Z0; */
  /* transfer current neutron to Monitor_nD vars */
  /* 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 = Monitor_nD_Trace(&DEFS, &Vars, _particle);

  SCATTER;
%}

SAVE
%{

  Monitor_nD_Save(&DEFS, &Vars);

%}

FINALLY
%{
  /* free pointers */
  Monitor_nD_Finally(&DEFS, &Vars);
  if (bufsize) {
    printf("Virtual_output: %s: Saved %llu events (from buffer) in file %s\n",
           NAME_CURRENT_COMP, Vars.Nsum, Vars.Mon_File);
    if (bufsize < Vars.Nsum)
      printf("WARNING         When using this source, intensities must be multiplied\n"
             "                by a factor %g\n", (double)Vars.Nsum/(double)bufsize);
  } else printf("Virtual_output: %s: Saved %llu events (all) in file %s\n", NAME_CURRENT_COMP, Vars.Nsum, Vars.Mon_File);
%}

MCDISPLAY
%{
  Monitor_nD_McDisplay(&DEFS, &Vars);
%}

END
