/*******************************************************************************
*
* McStas, the neutron ray-tracing package: Vitess_output.comp
*         Copyright (C) 1997-2006 Risoe National Laboratory, Roskilde, Denmark
*
* Component: Vitess_output
*
* %I
* Written by: Kristian Nielsen
* Date: June 6, 2000
* Version: $Revision: 1.18 $
* Origin: McStas 1.5.0
* Release: McStas 1.9.1
* Modified by: E. Farhi, Sep 28th, 2001: added spin
*
* Write neutron state parameters to VITESS neutron file.
*
* %D
* Detector-like component writing neutron state parameters to a
* VITESS neutron file. Used to interface McStas components or
* simulations into VITESS. Each neutron is 104 bytes.
*
* Note that when standard output is used, as is the default, no
* monitors or other components that produce terminal output must be
* used, or the neutron output from this component will become
* corrupted.
*
* Example: Vitess_output(file="MySource.vit", bufsize = 10000, progress = 1)
*
* %P
* INPUT PARAMETERS
*
* file:     Filename of neutron file to write. Default is standard
*           output [string]
* bufsize:  Size of neutron output buffer [records]
* progress: If not zero, output dots as progress indicator [flag]
*
* %E
*******************************************************************************/


DEFINE COMPONENT Vitess_output
DEFINITION PARAMETERS (file = 0)
SETTING PARAMETERS (int bufsize = 10000, int progress = 0)
OUTPUT PARAMETERS (hfile, obuf, pos, p_out, p2_out)
STATE PARAMETERS (x,y,z,vx,vy,vz,t,s1,s2,p)
POLARISATION PARAMETERS (sx,sy,sz)
SHARE
%{
%include "general"
%include "vitess-lib" 
%}

DECLARE
%{
char *filename;                 /* path + filename             */
FILE *hfile;			/* Neutron output file handle  */
Neutron *obuf;			/* Neutron output buffer       */
int pos;			/* Current position in buffer  */
double p_out;                   /* sum of output weight        */
double p2_out;                  /* square sum of output weight */
%}

INITIALIZE
%{
  /* Open neutron output file. */
  if (file==NULL)
  {
    hfile = stdout;
  }
  else if (!strcmp(file, "no_file"))
  {
    hfile = NULL;
  }
  else
  {
    hfile = fopen((filename=FullParName(file)), "wb");
    if(!hfile)
    {
      fprintf(stderr, "Vitess_output: Error: Cannot open output file %s.\n", filename);
      exit(1);
    }
  }
#ifdef WIN32
  if(hfile==stdout) 
  { if(_setmode(_fileno( stdout ), _O_BINARY ) == -1) 
    { fprintf(stderr,"Can't set stdout to binary mode\n");
      exit(1);
    }
  }
#endif

  /* Allocate neutron output buffer. */
  obuf = calloc(bufsize, sizeof(Neutron));
  if(!obuf)
  {
    fprintf(stderr, "Vitess_output: Error: Cannot allocate neutron buffer.\n");
    exit(1);
  }
  /* Initialize buffer. */
  pos = 0;  
%}

TRACE
%{
  int count;

  /* Flush output buffer if full. */
  if(hfile && pos >= bufsize) 
  { count = fwrite(obuf, sizeof(Neutron), bufsize, hfile);
    if(progress)
    {
      fputc('.', stderr);	/* Output progress indicator. */
      fflush(stderr);
    }
    if(count != bufsize)
    {
      fprintf(stderr, "Vitess_output: Error during write of neutron file.\n");
      exit(1);
    }
    else
    {
      pos = 0;			/* Reposition at start of buffer */
    }
  }
  obuf[pos] = mcstas2vitess(x, y, z, vx, vy, vz, t, sx, sy, sz, p);
  obuf[pos].Color   = vitess_col;
  obuf[pos].ID.IDNo = vitess_ID.IDNo;     
  memcpy(obuf[pos].ID.IDGrp, vitess_ID.IDGrp, 2);

  p_out  += p;
  p2_out += p*p;
  ++pos;
%}
FINALLY
%{
  int count;

  /* Flush output buffer if necessary. */
  if(hfile && pos > 0)
  { count = fwrite(obuf, sizeof(Neutron), pos, hfile);
    if(count != pos)
    {
      fprintf(stderr, "Vitess_output: Error during write of neutron file.\n");
      exit(1);
    }
  }
  if(progress)
    fprintf(stderr, ".\n");	/* Output final progress indicator. */
  if(obuf)
    free(obuf);
  if(hfile && file)
    fclose(hfile);
%}
MCDISPLAY
%{
  /* Invisible component. */
%}

END
