/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright 1997-2002, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Component: Virtual_tripoli4_output
*
* %I
* Written by: <a href="mailtoguillaume.campioni@cea.fr">Guillaume Campioni</a>
* Date: Sep 28th, 2001
* Origin: <a href="http://www.cea-llb.fr">LLB</a>
*
* Detector-like component that writes neutron state parameters into a
* 'virtual source' neutron file when neutrons come from the source :
* Virtual_tripoli4_input.comp
*
* %D
* Detector-like component writing neutron state parameters to a
* virtual source neutron file when neutron are coming from a
* Virtual_tripoli4_input.comp.
* The component geometry is the full plane, and saves the neutron state as
* it exits from the previous component.
* Format is the one used by TRIPOLI4.4 stock files :
*
*   NEUTRON energy position_X position_Y position_Z dir_X dir_Y dir_Z weight
*
* energy is in [Mega eV]
* positions are in [cm] and the direction vector is normalized to 1.
*
* %BUGS
* This component will NOT work with parallel execution (MPI/GPU).
*
* EXAMPLE:
* To create a file collecting all neutron states with TRIPOLI4 format
*  COMPONENT T4output = Virtual_tripoli4_output(
*    filename = "exit_guide_result.dat", batch = 1 )
*  at the position where will be the Virtual_tripoli4_input when reading the file.
*
* %P
* INPUT PARAMETERS
* filename: [str]                     Name of the Tripoli4 neutron output file,
*                                     or stdout if left to 0.
* batch: [1]                          Index of the Tripoli batch to generate, when no
*                                     Tripoli4_input component is available in instrument.
*
* %L
* <a href="http://www.nea.fr/html/dbprog/tripoli-abs.html">Tripoli</a>
* Virtual_tripoli4_input
*
* %E
*******************************************************************************/

DEFINE COMPONENT Virtual_tripoli4_output
SETTING PARAMETERS (string filename=0, batch=1)

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

DECLARE
%{
  long previous_batch;
  FILE *hfile;
%}

INITIALIZE
%{
  previous_batch=0;
  int i;
  char ** head;
  long nl;

#if defined (USE_MPI) || defined(OPENACC)
  exit(printf("Tripoli4_output: %s: ERROR: "
    "This component can not be used in parallel execution mode (MPI/GPU). Abort.\n", 
    NAME_CURRENT_COMP));
#endif

  /* Open neutron output file. */
  if(filename && strcmp(filename,"NULL") && strcmp(filename,"0") && strcmp(filename,"stdout"))
    hfile = fopen(filename, "w");
  else
    hfile = stdout;
  if(!hfile)
  {
    fprintf(stderr, "Tripoli4_output: %s: Error: Cannot open output file %s.\n", NAME_CURRENT_COMP, (filename && strcmp(filename,"NULL") && strcmp(filename,"0") && strcmp(filename,"stdout") ? filename : "stdout"));
    exit(1);
  }
  fprintf(hfile,"# Tripoli4  batch file %s written by %s\n",
    (filename && strcmp(filename,"NULL") && strcmp(filename,"0") && strcmp(filename,"stdout") ? filename : "stdout"),
    MCCODE_STRING);
  fprintf(hfile,"# Generated by component %s in instrument %s (%s)\n", NAME_CURRENT_COMP, instrument_name, instrument_source);
  fprintf(hfile,"# Format: Tripoli4 data text file with header\n");

  if (batch <= 0)
  {
    fprintf(stderr, "Tripoli4_output: %s: Error: Negative batch number (%d). Using 1.\n", NAME_CURRENT_COMP, (long)batch);
    batch = 1;
  }
  /* generates a default Tripoli 4 header */
  fprintf(hfile,"# Data on the original simulation which generates this file : \n");
  fprintf(hfile,"NB_BATCH   1\n");
  fprintf(hfile,"TAILLE     Unknown\n");
  fprintf(hfile,"PARTICULE  NEUTRON\n");
  fprintf(hfile,"INTENSITE  %g\n",(double)mcget_ncount());
  fprintf(hfile,"SIMULATION PROTECTION\n");
  fprintf(hfile,"Following lines are: type, energy in MeV, position = (x,y,z) in cm, direction = (u,v,w), statistical weight\n");

%}

TRACE
%{
  double Mev2Joule = 1.602e-13;
  double Mneutron  = 1.6749543e-27;
  long   current_batch=0;

  double energy, speed, weight;
  double ux,uy,uz,pos_x,pos_y,pos_z;

  current_batch = batch;

  if (current_batch != previous_batch)
  {
    if (previous_batch == 0) {
      /* write 1st batch header */
      fprintf(hfile,"------------------------------------------------------------------------------------------------------------\n");
      fprintf(hfile, "BEGIN_OF_BATCH  %d\n\n", current_batch);
    } else {
      fprintf(hfile, "\nEND_OF_BATCH  %d\n",   previous_batch);
      fprintf(hfile,"------------------------------------------------------------------------------------------------------------\n");
      fprintf(hfile,"------------------------------------------------------------------------------------------------------------\n");
      fprintf(hfile, "BEGIN_OF_BATCH  %d\n\n", current_batch);
    }
    previous_batch = current_batch;
  }
  /* writes Tripoli file line by line */
  speed = vx*vx + vy*vy + vz*vz;
  energy = speed / 2. * Mneutron / Mev2Joule;

  speed = sqrt(speed);
  ux = vx/speed;
  uy = vy/speed;
  uz = vz/speed;

  pos_x = x * 100.;
  pos_y = y * 100.;
  pos_z = z * 100.;

  weight = p;
//printf("NEUTRON FINAL MC\t%f  %f  %f  %f  %f  %f  %f  %f  %f  %f  %e \n",x,y,z,vx,vy,vz,t,sx,sy,sz,p);
//printf("NEUTRON FINAL TR\t%e \t%f \t%f \t%f \t%f \t%f \t%f \t%e \n", energy, pos_x, pos_y, pos_z, ux, uy, uz, weight);

  fprintf(hfile, "NEUTRON \t%e \t%f \t%f \t%f \t%f \t%f \t%f \t%e \n", energy, pos_x, pos_y, pos_z, ux, uy, uz, weight);

%}

SAVE
%{
  if (hfile) {
    fprintf(hfile, "\nEND_OF_BATCH  %d\n",   previous_batch);
    fprintf(hfile,"------------------------------------------------------------------------------------------------------------\n");
    fflush(hfile);
  }

%}

FINALLY
%{
  if (hfile) fclose(hfile);
%}

END
