/*******************************************************************************
*
* McStas, the neutron ray-tracing package: Vitess_input.comp
*         Copyright (C) 1997-2006 Risoe National Laboratory, Roskilde, Denmark
*
* Component: Vitess_input
*
* %I
* Written by: Kristian Nielsen
* Date: June 6, 2000
* Version: $Revision: 1.19 $
* Origin: McStas 1.5.0
* Release: McStas 1.9.1
* Modified by: E. Farhi, Sep 28th, 2001: added spin
*
* Read neutron state parameters from VITESS neutron file.
*
* %D
* Source-like component reading neutron state parameters from a
* VITESS neutron file. Used to interface McStas components or
* simulations into VITESS. Each neutron is 104 bytes.
*
* Example: Vitess_input(file="MySource.vit", bufsize = 10000, repeat_count = 2)
*
* %P
* INPUT PARAMETERS
*
* file:         Filename of neutron file to read. Default is
*               standard input [string]
* bufsize:      Size of neutron input buffer [records]
* repeat_count: Number of times to repeat each neutron read [1]
*
* OUTPUT PARAMETERS
*
* finished:     Set to 1 when the last neutron has been read [int]
*
* %E
*******************************************************************************/


DEFINE COMPONENT Vitess_input
DEFINITION PARAMETERS (file = 0)
SETTING PARAMETERS (int bufsize = 10000, repeat_count = 1)
OUTPUT PARAMETERS (hfile, ibuf, size, pos, rep, finished)
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 input file handle */
Neutron *ibuf;			/* Neutron input buffer */
int size;			/* Number of neutrons currently in buffer */
int pos;			/* Current position in buffer */
int rep;			/* Neutron repeat count */
int finished;			/* Set to 1 when last neutron read */
%}

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

  /* Allocate neutron input buffer. */
  ibuf = calloc(bufsize, sizeof(Neutron));
  if(!ibuf)
  {
    fprintf(stderr, "Vitess_input: Error: Cannot allocate neutron buffer.\n");
    exit(1);
  }
  /* Initialize buffer. */
  size = 0;
  pos = 0;
  rep = 0;
  finished = 0;
%}

TRACE
%{
  if(pos >= size) {
    /* Buffer is empty. */
    size = fread(ibuf, sizeof(Neutron), bufsize, hfile);
    if(size <= 0)
    {
      if(ferror(hfile))
	fprintf(stderr, "Vitess_input: Error during read of neutron file.\n");
      if(feof(hfile) || ferror(hfile))
	finished = 1;		/* End of file or error reached */
    }
    else
    {
      pos = 0;			/* Reposition at start of buffer */
    }
  }
  /* When no more neutron records are available in the neutron file,
     any remaining iterations are skipped by immediately ABSORB'ing
     the neutron. */
  if(finished)
    ABSORB;
  vitess2mcstas(ibuf[pos], &x, &y, &z, &vx, &vy, &vz, &t, &sx, &sy, &sz, &p);
  vitess_col       =      ibuf[pos].Color;
  vitess_ID.IDNo   =      ibuf[pos].ID.IDNo;
  memcpy(vitess_ID.IDGrp, ibuf[pos].ID.IDGrp, 2);

  /* Repeat the same neutron state parameters the required number of
     times. */
  ++rep;
  if(rep >= repeat_count)
  {
    rep = 0;
    ++pos;
  }
%}
FINALLY
%{
  if(ibuf)
    free(ibuf);
  if(hfile && file)
    fclose(hfile);
%}
MCDISPLAY
%{
  /* Invisible component. */
%}

END
