/* Automatically generated file. Do not edit. 
 * Format:     ANSI C source code
 * Creator:    McStas <http://neutron.risoe.dk>
 * Instrument: TOFexercise42.instr (TOFexercise42)
 * Date:       Wed Jul 18 14:54:58 2012
 */


#define MCSTAS_VERSION "1.12c - Jun. 03, 2011"
#define MC_USE_DEFAULT_MAIN
#define MC_TRACE_ENABLED
#define MC_EMBEDDED_RUNTIME

#line 1 "mcstas-r.h"
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2011, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Runtime: share/mcstas-r.h
*
* %Identification
* Written by: KN
* Date:    Aug 29, 1997
* Release: McStas X.Y
* Version: $Revision: 1.101 $
*
* Runtime system header for McStas.
*
* In order to use this library as an external library, the following variables
* and macros must be declared (see details in the code)
*
*   struct mcinputtable_struct mcinputtable[];
*   int mcnumipar;
*   char mcinstrument_name[], mcinstrument_source[];
*   int mctraceenabled, mcdefaultmain;
*   extern MCNUM  mccomp_storein[];
*   extern MCNUM  mcAbsorbProp[];
*   extern MCNUM  mcScattered;
*   #define MCSTAS_VERSION "the McStas version"
*
* Usage: Automatically embbeded in the c code.
*
* $Id: mcstas-r.h,v 1.101 2009-04-02 09:47:46 pkwi Exp $
*
*       $Log: mcstas-r.h,v $
*       Revision 1.101  2009-04-02 09:47:46  pkwi
*       Updated runtime and interoff from dev branch (bugfixes etc.)
*
*       Proceeding to test before release
*
*       Revision 1.108  2009/01/23 14:01:12  farhi
*       Back to smaller buffer size for MPI exchange, to ensure that it works on
*       *most* machines.
*
*       Revision 1.107  2009/01/23 10:51:30  farhi
*       Minor speedup: Identity rotation matrices are now checked for and
*       caculations reduced.
*       It seems this McSatsStable commit did not got through for McStas 1.12c
*
*       Revision 1.106  2009/01/15 15:42:44  farhi
*       Saving lists using MPI: must use MPI_Ssend to avoid the buffer max size
*       in MPI1
*
*       Revision 1.105  2008/10/21 15:19:18  farhi
*       use common CHAR_BUFFER_LENGTH = 1024
*
*       Revision 1.104  2008/09/02 08:36:17  farhi
*       MPI support: block size defined in mcstas-r.h as 1e5. Correct bug when
*       p0, p1 or p2 are NULL, and re-enable S(q,w) save in Isotropic_Sqw with
*       MPI.
*
*       Revision 1.103  2008/08/26 13:32:05  farhi
*       Remove Threading support which is poor efficiency and may give wrong
*       results
*       Add quotes around string instrument parameters from mcgui simulation
*       dialog
*
*       Revision 1.102  2008/08/25 14:13:28  farhi
*       changed neutron-mc to mcstas-users
*
*       Revision 1.101  2008/07/17 12:50:18  farhi
*       MAJOR commit to McStas 2.x
*       uniformized parameter naming in components
*       uniformized SITE for instruments
*       all compile OK
*
*       Revision 1.99  2008/04/25 08:26:33  erkn
*       added utility functions/macros for intersecting with a plane and mirroring a vector in a plane
*
*       Revision 1.98  2008/04/21 15:50:19  pkwi
*       Name change randvec_target_rect -> randvec_target_rect_real .
*
*       The renamed routine takes local emmission coordinate into account, correcting for the
*       effects mentioned by George Apostolopoulus <gapost@ipta.demokritos.gr> to the
*       mcstas-users list (parameter list extended by four parms).
*
*       For backward-compatibility, a define has been added that maps randvec_target_rect
*       to the new routine, defaulting to the "old" behaviour.
*
*       To make any use of these modifications, we need to correct all (or all relevant) comps
*       that have calls to randvec_target_rect.
*
*       Will supply a small doc with plots showing that we now correct for the effect pointed
*       out by George.
*
*       Similar change should in principle happen to the _sphere focusing routine.
*
*       Revision 1.97  2008/02/10 20:55:53  farhi
*       OpenMP number of nodes now set properly from either --threads=NB or
*       --threads which sets the computer core nb.
*
*       Revision 1.96  2008/02/10 15:12:56  farhi
*       mcgui: save log when File/Quit
*       mcrun/mcgui: OpenMP now uses the specified number of nodes
*       mcstas-r: number of OpenMP nodes can be set by user. If left at default
*       (--threads), then use omp_get_num_threads. This may be inaccurate on some systems..
*
*       Revision 1.95  2008/02/09 22:26:27  farhi
*       Major contrib for clusters/multi-core: OpenMP support
*       	try ./configure --with-cc=gcc4.2 or icc
*       then mcrun --threads ...
*       Also tidy-up configure. Made relevant changes to mcrun/mcgui to enable OpenMP
*       Updated install-doc accordingly
*
*       Revision 1.94  2007/08/09 16:47:34  farhi
*       Solved old gcc compilation issue when using macros in macros.
*       Solved MPI issuie when exiting in the middle of a simulation. Now use MPI_Abort.
*
*       Revision 1.93  2007/05/29 14:57:56  farhi
*       New rand function to shoot on a triangular distribution. Useful to simulate chopper time spread.
*
*       Revision 1.92  2007/02/01 15:49:45  pkwi
*       For some instruments (e.g. h8) , it seems that <sys/stat.h> is needed to compile on Mac OS X (like FreeBSD)
*
*       Added define to include this.
*
*       Revision 1.91  2007/01/29 15:51:56  farhi
*       mcstas-r: avoid undef of USE_NEXUS as napi is importer afterwards
*
*       Revision 1.90  2007/01/25 14:57:36  farhi
*       NeXus output now supports MPI. Each node writes a data set in the NXdata
*       group. Uses compression LZW (may be unactivated with the
*       -DUSE_NEXUS_FLAT).
*
*       Revision 1.89  2007/01/23 00:41:05  pkwi
*       Edits by Jiao Lin (linjao@caltech.edu) for embedding McStas in the DANSE project. Define -DDANSE during compile will enable these edits.
*
*       Have tested that McStas works properly without the -DDANSE.
*
*       Jiao: Could you please test if all is now OK?
*       (After 15 minutes) Get current CVS tarball from http://www.mcstas.org/cvs
*
*       Revision 1.88  2007/01/22 01:38:25  farhi
*       Improved NeXus/NXdata support. Attributes may not be at the right place
*       yet.
*
*       Revision 1.87  2007/01/21 15:43:08  farhi
*       NeXus support. Draft version (functional). To be tuned.
*
*       Revision 1.86  2006/08/28 10:12:25  pchr
*       Basic infrastructure for spin propagation in magnetic fields.
*
*       Revision 1.85  2006/08/15 12:09:35  pkwi
*       Global define GRAVITY=9.81, used in PROP_ routines and Guide_gravity. Will add handeling of
*
*       -g xx / --gravitation==xx
*
*       in mcstas-r.c at a later time.
*
*       Revision 1.84  2006/08/03 13:11:18  pchr
*       Added additional functions for handling vectors.
*
*       Revision 1.83  2006/07/25 08:49:13  pchr
*       Inserted missing end brackets in routines PROP_X0 and PROP_Y0.
*
*       Revision 1.82  2006/07/06 08:59:21  pchr
*       Added new draw methods for rectangle and box.
*
*       Revision 1.81  2006/05/19 14:17:40  farhi
*       Added support for multi threading with --threads=NB option for mcrun or instr.out
*       Requires new option in mcgui run dialog: a popup menu to select run mode ?
*
*       Revision 1.80  2006/04/05 11:45:05  pkwi
*       Need to include <sys/stat.h> on FreeBSD 6.0 / PC-BSD (maybe also other bsd's?!) for prototype declaration of mkdir call...
*
*       Revision 1.79  2006/03/15 16:00:42  farhi
*       minor modifications (position of FLT_MAX in code)
*
*       Revision 1.78  2005/08/31 08:35:53  farhi
*       MCdisplay now prints component name and position when building view (bug/request 44 closed)
*
*       Revision 1.77  2005/08/24 11:55:12  pkwi
*       Usage of mcallowbackprop flag in all PROP routines. Use in component by e.g.
*
*       ALLOWBACKPROP;
*       PROP_Z0;
*
*       Prop routines disallow backpropagation on exit.
*
*       Revision 1.76  2005/08/24 09:51:31  pkwi
*       Beamstop and runtime modified according to Emmanuels remarks.
*
*       To allow backpropagation in a specific component, use
*
*       ALLOW_BACKPROP;
*
*       before calling
*
*       PROP_Z0;
*
*       (One could consider making the backpropagation flag common to all propagation routines, should we do so?)
*
*       Revision 1.75  2005/08/12 11:23:19  pkwi
*       Special Z0 backpropagation macro defined to allow backpropagation without absorbtion. Needed in Beamstop.comp. We foresee usage elsewhere. Problematic: Duplication of code - can we think of a better way to handle this problem?
*
*       Revision 1.74  2005/07/25 14:55:08  farhi
*       DOC update:
*       checked all parameter [unit] + text to be OK
*       set all versions to CVS Revision
*
*       Revision 1.73  2005/07/18 14:43:05  farhi
*       Now gives a warning message per component for 'computational absorbs'
*
*       Revision 1.72  2005/06/20 08:09:07  farhi
*       Changed all ABSORB by adding mcAbsorbProp incrementation
*       in PROP macros
*
*       Revision 1.71  2005/05/29 09:50:32  pkwi
*       t=0 now allowed in PROP_X0, PROP_Y0, PROP_Z0. As far as I can see, there are no other occurancies of this problem in the propagation routines.
*
*       Fixes bug #43 on BugZilla
*
*       Revision 1.70  2005/02/24 15:57:20  farhi
*       FIXED gravity bug (probably OK). Gravity is not handled properly in other Guide elements. Will adapt so that it works better...
*       The n.v was not computed using the actual 'v' values when reaching the guide side, but before propagation. So the velocity was not reflected, but scattered depending on the previous neutron position/velocity, bringing strange divergence effects.
*       On other guide elements, should update the n.v term just before reflection, not computing it before propagation... This probably holds for some other components (monochromators ???) to be checked !
*
*       Revision 1.69  2005/02/23 12:36:53  farhi
*       Added gravitation support in PROP_X0 and PROP_Y0
*
*       Revision 1.66  2005/02/16 12:21:39  farhi
*       Removed left spaces at end of lines
*
*       Revision 1.65  2005/01/26 14:41:16  farhi
*       Updated constant values from CODATA 2002
*
*       Revision 1.64  2005/01/18 10:32:28  farhi
*       Clarify a macro for MPI
*
*       Revision 1.63  2004/11/30 16:14:47  farhi
*       Uses NOSIGNALS and put back PROP_X0 and Y0 for some contrib comps
*
*       Revision 1.62  2004/09/21 12:25:03  farhi
*       Reorganised code so that I/O functions are includable easely (for mcformat.c)
*
*       Revision 1.59  2004/09/03 14:19:14  farhi
*       Correct invertion in mcformat specs structure
*
*       Revision 1.58  2004/07/30 14:49:15  farhi
*       MPI update for usage with mcrun.
*       Still done by Christophe Taton. CC=mpicc and CFLAGS = -DUSE_MPI.
*       Execute (using mpich) with:
*                 mpirun -np NumNodes -machinefile <file> instr.out parameters...
*            where <file> is text file that lists the machines to use
*
*       Revision 1.57  2004/07/16 14:59:03  farhi
*       MPI support. Requires to have mpi installed, and compile with
*          CC=mpicc and CFLAGS = -DUSE_MPI.
*       Work done by Christophe Taton from ENSIMAG/Grenoble
*       Execute (using mpich) with:
*          mpirun -np NumNodes -machinefile <file> instr.out parameters...
*       where <file> is text file that lists the machines to use
*
*       Revision 1.56  2004/06/30 12:11:29  farhi
*       Updated obsolete MCDETECTOR_OUT #define -> mcdetector_out_0d
*
*       Revision 1.55  2003/10/21 14:08:12  pkwi
*       Rectangular focusing improved: Renamed randvec_target_rect to randvec_target_rect_angular. Wrote new randvec_target_rect routine, w/h in metres. Both routines use use component orientation (ROT_A_CURRENT_COMP) as input.
*
*       Modifications to Res_sample and V_sample to match new features of the runtime.
*
*       Revision 1.54  2003/09/05 08:59:18  farhi
*       added INSTRUMENT parameter default value grammar
*       mcinputtable now has also default values
*       mcreadpar now uses default values if parameter not given
*       extended instr_formal parameter struct
*       extended mcinputtable structure type
*
*       Revision 1.53  2003/04/07 11:50:51  farhi
*       Extended the way mcplot:plotter is assigned. Set --portable ok
*       Handle Scilab:Tk and ~GTk menu (shifted)
*       Updated help in mcrun and mcstas-r.c
*
*       Revision 1.52  2003/04/04 18:20:21  farhi
*       remove some warnings (duplicated decl) for --no-runtime on Dec OSF
*
*       Revision 1.51  2003/04/04 14:27:19  farhi
*       Moved format definitions to mcstas-r.c for --no-runtime to work
*
*       Revision 1.50  2003/02/11 12:28:46  farhi
*       Variouxs bug fixes after tests in the lib directory
*       mcstas_r  : disable output with --no-out.. flag. Fix 1D McStas output
*       read_table:corrected MC_SYS_DIR -> MCSTAS define
*       monitor_nd-lib: fix Log(signal) log(coord)
*       HOPG.trm: reduce 4000 points -> 400 which is enough and faster to resample
*       Progress_bar: precent -> percent parameter
*       CS: ----------------------------------------------------------------------
*
* Revision 1.5 2002/10/19 22:46:21 ef
*        gravitation for all with -g. Various output formats.
*
* Revision 1.4 2002/09/17 12:01:21 ef
*       removed unused macros (PROP_Y0, X0), changed randvec_target_sphere to circle
* added randvec_target_rect
*
* Revision 1.3 2002/08/28 11:36:37 ef
*       Changed to lib/share/c code
*
* Revision 1.2 2001/10/10 11:36:37 ef
*       added signal handler
*
* Revision 1.1 1998/08/29 11:36:37 kn
*       Initial revision
*
*******************************************************************************/

#ifndef MCSTAS_R_H
#define MCSTAS_R_H "$Revision: 1.101 $"

#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>
#include <errno.h>
#include <time.h>
#include <float.h>

/* If the runtime is embedded in the simulation program, some definitions can
   be made static. */

#ifdef MC_EMBEDDED_RUNTIME
#define mcstatic static
#else
#define mcstatic
#endif

#ifdef __dest_os
#if (__dest_os == __mac_os)
#define MAC
#endif
#endif

#ifdef __FreeBSD__
#define NEED_STAT_H
#endif

#if defined(__APPLE__) && defined(__GNUC__)
#define NEED_STAT_H
#endif

#ifdef NEED_STAT_H
#include <sys/stat.h>
#endif

#ifndef MC_PATHSEP_C
#ifdef WIN32
#define MC_PATHSEP_C '\\'
#define MC_PATHSEP_S "\\"
#else  /* !WIN32 */
#ifdef MAC
#define MC_PATHSEP_C ':'
#define MC_PATHSEP_S ":"
#else  /* !MAC */
#define MC_PATHSEP_C '/'
#define MC_PATHSEP_S "/"
#endif /* !MAC */
#endif /* !WIN32 */
#endif /* MC_PATHSEP_C */

#ifndef MCSTAS_VERSION
#define MCSTAS_VERSION "External Run-time"
#endif

#ifdef MC_PORTABLE
#ifndef NOSIGNALS
#define NOSIGNALS
#endif
#endif

#ifdef MAC
#ifndef NOSIGNALS
#define NOSIGNALS
#endif
#endif

#ifdef USE_MPI
#ifndef NOSIGNALS
#define NOSIGNALS
#endif
#endif

#if (USE_NEXUS == 0)
#undef USE_NEXUS
#endif

/* I/O section part ========================================================= */

/* Note: the enum instr_formal_types definition MUST be kept
   synchronized with the one in mcstas.h and with the
   instr_formal_type_names array in cogen.c. */
enum instr_formal_types
  {
    instr_type_double, instr_type_int, instr_type_string
  };
struct mcinputtable_struct {
  char *name; /* name of parameter */
  void *par;  /* pointer to instrument parameter (variable) */
  enum instr_formal_types type;
  char *val;  /* default value */
};

typedef double MCNUM;
typedef struct {MCNUM x, y, z;} Coords;
typedef MCNUM Rotation[3][3];

/* the following variables are defined in the McStas generated C code
   but should be defined externally in case of independent library usage */
#ifndef DANSE
extern struct mcinputtable_struct mcinputtable[];
extern int    mcnumipar;
extern char   mcinstrument_name[], mcinstrument_source[];
extern MCNUM  mccomp_storein[]; /* 11 coords * number of components in instrument */
extern MCNUM  mcAbsorbProp[];
extern MCNUM  mcScattered;
#ifndef MC_ANCIENT_COMPATIBILITY
extern int mctraceenabled, mcdefaultmain;
#endif
#endif

/* file I/O definitions and function prototypes */

struct mcformats_struct {
  char *Name;  /* may also specify: append, partial(hidden), binary */
  char *Extension;
  char *Header;
  char *Footer;
  char *BeginSection;
  char *EndSection;
  char *AssignTag;
  char *BeginData;
  char *EndData;
  char *BeginErrors;
  char *EndErrors;
  char *BeginNcount;
  char *EndNcount;
  };

#ifndef MC_EMBEDDED_RUNTIME /* the mcstatic variables (from mcstas-r.c) */
extern FILE * mcsiminfo_file;
extern int    mcgravitation;
extern int    mcdotrace;
extern struct mcformats_struct mcformats[];
extern struct mcformats_struct mcformat;
extern struct mcformats_struct mcformat_data;
#else
mcstatic FILE *mcsiminfo_file        = NULL;
#endif

/* Useful macros ============================================================ */

#define DETECTOR_OUT(p0,p1,p2) mcdetector_out_0D(NAME_CURRENT_COMP,p0,p1,p2,NAME_CURRENT_COMP,POS_A_CURRENT_COMP)
#define DETECTOR_OUT_0D(t,p0,p1,p2) mcdetector_out_0D(t,p0,p1,p2,NAME_CURRENT_COMP,POS_A_CURRENT_COMP)
#define DETECTOR_OUT_1D(t,xl,yl,xvar,x1,x2,n,p0,p1,p2,f) \
     mcdetector_out_1D(t,xl,yl,xvar,x1,x2,n,p0,p1,p2,f,NAME_CURRENT_COMP,POS_A_CURRENT_COMP)
#define DETECTOR_OUT_2D(t,xl,yl,x1,x2,y1,y2,m,n,p0,p1,p2,f) \
     mcdetector_out_2D(t,xl,yl,x1,x2,y1,y2,m,n,p0,p1,p2,f,NAME_CURRENT_COMP,POS_A_CURRENT_COMP)
#define DETECTOR_OUT_3D(t,xl,yl,zl,xv,yv,zv,x1,x2,y1,y2,z1,z2,m,n,p,p0,p1,p2,f) \
     mcdetector_out_3D(t,xl,yl,zl,xv,yv,zv,x1,x2,y1,y2,z1,z2,m,n,p,p0,p1,p2,f,NAME_CURRENT_COMP,POS_A_CURRENT_COMP)
#define DETECTOR_CUSTOM_HEADER(t)  if (t && strlen(t)) { \
     mcDetectorCustomHeader=malloc(strlen(t)); \
     if (mcDetectorCustomHeader) strcpy(mcDetectorCustomHeader, t); }

#define randvec_target_rect(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9)  randvec_target_rect_real(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,0,0,0,1)

/* MPI stuff ================================================================ */

#ifdef USE_MPI
#include "mpi.h"

/*
 * MPI_MASTER(i):
 * execution of i only on master node
 */
#define MPI_MASTER(statement) { \
  if(mpi_node_rank == mpi_node_root)\
  { statement; } \
}

#ifndef MPI_REDUCE_BLOCKSIZE
#define MPI_REDUCE_BLOCKSIZE 10000
#endif

int mc_MPI_Reduce(void* sbuf, void* rbuf,
                  int count, MPI_Datatype dtype,
                  MPI_Op op, int root, MPI_Comm comm);

#define exit(code) MPI_Abort(MPI_COMM_WORLD, code)

#else /* !USE_MPI */
#define MPI_MASTER(instr) instr
#endif /* USE_MPI */

#ifdef USE_MPI
static int mpi_node_count;
#endif

#ifdef USE_THREADS  /* user want threads */
#error Threading (USE_THREADS) support has been removed for very poor efficiency. Use MPI/SSH grid instead.
#endif

/* I/O function prototypes ================================================== */

/* The mcformat.Name may contain additional keywords:
 *  no header: omit the format header
 *  no footer: omit the format footer
 */

void   mcset_ncount(unsigned long long int count);
unsigned long long int mcget_ncount(void);
unsigned long long int mcget_run_num(void);
double mcdetector_out(char *cname, double p0, double p1, double p2, char *filename);
double mcdetector_out_0D(char *t, double p0, double p1, double p2, char *c, Coords pos);
double mcdetector_out_1D(char *t, char *xl, char *yl,
                  char *xvar, double x1, double x2, int n,
                  double *p0, double *p1, double *p2, char *f, char *c, Coords pos);
double mcdetector_out_2D(char *t, char *xl, char *yl,
                  double x1, double x2, double y1, double y2, int m,
                  int n, double *p0, double *p1, double *p2, char *f,
                  char *c, Coords pos);
double mcdetector_out_3D(char *t, char *xl, char *yl, char *zl,
      char *xvar, char *yvar, char *zvar,
                  double x1, double x2, double y1, double y2, double z1, double z2, int m,
                  int n, int p, double *p0, double *p1, double *p2, char *f,
                  char *c, Coords pos);
void   mcinfo_simulation(FILE *f, struct mcformats_struct format,
  char *pre, char *name); /* used to add sim parameters (e.g. in Res_monitor) */
void   mcsiminfo_init(FILE *f);
void   mcsiminfo_close(void);
char *mcfull_file(char *name, char *ext);

#ifndef FLT_MAX
#define FLT_MAX         3.40282347E+38F /* max decimal value of a "float" */
#endif

#ifndef CHAR_BUF_LENGTH
#define CHAR_BUF_LENGTH 1024
#endif

/* Following part is only embedded when not redundent with mcstas.h ========= */

#ifndef MCSTAS_H

#ifndef NOSIGNALS
#include <signal.h>
#define SIG_MESSAGE(msg) strcpy(mcsig_message, msg);
#else
#define SIG_MESSAGE(msg)
#endif /* !NOSIGNALS */



/* Useful macros ============================================================ */

#define RAD2MIN  ((180*60)/PI)
#define MIN2RAD  (PI/(180*60))
#define DEG2RAD  (PI/180)
#define RAD2DEG  (180/PI)
#define AA2MS    629.622368        /* Convert k[1/AA] to v[m/s] */
#define MS2AA    1.58825361e-3     /* Convert v[m/s] to k[1/AA] */
#define K2V      AA2MS
#define V2K      MS2AA
#define Q2V      AA2MS
#define V2Q      MS2AA
#define SE2V     437.393377        /* Convert sqrt(E)[meV] to v[m/s] */
#define VS2E     5.22703725e-6     /* Convert (v[m/s])**2 to E[meV] */
#define FWHM2RMS 0.424660900144    /* Convert between full-width-half-max and */
#define RMS2FWHM 2.35482004503     /* root-mean-square (standard deviation) */
#define HBAR     1.05457168e-34    /* [Js] h bar Planck constant CODATA 2002 */
#define MNEUTRON 1.67492728e-27    /* [kg] mass of neutron CODATA 2002 */
#define GRAVITY  9.81              /* [m/s^2] gravitational acceleration */

#ifndef PI
# ifdef M_PI
#  define PI M_PI
# else
#  define PI 3.14159265358979323846
# endif
#endif

/* mccomp_posa and mccomp_posr are defined in McStas generated C code */
#define POS_A_COMP_INDEX(index) \
    (mccomp_posa[index])
#define POS_R_COMP_INDEX(index) \
    (mccomp_posr[index])
/* mcScattered defined in McStas generated C code */
#define SCATTERED mcScattered

/* Retrieve component information from the kernel */
/* Name, position and orientation (both absolute and relative)  */
/* Any component: For "redundancy", see comment by KN */
#define tmp_name_comp(comp) #comp
#define NAME_COMP(comp) tmp_name_comp(comp)
#define tmp_pos_a_comp(comp) (mcposa ## comp)
#define POS_A_COMP(comp) tmp_pos_a_comp(comp)
#define tmp_pos_r_comp(comp) (mcposr ## comp)
#define POS_R_COMP(comp) tmp_pos_r_comp(comp)
#define tmp_rot_a_comp(comp) (mcrota ## comp)
#define ROT_A_COMP(comp) tmp_rot_a_comp(comp)
#define tmp_rot_r_comp(comp) (mcrotr ## comp)
#define ROT_R_COMP(comp) tmp_rot_r_comp(comp)

/* Current component */
#define NAME_CURRENT_COMP  NAME_COMP(mccompcurname)
#define INDEX_CURRENT_COMP mccompcurindex
#define POS_A_CURRENT_COMP POS_A_COMP(mccompcurname)
#define POS_R_CURRENT_COMP POS_R_COMP(mccompcurname)
#define ROT_A_CURRENT_COMP ROT_A_COMP(mccompcurname)
#define ROT_R_CURRENT_COMP ROT_R_COMP(mccompcurname)



#define SCATTER do {mcDEBUG_SCATTER(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz, \
        mcnlt,mcnlsx,mcnlsy, mcnlp); mcScattered++;} while(0)
#define ABSORB do {mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz, \
        mcnlt,mcnlsx,mcnlsy, mcnlp); mcDEBUG_ABSORB(); MAGNET_OFF; goto mcabsorb;} while(0)
/* Note: The two-stage approach to MC_GETPAR is NOT redundant; without it,
* after #define C sample, MC_GETPAR(C,x) would refer to component C, not to
* component sample. Such are the joys of ANSI C.

* Anyway the usage of MCGETPAR requires that we use sometimes bare names...
*/
#define MC_GETPAR2(comp, par) (mcc ## comp ## _ ## par)
#define MC_GETPAR(comp, par) MC_GETPAR2(comp,par)

#define STORE_NEUTRON(index, x, y, z, vx, vy, vz, t, sx, sy, sz, p) \
  mcstore_neutron(mccomp_storein,index, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
#define RESTORE_NEUTRON(index, x, y, z, vx, vy, vz, t, sx, sy, sz, p) \
  mcrestore_neutron(mccomp_storein,index, &x, &y, &z, &vx, &vy, &vz, &t, &sx, &sy, &sz, &p);

#define MAGNET_ON \
  do { \
    mcMagnet = 1; \
  } while(0)

#define MAGNET_OFF \
  do { \
    mcMagnet = 0; \
  } while(0)

#define ALLOW_BACKPROP \
  do { \
    mcallowbackprop = 1; \
  } while(0)

#define DISALLOW_BACKPROP \
  do { \
    mcallowbackprop = 0; \
  } while(0)

#define PROP_MAGNET(dt) \
  do { \
    /* change coordinates from local system to magnet system */ \
    Rotation rotLM, rotTemp; \
    Coords   posLM = coords_sub(POS_A_CURRENT_COMP, mcMagnetPos); \
    rot_transpose(ROT_A_CURRENT_COMP, rotTemp); \
    rot_mul(rotTemp, mcMagnetRot, rotLM); \
    mcMagnetPrecession(mcnlx, mcnly, mcnlz, mcnlt, mcnlvx, mcnlvy, mcnlvz, \
	   	       &mcnlsx, &mcnlsy, &mcnlsz, dt, posLM, rotLM); \
  } while(0)

#define mcPROP_DT(dt) \
  do { \
    if (mcMagnet && dt > 0) PROP_MAGNET(dt);\
    mcnlx += mcnlvx*(dt); \
    mcnly += mcnlvy*(dt); \
    mcnlz += mcnlvz*(dt); \
    mcnlt += (dt); \
  } while(0)

/* ADD: E. Farhi, Aug 6th, 2001 PROP_GRAV_DT propagation with acceleration */
#define PROP_GRAV_DT(dt, Ax, Ay, Az) \
  do { \
    if(dt < 0 && mcallowbackprop == 0) { mcAbsorbProp[INDEX_CURRENT_COMP]++; ABSORB; }\
    if (mcMagnet) printf("Spin precession gravity\n"); \
    mcnlx  += mcnlvx*(dt) + (Ax)*(dt)*(dt)/2; \
    mcnly  += mcnlvy*(dt) + (Ay)*(dt)*(dt)/2; \
    mcnlz  += mcnlvz*(dt) + (Az)*(dt)*(dt)/2; \
    mcnlvx += (Ax)*(dt); \
    mcnlvy += (Ay)*(dt); \
    mcnlvz += (Az)*(dt); \
    mcnlt  += (dt); \
    DISALLOW_BACKPROP;\
  } while(0)

#define PROP_DT(dt) \
  do { \
    if(dt < 0 && mcallowbackprop == 0) { mcAbsorbProp[INDEX_CURRENT_COMP]++; ABSORB; }; \
    if (mcgravitation) { Coords mcLocG; double mc_gx, mc_gy, mc_gz; \
    mcLocG = rot_apply(ROT_A_CURRENT_COMP, coords_set(0,-GRAVITY,0)); \
    coords_get(mcLocG, &mc_gx, &mc_gy, &mc_gz); \
    PROP_GRAV_DT(dt, mc_gx, mc_gy, mc_gz); } \
    else mcPROP_DT(dt); \
    DISALLOW_BACKPROP;\
  } while(0)


#define PROP_Z0 \
  do { \
    if (mcgravitation) { Coords mcLocG; int mc_ret; \
    double mc_dt, mc_gx, mc_gy, mc_gz; \
    mcLocG = rot_apply(ROT_A_CURRENT_COMP, coords_set(0,-GRAVITY,0)); \
    coords_get(mcLocG, &mc_gx, &mc_gy, &mc_gz); \
    mc_ret = solve_2nd_order(&mc_dt, -mc_gz/2, -mcnlvz, -mcnlz); \
    if (mc_ret && mc_dt>=0) PROP_GRAV_DT(mc_dt, mc_gx, mc_gy, mc_gz); \
    else { if (mcallowbackprop ==0) {mcAbsorbProp[INDEX_CURRENT_COMP]++; ABSORB; }}; }\
    else mcPROP_Z0; \
    DISALLOW_BACKPROP;\
  } while(0)

#define mcPROP_Z0 \
  do { \
    double mc_dt; \
    if(mcnlvz == 0) { mcAbsorbProp[INDEX_CURRENT_COMP]++; ABSORB; }; \
    mc_dt = -mcnlz/mcnlvz; \
    if(mc_dt < 0 && mcallowbackprop == 0) { mcAbsorbProp[INDEX_CURRENT_COMP]++; ABSORB; }; \
    mcPROP_DT(mc_dt); \
    mcnlz = 0; \
    DISALLOW_BACKPROP;\
  } while(0)

#define PROP_X0 \
  do { \
    if (mcgravitation) { Coords mcLocG; int mc_ret; \
    double mc_dt, mc_gx, mc_gy, mc_gz; \
    mcLocG = rot_apply(ROT_A_CURRENT_COMP, coords_set(0,-GRAVITY,0)); \
    coords_get(mcLocG, &mc_gx, &mc_gy, &mc_gz); \
    mc_ret = solve_2nd_order(&mc_dt, -mc_gx/2, -mcnlvx, -mcnlx); \
    if (mc_ret && mc_dt>=0) PROP_GRAV_DT(mc_dt, mc_gx, mc_gy, mc_gz); \
    else { if (mcallowbackprop ==0) {mcAbsorbProp[INDEX_CURRENT_COMP]++; ABSORB; }}; }\
    else mcPROP_X0; \
    DISALLOW_BACKPROP;\
  } while(0)

#define mcPROP_X0 \
  do { \
    double mc_dt; \
    if(mcnlvx == 0) { mcAbsorbProp[INDEX_CURRENT_COMP]++; ABSORB; }; \
    mc_dt = -mcnlx/mcnlvx; \
    if(mc_dt < 0 && mcallowbackprop == 0) { mcAbsorbProp[INDEX_CURRENT_COMP]++; ABSORB; }; \
    mcPROP_DT(mc_dt); \
    mcnlx = 0; \
    DISALLOW_BACKPROP;\
  } while(0)

#define PROP_Y0 \
  do { \
    if (mcgravitation) { Coords mcLocG; int mc_ret; \
    double mc_dt, mc_gx, mc_gy, mc_gz; \
    mcLocG = rot_apply(ROT_A_CURRENT_COMP, coords_set(0,-GRAVITY,0)); \
    coords_get(mcLocG, &mc_gx, &mc_gy, &mc_gz); \
    mc_ret = solve_2nd_order(&mc_dt, -mc_gy/2, -mcnlvy, -mcnly); \
    if (mc_ret && mc_dt>=0) PROP_GRAV_DT(mc_dt, mc_gx, mc_gy, mc_gz); \
    else { if (mcallowbackprop ==0) {mcAbsorbProp[INDEX_CURRENT_COMP]++; ABSORB; }}; }\
    else mcPROP_Y0; \
    DISALLOW_BACKPROP;\
  } while(0)


#define mcPROP_Y0 \
  do { \
    double mc_dt; \
    if(mcnlvy == 0) { mcAbsorbProp[INDEX_CURRENT_COMP]++; ABSORB; }; \
    mc_dt = -mcnly/mcnlvy; \
    if(mc_dt < 0 && mcallowbackprop == 0) { mcAbsorbProp[INDEX_CURRENT_COMP]++; ABSORB; }; \
    mcPROP_DT(mc_dt); \
    mcnly = 0; \
    DISALLOW_BACKPROP; \
  } while(0)

#define vec_prod(x, y, z, x1, y1, z1, x2, y2, z2) \
  do { \
    double mcvp_tmpx, mcvp_tmpy, mcvp_tmpz; \
    mcvp_tmpx = (y1)*(z2) - (y2)*(z1); \
    mcvp_tmpy = (z1)*(x2) - (z2)*(x1); \
    mcvp_tmpz = (x1)*(y2) - (x2)*(y1); \
    (x) = mcvp_tmpx; (y) = mcvp_tmpy; (z) = mcvp_tmpz; \
  } while(0)

#define scalar_prod(x1, y1, z1, x2, y2, z2) \
  ((x1)*(x2) + (y1)*(y2) + (z1)*(z2))

#define NORM(x,y,z) \
  do { \
    double mcnm_tmp = sqrt((x)*(x) + (y)*(y) + (z)*(z)); \
    if(mcnm_tmp != 0.0) \
    { \
      (x) /= mcnm_tmp; \
      (y) /= mcnm_tmp; \
      (z) /= mcnm_tmp; \
    } \
  } while(0)

#define rotate(x, y, z, vx, vy, vz, phi, ax, ay, az) \
  do { \
    double mcrt_tmpx = (ax), mcrt_tmpy = (ay), mcrt_tmpz = (az); \
    double mcrt_vp, mcrt_vpx, mcrt_vpy, mcrt_vpz; \
    double mcrt_vnx, mcrt_vny, mcrt_vnz, mcrt_vn1x, mcrt_vn1y, mcrt_vn1z; \
    double mcrt_bx, mcrt_by, mcrt_bz; \
    double mcrt_cos, mcrt_sin; \
    NORM(mcrt_tmpx, mcrt_tmpy, mcrt_tmpz); \
    mcrt_vp = scalar_prod((vx), (vy), (vz), mcrt_tmpx, mcrt_tmpy, mcrt_tmpz); \
    mcrt_vpx = mcrt_vp*mcrt_tmpx; \
    mcrt_vpy = mcrt_vp*mcrt_tmpy; \
    mcrt_vpz = mcrt_vp*mcrt_tmpz; \
    mcrt_vnx = (vx) - mcrt_vpx; \
    mcrt_vny = (vy) - mcrt_vpy; \
    mcrt_vnz = (vz) - mcrt_vpz; \
    vec_prod(mcrt_bx, mcrt_by, mcrt_bz, \
             mcrt_tmpx, mcrt_tmpy, mcrt_tmpz, mcrt_vnx, mcrt_vny, mcrt_vnz); \
    mcrt_cos = cos((phi)); mcrt_sin = sin((phi)); \
    mcrt_vn1x = mcrt_vnx*mcrt_cos + mcrt_bx*mcrt_sin; \
    mcrt_vn1y = mcrt_vny*mcrt_cos + mcrt_by*mcrt_sin; \
    mcrt_vn1z = mcrt_vnz*mcrt_cos + mcrt_bz*mcrt_sin; \
    (x) = mcrt_vpx + mcrt_vn1x; \
    (y) = mcrt_vpy + mcrt_vn1y; \
    (z) = mcrt_vpz + mcrt_vn1z; \
  } while(0)

#define mirror(x,y,z,rx,ry,rz,nx,ny,nz) \
  do { \
    double mcrt_tmpx= (nx), mcrt_tmpy = (ny), mcrt_tmpz = (nz); \
    double mcrt_tmpt; \
    NORM(mcrt_tmpx, mcrt_tmpy, mcrt_tmpz); \
    mcrt_tmpt=scalar_prod((rx),(ry),(rz),mcrt_tmpx,mcrt_tmpy,mcrt_tmpz); \
    (x) = rx -2 * mcrt_tmpt*mcrt_rmpx; \
    (y) = ry -2 * mcrt_tmpt*mcrt_rmpy; \
    (z) = rz -2 * mcrt_tmpt*mcrt_rmpz; \
  } while (0)

#ifdef MC_TRACE_ENABLED
#define DEBUG
#endif

#ifdef DEBUG
#define mcDEBUG_INSTR() if(!mcdotrace); else { printf("INSTRUMENT:\n"); printf("Instrument '%s' (%s)\n", mcinstrument_name, mcinstrument_source); }
#define mcDEBUG_COMPONENT(name,c,t) if(!mcdotrace); else {\
  printf("COMPONENT: \"%s\"\n" \
         "POS: %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g\n", \
         name, c.x, c.y, c.z, t[0][0], t[0][1], t[0][2], \
         t[1][0], t[1][1], t[1][2], t[2][0], t[2][1], t[2][2]); \
  printf("Component %30s AT (%g,%g,%g)\n", name, c.x, c.y, c.z); \
  }
#define mcDEBUG_INSTR_END() if(!mcdotrace); else printf("INSTRUMENT END:\n");
#define mcDEBUG_ENTER() if(!mcdotrace); else printf("ENTER:\n");
#define mcDEBUG_COMP(c) if(!mcdotrace); else printf("COMP: \"%s\"\n", c);
#define mcDEBUG_STATE(x,y,z,vx,vy,vz,t,s1,s2,p) if(!mcdotrace); else \
  printf("STATE: %g, %g, %g, %g, %g, %g, %g, %g, %g, %g\n", \
         x,y,z,vx,vy,vz,t,s1,s2,p);
#define mcDEBUG_SCATTER(x,y,z,vx,vy,vz,t,s1,s2,p) if(!mcdotrace); else \
  printf("SCATTER: %g, %g, %g, %g, %g, %g, %g, %g, %g, %g\n", \
         x,y,z,vx,vy,vz,t,s1,s2,p);
#define mcDEBUG_LEAVE() if(!mcdotrace); else printf("LEAVE:\n");
#define mcDEBUG_ABSORB() if(!mcdotrace); else printf("ABSORB:\n");
#else
#define mcDEBUG_INSTR()
#define mcDEBUG_COMPONENT(name,c,t)
#define mcDEBUG_INSTR_END()
#define mcDEBUG_ENTER()
#define mcDEBUG_COMP(c)
#define mcDEBUG_STATE(x,y,z,vx,vy,vz,t,s1,s2,p)
#define mcDEBUG_SCATTER(x,y,z,vx,vy,vz,t,s1,s2,p)
#define mcDEBUG_LEAVE()
#define mcDEBUG_ABSORB()
#endif

#ifdef TEST
#define test_printf printf
#else
#define test_printf while(0) printf
#endif

#ifndef MC_RAND_ALG
#define MC_RAND_ALG 1
#endif

#if MC_RAND_ALG == 0
   /* Use system random() (not recommended). */
#  define MC_RAND_MAX RAND_MAX
#elif MC_RAND_ALG == 1
   /* "Mersenne Twister", by Makoto Matsumoto and Takuji Nishimura. */
#  define MC_RAND_MAX ((unsigned long)0xffffffff)
#  define random mt_random
#  define srandom mt_srandom
#elif MC_RAND_ALG == 2
   /* Algorithm used in McStas CVS-080208 and earlier (not recommended). */
#  define MC_RAND_MAX 0x7fffffff
#  define random mc_random
#  define srandom mc_srandom
#else
#  error "Bad value for random number generator choice."
#endif

#define rand01() ( ((double)random())/((double)MC_RAND_MAX+1) )
#define randpm1() ( ((double)random()) / (((double)MC_RAND_MAX+1)/2) - 1 )
#define rand0max(max) ( ((double)random()) / (((double)MC_RAND_MAX+1)/(max)) )
#define randminmax(min,max) ( rand0max((max)-(min)) + (min) )

#ifndef DANSE
void mcinit(void);
void mcraytrace(void);
void mcsave(FILE *);
void mcfinally(void);
void mcdisplay(void);
#endif

void mcdis_magnify(char *);
void mcdis_line(double, double, double, double, double, double);
void mcdis_dashed_line(double, double, double, double, double, double, int);
void mcdis_multiline(int, ...);
void mcdis_rectangle(char *, double, double, double, double, double);
void mcdis_box(double, double, double, double, double, double);
void mcdis_circle(char *, double, double, double, double);


typedef int mc_int32_t;
mc_int32_t mc_random(void);
void mc_srandom (unsigned int x);
unsigned long mt_random(void);
void mt_srandom (unsigned long x);

Coords coords_set(MCNUM x, MCNUM y, MCNUM z);
Coords coords_get(Coords a, MCNUM *x, MCNUM *y, MCNUM *z);
Coords coords_add(Coords a, Coords b);
Coords coords_sub(Coords a, Coords b);
Coords coords_neg(Coords a);
Coords coords_scale(Coords b, double scale);
double coords_sp(Coords a, Coords b);
Coords coords_xp(Coords b, Coords c);
void   coords_print(Coords a);

void rot_set_rotation(Rotation t, double phx, double phy, double phz);
int  rot_test_identity(Rotation t);
void rot_mul(Rotation t1, Rotation t2, Rotation t3);
void rot_copy(Rotation dest, Rotation src);
void rot_transpose(Rotation src, Rotation dst);
Coords rot_apply(Rotation t, Coords a);
void mccoordschange(Coords a, Rotation t, double *x, double *y, double *z,
    double *vx, double *vy, double *vz, double *time,
    double *s1, double *s2);
void mccoordschange_polarisation(Rotation t,
    double *sx, double *sy, double *sz);
double mcestimate_error(double N, double p1, double p2);
void mcreadparams(void);

void mcsetstate(double x, double y, double z, double vx, double vy, double vz,
                double t, double sx, double sy, double sz, double p);
void mcgenstate(void);
double randnorm(void);
double randtriangle(void);
void normal_vec(double *nx, double *ny, double *nz,
    double x, double y, double z);
int inside_rectangle(double, double, double, double);
int box_intersect(double *dt_in, double *dt_out, double x, double y, double z,
    double vx, double vy, double vz, double dx, double dy, double dz);
int cylinder_intersect(double *t0, double *t1, double x, double y, double z,
    double vx, double vy, double vz, double r, double h);
int sphere_intersect(double *t0, double *t1, double x, double y, double z,
                 double vx, double vy, double vz, double r);
/* ADD: E. Farhi, Aug 6th, 2001 solve_2nd_order */
int solve_2nd_order(double *Idt,
    double A,  double B,  double C);
void randvec_target_circle(double *xo, double *yo, double *zo,
    double *solid_angle, double xi, double yi, double zi, double radius);
#define randvec_target_sphere randvec_target_circle
#define plane_intersect_Gfast solve_2nd_order
void randvec_target_rect_angular(double *xo, double *yo, double *zo,
    double *solid_angle,
               double xi, double yi, double zi, double height, double width, Rotation A);
void randvec_target_rect_real(double *xo, double *yo, double *zo,
    double *solid_angle,
	       double xi, double yi, double zi, double height, double width, Rotation A,
			 double lx, double ly, double lz, int order);
void extend_list(int count, void **list, int *size, size_t elemsize);

int mcstas_main(int argc, char *argv[]);


#endif /* !MCSTAS_H */

#endif /* MCSTAS_R_H */
/* End of file "mcstas-r.h". */

#line 1008 "TOFexercise42.c"

#line 1 "nexus-lib.h"
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2011, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Runtime: share/nexus-lib.h
*
* %Identification
* Written by: EF
* Date:    Jan 17, 2007
* Release: McStas CVS-080208
* Version: $Revision: 1.8 $
*
* NeXus Runtime system header for McStas.
* Overrides default mcstas runtime functions.
* Embedded within instrument in runtime mode.
*
* Usage: Automatically embbeded in the c code whenever required.
*
* $Id: nexus-lib.h,v 1.8 2008-02-09 22:26:27 farhi Exp $
*
* $Log: nexus-lib.h,v $
* Revision 1.8  2008-02-09 22:26:27  farhi
* Major contrib for clusters/multi-core: OpenMP support
* 	try ./configure --with-cc=gcc4.2 or icc
* then mcrun --threads ...
* Also tidy-up configure. Made relevant changes to mcrun/mcgui to enable OpenMP
* Updated install-doc accordingly
*
* Revision 1.7  2007/03/05 19:02:55  farhi
* NEXUS support now works as MPI. NEXUS keyword is optional and only -DUSE_NEXUS is required. All instruments may then export in NEXUS if McStas
* has been installed with --with-nexus
*
* Revision 1.6  2007/03/02 14:35:56  farhi
* Updated install doc for NeXus and reconfigure tool.
* better NeXus support with compression
*
* Revision 1.5  2007/02/09 13:21:38  farhi
* NeXus compression does not work right. Use flat NeXus as default.
*
* Revision 1.4  2007/01/26 16:23:25  farhi
* NeXus final integration (mcplot, mcgui, mcrun).
* Only mcgui initiate mcstas.nxs as default output file, whereas
* simulation may use instr_time.nxs
*
* Revision 1.3  2007/01/22 15:13:42  farhi
* Fully functional NeXus output format.
* Works also for lists, but as catenation is not working in NAPI, one
* has to store all in memory (e.g. with large Monitor_nD bufsize), so that
* its written in one go at the end of sim.
*
* Revision 1.2  2007/01/22 01:38:25  farhi
* Improved NeXus/NXdata support. Attributes may not be at the right place
* yet.
*
* Revision 1.1  2007/01/21 15:43:08  farhi
* NeXus support. Draft version (functional). To be tuned.
*
*
*******************************************************************************/

#ifdef USE_NEXUS

#include "napi.h"
#include <sys/stat.h>

/* NeXus variables to be used in functions */
NXhandle mcnxHandle;
char    *mcnxFilename=NULL;
char     mcnxversion[128];       /* init in cogen_init: 4,5 xml and compress */

/* NeXus output functions that replace calls to pfprintf in mcstas-r */
int mcnxfile_init(char *name, char *ext, char *mode, NXhandle *nxhandle);
int mcnxfile_close(NXhandle *nxHandle);

/* header/footer. f=mcsiminfo_file, datafile */
/* creates Entry=valid_parent+file+timestamp */
int mcnxfile_header(NXhandle nxhandle, char *part,
    char *pre,                  /* %1$s  PRE  */
    char *instrname,            /* %2$s  SRC  */
    char *file,                 /* %3$s  FIL  */
    char *format_name,          /* %4$s  FMT  */
    char *date,                 /* %5$s  DAT  */
    char *user,                 /* %6$s  USR  */
    char *valid_parent,         /* %7$s  PAR = file */
    long  date_l);               /* %8$li DATL */

/* tag=value */
int mcnxfile_tag(NXhandle nxhandle,
    char *pre,          /* %1$s PRE */
    char *valid_section,/* %2$s SEC */
    char *name,         /* %3$s NAM */
    char *value);        /* %4$s VAL */

/* begin/end section */
int mcnxfile_section(NXhandle nxhandle, char *part,
    char *pre,          /* %1$s  PRE  */
    char *type,         /* %2$s  TYP  */
    char *name,         /* %3$s  NAM  */
    char *valid_name,   /* %4$s  VNA  */
    char *parent,       /* %5$s  PAR  */
    char *valid_parent, /* %6$s  VPA  */
    int   level);        /* %7$i  LVL */

/* data block begin/end */
int mcnxfile_datablock(NXhandle nxhandle, char *part,
      char *pre,          /* %1$s   PRE  */
      char *valid_parent, /* %2$s   PAR  */
      char *filename,     /* %3$s   FIL  */
      char *xlabel,       /* %4$s   XLA  */
      char *valid_xlabel, /* %5$s   XVL  */
      char *ylabel,       /* %6$s   YLA  */
      char *valid_ylabel, /* %7$s   YVL  */
      char *zlabel,       /* %8$s   ZLA  */
      char *valid_zlabel, /* %9$s   ZVL  */
      char *title,        /* %10$s  TITL */
      char *xvar,         /* %11$s  XVAR */
      char *yvar,         /* %12$s  YVAR */
      char *zvar,         /* %13$s  ZVAR */
      int  m,            /* %14$i  MDIM */
      int  n,            /* %15$i  NDIM */
      int  p,            /* %16$i  PDIM */
      double x1,           /* %17$g  XMIN */
      double x2,           /* %18$g  XMAX */
      double y1,           /* %19$g  YMIN */
      double y2,           /* %20$g  YMAX */
      double z1,           /* %21$g  ZMIN */
      double z2,           /* %22$g  ZMAX */
      double *p0,
      double *p1,
      double *p2);

#endif
/* End of file "nexus-lib.h". */

#line 1148 "TOFexercise42.c"

#line 1 "nexus-lib.c"
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2011, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Runtime: share/nexus-lib.c
*
* %Identification
* Written by: KN
* Date:    Jan 17, 2007
* Release: McStas 1.12c
* Version: $Revision: 1.12 $
*
* NeXus Runtime output functions for McStas.
* Overrides default mcstas runtime functions.
* Embedded within instrument in runtime mode.
*
* Usage: Automatically embbeded in the c code whenever required.
*
* $Id: nexus-lib.c,v 1.12 2008-02-09 22:26:27 farhi Exp $
*
* $Log: nexus-lib.c,v $
* Revision 1.12  2008-02-09 22:26:27  farhi
* Major contrib for clusters/multi-core: OpenMP support
* 	try ./configure --with-cc=gcc4.2 or icc
* then mcrun --threads ...
* Also tidy-up configure. Made relevant changes to mcrun/mcgui to enable OpenMP
* Updated install-doc accordingly
*
* Revision 1.11  2007/03/06 09:39:15  farhi
* NeXus default output is now "5 zip". Then NEXUS keyword is purely optional.
*
* Revision 1.10  2007/03/05 19:02:55  farhi
* NEXUS support now works as MPI. NEXUS keyword is optional and only -DUSE_NEXUS is required. All instruments may then export in NEXUS if McStas
* has been installed with --with-nexus
*
* Revision 1.9  2007/03/02 14:35:56  farhi
* Updated install doc for NeXus and reconfigure tool.
* better NeXus support with compression
*
* Revision 1.8  2007/02/24 16:44:41  farhi
* nexus support adapted partially for SNS. File name can be specified with -f option of instr.exe or mcrun or follow NEXUS keyword. The NULL filename will set 'instr_timestamp'.
*
* Revision 1.7  2007/02/09 13:21:37  farhi
* NeXus compression does not work right. Use flat NeXus as default.
*
* Revision 1.6  2007/01/26 16:23:25  farhi
* NeXus final integration (mcplot, mcgui, mcrun).
* Only mcgui initiate mcstas.nxs as default output file, whereas
* simulation may use instr_time.nxs
*
* Revision 1.5  2007/01/25 14:57:36  farhi
* NeXus output now supports MPI. Each node writes a data set in the NXdata
* group. Uses compression LZW when -DUSE_NEXUS_COMP.
*
* Revision 1.3  2007/01/22 15:13:42  farhi
* Fully functional NeXus output format.
* Works also for lists, but as catenation is not working in NAPI, one
* has to store all in memory (e.g. with large Monitor_nD bufsize), so that
* its written in one go at the end of sim.
*
* Revision 1.2  2007/01/22 01:38:25  farhi
* Improved NeXus/NXdata support. Attributes may not be at the right place
* yet.
*
* Revision 1.1  2007/01/21 15:43:08  farhi
* NeXus support. Draft version (functional). To be tuned.
*
*
*******************************************************************************/

#ifdef USE_NEXUS

/* NeXus output functions that replace calls to pfprintf in mcstas-r */
int mcnxfile_init(char *name, char *ext, char *mode, NXhandle *nxhandle)
{
  int mcnxMode=NXACC_CREATE5;
  char mcnxExt[10];
  strcpy(mcnxExt, ext);
  char nxversion[128];
  int i;
  if (!mcnxversion || !strlen(mcnxversion)) strcpy(nxversion, "5 zip");
  else for (i=0; i< strlen(mcnxversion) && i < 128; nxversion[i]=tolower(mcnxversion[i++]));

  if    (strstr(nxversion,"xml")) { mcnxMode =NXACC_CREATEXML; strcpy(mcnxExt, "xml"); }
  else if (strstr(nxversion,"4")) { mcnxMode =NXACC_CREATE;     }
  else if (strstr(nxversion,"5")) { mcnxMode =NXACC_CREATE5;    }

  if (!strcmp(mode, "a"))    mcnxMode |= NXACC_RDWR;
  mcnxFilename = mcfull_file(name, mcnxExt);
  if (NXopen(mcnxFilename, mcnxMode, nxhandle) == NX_ERROR) {
    mcsiminfo_file = NULL;
  } else { mcsiminfo_file=(FILE*)mcnxFilename; }
  return(mcsiminfo_file != NULL);
}

int mcnxfile_close(NXhandle *nxHandle)
{
  return(NXclose(nxHandle));
}

/* mcnxfile_header: header/footer. f=mcsiminfo_file, datafile */
/* write class attributes in current SDS. Returns: NX_ERROR or NX_OK */
int mcnxfile_header(NXhandle nxhandle, char *part,
    char *pre,                  /* %1$s  PRE  */
    char *instrname,            /* %2$s  SRC  */
    char *file,                 /* %3$s  FIL  */
    char *format_name,          /* %4$s  FMT  */
    char *date,                 /* %5$s  DAT  */
    char *user,                 /* %6$s  USR  */
    char *valid_parent,         /* %7$s  PAR = file */
    long  date_l)               /* %8$li DATL */
{
  if (!strcmp(part, "header")) {
    if (NXputattr(nxhandle, "user_name", user, strlen(user), NX_CHAR) == NX_ERROR)
      return(NX_ERROR);
    char creator[128];
    sprintf(creator, "%s McStas " MCSTAS_VERSION " [www.mcstas.org]", instrname);
    NXputattr(nxhandle, "creator", creator, strlen(creator), NX_CHAR);
    NXputattr(nxhandle, "simulation_begin", date, strlen(date), NX_CHAR);
    char *url="http://www.nexusformat.org/";
    NXputattr(nxhandle, "URL", url, strlen(url), NX_CHAR);
    char *browser="hdfview or NXbrowse or HDFExplorer";
    NXputattr(nxhandle, "Browser", browser, strlen(browser), NX_CHAR);
#if defined (USE_MPI) || defined(USE_THREADS)
    NXputattr (nxhandle, "number_of_nodes", &mpi_node_count, 1, NX_INT32);
#endif
    return(NXputattr(nxhandle, "Format", format_name, strlen(format_name), NX_CHAR));
  } else
    return(NXputattr(nxhandle, "simulation_end", date, strlen(date), NX_CHAR));
} /* mcnxfile_header */

/* mcnxfile_tag: tag=value in the current group. Returns: NX_ERROR or NX_OK */
int mcnxfile_tag(NXhandle nxhandle,
    char *pre,          /* %1$s PRE */
    char *valid_section,/* %2$s SEC */
    char *name,         /* %3$s NAM */
    char *value)        /* %4$s VAL */
{
  return(NXputattr(nxhandle, name, value, strlen(value), NX_CHAR));
} /* mcnxfile_tag */

/* mcnxfile_section: begin/end section. Returns: NX_ERROR or NX_OK */
int mcnxfile_section(NXhandle nxhandle, char *part,
    char *pre,          /* %1$s  PRE  */
    char *type,         /* %2$s  TYP  */
    char *name,         /* %3$s  NAM  */
    char *valid_name,   /* %4$s  VNA  */
    char *parent,       /* %5$s  PAR  */
    char *valid_parent, /* %6$s  VPA  */
    int   level)        /* %7$i  LVL */
{
  char nxname[1024];
  int length;
  if (!strcmp(part, "end_data"))   return(NXclosedata(nxhandle));
  if (!strcmp(part, "end"))        return(NXclosegroup(nxhandle));

  if (!strcmp(type, "instrument")) strcpy(nxname, "instrument");
  else if (!strcmp(type, "simulation")) strcpy(nxname, "simulation");
  else strcpy(nxname, valid_name);
  if (!strcmp(part, "instr_code")) {
    FILE *f;
    char *instr_code=NULL;
    struct stat stfile;
    if (stat(name,&stfile) != 0) {
      instr_code = (char*)malloc(1024);
      if (instr_code) sprintf(instr_code, "File %s not found", name);
    } else {
      long filesize = stfile.st_size;
      f=fopen(name, "r");
      instr_code = (char*)malloc(filesize);
      if (instr_code && f) fread(instr_code, 1, filesize, f);
      if (f) fclose(f);
    }
    length = strlen(instr_code);
    if (length) {
      NXmakedata(nxhandle, "instr_code", NX_CHAR, 1, &length);
        NXopendata(nxhandle, "instr_code");
        NXputdata (nxhandle, instr_code);
        NXputattr (nxhandle, "file_name", name, strlen(name), NX_CHAR);
        NXputattr (nxhandle, "file_size", &length, 1, NX_INT32);
        NXputattr (nxhandle, "McStas_version", MCSTAS_VERSION, strlen(MCSTAS_VERSION), NX_CHAR);
        NXputattr (nxhandle, "instr_name", parent, strlen(parent), NX_CHAR);
      return(NXclosedata(nxhandle));
    } else
    return(NX_ERROR);
  }
  if (!strcmp(part, "begin")) {
    char nxtype[128];
    sprintf(nxtype, "NX%s", type);
    if (NXmakegroup(nxhandle, nxname, nxtype) == NX_ERROR)
      fprintf(stderr, "Warning: could not open SDS to store %s %s information\n",
        nxname, nxtype);
    NXopengroup(nxhandle, nxname, nxtype);
    /* open a SDS to store attributes */
    sprintf(nxname, "Information about %s of type %s is stored in attributes", name, nxtype);
    length = strlen(nxname);
    NXmakedata(nxhandle, "information", NX_CHAR, 1, &length);
    NXopendata(nxhandle, "information");
    NXputdata (nxhandle, nxname);
    NXputattr(nxhandle, "name", name, strlen(name), NX_CHAR);
    NXputattr(nxhandle, "parent", parent, strlen(parent), NX_CHAR);
  }
  return(NX_OK);
} /* mcnxfile_section */

/* mcnxfile_datablock: data block begin/end. Returns: NX_ERROR or NX_OK */
int mcnxfile_datablock(NXhandle nxhandle, char *part,
      char *format, char *valid_parent, char *filename, char *xlabel, char *valid_xlabel, char *ylabel, char *valid_ylabel, char *zlabel, char *valid_zlabel, char *title, char *xvar, char *yvar, char *zvar, int  m, int  n, int  p, double x1, double x2, double y1, double y2, double z1, double z2, double *p0, double *p1, double *p2)
{
  /* write axes, only for data */
  if (strstr(part, "data")) {
    int i;
    if (!strstr(format, "list")) {
    /* X axis */
    if (m > 1) {
      double axis[m];
      for(i = 0; i < m; i++)
        axis[i] = x1+(x2-x1)*(i+0.5)/(abs(m));
      if (strstr(mcnxversion,"compress") || strstr(mcnxversion,"zip"))
        NXcompmakedata(nxhandle, valid_xlabel, NX_FLOAT64, 1, &m, NX_COMP_LZW, &m);
      else
        NXmakedata(nxhandle, valid_xlabel, NX_FLOAT64, 1, &m);

      NXopendata(nxhandle, valid_xlabel);
      NXputdata (nxhandle, axis);
      NXputattr (nxhandle, "long_name", xlabel, strlen(xlabel), NX_CHAR);
      NXputattr (nxhandle, "short_name", xvar, strlen(xvar), NX_CHAR);
      int naxis=1;
      NXputattr (nxhandle, "axis", &naxis, 1, NX_INT32);
      NXputattr (nxhandle, "units", xvar, strlen(xvar), NX_CHAR);
      int nprimary=1;
      NXputattr (nxhandle, "primary", &nprimary, 1, NX_INT32);
      NXclosedata(nxhandle);
    }
    if (n >= 1) {
      double axis[n];
      for(i = 0; i < n; i++)
        axis[i] = y1+(y2-y1)*(i+0.5)/(abs(n));
      if (strstr(mcnxversion,"compress") || strstr(mcnxversion,"zip"))
        NXcompmakedata(nxhandle, valid_ylabel, NX_FLOAT64, 1, &n, NX_COMP_LZW, &n);
      else
        NXmakedata(nxhandle, valid_ylabel, NX_FLOAT64, 1, &n);

      NXopendata(nxhandle, valid_ylabel);
      NXputdata (nxhandle, axis);
      NXputattr (nxhandle, "long_name", ylabel, strlen(ylabel), NX_CHAR);
      NXputattr (nxhandle, "short_name", yvar, strlen(yvar), NX_CHAR);
      int naxis=2;
      NXputattr (nxhandle, "axis", &naxis, 1, NX_INT32);
      NXputattr (nxhandle, "units", yvar, strlen(yvar), NX_CHAR);
      int nprimary=1;
      NXputattr (nxhandle, "primary", &nprimary, 1, NX_INT32);
      NXclosedata(nxhandle);
    }
    if (p > 1) {
      double axis[p];
      for(i = 0; i < p; i++)
        axis[i] = z1+(z2-z1)*(i+0.5)/(abs(p));
      if (strstr(mcnxversion,"compress") || strstr(mcnxversion,"zip"))
        NXcompmakedata(nxhandle, valid_zlabel, NX_FLOAT64, 1, &p, NX_COMP_LZW, &p);
      else
        NXmakedata(nxhandle, valid_zlabel, NX_FLOAT64, 1, &p);

      NXopendata(nxhandle, valid_zlabel);
      NXputdata (nxhandle, axis);
      NXputattr (nxhandle, "long_name", zlabel, strlen(zlabel), NX_CHAR);
      NXputattr (nxhandle, "short_name", zvar, strlen(zvar), NX_CHAR);
      int naxis=3;
      NXputattr (nxhandle, "axis", &naxis, 1, NX_INT32);
       NXputattr (nxhandle, "units", zvar, strlen(zvar), NX_CHAR);
      int nprimary=1;
      NXputattr (nxhandle, "primary", &nprimary, 1, NX_INT32);
      NXclosedata(nxhandle);
    }
  } } /* end format != list for data */
  /* write data */
  int rank=0;
  int dims[3];  /* number of elements to write */
  if (m > 1) { rank++; dims[0]=m; }
  if (n > 1) { rank++; dims[1]=n; }
  if (p > 1) { rank++; dims[2]=p; }
  char *nxname=part;
  double *data;
  if (strstr(part,"data"))         { data=p1; }
  else if (strstr(part,"errors"))  { data=p2; }
  else if (strstr(part,"ncount"))  { data=p0; }
  /* ignore errors for making/opening data (in case this has already been done */
  if (strstr(mcnxversion,"compress") || strstr(mcnxversion,"zip"))
    NXmakedata(nxhandle, nxname, NX_FLOAT64, rank, dims);
  else
    NXcompmakedata(nxhandle, nxname, NX_FLOAT64, rank, dims, NX_COMP_LZW, dims);

  NXopendata(nxhandle, nxname);
  int israw=(strstr(format, " raw") != NULL);
  if (data == p2 && !israw) {
    double* s = (double*)malloc(abs(m*n*p)*sizeof(double));
    if (s) {
      long    i;
      for (i=0; i<abs(m*n*p); i++)
        s[i] = mcestimate_error(p0[i],p1[i],p2[i]);
      NXputdata (nxhandle, s);
      free(s);
    } else {
      fprintf(stderr, "McStas: Out of memory for writing 'errors' in NeXus file '%s'. Writing 'raw' errors (mcnxfile_datablock)\n", filename);
      NXputdata (nxhandle, data);
      char *msg="yes: 'errors' is p^2, not sigma.";
      NXputattr(nxhandle, "raw", msg, strlen(msg), NX_CHAR);
    }
  } else
    NXputdata (nxhandle, data);
  NXputattr(nxhandle, "parent", valid_parent, strlen(valid_parent), NX_CHAR);
  int signal=1;
  if (strstr(part,"data")) {
    NXputattr(nxhandle, "signal", &signal, 1, NX_INT32);
    NXputattr(nxhandle, "short_name", filename, strlen(filename), NX_CHAR);
  }
  char nxtitle[1024];
  sprintf(nxtitle, "%s '%s'", nxname, title);
  NXputattr(nxhandle, "long_name", nxtitle, strlen(nxtitle), NX_CHAR);
  /* first write attributes */
  char creator[128];
  sprintf(creator, "%s/%s", mcinstrument_name, valid_parent);
  NXputattr(nxhandle, "creator", creator, strlen(creator), NX_CHAR);
  return(NXclosedata(nxhandle));
} /* mcnxfile_datablock */

#endif
/* End of file "nexus-lib.c". */

#line 1483 "TOFexercise42.c"

#line 1 "mcstas-r.c"
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2011, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Runtime: share/mcstas-r.c
*
* %Identification
* Written by: KN
* Date:    Aug 29, 1997
* Release: McStas X.Y
* Version: $Revision: 1.194 $
*
* Runtime system for McStas.
* Embedded within instrument in runtime mode.
*
* Usage: Automatically embbeded in the c code whenever required.
*
* $Id: mcstas-r.c,v 1.194 2009-04-02 09:47:46 pkwi Exp $
*
* $Log: mcstas-r.c,v $
* Revision 1.194  2009-04-02 09:47:46  pkwi
* Updated runtime and interoff from dev branch (bugfixes etc.)
*
* Proceeding to test before release
*
* Revision 1.217  2009/03/26 13:41:36  erkn
* fixed bug in mcestimate_error. Missing factor 1/N in quadratic (1st) term of square sum.
*
* Revision 1.216  2009/02/20 16:17:55  farhi
* Fixed warnings and a few bugs detected with GCC 4.3.
*
* Revision 1.215  2009/02/13 14:03:20  farhi
* Fixed GCC 4.3 warnings. More will come in components.
*
* Revision 1.214  2009/02/12 10:43:48  erkn
* check abs. value to protect for rounding errors - not signed value.
*
* Revision 1.213  2009/02/11 15:11:05  farhi
* printf format fixes revealed with gcc 4.3
*
* Revision 1.212  2009/01/23 10:51:30  farhi
* Minor speedup: Identity rotation matrices are now checked for and
* caculations reduced.
* It seems this McSatsStable commit did not got through for McStas 1.12c
*
* Revision 1.211  2009/01/18 14:43:13  farhi
* Fixed MPI event list output (broken and reported first by A. Percival).
* This required to split lists in small blocks not to overflow the MPI
* buffer.
*
* Revision 1.207  2008/10/21 15:19:18  farhi
* use common CHAR_BUFFER_LENGTH = 1024
*
* Revision 1.206  2008/10/14 14:29:50  farhi
* sans sample expanded with cylinder and sphere. cosmetics and updated
* todo.
*
* Revision 1.205  2008/10/09 14:47:53  farhi
* cosmetics for SIGNAL displaying starting date
*
* Revision 1.204  2008/09/08 10:08:21  farhi
* in save sessions, filename was not registered in mcopenedfiles,
* but was searching for simfile (always opened) leading
* to always catenated files. This happen when e.g. sending USR2 or using
* intermediate saves.
*
* Revision 1.203  2008/09/05 10:04:20  farhi
* sorry, my mistake...
*
* Revision 1.202  2008/09/02 14:50:42  farhi
* cosmetics
*
* Revision 1.201  2008/09/02 08:36:17  farhi
* MPI support: block size defined in mcstas-r.h as 1e5. Correct bug when
* p0, p1 or p2 are NULL, and re-enable S(q,w) save in Isotropic_Sqw with
* MPI.
*
* Revision 1.200  2008/08/29 15:35:08  farhi
* Split MPI_Reduce into 1e5 bits to avoid de-sync of nodes.. This was done
* in fact in last commit.
*
* Revision 1.199  2008/08/29 15:32:28  farhi
* Indicate memory allocation size when reporting error.
*
* Revision 1.198  2008/08/26 13:32:05  farhi
* Remove Threading support which is poor efficiency and may give wrong
* results
* Add quotes around string instrument parameters from mcgui simulation
* dialog
*
* Revision 1.197  2008/08/25 14:13:28  farhi
* changed neutron-mc to mcstas-users
*
* Revision 1.196  2008/08/19 11:25:52  farhi
* make sure the opened file list is reset when calling mcsave (same save
* session). already opened files are catenated, just as with the catenate
* word in mcformat.Name
*
* Revision 1.195  2008/08/07 21:52:10  farhi
* Second major commit for v2: fixed sources, and most instruments for
* automatic testing. A few instruments need more work still.
*
* Revision 1.194  2008/07/17 12:50:18  farhi
* MAJOR commit to McStas 2.x
* uniformized parameter naming in components
* uniformized SITE for instruments
* all compile OK
*
* Revision 1.192  2008/04/25 08:26:33  erkn
* added utility functions/macros for intersecting with a plane and mirroring a vector in a plane
*
* Revision 1.191  2008/04/21 16:08:05  pkwi
* OpenMPI mpicc dislikes declaration of the counter var in the for(   ) (C99 extension)
*
* Revision 1.190  2008/04/21 15:50:19  pkwi
* Name change randvec_target_rect -> randvec_target_rect_real .
*
* The renamed routine takes local emmission coordinate into account, correcting for the
* effects mentioned by George Apostolopoulus <gapost@ipta.demokritos.gr> to the
* mcstas-users list (parameter list extended by four parms).
*
* For backward-compatibility, a define has been added that maps randvec_target_rect
* to the new routine, defaulting to the "old" behaviour.
*
* To make any use of these modifications, we need to correct all (or all relevant) comps
* that have calls to randvec_target_rect.
*
* Will supply a small doc with plots showing that we now correct for the effect pointed
* out by George.
*
* Similar change should in principle happen to the _sphere focusing routine.
*
* Revision 1.189  2008/04/02 13:20:20  pkwi
* Minor correction: && -> || , otherwise we still stop at the cmdline/default ncount...
*
* Revision 1.188  2008/04/02 12:32:38  farhi
* Add explicit condition for node raytrace loop end with ncount value,
* instead of using local copy of ncount. Makes mcset_ncount work again...
*
* Revision 1.187  2008/03/27 12:47:26  farhi
* Fixed unwanted additional NL chars when using mcformat on PGPLOT 1D
*
* Revision 1.186  2008/03/25 14:34:49  pkwi
* Restoring Revision 1.184 since last commit breaks mcplot 1-D plots.
*
* (Emmanuel will fix 'locally' for mcformat)
*
* Revision 1.184  2008/03/11 16:13:08  farhi
* Infrastructure for running mcrun/mcgui on a grid. --force-compile spans
* over nodes. Local data files are sent to slaves for proper execution of
* complex components.
*
* Revision 1.183  2008/02/14 08:56:35  farhi
* McRun/McGUI SSH grid now operates on each simulation. This emulates completely
* MPI without installing it. Simulation steps for scans may also be distributed,
* and single runs can be sent to execute on other machines transparently.
* mcrun code has reduced in size. mcformat is used to merge nodes.
*
* Revision 1.182  2008/02/10 20:55:53  farhi
* OpenMP number of nodes now set properly from either --threads=NB or
* --threads which sets the computer core nb.
*
* Revision 1.180  2008/02/09 22:26:27  farhi
* Major contrib for clusters/multi-core: OpenMP support
* 	try ./configure --with-cc=gcc4.2 or icc
* then mcrun --threads ...
* Also tidy-up configure. Made relevant changes to mcrun/mcgui to enable OpenMP
* Updated install-doc accordingly
*
* Revision 1.179  2008/01/18 15:39:08  farhi
* mcformat merge mode now takes into account individual Ncount so that addition
* is a weighted sum. Event lists (when 'list' is found in Format) are catenated
* un-weighted.
* Option --format_data aliased to --format-data (internal usage)
*
* Revision 1.178  2007/12/12 08:48:58  pkwi
* Fix for wrong ncount in monitor 'ratios' in case of MPI
*
* Revision 1.177  2007/11/21 09:16:55  farhi
* Added MPI_Barrier to easy synchronization of nodes before Reduce (hey Dude !)
* (Windows) Fixed mcformat catenation of path containing disk label.
*
* Revision 1.176  2007/11/20 20:48:44  pkwi
* Fixes for MPI and input from virtual sources.
*
* When using a virtual source (with N neutron rays), the ncount is now
* restricted to exactly
*
* Ncnt = N * ceil(k/m)
*
* where k is a requested number of repetitions and m is the number of mpi hosts.
*
* Revision 1.175  2007/11/20 14:58:23  farhi
* Fixed change of ncount when using MPI (e.g. Virtual sources)
*
* Revision 1.174  2007/10/18 10:01:22  farhi
* mcdetector_out: fflush(NULL) to flush all opened streams, not only for MPI.
*
* Revision 1.173  2007/10/17 13:05:04  farhi
* MPI run: solve output scrambling when using MPI: force fflush when saving.
*
* Revision 1.172  2007/10/02 09:59:00  farhi
* Fixed exit call for instr --help and --info with or without MPI.
*
* Revision 1.171  2007/09/14 14:46:48  farhi
* mcstas-r: instr.out with MPI may now exit without error code in case of 'usage' and 'info'.
*
* Revision 1.170  2007/08/10 11:30:44  pkwi
* Compilation of mcformat warned about missing newline at end of mcstas-r.c. Added.
*
* Revision 1.169  2007/08/09 16:47:34  farhi
* Solved old gcc compilation issue when using macros in macros.
* Solved MPI issuie when exiting in the middle of a simulation. Now use MPI_Abort.
*
* Revision 1.168  2007/06/30 10:05:11  farhi
* Focus: new TOF-angle detector, so tht it looks like real data
* mcstas-r.c: fixed 2D monitor calls that are in fact 1D.
* Plus cosmetics
*
* Revision 1.167  2007/06/13 08:46:08  pkwi
* A couple of bugfixes...
*
* Virtual_input got the n+1'th weight for the n'th neutron.
*
* mcstas-r.c base adress for store/restore pointers fixed.
*
* These bugs had effect on use of virtual sources plus the new SPLIT keyword...
*
* Will double-check if this is a problem with current stable relase 1.10 and
* report to mcstas-users.
*
* Thanks to Kim Lefmann / Linda Udby for noticing a subtile energy-widening
* effect when using a virtual source!
*
* Revision 1.166  2007/06/11 09:05:33  pkwi
* We need to also check on filename_orig here, otherwise free() is run on a descriptive string in case of Monitor.comp.
*
* Revision 1.165  2007/06/06 12:30:07  pkwi
* Re-introducing --help item for MPI enabled instruments. Was removed on last cvs commit... Please remember to cvs update before committing.
*
* Revision 1.164  2007/05/29 14:57:56  farhi
* New rand function to shoot on a triangular distribution. Useful to simulate chopper time spread.
*
* Revision 1.162  2007/05/18 13:34:54  farhi
* mcformat: warning when using --scan to non McStas/PGPLOT format
* new instrument with sample container and single environment sheild
* removed OpenGENIE format (never used)
*
* Revision 1.161  2007/05/11 10:17:27  farhi
* fix field naming when generating/converting data files.
*
* Revision 1.160  2007/04/20 12:25:25  farhi
* Field names should not exceed e.g. 32 (for Matlab/scilab, etc compatibility).
* Now using VALID_NAME_LENGTH define.
*
* Revision 1.159  2007/04/03 13:29:49  farhi
* store/restore neutron now uses incremented pointer.
* Might improve slightly performances
*
* Revision 1.158  2007/03/12 14:06:35  farhi
* Warning 'Low Stat' when >25 % error in detector results
*
* Revision 1.157  2007/03/05 19:02:55  farhi
* NEXUS support now works as MPI. NEXUS keyword is optional and only -DUSE_NEXUS is required. All instruments may then export in NEXUS if McStas
* has been installed with --with-nexus
*
* Revision 1.156  2007/02/24 16:44:41  farhi
* nexus support adapted partially for SNS. File name can be specified with -f option of instr.exe or mcrun or follow NEXUS keyword. The NULL filename will set 'instr_timestamp'.
*
* Revision 1.155  2007/02/17 13:37:50  farhi
* cogen: display tip when no NEXUS keyword but user wants NeXus output.
* mcstas-r.c: fixed pb when using MPI, that gave 0 detector values.
*
* Revision 1.154  2007/02/06 14:07:40  vel
* Axes limits for 3rd axis using  DETECTOR_OUT_3D are corrected
*
* Revision 1.153  2007/02/05 10:16:08  pkwi
* Mac OS, MPI related: Disable use of sighandler in case of NOSIGNALS
*
* Revision 1.152  2007/01/29 15:51:56  farhi
* mcstas-r: avoid undef of USE_NEXUS as napi is importer afterwards
*
* Revision 1.151  2007/01/29 15:16:07  farhi
* Output file customization in header, through the DETECTOR_CUSTOM_HEADER macro.
* Small adds-on in install doc.
*
* Revision 1.150  2007/01/26 16:23:25  farhi
* NeXus final integration (mcplot, mcgui, mcrun).
* Only mcgui initiate mcstas.nxs as default output file, whereas
* simulation may use instr_time.nxs
*
* Revision 1.149  2007/01/25 14:57:36  farhi
* NeXus output now supports MPI. Each node writes a data set in the NXdata
* group. Uses compression LZW (may be unactivated with the
* -DUSE_NEXUS_FLAT).
*
* Revision 1.148  2007/01/23 00:41:05  pkwi
* Edits by Jiao Lin (linjao@caltech.edu) for embedding McStas in the DANSE project. Define -DDANSE during compile will enable these edits.
*
* Have tested that McStas works properly without the -DDANSE.
*
* Jiao: Could you please test if all is now OK?
* (After 15 minutes) Get current CVS tarball from http://www.mcstas.org/cvs
*
* Revision 1.147  2007/01/22 18:22:43  farhi
* NeXus support for lists and Virtual_output

* Revision 1.146  2007/01/22 15:13:42  farhi
* Fully functional NeXus output format.
* Works also for lists, but as catenation is not working in NAPI, one
* has to store all in memory (e.g. with large Monitor_nD bufsize), so that
* its written in one go at the end of sim.
*
* Revision 1.145  2007/01/22 01:38:25  farhi
* Improved NeXus/NXdata support. Attributes may not be at the right place
* yet.
*
* Revision 1.144  2007/01/21 15:43:08  farhi
* NeXus support. Draft version (functional). To be tuned.
*
* Revision 1.143  2006/12/19 18:51:52  farhi
* Trace disables MPI and Threads only in multicpu mode...
*
* Revision 1.142  2006/12/19 15:11:57  farhi
* Restored basic threading support without mutexes. All is now in mcstas-r.c
*
* Revision 1.141  2006/10/12 12:09:11  farhi
* mcformat can now handle scans, but only works with PGPLOT output format now.
* Input format is any, compatible with --merge as well.
*
* Revision 1.140  2006/10/09 11:31:35  farhi
* Added blue/white sky to VRML output files. Prefer Octagaplayer.
*
* Revision 1.139  2006/10/03 22:14:24  farhi
* Added octaga VRML player in install
*
* Revision 1.138  2006/09/05 15:26:18  farhi
* Update of mcformat
*
* Revision 1.137  2006/08/30 12:13:41  farhi
* Define mutexes for mcstas-r parts.
*
* Revision 1.136  2006/08/28 10:12:25  pchr
* Basic infrastructure for spin propagation in magnetic fields.
*
* Revision 1.135  2006/08/03 13:11:18  pchr
* Added additional functions for handling vectors.
*
* Revision 1.134  2006/07/11 12:21:17  pchr
* Changed polarization default value to be (0, 0, 0) (old was: sy=1)
*
* Revision 1.133  2006/07/06 08:59:21  pchr
* Added new draw methods for rectangle and box.
*
* Revision 1.132  2006/06/01 09:12:45  farhi
* Correct bug related to event for run_num > ncount
* Now forces simulation to finish both in Virtual_input and mcraytrace()
*
* Revision 1.131  2006/05/29 11:51:02  farhi
* Fixed thread joining that caused SEGV when using many threads
*
* Revision 1.130  2006/05/19 19:01:15  farhi
* rum_num now regularly incremented and display warning when pthread requested but not compiled
*
* Revision 1.129  2006/05/19 14:17:40  farhi
* Added support for multi threading with --threads=NB option for mcrun or instr.out
* Requires new option in mcgui run dialog: a popup menu to select run mode ?
*
* Revision 1.128  2006/03/22 14:54:13  farhi
* Added EOL chars (\n) for all matrix output to all formats except IDL
* (which has limitations in the way matrix are entered).
* Will generate data sets to be handled by mcformat/mcconvert
*
* Revision 1.127  2006/03/15 15:59:37  farhi
* output format function more robust (uses default args if called with NULL args)
*
* Revision 1.126  2006/03/02 12:39:33  pkwi
* Corrected typo in last commit:
*
* tout should have been t_out - resulted in:
*
* lp-07151:~> mcrun -c vanadium_example.instr
* Translating instrument definition 'vanadium_example.instr' into C ...
* mcstas -t -o vanadium_example.c vanadium_example.instr
* Warning: 'Source_flat' is an obsolete component (not maintained).
* Compiling C source 'vanadium_example.c' ...
* gcc -g -O2 -o vanadium_example.out vanadium_example.c -lm
* mcstas-r.c: In function `cylinder_intersect':
* mcstas-r.c:3713: error: `tout' undeclared (first use in this function)
* mcstas-r.c:3713: error: (Each undeclared identifier is reported only once
* mcstas-r.c:3713: error: for each function it appears in.)
* ** Error exit **
* lp-07151:~>
*
* Please make simple tests of compilation etc. before committing...
*
* Revision 1.125  2006/03/01 16:06:25  farhi
* Fixed error in cylinder_intersect when trajectory is parallel to the cylinder axis (raised by T. Vanvuure).
*
* Revision 1.124  2005/12/12 13:43:14  farhi
* remove gridding on Matlab in-line plots
*
* Revision 1.123  2005/11/08 14:20:33  farhi
* misprint
*
* Revision 1.122  2005/11/08 13:37:49  farhi
* Warnings for formats are now easier to read
*
* Revision 1.121  2005/09/16 08:43:19  farhi
* Removed floor+0.5 in Monitor_nD
* Take care of ploting with bin centers in mcplot stuff (inline+matlab+scilab+octave...)
*
* Revision 1.120  2005/08/24 09:51:31  pkwi
* Beamstop and runtime modified according to Emmanuels remarks.
*
* To allow backpropagation in a specific component, use
*
* ALLOW_BACKPROP;
*
* before calling
*
* PROP_Z0;
*
* (One could consider making the backpropagation flag common to all propagation routines, should we do so?)
*
* Revision 1.119  2005/07/25 14:55:08  farhi
* DOC update:
* checked all parameter [unit] + text to be OK
* set all versions to CVS Revision
*
* Revision 1.118  2005/07/21 10:19:24  farhi
* Corrected big bug in randvec_*_rect routines when shooting 4PI
* (when one of the params is 0)
* 'circle' routine was OK.
*
* Revision 1.117  2005/07/05 12:04:22  farhi
* Solve bug with default values and non optional parameters
*
* Revision 1.116  2005/07/04 09:06:42  farhi
* test for scilab not bianry and large matrix -> warning more often...
*
* Revision 1.115  2005/06/29 15:08:49  lieutenant
* x values centred (for 1-dim PGPLOT plots) Bug 39
*
* Revision 1.114  2005/06/22 08:56:23  farhi
* Adding 'b' flag to fopen (new files) for binary support on Win32
*
* Revision 1.113  2005/06/20 08:04:18  farhi
* More cautious message for Low Stat
* Add rounding error check in coords_sub
*
* Revision 1.112  2005/05/07 14:29:01  lieutenant
* function coords_add: z=0 if abs(z)<1e-14 to prevent loss of neutrons by numerical rounding errors
*
* Revision 1.111  2005/03/30 21:37:21  farhi
* Corrected gravity bug at last after left test modification (A was replaced by 0 for comp testing, and not put back). Thanks Klaus ! Small time values replaced by 0 in 2nd order solve (Klaus).
*
* Revision 1.110  2005/03/23 14:41:11  farhi
* Added test not to overwrite/delete a temp file by itself
*
* Revision 1.109  2005/03/02 10:40:27  farhi
* Now displays warning for Low Statistics and large matrices in text mode for Matlab/Scilab
*
* Revision 1.108  2005/02/24 15:57:20  farhi
* FIXED gravity bug (probably OK). Gravity is not handled properly in other Guide elements. Will adapt so that it works better...
* The n.v was not computed using the actual 'v' values when reaching the guide side, but before propagation. So the velocity was not reflected, but scattered depending on the previous neutron position/velocity, bringing strange divergence effects.
* On other guide elements, should update the n.v term just before reflection, not computing it before propagation... This probably holds for some other components (monochromators ???) to be checked !
*
* Revision 1.107  2005/02/23 12:29:55  farhi
* FIXED GRAVITATION BUG: was in the choice of the intersection time (2nd order
* equation result) of trajectory with plane
*
* Revision 1.105  2005/02/17 15:54:56  farhi
* Added 'per bin' in labels if more that 1 bin. Requested by R. Cubitt
*
* Revision 1.104  2005/02/16 12:20:36  farhi
* Removed left space chars at end of lines
*
* Revision 1.103  2004/11/30 16:13:22  farhi
* Put back PROP_X0 and Y0 that are used in some contrib components
* Uses NOSIGNALS and set signal handling from that
*
* Revision 1.102  2004/11/29 14:29:02  farhi
* Show title as filename in 'Detector: ... "filename"' line if no file name given
*
* Revision 1.101  2004/11/16 13:35:47  farhi
* Correct HTML -> VRML data format pre selection. May be overridden when using the --format_data option (currently undocumented)
*
* Revision 1.100  2004/09/30 08:23:41  farhi
* Correct pointer mismatch in 'xlimits' for PGPLOT data files
*
* Revision 1.99  2004/09/21 12:25:02  farhi
* Reorganised code so that I/O functions are includable easely (for mcformat.c)
*
* Revision 1.97  2004/09/09 13:46:52  farhi
* Code clean-up
*
* Revision 1.96  2004/09/07 12:28:21  farhi
* Correct allocation bug SEGV in multi-format handling
*
* Revision 1.95  2004/09/03 13:51:07  farhi
* add extension automatically in data/sim files
* may use a format for sim files, and an oher for data, e.g. HTML/VRML.
* added --data_format option to handle 2nd file format.
*
* Revision 1.94  2004/09/01 14:03:41  farhi
* 1 new VRML format for single data files. requires more work for the 'sim' file
* 2 add more info in output file name headers about how to view data
* 3 re-arranged format structure fields in more logical way
* 4 checked all formats for valid export
* 5 compute and update y/z min/max for correct values in data block of files
* 6 correct bug in dynamic format fields alloction when replacing aliases
* 7 adding more field aliases
* 8 use more dynamic allocations to avoid local const variables
*
* Revision 1.93  2004/08/25 09:45:41  farhi
* Main change in the format definition specifications. Aliases are now available to ease maintenance and writing of new formats, e.g. %FIL instead of %2$s !!
*
* Revision 1.92  2004/08/04 10:38:08  farhi
* Added 'raw' data set support (N,p,sigma) -> (N,p,p2) in data files, so that this is additive (for better grid support)
*
* Revision 1.91  2004/07/30 14:49:15  farhi
* MPI update for usage with mcrun.
* Still done by Christophe Taton. CC=mpicc and CFLAGS = -DUSE_MPI.
* Execute (using mpich) with:
*           mpirun -np NumNodes -machinefile <file> instr.out parameters...
*      where <file> is text file that lists the machines to use
*
* Revision 1.90  2004/07/16 14:59:03  farhi
* MPI support. Requires to have mpi installed, and compile with
*    CC=mpicc and CFLAGS = -DUSE_MPI.
* Work done by Christophe Taton from ENSIMAG/Grenoble
* Execute (using mpich) with:
*    mpirun -np NumNodes -machinefile <file> instr.out parameters...
* where <file> is text file that lists the machines to use
*
* Revision 1.88  2004/06/30 15:06:06  farhi
* Solved 'pre' SEGV occuring when indenting/unindenting a Parameter block
* in a data file. Removed Date field in mcinfo_simulation, as this is now included
* in all data files.
*
* Revision 1.86  2004/06/16 14:03:07  farhi
* Corrected misprint
*
* Revision 1.85  2004/03/05 17:43:47  farhi
* Default instr parameters are now correctly handled in all instrument usage cases.
*
* Revision 1.84  2004/03/03 13:41:23  pkwi
* Corrected error in relation to instrument default values: 0's were used in all cases.
*
* Revision 1.83  2004/02/26 12:53:27  farhi
* Scilab format now enables more than one monitor file for a single component
* (e.g. Monitor_nD with multiple detectors).
*
* Revision 1.82  2004/02/23 12:48:42  farhi
* Additional check for default value and unset parameters
*
* Revision 1.81  2004/02/19 14:42:52  farhi
* Experimental Octave/OpenGENIE output format (for ISIS)
*
* Revision 1.80  2004/01/23 16:14:12  pkwi
* Updated version of Mersenne Twister algorithm. make test'ed ok on my machine.
*
* Revision 1.79  2003/11/28 18:08:32  farhi
* Corrected error for IDL import
*
* Revision 1.77  2003/10/22 15:51:26  farhi
* <instr> -i also displays default parameter values (if any), which may be
* read by mcgui for init of Run Simulation dialog
*
* Revision 1.76  2003/10/22 09:18:00  farhi
* Solved name conflict problem for Matlab/Scilab by adding 'mc_' prefix
* to all component/file field names. Works ok for both, and also in binary.
*
* Revision 1.75  2003/10/21 14:08:12  pkwi
* Rectangular focusing improved: Renamed randvec_target_rect to randvec_target_rect_angular. Wrote new randvec_target_rect routine, w/h in metres. Both routines use use component orientation (ROT_A_CURRENT_COMP) as input.
*
* Modifications to Res_sample and V_sample to match new features of the runtime.
*
* Revision 1.74  2003/10/21 11:54:48  farhi
* instrument default parameter value handling now works better
* either from args or from mcreadparam (prompt)
*
* Revision 1.73  2003/09/05 08:59:17  farhi
* added INSTRUMENT parameter default value grammar
* mcinputtable now has also default values
* mcreadpar now uses default values if parameter not given
* extended instr_formal parameter struct
* extended mcinputtable structure type
*
* Revision 1.72  2003/08/26 12:32:43  farhi
* Corrected 4PI random vector generation to retain initial vector length
*
* Revision 1.71  2003/08/20 09:25:00  farhi
* Add the instrument Source tag in scan files (origin of data !)
*
* Revision 1.70  2003/08/12 13:35:52  farhi
* displays known signals list in instrument help (-h)
*
* Revision 1.68  2003/06/17 14:21:54  farhi
* removed 'clear %4$s' in Scilab/Matlab 'end of section' format which
* caused pb when comp_name == file_name
*
* Revision 1.67  2003/06/12 10:22:00  farhi
* -i show info as McStas format, --info use MCSTAS_FORMAT or --format setting
*
* Revision 1.66  2003/06/10 11:29:58  pkwi
* Corrected multiple parse errors: Added two missing sets of curly brackets { } in parameter parsing function.
*
* Revision 1.65  2003/06/05 09:25:59  farhi
* restore header support in data files when --format option found
*
* Revision 1.64  2003/05/26 10:21:00  farhi
* Correct core dump for instrument STRING parameters in 'string printer'
*
* Revision 1.63  2003/05/20 11:54:38  farhi
* make sighandler not restart SAVE when already saving (USR2)
*
* Revision 1.62  2003/05/16 12:13:03  farhi
* added path rehash for Matlab mcload_inline
*
* Revision 1.61  2003/04/25 16:24:44  farhi
* corrected 4PI scattering from randvec_* functions causing mcdisplay to crash
* when using (0,0,0) vector for coordinate transformations
*
* Revision 1.60  2003/04/16 14:55:47  farhi
* Major change in saving data so that it's shown just like PGPLOT
* and axes+labels should follow data orientation (if transposed)
* when in binary mode, sets -a as default. Use +a to force text header
*
* Revision 1.59  2003/04/09 15:51:33  farhi
* Moved MCSTAS_FORMAT define
*
* Revision 1.58  2003/04/08 18:55:56  farhi
* Made XML format more NeXus compliant
*
* Revision 1.57  2003/04/07 11:50:50  farhi
* Extended the way mcplot:plotter is assigned. Set --portable ok
* Handle Scilab:Tk and ~GTk menu (shifted)
* Updated help in mcrun and mcstas-r.c
*
* Revision 1.56  2003/04/04 18:36:12  farhi
* Corrected $ and % chars for IDL format, conflicting with pfprintf (Dec/SGI)
*
* Revision 1.55  2003/04/04 15:11:08  farhi
* Use MCSTAS_FORMAT env var for default plotter, or use mcstas_config
* Corrected strlen(NULL pointer) for getenv(MCSTAS_FORMAT)==NULL
*
* Revision 1.54  2003/04/04 14:26:25  farhi
* Managed --no-runtime to work. Use MCSTAS_FORMAT env/define for default format
* Make --no-output-files still print out the integrated counts
*
* Revision 1.53  2003/02/18 09:10:52  farhi
* Just changed a message (warning for -a flag binary)
*
* Revision 1.51  2003/02/11 12:28:46  farhi
* Variouxs bug fixes after tests in the lib directory
* mcstas_r  : disable output with --no-out.. flag. Fix 1D McStas output
* read_table:corrected MC_SYS_DIR -> MCSTAS define
* monitor_nd-lib: fix Log(signal) log(coord)
* HOPG.trm: reduce 4000 points -> 400 which is enough and faster to resample
* Progress_bar: precent -> percent parameter
* CS: ----------------------------------------------------------------------
*
* Revision 1.50  2003/02/06 14:25:05  farhi
* Made --no-output-files work again and 1D McStas data 4 columns again
*
* : ----------------------------------------------------------------------
*
* Revision 1.7 2002/10/19 22:46:21 ef
*        gravitation for all with -g. Various output formats.
*
* Revision 1.6 2002/09/17 12:01:21 ef
*        changed randvec_target_sphere to circle
* added randvec_target_rect
*
* Revision 1.5 2002/09/03 19:48:01 ef
*        corrected randvec_target_sphere. created target_rect.
*
* Revision 1.4 2002/09/02 18:59:05 ef
*        moved adapt_tree functions to independent lib. Updated sighandler.
*
* Revision 1.3 2002/08/28 11:36:37 ef
*        Changed to lib/share/c code
*
* Revision 1.2 2001/10/10 11:36:37 ef
*        added signal handler
*
* Revision 1.1 1998/08/29 11:36:37 kn
*        Initial revision
*
*******************************************************************************/

#ifndef MCSTAS_R_H
#include "mcstas-r.h"
#endif
#ifdef DANSE
#include "mcstas-globals.h"
#endif

/*******************************************************************************
* The I/O format definitions and functions
*******************************************************************************/

#ifndef DANSE
#ifdef MC_ANCIENT_COMPATIBILITY
int mctraceenabled = 0;
int mcdefaultmain  = 0;
#endif
/* else defined directly in the McStas generated C code */

static   long mcseed                 = 0;
static   int  mcascii_only           = 0;
static   int  mcsingle_file          = 0;
static   long mcstartdate            = 0;
static   int  mcdisable_output_files = 0;
mcstatic int  mcgravitation          = 0;
mcstatic int  mcdotrace              = 0;
/* mcstatic FILE *mcsiminfo_file        = NULL; */
static   char *mcdirname             = NULL;
static   char *mcsiminfo_name        = "mcstas";
int      mcallowbackprop             = 0;
int      mcMagnet                    = 0;
/*the magnet stack*/
double*  mcMagnetData                = NULL;
Coords   mcMagnetPos;
Rotation mcMagnetRot;
char*    mcDetectorCustomHeader      = NULL;
char*    mcopenedfiles               = "";
long     mcopenedfiles_size          = 0;
#endif

/* mcMagneticField(x, y, z, t, Bx, By, Bz) */
void (*mcMagneticField) (double, double, double, double,
			 double*, double*, double*) = NULL;
void (*mcMagnetPrecession) (double, double, double, double, double, double,
			    double, double*, double*, double*, double, Coords, Rotation) = NULL;

/* Number of neutron histories to simulate. */
#ifndef DANSE
mcstatic unsigned long long int mcncount             = 1e6;
mcstatic unsigned long long int mcrun_num            = 0;
#endif

/* parameters handling ====================================================== */

/* Instrument input parameter type handling. */
/* mcparm_double: extract double value from 's' into 'vptr' */
static int
mcparm_double(char *s, void *vptr)
{
  char *p;
  double *v = (double *)vptr;

  if (!s) { *v = 0; return(1); }
  *v = strtod(s, &p);
  if(*s == '\0' || (p != NULL && *p != '\0') || errno == ERANGE)
    return 0;                        /* Failed */
  else
    return 1;                        /* Success */
}

/* mcparminfo_double: display parameter type double */
static char *
mcparminfo_double(char *parmname)
{
  return "double";
}

/* mcparmerror_double: display error message when failed extract double */
static void
mcparmerror_double(char *parm, char *val)
{
  fprintf(stderr, "Error: Invalid value '%s' for floating point parameter %s (mcparmerror_double)\n",
          val, parm);
}

/* mcparmprinter_double: convert double to string */
static void
mcparmprinter_double(char *f, void *vptr)
{
  double *v = (double *)vptr;
  sprintf(f, "%g", *v);
}

/* mcparm_int: extract int value from 's' into 'vptr' */
static int
mcparm_int(char *s, void *vptr)
{
  char *p;
  int *v = (int *)vptr;
  long x;

  if (!s) { *v = 0; return(1); }
  *v = 0;
  x = strtol(s, &p, 10);
  if(x < INT_MIN || x > INT_MAX)
    return 0;                        /* Under/overflow */
  *v = x;
  if(*s == '\0' || (p != NULL && *p != '\0') || errno == ERANGE)
    return 0;                        /* Failed */
  else
    return 1;                        /* Success */
}

/* mcparminfo_int: display parameter type int */
static char *
mcparminfo_int(char *parmname)
{
  return "int";
}

/* mcparmerror_int: display error message when failed extract int */
static void
mcparmerror_int(char *parm, char *val)
{
  fprintf(stderr, "Error: Invalid value '%s' for integer parameter %s (mcparmerror_int)\n",
          val, parm);
}

/* mcparmprinter_int: convert int to string */
static void
mcparmprinter_int(char *f, void *vptr)
{
  int *v = (int *)vptr;
  sprintf(f, "%d", *v);
}

/* mcparm_string: extract char* value from 's' into 'vptr' (copy) */
static int
mcparm_string(char *s, void *vptr)
{
  char **v = (char **)vptr;
  if (!s) { *v = NULL; return(1); }
  *v = (char *)malloc(strlen(s) + 1);
  if(*v == NULL)
  {
    exit(fprintf(stderr, "Error: Out of memory %li (mcparm_string).\n", (long)strlen(s) + 1));
  }
  strcpy(*v, s);
  return 1;                        /* Success */
}

/* mcparminfo_string: display parameter type string */
static char *
mcparminfo_string(char *parmname)
{
  return "string";
}

/* mcparmerror_string: display error message when failed extract string */
static void
mcparmerror_string(char *parm, char *val)
{
  fprintf(stderr, "Error: Invalid value '%s' for string parameter %s (mcparmerror_string)\n",
          val, parm);
}

/* mcparmprinter_string: convert string to string (including esc chars) */
static void
mcparmprinter_string(char *f, void *vptr)
{
  char **v = (char **)vptr;
  char *p;

  if (!*v) { *f='\0'; return; }
  strcpy(f, "");
  for(p = *v; *p != '\0'; p++)
  {
    switch(*p)
    {
      case '\n':
        strcat(f, "\\n");
        break;
      case '\r':
        strcat(f, "\\r");
        break;
      case '"':
        strcat(f, "\\\"");
        break;
      case '\\':
        strcat(f, "\\\\");
        break;
      default:
        strncat(f, p, 1);
    }
  }
  /* strcat(f, "\""); */
}

/* now we may define the parameter structure, using previous functions */
static struct
  {
    int (*getparm)(char *, void *);
    char * (*parminfo)(char *);
    void (*error)(char *, char *);
    void (*printer)(char *, void *);
  } mcinputtypes[] =
      {
        mcparm_double, mcparminfo_double, mcparmerror_double,
                mcparmprinter_double,
        mcparm_int, mcparminfo_int, mcparmerror_int,
                mcparmprinter_int,
        mcparm_string, mcparminfo_string, mcparmerror_string,
                mcparmprinter_string
      };

/* mcestimate_error: compute sigma from N,p,p2 in Gaussian large numbers approx */
double mcestimate_error(double N, double p1, double p2)
{
  double pmean, n1;
  if(N <= 1)
    return p1;
  pmean = p1 / N;
  n1 = N - 1;
  /* Note: underflow may cause p2 to become zero; the fabs() below guards
     against this. */
  return sqrt((N/n1)*fabs(p2 - pmean*pmean));
}

/* mcset_ncount: set total number of neutrons to generate */
void mcset_ncount(unsigned long long int count)
{
  mcncount = count;
}

/* mcget_ncount: get total number of neutrons to generate */
unsigned long long int mcget_ncount(void)
{
  return mcncount;
}

/* mcget_run_num: get curent number of neutrons in TRACE */
unsigned long long int mcget_run_num(void)
{
  return mcrun_num;
}

#ifdef USE_MPI
/* MPI rank */
static int mpi_node_rank;
static int mpi_node_root = 0;

/*******************************************************************************
* mc_MPI_Reduce: Gathers arrays from MPI nodes using Reduce function.
*******************************************************************************/
int mc_MPI_Reduce(void *sbuf, void *rbuf,
                  int count, MPI_Datatype dtype,
                  MPI_Op op, int root, MPI_Comm comm)
{
  void *lrbuf;
  int dsize;
  int res= MPI_SUCCESS;
  
  if (!sbuf || count <= 0) return(-1);

  MPI_Type_size(dtype, &dsize);
  lrbuf = malloc(count*dsize);
  if (lrbuf == NULL)
    exit(fprintf(stderr, "Error: Out of memory %li (mc_MPI_Reduce).\n", (long)count*dsize));
  /* we must cut the buffer into blocks not exceeding the MPI max buffer size of 32000 */
  long offset=0;
  int  length=MPI_REDUCE_BLOCKSIZE; /* defined in mcstas.h */
  while (offset < count && res == MPI_SUCCESS) {
    if (!length || offset+length > count-1) length=count-offset; else length=MPI_REDUCE_BLOCKSIZE;
    res = MPI_Reduce((void*)(sbuf+offset*dsize), (void*)(lrbuf+offset*dsize), length, dtype, op, root, comm);
    offset += length;
  }

  if(res != MPI_SUCCESS)
    fprintf(stderr, "Warning: node %i: MPI_Reduce error (mc_MPI_Reduce) at offset=%li, count=%i\n", mpi_node_rank, offset, count);

  if(mpi_node_rank == root)
    memcpy(rbuf, lrbuf, count*dsize);

  free(lrbuf);
  return res;
}

/*******************************************************************************
* mc_MPI_Send: Send array to MPI node by blocks to avoid buffer limit
*******************************************************************************/
int mc_MPI_Send(void *sbuf, 
                  int count, MPI_Datatype dtype,
                  int dest, MPI_Comm comm)
{
  int dsize;
  int res= MPI_SUCCESS;
  
  if (!sbuf || count <= 0) return(-1);

  MPI_Type_size(dtype, &dsize);

  long offset=0;
  int  tag=1;
  int  length=MPI_REDUCE_BLOCKSIZE; /* defined in mcstas.h */
  while (offset < count && res == MPI_SUCCESS) {
    if (offset+length > count-1) length=count-offset; else length=MPI_REDUCE_BLOCKSIZE;
    res = MPI_Send((void*)(sbuf+offset*dsize), length, dtype, dest, tag++, comm);
    offset += length;
  }

  if(res != MPI_SUCCESS)
    fprintf(stderr, "Warning: node %i: MPI_Send error (mc_MPI_Send) at offset=%li, count=%i tag=%i\n", mpi_node_rank, offset, count, tag);

  return res;
}

/*******************************************************************************
* mc_MPI_Recv: Receives arrays from MPI nodes by blocks to avoid buffer limit
*             the buffer must have been allocated previously.
*******************************************************************************/
int mc_MPI_Recv(void *sbuf, 
                  int count, MPI_Datatype dtype,
                  int source, MPI_Comm comm)
{
  int dsize;
  int res= MPI_SUCCESS;
  
  if (!sbuf || count <= 0) return(-1);

  MPI_Type_size(dtype, &dsize);

  long offset=0;
  int  tag=1;
  int  length=MPI_REDUCE_BLOCKSIZE; /* defined in mcstas.h */
  while (offset < count && res == MPI_SUCCESS) {
    if (offset+length > count-1) length=count-offset; else length=MPI_REDUCE_BLOCKSIZE;
    res = MPI_Recv((void*)(sbuf+offset*dsize), length, dtype, source, tag++, comm, MPI_STATUS_IGNORE);
    offset += length;
  }

  if(res != MPI_SUCCESS)
    fprintf(stderr, "Warning: node %i: MPI_Send error (mc_MPI_Send) at offset=%li, count=%i tag=%i\n", mpi_node_rank, offset, count, tag);

  return res;
}

#endif /* USE_MPI */

/* Multiple output format support. ========================================== */
#ifdef USE_NEXUS
#define mcNUMFORMATS 9
#else
#define mcNUMFORMATS 8
#endif
#ifndef MCSTAS_FORMAT
#define MCSTAS_FORMAT "McStas"  /* default format */
#endif

#ifndef DANSE
mcstatic struct mcformats_struct mcformat;
mcstatic struct mcformats_struct mcformat_data;
#endif

/*******************************************************************************
* Definition of output formats. structure defined in mcstas-r.h
* Name aliases are defined in mcuse_format_* functions (below)
*******************************************************************************/

mcstatic struct mcformats_struct mcformats[mcNUMFORMATS] = {
  { "McStas", "sim",
    "%PREFormat: %FMT file. Use mcplot/PGPLOT to view.\n"
      "%PREURL:    http://www.mcstas.org/\n"
      "%PREEditor: %USR\n"
      "%PRECreator:%SRC simulation (McStas " MCSTAS_VERSION ")\n"
      "%PREDate:   Simulation started (%DATL) %DAT\n"
      "%PREFile:   %FIL\n",
    "%PREEndDate:%DAT\n",
    "%PREbegin %TYP\n",
    "%PREend %TYP\n",
    "%PRE%NAM: %VAL\n",
    "", "",
    "%PREErrors [%PAR/%FIL]: \n", "",
    "%PREEvents [%PAR/%FIL]: \n", "" },
  { "Scilab", "sci",
    "function mc_%VPA = get_%VPA(p)\n"
      "// %FMT function issued from McStas on %DAT\n"
      "// McStas simulation %SRC: %FIL %FMT\n"
      "// Import data using scilab> exec('%VPA.sci',-1); s=get_%VPA(); and s=get_%VPA('plot'); to plot\n"
      "mode(-1); //silent execution\n"
      "if argn(2) > 0, p=1; else p=0; end\n"
      "mc_%VPA = struct();\n"
      "mc_%VPA.Format ='%FMT';\n"
      "mc_%VPA.URL    ='http://www.mcstas.org';\n"
      "mc_%VPA.Editor ='%USR';\n"
      "mc_%VPA.Creator='%SRC McStas " MCSTAS_VERSION " simulation';\n"
      "mc_%VPA.Date   =%DATL; // for getdate\n"
      "mc_%VPA.File   ='%FIL';\n",
    "mc_%VPA.EndDate=%DATL; // for getdate\nendfunction\n"
    "function d=mcload_inline(d)\n"
      "// local inline func to load data\n"
      "execstr(['S=['+part(d.type,10:(length(d.type)-1))+'];']);\n"
      "if ~length(d.data)\n"
      " if ~length(strindex(d.format, 'binary'))\n"
      "  exec(d.filename,-1);p=d.parent;\n"
      "  if ~execstr('d2='+d.func+'();','errcatch'),d=d2; d.parent=p;end\n"
      " else\n"
      "  if length(strindex(d.format, 'float')), t='f';\n"
      "  elseif length(strindex(d.format, 'double')), t='d';\n"
      "  else return; end\n"
      "  fid=mopen(d.filename, 'rb');\n"
      "  pS = prod(S);\n"
      "  x = mget(3*pS, t, fid);\n"
      "  d.data  =matrix(x(1:pS), S);\n"
      "  if length(x) >= 3*pS,\n"
      "  d.errors=matrix(x((pS+1):(2*pS)), S);\n"
      "  d.events=matrix(x((2*pS+1):(3*pS)), S);end\n"
      "  mclose(fid);\n"
      "  return\n"
      " end\n"
      "end\n"
      "endfunction\n"
      "function d=mcplot_inline(d,p)\n"
      "// local inline func to plot data\n"
      "if ~length(strindex(d.type,'0d')), d=mcload_inline(d); end\n"
      "if ~p, return; end;\n"
      "execstr(['l=[',d.xylimits,'];']); S=size(d.data);\n"
      "t1=['['+d.parent+'] '+d.filename+': '+d.title];t = [t1;['  '+d.variables+'=['+d.values+']'];['  '+d.signal];['  '+d.statistics]];\n"
      "mprintf('%%s\\n',t(:));\n"
      "if length(strindex(d.type,'0d')),return; end\n"
      "w=winsid();if length(w),w=w($)+1; else w=0; end\n"
      "xbasr(w); xset('window',w);\n"
      "if length(strindex(d.type,'2d'))\n"
      " if S(2) > 1, d.stepx=abs(l(1)-l(2))/(S(2)-1); else d.stepx=0; end\n"
      " if S(1) > 1, d.stepy=abs(l(3)-l(4))/(S(1)-1); else d.stepy=0; end\n"
      " d.x=linspace(l(1)+d.stepx/2,l(2)-d.stepx/2,S(2));\n"
      " d.y=linspace(l(3)+d.stepy/2,l(4)-d.stepy/2,S(1)); z=d.data;\n"
      " xlab=d.xlabel; ylab=d.ylabel; x=d.x; y=d.y;\n"
      " fz=max(abs(z));fx=max(abs(d.x));fy=max(abs(d.y));\n"
      " if fx>0,fx=round(log10(fx)); x=x/10^fx; xlab=xlab+' [*10^'+string(fx)+']'; end\n"
      " if fy>0,fy=round(log10(fy)); y=y/10^fy; ylab=ylab+' [*10^'+string(fy)+']'; end\n"
      " if fz>0,fz=round(log10(fz)); z=z/10^fz; t1=t1+' [*10^'+string(fz)+']'; end\n"
      " xset('colormap',hotcolormap(64));\n"
      " plot3d1(x,y,z',90,0,xlab+'@'+ylab+'@'+d.zlabel,[-1,2,4]); xtitle(t);\n"
      "else\n"
      " if max(S) > 1, d.stepx=abs(l(1)-l(2))/(max(S)-1); else d.stepx=0; end\n"
      " d.x=linspace(l(1)+d.stepx/2,l(2)-d.stepx/2,max(S));\n"
      " plot2d(d.x,d.data);xtitle(t,d.xlabel,d.ylabel);\n"
      "end\n"
      "xname(t1);\nendfunction\n"
    "mc_%VPA=get_%VPA();\n",
    "// Section %TYP [%NAM] (level %LVL)\n"
      "%PREt=[]; execstr('t=mc_%VNA.class','errcatch'); if ~length(t), mc_%VNA = struct(); end; mc_%VNA.class = '%TYP';",
    "%PREmc_%VPA.mc_%VNA = 0; mc_%VPA.mc_%VNA = mc_%VNA;\n",
    "%PREmc_%SEC.%NAM = '%VAL';\n",
    "%PREmc_%VPA.func='get_%VPA';\n%PREmc_%VPA.data = [ \n",
    " ]; // end of data\n%PREif length(mc_%VPA.data) == 0, single_file=0; else single_file=1; end\n%PREmc_%VPA=mcplot_inline(mc_%VPA,p);\n",
    "%PREerrors = [ \n",
    " ]; // end of errors\n%PREif single_file == 1, mc_%VPA.errors=errors; end\n",
    "%PREevents = [ \n",
    " ]; // end of events\n%PREif single_file == 1, mc_%VPA.events=events; end\n"},
  { "Matlab", "m",
    "function mc_%VPA = get_%VPA(p)\n"
      "%% %FMT function issued from McStas on %DAT\n"
      "%% McStas simulation %SRC: %FIL\n"
      "%% Import data using matlab> s=%VPA; and s=%VPA('plot'); to plot\n"
      "if nargout == 0 | nargin > 0, p=1; else p=0; end\n"
      "mc_%VPA.Format ='%FMT';\n"
      "mc_%VPA.URL    ='http://www.mcstas.org';\n"
      "mc_%VPA.Editor ='%USR';\n"
      "mc_%VPA.Creator='%SRC McStas " MCSTAS_VERSION " simulation';\n"
      "mc_%VPA.Date   =%DATL; %% for datestr\n"
      "mc_%VPA.File   ='%FIL';\n",
    "mc_%VPA.EndDate=%DATL; %% for datestr\n"
      "function d=mcload_inline(d)\n"
      "%% local inline function to load data\n"
      "S=d.type; eval(['S=[ ' S(10:(length(S)-1)) ' ];']);\n"
      "if isempty(d.data)\n"
      " if ~length(findstr(d.format, 'binary'))\n"
      "  if ~strcmp(d.filename,[d.func,'.m']) copyfile(d.filename,[d.func,'.m']); end\n"
      "  p=d.parent;path(path);\n"
      "  eval(['d=',d.func,';']);d.parent=p;\n"
      "  if ~strcmp(d.filename,[d.func,'.m']) delete([d.func,'.m']); end\n"
      " else\n"
      "  if length(findstr(d.format, 'float')), t='single';\n"
      "  elseif length(findstr(d.format, 'double')), t='double';\n"
      "  else return; end\n"
      "  if length(S) == 1, S=[S 1]; end\n"
      "  fid=fopen(d.filename, 'r');\n"
      "  pS = prod(S);\n"
      "  x = fread(fid, 3*pS, t);\n"
      "  d.data  =reshape(x(1:pS), S);\n"
      "  if prod(size(x)) >= 3*pS,\n"
      "  d.errors=reshape(x((pS+1):(2*pS)), S);\n"
      "  d.events=reshape(x((2*pS+1):(3*pS)), S);end\n"
      "  fclose(fid);\n"
      "  return\n"
      " end\n"
      "end\n"
      "return;\n"
      "function d=mcplot_inline(d,p)\n"
      "%% local inline function to plot data\n"
      "if isempty(findstr(d.type,'0d')), d=mcload_inline(d); end\nif ~p, return; end;\n"
      "eval(['l=[',d.xylimits,'];']); S=size(d.data);\n"
      "t1=['[',d.parent,'] ',d.filename,': ',d.title];t = strvcat(t1,['  ',d.variables,'=[',d.values,']'],['  ',d.signal],['  ',d.statistics]);\n"
      "disp(t);\n"
      "if ~isempty(findstr(d.type,'0d')), return; end\n"
      "figure; if ~isempty(findstr(d.type,'2d'))\n"
      " if S(2) > 1, d.stepx=abs(l(1)-l(2))/(S(2)-1); else d.stepx=0; end\n"
      " if S(1) > 1, d.stepy=abs(l(3)-l(4))/(S(1)-1); else d.stepy=0; end\n"
      " d.x=linspace(l(1)+d.stepx/2,l(2)-d.stepx/2,S(2));\n"
      " d.y=linspace(l(3)+d.stepy/2,l(4)-d.stepy/2,S(1));\n"
      " surface(d.x,d.y,d.data); xlim([l(1) l(2)]); ylim([l(3) l(4)]); shading flat;\n"
      "else\n"
      " if max(S) > 1, d.stepx=abs(l(1)-l(2))/(max(S)-1); else d.stepx=0; end\n"
      " d.x=linspace(l(1)+d.stepx/2,l(2)-d.stepx/2,max(S));\n"
      " plot(d.x,d.data); xlim([l(1) l(2)]);\n"
      "end\n"
      "xlabel(d.xlabel); ylabel(d.ylabel); title(t); \n"
      "set(gca,'position',[.18,.18,.7,.65]); set(gcf,'name',t1);grid on;\n"
      "if ~isempty(findstr(d.type,'2d')), colorbar; end\n",
    "%% Section %TYP [%NAM] (level %LVL)\n"
      "mc_%VNA.class = '%TYP';",
    "mc_%VPA.mc_%VNA = mc_%VNA;\n",
    "%PREmc_%SEC.%NAM = '%VAL';\n",
    "%PREmc_%VPA.func='%VPA';\n%PREmc_%VPA.data = [ \n",
    " ]; %% end of data\nif length(mc_%VPA.data) == 0, single_file=0; else single_file=1; end\nmc_%VPA=mcplot_inline(mc_%VPA,p);\n",
    "%PREerrors = [ \n",
    " ]; %% end of errors\nif single_file, mc_%VPA.errors=errors; end\n",
    "%PREevents = [ \n",
    " ]; %% end of events\nif single_file, mc_%VPA.events=events; end\n"},
  { "IDL", "pro",
    "; McStas/IDL file. Import using idl> s=%VPA() and s=%VPA(/plot) to plot\n"
      "function mcload_inline,d\n"
      "; local inline function to load external data\n"
      "S=d.type & a=execute('S=long(['+strmid(S,9,strlen(S)-10)+'])')\n"
      "if strpos(d.format, 'binary') lt 0 then begin\n"
      " p=d.parent\n"
      " x=read_binary(d.filename)\n"
      " get_lun, lun\n"
      " openw,lun,d.func+'.pro'\n"
      " writeu, lun,x\n"
      " free_lun,lun\n"
      " resolve_routine, d.func, /is_func, /no\n"
      " d=call_function(d.func)\n"
      "endif else begin\n"
      " if strpos(d.format, 'float') ge 0 then t=4 $\n"
      " else if strpos(d.format, 'double') ge 0 then t=5 $\n"
      " else return,d\n"
      " x=read_binary(d.filename, data_type=t)\n"
      " pS=n_elements(S)\nif pS eq 1 then pS=long(S) $\n"
      " else if pS eq 2 then pS=long(S(0)*S(1)) $\n"
      " else pS=long(S(0)*S(1)*S(2))\n"
      " pS=pS(0)\nstv,d,'data',reform(x(0:(pS-1)),S)\n"
      " d.data=transpose(d.data)\n"
      " if n_elements(x) ge long(3*pS) then begin\n"
      "  stv,d,'errors',reform(x(pS:(2*pS-1)),S)\n"
      "  stv,d,'events',reform(x((2*pS):(3*pS-1)),S)\n"
      "  d.errors=transpose(d.errors)\n"
      "  d.events=transpose(d.events)\n"
      " endif\n"
      "endelse\n"
      "return,d\nend ; FUN load\n"
    "function mcplot_inline,d,p\n"
      "; local inline function to plot data\n"
      "if size(d.data,/typ) eq 7 and strpos(d.type,'0d') lt 0 then d=mcload_inline(d)\n"
      "if p eq 0 or strpos(d.type,'0d') ge 0 then return, d\n"
      "S=d.type & a=execute('S=long(['+strmid(S,9,strlen(S)-10)+'])')\n"
      "stv,d,'data',reform(d.data,S,/over)\n"
      "if total(strpos(tag_names(d),'ERRORS')+1) gt 0 then begin\n"
      " stv,d,'errors',reform(d.errors,S,/over)\n"
      " stv,d,'events',reform(d.events,S,/over)\n"
      "endif\n"
      "d.xylimits=strjoin(strsplit(d.xylimits,' ',/extract),',') & a=execute('l=['+d.xylimits+']')\n"
      "t1='['+d.parent+'] '+d.filename+': '+d.title\n"
      "t=[t1,'  '+d.variables+'=['+d.values+']','  '+d.signal,'  '+d.statistics]\n"
      "print,t\n"
      "if strpos(d.type,'0d') ge 0 then return,d\n"
      "d.xlabel=strjoin(strsplit(d.xlabel,'`!\"^&*()-+=|\\,.<>/?@''~#{[}]',/extract),'_')\n"
      "d.ylabel=strjoin(strsplit(d.ylabel,'`!\"^&*()-+=|\\,.<>/?@''~#{[}]',/extract),'_')\n"
      "stv,d,'x',l(0)+indgen(S(0))*(l(1)-l(0))/S(0)\n"
      "if strpos(d.type,'2d') ge 0 then begin\n"
      "  name={DATA:d.func,IX:d.xlabel,IY:d.ylabel}\n"
      "  stv,d,'y',l(2)+indgen(S(1))*(l(3)-l(2))/S(1)\n"
      "  live_surface,d.data,xindependent=d.x,yindependent=d.y,name=name,reference_out=Win\n"
      "endif else begin\n"
      "  name={DATA:d.func,I:d.xlabel}\n"
      "  live_plot,d.data,independent=d.x,name=name,reference_out=Win\n"
      "endelse\n"
      "live_text,t,Window_In=Win.Win,location=[0.3,0.9]\n"
      "return,d\nend ; FUN plot\n"
    "pro stv,S,T,V\n"
      "; procedure set-tag-value that does S.T=V\n"
      "sv=size(V)\n"
      "T=strupcase(T)\n"
      "TL=strupcase(tag_names(S))\n"
      "id=where(TL eq T)\n"
      "sz=[0,0,0]\n"
      "vd=n_elements(sv)-2\n"
      "type=sv[vd]\n"
      "if id(0) ge 0 then d=execute('sz=SIZE(S.'+T+')')\n"
      "if (sz(sz(0)+1) ne sv(sv(0)+1)) or (sz(0) ne sv(0)) $\n"
      "  or (sz(sz(0)+2) ne sv(sv(0)+2)) $\n"
      "  or type eq 8 then begin\n"
      " ES = ''\n"
      " for k=0,n_elements(TL)-1 do begin\n"
      "  case TL(k) of\n"
      "   T:\n"
      "   else: ES=ES+','+TL(k)+':S.'+TL(k)\n"
      "  endcase\n"
      " endfor\n"
      " d=execute('S={'+T+':V'+ES+'}')\n"
      "endif else d=execute('S.'+T+'=V')\n"
      "end ; PRO stv\n"
    "function %VPA,plot=plot\n"
      "; %FMT function issued from McStas on %DAT\n"
      "; McStas simulation %SRC: %FIL\n"
      "; import using s=%VPA() and s=%VPA(/plot) to plot\n"
      "if keyword_set(plot) then p=1 else p=0\n"
      "%7$s={Format:'%FMT',URL:'http://www.mcstas.org',"
      "Editor:'%USR',$\n"
      "Creator:'%SRC McStas " MCSTAS_VERSION " simulation',$\n"
      "Date:%DATL,"
      "File:'%FIL'}\n",
    "stv,%VPA,'EndDate',%DATL ; for systime\nreturn, %VPA\nend\n",
    "; Section %TYP [%NAM] (level %LVL)\n"
      "%PRE%VNA={class:'%TYP'}\n",
    "%PREstv,%VPA,'%VNA',%VNA\n",
    "%PREstv,%SEC,'%NAM','%VAL'\n",
    "%PREstv,%VPA,'func','%VPA' & data=[ $\n",
    " ]\n%PREif size(data,/type) eq 7 then single_file=0 else single_file=1\n"
    "%PREstv,%VPA,'data',data & data=0 & %VPA=mcplot_inline(%VPA,p)\n",
    "%PREif single_file ne 0 then begin errors=[ ",
    " ]\n%PREstv,%VPA,'errors',reform(errors,%MDIM,%NDIM,/over) & errors=0\n%PREendif\n",
    "%PREif single_file ne 0 then begin events=[ ",
    " ]\n%PREstv,%VPA,'events',reform(events,%MDIM,%NDIM,/over) & events=0\n%PREendif\n\n"},
  { "XML", "xml",
    "<?xml version=\"1.0\" ?>\n<!--\n"
      "URL:    http://www.nexusformat.org/\n"
      "Editor: %USR\n"
      "Creator:%SRC McStas " MCSTAS_VERSION " [www.mcstas.org].\n"
      "Date:   Simulation started (%DATL) %DAT\n"
      "File:   %FIL\n"
      "View with Mozilla, InternetExplorer, gxmlviewer, kxmleditor\n-->\n"
      "<NX%PAR file_name=\"%FIL\" file_time=\"%DAT\" user=\"%USR\">\n"
        "<NXentry name=\"McStas " MCSTAS_VERSION "\"><start_time>%DAT</start_time>\n",
    "<end_time>%DAT</end_time></NXentry></NX%PAR>\n<!-- EndDate:%DAT -->\n",
    "%PRE<NX%TYP name=\"%NAM\">\n",
    "%PRE</NX%TYP>\n",
    "%PRE<%NAM>%VAL</%NAM>\n",
    "%PRE<%XVL long_name=\"%XLA\" axis=\"1\" primary=\"1\" min=\"%XMIN\""
        " max=\"%XMAX\" dims=\"%MDIM\" range=\"1\"></%XVL>\n"
      "%PRE<%YVL long_name=\"%YLA\" axis=\"2\" primary=\"1\" min=\"%YMIN\""
        " max=\"%YMAX\" dims=\"%NDIM\" range=\"1\"></%YVL>\n"
      "%PRE<%ZVL long_name=\"%ZLA\" axis=\"3\" primary=\"1\" min=\"%ZMIN\""
        " max=\"%ZMAX\" dims=\"%PDIM\" range=\"1\"></%ZVL>\n"
      "%PRE<data long_name=\"%TITL\" signal=\"1\"  axis=\"[%XVL,%YVL,%ZVL]\" file_name=\"%FIL\">\n",
    "%PRE</data>\n",
    "%PRE<errors>\n", "%PRE</errors>\n",
    "%PRE<monitor>\n", "%PRE</monitor>\n"},
  { "HTML", "html",
    "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD %DAT//EN\"\n"
      "\"http://www.w3.org/TR/html4/strict.dtd\">\n"
      "<HTML><HEAD><META name=\"Author\" content=\"%PAR\">\n"
      "<META name=\"Creator\" content=\"%PAR (%SRC) McStas " MCSTAS_VERSION " [www.mcstas.org] simulation\">\n"
      "<META name=\"Date\" content=\"%DAT\">\n"
      "<TITLE>[McStas %PAR (%SRC)]%FIL</TITLE></HEAD>\n"
      "<BODY><center><h1><a name=\"%PAR\">"
        "McStas simulation %SRC (%SRC): Result file %FIL.html</a></h1></center><br>\n"
        "This simulation report was automatically created by"
        " <a href=\"http://www.mcstas.org/\"><i>McStas " MCSTAS_VERSION "</i></a><br>\n"
        "<pre>User:   %USR<br>\n"
        "%PRECreator: <a href=\"%SRC\">%SRC</a> %PAR McStas simulation<br>\n"
        "%PREFormat:  %FMT<br>\n"
        "%PREDate:    (%DATL) %DAT<br></pre>\n"
        "VRML viewers may be obtained at <a href=\"http://cic.nist.gov/vrml/vbdetect.html\">http://cic.nist.gov/vrml/vbdetect.html</a>\n",
    "<b>EndDate: </b>(%DATL) %DAT<br></BODY></HTML>\n",
    "%PRE<h%LVL><a name=\"%NAM\">%TYP %NAM</a></h%LVL> "
      "[child of <a href=\"#%PAR\">%PAR</a>]<br>\n",
    "[end of <a href=\"#%NAM\">%TYP %NAM</a>]<br>\n",
    "%PRE<b>%NAM: </b>%VAL<br>\n",
    "%PRE<b>DATA</b><br><center><embed src=\"%FIL\" type=\"model/vrml\" width=\"75%%\" height=\"50%%\"></embed><br>File <a href=\"%FIL\">%FIL [VRML format]</a></center><br>\n", "%PREEnd of DATA<br>\n",
    "%PRE<b>ERRORS</b><br>\n","%PREEnd of ERRORS<br>\n",
    "%PRE<b>EVENTS</b><br>\n", "%PREEnd of EVENTS<br>\n"},
  { "Octave", "m",
    "function mc_%VPA = get_%VPA(p)\n"
      "%% %FMT function issued from McStas on %DAT\n"
      "%% McStas simulation %SRC: %FIL\n"
      "%% Import data using octave> s=%VPA(); and plot with s=%VPA('plot');\n"
      "if nargin > 0, p=1; else p=0; end\n"
      "mc_%VPA.Format ='%FMT';\n"
      "mc_%VPA.URL    ='http://www.mcstas.org';\n"
      "mc_%VPA.Editor ='%USR';\n"
      "mc_%VPA.Creator='%SRC McStas " MCSTAS_VERSION " simulation';\n"
      "mc_%VPA.Date   =%DATL; %% for datestr\n"
      "mc_%VPA.File   ='%FIL';\n",
    "mc_%VPA.EndDate=%DATL; %% for datestr\nendfunction\n"
      "if exist('mcload_inline'), return; end\n"
      "function d=mcload_inline(d)\n"
      "%% local inline function to load data\n"
      "S=d.type; eval(['S=[ ' S(10:(length(S)-1)) ' ];']);\n"
      "if isempty(d.data)\n"
      " if ~length(findstr(d.format, 'binary'))\n"
      "  source(d.filename);p=d.parent;\n"
      "  eval(['d=get_',d.func,';']);d.parent=p;\n"
      " else\n"
      "  if length(findstr(d.format, 'float')), t='float';\n"
      "  elseif length(findstr(d.format, 'double')), t='double';\n"
      "  else return; end\n"
      "  if length(S) == 1, S=[S 1]; end\n"
      "  fid=fopen(d.filename, 'r');\n"
      "  pS = prod(S);\n"
      "  x = fread(fid, 3*pS, t);\n"
      "  d.data  =reshape(x(1:pS), S);\n"
      "  if prod(size(x)) >= 3*pS,\n"
      "  d.errors=reshape(x((pS+1):(2*pS)), S);\n"
      "  d.events=reshape(x((2*pS+1):(3*pS)), S);end\n"
      "  fclose(fid);\n"
      "  return\n"
      " end\n"
      "end\n"
      "return;\nendfunction\n\n"
      "function d=mcplot_inline(d,p)\n"
      "%% local inline function to plot data\n"
      "if isempty(findstr(d.type,'0d')), d=mcload_inline(d); end\nif ~p, return; end;\n"
      "eval(['l=[',d.xylimits,'];']); S=size(d.data);\n"
      "t1=['[',d.parent,'] ',d.filename,': ',d.title];t = strcat(t1,['  ',d.variables,'=[',d.values,']'],['  ',d.signal],['  ',d.statistics]);\n"
      "disp(t);\n"
      "if ~isempty(findstr(d.type,'0d')), return; end\n"
      "xlabel(d.xlabel); ylabel(d.ylabel); title(t);"
      "figure; if ~isempty(findstr(d.type,'2d'))\n"
      " if S(2) > 1, d.stepx=abs(l(1)-l(2))/(S(2)-1); else d.stepx=0; end\n"
      " if S(1) > 1, d.stepy=abs(l(3)-l(4))/(S(1)-1); else d.stepy=0; end\n"
      " d.x=linspace(l(1)+d.stepx/2,l(2)-d.stepx/2,S(2));\n"
      " d.y=linspace(l(3)+d.stepy/2,l(4)-d.stepy/2,S(1));\n"
      " mesh(d.x,d.y,d.data);\n"
      "else\n"
      " if max(S) > 1, d.stepx=abs(l(1)-l(2))/(max(S)-1); else d.stepx=0; end\n"
      " d.x=linspace(l(1)+d.stepx/2,l(2)-d.stepx/2,max(S));\n"
      " plot(d.x,d.data);\n"
      "end\nendfunction\n",
    "%% Section %TYP [%NAM] (level %LVL)\n"
      "mc_%VNA.class = '%TYP';",
    "mc_%VPA.mc_%VNA = mc_%VNA;\n",
    "%PREmc_%SEC.%NAM = '%VAL';\n",
    "%PREmc_%VPA.func='%VPA';\n%PREmc_%VPA.data = [ \n",
    " ]; %% end of data\nif length(mc_%VPA.data) == 0, single_file=0; else single_file=1; end\nmc_%VPA=mcplot_inline(mc_%VPA,p);\n",
    "%PREerrors = [ \n",
    " ]; %% end of errors\nif single_file, mc_%VPA.errors=errors; end\n",
    "%PREevents = [ \n",
    " ]; %% end of events\nif single_file, mc_%VPA.events=events; end\n"},
  { "VRML", "wrl",
    "#VRML V2.0 utf8\n%PREFormat: %FMT file\n"
      "%PREuse freeWRL, openvrml, vrmlview, CosmoPlayer, Cortona, Octaga... to view file\n"
      "WorldInfo {\n"
      "title \"%SRC/%FIL simulation Data\"\n"
      "info [ \"URL:    http://www.mcstas.org/\"\n"
      "       \"Editor: %USR\"\n"
      "       \"Creator:%SRC simulation (McStas)\"\n"
      "       \"Date:   Simulation started (%DATL) %DAT\"\n"
      "       \"File:   %FIL\" ]\n}\n"
      "Background { skyAngle [ 1.57 1.57] skyColor [0 0 1, 1 1 1, 0.1 0 0] }\n",
    "%PREEndDate:%DAT\n",
    "%PREbegin %TYP %PAR\n",
    "%PREend %TYP %PAR\n",
    "%PRE%SEC.%NAM= '%VAL'\n",
    "%PREThe Proto that contains data values and objects to plot these\n"
      "PROTO I_ERR_N_%VPA [\n"
      "%PREthe PROTO parameters\n"
      "  field MFFloat Data [ ]\n"
      "  field MFFloat Errors [ ]\n"
      "  field MFFloat Ncounts [ ]\n"
      "] { %PREThe plotting objects/methods in the Proto\n"
      "  %PREdraw a small sphere at the origin\n"
      "  DEF Data_%VPA Group {\n"
      "  children [\n"
      "    DEF CoordinateOrigin Group {\n"
      "      children [\n"
      "        Transform { translation  0 0 0 }\n"
      "        Shape { \n"
      "          appearance Appearance { \n"
      "            material Material {\n"
      "              diffuseColor 1.0 1.0 0.0\n"
      "              transparency 0.5 } }\n"
      "          geometry Sphere { radius .01 } \n"
      "    } ] }\n"
      "    %PREdefintion of the arrow allong Y axis\n"
      "    DEF ARROW Group {\n"
      "      children [\n"
      "        Transform {\n"
      "          translation 0 0.5 0\n"
      "          children [\n"
      "            Shape {\n"
      "              appearance DEF ARROW_APPEARANCE Appearance {\n"
      "                material Material {\n"
      "                  diffuseColor .3 .3 1\n"
      "                  emissiveColor .1 .1 .33\n"
      "                }\n"
      "              }\n"
      "              geometry Cylinder {\n"
      "                bottom FALSE\n"
      "                radius .005\n"
      "                height 1\n"
      "                top FALSE\n"
      "        } } ] }\n"
      "        Transform {\n"
      "          translation 0 1 0\n"
      "          children [\n"
      "            DEF ARROW_POINTER Shape {\n"
      "              geometry Cone {\n"
      "                bottomRadius .05\n"
      "                height .1\n"
      "              }\n"
      "              appearance USE ARROW_APPEARANCE\n"
      "    } ] } ] }\n"
      "    %PREthe arrow along X axis\n"
      "    Transform {\n"
      "      translation 0 0 0\n"
      "      rotation 1 0 0 1.57\n"
      "      children [\n"
      "        Group {\n"
      "          children [ \n"
      "            USE ARROW\n"
      "    ] } ] }\n"
      "    %PREthe arrow along Z axis\n"
      "    Transform {\n"
      "      translation 0 0 0\n"
      "      rotation 0 0 1 -1.57\n"
      "      children [\n"
      "        Group {\n"
      "          children [ \n"
      "            USE ARROW\n"
      "    ] } ] }\n"
      "    %PREthe Y label (which is vertical)\n"
      "    DEF Y_Label Group {\n"
      "      children [\n"
      "        Transform {\n"
      "          translation 0 1 0\n"
      "          children [\n"
      "            Billboard {\n"
      "              children [\n"
      "                Shape {\n"
      "                  appearance DEF LABEL_APPEARANCE Appearance {\n"
      "                    material Material {\n"
      "                      diffuseColor 1 1 .3\n"
      "                      emissiveColor .33 .33 .1\n"
      "                    } }\n"
      "                  geometry Text { \n"
      "                    string [ \"%ZVAR: %ZLA\", \"%ZMIN:%ZMAX - %PDIM points\" ] \n"
      "                    fontStyle FontStyle {  size .2 }\n"
      "    } } ] } ] } ] }\n"
      "    %PREthe X label\n"
      "    DEF X_Label Group {\n"
      "      children [\n"
      "        Transform {\n"
      "          translation 1 0 0\n"
      "          children [\n"
      "            Billboard {\n"
      "              children [\n"
      "                Shape {\n"
      "                  appearance DEF LABEL_APPEARANCE Appearance {\n"
      "                    material Material {\n"
      "                      diffuseColor 1 1 .3\n"
      "                      emissiveColor .33 .33 .1\n"
      "                    } }\n"
      "                  geometry Text { \n"
      "                    string [ \"%XVAR: %XLA\", \"%XMIN:%XMAX - %MDIM points\" ] \n"
      "                    fontStyle FontStyle {  size .2 }\n"
      "    } } ] } ] } ] }\n"
      "    %PREthe Z label\n"
      "    DEF Z_Label Group {\n"
      "      children [\n"
      "        Transform {\n"
      "          translation 0 0 1\n"
      "          children [\n"
      "            Billboard {\n"
      "              children [\n"
      "                Shape {\n"
      "                  appearance DEF LABEL_APPEARANCE Appearance {\n"
      "                    material Material {\n"
      "                      diffuseColor 1 1 .3\n"
      "                      emissiveColor .33 .33 .1\n"
      "                    } }\n"
      "                  geometry Text { \n"
      "                    string [ \"%YVAR: %YLA\", \"%YMIN:%YMAX - %NDIM points\" ] \n"
      "                    fontStyle FontStyle {  size .2 }\n"
      "    } } ] } ] } ] }\n"
      "    %PREThe text information (header data )\n"
      "    DEF Header Group {\n"
      "      children [\n"
      "        Transform {\n"
      "          translation 0 2 0\n"
      "          children [\n"
      "            Billboard {\n"
      "              children [\n"
      "                Shape {\n"
      "                  appearance Appearance {\n"
      "                    material Material { \n"
      "                      diffuseColor .9 0 0\n"
      "                      emissiveColor .9 0 0 }\n"
      "                  }\n"
      "                  geometry Text {\n"
      "                    string [ \"%PAR/%FIL\",\"%TITL\" ]\n"
      "                    fontStyle FontStyle {\n"
      "                        style \"BOLD\"\n"
      "                        size .2\n"
      "    } } } ] } ] } ] }\n"
      "    %PREThe Data plot\n"
      "    DEF MonitorData Group {\n"
      "      children [\n"
      "        DEF TransformData Transform {\n"
      "          children [\n"
      "            Shape {\n"
      "              appearance Appearance {\n"
      "                material Material { emissiveColor 0 0.2 0 }\n"
      "              }\n"
      "              geometry ElevationGrid {\n"
      "                xDimension  %MDIM\n"
      "                zDimension  %NDIM\n"
      "                xSpacing    1\n"
      "                zSpacing    1\n"
      "                solid       FALSE\n"
      "                height IS Data\n"
      "    } } ] } ] }\n"
      "    %PREThe VRMLScript that redimension x and z axis within 0:1\n"
      "    %PREand re-scale data within 0:1\n"
      "    DEF GetScale Script {\n"
      "      eventOut SFVec3f scale_vect\n"
      "      url \"javascript: \n"
      "        function initialize( ) {\n"
      "          scale_vect = new SFVec3f(1.0/%MDIM, 1.0/Math.abs(%ZMAX-%ZMIN), 1.0/%NDIM); }\" }\n"
      "  ] }\n"
      "ROUTE GetScale.scale_vect TO TransformData.scale\n} # end of PROTO\n"
      "%PREnow we call the proto with Data values\n"
      "I_ERR_N_%VPA {\nData [\n",
    "] # End of Data\n",
    "Errors [\n",
    "] # End of Errors\n",
    "Ncounts [\n",
    "] # End of Ncounts\n}" }
#ifdef USE_NEXUS
    ,
    { "NeXus", "nxs",
    "%PREFormat: %FMT file. Use hdfview to view.\n"
      "%PREURL:    http://www.mcstas.org/\n"
      "%PREEditor: %USR\n"
      "%PRECreator:%SRC simulation (McStas " MCSTAS_VERSION ")\n"
      "%PREDate:   Simulation started (%DATL) %DAT\n"
      "%PREFile:   %FIL\n",
    "%PREEndDate:%DAT\n",
    "%PREbegin %TYP\n",
    "%PREend %TYP\n",
    "%PRE%NAM: %VAL\n",
    "", "",
    "%PREErrors [%PAR/%FIL]: \n", "",
    "%PREEvents [%PAR/%FIL]: \n", "" }
#endif
};

/* file i/o handling ======================================================== */

/*******************************************************************************
* mcfull_file: allocates a full file name=mcdirname+file
*******************************************************************************/
char *mcfull_file(char *name, char *ext)
{
  int dirlen;
  char *mem;
  dirlen = mcdirname ? strlen(mcdirname) : 0;
  mem = malloc(dirlen + strlen(name) + 256);
  if(!mem)
  {
    exit(fprintf(stderr, "Error: Out of memory %li (mcfull_file)\n", (long)(dirlen + strlen(name) + 256)));
  }
  strcpy(mem, "");
  if(dirlen)
  {
    strcat(mem, mcdirname);
    if(mcdirname[dirlen - 1] != MC_PATHSEP_C &&
       name[0] != MC_PATHSEP_C)
      strcat(mem, MC_PATHSEP_S);
  }
  strcat(mem, name);
  if (!strchr(name, '.') && ext)
  { /* add extension if not in file name already */
    strcat(mem, ".");
    strcat(mem, ext);
  }
  return(mem);
}

/*******************************************************************************
* mcnew_file: opens a new file within mcdirname if non NULL
*             if mode is non 0, then mode is used, else mode is 'w'
*******************************************************************************/
FILE *mcnew_file(char *name, char *ext, char *mode)
{
  char *mem;
  FILE *file;

  if (!name || strlen(name) == 0) return(NULL);

  mem = mcfull_file(name, ext);
  file = fopen(mem, (mode ? mode : "w"));
  if(!file)
    fprintf(stderr, "Warning: could not open output file '%s' in mode '%s' (mcnew_file)\n", mem, mode);
  else {
    if (!mcopenedfiles || 
        (mcopenedfiles && mcopenedfiles_size <= strlen(mcopenedfiles)+strlen(mem))) {
      mcopenedfiles_size+=CHAR_BUF_LENGTH;
      if (!mcopenedfiles || !strlen(mcopenedfiles))
        mcopenedfiles = calloc(1, mcopenedfiles_size);
      else
        mcopenedfiles = realloc(mcopenedfiles, mcopenedfiles_size);
    } 
    strcat(mcopenedfiles, " ");
    strcat(mcopenedfiles, mem);
  }
  free(mem);
  
  return file;
} /* mcnew_file */

/*******************************************************************************
* str_rep: Replaces a token by an other (of SAME length) in a string
* This function modifies 'string'
*******************************************************************************/
char *str_rep(char *string, char *from, char *to)
{
  char *p;

  if (!string || !strlen(string)) return(string);
  if (strlen(from) != strlen(to)) return(string);

  p   = string;

  while (( p = strstr(p, from) ) != NULL) {
    long index;
    for (index=0; index<strlen(to); index++) p[index]=to[index];
  }
  return(string);
}

#define VALID_NAME_LENGTH 64
/*******************************************************************************
* mcvalid_name: makes a valid string for variable names.
*   copy 'original' into 'valid', replacing invalid characters by '_'
*   char arrays must be pre-allocated. n can be 0, or the maximum number of
*   chars to be copied/checked
*******************************************************************************/
static char *mcvalid_name(char *valid, char *original, int n)
{
  long i;


  if (original == NULL || strlen(original) == 0)
  { strcpy(valid, "noname"); return(valid); }
  if (n <= 0) n = strlen(valid);

  if (n > strlen(original)) n = strlen(original);
  else original += strlen(original)-n;
  strncpy(valid, original, n);

  for (i=0; i < n; i++)
  {
    if ( (valid[i] > 122)
      || (valid[i] < 32)
      || (strchr("!\"#$%&'()*+,-.:;<=>?@[\\]^`/ \n\r\t", valid[i]) != NULL) )
    {
      if (i) valid[i] = '_'; else valid[i] = 'm';
    }
  }
  valid[i] = '\0';

  return(valid);
} /* mcvalid_name */

/*******************************************************************************
* pfprintf: just as fprintf with positional arguments %N$t, 
*   but with (char *)fmt_args being the list of arg type 't'.
*   Needed as the vfprintf is not correctly handled on some platforms.
*   1- look for the maximum %d$ field in fmt
*   2- look for all %d$ fields up to max in fmt and set their type (next alpha)
*   3- retrieve va_arg up to max, and save pointer to arg in local arg array
*   4- use strchr to split around '%' chars, until all pieces are written
*   returns number of arguments written.
* Warning: this function is restricted to only handles types t=s,g,i,li
*          without additional field formating, e.g. %N$t
*******************************************************************************/
static int pfprintf(FILE *f, char *fmt, char *fmt_args, ...)
{
  #define MyNL_ARGMAX 50
  char  *fmt_pos;

  char *arg_char[MyNL_ARGMAX];
  int   arg_int[MyNL_ARGMAX];
  long  arg_long[MyNL_ARGMAX];
  double arg_double[MyNL_ARGMAX];

  char *arg_posB[MyNL_ARGMAX];  /* position of '%' */
  char *arg_posE[MyNL_ARGMAX];  /* position of '$' */
  char *arg_posT[MyNL_ARGMAX];  /* position of type */

  int   arg_num[MyNL_ARGMAX];   /* number of argument (between % and $) */
  int   this_arg=0;
  int   arg_max=0;
  va_list ap;

  if (!f || !fmt_args || !fmt) return(-1);
  for (this_arg=0; this_arg<MyNL_ARGMAX;  arg_num[this_arg++] =0); this_arg = 0;
  fmt_pos = fmt;
  while(1)  /* analyse the format string 'fmt' */
  {
    char *tmp;

    arg_posB[this_arg] = (char *)strchr(fmt_pos, '%');
    tmp = arg_posB[this_arg];
    if (tmp)	/* found a percent */
    {
      char  printf_formats[]="dliouxXeEfgGcs\0";
      arg_posE[this_arg] = (char *)strchr(tmp, '$');
      if (arg_posE[this_arg] && isdigit(tmp[1]))
      { /* found a dollar following a percent  and a digit after percent */
        char  this_arg_chr[10];
        

        /* extract positional argument index %*$ in fmt */
        strncpy(this_arg_chr, arg_posB[this_arg]+1, arg_posE[this_arg]-arg_posB[this_arg]-1 < 10 ? arg_posE[this_arg]-arg_posB[this_arg]-1 : 9);
        this_arg_chr[arg_posE[this_arg]-arg_posB[this_arg]-1] = '\0';
        arg_num[this_arg] = atoi(this_arg_chr);
        if (arg_num[this_arg] <=0 || arg_num[this_arg] >= MyNL_ARGMAX)
          return(-fprintf(stderr,"pfprintf: invalid positional argument number (%i is <=0 or >=%i) from '%s'.\n", arg_num[this_arg], MyNL_ARGMAX, this_arg_chr));
        /* get type of positional argument: follows '%' -> arg_posE[this_arg]+1 */
        fmt_pos = arg_posE[this_arg]+1;
        fmt_pos[0] = tolower(fmt_pos[0]);
        if (!strchr(printf_formats, fmt_pos[0]))
          return(-fprintf(stderr,"pfprintf: invalid positional argument type (%c != expected %c).\n", fmt_pos[0], fmt_args[arg_num[this_arg]-1]));
        if (fmt_pos[0] == 'l' && (fmt_pos[1] == 'i' || fmt_pos[1] == 'd')) fmt_pos++;
        arg_posT[this_arg] = fmt_pos;
        /* get next argument... */
        this_arg++;
      }
      else
      { /* no dollar or no digit */
        if  (tmp[1] == '%') {
          fmt_pos = arg_posB[this_arg]+2;  /* found %% */
        } else if (strchr(printf_formats,tmp[1])) {
          fmt_pos = arg_posB[this_arg]+1;  /* found %s */
        } else { 
          return(-fprintf(stderr,"pfprintf: must use only positional arguments (%s).\n", arg_posB[this_arg]));
        }
      }
    } else
      break;  /* no more % argument */
  }
  arg_max = this_arg;
  /* get arguments from va_arg list, according to their type */
  va_start(ap, fmt_args);
  for (this_arg=0; this_arg<strlen(fmt_args); this_arg++)
  {

    switch(tolower(fmt_args[this_arg]))
    {
      case 's':                       /* string */
              arg_char[this_arg] = va_arg(ap, char *);
              break;
      case 'd':
      case 'i':
      case 'c':                      /* int */
              arg_int[this_arg] = va_arg(ap, int);
              break;
      case 'l':                       /* long int */
              arg_long[this_arg] = va_arg(ap, long int);
              break;
      case 'f':
      case 'g':
      case 'e':                      /* double */
              arg_double[this_arg] = va_arg(ap, double);
              break;
      default: fprintf(stderr,"pfprintf: argument type is not implemented (arg %%%i$ type %c).\n", this_arg+1, fmt_args[this_arg]);
    }
  }
  va_end(ap);
  /* split fmt string into bits containing only 1 argument */
  fmt_pos = fmt;
  for (this_arg=0; this_arg<arg_max; this_arg++)
  {
    char *fmt_bit;
    int   arg_n;

    if (arg_posB[this_arg]-fmt_pos>0)
    {
      fmt_bit = (char*)malloc(arg_posB[this_arg]-fmt_pos+10);
      if (!fmt_bit) return(-fprintf(stderr,"pfprintf: not enough memory.\n"));
      strncpy(fmt_bit, fmt_pos, arg_posB[this_arg]-fmt_pos);
      fmt_bit[arg_posB[this_arg]-fmt_pos] = '\0';
      fprintf(f, "%s", fmt_bit); /* fmt part without argument */
    } else
    {
      fmt_bit = (char*)malloc(10);
      if (!fmt_bit) return(-fprintf(stderr,"pfprintf: not enough memory.\n"));
    }
    arg_n = arg_num[this_arg]-1; /* must be >= 0 */
    strcpy(fmt_bit, "%");
    strncat(fmt_bit, arg_posE[this_arg]+1, arg_posT[this_arg]-arg_posE[this_arg]);
    fmt_bit[arg_posT[this_arg]-arg_posE[this_arg]+1] = '\0';

    switch(tolower(fmt_args[arg_n]))
    {
      case 's': fprintf(f, fmt_bit, arg_char[arg_n]);
                break;
      case 'd':
      case 'i':
      case 'c':                      /* int */
              fprintf(f, fmt_bit, arg_int[arg_n]);
              break;
      case 'l':                       /* long */
              fprintf(f, fmt_bit, arg_long[arg_n]);
              break;
      case 'f':
      case 'g':
      case 'e':                       /* double */
              fprintf(f, fmt_bit, arg_double[arg_n]);
              break;
    }
    fmt_pos = arg_posT[this_arg]+1;
    if (this_arg == arg_max-1)
    { /* add eventual leading characters for last parameter */
      if (fmt_pos < fmt+strlen(fmt))
        fprintf(f, "%s", fmt_pos);
    }
    if (fmt_bit) free(fmt_bit);

  }
  return(this_arg);
} /* pfprintf */

/*******************************************************************************
* mcfile_header: output header/footer using specific file format.
*   outputs, in file 'name' having preallocated 'f' handle, the format Header
*   'part' may be 'header' or 'footer' depending on part to write
*   if name == NULL, ignore function (no header/footer output)
*******************************************************************************/
static int mcfile_header(FILE *f, struct mcformats_struct format, char *part, char *pre, char *name, char *parent)
{
  char user[64];
  char date[64];
  char *HeadFoot;
  long date_l; /* date as a long number */
  time_t t;
  char valid_parent[256];
  char instrname[256];
  char file[256];

  if(!f)
    return (-1);

  time(&t);

  if (part && !strcmp(part,"footer"))
  {
    HeadFoot = format.Footer;
    date_l = (long)t;
  }
  else
  {
    HeadFoot = format.Header;
    date_l = mcstartdate;
  }
  t = (time_t)date_l;

  if (!strlen(HeadFoot) || (!name)) return (-1);

  sprintf(file,"%s",name);
  sprintf(user,"%s on %s",
        getenv("USER") ? getenv("USER") : "mcstas",
        getenv("HOST") ? getenv("HOST") : "localhost");
  if (strstr(format.Name, "HTML")) {
    sprintf(instrname,"%s", mcinstrument_source);
    mcvalid_name(valid_parent, mcinstrument_name, VALID_NAME_LENGTH);
  } else {
    sprintf(instrname,"%s (%s)", mcinstrument_name, mcinstrument_source);
    if (parent && strlen(parent)) mcvalid_name(valid_parent, parent, VALID_NAME_LENGTH);
    else strcpy(valid_parent, "root");
  }
  strncpy(date, ctime(&t), 64);
  if (strlen(date)) date[strlen(date)-1] = '\0';

#ifdef USE_NEXUS
  if (strstr(format.Name, "NeXus")) {
    if(mcnxfile_header(mcnxHandle, part,
    pre,                  /* %1$s  PRE  */
    instrname,            /* %2$s  SRC  */
    file,                 /* %3$s  FIL  */
    format.Name,          /* %4$s  FMT  */
    date,                 /* %5$s  DAT  */
    user,                 /* %6$s  USR  */
    valid_parent,         /* %7$s  PAR  */
    date_l) == NX_ERROR) {
      fprintf(stderr, "Error: writing NeXus header file %s (mcfile_header)\n", file);
      return(-1);
    } else return(1); }
  else
#endif
  return(pfprintf(f, HeadFoot, "sssssssl",
    pre,                  /* %1$s  PRE  */
    instrname,            /* %2$s  SRC  */
    file,                 /* %3$s  FIL  */
    format.Name,          /* %4$s  FMT  */
    date,                 /* %5$s  DAT  */
    user,                 /* %6$s  USR  */
    valid_parent,         /* %7$s  PAR  */
    date_l));             /* %8$li DATL */
} /* mcfile_header */

/*******************************************************************************
* mcfile_tag: output tag/value using specific file format.
*   outputs, in file with 'f' handle, a tag/value pair.
*   if name == NULL, ignore function (no section definition)
*******************************************************************************/
static int mcfile_tag(FILE *f, struct mcformats_struct format, char *pre, char *section, char *name, char *value)
{
  char valid_section[256];
  char valid_name[256];
  int i;

  if (!strlen(format.AssignTag) || (!name) || (!f)) return(-1);

  mcvalid_name(valid_section, section, VALID_NAME_LENGTH);
  mcvalid_name(valid_name, name, VALID_NAME_LENGTH);

  /* remove quote chars in values */
  if (strstr(format.Name, "Scilab") || strstr(format.Name, "Matlab") || strstr(format.Name, "IDL"))
    for(i = 0; i < strlen(value); i++) {
      if (value[i] == '"' || value[i] == '\'')   value[i] = ' ';
      if (value[i] == '\n'  || value[i] == '\r') value[i] = ';';
    }
#ifdef USE_NEXUS
  if (strstr(format.Name, "NeXus")) {
    if(mcnxfile_tag(mcnxHandle, pre, valid_section, name, value) == NX_ERROR) {
      fprintf(stderr, "Error: writing NeXus tag file %s/%s=%s (mcfile_tag)\n", section, name, value);
      return(-1);
    } else return(1); }
  else
#endif
  return(pfprintf(f, format.AssignTag, "ssss",
    pre,          /* %1$s PRE */
    valid_section,/* %2$s SEC */
    valid_name,   /* %3$s NAM */
    value));      /* %4$s VAL */
} /* mcfile_tag */

/*******************************************************************************
* mcfile_section: output section start/end using specific file format.
*   outputs, in file 'name' having preallocated 'f' handle, the format Section.
*   'part' may be 'begin' or 'end' depending on section part to write
*   'type' may be e.g. 'instrument','simulation','component','data'
*   if name == NULL, ignore function (no section definition)
*   the prefix 'pre' is automatically indented/un-indented (pre-allocated !)
*******************************************************************************/
static int mcfile_section(FILE *f, struct mcformats_struct format, char *part, char *pre, char *name, char *type, char *parent, int level)
{
  char *Section;
  char valid_name[256];
  char valid_parent[256];
  int  ret;

  if(!f && !strstr(format.Name, "NeXus")) return (-1);

  if (part && !strcmp(part,"end")) Section = format.EndSection;
  else Section = format.BeginSection;

  if (!strlen(Section) || (!name)) return (-1);

  if (strcmp(part,"header") && strstr(format.Name, "no header")) return (-1);
  if (strcmp(part,"footer") && strstr(format.Name, "no footer")) return (-1);

  mcvalid_name(valid_name, name, VALID_NAME_LENGTH);
  if (parent && strlen(parent)) mcvalid_name(valid_parent, parent, VALID_NAME_LENGTH);
  else strcpy(valid_parent, "root");

  if (!strcmp(part,"end") && pre)       /* un-indent */
  {
    if (strlen(pre) > 2) pre[strlen(pre)-2]='\0';
  }
#ifdef USE_NEXUS
  if (strstr(format.Name, "NeXus")) {
    if (mcnxfile_section(mcnxHandle,part,
      pre, type, name, valid_name, parent, valid_parent, level) == NX_ERROR) {
      fprintf(stderr, "Error: writing NeXus section %s/%s=NX%s (mcfile_section)\n", parent, name, type);
      ret=-1;
    } else ret=1; }
  else
#endif
  ret = pfprintf(f, Section, "ssssssi",
    pre,          /* %1$s  PRE  */
    type,         /* %2$s  TYP  */
    name,         /* %3$s  NAM  */
    valid_name,   /* %4$s  VNA  */
    parent,       /* %5$s  PAR  */
    valid_parent, /* %6$s  VPA  */
    level);       /* %7$i  LVL */

  if (!strcmp(part,"begin"))
  {
    if (pre) strcat(pre,"  ");  /* indent */
    if (name && strlen(name))
      mcfile_tag(f, format, pre, name, "name", name);
    if (parent && strlen(parent))
      mcfile_tag(f, format, pre, name, "parent", parent);
  }

  return(ret);
} /* mcfile_section */

/*******************************************************************************
* mcinfo_instrument: output instrument info
*******************************************************************************/
static void mcinfo_instrument(FILE *f, struct mcformats_struct format,
  char *pre, char *name)
{
  char Value[1300] = "";
  int  i;

  if (!f) return;

  for(i = 0; i < mcnumipar; i++)
  {
    char ThisParam[256];
    if (strlen(mcinputtable[i].name) > 200) break;
    sprintf(ThisParam, " %s(%s)", mcinputtable[i].name,
            (*mcinputtypes[mcinputtable[i].type].parminfo)
                (mcinputtable[i].name));
    strcat(Value, ThisParam);
    if (strlen(Value) > CHAR_BUF_LENGTH) break;
  }
  mcfile_tag(f, format, pre, name, "Parameters", Value);
  mcfile_tag(f, format, pre, name, "Source", mcinstrument_source);
  mcfile_tag(f, format, pre, name, "Trace_enabled", mctraceenabled ? "yes" : "no");
  mcfile_tag(f, format, pre, name, "Default_main", mcdefaultmain ? "yes" : "no");
  mcfile_tag(f, format, pre, name, "Embedded_runtime",
#ifdef MC_EMBEDDED_RUNTIME
         "yes"
#else
         "no"
#endif
         );
} /* mcinfo_instrument */

/*******************************************************************************
* mcinfo_instrument: output simulation info
*******************************************************************************/
void mcinfo_simulation(FILE *f, struct mcformats_struct format,
  char *pre, char *name)
{
  int i;
  double run_num, ncount;
  char Value[256];

  if (!f) return;

  run_num = mcget_run_num();
  ncount  = 
#ifdef USE_MPI
    mpi_node_count * 
#endif
    mcget_ncount();
  
  if (run_num == 0 || run_num == ncount) sprintf(Value, "%g", ncount);
  else sprintf(Value, "%g/%g", run_num, ncount);
  mcfile_tag(f, format, pre, name, "Ncount", Value);
  mcfile_tag(f, format, pre, name, "Trace", mcdotrace ? "yes" : "no");
  mcfile_tag(f, format, pre, name, "Gravitation", mcgravitation ? "yes" : "no");
  if(mcseed)
  {
    sprintf(Value, "%ld", mcseed);
    mcfile_tag(f, format, pre, name, "Seed", Value);
  }
  if (strstr(format.Name, "McStas"))
  {
    for(i = 0; i < mcnumipar; i++)
    {
      if (mcrun_num || (mcinputtable[i].val && strlen(mcinputtable[i].val))) {
        if (mcinputtable[i].par == NULL) {
          strncpy(Value, (mcinputtable[i].val ? mcinputtable[i].val : ""), 256);
        } else (*mcinputtypes[mcinputtable[i].type].printer)(Value, mcinputtable[i].par);
        fprintf(f, "%sParam: %s=%s", pre, mcinputtable[i].name, Value);
        fprintf(f, "\n");
      }
    }
  }
  else
  {
    mcfile_section(f, format, "begin", pre, "parameters", "parameters", name, 3);
    for(i = 0; i < mcnumipar; i++)
    {
      if (mcinputtable[i].par == NULL)
        strncpy(Value, (mcinputtable[i].val ? mcinputtable[i].val : ""), 256);
      else (*mcinputtypes[mcinputtable[i].type].printer)(Value, mcinputtable[i].par);
      mcfile_tag(f, format, pre, "parameters", mcinputtable[i].name, Value);
    }
    mcfile_section(f, format, "end", pre, "parameters", "parameters", name, 3);
  }
} /* mcinfo_simulation */

/*******************************************************************************
* mcinfo_data: output data info, computes basic stats.
*******************************************************************************/
static void mcinfo_data(FILE *f, struct mcformats_struct format,
  char *pre, char *parent, char *title,
  int m, int n, int p,
  char *xlabel, char *ylabel, char *zlabel,
  char *xvar, char *yvar, char *zvar,
  double *x1, double *x2, double *y1, double *y2, double *z1, double *z2,
  char *filename,
  double *p0, double *p1, double *p2, char istransposed, Coords posa)
{
  char type[256];
  char stats[256];
  char vars[256];
  char signal[256];
  char values[256];
  char limits[256];
  char lim_field[10];
  char c[32];
  double run_num, ncount;
  char ratio[256];
  char pos[256];

  double sum_xz  = 0;
  double sum_yz  = 0;
  double sum_z   = 0;
  double sum_y   = 0;
  double sum_x   = 0;
  double sum_x2z = 0;
  double sum_y2z = 0;
  double min_z   = 0;
  double max_z   = 0;
  double fmon_x=0, smon_x=0, fmon_y=0, smon_y=0, mean_z=0;
  double Nsum=0;
  double P2sum=0;

  int    i,j;

  if (!f || m*n*p == 0) return;

  if (p1)
  {
    min_z   = p1[0];
    max_z   = min_z;
    for(j = 0; j < n*p; j++)
    {
      for(i = 0; i < m; i++)
      {
        double x,y,z;
        double N, E;
        long index;

        if (!istransposed) index = i*n*p + j;
        else index = i+j*m;
        if (p0) N = p0[index];
        if (p2) E = p2[index];

        if (m) x = *x1 + (i + 0.5)/m*(*x2 - *x1); else x = 0;
        if (n && p) y = *y1 + (j + 0.5)/n/p*(*y2 - *y1); else y = 0;
        z = p1[index];
        sum_xz += x*z;
        sum_yz += y*z;
        sum_x += x;
        sum_y += y;
        sum_z += z;
        sum_x2z += x*x*z;
        sum_y2z += y*y*z;
        if (z > max_z) max_z = z;
        if (z < min_z) min_z = z;

        Nsum += p0 ? N : 1;
        P2sum += p2 ? E : z*z;
      }
    }
    if (sum_z && n*m*p)
    {
      fmon_x = sum_xz/sum_z;
      fmon_y = sum_yz/sum_z;
      smon_x = sqrt(sum_x2z/sum_z-fmon_x*fmon_x);
      smon_y = sqrt(sum_y2z/sum_z-fmon_y*fmon_y);
      mean_z = sum_z/n/m/p;
    }
  }

  if (abs(m*n*p) == 1)
  { strcpy(type, "array_0d"); strcpy(stats, ""); }
  else if (n == 1 || m == 1)
  { if (m == 1) {m = n; n = 1; }
    sprintf(type, "array_1d(%d)", m);
    sprintf(stats, "X0=%g; dX=%g;", fmon_x, smon_x); }
  else
  { if (strstr(format.Name," scan ")) sprintf(type, "multiarray_1d(%d)", n);
    else if (p == 1) sprintf(type, "array_2d(%d, %d)", m, n);
    else sprintf(type, "array_3d(%d, %d, %d)", m, n, p);
    sprintf(stats, "X0=%g; dX=%g; Y0=%g; dY=%g;", fmon_x, smon_x, fmon_y, smon_y); }
  strcpy(c, "I ");
  if (zvar && strlen(zvar)) strncpy(c, zvar,32);
  else if (yvar && strlen(yvar)) strncpy(c, yvar,32);
  else if (xvar && strlen(xvar)) strncpy(c, xvar,32);
  else strncpy(c, xvar,32);
  if (m == 1 || n == 1) sprintf(vars, "%s %s %s_err N", xvar, c, c);
  else sprintf(vars, "%s %s_err N", c, c);

  run_num = mcget_run_num();
  ncount  = 
#ifdef USE_MPI
    mpi_node_count * 
#endif
    mcget_ncount();
  sprintf(ratio, "%g/%g", run_num, ncount);

  mcfile_tag(f, format, pre, parent, "type", type);
  mcfile_tag(f, format, pre, parent, "Source", mcinstrument_source);
  if (parent) mcfile_tag(f, format, pre, parent, (strstr(format.Name,"McStas") ? "component" : "parent"), parent);
  sprintf(pos, "%g %g %g", posa.x, posa.y, posa.z);
  mcfile_tag(f, format, pre, parent, "position", pos);

  if (title) mcfile_tag(f, format, pre, parent, "title", title);
  mcfile_tag(f, format, pre, parent, "ratio", ratio);
  if (filename) {
    mcfile_tag(f, format, pre, parent, "filename", filename);
    mcfile_tag(f, format, pre, parent, "format", format.Name);
  } else mcfile_tag(f, format, pre, parent, "filename", "");

  if (p1)
  {
    if (n*m*p > 1)
    {
      sprintf(signal, "Min=%g; Max=%g; Mean= %g;", min_z, max_z, mean_z);
      if (m > 1 && n == 1 && p == 1) { *y1 = min_z; *y2 = max_z; *z1=*y1; *z2=*y2; }
      else if (m > 1 && n > 1 && p == 1) { *z1 = min_z; *z2 = max_z;}
    } else strcpy(signal, "");

    mcfile_tag(f, format, pre, parent, "statistics", stats);
    mcfile_tag(f, format, pre, parent,
      strstr(format.Name, "NeXus") ? "Signal" : "signal", signal);

    sprintf(values, "%g %g %g", sum_z, mcestimate_error(Nsum, sum_z, P2sum), Nsum);
    mcfile_tag(f, format, pre, parent, "values", values);
  }
  strcpy(lim_field, "xylimits");
  if (n*m > 1)
  {
    mcfile_tag(f, format, pre, parent, (strstr(format.Name," scan ") ? "xvars" : "xvar"), xvar);
    mcfile_tag(f, format, pre, parent, (strstr(format.Name," scan ") ? "yvars" : "yvar"), yvar);
    mcfile_tag(f, format, pre, parent, "xlabel", xlabel);
    mcfile_tag(f, format, pre, parent, "ylabel", ylabel);
    if ((n == 1 || m == 1 || strstr(format.Name," scan ")) && strstr(format.Name, "McStas"))
    {
      sprintf(limits, "%g %g", *x1, *x2);
      strcpy(lim_field, "xlimits");
    }
    else
    {
      if (!strstr(format.Name," scan ")) {
        mcfile_tag(f, format, pre, parent, "zvar", zvar);
        mcfile_tag(f, format, pre, parent, "zlabel", zlabel);
      }
      sprintf(limits, "%g %g %g %g %g %g", *x1, *x2, *y1, *y2, *z1, *z2);
    }
  } else strcpy(limits, "0 0 0 0 0 0");
  mcfile_tag(f, format, pre, parent, lim_field, limits);
  mcfile_tag(f, format, pre, parent, "variables", strstr(format.Name," scan ") ? zvar : vars);
  /* add warning in case of low statistics or large number of bins in text format mode */
  if (mcestimate_error(Nsum, sum_z, P2sum) > sum_z/4) fprintf(stderr,
    "Warning: file '%s': Low Statistics\n",
    filename);
  else
  if (n*m*p > 1000 && Nsum < n*m*p && Nsum) fprintf(stderr,
    "Warning: file '%s':\n"
    "         Low Statistics (%g events in %dx%dx%d bins).\n",
    filename, Nsum, m,n,p);
  if ( !strstr(format.Name, "binary")
    && (strstr(format.Name, "Scilab") || strstr(format.Name, "Matlab"))
    && (n*m*p > 10000 || m > 1000) ) fprintf(stderr,
      "Warning: file '%s' (%s format)\n"
      "         Large matrices (%dx%dx%d) in text mode may be\n"
      "         slow or fail at import. Prefer binary mode.\n",
      filename, format.Name, m,n,p);
   if (mcDetectorCustomHeader && strlen(mcDetectorCustomHeader)) {
     mcfile_tag(f, format, pre, parent, "custom", mcDetectorCustomHeader);
   }
} /* mcinfo_data */

/*******************************************************************************
* mcsiminfo_init: writes simulation structured description file (mcstas.sim)
*******************************************************************************/
void mcsiminfo_init(FILE *f)
{
#ifdef USE_MPI
  if(mpi_node_rank != mpi_node_root) return;
#endif
  if (mcdisable_output_files) return;
  if (!f && (!mcsiminfo_name || !strlen(mcsiminfo_name))) return;
  /* clear list of opened files to start new save session */
  if (mcopenedfiles && strlen(mcopenedfiles) > 0) strcpy(mcopenedfiles, "");
#ifdef USE_NEXUS
  /* NeXus sim info is the NeXus root file */
  if(strstr(mcformat.Name, "NeXus")) {
    if (mcnxfile_init(mcsiminfo_name, mcformat.Extension,
      strstr(mcformat.Name, "append") || strstr(mcformat.Name, "catenate") ? "a":"w",
      &mcnxHandle) == NX_ERROR) {
      exit(fprintf(stderr, "Error: opening NeXus file %s (mcsiminfo_init)\n", mcsiminfo_name));
    } else mcsiminfo_file = (FILE *)mcsiminfo_name;
  } else
#endif
  if (!f) mcsiminfo_file = mcnew_file(mcsiminfo_name, mcformat.Extension,
    strstr(mcformat.Name, "append") 
      || strstr(mcformat.Name, "catenate")  
      || strstr(mcopenedfiles, mcsiminfo_name) 
    ? "a":"w");
  else mcsiminfo_file = f;
  if(!mcsiminfo_file)
    fprintf(stderr,
            "Warning: could not open simulation description file '%s' (mcsiminfo_init)\n",
            mcsiminfo_name);
  else
  {
    char *pre; /* allocate enough space for indentations */
    int  ismcstas_nx;
    char simname[CHAR_BUF_LENGTH];
    char root[10];

    pre = (char *)malloc(20);
    if (!pre) exit(fprintf(stderr, "Error: insufficient memory (mcsiminfo_init)\n"));
    strcpy(pre, strstr(mcformat.Name, "VRML")
               || strstr(mcformat.Name, "OpenGENIE") ? "# " : "  ");


    ismcstas_nx = (strstr(mcformat.Name, "McStas") || strstr(mcformat.Name, "NeXus"));
    strcpy(root, strstr(mcformat.Name, "XML") ? "root" : "mcstas");
    sprintf(simname, "%s%s%s",
      mcdirname ? mcdirname : ".", MC_PATHSEP_S, mcsiminfo_name);

#ifdef USE_NEXUS
    if (strstr(mcformat.Name, "NeXus")) {
      /* NXentry class */
      char file_time[CHAR_BUF_LENGTH];
      sprintf(file_time, "%s_%li", mcinstrument_name, mcstartdate);
      mcfile_section(mcsiminfo_file, mcformat, "begin", pre, file_time, "entry", root, 1);
    }
#endif

    mcfile_header(mcsiminfo_file, mcformat, "header", pre, simname, root);
#ifdef USE_NEXUS
    if (strstr(mcformat.Name, "NeXus"))
    mcnxfile_section(mcnxHandle,"end_data", NULL, NULL, NULL, NULL, NULL, NULL, 0);
#endif
    /* begin-end instrument */
    mcfile_section(mcsiminfo_file, mcformat, "begin", pre, mcinstrument_name, "instrument", root, 1);
    mcinfo_instrument(mcsiminfo_file, mcformat, pre, mcinstrument_name);
#ifdef USE_NEXUS
    if (strstr(mcformat.Name, "NeXus")) {
      mcnxfile_section(mcnxHandle,"end_data", NULL, NULL, NULL, NULL, NULL, NULL, 0);
      mcnxfile_section(mcnxHandle,"instr_code",
        pre, "instrument", mcinstrument_source, NULL, mcinstrument_name, NULL, 0);
    }
#endif
    if (ismcstas_nx) mcfile_section(mcsiminfo_file, mcformat, "end", pre, mcinstrument_name, "instrument", root, 1);

    /* begin-end simulation */
    mcfile_section(mcsiminfo_file, mcformat, "begin", pre, simname, "simulation", mcinstrument_name, 2);
    mcinfo_simulation(mcsiminfo_file, mcformat, pre, simname);
#ifdef USE_NEXUS
    if (strstr(mcformat.Name, "NeXus"))
    mcnxfile_section(mcnxHandle,"end_data", NULL, NULL, NULL, NULL, NULL, NULL, 0);
#endif
    if (ismcstas_nx) mcfile_section(mcsiminfo_file, mcformat, "end", pre, simname, "simulation", mcinstrument_name, 2);

    free(pre);
  }
} /* mcsiminfo_init */

/*******************************************************************************
* mcsiminfo_close: close simulation file (mcstas.sim)
*******************************************************************************/
void mcsiminfo_close(void)
{
#ifdef USE_MPI
  if(mpi_node_rank != mpi_node_root) return;
#endif
  if (mcdisable_output_files) return;
  if(mcsiminfo_file)
  {
    int  ismcstas_nx;
    char simname[CHAR_BUF_LENGTH];
    char root[10];
    char *pre;

    pre = (char *)malloc(20);
    if (!pre) exit(fprintf(stderr, "Error: insufficient memory (mcsiminfo_close)\n"));
    strcpy(pre, strstr(mcformat.Name, "VRML")
               || strstr(mcformat.Name, "OpenGENIE") ? "# " : "  ");

    ismcstas_nx = (strstr(mcformat.Name, "McStas") || strstr(mcformat.Name, "NeXus"));
    strcpy(root, strstr(mcformat.Name, "XML") ? "root" : "mcstas");
    sprintf(simname, "%s%s%s",
      mcdirname ? mcdirname : ".", MC_PATHSEP_S, mcsiminfo_name);

    if (!ismcstas_nx)
    {
      mcfile_section(mcsiminfo_file, mcformat, "end", pre, simname, "simulation", mcinstrument_name, 2);
      mcfile_section(mcsiminfo_file, mcformat, "end", pre, mcinstrument_name, "instrument", root, 1);
    }
#ifdef USE_NEXUS
    if (strstr(mcformat.Name, "NeXus")) mcfile_section(mcsiminfo_file, mcformat, "end", pre, mcinstrument_name, "entry", root, 1);
#endif
    mcfile_header(mcsiminfo_file, mcformat, "footer", pre, simname, root);
#ifdef USE_NEXUS
    if (strstr(mcformat.Name, "NeXus")) mcnxfile_close(&mcnxHandle);
#endif
    if (mcsiminfo_file != stdout && mcsiminfo_file && !strstr(mcformat.Name, "NeXus")) fclose(mcsiminfo_file);
    mcsiminfo_file = NULL;

    free(pre);
  }
} /* mcsiminfo_close */

/*******************************************************************************
* mcfile_datablock: output a single data block using specific file format.
*   'part' can be 'data','errors','ncount'
*   if y1 == y2 == 0 and McStas format, then stores as a 1D array with [I,E,N]
*   return value: 0=0d/2d, 1=1d
*   when !single_file, create independent data files, with header and data tags
*   if one of the dimensions m,n,p is negative, the data matrix will be written
*   after transposition of m/x and n/y dimensions
*******************************************************************************/
static int mcfile_datablock(FILE *f, struct mcformats_struct format,
  char *pre, char *parent, char *part,
  double *p0, double *p1, double *p2, int m, int n, int p,
  char *xlabel, char *ylabel, char *zlabel, char *title,
  char *xvar, char *yvar, char *zvar,
  double *x1, double *x2, double *y1, double *y2, double *z1, double *z2,
  char *filename, char istransposed, Coords posa)
{
  char *Begin;
  char *End;
  char valid_xlabel[64];
  char valid_ylabel[64];
  char valid_zlabel[64];
  char valid_parent[64];
  FILE *datafile= NULL;
  int  isdata=0;
  int  just_header=0;
  int  i,j, is1d;
  double Nsum=0, Psum=0, P2sum=0;
  char sec[256];
  char isdata_present;
  char israw_data=0; /* raw data=(N,p,p2) instead of (N,P,sigma) */
  struct mcformats_struct dataformat;

  if (strstr(part,"data"))
  { isdata = 1; Begin = format.BeginData; End = format.EndData; }
  if (strstr(part,"errors"))
  { isdata = 2; Begin = format.BeginErrors; End = format.EndErrors; }
  if (strstr(part,"ncount"))
  { isdata = 0; Begin = format.BeginNcount; End = format.EndNcount; }
  if (strstr(part, "begin")) just_header = 1;
  if (strstr(part, "end"))   just_header = 2;

  isdata_present=((isdata==1 && p1) || (isdata==2 && p2) || (isdata==0 && p0));

  is1d = ((m==1 || n==1) && strstr(format.Name,"McStas"));
  mcvalid_name(valid_xlabel, xlabel, 64);
  mcvalid_name(valid_ylabel, ylabel, 64);
  mcvalid_name(valid_zlabel, zlabel, 64);

  if (strstr(format.Name, "McStas") || !filename || strlen(filename) == 0)
    mcvalid_name(valid_parent, parent, VALID_NAME_LENGTH);
  else mcvalid_name(valid_parent, filename, VALID_NAME_LENGTH);

#ifdef USE_NEXUS
  if (strstr(format.Name, "NeXus")) {
    /* istransposed==1 : end NeXus data only with last output slab */
    if (strstr(part,"data") && !strstr(format.Name,"no header")) { /* writes attributes in information SDS */
      mcinfo_data(mcsiminfo_file, format, pre, valid_parent, title, m, n, p,
                  xlabel, ylabel, zlabel, xvar, yvar, zvar,
                  x1, x2, y1, y2, z1, z2, filename, p0, p1, p2,
                  0, posa);
      mcnxfile_section(mcnxHandle,"end_data", NULL, filename, NULL, NULL, NULL, NULL, 0);
    }
    if(mcnxfile_datablock(mcnxHandle, part,
      format.Name, valid_parent, filename, xlabel, valid_xlabel, ylabel, valid_ylabel, zlabel, valid_zlabel, title, xvar, yvar, zvar, abs(m), abs(n), abs(p), *x1, *x2, *y1, *y2, *z1, *z2, p0, p1, p2) == NX_ERROR) {
      fprintf(stderr, "Error: writing NeXus data %s/%s (mcfile_datablock)\n", parent, filename);
    }
    return(0); }
#endif

  if (strstr(format.Name, " raw")) israw_data = 1;

  /* if normal or begin and part == data: output info_data (sim/data_file) */
  if (isdata == 1 && just_header != 2 && f)
  {
    if(!strstr(format.Name, "no header")) {
      mcinfo_data(f, format, pre, valid_parent, title, m, n, p,
                  xlabel, ylabel, zlabel, xvar, yvar, zvar,
                  x1, x2, y1, y2, z1, z2, filename, p0, p1, p2,
                  istransposed, posa);
    }
  }

  /* if normal or begin: begin part (sim/data file) */
  if (strlen(Begin) && just_header != 2 && f) {
    pfprintf(f, Begin, "sssssssssssssiiigggggg",
      pre,          /* %1$s   PRE  */
      valid_parent, /* %2$s   PAR  */
      filename,     /* %3$s   FIL  */
      xlabel,       /* %4$s   XLA  */
      valid_xlabel, /* %5$s   XVL  */
      ylabel,       /* %6$s   YLA  */
      valid_ylabel, /* %7$s   YVL  */
      zlabel,       /* %8$s   ZLA  */
      valid_zlabel, /* %9$s   ZVL  */
      title,        /* %10$s  TITL */
      xvar,         /* %11$s  XVAR */
      yvar,         /* %12$s  YVAR */
      zvar,         /* %13$s  ZVAR */
      m,            /* %14$i  MDIM */
      n,            /* %15$i  NDIM */
      p,            /* %16$i  PDIM */
      *x1,           /* %17$g  XMIN */
      *x2,           /* %18$g  XMAX */
      *y1,           /* %19$g  YMIN */
      *y2,           /* %20$g  YMAX */
      *z1,           /* %21$g  ZMIN */
      *z2);          /* %22$g  ZMAX */
  }
 /* if normal, and !single:
  *   open datafile,
  *   if !ascii_only
  *     if data: write file header,
  *     call datablock part+header(begin)
  * else data file = f
  */
  dataformat=format;
  if (!mcsingle_file && just_header == 0)
  {
    /* if data: open new file for data else append for error/ncount */
    if (filename) {
      char mode[10];

      strcpy(mode,
             (isdata != 1 || strstr(format.Name, "no header")
              || strstr(format.Name, "append") 
              || strstr(format.Name, "catenate") 
              || strstr(mcopenedfiles, filename) ?
             "a" : "w"));
      if (strstr(format.Name, "binary")) strcat(mode, "b");
      if (mcformat_data.Name) dataformat = mcformat_data;
      datafile = mcnew_file(filename, dataformat.Extension, mode);
    } else datafile = NULL;
    /* special case of IDL: can not have empty vectors. Init to 'external' */
    if (strstr(format.Name, "IDL") && f) fprintf(f, "'external'");
    /* if data, start with root header plus tags of parent data */
    if (datafile && !mcascii_only)
    {
      char *new_pre;
      char *mode;
      new_pre = (char *)malloc(20);
      mode    = (char *)malloc(20);
      if (!new_pre || !mode) exit(fprintf(stderr, "Error: insufficient memory (mcfile_datablock)\n"));
      strcpy(new_pre, (strstr(dataformat.Name, "McStas")
               || strstr(dataformat.Name, "VRML")
               || strstr(dataformat.Name, "OpenGENIE") ? "# " : ""));

      if (isdata == 1) {
        if(!strstr(format.Name, "no header"))
          {
            mcfile_header(datafile, dataformat, "header", new_pre,
                          filename, valid_parent);
            mcinfo_simulation(datafile, dataformat,
                              new_pre, valid_parent);
          }
      }
      sprintf(mode, "%s begin", part);
      /* write header+data block begin tags into datafile */
      mcfile_datablock(datafile, dataformat, new_pre,
          valid_parent, mode,
          p0, p1, p2, m, n, p,
          xlabel,  ylabel, zlabel, title,
          xvar, yvar, zvar,
          x1, x2, y1, y2, z1, z2, filename, istransposed, posa);
      free(mode); free(new_pre);
    }
  }
  else if (just_header == 0)
  {
    if (strstr(format.Name, "McStas") && abs(m*n*p)>1 && f)
    {
      if (is1d) sprintf(sec,"array_1d(%d)", m);
      else if (p==1) sprintf(sec,"array_2d(%d,%d)", m,n);
      else sprintf(sec,"array_3d(%d,%d,%d)", m,n,p);
      fprintf(f,"%sbegin %s\n", pre, sec);
      datafile = f; dataformat=format;
    }
    if (mcsingle_file) { datafile = f; dataformat=format; }
  }

  /* if normal: [data] in data file */
  /* do loops: 2 loops on m,n. */
  if (just_header == 0)
  {
    char eol_char[3];
    int  isIDL, isPython;
    int  isBinary=0;

    if (strstr(format.Name, "binary")) isBinary=1;
    if (strstr(format.Name, "float"))  isBinary=1;
    else if (strstr(format.Name, "double")) isBinary=2;
    isIDL    = (strstr(format.Name, "IDL") != NULL);
    isPython = (strstr(format.Name, "Python") != NULL);
    if (isIDL) strcpy(eol_char,"$\n"); else strcpy(eol_char,"\n");

    if (datafile && !isBinary)
    for(j = 0; j < n*p; j++)  /* loop on rows(y) */
    {
      for(i = 0; i < m; i++)  /* write all columns (x) */
      {
        double I=0, E=0, N=0;
        double value=0;
        long index;

        if (!istransposed) index = i*n*p + j;
        else index = i+j*m;
        if (p0) N = p0[index];
        if (p1) I = p1[index];
        if (p2) E = p2[index];

        Nsum += p0 ? N : 1;
        Psum += I;
        P2sum += p2 ? E : I*I;

        if (p0 && p1 && p2 && !israw_data) E = mcestimate_error(N,I,E);
        if(isdata_present)
        {
          if (is1d)
          {
            double x;
            x = *x1+(*x2-*x1)*(index+0.5)/(abs(m*n*p));
            if (abs(m*n*p) > 1) fprintf(datafile, "%g %g %g %g\n", x, I, E, N);
          }
          else
          {
            if (isdata == 1) value = I;
            else if (isdata == 0) value = N;
            else if (isdata == 2) value = E;
            fprintf(datafile, "%g", value);
            if ((isIDL || isPython) && ((i+1)*(j+1) < abs(m*n*p))) fprintf(datafile, ",");
            else fprintf(datafile, " ");
          }
        }
      }
      if (isdata_present && !is1d) fprintf(datafile, "%s", eol_char);
    } /* end 2 loops if not Binary */
    if (datafile && isBinary)
    {
      double *d=NULL;
      if (isdata==1) d=p1;
      else if (isdata==2) d=p2;
      else if (isdata==0) d=p0;

      if (d && isBinary == 1)  /* float */
      {
        float *s;
        s = (float*)malloc(abs(m*n*p)*sizeof(float));
        if (s)
        {
          long    i, count;
          for (i=0; i<abs(m*n*p); i++)
            { if (isdata != 2 || israw_data) s[i] = (float)d[i];
              else s[i] = (float)mcestimate_error(p0[i],p1[i],p2[i]); }
            count = fwrite(s, sizeof(float), abs(m*n*p), datafile);
          if (count != abs(m*n*p)) fprintf(stderr, "McStas: error writing float binary file '%s' (%li instead of %li, mcfile_datablock)\n", filename,count, (long)abs(m*n*p));
          free(s);
        } else fprintf(stderr, "McStas: Out of memory for writing %li float binary file '%s' (mcfile_datablock)\n", (long)abs(m*n*p)*sizeof(float), filename);
      }
      else if (d && isBinary == 2)  /* double */
      {
        long count;
        double *s=NULL;
        if (isdata == 2 && !israw_data)
        {
          s = (double*)malloc(abs(m*n*p)*sizeof(double));
          if (s) { long i;
            for (i=0; i<abs(m*n*p); i++)
              s[i] = (double)mcestimate_error(p0[i],p1[i],p2[i]);
            d = s;
          }
          else fprintf(stderr, "McStas: Out of memory for writing %li 'errors' part of double binary file '%s' (mcfile_datablock)\n", (long)abs(m*n*p)*sizeof(double), filename);
        }
        count = fwrite(d, sizeof(double), abs(m*n*p), datafile);
        if (isdata == 2 && s) free(s);
        if (count != abs(m*n*p)) fprintf(stderr, "McStas: error writing double binary file '%s' (%li instead of %li, mcfile_datablock)\n", filename,count, (long)abs(m*n*p));
      }
    } /* end if Binary */
  }
  if (strstr(format.Name, "McStas") || !filename || strlen(filename) == 0)
    mcvalid_name(valid_parent, parent, VALID_NAME_LENGTH);
  else mcvalid_name(valid_parent, filename, VALID_NAME_LENGTH);
  /* if normal or end: end_data */
  if (strlen(End) && just_header != 1 && f) {
    pfprintf(f, End, "sssssssssssssiiigggggg",
      pre,          /* %1$s   PRE  */
      valid_parent, /* %2$s   PAR  */
      filename,     /* %3$s   FIL  */
      xlabel,       /* %4$s   XLA  */
      valid_xlabel, /* %5$s   XVL  */
      ylabel,       /* %6$s   YLA  */
      valid_ylabel, /* %7$s   YVL  */
      zlabel,       /* %8$s   ZLA  */
      valid_zlabel, /* %9$s   ZVL  */
      title,        /* %10$s  TITL */
      xvar,         /* %11$s  XVAR */
      yvar,         /* %12$s  YVAR */
      zvar,         /* %13$s  ZVAR */
      m,            /* %14$i  MDIM */
      n,            /* %15$i  NDIM */
      p,            /* %16$i  PDIM */
      *x1,           /* %17$g  XMIN */
      *x2,           /* %18$g  XMAX */
      *y1,           /* %19$g  YMIN */
      *y2,           /* %20$g  YMAX */
      *z1,           /* %21$g  ZMIN */
      *z2);          /* %22$g  ZMAX */
  }

 /* if normal and !single and datafile:
  *   datablock part+footer
  *   write file footer
  *   close datafile
  */
  if (!mcsingle_file && just_header == 0)
  {
    char *mode;
    char *new_pre;

    new_pre = (char *)malloc(20);
    mode    = (char *)malloc(20);
    if (!new_pre || !mode) exit(fprintf(stderr, "Error: insufficient memory (mcfile_datablock)\n"));

    strcpy(new_pre, (strstr(dataformat.Name, "McStas")
               || strstr(dataformat.Name, "VRML")
               || strstr(dataformat.Name, "OpenGENIE") ? "# " : ""));

    if (datafile && datafile != f && !mcascii_only)
    {
      sprintf(mode, "%s end", part);
      /* write header+data block end tags into datafile */
      mcfile_datablock(datafile, dataformat, new_pre,
          valid_parent, mode,
          p0, p1, p2, m, n, p,
          xlabel,  ylabel, zlabel, title,
          xvar, yvar, zvar,
          x1, x2, y1, y2, z1, z2, filename, istransposed, posa);
      if ((isdata == 1 && is1d) || strstr(part,"ncount") || !p0 || !p2) /* either ncount, or 1d */
        if(!strstr(format.Name, "no footer"))
          mcfile_header(datafile, dataformat, "footer", new_pre,
                        filename, valid_parent);
    }
    if (datafile && datafile != f) fclose(datafile);
    free(mode); free(new_pre);
  }
  else
  {
    if (strstr(format.Name, "McStas") && just_header == 0 && abs(m*n*p) > 1)
      fprintf(f,"%send %s\n", pre, sec);
  }

  /* set return value */
  return(is1d);
} /* mcfile_datablock */

/*******************************************************************************
* mcfile_data: output data/errors/ncounts using specified file format.
*   if McStas 1D then data is stored. f is the simfile handle or NULL.
*   as a long 1D array [p0, p1, p2] to reorder -> don't output err/ncount again.
*   if p1 or p2 is NULL then skip that part.
*******************************************************************************/
static int mcfile_data(FILE *f, struct mcformats_struct format,
  char *pre, char *parent,
  double *p0, double *p1, double *p2, int m, int n, int p,
  char *xlabel, char *ylabel, char *zlabel, char *title,
  char *xvar, char *yvar, char *zvar,
  double ox1, double ox2, double oy1, double oy2, double oz1, double oz2,
  char *filename, char istransposed, Coords posa)
{
  int is1d;
  double x2, x1, y2, y1, z2, z1;

  x1=ox1; y1=oy1; z1=oz1;
  x2=ox2; y2=oy2; z2=oz2;

  /* return if f,n,m,p1 NULL */
  if ((m*n*p == 0) || !p1) return (-1);
  /* output data block */
  is1d = mcfile_datablock(f, format, pre, parent, "data",
    p0, p1, p2, m, n, p,
    xlabel,  ylabel, zlabel, title,
    xvar, yvar, zvar,
    &x1, &x2, &y1, &y2, &z1, &z2, filename, istransposed, posa);
  /* return if 1D data */
  if (is1d) return(is1d);
  /* output error block and p2 non NULL */
  if (p0 && p2) mcfile_datablock(f, format, pre, parent, "errors",
    p0, p1, p2, m, n, p,
    xlabel,  ylabel, zlabel, title,
    xvar, yvar, zvar,
    &x1, &x2, &y1, &y2, &z1, &z2, filename, istransposed, posa);
  /* output ncount block and p0 non NULL */
  if (p0 && p2) mcfile_datablock(f, format, pre, parent, "ncount",
    p0, p1, p2, m, n, p,
    xlabel,  ylabel, zlabel, title,
    xvar, yvar, zvar,
    &x1, &x2, &y1, &y2, &z1, &z2, filename, istransposed, posa);

  return(is1d);
} /* mcfile_data */

double mcdetector_out(char *cname, double p0, double p1, double p2, char *filename)
{
  printf("Detector: %s_I=%g %s_ERR=%g %s_N=%g",
         cname, p1, cname, mcestimate_error(p0,p1,p2), cname, p0);
  if(filename && strlen(filename))
    printf(" \"%s\"", filename);
  printf("\n");
  return(p0);
}

/*******************************************************************************
* mcdetector_out_012D: main output function, works for 0d, 1d, 2d data
*   parent is the component name. Handles MPI stuff.
*******************************************************************************/
static double mcdetector_out_012D(struct mcformats_struct format,
  char *parent, char *title,
  int m, int n,  int p,
  char *xlabel, char *ylabel, char *zlabel,
  char *xvar, char *yvar, char *zvar,
  double x1, double x2, double y1, double y2, double z1, double z2,
  char *filename_orig,
  double *p0, double *p1, double *p2,
  Coords posa)
{
  char simname[512];
  int i,j;
  double Nsum=0, Psum=0, P2sum=0;
  FILE *simfile_f=NULL;
  char istransposed=0;
  char *pre;
  char *filename=NULL;

#ifdef USE_MPI
  int mpi_event_list;
#endif /* !USE_MPI */

  if (!p1 || (p1 && abs(m*n*p) > 1 && (!filename_orig || !strlen(filename_orig)))) return(0);

  pre = (char *)malloc(20);
  if (!pre) exit(fprintf(stderr, "Error: insufficient memory (mcdetector_out_012D)\n"));
  strcpy(pre, strstr(format.Name, "VRML")
           || strstr(format.Name, "OpenGENIE") ? "# " : "");
  if (filename_orig && abs(m*n*p) > 1) {
    filename = (char *)malloc(CHAR_BUF_LENGTH);
    if (!filename) exit(fprintf(stderr, "Error: insufficient memory (mcdetector_out_012D)\n"));
    strcpy(filename, filename_orig);
    if (!strchr(filename, '.') && !strstr(format.Name, "NeXus"))
    { /* add extension to file name if it is missing and not NeXus  */
      strcat(filename,".");
      if (mcformat_data.Extension) strcat(filename,mcformat_data.Extension);
      else strcat(filename,mcformat.Extension);
    }
  }
  fflush(NULL);

#ifdef USE_MPI
  mpi_event_list = (strstr(format.Name," list ") != NULL);

  if (!mpi_event_list && mpi_node_count > 1) {
    /* we save additive data: reduce everything */
    if (p0) mc_MPI_Reduce(p0, p0, abs(m*n*p), MPI_DOUBLE, MPI_SUM, mpi_node_root, MPI_COMM_WORLD);
    if (p1) mc_MPI_Reduce(p1, p1, abs(m*n*p), MPI_DOUBLE, MPI_SUM, mpi_node_root, MPI_COMM_WORLD);
    if (p2) mc_MPI_Reduce(p2, p2, abs(m*n*p), MPI_DOUBLE, MPI_SUM, mpi_node_root, MPI_COMM_WORLD);

    /* slaves are done */
    if(mpi_node_rank != mpi_node_root) return 0;
      
    if (!p0) {  /* additive signal must be then divided by the number of nodes */ 
      for (i=0; i<abs(m*n*p); i++) { 
        p1[i] /= mpi_node_count; 
        if (p2) p2[i] /= mpi_node_count; 
      } 
    } 
  }
#endif /* USE_MPI */

  if (!strstr(format.Name, "NeXus")) {
    if (m<0 || n<0 || p<0)                istransposed = !istransposed;
    if (strstr(format.Name, "binary"))    istransposed = !istransposed;
    if (strstr(format.Name, "transpose")) istransposed = !istransposed;
    if (istransposed)
    { /* do the swap once for all */
      i=m; m=abs(n); n=abs(i); p=abs(p);
    }
  } else m=abs(m); n=abs(n); p=abs(p);

  if (!strstr(format.Name," list ")) simfile_f = mcsiminfo_file; /* use sim file */
  if (mcdirname)
    sprintf(simname, "%s%s%s", mcdirname, MC_PATHSEP_S, mcsiminfo_name);
  else
    sprintf(simname, "%s%s%s", ".", MC_PATHSEP_S, mcsiminfo_name);

  if (!mcdisable_output_files) {
    MPI_MASTER (
      if (!strstr(format.Name,"NeXus"))
      mcfile_section(simfile_f, format, "begin", pre, parent, "component", simname, 3);
      mcfile_section(simfile_f, format, "begin", pre, filename, "data", parent, 4);
      );
  }

  if (mcDetectorCustomHeader && strlen(mcDetectorCustomHeader)) {
     if (strstr(format.Name, "Octave") || strstr(format.Name, "Matlab"))
       str_rep(mcDetectorCustomHeader, "%PRE", "%   ");
     else if (strstr(format.Name, "IDL"))    str_rep(mcDetectorCustomHeader, "%PRE", ";   ");
     else if (strstr(format.Name, "Scilab")) str_rep(mcDetectorCustomHeader, "%PRE", "//  ");
     else if (strstr(format.Name, "McStas")) str_rep(mcDetectorCustomHeader, "%PRE", "#   ");
     else str_rep(mcDetectorCustomHeader, "%PRE", "    ");
   }

#ifdef USE_MPI
  if (mpi_event_list && mpi_node_count > 1) {
    if (mpi_node_rank != mpi_node_root) {
      /* we save an event list: all slaves send their data to master */
      /* m, n, p must be sent too, since all slaves do not have the same number of events */
      int mnp[3];
      mnp[0] = m; mnp[1] = n; mnp[2] = p;
        
      if (MPI_Send(mnp, 3, MPI_INT, mpi_node_root, 0, MPI_COMM_WORLD)!= MPI_SUCCESS)
        fprintf(stderr, "Warning: node %i to master: MPI_Send mnp list error (mcdetector_out_012D)", mpi_node_rank);
      if (!p1 || mc_MPI_Send(p1, abs(mnp[0]*mnp[1]*mnp[2]), MPI_DOUBLE, mpi_node_root, MPI_COMM_WORLD)!= MPI_SUCCESS)
        fprintf(stderr, "Warning: node %i to master: MPI_Send p1 list error (mcdetector_out_012D)", mpi_node_rank);
      /* slaves are done */
      return 0;
    } else { /* master node list */
      int node_i;
      /* get, then save master and slaves event lists */
      for(node_i=0; node_i<mpi_node_count; node_i++) {
        double *this_p1=NULL; /* buffer to hold the list to save */
        int    mnp[3]={0,0,0};        /* size of this buffer */
        if (node_i != mpi_node_root) { /* get data from slaves */
          if (MPI_Recv(mnp, 3, MPI_INT, node_i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE)!= MPI_SUCCESS)
            fprintf(stderr, "Warning: master from node %i: MPI_Recv mnp list error (mcdetector_out_012D)", node_i);
          this_p1 = (double *)calloc(abs(mnp[0]*mnp[1]*mnp[2]), sizeof(double));
          if (!this_p1 || mc_MPI_Recv(this_p1, abs(mnp[0]*mnp[1]*mnp[2]), MPI_DOUBLE, node_i, MPI_COMM_WORLD)!= MPI_SUCCESS)
            fprintf(stderr, "Warning: master from node %i: MPI_Recv p1 list error (mcdetector_out_012D)", node_i);
        } else {
          this_p1 = p1; 
          mnp[0] = m; mnp[1] = n; mnp[2] = p;
        }
        if (!strstr(format.Name, "NeXus")) { /* not MPI+NeXus format */
          char *formatName_orig = mcformat.Name;  /* copy the pointer position */
          char  formatName[256];
          strcpy(formatName, mcformat.Name);
          if (!strstr(formatName, "append")) strcat(formatName, " append ");
          if (node_i == 1) { /* first slave */
            /* disables header: it has been written by master */
            if (!strstr(formatName, "no header")) strcat(formatName, " no header ");
          }
          char *no_footer = strstr(formatName, "no footer");
          if (node_i == mpi_node_count-1) { /* last node */
            /* we write the last data block: request a footer */
            if (no_footer) strncpy(no_footer, "         ", 9);
          } else if (node_i == mpi_node_root) {
            /* master does not need footer (followed by slaves) */
            if (!no_footer) strcat(formatName, " no footer "); /* slaves do not need footer */
          }
          if (!mcdisable_output_files && this_p1) {
            mcformat.Name = formatName; /* use special customized format for list MPI */
            mcfile_data(simfile_f, format,
                        pre, parent,
                        NULL, this_p1, NULL, mnp[0], mnp[1], mnp[2],
                        xlabel, ylabel, zlabel, title,
                        xvar, yvar, zvar,
                        x1, x2, y1, y2, z1, z2, filename, istransposed, posa);
            mcformat.Name= formatName_orig; /* restore original format */
          }
        }
#ifdef USE_NEXUS
        else {
          /* MPI+NeXus: write one SDS per node list */
          char part[256];
          sprintf(part, "data_node_%i", node_i);
          if(mcnxfile_datablock(mcnxHandle, part,
              format.Name, parent, filename, xlabel, xlabel, ylabel, ylabel, zlabel, zlabel, title,
              xvar, yvar, zvar, abs(mnp[0]), abs(mnp[1]), abs(mnp[2]), x1, x2, y1, y2, z1, z2, NULL, this_p1, NULL)
              == NX_ERROR) {
            fprintf(stderr, "Error: writing NeXus data %s/%s (mcfile_datablock)\n", parent, filename);
          }
        }
#endif /* USE_NEXUS */
        if (node_i != mpi_node_root && this_p1) free(this_p1);
      } /* end for node_i */
    } /* end list for master node */
  } else
#endif /* USE_MPI */
  if (!mcdisable_output_files) { /* normal output */
    mcfile_data(simfile_f, format,
                pre, parent,
                p0, p1, p2, m, n, p,
                xlabel, ylabel, zlabel, title,
                xvar, yvar, zvar,
                x1, x2, y1, y2, z1, z2, filename, istransposed, posa);
  }

  if (!mcdisable_output_files) {
    mcfile_section(simfile_f, format, "end", pre, filename, "data", parent, 4);
    if (!strstr(format.Name,"NeXus"))
    mcfile_section(simfile_f, format, "end", pre, parent, "component", simname, 3);
  }

  if (simfile_f || mcdisable_output_files) {
    for(j = 0; j < n*p; j++) {
      for(i = 0; i < m; i++) {
        double N,I,E;
        int index;
        if (!istransposed) index = i*n*p + j;
        else index = i+j*m;
        if (p0) N = p0[index];
        if (p1) I = p1[index];
        if (p2) E = p2[index];

        Nsum += p0 ? N : 1;
        Psum += I;
        P2sum += p2 ? E : I*I;
      }
    }
    /* give 0D detector output. */
    if ((!filename || !strlen(filename)) && title && strlen(title)) filename = title;
    mcdetector_out(parent, Nsum, Psum, P2sum, filename);
  }
  free(pre); if (filename && filename_orig) free(filename);
  if (mcDetectorCustomHeader && strlen(mcDetectorCustomHeader)) {
     free(mcDetectorCustomHeader); mcDetectorCustomHeader=NULL;
  }
  fflush(NULL);
  return(Psum);
} /* mcdetector_out_012D */

/*******************************************************************************
* mcdetector_out_0D: wrapper to mcdetector_out_012D for 0D (single value).
*******************************************************************************/
double mcdetector_out_0D(char *t, double p0, double p1, double p2,
                         char *c, Coords posa)
{
  return(mcdetector_out_012D(mcformat,
    (c ? c : "McStas component"), (t ? t : "McStas data"),
    1, 1, 1,
    "I", "", "",
    "I", "", "",
    0, 0, 0, 0, 0, 0, NULL,
    &p0, &p1, &p2, posa));
}

/*******************************************************************************
* mcdetector_out_1D: wrapper to mcdetector_out_012D for 1D.
*******************************************************************************/
double mcdetector_out_1D(char *t, char *xl, char *yl,
                  char *xvar, double x1, double x2, int n,
                  double *p0, double *p1, double *p2, char *f,
                  char *c, Coords posa)
{
  return(mcdetector_out_012D(mcformat,
    (c ? c : "McStas component"), (t ? t : "McStas 1D data"),
    n, 1, 1,
    (xl ? xl : "X"), (yl ? yl : "Y"), (n > 1 ? "Signal per bin" : " Signal"),
    (xvar ? xvar : "x"), "(I,I_err)", "I",
    x1, x2, 0, 0, 0, 0, f,
    p0, p1, p2, posa));
}

/*******************************************************************************
* mcdetector_out_2D: wrapper to mcdetector_out_012D for 2D.
*******************************************************************************/
double mcdetector_out_2D(char *t, char *xl, char *yl,
                  double x1, double x2, double y1, double y2, int m,
                  int n, double *p0, double *p1, double *p2, char *f,
                  char *c, Coords posa)
{
  char xvar[3];
  char yvar[3];

  strcpy(xvar, "x "); strcpy(yvar, "y ");
  if (xl && strlen(xl)) strncpy(xvar, xl, 2);
  if (yl && strlen(yl)) strncpy(yvar, yl, 2);

  /* is it in fact a 1D call ? */
  if (m == 1)      return(mcdetector_out_1D(
                    t, yl, "I", yvar, y1, y2, n, p0, p1, p2, f, c, posa));
  else if (n == 1) return(mcdetector_out_1D(
                    t, xl, "I", xvar, x1, x2, m, p0, p1, p2, f, c, posa));

  return(mcdetector_out_012D(mcformat,
    (c ? c : "McStas component"), (t ? t : "McStas 2D data"),
    m, n, 1,
    (xl ? xl : "X"), (yl ? yl : "Y"), (n*m > 1 ? "Signal per bin" : " Signal"),
    xvar, yvar, "I",
    x1, x2, y1, y2, 0, 0, f,
    p0, p1, p2, posa));
}

/*******************************************************************************
* mcdetector_out_3D: wrapper to mcdetector_out_012D for 3D.
*   exported as a large 2D array, but the " dims are given in the header
*******************************************************************************/
double mcdetector_out_3D(char *t, char *xl, char *yl, char *zl,
      char *xvar, char *yvar, char *zvar,
                  double x1, double x2, double y1, double y2, double z1, double z2, int m,
                  int n, int p, double *p0, double *p1, double *p2, char *f,
                  char *c, Coords posa)
{
  return(mcdetector_out_012D(mcformat,
    (c ? c : "McStas component"), (t ? t : "McStas 3D data"),
    m, n, p,
    (xl ? xl : "X"), (yl ? yl : "Y"), (zl ? zl : "Z"),
    (xvar ? xvar : "x"), (yvar ? yvar : "y"), (zvar ? zvar : "z"),
    x1, x2, y1, y2, z1, z2, f,
    p0, p1, p2, posa));
}

/* end of file i/o functions ================================================ */

/* mcuse_format_header: Replaces aliases names in format fields (header part) */
char *mcuse_format_header(char *format_const)
{ /* Header Footer */
  char *format=NULL;

  if (!format_const) return(NULL);
  format = (char *)malloc(strlen(format_const)+1);
  if (!format) exit(fprintf(stderr, "Error: insufficient memory (mcuse_format_header)\n"));
  strcpy(format, format_const);
  str_rep(format, "%PRE", "%1$s"); /* prefix */
  str_rep(format, "%SRC", "%2$s"); /* name of instrument source file */
  str_rep(format, "%FIL", "%3$s"); /* output file name (data) */
  str_rep(format, "%FMT", "%4$s"); /* format name */
  str_rep(format, "%DATL","%8$li");/* Time elapsed since Jan 1st 1970, in seconds */
  str_rep(format, "%DAT", "%5$s"); /* Date as a string */
  str_rep(format, "%USR", "%6$s"); /* User/machine name */
  str_rep(format, "%PAR", "%7$s"); /* Parent name (root/mcstas) valid_parent */
  str_rep(format, "%VPA", "%7$s");
  return(format);
}

/* mcuse_format_tag: Replaces aliases names in format fields (tag part) */
char *mcuse_format_tag(char *format_const)
{ /* AssignTag */
  char *format=NULL;

  if (!format_const) return(NULL);
  format = (char *)malloc(strlen(format_const)+1);
  if (!format) exit(fprintf(stderr, "Error: insufficient memory (mcuse_format_tag)\n"));
  strcpy(format, format_const);
  str_rep(format, "%PRE", "%1$s"); /* prefix */
  str_rep(format, "%SEC", "%2$s"); /* section/parent name valid_parent/section */
  str_rep(format, "%PAR", "%2$s");
  str_rep(format, "%VPA", "%2$s");
  str_rep(format, "%NAM", "%3$s"); /* name of field valid_name */
  str_rep(format, "%VNA", "%3$s");
  str_rep(format, "%VAL", "%4$s"); /* value of field */
  return(format);
}

/* mcuse_format_section: Replaces aliases names in format fields (section part) */
char *mcuse_format_section(char *format_const)
{ /* BeginSection EndSection */
  char *format=NULL;

  if (!format_const) return(NULL);
  format = (char *)malloc(strlen(format_const)+1);
  if (!format) exit(fprintf(stderr, "Error: insufficient memory (mcuse_format_section)\n"));
  strcpy(format, format_const);
  str_rep(format, "%PRE", "%1$s"); /* prefix */
  str_rep(format, "%TYP", "%2$s"); /* type/class of section */
  str_rep(format, "%NAM", "%3$s"); /* name of section */
  str_rep(format, "%SEC", "%3$s");
  str_rep(format, "%VNA", "%4$s"); /* valid name (letters/digits) of section */
  str_rep(format, "%PAR", "%5$s"); /* parent name (simulation) */
  str_rep(format, "%VPA", "%6$s"); /* valid parent name (letters/digits) */
  str_rep(format, "%LVL", "%7$i"); /* level index */
  return(format);
}

/* mcuse_format_data: Replaces aliases names in format fields (data part) */
char *mcuse_format_data(char *format_const)
{ /* BeginData EndData BeginErrors EndErrors BeginNcount EndNcount */
  char *format=NULL;

  if (!format_const) return(NULL);
  format = (char *)malloc(strlen(format_const)+1);
  if (!format) exit(fprintf(stderr, "Error: insufficient memory (mcuse_format_data)\n"));
  strcpy(format, format_const);
  str_rep(format, "%PRE", "%1$s"); /* prefix */
  str_rep(format, "%PAR", "%2$s"); /* parent name (component instance name) valid_parent */
  str_rep(format, "%VPA", "%2$s");
  str_rep(format, "%FIL", "%3$s"); /* output file name (data) */
  str_rep(format, "%XLA", "%4$s"); /* x axis label */
  str_rep(format, "%XVL", "%5$s"); /* x axis valid label (letters/digits) */
  str_rep(format, "%YLA", "%6$s"); /* y axis label */
  str_rep(format, "%YVL", "%7$s"); /* y axis valid label (letters/digits) */
  str_rep(format, "%ZLA", "%8$s"); /* z axis label */
  str_rep(format, "%ZVL", "%9$s"); /* z axis valid label (letters/digits) */
  str_rep(format, "%TITL", "%10$s"); /* data title */
  str_rep(format, "%XVAR", "%11$s"); /* x variables */
  str_rep(format, "%YVAR", "%12$s"); /* y variables */
  str_rep(format, "%ZVAR", "%13$s"); /* z variables */
  str_rep(format, "%MDIM", "%14$i"); /* m dimension of x axis */
  str_rep(format, "%NDIM", "%15$i"); /* n dimension of y axis */
  str_rep(format, "%PDIM", "%16$i"); /* p dimension of z axis */
  str_rep(format, "%XMIN", "%17$g"); /* x min axis value (m bins) */
  str_rep(format, "%XMAX", "%18$g"); /* x max axis value (m bins) */
  str_rep(format, "%YMIN", "%19$g"); /* y min axis value (n bins) */
  str_rep(format, "%YMAX", "%20$g"); /* y max axis value (n bins) */
  str_rep(format, "%ZMIN", "%21$g"); /* z min axis value (usually min of signal, p bins) */
  str_rep(format, "%ZMAX", "%22$g"); /* z max axis value (usually max of signal, p bins) */
  return(format);
}

/*******************************************************************************
* mcuse_format: selects an output format for sim and data files. returns format
*******************************************************************************/
struct mcformats_struct mcuse_format(char *format)
{
  int i,j;
  int i_format=-1;
  char *tmp;
  char low_format[256];
  struct mcformats_struct usedformat;

  usedformat.Name = NULL;
  /* get the format to lower case */
  if (!format) exit(fprintf(stderr, "Error: Invalid NULL format. Exiting (mcuse_format)\n"));
  strcpy(low_format, format);
  for (i=0; i<strlen(low_format); i++) low_format[i]=tolower(format[i]);
  /* handle format aliases */
  if (!strcmp(low_format, "pgplot")) strcpy(low_format, "mcstas");
  if (!strcmp(low_format, "hdf"))    strcpy(low_format, "nexus");
#ifndef USE_NEXUS
  if (!strcmp(low_format, "nexus"))
    fprintf(stderr, "WARNING: to enable NeXus format you must have the NeXus libs installed.\n"
                    "         You should then re-compile with the -DUSE_NEXUS define.\n");
#endif

  tmp = (char *)malloc(256);
  if(!tmp) exit(fprintf(stderr, "Error: insufficient memory (mcuse_format)\n"));

  /* look for a specific format in mcformats.Name table */
  for (i=0; i < mcNUMFORMATS; i++)
  {
    strcpy(tmp, mcformats[i].Name);
    for (j=0; j<strlen(tmp); j++) tmp[j] = tolower(tmp[j]);
    if (strstr(low_format, tmp))  i_format = i;
  }
  if (i_format < 0)
  {
    i_format = 0; /* default format is #0 McStas */
    fprintf(stderr, "Warning: unknown output format '%s'. Using default (%s, mcuse_format).\n", format, mcformats[i_format].Name);
  }

  usedformat = mcformats[i_format];
  strcpy(tmp, usedformat.Name);
  usedformat.Name = tmp;
  if (strstr(low_format,"raw")) strcat(usedformat.Name," raw");
  if (strstr(low_format,"binary"))
  {
    if (strstr(low_format,"double")) strcat(usedformat.Name," binary double data");
    else strcat(usedformat.Name," binary float data");
    mcascii_only = 1;
  }

  /* Replaces vfprintf parameter name aliases */
  /* Header Footer */
  usedformat.Header       = mcuse_format_header(usedformat.Header);
  usedformat.Footer       = mcuse_format_header(usedformat.Footer);
  /* AssignTag */
  usedformat.AssignTag    = mcuse_format_tag(usedformat.AssignTag);
  /* BeginSection EndSection */
  usedformat.BeginSection = mcuse_format_section(usedformat.BeginSection);
  usedformat.EndSection   = mcuse_format_section(usedformat.EndSection);
  /*  BeginData  EndData  BeginErrors  EndErrors  BeginNcount  EndNcount  */
  usedformat.BeginData    = mcuse_format_data(usedformat.BeginData  );
  usedformat.EndData      = mcuse_format_data(usedformat.EndData    );
  usedformat.BeginErrors  = mcuse_format_data(usedformat.BeginErrors);
  usedformat.EndErrors    = mcuse_format_data(usedformat.EndErrors  );
  usedformat.BeginNcount  = mcuse_format_data(usedformat.BeginNcount);
  usedformat.EndNcount    = mcuse_format_data(usedformat.EndNcount  );

  return(usedformat);
} /* mcuse_format */

/* mcclear_format: free format structure */
void mcclear_format(struct mcformats_struct usedformat)
{
/* free format specification strings */
  if (usedformat.Name        ) free(usedformat.Name        );
  else return;
  if (usedformat.Header      ) free(usedformat.Header      );
  if (usedformat.Footer      ) free(usedformat.Footer      );
  if (usedformat.AssignTag   ) free(usedformat.AssignTag   );
  if (usedformat.BeginSection) free(usedformat.BeginSection);
  if (usedformat.EndSection  ) free(usedformat.EndSection  );
  if (usedformat.BeginData   ) free(usedformat.BeginData   );
  if (usedformat.EndData     ) free(usedformat.EndData     );
  if (usedformat.BeginErrors ) free(usedformat.BeginErrors );
  if (usedformat.EndErrors   ) free(usedformat.EndErrors   );
  if (usedformat.BeginNcount ) free(usedformat.BeginNcount );
  if (usedformat.EndNcount   ) free(usedformat.EndNcount   );
} /* mcclear_format */

/* mcuse_file: will save data/sim files */
static void mcuse_file(char *file)
{
  if (file && strcmp(file, "NULL"))
    mcsiminfo_name = file;
  else {
    char *filename=(char*)malloc(CHAR_BUF_LENGTH);
    sprintf(filename, "%s_%li", mcinstrument_name, mcstartdate);
    mcsiminfo_name = filename;
  }
  mcsingle_file  = 1;
}

/* Following part is only embedded when not redundent with mcstas.h ========= */

#ifndef MCSTAS_H

/* MCDISPLAY support. ======================================================= */

/*******************************************************************************
* Just output MCDISPLAY keywords to be caught by an external plotter client.
*******************************************************************************/

void mcdis_magnify(char *what){
  printf("MCDISPLAY: magnify('%s')\n", what);
}

void mcdis_line(double x1, double y1, double z1,
                double x2, double y2, double z2){
  printf("MCDISPLAY: multiline(2,%g,%g,%g,%g,%g,%g)\n",
         x1,y1,z1,x2,y2,z2);
}

void mcdis_dashed_line(double x1, double y1, double z1,
		       double x2, double y2, double z2, int n){
  int i;
  const double dx = (x2-x1)/(2*n+1);
  const double dy = (y2-y1)/(2*n+1);
  const double dz = (z2-z1)/(2*n+1);

  for(i = 0; i < n+1; i++)
    mcdis_line(x1 + 2*i*dx,     y1 + 2*i*dy,     z1 + 2*i*dz,
	       x1 + (2*i+1)*dx, y1 + (2*i+1)*dy, z1 + (2*i+1)*dz);
}

void mcdis_multiline(int count, ...){
  va_list ap;
  double x,y,z;

  printf("MCDISPLAY: multiline(%d", count);
  va_start(ap, count);
  while(count--)
    {
    x = va_arg(ap, double);
    y = va_arg(ap, double);
    z = va_arg(ap, double);
    printf(",%g,%g,%g", x, y, z);
    }
  va_end(ap);
  printf(")\n");
}

void mcdis_rectangle(char* plane, double x, double y, double z,
		     double width, double height){
  /* draws a rectangle in the plane           */
  /* x is ALWAYS width and y is ALWAYS height */
  if (strcmp("xy", plane)==0) {
    mcdis_multiline(5,
		    x - width/2, y - height/2, z,
		    x + width/2, y - height/2, z,
		    x + width/2, y + height/2, z,
		    x - width/2, y + height/2, z,
		    x - width/2, y - height/2, z);
  } else if (strcmp("xz", plane)==0) {
    mcdis_multiline(5,
		    x - width/2, y, z - height/2,
		    x + width/2, y, z - height/2,
		    x + width/2, y, z + height/2,
		    x - width/2, y, z + height/2,
		    x - width/2, y, z - height/2);
  } else if (strcmp("yz", plane)==0) {
    mcdis_multiline(5,
		    x, y - height/2, z - width/2,
		    x, y - height/2, z + width/2,
		    x, y + height/2, z + width/2,
		    x, y + height/2, z - width/2,
		    x, y - height/2, z - width/2);
  } else {

    fprintf(stderr, "Error: Definition of plane %s unknown\n", plane);
    exit(1);
  }
}

/*  draws a box with center at (x, y, z) and
    width (deltax), height (deltay), length (deltaz) */
void mcdis_box(double x, double y, double z,
	       double width, double height, double length){

  mcdis_rectangle("xy", x, y, z-length/2, width, height);
  mcdis_rectangle("xy", x, y, z+length/2, width, height);
  mcdis_line(x-width/2, y-height/2, z-length/2,
	     x-width/2, y-height/2, z+length/2);
  mcdis_line(x-width/2, y+height/2, z-length/2,
	     x-width/2, y+height/2, z+length/2);
  mcdis_line(x+width/2, y-height/2, z-length/2,
	     x+width/2, y-height/2, z+length/2);
  mcdis_line(x+width/2, y+height/2, z-length/2,
	     x+width/2, y+height/2, z+length/2);
}

void mcdis_circle(char *plane, double x, double y, double z, double r){
  printf("MCDISPLAY: circle('%s',%g,%g,%g,%g)\n", plane, x, y, z, r);
}

/* coordinates handling ===================================================== */

/*******************************************************************************
* Since we use a lot of geometric calculations using Cartesian coordinates,
* we collect some useful routines here. However, it is also permissible to
* work directly on the underlying struct coords whenever that is most
* convenient (that is, the type Coords is not abstract).
*
* Coordinates are also used to store rotation angles around x/y/z axis.
*
* Since coordinates are used much like a basic type (such as double), the
* structure itself is passed and returned, rather than a pointer.
*
* At compile-time, the values of the coordinates may be unknown (for example
* a motor position). Hence coordinates are general expressions and not simple
* numbers. For this we used the type Coords_exp which has three CExp
* fields. For runtime (or calculations possible at compile time), we use
* Coords which contains three double fields.
*******************************************************************************/

/* coords_set: Assign coordinates. */
Coords
coords_set(MCNUM x, MCNUM y, MCNUM z)
{
  Coords a;

  a.x = x;
  a.y = y;
  a.z = z;
  return a;
}

/* coords_get: get coordinates. Required when 'x','y','z' are #defined as neutron pars */
Coords
coords_get(Coords a, MCNUM *x, MCNUM *y, MCNUM *z)
{
  *x = a.x;
  *y = a.y;
  *z = a.z;
  return a;
}

/* coords_add: Add two coordinates. */
Coords
coords_add(Coords a, Coords b)
{
  Coords c;

  c.x = a.x + b.x;
  c.y = a.y + b.y;
  c.z = a.z + b.z;
  if (fabs(c.z) < 1e-14) c.z=0.0;
  return c;
}

/* coords_sub: Subtract two coordinates. */
Coords
coords_sub(Coords a, Coords b)
{
  Coords c;

  c.x = a.x - b.x;
  c.y = a.y - b.y;
  c.z = a.z - b.z;
  if (fabs(c.z) < 1e-14) c.z=0.0;
  return c;
}

/* coords_neg: Negate coordinates. */
Coords
coords_neg(Coords a)
{
  Coords b;

  b.x = -a.x;
  b.y = -a.y;
  b.z = -a.z;
  return b;
}

/* coords_scale: Scale a vector. */
Coords coords_scale(Coords b, double scale) {
  Coords a;

  a.x = b.x*scale;
  a.y = b.y*scale;
  a.z = b.z*scale;
  return a;
}

/* coords_sp: Scalar product: a . b */
double coords_sp(Coords a, Coords b) {
  double value;

  value = a.x*b.x + a.y*b.y + a.z*b.z;
  return value;
}

/* coords_xp: Cross product: a = b x c. */
Coords coords_xp(Coords b, Coords c) {
  Coords a;

  a.x = b.y*c.z - c.y*b.z;
  a.y = b.z*c.x - c.z*b.x;
  a.z = b.x*c.y - c.x*b.y;
  return a;
}

/* coords_mirror: Mirror a in plane (through the origin) defined by normal n*/
Coords coords_mirror(Coords a, Coords n) {
  double t = scalar_prod(n.x, n.y, n.z, n.x, n.y, n.z);
  Coords b;
  if (t!=1) {
    t = sqrt(t);
    n.x /= t;
    n.y /= t;
    n.z /= t;
  }
  t=scalar_prod(a.x, a.y, a.z, n.x, n.y, n.z);
  b.x = a.x-2*t*n.x;
  b.y = a.y-2*t*n.y;
  b.z = a.z-2*t*n.z;
  return b;
}

/* coords_print: Print out vector values. */
void coords_print(Coords a) {

  fprintf(stdout, "(%f, %f, %f)\n", a.x, a.y, a.z);
  return;
}

/*******************************************************************************
* The Rotation type implements a rotation transformation of a coordinate
* system in the form of a double[3][3] matrix.
*
* Contrary to the Coords type in coords.c, rotations are passed by
* reference. Functions that yield new rotations do so by writing to an
* explicit result parameter; rotations are not returned from functions. The
* reason for this is that arrays cannot by returned from functions (though
* structures can; thus an alternative would have been to wrap the
* double[3][3] array up in a struct). Such are the ways of C programming.
*
* A rotation represents the tranformation of the coordinates of a vector when
* changing between coordinate systems that are rotated with respect to each
* other. For example, suppose that coordinate system Q is rotated 45 degrees
* around the Z axis with respect to coordinate system P. Let T be the
* rotation transformation representing a 45 degree rotation around Z. Then to
* get the coordinates of a vector r in system Q, apply T to the coordinates
* of r in P. If r=(1,0,0) in P, it will be (sqrt(1/2),-sqrt(1/2),0) in
* Q. Thus we should be careful when interpreting the sign of rotation angles:
* they represent the rotation of the coordinate systems, not of the
* coordinates (which has opposite sign).
*******************************************************************************/

/*******************************************************************************
* rot_set_rotation: Get transformation for rotation first phx around x axis,
* then phy around y, then phz around z.
*******************************************************************************/
void
rot_set_rotation(Rotation t, double phx, double phy, double phz)
{
  if ((phx == 0) && (phy == 0) && (phz == 0)) {
    t[0][0] = 1.0;
    t[0][1] = 0.0;
    t[0][2] = 0.0;
    t[1][0] = 0.0;
    t[1][1] = 1.0;
    t[1][2] = 0.0;
    t[2][0] = 0.0;
    t[2][1] = 0.0;
    t[2][2] = 1.0;
  } else {
    double cx = cos(phx);
    double sx = sin(phx);
    double cy = cos(phy);
    double sy = sin(phy);
    double cz = cos(phz);
    double sz = sin(phz);
    
    t[0][0] = cy*cz;
    t[0][1] = sx*sy*cz + cx*sz;
    t[0][2] = sx*sz - cx*sy*cz;
    t[1][0] = -cy*sz;
    t[1][1] = cx*cz - sx*sy*sz;
    t[1][2] = sx*cz + cx*sy*sz;
    t[2][0] = sy;
    t[2][1] = -sx*cy;
    t[2][2] = cx*cy;
  } 
}

/*******************************************************************************
* rot_test_identity: Test if rotation is identity
*******************************************************************************/
int 
rot_test_identity(Rotation t)
{
  return (t[0][0] + t[1][1] + t[2][2] == 3);
}

/*******************************************************************************
* rot_mul: Matrix multiplication of transformations (this corresponds to
* combining transformations). After rot_mul(T1, T2, T3), doing T3 is
* equal to doing first T2, then T1.
* Note that T3 must not alias (use the same array as) T1 or T2.
*******************************************************************************/
void
rot_mul(Rotation t1, Rotation t2, Rotation t3)
{
  int i,j;
  if (rot_test_identity(t1)) {
    memcpy(t3, t2, 9 * sizeof (double));
  } else if (rot_test_identity(t2)) {
    memcpy(t3, t1, 9 * sizeof (double));
  } else {
    for(i = 0; i < 3; i++)
      for(j = 0; j < 3; j++)
	t3[i][j] = t1[i][0]*t2[0][j] + t1[i][1]*t2[1][j] + t1[i][2]*t2[2][j];
  }
}

/*******************************************************************************
* rot_copy: Copy a rotation transformation (arrays cannot be assigned in C).
*******************************************************************************/
void
rot_copy(Rotation dest, Rotation src)
{
	memcpy(dest, src, 9 * sizeof (double));
}

/*******************************************************************************
* rot_transpose: Matrix transposition, which is inversion for Rotation matrices
*******************************************************************************/
void
rot_transpose(Rotation src, Rotation dst)
{
  dst[0][0] = src[0][0];
  dst[0][1] = src[1][0];
  dst[0][2] = src[2][0];
  dst[1][0] = src[0][1];
  dst[1][1] = src[1][1];
  dst[1][2] = src[2][1];
  dst[2][0] = src[0][2];
  dst[2][1] = src[1][2];
  dst[2][2] = src[2][2];
}

/*******************************************************************************
* rot_apply: returns t*a
*******************************************************************************/
Coords
rot_apply(Rotation t, Coords a)
{
  Coords b;
  if (rot_test_identity(t)) { 
    return a;
  } else {
    b.x = t[0][0]*a.x + t[0][1]*a.y + t[0][2]*a.z;
    b.y = t[1][0]*a.x + t[1][1]*a.y + t[1][2]*a.z;
    b.z = t[2][0]*a.x + t[2][1]*a.y + t[2][2]*a.z;
    return b;
  }
}

/*******************************************************************************
* mccoordschange: applies rotation to (x y z) and (vx vy vz). Spin unchanged
*******************************************************************************/
void
mccoordschange(Coords a, Rotation t, double *x, double *y, double *z,
               double *vx, double *vy, double *vz, double *time,
               double *s1, double *s2)
{
  Coords b, c;

  b.x = *x;
  b.y = *y;
  b.z = *z;
  c = rot_apply(t, b);
  b = coords_add(c, a);
  *x = b.x;
  *y = b.y;
  *z = b.z;

  b.x = *vx;
  b.y = *vy;
  b.z = *vz;
  c = rot_apply(t, b);
  *vx = c.x;
  *vy = c.y;
  *vz = c.z;
  /* spin handled with mccoordschange_polarisation */
}

/*******************************************************************************
* mccoordschange_polarisation: applies rotation to (sx sy sz)
*******************************************************************************/
void
mccoordschange_polarisation(Rotation t, double *sx, double *sy, double *sz)
{
  Coords b, c;

  b.x = *sx;
  b.y = *sy;
  b.z = *sz;
  c = rot_apply(t, b);
  *sx = c.x;
  *sy = c.y;
  *sz = c.z;
}

/*******************************************************************************
* mcstore_neutron: stores neutron coodinates into global array (per component)
*******************************************************************************/
void
mcstore_neutron(MCNUM *s, int index, double x, double y, double z,
               double vx, double vy, double vz, double t,
               double sx, double sy, double sz, double p)
{
    double *dptr = &s[11*index];
    *dptr++  = x;
    *dptr++  = y ;
    *dptr++  = z ;
    *dptr++  = vx;
    *dptr++  = vy;
    *dptr++  = vz;
    *dptr++  = t ;
    *dptr++  = sx;
    *dptr++  = sy;
    *dptr++  = sz;
    *dptr    = p ;
}

/*******************************************************************************
* mcrestore_neutron: restores neutron coodinates from global array
*******************************************************************************/
void
mcrestore_neutron(MCNUM *s, int index, double *x, double *y, double *z,
               double *vx, double *vy, double *vz, double *t,
               double *sx, double *sy, double *sz, double *p)
{
    double *dptr = &s[11*index];
    *x  =  *dptr++;
    *y  =  *dptr++;
    *z  =  *dptr++;
    *vx =  *dptr++;
    *vy =  *dptr++;
    *vz =  *dptr++;
    *t  =  *dptr++;
    *sx =  *dptr++;
    *sy =  *dptr++;
    *sz =  *dptr++;
    *p  =  *dptr;
}

/* init/run/rand handling =================================================== */

/* mcreadparams: request parameters from the prompt (or use default) */
void
mcreadparams(void)
{
  int i,j,status;
  static char buf[CHAR_BUF_LENGTH];
  char *p;
  int len;

  MPI_MASTER(printf("Instrument parameters for %s (%s)\n",
                    mcinstrument_name, mcinstrument_source));

  for(i = 0; mcinputtable[i].name != 0; i++)
  {
    do
    {
      MPI_MASTER(
                 if (mcinputtable[i].val && strlen(mcinputtable[i].val))
                   printf("Set value of instrument parameter %s (%s) [default='%s']:\n",
                          mcinputtable[i].name,
                          (*mcinputtypes[mcinputtable[i].type].parminfo)
                          (mcinputtable[i].name), mcinputtable[i].val);
                 else
                   printf("Set value of instrument parameter %s (%s):\n",
                          mcinputtable[i].name,
                          (*mcinputtypes[mcinputtable[i].type].parminfo)
                          (mcinputtable[i].name));
                 fflush(stdout);
                 );
#ifdef USE_MPI
      if(mpi_node_rank == mpi_node_root)
        {
          p = fgets(buf, CHAR_BUF_LENGTH, stdin);
          if(p == NULL)
            {
              fprintf(stderr, "Error: empty input for paramater %s (mcreadparams)\n", mcinputtable[i].name);
              exit(1);
            }
        }
      else
        p = buf;
      MPI_Bcast(buf, CHAR_BUF_LENGTH, MPI_CHAR, mpi_node_root, MPI_COMM_WORLD);
#else /* !USE_MPI */
      p = fgets(buf, CHAR_BUF_LENGTH, stdin);
      if(p == NULL)
        {
          fprintf(stderr, "Error: empty input for paramater %s (mcreadparams)\n", mcinputtable[i].name);
          exit(1);
        }
#endif /* USE_MPI */
      len = strlen(buf);
      if (!len || (len == 1 && (buf[0] == '\n' || buf[0] == '\r')))
      {
        if (mcinputtable[i].val && strlen(mcinputtable[i].val)) {
          strncpy(buf, mcinputtable[i].val, CHAR_BUF_LENGTH);  /* use default value */
          len = strlen(buf);
        }
      }
      for(j = 0; j < 2; j++)
      {
        if(len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
        {
          len--;
          buf[len] = '\0';
        }
      }

      status = (*mcinputtypes[mcinputtable[i].type].getparm)
                   (buf, mcinputtable[i].par);
      if(!status)
      {
        (*mcinputtypes[mcinputtable[i].type].error)(mcinputtable[i].name, buf);
        if (!mcinputtable[i].val || strlen(mcinputtable[i].val)) {
          fprintf(stderr, "       Change %s default value in instrument definition.\n", mcinputtable[i].name);
          exit(1);
        }
      }
    } while(!status);
  }
}

/* mcsetstate: transfert parameters into global McStas variables */
void
mcsetstate(double x, double y, double z, double vx, double vy, double vz,
           double t, double sx, double sy, double sz, double p)
{
  extern double mcnx, mcny, mcnz, mcnvx, mcnvy, mcnvz;
  extern double mcnt, mcnsx, mcnsy, mcnsz, mcnp;

  mcnx = x;
  mcny = y;
  mcnz = z;
  mcnvx = vx;
  mcnvy = vy;
  mcnvz = vz;
  mcnt = t;
  mcnsx = sx;
  mcnsy = sy;
  mcnsz = sz;
  mcnp = p;
}

/* mcgenstate: set default neutron parameters */
void
mcgenstate(void)
{
  mcsetstate(0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
  /* old initialisation: mcsetstate(0, 0, 0, 0, 0, 1, 0, sx=0, sy=1, sz=0, 1); */
}

/* McStas random number routine. */

/*
 * Copyright (c) 1983 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/*
 * This is derived from the Berkeley source:
 *        @(#)random.c        5.5 (Berkeley) 7/6/88
 * It was reworked for the GNU C Library by Roland McGrath.
 * Rewritten to use reentrant functions by Ulrich Drepper, 1995.
 */

/*******************************************************************************
* Modified for McStas from glibc 2.0.7pre1 stdlib/random.c and
* stdlib/random_r.c.
*
* This way random() is more than four times faster compared to calling
* standard glibc random() on ix86 Linux, probably due to multithread support,
* ELF shared library overhead, etc. It also makes McStas generated
* simulations more portable (more likely to behave identically across
* platforms, important for parrallel computations).
*******************************************************************************/


#define        TYPE_3                3
#define        BREAK_3                128
#define        DEG_3                31
#define        SEP_3                3

static mc_int32_t randtbl[DEG_3 + 1] =
  {
    TYPE_3,

    -1726662223, 379960547, 1735697613, 1040273694, 1313901226,
    1627687941, -179304937, -2073333483, 1780058412, -1989503057,
    -615974602, 344556628, 939512070, -1249116260, 1507946756,
    -812545463, 154635395, 1388815473, -1926676823, 525320961,
    -1009028674, 968117788, -123449607, 1284210865, 435012392,
    -2017506339, -911064859, -370259173, 1132637927, 1398500161,
    -205601318,
  };

static mc_int32_t *fptr = &randtbl[SEP_3 + 1];
static mc_int32_t *rptr = &randtbl[1];
static mc_int32_t *state = &randtbl[1];
#define rand_deg DEG_3
#define rand_sep SEP_3
static mc_int32_t *end_ptr = &randtbl[sizeof (randtbl) / sizeof (randtbl[0])];

mc_int32_t
mc_random (void)
{
  mc_int32_t result;

  *fptr += *rptr;
  /* Chucking least random bit.  */
  result = (*fptr >> 1) & 0x7fffffff;
  ++fptr;
  if (fptr >= end_ptr)
  {
    fptr = state;
    ++rptr;
  }
  else
  {
    ++rptr;
    if (rptr >= end_ptr)
      rptr = state;
  }
  return result;
}

void
mc_srandom (unsigned int x)
{
  /* We must make sure the seed is not 0.  Take arbitrarily 1 in this case.  */
  state[0] = x ? x : 1;
  {
    long int i;
    for (i = 1; i < rand_deg; ++i)
    {
      /* This does:
         state[i] = (16807 * state[i - 1]) % 2147483647;
         but avoids overflowing 31 bits.  */
      long int hi = state[i - 1] / 127773;
      long int lo = state[i - 1] % 127773;
      long int test = 16807 * lo - 2836 * hi;
      state[i] = test + (test < 0 ? 2147483647 : 0);
    }
    fptr = &state[rand_sep];
    rptr = &state[0];
    for (i = 0; i < 10 * rand_deg; ++i)
      random ();
  }
}

/* "Mersenne Twister", by Makoto Matsumoto and Takuji Nishimura. */
/* See http://www.math.keio.ac.jp/~matumoto/emt.html for original source. */


/*
   A C-program for MT19937, with initialization improved 2002/1/26.
   Coded by Takuji Nishimura and Makoto Matsumoto.

   Before using, initialize the state by using mt_srandom(seed)
   or init_by_array(init_key, key_length).

   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

     1. Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.

     2. Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.

     3. The names of its contributors may not be used to endorse or promote
        products derived from this software without specific prior written
        permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


   Any feedback is very welcome.
   http://www.math.keio.ac.jp/matumoto/emt.html
   email: matumoto@math.keio.ac.jp
*/

#include <stdio.h>

/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL   /* constant vector a */
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */

static unsigned long mt[N]; /* the array for the state vector  */
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */

/* initializes mt[N] with a seed */
void mt_srandom(unsigned long s)
{
    mt[0]= s & 0xffffffffUL;
    for (mti=1; mti<N; mti++) {
        mt[mti] =
            (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
        /* In the previous versions, MSBs of the seed affect   */
        /* only MSBs of the array mt[].                        */
        /* 2002/01/09 modified by Makoto Matsumoto             */
        mt[mti] &= 0xffffffffUL;
        /* for >32 bit machines */
    }
}

/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
void init_by_array(init_key, key_length)
unsigned long init_key[], key_length;
{
    int i, j, k;
    mt_srandom(19650218UL);
    i=1; j=0;
    k = (N>key_length ? N : key_length);
    for (; k; k--) {
        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
          + init_key[j] + j; /* non linear */
        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
        i++; j++;
        if (i>=N) { mt[0] = mt[N-1]; i=1; }
        if (j>=key_length) j=0;
    }
    for (k=N-1; k; k--) {
        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
          - i; /* non linear */
        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
        i++;
        if (i>=N) { mt[0] = mt[N-1]; i=1; }
    }

    mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
}

/* generates a random number on [0,0xffffffff]-interval */
unsigned long mt_random(void)
{
    unsigned long y;
    static unsigned long mag01[2]={0x0UL, MATRIX_A};
    /* mag01[x] = x * MATRIX_A  for x=0,1 */

    if (mti >= N) { /* generate N words at one time */
        int kk;

        if (mti == N+1)   /* if mt_srandom() has not been called, */
            mt_srandom(5489UL); /* a default initial seed is used */

        for (kk=0;kk<N-M;kk++) {
            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
        }
        for (;kk<N-1;kk++) {
            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
        }
        y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
        mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];

        mti = 0;
    }

    y = mt[mti++];

    /* Tempering */
    y ^= (y >> 11);
    y ^= (y << 7) & 0x9d2c5680UL;
    y ^= (y << 15) & 0xefc60000UL;
    y ^= (y >> 18);

    return y;
}

#undef N
#undef M
#undef MATRIX_A
#undef UPPER_MASK
#undef LOWER_MASK

/* End of "Mersenne Twister". */

/* End of McStas random number routine. */

/* randnorm: generate a random number from normal law */
double
randnorm(void)
{
  static double v1, v2, s;
  static int phase = 0;
  double X, u1, u2;

  if(phase == 0)
  {
    do
    {
      u1 = rand01();
      u2 = rand01();
      v1 = 2*u1 - 1;
      v2 = 2*u2 - 1;
      s = v1*v1 + v2*v2;
    } while(s >= 1 || s == 0);

    X = v1*sqrt(-2*log(s)/s);
  }
  else
  {
    X = v2*sqrt(-2*log(s)/s);
  }

  phase = 1 - phase;
  return X;
}

/* generate a random number from -1 to 1 with triangle distribution */
double randtriangle(void) {
  double randnum=rand01();
  if (randnum>0.5) return(1-sqrt(2*(randnum-0.5)));
  else return(sqrt(2*randnum)-1);
}

/* intersect handling ======================================================= */

/* normal_vec: Compute normal vector to (x,y,z). */
void normal_vec(double *nx, double *ny, double *nz,
                double x, double y, double z)
{
  double ax = fabs(x);
  double ay = fabs(y);
  double az = fabs(z);
  double l;
  if(x == 0 && y == 0 && z == 0)
  {
    *nx = 0;
    *ny = 0;
    *nz = 0;
    return;
  }
  if(ax < ay)
  {
    if(ax < az)
    {                           /* Use X axis */
      l = sqrt(z*z + y*y);
      *nx = 0;
      *ny = z/l;
      *nz = -y/l;
      return;
    }
  }
  else
  {
    if(ay < az)
    {                           /* Use Y axis */
      l = sqrt(z*z + x*x);
      *nx = z/l;
      *ny = 0;
      *nz = -x/l;
      return;
    }
  }
  /* Use Z axis */
  l = sqrt(y*y + x*x);
  *nx = y/l;
  *ny = -x/l;
  *nz = 0;
}

/* inside_rectangle: Check if (x,y) is inside rectangle (xwidth, yheight) */
/* return 0 if outside and 1 if inside */
int inside_rectangle(double x, double y, double xwidth, double yheight)
{
  if (x>-xwidth/2 && x<xwidth/2 && y>-yheight/2 && y<yheight/2)
    return 1;
  else
    return 0;
}

/* box_intersect: compute time intersection with a box
 * returns 0 when no intersection is found
 *      or 1 in case of intersection with resulting times dt_in and dt_out
 * This function written by Stine Nyborg, 1999. */
int box_intersect(double *dt_in, double *dt_out,
                  double x, double y, double z,
                  double vx, double vy, double vz,
                  double dx, double dy, double dz)
{
  double x_in, y_in, z_in, tt, t[6], a, b;
  int i, count, s;

      /* Calculate intersection time for each of the six box surface planes
       *  If the box surface plane is not hit, the result is zero.*/

  if(vx != 0)
   {
    tt = -(dx/2 + x)/vx;
    y_in = y + tt*vy;
    z_in = z + tt*vz;
    if( y_in > -dy/2 && y_in < dy/2 && z_in > -dz/2 && z_in < dz/2)
      t[0] = tt;
    else
      t[0] = 0;

    tt = (dx/2 - x)/vx;
    y_in = y + tt*vy;
    z_in = z + tt*vz;
    if( y_in > -dy/2 && y_in < dy/2 && z_in > -dz/2 && z_in < dz/2)
      t[1] = tt;
    else
      t[1] = 0;
   }
  else
    t[0] = t[1] = 0;

  if(vy != 0)
   {
    tt = -(dy/2 + y)/vy;
    x_in = x + tt*vx;
    z_in = z + tt*vz;
    if( x_in > -dx/2 && x_in < dx/2 && z_in > -dz/2 && z_in < dz/2)
      t[2] = tt;
    else
      t[2] = 0;

    tt = (dy/2 - y)/vy;
    x_in = x + tt*vx;
    z_in = z + tt*vz;
    if( x_in > -dx/2 && x_in < dx/2 && z_in > -dz/2 && z_in < dz/2)
      t[3] = tt;
    else
      t[3] = 0;
   }
  else
    t[2] = t[3] = 0;

  if(vz != 0)
   {
    tt = -(dz/2 + z)/vz;
    x_in = x + tt*vx;
    y_in = y + tt*vy;
    if( x_in > -dx/2 && x_in < dx/2 && y_in > -dy/2 && y_in < dy/2)
      t[4] = tt;
    else
      t[4] = 0;

    tt = (dz/2 - z)/vz;
    x_in = x + tt*vx;
    y_in = y + tt*vy;
    if( x_in > -dx/2 && x_in < dx/2 && y_in > -dy/2 && y_in < dy/2)
      t[5] = tt;
    else
      t[5] = 0;
   }
  else
    t[4] = t[5] = 0;

  /* The intersection is evaluated and *dt_in and *dt_out are assigned */

  a = b = s = 0;
  count = 0;

  for( i = 0; i < 6; i = i + 1 )
    if( t[i] == 0 )
      s = s+1;
    else if( count == 0 )
    {
      a = t[i];
      count = 1;
    }
    else
    {
      b = t[i];
      count = 2;
    }

  if ( a == 0 && b == 0 )
    return 0;
  else if( a < b )
  {
    *dt_in = a;
    *dt_out = b;
    return 1;
  }
  else
  {
    *dt_in = b;
    *dt_out = a;
    return 1;
  }

}

/* cylinder_intersect: compute intersection with a cylinder
 * returns 0 when no intersection is found
 *      or 2/4/8/16 bits depending on intersection,
 *     and resulting times t0 and t1
 * Written by: EM,NB,ABA 4.2.98 */
int
cylinder_intersect(double *t0, double *t1, double x, double y, double z,
                   double vx, double vy, double vz, double r, double h)
{
  double D, t_in, t_out, y_in, y_out;
  int ret=1;

  D = (2*vx*x + 2*vz*z)*(2*vx*x + 2*vz*z)
    - 4*(vx*vx + vz*vz)*(x*x + z*z - r*r);

  if (D>=0)
  {
    if (vz*vz + vx*vx) {
      t_in  = (-(2*vz*z + 2*vx*x) - sqrt(D))/(2*(vz*vz + vx*vx));
      t_out = (-(2*vz*z + 2*vx*x) + sqrt(D))/(2*(vz*vz + vx*vx));
    } else if (vy) { /* trajectory parallel to cylinder axis */
      t_in = (y + h/2)/vy;
      t_out = (y - h/2)/vy;
      if (t_in>t_out){ 
	        double tmp=t_in; 
	        t_in=t_out;t_out=tmp; 
	    } 
    } else return 0;
    y_in = vy*t_in + y;
    y_out =vy*t_out + y;

    if ( (y_in > h/2 && y_out > h/2) || (y_in < -h/2 && y_out < -h/2) )
      return 0;
    else
    {
      if (y_in > h/2)
        { t_in = ((h/2)-y)/vy; ret += 2; }
      else if (y_in < -h/2)
        { t_in = ((-h/2)-y)/vy; ret += 4; }
      if (y_out > h/2)
        { t_out = ((h/2)-y)/vy; ret += 8; }
      else if (y_out < -h/2)
        { t_out = ((-h/2)-y)/vy; ret += 16; }
    }
    *t0 = t_in;
    *t1 = t_out;
    return ret;
  }
  else
  {
    *t0 = *t1 = 0;
    return 0;
  }
}


/* sphere_intersect: Calculate intersection between a line and a sphere.
 * returns 0 when no intersection is found
 *      or 1 in case of intersection with resulting times t0 and t1 */
int
sphere_intersect(double *t0, double *t1, double x, double y, double z,
                 double vx, double vy, double vz, double r)
{
  double A, B, C, D, v;

  v = sqrt(vx*vx + vy*vy + vz*vz);
  A = v*v;
  B = 2*(x*vx + y*vy + z*vz);
  C = x*x + y*y + z*z - r*r;
  D = B*B - 4*A*C;
  if(D < 0)
    return 0;
  D = sqrt(D);
  *t0 = (-B - D) / (2*A);
  *t1 = (-B + D) / (2*A);
  return 1;
}

/* solve_2nd_order: second order equation solve: A*t^2 + B*t + C = 0
 * returns 0 if no solution was found, or set 't' to the smallest positive
 * solution.
 * EXAMPLE usage for intersection of a trajectory with a plane in gravitation
 * field (gx,gy,gz):
 * The neutron starts at point r=(x,y,z) with velocityv=(vx vy vz). The plane
 * has a normal vector n=(nx,ny,nz) and contains the point W=(wx,wy,wz).
 * The problem consists in solving the 2nd order equation:
 *      1/2.n.g.t^2 + n.v.t + n.(r-W) = 0
 * so that A = 0.5 n.g; B = n.v; C = n.(r-W);
 * Without acceleration, t=-n.(r-W)/n.v
 */
int solve_2nd_order(double *Idt,
                  double A,  double B,  double C)
{
  int ret=0;

  *Idt = 0;

  if (fabs(A) < 1E-10) /* this plane is parallel to the acceleration: A ~ 0 */
  {
    if (B) {  *Idt = -C/B; ret=3; }
    /* else the speed is parallel to the plane, no intersection: A=B=0 ret=0 */
  }
  else
  {
    double D;
    D = B*B - 4*A*C;
    if (D >= 0) /* Delta > 0: neutron trajectory hits the mirror */
    {
      double sD, dt1, dt2;
      sD = sqrt(D);
      dt1 = (-B + sD)/2/A;
      dt2 = (-B - sD)/2/A;
      /* we identify very small values with zero */
      if (fabs(dt1) < 1e-10) dt1=0.0;
      if (fabs(dt2) < 1e-10) dt2=0.0;

      /* now we choose the smallest positive solution */
      if      (dt1<=0.0 && dt2>0.0) ret=2; /* dt2 positive */
      else if (dt2<=0.0 && dt1>0.0) ret=1; /* dt1 positive */
      else if (dt1> 0.0 && dt2>0.0)
      {  if (dt1 < dt2) ret=1; else ret=2; } /* all positive: min(dt1,dt2) */
      /* else two solutions are negative. ret=0 */
      if (ret==1) *Idt = dt1; else if (ret==2) *Idt=dt2;
    } /* else Delta <0: no intersection.  ret=0 */
  }
  return(ret);
}

/* plane_intersect: Calculate intersection between a plane and a line.
 * returns 0 when no intersection is found (i.e. line is parallel to the plane)
 * returns 1 or -1 when intersection time is positive and negative respectively
 */  
int
plane_intersect(double *t, double x, double y, double z,
                 double vx, double vy, double vz, double nx, double ny, double nz, double wx, double wy, double wz)
{
  double s;
  if (fabs(s=scalar_prod(nx,ny,nz,vx,vy,vz))<FLT_EPSILON) return 0;
  *t = - scalar_prod(nx,ny,nz,x-wx,y-wy,z-wz)/s;
  if (*t<0) return -1;
  else return 1;
}

/* randvec_target_circle: Choose random direction towards target at (x,y,z)
 * with given radius.
 * If radius is zero, choose random direction in full 4PI, no target. */
void
randvec_target_circle(double *xo, double *yo, double *zo, double *solid_angle,
               double xi, double yi, double zi, double radius)
{
  double l2, phi, theta, nx, ny, nz, xt, yt, zt, xu, yu, zu;

  if(radius == 0.0)
  {
    /* No target, choose uniformly a direction in full 4PI solid angle. */
    theta = acos (1 - rand0max(2));
    phi = rand0max(2 * PI);
    if(solid_angle)
      *solid_angle = 4*PI;
    nx = 1;
    ny = 0;
    nz = 0;
    yi = sqrt(xi*xi+yi*yi+zi*zi);
    zi = 0;
    xi = 0;
  }
  else
  {
    double costheta0;
    l2 = xi*xi + yi*yi + zi*zi; /* sqr Distance to target. */
    costheta0 = sqrt(l2/(radius*radius+l2));
    if (radius < 0) costheta0 *= -1;
    if(solid_angle)
    {
      /* Compute solid angle of target as seen from origin. */
        *solid_angle = 2*PI*(1 - costheta0);
    }

    /* Now choose point uniformly on circle surface within angle theta0 */
    theta = acos (1 - rand0max(1 - costheta0)); /* radius on circle */
    phi = rand0max(2 * PI); /* rotation on circle at given radius */
    /* Now, to obtain the desired vector rotate (xi,yi,zi) angle theta around a
       perpendicular axis u=i x n and then angle phi around i. */
    if(xi == 0 && zi == 0)
    {
      nx = 1;
      ny = 0;
      nz = 0;
    }
    else
    {
      nx = -zi;
      nz = xi;
      ny = 0;
    }
  }

  /* [xyz]u = [xyz]i x n[xyz] (usually vertical) */
  vec_prod(xu,  yu,  zu, xi, yi, zi,        nx, ny, nz);
  /* [xyz]t = [xyz]i rotated theta around [xyz]u */
  rotate  (xt,  yt,  zt, xi, yi, zi, theta, xu, yu, zu);
  /* [xyz]o = [xyz]t rotated phi around n[xyz] */
  rotate (*xo, *yo, *zo, xt, yt, zt, phi, xi, yi, zi);
}


/* randvec_target_rect_angular: Choose random direction towards target at
 * (xi,yi,zi) with given ANGULAR dimension height x width. height=phi_x,
 * width=phi_y (radians)
 * If height or width is zero, choose random direction in full 4PI, no target. */
void
randvec_target_rect_angular(double *xo, double *yo, double *zo, double *solid_angle,
               double xi, double yi, double zi, double width, double height, Rotation A)
{
  double theta, phi, nx, ny, nz, xt, yt, zt, xu, yu, zu;
  Coords tmp;
  Rotation Ainverse;

  rot_transpose(A, Ainverse);

  if(height == 0.0 || width == 0.0)
  {
    randvec_target_circle(xo, yo, zo, solid_angle,
               xi, yi, zi, 0);
    return;
  }
  else
  {
    if(solid_angle)
    {
      /* Compute solid angle of target as seen from origin. */
      *solid_angle = 2*fabs(width*sin(height/2));
    }

    /* Go to global coordinate system */

    tmp = coords_set(xi, yi, zi);
    tmp = rot_apply(Ainverse, tmp);
    coords_get(tmp, &xi, &yi, &zi);

    /* Now choose point uniformly on quadrant within angle theta0/phi0 */
    theta = width*randpm1()/2.0;
    phi   = height*randpm1()/2.0;
    /* Now, to obtain the desired vector rotate (xi,yi,zi) angle phi around
       n, and then theta around u. */
    if(xi == 0 && zi == 0)
    {
      nx = 1;
      ny = 0;
      nz = 0;
    }
    else
    {
      nx = -zi;
      nz = xi;
      ny = 0;
    }
  }

  /* [xyz]u = [xyz]i x n[xyz] (usually vertical) */
  vec_prod(xu,  yu,  zu, xi, yi, zi,        nx, ny, nz);
  /* [xyz]t = [xyz]i rotated theta around [xyz]u */
  rotate  (xt,  yt,  zt, xi, yi, zi, phi, nx, ny, nz);
  /* [xyz]o = [xyz]t rotated phi around n[xyz] */
  rotate (*xo, *yo, *zo, xt, yt, zt, theta, xu,  yu,  zu);

  /* Go back to local coordinate system */
  tmp = coords_set(*xo, *yo, *zo);
  tmp = rot_apply(A, tmp);
  coords_get(tmp, &*xo, &*yo, &*zo);

}

/* randvec_target_rect_real: Choose random direction towards target at (xi,yi,zi)
 * with given dimension height x width (in meters !).
 *
 * Local emission coordinate is taken into account and corrected for 'order' times.
 * (See remarks posted to mcstas-users by George Apostolopoulus <gapost@ipta.demokritos.gr>)
 *
 * If height or width is zero, choose random direction in full 4PI, no target. 
 * 
 * Traditionally, this routine had the name randvec_target_rect - this is now a
 * a define (see mcstas-r.h) pointing here. If you use the old rouine, you are NOT
 * taking the local emmission coordinate into account. 
*/

void
randvec_target_rect_real(double *xo, double *yo, double *zo, double *solid_angle,
               double xi, double yi, double zi, double width, double height, Rotation A, double lx, double ly, double lz, int order)
{
  double dx, dy, dist, dist_p, nx, ny, nz, mx, my, mz, n_norm, m_norm;
  double cos_theta;
  Coords tmp;
  Rotation Ainverse;

  rot_transpose(A, Ainverse);

  if(height == 0.0 || width == 0.0)
  {
    randvec_target_circle(xo, yo, zo, solid_angle,
               xi, yi, zi, 0);
    return;
  }
  else
  {

    /* Now choose point uniformly on rectangle within width x height */
    dx = width*randpm1()/2.0;
    dy = height*randpm1()/2.0;

    /* Determine distance to target plane*/
    dist = sqrt(xi*xi + yi*yi + zi*zi);
    /* Go to global coordinate system */

    tmp = coords_set(xi, yi, zi);
    tmp = rot_apply(Ainverse, tmp);
    coords_get(tmp, &xi, &yi, &zi);

    /* Determine vector normal to neutron axis (z) and gravity [0 1 0] */
    vec_prod(nx, ny, nz, xi, yi, zi, 0, 1, 0);

    /* This now defines the x-axis, normalize: */
    n_norm=sqrt(nx*nx + ny*ny + nz*nz);
    nx = nx/n_norm;
    ny = ny/n_norm;
    nz = nz/n_norm;

    /* Now, determine our y-axis (vertical in many cases...) */
    vec_prod(mx, my, mz, xi, yi, zi, nx, ny, nz);
    m_norm=sqrt(mx*mx + my*my + mz*mz);
    mx = mx/m_norm;
    my = my/m_norm;
    mz = mz/m_norm;

    /* Our output, random vector can now be defined by linear combination: */

    *xo = xi + dx * nx + dy * mx;
    *yo = yi + dx * ny + dy * my;
    *zo = zi + dx * nz + dy * mz;

    /* Go back to local coordinate system */
    tmp = coords_set(*xo, *yo, *zo);
    tmp = rot_apply(A, tmp);
    coords_get(tmp, &*xo, &*yo, &*zo);

    /* Go back to local coordinate system */
    tmp = coords_set(xi, yi, zi);
    tmp = rot_apply(A, tmp);
    coords_get(tmp, &xi, &yi, &zi);

    if (solid_angle) {
      /* Calculate vector from local point to remote random point */
      lx = *xo - lx;
      ly = *yo - ly;
      lz = *zo - lz;
      dist_p = sqrt(lx*lx + ly*ly + lz*lz);
      
      /* Adjust the 'solid angle' */
      /* 1/r^2 to the chosen point times cos(\theta) between the normal */
      /* vector of the target rectangle and direction vector of the chosen point. */
      cos_theta = (xi * lx + yi * ly + zi * lz) / (dist * dist_p);
      *solid_angle = width * height / (dist_p * dist_p); 
      int counter;
      for (counter = 0; counter < order; counter++) {
	*solid_angle = *solid_angle * cos_theta;
      }
    }
  }
}


/* extend_list: Make sure a list is big enough to hold element COUNT.
*
* The list is an array, and the argument 'list' is a pointer to a pointer to
* the array start. The argument 'size' is a pointer to the number of elements
* in the array. The argument 'elemsize' is the sizeof() an element. The
* argument 'count' is the minimum number of elements needed in the list.
*
* If the old array is to small (or if *list is NULL or *size is 0), a
* sufficuently big new array is allocated, and *list and *size are updated.
*/
void extend_list(int count, void **list, int *size, size_t elemsize)
{
  if(count >= *size)
  {
    void *oldlist = *list;
    if(*size > 0)
      *size *= 2;
    else
      *size = 32;
    *list = malloc(*size*elemsize);
    if(!*list)
    {
      exit(fprintf(stderr, "\nError: Out of memory %li (extend_list).\n", (long)*size*elemsize));
    }
    if(oldlist)
    {
      memcpy(*list, oldlist, count*elemsize);
      free(oldlist);
    }
  }
}

/* mcsetn_arg: get ncount from a string argument */
static void
mcsetn_arg(char *arg)
{
  mcset_ncount((long long int) strtod(arg, NULL));
}

/* mcsetseed: set the random generator seed from a string argument */
static void
mcsetseed(char *arg)
{
  mcseed = atol(arg);
  if(mcseed) {
#ifdef USE_MPI
    if (mpi_node_count > 1) srandom(mcseed+mpi_node_rank);
    else
#endif
    srandom(mcseed);
  } else {
    fprintf(stderr, "Error: seed must not be zero (mcsetseed)\n");
    exit(1);
  }
}

/* mchelp: displays instrument executable help with possible options */
static void
mchelp(char *pgmname)
{
  int i;

  fprintf(stderr, "Usage: %s [options] [parm=value ...]\n", pgmname);
  fprintf(stderr,
"Options are:\n"
"  -s SEED   --seed=SEED      Set random seed (must be != 0)\n"
"  -n COUNT  --ncount=COUNT   Set number of neutrons to simulate.\n"
"  -d DIR    --dir=DIR        Put all data files in directory DIR.\n"
"  -f FILE   --file=FILE      Put all data in a single file.\n"
"  -t        --trace          Enable trace of neutron through instrument.\n"
"  -g        --gravitation    Enable gravitation for all trajectories.\n"
"  -a        --data-only      Do not put any headers in the data files.\n"
"  --no-output-files          Do not write any data files.\n"
"  -h        --help           Show this help message.\n"
"  -i        --info           Detailed instrument information.\n"
"  --format=FORMAT            Output data files using format FORMAT\n"
"                             (use option +a to include text header in files\n"
#ifdef USE_MPI
"This instrument has been compiled with MPI support. Use 'mpirun'.\n"
#endif
"\n"
);
  if(mcnumipar > 0)
  {
    fprintf(stderr, "Instrument parameters are:\n");
    for(i = 0; i < mcnumipar; i++)
      if (mcinputtable[i].val && strlen(mcinputtable[i].val))
        fprintf(stderr, "  %-16s(%s) [default='%s']\n", mcinputtable[i].name,
        (*mcinputtypes[mcinputtable[i].type].parminfo)(mcinputtable[i].name),
        mcinputtable[i].val);
      else
        fprintf(stderr, "  %-16s(%s)\n", mcinputtable[i].name,
        (*mcinputtypes[mcinputtable[i].type].parminfo)(mcinputtable[i].name));
  }
  fprintf(stderr, "Available output formats are (default is %s):\n  ", mcformat.Name);
  for (i=0; i < mcNUMFORMATS; fprintf(stderr,"\"%s\" " , mcformats[i++].Name) );
  fprintf(stderr, "\n  Format modifiers: FORMAT may be followed by 'binary float' or \n");
  fprintf(stderr, "  'binary double' to save data blocks as binary. This removes text headers.\n");
  fprintf(stderr, "  The MCSTAS_FORMAT environment variable may set the default FORMAT to use.\n");
#ifndef NOSIGNALS
  fprintf(stderr, "Known signals are: "
#ifdef SIGUSR1
  "USR1 (status) "
#endif
#ifdef SIGUSR2
  "USR2 (save) "
#endif
#ifdef SIGBREAK
  "BREAK (save) "
#endif
#ifdef SIGTERM
  "TERM (save and exit)"
#endif
  "\n");
#endif /* !NOSIGNALS */
}

/* mcshowhelp: show help and exit with 0 */
static void
mcshowhelp(char *pgmname)
{
  mchelp(pgmname);
#ifdef USE_MPI
#undef exit
#endif
  exit(0);
#ifdef USE_MPI
#define exit(code) MPI_Abort(MPI_COMM_WORLD, code)
#endif
}

/* mcusage: display usage when error in input arguments and exit with 1 */
static void
mcusage(char *pgmname)
{
  fprintf(stderr, "Error: incorrect command line arguments\n");
  mchelp(pgmname);
  exit(1);
}

/* mcenabletrace: enable trace/mcdisplay or error if requires recompile */
static void
mcenabletrace(void)
{
 if(mctraceenabled)
  mcdotrace = 1;
 else
 {
   fprintf(stderr,
           "Error: trace not enabled (mcenabletrace)\n"
           "Please re-run the McStas compiler "
                   "with the --trace option, or rerun the\n"
           "C compiler with the MC_TRACE_ENABLED macro defined.\n");
   exit(1);
 }
}

/* mcuse_dir: set data/sim storage directory and create it,
 * or exit with error if exists */
static void
mcuse_dir(char *dir)
{
#ifdef MC_PORTABLE
  fprintf(stderr, "Error: "
          "Directory output cannot be used with portable simulation (mcuse_dir)\n");
  exit(1);
#else  /* !MC_PORTABLE */
#ifdef USE_MPI  
    if(mpi_node_rank == mpi_node_root)
    {
#endif
     if(mkdir(dir, 0777)) {
#ifndef DANSE
         fprintf(stderr, "Error: unable to create directory '%s' (mcuse_dir)\n", dir);
         fprintf(stderr, "(Maybe the directory already exists?)\n");       
         exit(1);
#endif
     }
#ifdef USE_MPI
   }
#endif
   mcdirname = dir;
#endif /* !MC_PORTABLE */
}

/* mcinfo: display instrument simulation info to stdout and exit */
static void
mcinfo(void)
{
  if(strstr(mcformat.Name,"NeXus"))
    exit(fprintf(stderr,"Error: Can not display instrument informtion in NeXus binary format\n"));
  mcsiminfo_init(stdout);
  mcsiminfo_close();
#ifdef USE_MPI
#undef exit
#endif
  exit(0);
#ifdef USE_MPI
#define exit(code) MPI_Abort(MPI_COMM_WORLD, code)
#endif
}

/* mcparseoptions: parse command line arguments (options, parameters) */
void
mcparseoptions(int argc, char *argv[])
{
  int i, j;
  char *p;
  int paramset = 0, *paramsetarray;

  /* Add one to mcnumipar to avoid allocating zero size memory block. */
  paramsetarray = malloc((mcnumipar + 1)*sizeof(*paramsetarray));
  if(paramsetarray == NULL)
  {
    fprintf(stderr, "Error: insufficient memory (mcparseoptions)\n");
    exit(1);
  }
  for(j = 0; j < mcnumipar; j++)
    {
      paramsetarray[j] = 0;
      if (mcinputtable[j].val != NULL && strlen(mcinputtable[j].val))
      {
        int  status;
        char buf[CHAR_BUF_LENGTH];
        strncpy(buf, mcinputtable[j].val, CHAR_BUF_LENGTH);
        status = (*mcinputtypes[mcinputtable[j].type].getparm)
                   (buf, mcinputtable[j].par);
        if(!status) fprintf(stderr, "Invalid '%s' default value %s in instrument definition (mcparseoptions)\n", mcinputtable[j].name, buf);
        else paramsetarray[j] = 1;
      } else {
        (*mcinputtypes[mcinputtable[j].type].getparm)
          (NULL, mcinputtable[j].par);
        paramsetarray[j] = 0;
      }
    }
  for(i = 1; i < argc; i++)
  {
    if(!strcmp("-s", argv[i]) && (i + 1) < argc)
      mcsetseed(argv[++i]);
    else if(!strncmp("-s", argv[i], 2))
      mcsetseed(&argv[i][2]);
    else if(!strcmp("--seed", argv[i]) && (i + 1) < argc)
      mcsetseed(argv[++i]);
    else if(!strncmp("--seed=", argv[i], 7))
      mcsetseed(&argv[i][7]);
    else if(!strcmp("-n", argv[i]) && (i + 1) < argc)
      mcsetn_arg(argv[++i]);
    else if(!strncmp("-n", argv[i], 2))
      mcsetn_arg(&argv[i][2]);
    else if(!strcmp("--ncount", argv[i]) && (i + 1) < argc)
      mcsetn_arg(argv[++i]);
    else if(!strncmp("--ncount=", argv[i], 9))
      mcsetn_arg(&argv[i][9]);
    else if(!strcmp("-d", argv[i]) && (i + 1) < argc)
      mcuse_dir(argv[++i]);
    else if(!strncmp("-d", argv[i], 2))
      mcuse_dir(&argv[i][2]);
    else if(!strcmp("--dir", argv[i]) && (i + 1) < argc)
      mcuse_dir(argv[++i]);
    else if(!strncmp("--dir=", argv[i], 6))
      mcuse_dir(&argv[i][6]);
    else if(!strcmp("-f", argv[i]) && (i + 1) < argc)
      mcuse_file(argv[++i]);
    else if(!strncmp("-f", argv[i], 2))
      mcuse_file(&argv[i][2]);
    else if(!strcmp("--file", argv[i]) && (i + 1) < argc)
      mcuse_file(argv[++i]);
    else if(!strncmp("--file=", argv[i], 7))
      mcuse_file(&argv[i][7]);
    else if(!strcmp("-h", argv[i]))
      mcshowhelp(argv[0]);
    else if(!strcmp("--help", argv[i]))
      mcshowhelp(argv[0]);
    else if(!strcmp("-i", argv[i])) {
      mcformat=mcuse_format(MCSTAS_FORMAT);
      mcinfo();
    }
    else if(!strcmp("--info", argv[i]))
      mcinfo();
    else if(!strcmp("-t", argv[i]))
      mcenabletrace();
    else if(!strcmp("--trace", argv[i]))
      mcenabletrace();
    else if(!strcmp("-a", argv[i]))
      mcascii_only = 1;
    else if(!strcmp("+a", argv[i]))
      mcascii_only = 0;
    else if(!strcmp("--data-only", argv[i]))
      mcascii_only = 1;
    else if(!strcmp("--gravitation", argv[i]))
      mcgravitation = 1;
    else if(!strcmp("-g", argv[i]))
      mcgravitation = 1;
    else if(!strncmp("--format=", argv[i], 9)) {
      mcascii_only = 0;
      mcformat=mcuse_format(&argv[i][9]);
    }
    else if(!strcmp("--format", argv[i]) && (i + 1) < argc) {
      mcascii_only = 0;
      mcformat=mcuse_format(argv[++i]);
    }
    else if(!strncmp("--format_data=", argv[i], 14) || !strncmp("--format-data=", argv[i], 14)) {
      mcascii_only = 0;
      mcformat_data=mcuse_format(&argv[i][14]);
    }
    else if((!strcmp("--format_data", argv[i]) || !strcmp("--format-data", argv[i])) && (i + 1) < argc) {
      mcascii_only = 0;
      mcformat_data=mcuse_format(argv[++i]);
    }
    else if(!strcmp("--no-output-files", argv[i]))
      mcdisable_output_files = 1;   
    else if(argv[i][0] != '-' && (p = strchr(argv[i], '=')) != NULL)
    {
      *p++ = '\0';

      for(j = 0; j < mcnumipar; j++)
        if(!strcmp(mcinputtable[j].name, argv[i]))
        {
          int status;
          status = (*mcinputtypes[mcinputtable[j].type].getparm)(p,
                        mcinputtable[j].par);
          if(!status || !strlen(p))
          {
            (*mcinputtypes[mcinputtable[j].type].error)
              (mcinputtable[j].name, p);
            exit(1);
          }
          paramsetarray[j] = 1;
          paramset = 1;
          break;
        }
      if(j == mcnumipar)
      {                                /* Unrecognized parameter name */
        fprintf(stderr, "Error: unrecognized parameter %s (mcparseoptions)\n", argv[i]);
        exit(1);
      }
    }
    else if(argv[i][0] == '-') {
      fprintf(stderr, "Error: unrecognized option argument %s (mcparseoptions). Ignored.\n", argv[i++]);
    }
    else
      mcusage(argv[0]);
  }
  if (!mcascii_only) {
    if (strstr(mcformat.Name,"binary")) fprintf(stderr, "Warning: %s files will contain text headers.\n         Use -a option to clean up.\n", mcformat.Name);
    strcat(mcformat.Name, " with text headers");
  }
  if(!paramset)
    mcreadparams();                /* Prompt for parameters if not specified. */
  else
  {
    for(j = 0; j < mcnumipar; j++)
      if(!paramsetarray[j])
      {
        fprintf(stderr, "Error: Instrument parameter %s left unset (mcparseoptions)\n",
                mcinputtable[j].name);
        exit(1);
      }
  }
  free(paramsetarray);
#ifdef USE_MPI
  if (mcdotrace) mpi_node_count=1; /* disable threading when in trace mode */
#endif
} /* mcparseoptions */

#ifndef NOSIGNALS
mcstatic char  mcsig_message[256];  /* ADD: E. Farhi, Sep 20th 2001 */


/* sighandler: signal handler that makes simulation stop, and save results */
void sighandler(int sig)
{
  /* MOD: E. Farhi, Sep 20th 2001: give more info */
  time_t t1, t0;
#define SIG_SAVE 0
#define SIG_TERM 1
#define SIG_STAT 2
#define SIG_ABRT 3

  printf("\n# McStas: [pid %i] Signal %i detected", getpid(), sig);
#if defined(SIGUSR1) && defined(SIGUSR2) && defined(SIGKILL)
  if (!strcmp(mcsig_message, "sighandler") && (sig != SIGUSR1) && (sig != SIGUSR2))
  {
    printf("\n# Fatal : unrecoverable loop ! Suicide (naughty boy).\n");
    kill(0, SIGKILL); /* kill myself if error occurs within sighandler: loops */
  }
#endif
  switch (sig) {
#ifdef SIGINT
    case SIGINT : printf(" SIGINT (interrupt from terminal, Ctrl-C)"); sig = SIG_TERM; break;
#endif
#ifdef SIGILL
    case SIGILL  : printf(" SIGILL (Illegal instruction)"); sig = SIG_ABRT; break;
#endif
#ifdef SIGFPE
    case SIGFPE  : printf(" SIGFPE (Math Error)"); sig = SIG_ABRT; break;
#endif
#ifdef SIGSEGV
    case SIGSEGV : printf(" SIGSEGV (Mem Error)"); sig = SIG_ABRT; break;
#endif
#ifdef SIGTERM
    case SIGTERM : printf(" SIGTERM (Termination)"); sig = SIG_TERM; break;
#endif
#ifdef SIGABRT
    case SIGABRT : printf(" SIGABRT (Abort)"); sig = SIG_ABRT; break;
#endif
#ifdef SIGQUIT
    case SIGQUIT : printf(" SIGQUIT (Quit from terminal)"); sig = SIG_TERM; break;
#endif
#ifdef SIGTRAP
    case SIGTRAP : printf(" SIGTRAP (Trace trap)"); sig = SIG_ABRT; break;
#endif
#ifdef SIGPIPE
    case SIGPIPE : printf(" SIGPIPE (Broken pipe)"); sig = SIG_ABRT; break;
#endif
#ifdef SIGUSR1
    case SIGUSR1 : printf(" SIGUSR1 (Display info)"); sig = SIG_STAT; break;
#endif
#ifdef SIGUSR2
    case SIGUSR2 : printf(" SIGUSR2 (Save simulation)"); sig = SIG_SAVE; break;
#endif
#ifdef SIGHUP
    case SIGHUP  : printf(" SIGHUP (Hangup/update)"); sig = SIG_SAVE; break;
#endif
#ifdef SIGBUS
    case SIGBUS  : printf(" SIGBUS (Bus error)"); sig = SIG_ABRT; break;
#endif
#ifdef SIGURG
    case SIGURG  : printf(" SIGURG (Urgent socket condition)"); sig = SIG_ABRT; break;
#endif
#ifdef SIGBREAK
    case SIGBREAK: printf(" SIGBREAK (Break signal, Ctrl-Break)"); sig = SIG_SAVE; break;
#endif
    default : printf(" (look at signal list for signification)"); sig = SIG_ABRT; break;
  }
  printf("\n");
  printf("# Simulation: %s (%s) \n", mcinstrument_name, mcinstrument_source);
  printf("# Breakpoint: %s ", mcsig_message);
  if (strstr(mcsig_message, "Save") && (sig == SIG_SAVE))
    sig = SIG_STAT;
  SIG_MESSAGE("sighandler");
  if (mcget_ncount() == 0)
    printf("(0 %%)\n" );
  else
  {
    printf("%.2f %% (%10.1f/%10.1f)\n", 100.0*mcget_run_num()/mcget_ncount(), 1.0*mcget_run_num(), 1.0*mcget_ncount());
  }
  t0 = (time_t)mcstartdate;
  t1 = time(NULL);
  printf("# Date:      %s", ctime(&t1));
  printf("# Started:   %s", ctime(&t0));

  if (sig == SIG_STAT)
  {
    printf("# McStas: Resuming simulation (continue)\n");
    fflush(stdout);
    return;
  }
  else
  if (sig == SIG_SAVE)
  {
    printf("# McStas: Saving data and resume simulation (continue)\n");
    mcsave(NULL);
    fflush(stdout);
    return;
  }
  else
  if (sig == SIG_TERM)
  {
    printf("# McStas: Finishing simulation (save results and exit)\n");
    mcfinally();
    exit(0);
  }
  else
  {
    fflush(stdout);
    perror("# Last I/O Error");
    printf("# McStas: Simulation stop (abort)\n");
    exit(-1);
  }
#undef SIG_SAVE
#undef SIG_TERM
#undef SIG_STAT
#undef SIG_ABRT

}
#endif /* !NOSIGNALS */

/* main raytrace loop */
void *mcstas_raytrace(void *p_node_ncount)
{
  double node_ncount = *((double*)p_node_ncount);
  
  while(mcrun_num < node_ncount || mcrun_num < mcget_ncount())
  {
    mcsetstate(0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
    /* old init: mcsetstate(0, 0, 0, 0, 0, 1, 0, sx=0, sy=1, sz=0, 1); */
    mcraytrace();
    mcrun_num++;
  }
  return (NULL);
}

/* mcstas_main: McStas main() function. */
int mcstas_main(int argc, char *argv[])
{
/*  double run_num = 0; */
  time_t t;
#ifdef USE_MPI
  char mpi_node_name[MPI_MAX_PROCESSOR_NAME];
  int  mpi_node_name_len;
#endif /* USE_MPI */
#if defined (USE_MPI)
  double mpi_mcncount;
#endif /* USE_MPI */

#ifdef MAC
  argc = ccommand(&argv);
#endif

#ifdef USE_MPI
  MPI_Init(&argc,&argv);
  MPI_Comm_size(MPI_COMM_WORLD, &mpi_node_count); /* get number of nodes */
  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_node_rank);
  MPI_Get_processor_name(mpi_node_name, &mpi_node_name_len);
#endif /* USE_MPI */

/* *** print number of nodes *********************************************** */
  t = (time_t)mcstartdate;
#ifdef USE_MPI
  if (mpi_node_count > 1) {
    MPI_MASTER(
    printf("Simulation %s (%s) running on %i nodes (master is %s, MPI version %i.%i).\n", 
      mcinstrument_name, mcinstrument_source, mpi_node_count, mpi_node_name, MPI_VERSION, MPI_SUBVERSION);
    );
    /* adapt random seed for each node */
    mcseed=(long)(time(&t) + mpi_node_rank); 
    srandom(mcseed); 
    t += mpi_node_rank;
  }
#else /* !USE_MPI */
  mcseed=(long)time(&t);
  srandom(mcseed); 
#endif /* !USE_MPI */
  mcstartdate = t;  /* set start date before parsing options and creating sim file */

/* *** parse options ******************************************************* */
  SIG_MESSAGE("main (Start)");
  mcformat=mcuse_format(getenv("MCSTAS_FORMAT") ? getenv("MCSTAS_FORMAT") : MCSTAS_FORMAT);
  /* default is to output as McStas format */
  mcformat_data.Name=NULL;
  /* read simulation parameters and options */
  mcparseoptions(argc, argv); /* sets output dir and format */
  if (strstr(mcformat.Name, "NeXus")) {
    if (mcformat_data.Name) mcclear_format(mcformat_data);
    mcformat_data.Name=NULL;
  }
  if (!mcformat_data.Name && strstr(mcformat.Name, "HTML"))
    mcformat_data = mcuse_format("VRML");

/* *** install sig handler, but only once !! after parameters parsing ******* */
#ifndef NOSIGNALS
#ifdef SIGQUIT
  signal( SIGQUIT ,sighandler);   /* quit (ASCII FS) */
#endif
#ifdef SIGABRT
  signal( SIGABRT ,sighandler);   /* used by abort, replace SIGIOT in the future */
#endif
#ifdef SIGTERM
  signal( SIGTERM ,sighandler);   /* software termination signal from kill */
#endif
#ifdef SIGUSR1
  signal( SIGUSR1 ,sighandler);   /* display simulation status */
#endif
#ifdef SIGUSR2
  signal( SIGUSR2 ,sighandler);
#endif
#ifdef SIGHUP
  signal( SIGHUP ,sighandler);
#endif
#ifdef SIGILL
  signal( SIGILL ,sighandler);    /* illegal instruction (not reset when caught) */
#endif
#ifdef SIGFPE
  signal( SIGFPE ,sighandler);    /* floating point exception */
#endif
#ifdef SIGBUS
  signal( SIGBUS ,sighandler);    /* bus error */
#endif
#ifdef SIGSEGV
  signal( SIGSEGV ,sighandler);   /* segmentation violation */
#endif
#endif /* !NOSIGNALS */
  if (!strstr(mcformat.Name,"NeXus")) {
    mcsiminfo_init(NULL); mcsiminfo_close();  /* makes sure we can do that */
  }
  SIG_MESSAGE("main (Init)");
  mcinit();
#ifndef NOSIGNALS
#ifdef SIGINT
  signal( SIGINT ,sighandler);    /* interrupt (rubout) only after INIT */
#endif
#endif /* !NOSIGNALS */

/* ================ main neutron generation/propagation loop ================ */
#if defined (USE_MPI)
  mpi_mcncount = mpi_node_count > 1 ?
    floor(mcncount / mpi_node_count) :
    mcncount; /* number of neutrons per node */
  mcncount = mpi_mcncount;  /* sliced Ncount on each MPI node */
#endif

/* main neutron event loop */
mcstas_raytrace(&mcncount);

#ifdef USE_MPI
 /* merge data from MPI nodes */
  if (mpi_node_count > 1) {
  MPI_Barrier(MPI_COMM_WORLD);
  mc_MPI_Reduce(&mcrun_num, &mcrun_num, 1, MPI_DOUBLE, MPI_SUM, mpi_node_root, MPI_COMM_WORLD);
  }
#endif

/* save/finally executed by master node/thread */
  mcfinally();
  mcclear_format(mcformat);
  if (mcformat_data.Name) mcclear_format(mcformat_data);

#ifdef USE_MPI
  MPI_Finalize();
#endif /* USE_MPI */

  return 0;
} /* mcstas_main */

#endif /* !MCSTAS_H */
/* End of file "mcstas-r.c". */

#line 6961 "TOFexercise42.c"
#ifdef MC_TRACE_ENABLED
int mctraceenabled = 1;
#else
int mctraceenabled = 0;
#endif
#define MCSTAS "/usr/local/lib/mcstas/"
int mcdefaultmain = 1;
char mcinstrument_name[] = "TOFexercise42";
char mcinstrument_source[] = "TOFexercise42.instr";
int main(int argc, char *argv[]){return mcstas_main(argc, argv);}
void mcinit(void);
void mcraytrace(void);
void mcsave(FILE *);
void mcfinally(void);
void mcdisplay(void);

/* Shared user declarations for all components 'Guide'. */
#line 67 "/usr/local/lib/mcstas/optics/Guide.comp"
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2011, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Library: share/read_table-lib.h
*
* %Identification
* Written by: EF
* Date: Aug 28, 2002
* Origin: ILL
* Release: McStas 1.12c
* Version: $Revision: 1.21 $
*
* This file is to be imported by components that may read data from table files
* It handles some shared functions.
*
* This library may be used directly as an external library. It has no dependency
*
* Usage: within SHARE
* %include "read_table-lib"
*
*
* $Id: read_table-lib.h,v 1.21 2006-11-27 15:29:39 farhi Exp $
*
* $Log: read_table-lib.h,v $
* Revision 1.21  2006-11-27 15:29:39  farhi
* Small improvement in interpolation methods of read-table lib.
*
* Revision 1.20  2006/03/15 16:04:14  farhi
* interpolation decl.
*
* Revision 1.19  2005/10/14 11:38:28  farhi
* Corrected missing #define
*
* Revision 1.18  2005/10/12 14:04:29  farhi
* Added function to parse header, Table_ParseHeader(header, "symbol1", ... , NULL)
* Useful for complex sample components, as well as mcformat/mcconvert stuff.
*
* Revision 1.17  2005/09/30 14:53:04  farhi
* REdiced length of title line in subplot's
*
* Revision 1.16  2005/07/25 14:55:08  farhi
* DOC update:
* checked all parameter [unit] + text to be OK
* set all versions to CVS Revision
*
* Revision 1.15  2005/07/20 13:08:43  farhi
* Changed Table_Init calling sequence (overrides Table_Alloc)
*
* Revision 1.14  2005/07/12 14:46:34  farhi
* Added Table_Alloc to create a user empty Table
* and Table_SetElement
*
* Revision 1.13  2005/07/05 14:25:59  farhi
* Added filesize in t_Table struct
*
* Revision 1.12  2005/07/05 12:06:40  farhi
* added new functions for table Array handling
* to be used in Isotropic_sqw and mcformat
*
* Revision 1.10  2005/01/20 14:16:43  farhi
* New functions to read separately all numerical bmocks in a text data file
* Will be used for Data conversion from PGPLOT/McStas (mcformat tool)
*
* Revision 1.9  2004/09/10 15:12:02  farhi
* Make these libs easier to externalize (lower dependencies) and add comment about how to make these independent for external linkage.
*
* Revision 1.8  2003/02/11 12:28:46  farhi
* Variouxs bug fixes after tests in the lib directory
* mcstas_r  : disable output with --no-out.. flag. Fix 1D McStas output
* read_table:corrected MC_SYS_DIR -> MCSTAS define
* monitor_nd-lib: fix Log(signal) log(coord)
* HOPG.trm: reduce 4000 points -> 400 which is enough and faster to resample
* Progress_bar: precent -> percent parameter
* CS: ----------------------------------------------------------------------
*
* Revision 1.1 2002/08/29 11:39:00 ef
* Initial revision extracted from lib/optics/Monochromators...
*******************************************************************************/

#ifndef READ_TABLE_LIB_H
#define READ_TABLE_LIB_H "$Revision: 1.21 $"

#define READ_TABLE_STEPTOL  0.02 /* tolerancy for constant step approx */

#ifndef MC_PATHSEP_C
#ifdef WIN32
#define MC_PATHSEP_C '\\'
#define MC_PATHSEP_S "\\"
#else  /* !WIN32 */
#ifdef MAC
#define MC_PATHSEP_C ':'
#define MC_PATHSEP_S ":"
#else  /* !MAC */
#define MC_PATHSEP_C '/'
#define MC_PATHSEP_S "/"
#endif /* !MAC */
#endif /* !WIN32 */
#endif /* !MC_PATHSEP_C */

#ifndef MCSTAS
#ifdef WIN32
#define MCSTAS "C:\\mcstas\\lib"
#else  /* !WIN32 */
#ifdef MAC
#define MCSTAS ":mcstas:lib" /* ToDo: What to put here? */
#else  /* !MAC */
#define MCSTAS "/usr/local/lib/mcstas"
#endif /* !MAC */
#endif /* !WIN32 */
#endif /* !MCSTAS */

#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>

  typedef struct struct_table
  {
    char    filename[256];
    long    filesize;
    char   *header;  /* text header, e.g. comments */
    double *data;    /* vector { x[0], y[0], ... x[n-1], y[n-1]... } */
    double  min_x;   /* min value of first column */
    double  max_x;   /* max value of first column */
    double  step_x;  /* minimal step value of first column */
    long    rows;    /* number of rows in matrix block */
    long    columns; /* number of columns in matrix block */

    long    begin;   /* start fseek index of block */
    long    end;     /* stop  fseek index of block */
    long    block_number;  /* block index. 0 is catenation of all */
    long    array_length;  /* number of elements in the t_Table array */
    char    monotonic;     /* true when 1st column/vector data is monotonic */
    char    constantstep;  /* true when 1st column/vector data has constant step */
    char    method[32];    /* interpolation method: nearest, linear */
  } t_Table;

/* read_table-lib function prototypes */
/* ========================================================================= */

/* 'public' functions */
long     Table_Read              (t_Table *Table, char *File, long block_number);
long     Table_Read_Offset       (t_Table *Table, char *File, long block_number,
                                  long *offset, long max_lines);
long     Table_Read_Offset_Binary(t_Table *Table, char *File, char *Type,
                                  long *Offset, long Rows, long Columns);
long     Table_Rebin(t_Table *Table);
long     Table_Info (t_Table Table);
double   Table_Index(t_Table Table,   long i, long j);
double   Table_Value(t_Table Table, double X, long j);
t_Table *Table_Read_Array(char *File, long *blocks);
void     Table_Free_Array(t_Table *Table);
long     Table_Info_Array(t_Table *Table);
int      Table_SetElement(t_Table *Table, long i, long j, double value);
long     Table_Init(t_Table *Table, long rows, long columns);

char **Table_ParseHeader(char *header, ...);

/* private functions */

void Table_Free(t_Table *Table);
long Table_Read_Handle(t_Table *Table, FILE *fid, long block_number, long max_lines);
static void Table_Stat(t_Table *Table);
double Table_Interp1d(double x, double x1, double y1, double x2, double y2);
double Table_Interp1d_nearest(double x, double x1, double y1, double x2, double y2);
double Table_Interp2d(double x, double y, double x1, double y1, double x2, double y2,
  double z11, double z12, double z21, double z22);

#endif

/* end of read_table-lib.h */
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2011, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Library: share/read_table-lib.c
*
* %Identification
* Written by: EF
* Date: Aug 28, 2002
* Origin: ILL
* Release: McStas 1.12c
* Version: $Revision: 1.38 $
*
* This file is to be imported by components that may read data from table files
* It handles some shared functions. Embedded within instrument in runtime mode.
* Variable names have prefix 'mc_rt_' for 'McStas Read Table' to avoid conflicts
*
* Usage: within SHARE
* %include "read_table-lib"
*
* $Id: read_table-lib.c,v 1.38 2008-07-03 09:40:01 farhi Exp $
*
* $Log: read_table-lib.c,v $
* Revision 1.38  2008-07-03 09:40:01  farhi
* Handle "NULL" and "0" file names
*
* Revision 1.37  2006/12/01 16:17:10  farhi
* cosmetics
*
* Revision 1.36  2006/11/29 14:07:09  farhi
* cosmetics
*
* Revision 1.35  2006/11/27 15:29:39  farhi
* Small improvement in interpolation methods of read-table lib.
*
* Revision 1.34  2006/10/03 22:16:45  farhi
* Added realistic PSD_Detector component with Gas tables
* Added test for Isotropic_Sqw
* Data files can be in local path, MCSTAS/data and contrib sub-dirs
*
* Revision 1.33  2006/07/21 09:05:05  farhi
* fixed bug in 2D interpolation routine
*
* Revision 1.32  2006/03/15 16:03:27  farhi
* interpolation functions now in the table handling by default.
* corrected nelements in array length return value of Table_Read_Array
*
* Revision 1.31  2006/02/14 15:29:40  farhi
* Fixed error when importing block number > 1
*
* Revision 1.30  2006/01/30 12:55:10  farhi
* incomplete table warning displays file name
*
* Revision 1.29  2005/10/14 11:38:28  farhi
* Corrected missing #define
*
* Revision 1.28  2005/10/12 14:04:29  farhi
* Added function to parse header, Table_ParseHeader(header, "symbol1", ... , NULL)
* Useful for complex sample components, as well as mcformat/mcconvert stuff.
*
* Revision 1.27  2005/10/05 08:50:53  farhi
* Extended buffer for Table line read (fgetl) to 64 ko instead of 4 ko.
* It failed with large matrices (e.g. more than 100 columns)
*
* Revision 1.26  2005/09/16 14:19:03  farhi
* Correct bug #56: SEGV when opening a non existent file with read-table. Was reported on usage of PowderN
*
* Revision 1.25  2005/08/31 14:50:29  farhi
* Fixed bugs when handling vectors with swapped (i,j) indexes
*
* Revision 1.24  2005/07/25 14:55:08  farhi
* DOC update:
* checked all parameter [unit] + text to be OK
* set all versions to CVS Revision
*
* Revision 1.23  2005/07/20 13:08:43  farhi
* Changed Table_Init calling sequence (overrides Table_Alloc)
*
* Revision 1.22  2005/07/12 14:46:26  farhi
* Added Table_Alloc to create a user empty Table
* and Table_SetElement
*
* Revision 1.21  2005/07/08 13:15:43  farhi
* Mismatch in argument swap
*
* Revision 1.20  2005/07/07 14:16:57  farhi
* Min and Max are computed for both row and column vectors
*
* Revision 1.19  2005/07/06 09:50:45  farhi
* Added check for non existing data file in Table_*_Array functions
*
* Revision 1.18  2005/07/06 08:44:28  farhi
* Display headers in Table_Info
* Also works with Arrays
*
* Revision 1.17  2005/07/05 14:30:27  farhi
* misprint
*
* Revision 1.16  2005/07/05 14:25:42  farhi
* added file size in t_Table structure
*
* Revision 1.15  2005/07/05 12:06:40  farhi
* added new functions for table Array handling
* to be used in Isotropic_sqw and mcformat
*
* Revision 1.13  2005/01/20 14:16:43  farhi
* New functions to read separately all numerical bmocks in a text data file
* Will be used for Data conversion from PGPLOT/McStas (mcformat tool)
*
* Revision 1.12  2004/09/10 15:12:02  farhi
* Make these libs easier to externalize (lower dependencies) and add comment about how to make these independent for external linkage.
*
* Revision 1.11  2004/09/09 13:48:02  farhi
* Code clean-up
*
* Revision 1.10  2004/09/03 13:46:50  farhi
* Correct misprint in comment
*
* Revision 1.9  2003/05/20 15:12:33  farhi
* malloc size for read table binary now needs less memory
*
* Revision 1.8  2003/02/11 12:28:46  farhi
* Variouxs bug fixes after tests in the lib directory
* mcstas_r  : disable output with --no-out.. flag. Fix 1D McStas output
* read_table:corrected MC_SYS_DIR -> MCSTAS define
* monitor_nd-lib: fix Log(signal) log(coord)
* HOPG.trm: reduce 4000 points -> 400 which is enough and faster to resample
* Progress_bar: precent -> percent parameter
* CS: ----------------------------------------------------------------------
*
* Revision 1.8  2003/02/06 14:14:41  farhi
* Corrected MC_SYS_DIR into MCSTAS definition of default lib location
*
* Revision 1.2 2002/12/19 12:48:07 ef
* Added binary import. Fixed Rebin. Added Stat.
*
* Revision 1.1 2002/08/29 11:39:00 ef
* Initial revision extracted from lib/optics/Monochromators...
*******************************************************************************/

#ifndef READ_TABLE_LIB_H
#include "read_table-lib.h"
#endif

/*******************************************************************************
* long Read_Table(t_Table *Table, char *name, int block_number)
*   ACTION: read a single Table from a text file
*   input   Table: pointer to a t_Table structure
*           name:  file name from which table should be extracted
*           block_number: if the file does contain more than one
*                 data block, then indicates which one to get (from index 1)
*                 a 0 value means append/catenate all
*   return  initialized single Table t_Table structure containing data, header, ...
*           number of read elements (-1: error, 0:header only)
* The routine stores any line starting with '#', '%' and ';' into the header
* File is opened, read and closed
* Other lines are interpreted as numerical data, and stored.
* Data block should be a rectangular matrix or vector.
* Data block may be rebined with Table_Rebin (also sort in ascending order)
*******************************************************************************/
  long Table_Read(t_Table *mc_rt_Table, char *mc_rt_File, long mc_rt_block_number)
  { /* reads all or a single data block from 'file' and returns a Table structure  */
    return(Table_Read_Offset(mc_rt_Table, mc_rt_File, mc_rt_block_number, NULL, 0));
  } /* end Table_Read */

/*******************************************************************************
* long Table_Read_Offset(t_Table *Table, char *name, int block_number, long *offset
*                        long max_lines)
*   ACTION: read a single Table from a text file, starting at offset
*     Same as Table_Read(..) except:
*   input   offset:    pointer to an offset (*offset should be 0 at start)
*           max_lines: max number of data rows to read from file (0 means all)
*   return  initialized single Table t_Table structure containing data, header, ...
*           number of read elements (-1: error, 0:header only)
*           updated *offset position (where end of reading occured)
*******************************************************************************/
  long Table_Read_Offset(t_Table *mc_rt_Table, char *mc_rt_File,
                         long mc_rt_block_number, long *mc_rt_offset,
                         long mc_rt_max_lines)
  { /* reads all/a data block in 'file' and returns a Table structure  */
    FILE *mc_rt_hfile;
    long  mc_rt_nelements;
    long  mc_rt_begin;
    long  mc_rt_filesize=0;
    struct stat mc_rt_stfile;

    if (!mc_rt_Table) return(-1);
    Table_Init(mc_rt_Table, 0, 0);
    if (!mc_rt_File)  return(-1);
    if (strlen(mc_rt_File) == 0) return (-1);
    if (!strcmp(mc_rt_File,"NULL") || !strcmp(mc_rt_File,"0"))  return(-1);
    mc_rt_hfile = fopen(mc_rt_File, "r");
    if(!mc_rt_hfile)
    {
      char mc_rt_path[256];
      char mc_rt_dir[256];

      if (!mc_rt_hfile)
      {
        strcpy(mc_rt_dir, getenv("MCSTAS") ? getenv("MCSTAS") : MCSTAS);
        sprintf(mc_rt_path, "%s%c%s%c%s", mc_rt_dir, MC_PATHSEP_C, "data", MC_PATHSEP_C, mc_rt_File);
        mc_rt_hfile = fopen(mc_rt_path, "r");
      }
      if (!mc_rt_hfile)
      {
        strcpy(mc_rt_dir, getenv("MCSTAS") ? getenv("MCSTAS") : MCSTAS);
        sprintf(mc_rt_path, "%s%c%s%c%s", mc_rt_dir, MC_PATHSEP_C, "contrib", MC_PATHSEP_C, mc_rt_File);
        mc_rt_hfile = fopen(mc_rt_path, "r");
      }
      if(!mc_rt_hfile)
      {
        fprintf(stderr, "Error: Could not open input file '%s' (Table_Read)\n", mc_rt_File);
        return (-1);
      }
    }
    stat(mc_rt_File,&mc_rt_stfile); mc_rt_filesize = mc_rt_stfile.st_size;
    if (mc_rt_offset && *mc_rt_offset) fseek(mc_rt_hfile, *mc_rt_offset, SEEK_SET);
    mc_rt_begin     = ftell(mc_rt_hfile);
    mc_rt_nelements = Table_Read_Handle(mc_rt_Table, mc_rt_hfile, mc_rt_block_number, mc_rt_max_lines);
    strncpy(mc_rt_Table->filename, mc_rt_File, 128);
    mc_rt_Table->begin = mc_rt_begin;
    mc_rt_Table->end   = ftell(mc_rt_hfile);
    mc_rt_Table->filesize = (mc_rt_filesize>0 ? mc_rt_filesize : 0);
    if (mc_rt_offset) *mc_rt_offset=mc_rt_Table->end;
    fclose(mc_rt_hfile);
    return(mc_rt_nelements);

  } /* end Table_Read_Offset */

/*******************************************************************************
* long Table_Read_Offset_Binary(t_Table *Table, char *File, char *type,
*                               long *offset, long rows, long columns)
*   ACTION: read a single Table from a binary file, starting at offset
*     Same as Table_Read_Offset(..) except that it handles binary files.
*   input   type: may be "float"/NULL or "double"
*           offset: pointer to an mc_rt_offset (*offset should be 0 at start)
*           rows   : number of rows (0 means read all)
*           columns: number of columns
*   return  initialized single Table t_Table structure containing data, header, ...
*           number of read elements (-1: error, 0:header only)
*           updated *offset position (where end of reading occured)
*******************************************************************************/
  long Table_Read_Offset_Binary(t_Table *mc_rt_Table, char *mc_rt_File, char *mc_rt_type,
                                long *mc_rt_offset, long mc_rt_rows, long mc_rt_columns)
  { /* reads all/a data block in binary 'file' and returns a Table structure  */
    long    mc_rt_nelements, mc_rt_sizeofelement;
    long    mc_rt_filesize;
    FILE   *mc_rt_hfile;
    struct stat mc_rt_stfile;
    double *mc_rt_data;
    long    mc_rt_i;
    long    mc_rt_begin;

    if (!mc_rt_Table) return(-1);

    Table_Init(mc_rt_Table, 0, 0);
    if (!mc_rt_File)  return(-1);
    if (strlen(mc_rt_File) == 0) return (-1);
    if (!strcmp(mc_rt_File,"NULL") || !strcmp(mc_rt_File,"0"))  return(-1);

    mc_rt_hfile = fopen(mc_rt_File, "r");
    if(!mc_rt_hfile)
    {
      char mc_rt_path[256];
      char mc_rt_dir[256];

      if (!mc_rt_hfile)
      {
        strcpy(mc_rt_dir, getenv("MCSTAS") ? getenv("MCSTAS") : MCSTAS);
        sprintf(mc_rt_path, "%s%c%s%c%s", mc_rt_dir, MC_PATHSEP_C, "data", MC_PATHSEP_C, mc_rt_File);
        mc_rt_hfile = fopen(mc_rt_path, "r");
      }
      if (!mc_rt_hfile)
      {
        strcpy(mc_rt_dir, getenv("MCSTAS") ? getenv("MCSTAS") : MCSTAS);
        sprintf(mc_rt_path, "%s%c%s%c%s", mc_rt_dir, MC_PATHSEP_C, "contrib", MC_PATHSEP_C, mc_rt_File);
        mc_rt_hfile = fopen(mc_rt_path, "r");
      }
      if(!mc_rt_hfile)
      {
        fprintf(stderr, "Error: Could not open input file '%s' (Table_Read_Offset_Binary)\n", mc_rt_File);
        return (-1);
      }
    }
    stat(mc_rt_File,&mc_rt_stfile);
    mc_rt_filesize = mc_rt_stfile.st_size;
    mc_rt_Table->filesize=mc_rt_filesize;
    if (mc_rt_type && !strcmp(mc_rt_type,"double")) mc_rt_sizeofelement = sizeof(double);
    else  mc_rt_sizeofelement = sizeof(float);
    if (mc_rt_offset && *mc_rt_offset) fseek(mc_rt_hfile, *mc_rt_offset, SEEK_SET);
    mc_rt_begin     = ftell(mc_rt_hfile);
    if (mc_rt_rows && mc_rt_filesize > mc_rt_sizeofelement*mc_rt_columns*mc_rt_rows)
      mc_rt_nelements = mc_rt_columns*mc_rt_rows;
    else mc_rt_nelements = (long)(mc_rt_filesize/mc_rt_sizeofelement);
    if (!mc_rt_nelements || mc_rt_filesize <= *mc_rt_offset) return(0);
    mc_rt_data    = (double*)malloc(mc_rt_nelements*mc_rt_sizeofelement);
    if (!mc_rt_data) {
      fprintf(stderr,"Error: allocating %ld elements for %s file '%s'. Too big (Table_Read_Offset_Binary).\n", mc_rt_nelements, mc_rt_type, mc_rt_File);
      exit(-1);
    }
    mc_rt_nelements = fread(mc_rt_data, mc_rt_sizeofelement, mc_rt_nelements, mc_rt_hfile);

    if (!mc_rt_data || !mc_rt_nelements)
    {
      fprintf(stderr,"Error: reading %ld elements from %s file '%s' (Table_Read_Offset_Binary)\n", mc_rt_nelements, mc_rt_type, mc_rt_File);
      exit(-1);
    }
    mc_rt_Table->begin   = mc_rt_begin;
    mc_rt_Table->end     = ftell(mc_rt_hfile);
    if (mc_rt_offset) *mc_rt_offset=mc_rt_Table->end;
    fclose(mc_rt_hfile);
    mc_rt_data = (double*)realloc(mc_rt_data, (double)mc_rt_nelements*mc_rt_sizeofelement);
    /* copy file data into Table */
    if (mc_rt_type && !strcmp(mc_rt_type,"double")) mc_rt_Table->data = mc_rt_data;
    else {
      float  *mc_rt_s;
      double *mc_rt_dataf;
      mc_rt_s     = (float*)mc_rt_data;
      mc_rt_dataf = (double*)malloc(sizeof(double)*mc_rt_nelements);
      for (mc_rt_i=0; mc_rt_i<mc_rt_nelements; mc_rt_i++)
        mc_rt_dataf[mc_rt_i]=mc_rt_s[mc_rt_i];
      free(mc_rt_data);
      mc_rt_Table->data = mc_rt_dataf;
    }
    strcpy(mc_rt_Table->filename, mc_rt_File);
    mc_rt_Table->rows    = mc_rt_nelements/mc_rt_columns;
    mc_rt_Table->columns = mc_rt_columns;
    mc_rt_Table->array_length = 1;
    mc_rt_Table->block_number = 1;

    Table_Stat(mc_rt_Table);

    return(mc_rt_nelements);
  } /* end Table_Read_Offset_Binary */

/*******************************************************************************
* long Read_Table_Handle(t_Table *Table, FILE *fid, int block_number, long max_lines)
*   ACTION: read a single Table from a text file handle (private)
*   input   Table:pointer to a t_Table structure
*           fid:  pointer to FILE handle
*           block_number: if the file does contain more than one
*                 data block, then indicates which one to get (from index 1)
*                 a 0 value means append/catenate all
*           max_lines: if non 0, only reads that number of lines
*   return  initialized single Table t_Table structure containing data, header, ...
*           modified Table t_Table structure containing data, header, ...
*           number of read elements (-1: error, 0:header only)
* The routine stores any line starting with '#', '%' and ';' into the header
* Other lines are interpreted as numerical data, and stored.
* Data block should be a rectangular matrix or vector.
* Data block may be rebined with Table_Rebin (also sort in ascending order)
*******************************************************************************/
  long Table_Read_Handle(t_Table *mc_rt_Table, FILE *mc_rt_hfile,
                         long mc_rt_block_number, long mc_rt_max_lines)
  { /* reads all/a data block from 'file' handle and returns a Table structure  */
    double *mc_rt_Data;
    char *mc_rt_Header;
    long  mc_rt_malloc_size         = 1024;
    long  mc_rt_malloc_size_h       = 4096;
    long  mc_rt_Rows = 0,   mc_rt_Columns = 0;
    long  mc_rt_count_in_array      = 0;
    long  mc_rt_count_in_header     = 0;
    long  mc_rt_block_Current_index = 0;
    char  mc_rt_flag_In_array       = 0;
    char  mc_rt_flag_End_row_loop   = 0;

    if (!mc_rt_Table) return(-1);
    Table_Init(mc_rt_Table, 0, 0);

    if(!mc_rt_hfile) {
       fprintf(stderr, "Error: File handle is NULL (Table_Read_Handle).\n");
       return (-1);
    }
    mc_rt_Header = (char*)  malloc(mc_rt_malloc_size_h*sizeof(char));
    mc_rt_Data   = (double*)malloc(mc_rt_malloc_size  *sizeof(double));
    if ((mc_rt_Header == NULL) || (mc_rt_Data == NULL)) {
       fprintf(stderr, "Error: Could not allocate Table and Header (Table_Read_Handle).\n");
       return (-1);
    }
    mc_rt_Header[0] = '\0';

    do { /* while (!mc_rt_flag_End_row_loop) */
      char  mc_rt_line[1024*1024];
      long  mc_rt_back_pos=0;   /* ftell start of line */

      mc_rt_back_pos = ftell(mc_rt_hfile);
      if (fgets(mc_rt_line, 1024*1024, mc_rt_hfile) != NULL) { /* analyse line */
        int mc_rt_i=0;
        char  mc_rt_flag_Store_into_header=0;
        /* first skip blank and tabulation characters */
        while (mc_rt_line[mc_rt_i] == ' ' || mc_rt_line[mc_rt_i] == '\t') mc_rt_i++;
        /* handle comments: stored in header */
        if ((mc_rt_line[mc_rt_i] == '#') || (mc_rt_line[mc_rt_i] == '%')
        || (mc_rt_line[mc_rt_i] == ';') || (mc_rt_line[mc_rt_i] == '/'))
        { /* line is a comment */
          mc_rt_flag_Store_into_header=1;
          mc_rt_flag_In_array = 0;
        } else {
          double mc_rt_X;

          /* get the number of columns splitting line with strtok */
          if (sscanf(mc_rt_line,"%lg ",&mc_rt_X) == 1)
          { /* line begins at least with one num */
            char  *mc_rt_InputTokens, *mc_rt_lexeme;
            char   mc_rt_flag_End_Line= 0;
            long   mc_rt_block_Num_Columns     = 0;

            mc_rt_InputTokens            = mc_rt_line;

            do { /* while (!mc_rt_flag_End_Line) */
              mc_rt_lexeme      = (char *)strtok(mc_rt_InputTokens, " ,;\t\n\r");
              mc_rt_InputTokens = NULL;
              if ((mc_rt_lexeme != NULL) && (strlen(mc_rt_lexeme) != 0))
              { /* reading line: the token is not empty */
                if (sscanf(mc_rt_lexeme,"%lg ",&mc_rt_X) == 1)
                { /* reading line: the token is a number in the line */
                  if (!mc_rt_flag_In_array)
                  { /* reading num: not already in a block: starts a new data block */
                    mc_rt_block_Current_index++;
                    mc_rt_flag_In_array    = 1;
                    mc_rt_block_Num_Columns= 0;
                    if (mc_rt_block_number)
                    { /* initialise a new data block */
                      mc_rt_Rows = 0;
                      mc_rt_count_in_array = 0;
                    } /* else append */
                  }
                  /* reading num: all blocks or selected block */
                  if ( mc_rt_flag_In_array &&  ((mc_rt_block_number == 0) || (mc_rt_block_number == mc_rt_block_Current_index)) )
                  {
                    /* starting block: already the desired number of rows ? */
                    if (mc_rt_block_Num_Columns == 0
                      && mc_rt_max_lines && mc_rt_Rows >= mc_rt_max_lines) {
                      mc_rt_flag_End_Line      = 1;
                      mc_rt_flag_End_row_loop  = 1;
                      mc_rt_flag_In_array      = 0;
                      /* reposition to begining of line (ignore line) */
                      fseek(mc_rt_hfile, mc_rt_back_pos, SEEK_SET);
                    } else { /* store into data array */
                      if (mc_rt_count_in_array >= mc_rt_malloc_size)
                      { /* realloc data buffer if necessary */
                        mc_rt_malloc_size = mc_rt_count_in_array+1024;
                        mc_rt_Data     = (double*)realloc(mc_rt_Data, mc_rt_malloc_size*sizeof(double));
                        if (mc_rt_Data == NULL)
                        {
                          fprintf(stderr, "Error: Can not re-allocate memory %li (Table_Read_Handle).\n", mc_rt_malloc_size*sizeof(double));
                          return (-1);
                        }
                      }
                      if (mc_rt_block_Num_Columns == 0) mc_rt_Rows++;
                      mc_rt_Data[mc_rt_count_in_array] = mc_rt_X;
                      mc_rt_count_in_array++;
                      mc_rt_block_Num_Columns++;
                    }
                  } /* reading num: end if mc_rt_flag_In_array */
                  else
                  { /* reading num: passed selected block */
                    if (mc_rt_block_number < mc_rt_block_Current_index)
                    { /* we finished to extract block -> force end of file reading */
                      mc_rt_flag_End_Line      = 1;
                      mc_rt_flag_End_row_loop  = 1;
                      mc_rt_flag_In_array  = 0;
                    }
                    /* else (if read all blocks) continue */
                  }
                } /* end reading num: end if sscanf mc_rt_lexeme -> numerical */
                else
                { /* reading line: the token is not numerical in that line. end block */
                  mc_rt_flag_End_Line = 1;
                  mc_rt_flag_In_array = 0;
                }
              }
              else
              { /* no more tokens in mc_rt_line */
                mc_rt_flag_End_Line = 1;
                if (mc_rt_block_Num_Columns) mc_rt_Columns = mc_rt_block_Num_Columns;
              }
            } while (!mc_rt_flag_End_Line); /* end while mc_rt_flag_End_Line */
          }
          else
          { /* ascii line: does not begin with a number: ignore line */
            mc_rt_flag_In_array          = 0;
            mc_rt_flag_Store_into_header = 1;
          }
        } /* end: if not line comment else numerical */
        if (mc_rt_flag_Store_into_header) { /* add line into header */
          mc_rt_count_in_header += strlen(mc_rt_line);
          if (mc_rt_count_in_header+4096 > mc_rt_malloc_size_h)
          { /* if succeed and in array : add (and realloc if necessary) */
            mc_rt_malloc_size_h = mc_rt_count_in_header+4096;
            mc_rt_Header     = (char*)realloc(mc_rt_Header, mc_rt_malloc_size_h*sizeof(char));
          }
          strncat(mc_rt_Header, mc_rt_line, 4096);
          mc_rt_flag_In_array  = 0; /* will start a new data block */
          /* exit line and file if passed desired block */
          if (mc_rt_block_number && mc_rt_block_number == mc_rt_block_Current_index) {
            mc_rt_flag_End_row_loop  = 1;

          }
        }
      } /* end: if fgets */
      else mc_rt_flag_End_row_loop = 1; /* else fgets : end of file */
    } while (!mc_rt_flag_End_row_loop); /* end while mc_rt_flag_End_row_loop */

    mc_rt_Table->block_number = mc_rt_block_number;
    mc_rt_Table->array_length = 1;
    if (mc_rt_count_in_header) mc_rt_Header    = (char*)realloc(mc_rt_Header, mc_rt_count_in_header*sizeof(char));
    mc_rt_Table->header       = mc_rt_Header;
    if (mc_rt_count_in_array*mc_rt_Rows*mc_rt_Columns == 0)
    {
      mc_rt_Table->rows         = 0;
      mc_rt_Table->columns      = 0;
      free(mc_rt_Data);
      return (0);
    }
    if (mc_rt_Rows * mc_rt_Columns != mc_rt_count_in_array)
    {
      fprintf(stderr, "Warning: Read_Table :%s %s Data has %li values that should be %li x %li\n",
        (mc_rt_Table->filename ? mc_rt_Table->filename : ""),
        (!mc_rt_block_number ? " catenated" : ""),
        mc_rt_count_in_array, mc_rt_Rows, mc_rt_Columns);
      mc_rt_Columns = mc_rt_count_in_array; mc_rt_Rows = 1;
    }
    mc_rt_Data     = (double*)realloc(mc_rt_Data, mc_rt_count_in_array*sizeof(double));
    mc_rt_Table->data         = mc_rt_Data;
    mc_rt_Table->rows         = mc_rt_Rows;
    mc_rt_Table->columns      = mc_rt_Columns;

    Table_Stat(mc_rt_Table);
    return (mc_rt_count_in_array);

  } /* end Table_Read_Handle */

/*******************************************************************************
* long Rebin_Table(t_Table *Table)
*   ACTION: rebin a single Table, sorting 1st column in ascending order
*   input   Table: single table containing data.
*                  The data block is reallocated in this process
*   return  updated Table with increasing, evenly spaced first column (index 0)
*           number of data elements (-1: error, 0:empty data)
*******************************************************************************/
  long Table_Rebin(t_Table *mc_rt_Table)
  {
    double mc_rt_new_step=0;
    long   mc_rt_i;
    /* performs linear interpolation on X axis (0-th column) */

    if (!mc_rt_Table) return(-1);
    if (!mc_rt_Table->data
    || mc_rt_Table->rows*mc_rt_Table->columns == 0 || !mc_rt_Table->step_x)
      return(0);
    Table_Stat(mc_rt_Table); /* recompute statitstics and minimal step */
    mc_rt_new_step = mc_rt_Table->step_x; /* minimal step in 1st column */

    if (mc_rt_Table->constantstep) /* already evenly spaced */
      return (mc_rt_Table->rows*mc_rt_Table->columns);
    else {
      long mc_rt_Length_Table;
      double *mc_rt_New_Table;

      mc_rt_Length_Table = ceil(fabs(mc_rt_Table->max_x - mc_rt_Table->min_x)/mc_rt_new_step);
      mc_rt_New_Table    = (double*)malloc(mc_rt_Length_Table*mc_rt_Table->columns*sizeof(double));

      for (mc_rt_i=0; mc_rt_i < mc_rt_Length_Table; mc_rt_i++)
      {
        long   mc_rt_j;
        double mc_rt_X;
        mc_rt_X = mc_rt_Table->min_x + mc_rt_i*mc_rt_new_step;
        mc_rt_New_Table[mc_rt_i*mc_rt_Table->columns] = mc_rt_X;
        for (mc_rt_j=1; mc_rt_j < mc_rt_Table->columns; mc_rt_j++)
          mc_rt_New_Table[mc_rt_i*mc_rt_Table->columns+mc_rt_j]
                = Table_Value(*mc_rt_Table, mc_rt_X, mc_rt_j);
      } /* end for mc_rt_i */

      mc_rt_Table->rows = mc_rt_Length_Table;
      mc_rt_Table->step_x = mc_rt_new_step;
      free(mc_rt_Table->data);
      mc_rt_Table->data = mc_rt_New_Table;
    } /* end else (!constantstep) */
    return (mc_rt_Table->rows*mc_rt_Table->columns);
  } /* end Rebin_Table */

/*******************************************************************************
* double Table_Index(t_Table Table, long i, long j)
*   ACTION: read an element [i,j] of a single Table
*   input   Table: table containing data
*           i : index of row      (0:Rows-1)
*           j : index of column   (0:Columns-1)
*   return  Value = data[i][j]
* Returns Value from the i-th row, j-th column of Table
* Tests are performed on indexes i,j to avoid errors
*******************************************************************************/
  double Table_Index(t_Table mc_rt_Table, long mc_rt_i, long mc_rt_j)
  {
    long mc_rt_AbsIndex;

    if (mc_rt_i < 0)        mc_rt_i = 0;
    if (mc_rt_j < 0)        mc_rt_j = 0;
    /* handle vectors specifically */
    if (mc_rt_Table.columns == 1 || mc_rt_Table.rows == 1) {
      mc_rt_AbsIndex = mc_rt_i+mc_rt_j;
    } else {
      if (mc_rt_i >= mc_rt_Table.rows)    mc_rt_i = mc_rt_Table.rows-1;
      if (mc_rt_j >= mc_rt_Table.columns) mc_rt_j = mc_rt_Table.columns-1;
      mc_rt_AbsIndex = mc_rt_i*(mc_rt_Table.columns)+mc_rt_j;
    }
    if (mc_rt_AbsIndex >= mc_rt_Table.rows*mc_rt_Table.columns)
      mc_rt_AbsIndex = mc_rt_Table.rows*mc_rt_Table.columns-1;
    else if (mc_rt_AbsIndex < 0) mc_rt_AbsIndex=0;
    if (mc_rt_Table.data != NULL)
      return(mc_rt_Table.data[mc_rt_AbsIndex]);
    else
      return(0);
  } /* end Table_Index */

/*******************************************************************************
* void Table_SetElement(t_Table *Table, long i, long j, double value)
*   ACTION: set an element [i,j] of a single Table
*   input   Table: table containing data
*           i : index of row      (0:mc_rt_Rows-1)
*           j : index of column   (0:Columns-1)
*           value = data[i][j]
* Returns 0 in case of error
* Tests are performed on indexes i,j to avoid errors
*******************************************************************************/
  int Table_SetElement(t_Table *mc_rt_Table, long mc_rt_i, long mc_rt_j,
                        double mc_rt_value)
  {
    long mc_rt_AbsIndex;

    if (mc_rt_i < 0)        mc_rt_i = 0;
    if (mc_rt_i >= mc_rt_Table->rows)    mc_rt_i = mc_rt_Table->rows-1;
    if (mc_rt_j < 0)        mc_rt_j = 0;
    if (mc_rt_j >= mc_rt_Table->columns) mc_rt_j = mc_rt_Table->columns-1;
    mc_rt_AbsIndex = mc_rt_i*(mc_rt_Table->columns)+mc_rt_j;
    if (mc_rt_Table->data != NULL)
      mc_rt_Table->data[mc_rt_AbsIndex] = mc_rt_value;
    else return(0);
    return(1);
  } /* end Table_SetElement */

/*******************************************************************************
* double Table_Value(t_Table Table, double X, long j)
*   ACTION: read column [j] of a single Table at row which 1st column is X
*   input   Table: table containing data.
*           X : data value in the first column (index 0)
*           j : index of column from which is extracted the Value (0:Columns-1)
*   return  Value = data[index for X][j] with linear interpolation
* Returns Value from the j-th column of Table corresponding to the
* X value for the 1st column (index 0)
* Tests are performed (within Table_Index) on indexes i,j to avoid errors
* NOTE: data should rather be monotonic, and evenly sampled.
*******************************************************************************/
  double Table_Value(t_Table mc_rt_Table, double X, long j)
  {
    long   mc_rt_Index;
    double mc_rt_X1, mc_rt_Y1, mc_rt_X2, mc_rt_Y2;
    double ret=0;

    if (X > mc_rt_Table.max_x) return Table_Index(mc_rt_Table,mc_rt_Table.rows-1  ,j);
    if (X < mc_rt_Table.min_x) return Table_Index(mc_rt_Table,0  ,j);

    if (!mc_rt_Table.constantstep)
      /* look for index surrounding X in the table -> mc_rt_Index */
      for (mc_rt_Index=1; mc_rt_Index < mc_rt_Table.rows-1; mc_rt_Index++)
      {
        mc_rt_X2 = Table_Index(mc_rt_Table, mc_rt_Index  ,0);
        mc_rt_X1 = Table_Index(mc_rt_Table, mc_rt_Index-1,0);
        if ((mc_rt_X1 <= X) && (X < mc_rt_X2)) break;
      } /* end for mc_rt_Index */
    else {
        mc_rt_Index = (long)floor((X - mc_rt_Table.min_x)
                          /(mc_rt_Table.max_x - mc_rt_Table.min_x)
                           *mc_rt_Table.rows);
        mc_rt_X1 = Table_Index(mc_rt_Table,mc_rt_Index  ,0);
        mc_rt_X2 = Table_Index(mc_rt_Table,mc_rt_Index+1,0);
    }
    mc_rt_Y2 = Table_Index(mc_rt_Table,mc_rt_Index  ,j);
    mc_rt_Y1 = Table_Index(mc_rt_Table,mc_rt_Index-1,j);

    if (!strcmp(mc_rt_Table.method,"linear"))
      ret = Table_Interp1d(X, mc_rt_X1,mc_rt_Y1, mc_rt_X2,mc_rt_Y2);
    else if (!strcmp(mc_rt_Table.method,"nearest"))
      ret = Table_Interp1d_nearest(X, mc_rt_X1,mc_rt_Y1, mc_rt_X2,mc_rt_Y2);

    return (ret);
  } /* end Table_Value */

/*******************************************************************************
* double Table_Value2d(t_Table Table, double X, double Y)
*   ACTION: read element [X,Y] of a matrix Table
*   input   Table: table containing data.
*           X : row index, may be non integer
*           Y : column index, may be non integer
*   return  Value = data[index X][index Y] with bi-linear interpolation
* Returns Value for the indexes [X,Y]
* Tests are performed (within Table_Index) on indexes i,j to avoid errors
* NOTE: data should rather be monotonic, and evenly sampled.
*******************************************************************************/
  double Table_Value2d(t_Table Table, double X, double Y)
  {
    double x1,x2,y1,y2,z11,z12,z21,z22;
    double ret=0;
    x1 = floor(X);
    y1 = floor(Y);
    if (x1 > Table.rows-1 || x1 < 0)    x2 = x1;
    else x2=x1+1;
    if (y1 > Table.columns-1 || y1 < 0) y2 = y1;
    else y2=y1+1;
    z11=Table_Index(Table, x1, y1);
    z12=Table_Index(Table, x1, y2);
    z21=Table_Index(Table, x2, y1);
    z22=Table_Index(Table, x2, y2);

    if (!strcmp(Table.method,"linear"))
      ret = Table_Interp2d(X,Y, x1,y1,x2,y2, z11,z12,z21,z22);
    else {
      if (fabs(X-x1) < fabs(X-x2)) {
        if (fabs(Y-y1) < fabs(Y-y2)) ret = z11; else ret = z12;
      } else {
        if (fabs(Y-y1) < fabs(Y-y2)) ret = z21; else ret = z22;
      }
    }
    return ret;
  } /* end Table_Value2d */


/*******************************************************************************
* void Table_Free(t_Table *Table)
*   ACTION: free a single Table
*   return: empty Table
*******************************************************************************/
  void Table_Free(t_Table *mc_rt_Table)
  {
    if (!mc_rt_Table) return;
    if (mc_rt_Table->data   != NULL) free(mc_rt_Table->data);
    if (mc_rt_Table->header != NULL) free(mc_rt_Table->header);
    mc_rt_Table->data   = NULL;
    mc_rt_Table->header = NULL;
  } /* end Table_Free */

/******************************************************************************
* void Table_Info(t_Table Table)
*    ACTION: print informations about a single Table
*******************************************************************************/
  long Table_Info(t_Table mc_rt_Table)
  {
    char mc_rt_buffer[256];
    long ret=0;

    if (!mc_rt_Table.block_number) strcpy(mc_rt_buffer, "catenated");
    else sprintf(mc_rt_buffer, "block %li", mc_rt_Table.block_number);
    printf("Table from file '%s' (%s)", mc_rt_Table.filename, mc_rt_buffer);
    if ((mc_rt_Table.data   != NULL) && (mc_rt_Table.rows*mc_rt_Table.columns))
    {
      printf(" is %li x %li ", mc_rt_Table.rows, mc_rt_Table.columns);
      if (mc_rt_Table.rows*mc_rt_Table.columns > 1)
        printf("(x=%g:%g)", mc_rt_Table.min_x, mc_rt_Table.max_x);
      else printf("(x=%g) ", mc_rt_Table.min_x);
      ret = mc_rt_Table.rows*mc_rt_Table.columns;
      if (mc_rt_Table.monotonic)    printf(", monotonic");
      if (mc_rt_Table.constantstep) printf(", constant step");
      printf(". interpolation: %s\n", mc_rt_Table.method);
    }
    else printf(" is empty.\n");

    if (mc_rt_Table.header && strlen(mc_rt_Table.header)) {
      char *header;
      int  i;
      header = malloc(80);
      if (!header) return(ret);
      for (i=0; i<80; header[i++]=0);
      if (strlen(mc_rt_Table.header) > 75) {
        strncpy(header, mc_rt_Table.header, 75-5);
        strcat( header, " ...");
      } else strcpy(header, mc_rt_Table.header);
      for (i=0; i<strlen(header); i++)
        if (header[i] == '\n' || header[i] == '\r') header[i] = ';';
      printf("  '%s'\n", header);
      free(header);
    }
    return(ret);
  } /* end Table_Info */

/******************************************************************************
* long Table_Init(t_Table *Table, m, n)
*   ACTION: initialise a Table to empty m by n table
*   return: empty Table
******************************************************************************/
long Table_Init(t_Table *mc_rt_Table, long rows, long columns)
{
  double *mc_rt_data=NULL;
  long   i;

  if (!mc_rt_Table) return(0);

  mc_rt_Table->header  = NULL;
  mc_rt_Table->filename[0]= '\0';
  mc_rt_Table->filesize= 0;
  mc_rt_Table->min_x   = 0;
  mc_rt_Table->max_x   = 0;
  mc_rt_Table->step_x  = 0;
  mc_rt_Table->block_number = 0;
  mc_rt_Table->array_length = 0;
  mc_rt_Table->monotonic    = 0;
  mc_rt_Table->constantstep = 0;
  mc_rt_Table->begin   = 0;
  mc_rt_Table->end     = 0;
  strcpy(mc_rt_Table->method,"linear");

  if (rows*columns >= 1) {
    mc_rt_data    = (double*)malloc(rows*columns*sizeof(double));
    if (mc_rt_data) for (i=0; i < rows*columns; mc_rt_data[i++]=0);
    else {
      fprintf(stderr,"Error: allocating %ld double elements."
                     "Too big (Table_Init).\n", rows*columns);
      rows = columns = 0;
    }
  }
  mc_rt_Table->rows    = (rows >= 1 ? rows : 0);
  mc_rt_Table->columns = (columns >= 1 ? columns : 0);
  mc_rt_Table->data    = mc_rt_data;
  return(mc_rt_Table->rows*mc_rt_Table->columns);
} /* end Table_Init */


/******************************************************************************
* void Table_Stat(t_Table *Table)
*   ACTION: computes min/max/mean step of 1st column for a single table (private)
*   return: updated Table
*******************************************************************************/
  static void Table_Stat(t_Table *mc_rt_Table)
  {
    long   mc_rt_i;
    double mc_rt_max_x, mc_rt_min_x;
    double mc_rt_row=1;
    char   mc_rt_monotonic=1;
    char   mc_rt_constantstep=1;
    double mc_rt_step=0;
    double mc_rt_n;

    if (!mc_rt_Table) return;
    if (!mc_rt_Table->rows || !mc_rt_Table->columns) return;
    if (mc_rt_Table->rows == 1) mc_rt_row=0;
    mc_rt_max_x = -FLT_MAX;
    mc_rt_min_x =  FLT_MAX;
    mc_rt_n     = (mc_rt_row ? mc_rt_Table->rows : mc_rt_Table->columns);

    /* get min and max of first column/vector */
    for (mc_rt_i=0; mc_rt_i < mc_rt_n; mc_rt_i++)
    {
      double mc_rt_X;
      mc_rt_X = (mc_rt_row ? Table_Index(*mc_rt_Table,mc_rt_i  ,0)
                               : Table_Index(*mc_rt_Table,0, mc_rt_i));
      if (mc_rt_X < mc_rt_min_x) mc_rt_min_x = mc_rt_X;
      if (mc_rt_X > mc_rt_max_x) mc_rt_max_x = mc_rt_X;
    } /* for */
    if (mc_rt_n > 1) {
      /* mean step */
      mc_rt_step = (mc_rt_max_x - mc_rt_min_x)/(mc_rt_n-1);
      /* now test if table is monotonic on first column, and get minimal step size */
      for (mc_rt_i=0; mc_rt_i < mc_rt_n-1; mc_rt_i++) {
        double mc_rt_X, mc_rt_diff;;
        mc_rt_X = (mc_rt_row ? Table_Index(*mc_rt_Table,mc_rt_i  ,0)
                            : Table_Index(*mc_rt_Table,0, mc_rt_i));
        mc_rt_diff         = Table_Index(*mc_rt_Table,mc_rt_i+1,0) - mc_rt_X;
        if (fabs(mc_rt_diff) < fabs(mc_rt_step)) mc_rt_step = mc_rt_diff;
        /* change sign ? */
        if ((mc_rt_Table->max_x - mc_rt_Table->min_x)*mc_rt_diff < 0 && mc_rt_monotonic)
          mc_rt_monotonic = 0;
      } /* end for */
      /* now test if steps are constant within READ_TABLE_STEPTOL */
      if (mc_rt_monotonic) {
      for (mc_rt_i=0; mc_rt_i < mc_rt_n-1; mc_rt_i++) {
        double mc_rt_X, mc_rt_diff;
        mc_rt_X = (mc_rt_row ? Table_Index(*mc_rt_Table,mc_rt_i  ,0)
                            : Table_Index(*mc_rt_Table,0, mc_rt_i));
        mc_rt_diff         = Table_Index(*mc_rt_Table,mc_rt_i+1,0) - mc_rt_X;
        if ( !(fabs(mc_rt_step)*(1-READ_TABLE_STEPTOL) < fabs(mc_rt_diff)
               && fabs(mc_rt_diff) < fabs(mc_rt_step)*(1+READ_TABLE_STEPTOL)) )
        { mc_rt_constantstep = 0; break; }
      }
}
    }
    mc_rt_Table->step_x= mc_rt_step;
    mc_rt_Table->max_x = mc_rt_max_x;
    mc_rt_Table->min_x = mc_rt_min_x;
    mc_rt_Table->monotonic = mc_rt_monotonic;
    mc_rt_Table->constantstep = mc_rt_constantstep;
  } /* end Table_Stat */

/******************************************************************************
* t_Table *Table_Read_Array(char *File, long *blocks)
*   ACTION: read as many data blocks as available, iteratively from file
*   return: initialized t_Table array, last element is an empty Table.
*           the number of extracted blocks in non NULL pointer *blocks
*******************************************************************************/
  t_Table *Table_Read_Array(char *mc_rt_File, long *mc_rt_blocks)
  {
    t_Table *mc_rt_Table_Array=NULL;
    long mc_rt_offset=0;
    long mc_rt_block_number=0;
    long mc_rt_allocated=256;
    long mc_rt_nelements=1;

    /* fisrt allocate an initial empty t_Table array */
    mc_rt_Table_Array = (t_Table *)malloc(mc_rt_allocated*sizeof(t_Table));
    if (!mc_rt_Table_Array) {
      fprintf(stderr, "Error: Can not allocate memory %li (Table_Read_Array).\n",
         mc_rt_allocated*sizeof(t_Table));
      *mc_rt_blocks = 0;
      return (NULL);
    }

    while (mc_rt_nelements > 0)
    {
      t_Table mc_rt_Table;

      /* access file at mc_rt_offset and get following block */
      mc_rt_nelements = Table_Read_Offset(&mc_rt_Table, mc_rt_File, 1,
      &mc_rt_offset,0);
      /* if ok, set t_Table block number else exit loop */
      mc_rt_block_number++;
      mc_rt_Table.block_number = mc_rt_block_number;
      /* if t_Table array is not long enough, expand and realocate */
      if (mc_rt_block_number >= mc_rt_allocated-1) {
        mc_rt_allocated += 256;
        mc_rt_Table_Array = (t_Table *)realloc(mc_rt_Table_Array,
           mc_rt_allocated*sizeof(t_Table));
        if (!mc_rt_Table_Array) {
          fprintf(stderr, "Error: Can not re-allocate memory %li (Table_Read_Array).\n",
              mc_rt_allocated*sizeof(t_Table));
          *mc_rt_blocks = 0;
          return (NULL);
        }
      }
      /* store it into t_Table array */
      mc_rt_Table_Array[mc_rt_block_number-1] = mc_rt_Table;
      /* continues until we find an empty block */
    }
    /* send back number of extracted blocks */
    if (mc_rt_blocks) *mc_rt_blocks = mc_rt_block_number-1;

    /* now store total number of elements in Table array */
    for (mc_rt_offset=0; mc_rt_offset < mc_rt_block_number;
      mc_rt_Table_Array[mc_rt_offset++].array_length = mc_rt_block_number-1);

    return(mc_rt_Table_Array);
  } /* end Table_Read_Array */
/*******************************************************************************
* void Table_Free_Array(t_Table *Table)
*   ACTION: free a Table array
*******************************************************************************/
  void Table_Free_Array(t_Table *mc_rt_Table)
  {
    long mc_rt_index=0;
    if (!mc_rt_Table) return;
    do {
        if (mc_rt_Table[mc_rt_index].data || mc_rt_Table[mc_rt_index].header)
          Table_Free(&mc_rt_Table[mc_rt_index]);
        else mc_rt_index=-1;
    } while (mc_rt_index>= 0);
    free(mc_rt_Table);
  } /* end Table_Free_Array */

/******************************************************************************
* long Table_Info_Array(t_Table *Table)
*    ACTION: print informations about a Table array
*    return: number of elements in the Table array
*******************************************************************************/
  long Table_Info_Array(t_Table *mc_rt_Table)
  {
    long mc_rt_index=0;

    if (!mc_rt_Table) return(-1);
    while (mc_rt_index < mc_rt_Table[mc_rt_index].array_length
       && (mc_rt_Table[mc_rt_index].data || mc_rt_Table[mc_rt_index].header)
       && (mc_rt_Table[mc_rt_index].rows*mc_rt_Table[mc_rt_index].columns) ) {
      Table_Info(mc_rt_Table[mc_rt_index]);
      mc_rt_index++;
    }
    printf("This Table array contains %li elements\n", mc_rt_index);
    return(mc_rt_index);
  } /* end Table_Info_Array */

/******************************************************************************
* char **Table_ParseHeaderchar *header, symbol1, symbol2, ..., NULL)
*    ACTION: search for char* symbols in header and return their value or NULL
*            Last argument MUST be NULL
*    return: array of char* with line following each symbol, or NULL if not found
*******************************************************************************/
#ifndef MyNL_ARGMAX
#define MyNL_ARGMAX 50
#endif

char **Table_ParseHeader(char *header, ...){
  va_list ap;
  char exit_flag=0;
  int counter=0;
  char **ret;

  if (!header) return(NULL);

  ret = (char**)calloc(MyNL_ARGMAX, sizeof(char*));
  if (!ret) {
    printf("Table_ParseHeader: Cannot allocate %i values array for Parser (Table_ParseHeader).\n",
      MyNL_ARGMAX);
    return(NULL);
  }

  va_start(ap, header);
  while(!exit_flag && counter < MyNL_ARGMAX-1)
  {
    char *arg_char;
    char *pos;
    /* get variable argument value as a char */
    arg_char = va_arg(ap, char *);
    ret[counter] = NULL;
    if (!arg_char){
      exit_flag = 1; break;
    }
    /* search for the symbol in the header */
    pos = strstr(header, arg_char);
    if (pos) {
      char *eol_pos;
      eol_pos = strchr(pos+strlen(arg_char), '\n');
      if (!eol_pos)
        eol_pos = strchr(pos+strlen(arg_char), '\r');
      if (!eol_pos) eol_pos = pos+strlen(pos)-1;
      ret[counter] = (char*)malloc(eol_pos - pos);
      if (!ret[counter]) {
        printf("Table_ParseHeader: Cannot allocate value[%i] array for Parser (Table_ParseHeader).\n",
          counter);
        exit_flag = 1; break;
      }
      strncpy(ret[counter], pos+strlen(arg_char), eol_pos - pos - strlen(arg_char));
      ret[counter][eol_pos - pos - strlen(arg_char)]='\0';
    }
    counter++;
  }
  va_end(ap);
  return(ret);
} /* Table_ParseHeader */

/******************************************************************************
* double Table_Interp1d(x, x1, y1, x2, y2)
*    ACTION: interpolates linearly at x between y1=f(x1) and y2=f(x2)
*    return: y=f(x) value
*******************************************************************************/
double Table_Interp1d(double x,
  double x1, double y1,
  double x2, double y2)
{
  double slope;
  if (x2 == x1) return (y1+y2)/2;
  if (y1 == y2) return  y1;
  slope = (y2 - y1)/(x2 - x1);
  return y1+slope*(x - x1);
} /* Table_Interp1d */

/******************************************************************************
* double Table_Interp1d_nearest(x, x1, y1, x2, y2)
*    ACTION: table lookup with nearest method at x between y1=f(x1) and y2=f(x2)
*    return: y=f(x) value
*******************************************************************************/
double Table_Interp1d_nearest(double x,
  double x1, double y1,
  double x2, double y2)
{
  if (fabs(x-x1) < fabs(x-x2)) return (y1);
  else return(y2);
} /* Table_Interp1d_nearest */

/******************************************************************************
* double Table_Interp2d(x,y, x1,y1, x2,y2, z11,z12,z21,z22)
*    ACTION: interpolates bi-linearly at (x,y) between z1=f(x1,y1) and z2=f(x2,y2)
*    return: z=f(x,y) value
*    x,y |   x1   x2
*    ----------------
*     y1 |   z11  z21
*     y2 |   z12  z22
*******************************************************************************/
double Table_Interp2d(double x, double y,
  double x1, double y1,
  double x2, double y2,
  double z11, double z12, double z21, double z22)
{
  double ratio_x, ratio_y;
  if (x2 == x1) return Table_Interp1d(y, y1,z11, y2,z12);
  if (y1 == y2) return Table_Interp1d(x, x1,z11, x2,z21);

  ratio_y = (y - y1)/(y2 - y1);
  ratio_x = (x - x1)/(x2 - x1);
  return (1-ratio_x)*(1-ratio_y)*z11 + ratio_x*(1-ratio_y)*z21
    + ratio_x*ratio_y*z22         + (1-ratio_x)*ratio_y*z12;
} /* Table_Interp2d */

/* end of read_table-lib.c */

#line 8256 "TOFexercise42.c"

/* Instrument parameters. */
MCNUM mcipguidetype;
MCNUM mciplmin;
MCNUM mciplmax;
MCNUM mcipmorepulses;
MCNUM mcippulselength;
MCNUM mcipfrequency;
MCNUM mcipsourcefocus;
MCNUM mcipTOF1min;
MCNUM mcipTOF1max;
MCNUM mcipTOF2min;
MCNUM mcipTOF2max;
MCNUM mcipTOF3min;
MCNUM mcipTOF3max;
MCNUM mcipguide_ell_fdin;
MCNUM mcipguide_ell_fdout;
MCNUM mcipguide_par_fdout;
MCNUM mcipguide_bal_d;
MCNUM mcipdivmon_big;
MCNUM mcipTOFdetectorAngle;

#define mcNUMIPAR 19
int mcnumipar = 19;
struct mcinputtable_struct mcinputtable[mcNUMIPAR+1] = {
  "guidetype", &mcipguidetype, instr_type_double, "1", 
  "lmin", &mciplmin, instr_type_double, "0.5", 
  "lmax", &mciplmax, instr_type_double, "3.0", 
  "morepulses", &mcipmorepulses, instr_type_double, "0", 
  "pulselength", &mcippulselength, instr_type_double, "2.86e-3", 
  "frequency", &mcipfrequency, instr_type_double, "14", 
  "sourcefocus", &mcipsourcefocus, instr_type_double, "2", 
  "TOF1min", &mcipTOF1min, instr_type_double, "0", 
  "TOF1max", &mcipTOF1max, instr_type_double, "6e3", 
  "TOF2min", &mcipTOF2min, instr_type_double, "0", 
  "TOF2max", &mcipTOF2max, instr_type_double, "1e4", 
  "TOF3min", &mcipTOF3min, instr_type_double, "0", 
  "TOF3max", &mcipTOF3max, instr_type_double, "1.3e5", 
  "guide_ell_fdin", &mcipguide_ell_fdin, instr_type_double, "12", 
  "guide_ell_fdout", &mcipguide_ell_fdout, instr_type_double, "2.6125", 
  "guide_par_fdout", &mcipguide_par_fdout, instr_type_double, "15", 
  "guide_bal_d", &mcipguide_bal_d, instr_type_double, "15", 
  "divmon_big", &mcipdivmon_big, instr_type_double, "0", 
  "TOFdetectorAngle", &mcipTOFdetectorAngle, instr_type_double, "130", 
  NULL, NULL, instr_type_double, ""
};

/* User declarations from instrument definition. */
#define mccompcurname TOFexercise42
#define guidetype mcipguidetype
#define lmin mciplmin
#define lmax mciplmax
#define morepulses mcipmorepulses
#define pulselength mcippulselength
#define frequency mcipfrequency
#define sourcefocus mcipsourcefocus
#define TOF1min mcipTOF1min
#define TOF1max mcipTOF1max
#define TOF2min mcipTOF2min
#define TOF2max mcipTOF2max
#define TOF3min mcipTOF3min
#define TOF3max mcipTOF3max
#define guide_ell_fdin mcipguide_ell_fdin
#define guide_ell_fdout mcipguide_ell_fdout
#define guide_par_fdout mcipguide_par_fdout
#define guide_bal_d mcipguide_bal_d
#define divmon_big mcipdivmon_big
#define TOFdetectorAngle mcipTOFdetectorAngle
#line 80 "TOFexercise42.instr"
    double sourcefocus_dist, sourcefocus_xw, sourcefocus_yh;
    double divmon_w, divmon_maxdiv;
    double guide_bal_ml;
#line 8329 "TOFexercise42.c"
#undef TOFdetectorAngle
#undef divmon_big
#undef guide_bal_d
#undef guide_par_fdout
#undef guide_ell_fdout
#undef guide_ell_fdin
#undef TOF3max
#undef TOF3min
#undef TOF2max
#undef TOF2min
#undef TOF1max
#undef TOF1min
#undef sourcefocus
#undef frequency
#undef pulselength
#undef morepulses
#undef lmax
#undef lmin
#undef guidetype
#undef mccompcurname

/* Neutron state table at each component input (local coords) */
/* [x, y, z, vx, vy, vz, t, sx, sy, sz, p] */
MCNUM mccomp_storein[11*21];
/* Components position table (absolute and relative coords) */
Coords mccomp_posa[21];
Coords mccomp_posr[21];
/* Counter for each comp to check for inactive ones */
MCNUM  mcNCounter[21];
MCNUM  mcPCounter[21];
MCNUM  mcP2Counter[21];
#define mcNUMCOMP 20 /* number of components */
/* Counter for PROP ABSORB */
MCNUM  mcAbsorbProp[21];
/* Flag true when previous component acted on the neutron (SCATTER) */
MCNUM mcScattered=0;
/* Declarations of component definition and setting parameters. */

/* Definition parameters for component 'Origin' [1]. */
#define mccOrigin_profile 0
/* Setting parameters for component 'Origin' [1]. */
MCNUM mccOrigin_percent;
MCNUM mccOrigin_flag_save;
MCNUM mccOrigin_minutes;

/* Setting parameters for component 'Moderator' [2]. */
MCNUM mccModerator_size;
MCNUM mccModerator_l_low;
MCNUM mccModerator_l_high;
MCNUM mccModerator_dist;
MCNUM mccModerator_xw;
MCNUM mccModerator_yh;
MCNUM mccModerator_freq;
MCNUM mccModerator_T;
MCNUM mccModerator_tau;
MCNUM mccModerator_tau1;
MCNUM mccModerator_tau2;
MCNUM mccModerator_d;
MCNUM mccModerator_n;
MCNUM mccModerator_n2;
MCNUM mccModerator_chi2;
MCNUM mccModerator_I0;
MCNUM mccModerator_I2;
MCNUM mccModerator_branch1;
MCNUM mccModerator_branch2;
MCNUM mccModerator_branch_tail;
MCNUM mccModerator_twopulses;

/* Definition parameters for component 'TOF_mon_1' [3]. */
#define mccTOF_mon_1_nchan 200
#define mccTOF_mon_1_filename "TOF_mon_1.dat"
/* Setting parameters for component 'TOF_mon_1' [3]. */
MCNUM mccTOF_mon_1_xmin;
MCNUM mccTOF_mon_1_xmax;
MCNUM mccTOF_mon_1_ymin;
MCNUM mccTOF_mon_1_ymax;
MCNUM mccTOF_mon_1_xwidth;
MCNUM mccTOF_mon_1_yheight;
MCNUM mccTOF_mon_1_t0;
MCNUM mccTOF_mon_1_t1;
MCNUM mccTOF_mon_1_dt;
MCNUM mccTOF_mon_1_restore_neutron;

/* Definition parameters for component 'TOF_lmon_1' [4]. */
#define mccTOF_lmon_1_nlam 200
#define mccTOF_lmon_1_nt 100
#define mccTOF_lmon_1_filename "TOF_lmon_1.dat"
#define mccTOF_lmon_1_t_0 mcipTOF1min
#define mccTOF_lmon_1_t_1 mcipTOF1max
/* Setting parameters for component 'TOF_lmon_1' [4]. */
MCNUM mccTOF_lmon_1_xmin;
MCNUM mccTOF_lmon_1_xmax;
MCNUM mccTOF_lmon_1_ymin;
MCNUM mccTOF_lmon_1_ymax;
MCNUM mccTOF_lmon_1_xwidth;
MCNUM mccTOF_lmon_1_yheight;
MCNUM mccTOF_lmon_1_lambda_0;
MCNUM mccTOF_lmon_1_lambda_1;
MCNUM mccTOF_lmon_1_restore_neutron;

/* Definition parameters for component 'TOF_mon_2' [5]. */
#define mccTOF_mon_2_nchan 200
#define mccTOF_mon_2_filename "TOF_mon_2.dat"
/* Setting parameters for component 'TOF_mon_2' [5]. */
MCNUM mccTOF_mon_2_xmin;
MCNUM mccTOF_mon_2_xmax;
MCNUM mccTOF_mon_2_ymin;
MCNUM mccTOF_mon_2_ymax;
MCNUM mccTOF_mon_2_xwidth;
MCNUM mccTOF_mon_2_yheight;
MCNUM mccTOF_mon_2_t0;
MCNUM mccTOF_mon_2_t1;
MCNUM mccTOF_mon_2_dt;
MCNUM mccTOF_mon_2_restore_neutron;

/* Definition parameters for component 'TOF_lmon_2' [6]. */
#define mccTOF_lmon_2_nlam 200
#define mccTOF_lmon_2_nt 100
#define mccTOF_lmon_2_filename "TOF_lmon_2.dat"
#define mccTOF_lmon_2_t_0 mcipTOF2min
#define mccTOF_lmon_2_t_1 mcipTOF2max
/* Setting parameters for component 'TOF_lmon_2' [6]. */
MCNUM mccTOF_lmon_2_xmin;
MCNUM mccTOF_lmon_2_xmax;
MCNUM mccTOF_lmon_2_ymin;
MCNUM mccTOF_lmon_2_ymax;
MCNUM mccTOF_lmon_2_xwidth;
MCNUM mccTOF_lmon_2_yheight;
MCNUM mccTOF_lmon_2_lambda_0;
MCNUM mccTOF_lmon_2_lambda_1;
MCNUM mccTOF_lmon_2_restore_neutron;

/* Definition parameters for component 'Guide1' [7]. */
#define mccGuide1_reflect 0
/* Setting parameters for component 'Guide1' [7]. */
MCNUM mccGuide1_w1;
MCNUM mccGuide1_h1;
MCNUM mccGuide1_w2;
MCNUM mccGuide1_h2;
MCNUM mccGuide1_l;
MCNUM mccGuide1_R0;
MCNUM mccGuide1_Qc;
MCNUM mccGuide1_alpha;
MCNUM mccGuide1_m;
MCNUM mccGuide1_W;

/* Definition parameters for component 'Guide2' [8]. */
#define mccGuide2_option "elliptical"
#define mccGuide2_segno 400
/* Setting parameters for component 'Guide2' [8]. */
MCNUM mccGuide2_w1;
MCNUM mccGuide2_h1;
MCNUM mccGuide2_l;
MCNUM mccGuide2_linw;
MCNUM mccGuide2_loutw;
MCNUM mccGuide2_linh;
MCNUM mccGuide2_louth;
MCNUM mccGuide2_R0;
MCNUM mccGuide2_Qcx;
MCNUM mccGuide2_Qcy;
MCNUM mccGuide2_alphax;
MCNUM mccGuide2_alphay;
MCNUM mccGuide2_W;
MCNUM mccGuide2_mx;
MCNUM mccGuide2_my;

/* Definition parameters for component 'Guide3' [9]. */
#define mccGuide3_option "parabolical"
#define mccGuide3_segno 400
/* Setting parameters for component 'Guide3' [9]. */
MCNUM mccGuide3_w1;
MCNUM mccGuide3_h1;
MCNUM mccGuide3_l;
MCNUM mccGuide3_linw;
MCNUM mccGuide3_loutw;
MCNUM mccGuide3_linh;
MCNUM mccGuide3_louth;
MCNUM mccGuide3_R0;
MCNUM mccGuide3_Qcx;
MCNUM mccGuide3_Qcy;
MCNUM mccGuide3_alphax;
MCNUM mccGuide3_alphay;
MCNUM mccGuide3_W;
MCNUM mccGuide3_mx;
MCNUM mccGuide3_my;

/* Definition parameters for component 'Guide4a' [10]. */
#define mccGuide4a_reflect 0
/* Setting parameters for component 'Guide4a' [10]. */
MCNUM mccGuide4a_w1;
MCNUM mccGuide4a_h1;
MCNUM mccGuide4a_w2;
MCNUM mccGuide4a_h2;
MCNUM mccGuide4a_l;
MCNUM mccGuide4a_R0;
MCNUM mccGuide4a_Qc;
MCNUM mccGuide4a_alpha;
MCNUM mccGuide4a_m;
MCNUM mccGuide4a_W;

/* Definition parameters for component 'Guide4b' [11]. */
#define mccGuide4b_reflect 0
/* Setting parameters for component 'Guide4b' [11]. */
MCNUM mccGuide4b_w1;
MCNUM mccGuide4b_h1;
MCNUM mccGuide4b_w2;
MCNUM mccGuide4b_h2;
MCNUM mccGuide4b_l;
MCNUM mccGuide4b_R0;
MCNUM mccGuide4b_Qc;
MCNUM mccGuide4b_alpha;
MCNUM mccGuide4b_m;
MCNUM mccGuide4b_W;

/* Definition parameters for component 'Guide4c' [12]. */
#define mccGuide4c_reflect 0
/* Setting parameters for component 'Guide4c' [12]. */
MCNUM mccGuide4c_w1;
MCNUM mccGuide4c_h1;
MCNUM mccGuide4c_w2;
MCNUM mccGuide4c_h2;
MCNUM mccGuide4c_l;
MCNUM mccGuide4c_R0;
MCNUM mccGuide4c_Qc;
MCNUM mccGuide4c_alpha;
MCNUM mccGuide4c_m;
MCNUM mccGuide4c_W;

/* Definition parameters for component 'TOF_mon_3' [13]. */
#define mccTOF_mon_3_nchan 200
#define mccTOF_mon_3_filename "TOF_mon_3.dat"
/* Setting parameters for component 'TOF_mon_3' [13]. */
MCNUM mccTOF_mon_3_xmin;
MCNUM mccTOF_mon_3_xmax;
MCNUM mccTOF_mon_3_ymin;
MCNUM mccTOF_mon_3_ymax;
MCNUM mccTOF_mon_3_xwidth;
MCNUM mccTOF_mon_3_yheight;
MCNUM mccTOF_mon_3_t0;
MCNUM mccTOF_mon_3_t1;
MCNUM mccTOF_mon_3_dt;
MCNUM mccTOF_mon_3_restore_neutron;

/* Definition parameters for component 'TOF_lmon_3' [14]. */
#define mccTOF_lmon_3_nlam 200
#define mccTOF_lmon_3_nt 100
#define mccTOF_lmon_3_filename "TOF_lmon_3.dat"
#define mccTOF_lmon_3_t_0 mcipTOF3min
#define mccTOF_lmon_3_t_1 mcipTOF3max
/* Setting parameters for component 'TOF_lmon_3' [14]. */
MCNUM mccTOF_lmon_3_xmin;
MCNUM mccTOF_lmon_3_xmax;
MCNUM mccTOF_lmon_3_ymin;
MCNUM mccTOF_lmon_3_ymax;
MCNUM mccTOF_lmon_3_xwidth;
MCNUM mccTOF_lmon_3_yheight;
MCNUM mccTOF_lmon_3_lambda_0;
MCNUM mccTOF_lmon_3_lambda_1;
MCNUM mccTOF_lmon_3_restore_neutron;

/* Definition parameters for component 'DivLambda_mon' [15]. */
#define mccDivLambda_mon_nlam 200
#define mccDivLambda_mon_ndiv 100
#define mccDivLambda_mon_filename "DivLambd_mon.dat"
#define mccDivLambda_mon_restore_neutron 1
/* Setting parameters for component 'DivLambda_mon' [15]. */
MCNUM mccDivLambda_mon_xmin;
MCNUM mccDivLambda_mon_xmax;
MCNUM mccDivLambda_mon_ymin;
MCNUM mccDivLambda_mon_ymax;
MCNUM mccDivLambda_mon_xwidth;
MCNUM mccDivLambda_mon_yheight;
MCNUM mccDivLambda_mon_maxdiv;
MCNUM mccDivLambda_mon_lambda_0;
MCNUM mccDivLambda_mon_lambda_1;

/* Setting parameters for component 'Sample' [16]. */
MCNUM mccSample_radius;
MCNUM mccSample_yheight;
MCNUM mccSample_q;
MCNUM mccSample_d;
MCNUM mccSample_d_phi;
MCNUM mccSample_pack;
MCNUM mccSample_j;
MCNUM mccSample_DW;
MCNUM mccSample_F2;
MCNUM mccSample_Vc;
MCNUM mccSample_sigma_a;
MCNUM mccSample_xwidth;
MCNUM mccSample_zthick;
MCNUM mccSample_h;

/* Definition parameters for component 'Detector' [17]. */
#define mccDetector_nt 200
#define mccDetector_filename "Detector.dat"
#define mccDetector_nphi 200
/* Setting parameters for component 'Detector' [17]. */
MCNUM mccDetector_radius;
MCNUM mccDetector_height;
MCNUM mccDetector_t_0;
MCNUM mccDetector_t_1;
MCNUM mccDetector_restore_neutron;

/* Definition parameters for component 'LineDetector' [19]. */
#define mccLineDetector_nchan 200
#define mccLineDetector_filename "LineDetector.dat"
/* Setting parameters for component 'LineDetector' [19]. */
MCNUM mccLineDetector_xmin;
MCNUM mccLineDetector_xmax;
MCNUM mccLineDetector_ymin;
MCNUM mccLineDetector_ymax;
MCNUM mccLineDetector_xwidth;
MCNUM mccLineDetector_yheight;
MCNUM mccLineDetector_t0;
MCNUM mccLineDetector_t1;
MCNUM mccLineDetector_dt;
MCNUM mccLineDetector_restore_neutron;

/* User component declarations. */

/* User declarations for component 'Origin' [1]. */
#define mccompcurname  Origin
#define mccompcurtype  Progress_bar
#define mccompcurindex 1
#define profile mccOrigin_profile
#define IntermediateCnts mccOrigin_IntermediateCnts
#define StartTime mccOrigin_StartTime
#define EndTime mccOrigin_EndTime
#define percent mccOrigin_percent
#define flag_save mccOrigin_flag_save
#define minutes mccOrigin_minutes
#line 48 "/usr/local/lib/mcstas/misc/Progress_bar.comp"
#ifndef PROGRESS_BAR
#define PROGRESS_BAR
#else
#error Only one Progress_bar component may be used in an instrument definition.
#endif

  double IntermediateCnts=0;
  time_t StartTime       =0;
  time_t EndTime         =0;
  time_t CurrentTime     =0;
#line 8672 "TOFexercise42.c"
#undef minutes
#undef flag_save
#undef percent
#undef EndTime
#undef StartTime
#undef IntermediateCnts
#undef profile
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Moderator' [2]. */
#define mccompcurname  Moderator
#define mccompcurtype  ESS_moderator_long
#define mccompcurindex 2
#define M mccModerator_M
#define F mccModerator_F
#define l_range mccModerator_l_range
#define w_mult mccModerator_w_mult
#define size mccModerator_size
#define l_low mccModerator_l_low
#define l_high mccModerator_l_high
#define dist mccModerator_dist
#define xw mccModerator_xw
#define yh mccModerator_yh
#define freq mccModerator_freq
#define T mccModerator_T
#define tau mccModerator_tau
#define tau1 mccModerator_tau1
#define tau2 mccModerator_tau2
#define d mccModerator_d
#define n mccModerator_n
#define n2 mccModerator_n2
#define chi2 mccModerator_chi2
#define I0 mccModerator_I0
#define I2 mccModerator_I2
#define branch1 mccModerator_branch1
#define branch2 mccModerator_branch2
#define branch_tail mccModerator_branch_tail
#define twopulses mccModerator_twopulses
#line 102 "/usr/local/lib/mcstas/sources/ESS_moderator_long.comp"
  double l_range, w_mult, branchframe;

  double M(double l, double temp)
    {
      double a=949.0/temp;
      return 2*a*a*exp(-a/(l*l))/(l*l*l*l*l);
    }

  double F(double t, double tau, int n)
    {
      return (exp(-t/tau)-exp(-n*t/tau))*n/(n-1)/tau;
    }
#line 8726 "TOFexercise42.c"
#undef twopulses
#undef branch_tail
#undef branch2
#undef branch1
#undef I2
#undef I0
#undef chi2
#undef n2
#undef n
#undef d
#undef tau2
#undef tau1
#undef tau
#undef T
#undef freq
#undef yh
#undef xw
#undef dist
#undef l_high
#undef l_low
#undef size
#undef w_mult
#undef l_range
#undef F
#undef M
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'TOF_mon_1' [3]. */
#define mccompcurname  TOF_mon_1
#define mccompcurtype  TOF_monitor
#define mccompcurindex 3
#define nchan mccTOF_mon_1_nchan
#define filename mccTOF_mon_1_filename
#define TOF_N mccTOF_mon_1_TOF_N
#define TOF_p mccTOF_mon_1_TOF_p
#define TOF_p2 mccTOF_mon_1_TOF_p2
#define t_min mccTOF_mon_1_t_min
#define t_max mccTOF_mon_1_t_max
#define delta_t mccTOF_mon_1_delta_t
#define xmin mccTOF_mon_1_xmin
#define xmax mccTOF_mon_1_xmax
#define ymin mccTOF_mon_1_ymin
#define ymax mccTOF_mon_1_ymax
#define xwidth mccTOF_mon_1_xwidth
#define yheight mccTOF_mon_1_yheight
#define t0 mccTOF_mon_1_t0
#define t1 mccTOF_mon_1_t1
#define dt mccTOF_mon_1_dt
#define restore_neutron mccTOF_mon_1_restore_neutron
#line 53 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
    double TOF_N[nchan];
    double TOF_p[nchan];
    double TOF_p2[nchan];
    double t_min, t_max, delta_t;
#line 8783 "TOFexercise42.c"
#undef restore_neutron
#undef dt
#undef t1
#undef t0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'TOF_lmon_1' [4]. */
#define mccompcurname  TOF_lmon_1
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 4
#define nlam mccTOF_lmon_1_nlam
#define nt mccTOF_lmon_1_nt
#define filename mccTOF_lmon_1_filename
#define t_0 mccTOF_lmon_1_t_0
#define t_1 mccTOF_lmon_1_t_1
#define tt_0 mccTOF_lmon_1_tt_0
#define tt_1 mccTOF_lmon_1_tt_1
#define TOFL_N mccTOF_lmon_1_TOFL_N
#define TOFL_p mccTOF_lmon_1_TOFL_p
#define TOFL_p2 mccTOF_lmon_1_TOFL_p2
#define xmin mccTOF_lmon_1_xmin
#define xmax mccTOF_lmon_1_xmax
#define ymin mccTOF_lmon_1_ymin
#define ymax mccTOF_lmon_1_ymax
#define xwidth mccTOF_lmon_1_xwidth
#define yheight mccTOF_lmon_1_yheight
#define lambda_0 mccTOF_lmon_1_lambda_0
#define lambda_1 mccTOF_lmon_1_lambda_1
#define restore_neutron mccTOF_lmon_1_restore_neutron
#line 57 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
    double TOFL_N[nt][nlam];
    double TOFL_p[nt][nlam];
    double TOFL_p2[nt][nlam];
    double tt_0, tt_1;
#line 8834 "TOFexercise42.c"
#undef restore_neutron
#undef lambda_1
#undef lambda_0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'TOF_mon_2' [5]. */
#define mccompcurname  TOF_mon_2
#define mccompcurtype  TOF_monitor
#define mccompcurindex 5
#define nchan mccTOF_mon_2_nchan
#define filename mccTOF_mon_2_filename
#define TOF_N mccTOF_mon_2_TOF_N
#define TOF_p mccTOF_mon_2_TOF_p
#define TOF_p2 mccTOF_mon_2_TOF_p2
#define t_min mccTOF_mon_2_t_min
#define t_max mccTOF_mon_2_t_max
#define delta_t mccTOF_mon_2_delta_t
#define xmin mccTOF_mon_2_xmin
#define xmax mccTOF_mon_2_xmax
#define ymin mccTOF_mon_2_ymin
#define ymax mccTOF_mon_2_ymax
#define xwidth mccTOF_mon_2_xwidth
#define yheight mccTOF_mon_2_yheight
#define t0 mccTOF_mon_2_t0
#define t1 mccTOF_mon_2_t1
#define dt mccTOF_mon_2_dt
#define restore_neutron mccTOF_mon_2_restore_neutron
#line 53 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
    double TOF_N[nchan];
    double TOF_p[nchan];
    double TOF_p2[nchan];
    double t_min, t_max, delta_t;
#line 8885 "TOFexercise42.c"
#undef restore_neutron
#undef dt
#undef t1
#undef t0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'TOF_lmon_2' [6]. */
#define mccompcurname  TOF_lmon_2
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 6
#define nlam mccTOF_lmon_2_nlam
#define nt mccTOF_lmon_2_nt
#define filename mccTOF_lmon_2_filename
#define t_0 mccTOF_lmon_2_t_0
#define t_1 mccTOF_lmon_2_t_1
#define tt_0 mccTOF_lmon_2_tt_0
#define tt_1 mccTOF_lmon_2_tt_1
#define TOFL_N mccTOF_lmon_2_TOFL_N
#define TOFL_p mccTOF_lmon_2_TOFL_p
#define TOFL_p2 mccTOF_lmon_2_TOFL_p2
#define xmin mccTOF_lmon_2_xmin
#define xmax mccTOF_lmon_2_xmax
#define ymin mccTOF_lmon_2_ymin
#define ymax mccTOF_lmon_2_ymax
#define xwidth mccTOF_lmon_2_xwidth
#define yheight mccTOF_lmon_2_yheight
#define lambda_0 mccTOF_lmon_2_lambda_0
#define lambda_1 mccTOF_lmon_2_lambda_1
#define restore_neutron mccTOF_lmon_2_restore_neutron
#line 57 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
    double TOFL_N[nt][nlam];
    double TOFL_p[nt][nlam];
    double TOFL_p2[nt][nlam];
    double tt_0, tt_1;
#line 8936 "TOFexercise42.c"
#undef restore_neutron
#undef lambda_1
#undef lambda_0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Guide1' [7]. */
#define mccompcurname  Guide1
#define mccompcurtype  Guide
#define mccompcurindex 7
#define reflect mccGuide1_reflect
#define pTable mccGuide1_pTable
#define w1 mccGuide1_w1
#define h1 mccGuide1_h1
#define w2 mccGuide1_w2
#define h2 mccGuide1_h2
#define l mccGuide1_l
#define R0 mccGuide1_R0
#define Qc mccGuide1_Qc
#define alpha mccGuide1_alpha
#define m mccGuide1_m
#define W mccGuide1_W
#line 72 "/usr/local/lib/mcstas/optics/Guide.comp"
  t_Table pTable;
#line 8978 "TOFexercise42.c"
#undef W
#undef m
#undef alpha
#undef Qc
#undef R0
#undef l
#undef h2
#undef w2
#undef h1
#undef w1
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Guide2' [8]. */
#define mccompcurname  Guide2
#define mccompcurtype  Guide_tapering
#define mccompcurindex 8
#define option mccGuide2_option
#define segno mccGuide2_segno
#define w1c mccGuide2_w1c
#define w2c mccGuide2_w2c
#define ww mccGuide2_ww
#define hh mccGuide2_hh
#define whalf mccGuide2_whalf
#define hhalf mccGuide2_hhalf
#define lwhalf mccGuide2_lwhalf
#define lhhalf mccGuide2_lhhalf
#define h1_in mccGuide2_h1_in
#define h2_out mccGuide2_h2_out
#define w1_in mccGuide2_w1_in
#define w2_out mccGuide2_w2_out
#define l_seg mccGuide2_l_seg
#define seg mccGuide2_seg
#define h12 mccGuide2_h12
#define h2 mccGuide2_h2
#define w12 mccGuide2_w12
#define w2 mccGuide2_w2
#define a_ell_q mccGuide2_a_ell_q
#define b_ell_q mccGuide2_b_ell_q
#define lbw mccGuide2_lbw
#define lbh mccGuide2_lbh
#define mxi mccGuide2_mxi
#define u1 mccGuide2_u1
#define u2 mccGuide2_u2
#define div1 mccGuide2_div1
#define p2_para mccGuide2_p2_para
#define test mccGuide2_test
#define Div1 mccGuide2_Div1
#define i mccGuide2_i
#define ii mccGuide2_ii
#define seg mccGuide2_seg
#define fu mccGuide2_fu
#define pos mccGuide2_pos
#define file_name mccGuide2_file_name
#define ep mccGuide2_ep
#define num mccGuide2_num
#define w1 mccGuide2_w1
#define h1 mccGuide2_h1
#define l mccGuide2_l
#define linw mccGuide2_linw
#define loutw mccGuide2_loutw
#define linh mccGuide2_linh
#define louth mccGuide2_louth
#define R0 mccGuide2_R0
#define Qcx mccGuide2_Qcx
#define Qcy mccGuide2_Qcy
#define alphax mccGuide2_alphax
#define alphay mccGuide2_alphay
#define W mccGuide2_W
#define mx mccGuide2_mx
#define my mccGuide2_my
#line 108 "/usr/local/lib/mcstas/optics/Guide_tapering.comp"
  double *w1c;
  double *w2c;
  double *ww, *hh;
  double *whalf, *hhalf;
  double *lwhalf, *lhhalf;
  double *h1_in, *h2_out, *w1_in, *w2_out;
  double l_seg, h12, h2, w12, w2, a_ell_q, b_ell_q, lbw, lbh;
  double mxi ,u1 ,u2 ,div1, p2_para;
  double test,Div1;
  int i,ii,seg;
  char *fu;
  char *pos;
  char file_name[1024];
  char *ep;
  FILE *num;

#line 9070 "TOFexercise42.c"
#undef my
#undef mx
#undef W
#undef alphay
#undef alphax
#undef Qcy
#undef Qcx
#undef R0
#undef louth
#undef linh
#undef loutw
#undef linw
#undef l
#undef h1
#undef w1
#undef num
#undef ep
#undef file_name
#undef pos
#undef fu
#undef seg
#undef ii
#undef i
#undef Div1
#undef test
#undef p2_para
#undef div1
#undef u2
#undef u1
#undef mxi
#undef lbh
#undef lbw
#undef b_ell_q
#undef a_ell_q
#undef w2
#undef w12
#undef h2
#undef h12
#undef seg
#undef l_seg
#undef w2_out
#undef w1_in
#undef h2_out
#undef h1_in
#undef lhhalf
#undef lwhalf
#undef hhalf
#undef whalf
#undef hh
#undef ww
#undef w2c
#undef w1c
#undef segno
#undef option
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Guide3' [9]. */
#define mccompcurname  Guide3
#define mccompcurtype  Guide_tapering
#define mccompcurindex 9
#define option mccGuide3_option
#define segno mccGuide3_segno
#define w1c mccGuide3_w1c
#define w2c mccGuide3_w2c
#define ww mccGuide3_ww
#define hh mccGuide3_hh
#define whalf mccGuide3_whalf
#define hhalf mccGuide3_hhalf
#define lwhalf mccGuide3_lwhalf
#define lhhalf mccGuide3_lhhalf
#define h1_in mccGuide3_h1_in
#define h2_out mccGuide3_h2_out
#define w1_in mccGuide3_w1_in
#define w2_out mccGuide3_w2_out
#define l_seg mccGuide3_l_seg
#define seg mccGuide3_seg
#define h12 mccGuide3_h12
#define h2 mccGuide3_h2
#define w12 mccGuide3_w12
#define w2 mccGuide3_w2
#define a_ell_q mccGuide3_a_ell_q
#define b_ell_q mccGuide3_b_ell_q
#define lbw mccGuide3_lbw
#define lbh mccGuide3_lbh
#define mxi mccGuide3_mxi
#define u1 mccGuide3_u1
#define u2 mccGuide3_u2
#define div1 mccGuide3_div1
#define p2_para mccGuide3_p2_para
#define test mccGuide3_test
#define Div1 mccGuide3_Div1
#define i mccGuide3_i
#define ii mccGuide3_ii
#define seg mccGuide3_seg
#define fu mccGuide3_fu
#define pos mccGuide3_pos
#define file_name mccGuide3_file_name
#define ep mccGuide3_ep
#define num mccGuide3_num
#define w1 mccGuide3_w1
#define h1 mccGuide3_h1
#define l mccGuide3_l
#define linw mccGuide3_linw
#define loutw mccGuide3_loutw
#define linh mccGuide3_linh
#define louth mccGuide3_louth
#define R0 mccGuide3_R0
#define Qcx mccGuide3_Qcx
#define Qcy mccGuide3_Qcy
#define alphax mccGuide3_alphax
#define alphay mccGuide3_alphay
#define W mccGuide3_W
#define mx mccGuide3_mx
#define my mccGuide3_my
#line 108 "/usr/local/lib/mcstas/optics/Guide_tapering.comp"
  double *w1c;
  double *w2c;
  double *ww, *hh;
  double *whalf, *hhalf;
  double *lwhalf, *lhhalf;
  double *h1_in, *h2_out, *w1_in, *w2_out;
  double l_seg, h12, h2, w12, w2, a_ell_q, b_ell_q, lbw, lbh;
  double mxi ,u1 ,u2 ,div1, p2_para;
  double test,Div1;
  int i,ii,seg;
  char *fu;
  char *pos;
  char file_name[1024];
  char *ep;
  FILE *num;

#line 9204 "TOFexercise42.c"
#undef my
#undef mx
#undef W
#undef alphay
#undef alphax
#undef Qcy
#undef Qcx
#undef R0
#undef louth
#undef linh
#undef loutw
#undef linw
#undef l
#undef h1
#undef w1
#undef num
#undef ep
#undef file_name
#undef pos
#undef fu
#undef seg
#undef ii
#undef i
#undef Div1
#undef test
#undef p2_para
#undef div1
#undef u2
#undef u1
#undef mxi
#undef lbh
#undef lbw
#undef b_ell_q
#undef a_ell_q
#undef w2
#undef w12
#undef h2
#undef h12
#undef seg
#undef l_seg
#undef w2_out
#undef w1_in
#undef h2_out
#undef h1_in
#undef lhhalf
#undef lwhalf
#undef hhalf
#undef whalf
#undef hh
#undef ww
#undef w2c
#undef w1c
#undef segno
#undef option
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Guide4a' [10]. */
#define mccompcurname  Guide4a
#define mccompcurtype  Guide
#define mccompcurindex 10
#define reflect mccGuide4a_reflect
#define pTable mccGuide4a_pTable
#define w1 mccGuide4a_w1
#define h1 mccGuide4a_h1
#define w2 mccGuide4a_w2
#define h2 mccGuide4a_h2
#define l mccGuide4a_l
#define R0 mccGuide4a_R0
#define Qc mccGuide4a_Qc
#define alpha mccGuide4a_alpha
#define m mccGuide4a_m
#define W mccGuide4a_W
#line 72 "/usr/local/lib/mcstas/optics/Guide.comp"
  t_Table pTable;
#line 9281 "TOFexercise42.c"
#undef W
#undef m
#undef alpha
#undef Qc
#undef R0
#undef l
#undef h2
#undef w2
#undef h1
#undef w1
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Guide4b' [11]. */
#define mccompcurname  Guide4b
#define mccompcurtype  Guide
#define mccompcurindex 11
#define reflect mccGuide4b_reflect
#define pTable mccGuide4b_pTable
#define w1 mccGuide4b_w1
#define h1 mccGuide4b_h1
#define w2 mccGuide4b_w2
#define h2 mccGuide4b_h2
#define l mccGuide4b_l
#define R0 mccGuide4b_R0
#define Qc mccGuide4b_Qc
#define alpha mccGuide4b_alpha
#define m mccGuide4b_m
#define W mccGuide4b_W
#line 72 "/usr/local/lib/mcstas/optics/Guide.comp"
  t_Table pTable;
#line 9316 "TOFexercise42.c"
#undef W
#undef m
#undef alpha
#undef Qc
#undef R0
#undef l
#undef h2
#undef w2
#undef h1
#undef w1
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Guide4c' [12]. */
#define mccompcurname  Guide4c
#define mccompcurtype  Guide
#define mccompcurindex 12
#define reflect mccGuide4c_reflect
#define pTable mccGuide4c_pTable
#define w1 mccGuide4c_w1
#define h1 mccGuide4c_h1
#define w2 mccGuide4c_w2
#define h2 mccGuide4c_h2
#define l mccGuide4c_l
#define R0 mccGuide4c_R0
#define Qc mccGuide4c_Qc
#define alpha mccGuide4c_alpha
#define m mccGuide4c_m
#define W mccGuide4c_W
#line 72 "/usr/local/lib/mcstas/optics/Guide.comp"
  t_Table pTable;
#line 9351 "TOFexercise42.c"
#undef W
#undef m
#undef alpha
#undef Qc
#undef R0
#undef l
#undef h2
#undef w2
#undef h1
#undef w1
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'TOF_mon_3' [13]. */
#define mccompcurname  TOF_mon_3
#define mccompcurtype  TOF_monitor
#define mccompcurindex 13
#define nchan mccTOF_mon_3_nchan
#define filename mccTOF_mon_3_filename
#define TOF_N mccTOF_mon_3_TOF_N
#define TOF_p mccTOF_mon_3_TOF_p
#define TOF_p2 mccTOF_mon_3_TOF_p2
#define t_min mccTOF_mon_3_t_min
#define t_max mccTOF_mon_3_t_max
#define delta_t mccTOF_mon_3_delta_t
#define xmin mccTOF_mon_3_xmin
#define xmax mccTOF_mon_3_xmax
#define ymin mccTOF_mon_3_ymin
#define ymax mccTOF_mon_3_ymax
#define xwidth mccTOF_mon_3_xwidth
#define yheight mccTOF_mon_3_yheight
#define t0 mccTOF_mon_3_t0
#define t1 mccTOF_mon_3_t1
#define dt mccTOF_mon_3_dt
#define restore_neutron mccTOF_mon_3_restore_neutron
#line 53 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
    double TOF_N[nchan];
    double TOF_p[nchan];
    double TOF_p2[nchan];
    double t_min, t_max, delta_t;
#line 9395 "TOFexercise42.c"
#undef restore_neutron
#undef dt
#undef t1
#undef t0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'TOF_lmon_3' [14]. */
#define mccompcurname  TOF_lmon_3
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 14
#define nlam mccTOF_lmon_3_nlam
#define nt mccTOF_lmon_3_nt
#define filename mccTOF_lmon_3_filename
#define t_0 mccTOF_lmon_3_t_0
#define t_1 mccTOF_lmon_3_t_1
#define tt_0 mccTOF_lmon_3_tt_0
#define tt_1 mccTOF_lmon_3_tt_1
#define TOFL_N mccTOF_lmon_3_TOFL_N
#define TOFL_p mccTOF_lmon_3_TOFL_p
#define TOFL_p2 mccTOF_lmon_3_TOFL_p2
#define xmin mccTOF_lmon_3_xmin
#define xmax mccTOF_lmon_3_xmax
#define ymin mccTOF_lmon_3_ymin
#define ymax mccTOF_lmon_3_ymax
#define xwidth mccTOF_lmon_3_xwidth
#define yheight mccTOF_lmon_3_yheight
#define lambda_0 mccTOF_lmon_3_lambda_0
#define lambda_1 mccTOF_lmon_3_lambda_1
#define restore_neutron mccTOF_lmon_3_restore_neutron
#line 57 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
    double TOFL_N[nt][nlam];
    double TOFL_p[nt][nlam];
    double TOFL_p2[nt][nlam];
    double tt_0, tt_1;
#line 9446 "TOFexercise42.c"
#undef restore_neutron
#undef lambda_1
#undef lambda_0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'DivLambda_mon' [15]. */
#define mccompcurname  DivLambda_mon
#define mccompcurtype  DivLambda_monitor
#define mccompcurindex 15
#define nlam mccDivLambda_mon_nlam
#define ndiv mccDivLambda_mon_ndiv
#define filename mccDivLambda_mon_filename
#define restore_neutron mccDivLambda_mon_restore_neutron
#define Div_N mccDivLambda_mon_Div_N
#define Div_p mccDivLambda_mon_Div_p
#define Div_p2 mccDivLambda_mon_Div_p2
#define xmin mccDivLambda_mon_xmin
#define xmax mccDivLambda_mon_xmax
#define ymin mccDivLambda_mon_ymin
#define ymax mccDivLambda_mon_ymax
#define xwidth mccDivLambda_mon_xwidth
#define yheight mccDivLambda_mon_yheight
#define maxdiv mccDivLambda_mon_maxdiv
#define lambda_0 mccDivLambda_mon_lambda_0
#define lambda_1 mccDivLambda_mon_lambda_1
#line 61 "/usr/local/lib/mcstas/monitors/DivLambda_monitor.comp"
    double Div_N[nlam][ndiv];
    double Div_p[nlam][ndiv];
    double Div_p2[nlam][ndiv];
#line 9494 "TOFexercise42.c"
#undef lambda_1
#undef lambda_0
#undef maxdiv
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef Div_p2
#undef Div_p
#undef Div_N
#undef restore_neutron
#undef filename
#undef ndiv
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Sample' [16]. */
#define mccompcurname  Sample
#define mccompcurtype  Powder1
#define mccompcurindex 16
#define my_s_v2 mccSample_my_s_v2
#define my_a_v mccSample_my_a_v
#define q_v mccSample_q_v
#define isrect mccSample_isrect
#define radius mccSample_radius
#define yheight mccSample_yheight
#define q mccSample_q
#define d mccSample_d
#define d_phi mccSample_d_phi
#define pack mccSample_pack
#define j mccSample_j
#define DW mccSample_DW
#define F2 mccSample_F2
#define Vc mccSample_Vc
#define sigma_a mccSample_sigma_a
#define xwidth mccSample_xwidth
#define zthick mccSample_zthick
#define h mccSample_h
#line 78 "/usr/local/lib/mcstas/samples/Powder1.comp"
  double my_s_v2, my_a_v, q_v;
  char   isrect=0;
#line 9540 "TOFexercise42.c"
#undef h
#undef zthick
#undef xwidth
#undef sigma_a
#undef Vc
#undef F2
#undef DW
#undef j
#undef pack
#undef d_phi
#undef d
#undef q
#undef yheight
#undef radius
#undef isrect
#undef q_v
#undef my_a_v
#undef my_s_v2
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Detector' [17]. */
#define mccompcurname  Detector
#define mccompcurtype  TOF_cylPSD_monitor
#define mccompcurindex 17
#define nt mccDetector_nt
#define filename mccDetector_filename
#define nphi mccDetector_nphi
#define TOF_N mccDetector_TOF_N
#define TOF_p mccDetector_TOF_p
#define TOF_p2 mccDetector_TOF_p2
#define radius mccDetector_radius
#define height mccDetector_height
#define t_0 mccDetector_t_0
#define t_1 mccDetector_t_1
#define restore_neutron mccDetector_restore_neutron
#line 49 "/usr/local/lib/mcstas/monitors/TOF_cylPSD_monitor.comp"
    double TOF_N[nt][nphi];
    double TOF_p[nt][nphi];
    double TOF_p2[nt][nphi];
    double binphi, tt_0, tt_1;
#line 9583 "TOFexercise42.c"
#undef restore_neutron
#undef t_1
#undef t_0
#undef height
#undef radius
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef nphi
#undef filename
#undef nt
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'arm1' [18]. */
#define mccompcurname  arm1
#define mccompcurtype  Arm
#define mccompcurindex 18
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'LineDetector' [19]. */
#define mccompcurname  LineDetector
#define mccompcurtype  TOF_monitor
#define mccompcurindex 19
#define nchan mccLineDetector_nchan
#define filename mccLineDetector_filename
#define TOF_N mccLineDetector_TOF_N
#define TOF_p mccLineDetector_TOF_p
#define TOF_p2 mccLineDetector_TOF_p2
#define t_min mccLineDetector_t_min
#define t_max mccLineDetector_t_max
#define delta_t mccLineDetector_delta_t
#define xmin mccLineDetector_xmin
#define xmax mccLineDetector_xmax
#define ymin mccLineDetector_ymin
#define ymax mccLineDetector_ymax
#define xwidth mccLineDetector_xwidth
#define yheight mccLineDetector_yheight
#define t0 mccLineDetector_t0
#define t1 mccLineDetector_t1
#define dt mccLineDetector_dt
#define restore_neutron mccLineDetector_restore_neutron
#line 53 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
    double TOF_N[nchan];
    double TOF_p[nchan];
    double TOF_p2[nchan];
    double t_min, t_max, delta_t;
#line 9634 "TOFexercise42.c"
#undef restore_neutron
#undef dt
#undef t1
#undef t0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

Coords mcposaOrigin, mcposrOrigin;
Rotation mcrotaOrigin, mcrotrOrigin;
Coords mcposaModerator, mcposrModerator;
Rotation mcrotaModerator, mcrotrModerator;
Coords mcposaTOF_mon_1, mcposrTOF_mon_1;
Rotation mcrotaTOF_mon_1, mcrotrTOF_mon_1;
Coords mcposaTOF_lmon_1, mcposrTOF_lmon_1;
Rotation mcrotaTOF_lmon_1, mcrotrTOF_lmon_1;
Coords mcposaTOF_mon_2, mcposrTOF_mon_2;
Rotation mcrotaTOF_mon_2, mcrotrTOF_mon_2;
Coords mcposaTOF_lmon_2, mcposrTOF_lmon_2;
Rotation mcrotaTOF_lmon_2, mcrotrTOF_lmon_2;
Coords mcposaGuide1, mcposrGuide1;
Rotation mcrotaGuide1, mcrotrGuide1;
Coords mcposaGuide2, mcposrGuide2;
Rotation mcrotaGuide2, mcrotrGuide2;
Coords mcposaGuide3, mcposrGuide3;
Rotation mcrotaGuide3, mcrotrGuide3;
Coords mcposaGuide4a, mcposrGuide4a;
Rotation mcrotaGuide4a, mcrotrGuide4a;
Coords mcposaGuide4b, mcposrGuide4b;
Rotation mcrotaGuide4b, mcrotrGuide4b;
Coords mcposaGuide4c, mcposrGuide4c;
Rotation mcrotaGuide4c, mcrotrGuide4c;
Coords mcposaTOF_mon_3, mcposrTOF_mon_3;
Rotation mcrotaTOF_mon_3, mcrotrTOF_mon_3;
Coords mcposaTOF_lmon_3, mcposrTOF_lmon_3;
Rotation mcrotaTOF_lmon_3, mcrotrTOF_lmon_3;
Coords mcposaDivLambda_mon, mcposrDivLambda_mon;
Rotation mcrotaDivLambda_mon, mcrotrDivLambda_mon;
Coords mcposaSample, mcposrSample;
Rotation mcrotaSample, mcrotrSample;
Coords mcposaDetector, mcposrDetector;
Rotation mcrotaDetector, mcrotrDetector;
Coords mcposaarm1, mcposrarm1;
Rotation mcrotaarm1, mcrotrarm1;
Coords mcposaLineDetector, mcposrLineDetector;
Rotation mcrotaLineDetector, mcrotrLineDetector;

MCNUM mcnx, mcny, mcnz, mcnvx, mcnvy, mcnvz, mcnt, mcnsx, mcnsy, mcnsz, mcnp;

/* end declare */

void mcinit(void) {
#define mccompcurname TOFexercise42
#define guidetype mcipguidetype
#define lmin mciplmin
#define lmax mciplmax
#define morepulses mcipmorepulses
#define pulselength mcippulselength
#define frequency mcipfrequency
#define sourcefocus mcipsourcefocus
#define TOF1min mcipTOF1min
#define TOF1max mcipTOF1max
#define TOF2min mcipTOF2min
#define TOF2max mcipTOF2max
#define TOF3min mcipTOF3min
#define TOF3max mcipTOF3max
#define guide_ell_fdin mcipguide_ell_fdin
#define guide_ell_fdout mcipguide_ell_fdout
#define guide_par_fdout mcipguide_par_fdout
#define guide_bal_d mcipguide_bal_d
#define divmon_big mcipdivmon_big
#define TOFdetectorAngle mcipTOFdetectorAngle
#line 87 "TOFexercise42.instr"
{
  if (guidetype>0 || sourcefocus == 2) {
    //focus source on guide entrance
    sourcefocus_dist = 6.01;
    sourcefocus_xw = 0.05;
    sourcefocus_yh = 0.05;  } 
  else if (sourcefocus == 1) {
    //focus source on back detector
    sourcefocus_dist = 149.9;
    sourcefocus_xw = 0.02;
    sourcefocus_yh = 0.02;  }
  
    if (divmon_big == 0) {
        //small divergence monitor (normal)
        divmon_w = 0.02;
        divmon_maxdiv = 0.2;  } 
    else if (divmon_big == 1) {
        //big divergence monitor
        divmon_w = 0.12;
        divmon_maxdiv = 0.4;  }    
    guide_bal_ml = 141.9 - 2*guide_bal_d;
}
#line 9744 "TOFexercise42.c"
#undef TOFdetectorAngle
#undef divmon_big
#undef guide_bal_d
#undef guide_par_fdout
#undef guide_ell_fdout
#undef guide_ell_fdin
#undef TOF3max
#undef TOF3min
#undef TOF2max
#undef TOF2min
#undef TOF1max
#undef TOF1min
#undef sourcefocus
#undef frequency
#undef pulselength
#undef morepulses
#undef lmax
#undef lmin
#undef guidetype
#undef mccompcurname
  /* Computation of coordinate transformations. */
  {
    Coords mctc1, mctc2;
    Rotation mctr1;

    mcDEBUG_INSTR()
    /* Component Origin. */
    SIG_MESSAGE("Origin (Init:Place/Rotate)");
    rot_set_rotation(mcrotaOrigin,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 9777 "TOFexercise42.c"
    rot_copy(mcrotrOrigin, mcrotaOrigin);
    mcposaOrigin = coords_set(
#line 115 "TOFexercise42.instr"
      0,
#line 115 "TOFexercise42.instr"
      0,
#line 115 "TOFexercise42.instr"
      0);
#line 9786 "TOFexercise42.c"
    mctc1 = coords_neg(mcposaOrigin);
    mcposrOrigin = rot_apply(mcrotaOrigin, mctc1);
    mcDEBUG_COMPONENT("Origin", mcposaOrigin, mcrotaOrigin)
    mccomp_posa[1] = mcposaOrigin;
    mccomp_posr[1] = mcposrOrigin;
    mcNCounter[1]  = mcPCounter[1] = mcP2Counter[1] = 0;
    mcAbsorbProp[1]= 0;
    /* Component Moderator. */
    SIG_MESSAGE("Moderator (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 9800 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaOrigin, mcrotaModerator);
    rot_transpose(mcrotaOrigin, mctr1);
    rot_mul(mcrotaModerator, mctr1, mcrotrModerator);
    mctc1 = coords_set(
#line 139 "TOFexercise42.instr"
      0,
#line 139 "TOFexercise42.instr"
      0,
#line 139 "TOFexercise42.instr"
      0);
#line 9811 "TOFexercise42.c"
    rot_transpose(mcrotaOrigin, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaModerator = coords_add(mcposaOrigin, mctc2);
    mctc1 = coords_sub(mcposaOrigin, mcposaModerator);
    mcposrModerator = rot_apply(mcrotaModerator, mctc1);
    mcDEBUG_COMPONENT("Moderator", mcposaModerator, mcrotaModerator)
    mccomp_posa[2] = mcposaModerator;
    mccomp_posr[2] = mcposrModerator;
    mcNCounter[2]  = mcPCounter[2] = mcP2Counter[2] = 0;
    mcAbsorbProp[2]= 0;
    /* Component TOF_mon_1. */
    SIG_MESSAGE("TOF_mon_1 (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 9828 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaModerator, mcrotaTOF_mon_1);
    rot_transpose(mcrotaModerator, mctr1);
    rot_mul(mcrotaTOF_mon_1, mctr1, mcrotrTOF_mon_1);
    mctc1 = coords_set(
#line 150 "TOFexercise42.instr"
      0,
#line 150 "TOFexercise42.instr"
      0,
#line 150 "TOFexercise42.instr"
      0);
#line 9839 "TOFexercise42.c"
    rot_transpose(mcrotaModerator, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaTOF_mon_1 = coords_add(mcposaModerator, mctc2);
    mctc1 = coords_sub(mcposaModerator, mcposaTOF_mon_1);
    mcposrTOF_mon_1 = rot_apply(mcrotaTOF_mon_1, mctc1);
    mcDEBUG_COMPONENT("TOF_mon_1", mcposaTOF_mon_1, mcrotaTOF_mon_1)
    mccomp_posa[3] = mcposaTOF_mon_1;
    mccomp_posr[3] = mcposrTOF_mon_1;
    mcNCounter[3]  = mcPCounter[3] = mcP2Counter[3] = 0;
    mcAbsorbProp[3]= 0;
    /* Component TOF_lmon_1. */
    SIG_MESSAGE("TOF_lmon_1 (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 9856 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaModerator, mcrotaTOF_lmon_1);
    rot_transpose(mcrotaTOF_mon_1, mctr1);
    rot_mul(mcrotaTOF_lmon_1, mctr1, mcrotrTOF_lmon_1);
    mctc1 = coords_set(
#line 163 "TOFexercise42.instr"
      0,
#line 163 "TOFexercise42.instr"
      0,
#line 163 "TOFexercise42.instr"
      0);
#line 9867 "TOFexercise42.c"
    rot_transpose(mcrotaModerator, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaTOF_lmon_1 = coords_add(mcposaModerator, mctc2);
    mctc1 = coords_sub(mcposaTOF_mon_1, mcposaTOF_lmon_1);
    mcposrTOF_lmon_1 = rot_apply(mcrotaTOF_lmon_1, mctc1);
    mcDEBUG_COMPONENT("TOF_lmon_1", mcposaTOF_lmon_1, mcrotaTOF_lmon_1)
    mccomp_posa[4] = mcposaTOF_lmon_1;
    mccomp_posr[4] = mcposrTOF_lmon_1;
    mcNCounter[4]  = mcPCounter[4] = mcP2Counter[4] = 0;
    mcAbsorbProp[4]= 0;
    /* Component TOF_mon_2. */
    SIG_MESSAGE("TOF_mon_2 (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 9884 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaModerator, mcrotaTOF_mon_2);
    rot_transpose(mcrotaTOF_lmon_1, mctr1);
    rot_mul(mcrotaTOF_mon_2, mctr1, mcrotrTOF_mon_2);
    mctc1 = coords_set(
#line 174 "TOFexercise42.instr"
      0,
#line 174 "TOFexercise42.instr"
      0,
#line 174 "TOFexercise42.instr"
      6);
#line 9895 "TOFexercise42.c"
    rot_transpose(mcrotaModerator, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaTOF_mon_2 = coords_add(mcposaModerator, mctc2);
    mctc1 = coords_sub(mcposaTOF_lmon_1, mcposaTOF_mon_2);
    mcposrTOF_mon_2 = rot_apply(mcrotaTOF_mon_2, mctc1);
    mcDEBUG_COMPONENT("TOF_mon_2", mcposaTOF_mon_2, mcrotaTOF_mon_2)
    mccomp_posa[5] = mcposaTOF_mon_2;
    mccomp_posr[5] = mcposrTOF_mon_2;
    mcNCounter[5]  = mcPCounter[5] = mcP2Counter[5] = 0;
    mcAbsorbProp[5]= 0;
    /* Component TOF_lmon_2. */
    SIG_MESSAGE("TOF_lmon_2 (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 9912 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaModerator, mcrotaTOF_lmon_2);
    rot_transpose(mcrotaTOF_mon_2, mctr1);
    rot_mul(mcrotaTOF_lmon_2, mctr1, mcrotrTOF_lmon_2);
    mctc1 = coords_set(
#line 187 "TOFexercise42.instr"
      0,
#line 187 "TOFexercise42.instr"
      0,
#line 187 "TOFexercise42.instr"
      6);
#line 9923 "TOFexercise42.c"
    rot_transpose(mcrotaModerator, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaTOF_lmon_2 = coords_add(mcposaModerator, mctc2);
    mctc1 = coords_sub(mcposaTOF_mon_2, mcposaTOF_lmon_2);
    mcposrTOF_lmon_2 = rot_apply(mcrotaTOF_lmon_2, mctc1);
    mcDEBUG_COMPONENT("TOF_lmon_2", mcposaTOF_lmon_2, mcrotaTOF_lmon_2)
    mccomp_posa[6] = mcposaTOF_lmon_2;
    mccomp_posr[6] = mcposrTOF_lmon_2;
    mcNCounter[6]  = mcPCounter[6] = mcP2Counter[6] = 0;
    mcAbsorbProp[6]= 0;
    /* Component Guide1. */
    SIG_MESSAGE("Guide1 (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 9940 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaModerator, mcrotaGuide1);
    rot_transpose(mcrotaTOF_lmon_2, mctr1);
    rot_mul(mcrotaGuide1, mctr1, mcrotrGuide1);
    mctc1 = coords_set(
#line 196 "TOFexercise42.instr"
      0,
#line 196 "TOFexercise42.instr"
      0,
#line 196 "TOFexercise42.instr"
      6.01);
#line 9951 "TOFexercise42.c"
    rot_transpose(mcrotaModerator, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaGuide1 = coords_add(mcposaModerator, mctc2);
    mctc1 = coords_sub(mcposaTOF_lmon_2, mcposaGuide1);
    mcposrGuide1 = rot_apply(mcrotaGuide1, mctc1);
    mcDEBUG_COMPONENT("Guide1", mcposaGuide1, mcrotaGuide1)
    mccomp_posa[7] = mcposaGuide1;
    mccomp_posr[7] = mcposrGuide1;
    mcNCounter[7]  = mcPCounter[7] = mcP2Counter[7] = 0;
    mcAbsorbProp[7]= 0;
    /* Component Guide2. */
    SIG_MESSAGE("Guide2 (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 9968 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaModerator, mcrotaGuide2);
    rot_transpose(mcrotaGuide1, mctr1);
    rot_mul(mcrotaGuide2, mctr1, mcrotrGuide2);
    mctc1 = coords_set(
#line 210 "TOFexercise42.instr"
      0,
#line 210 "TOFexercise42.instr"
      0,
#line 210 "TOFexercise42.instr"
      6.01);
#line 9979 "TOFexercise42.c"
    rot_transpose(mcrotaModerator, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaGuide2 = coords_add(mcposaModerator, mctc2);
    mctc1 = coords_sub(mcposaGuide1, mcposaGuide2);
    mcposrGuide2 = rot_apply(mcrotaGuide2, mctc1);
    mcDEBUG_COMPONENT("Guide2", mcposaGuide2, mcrotaGuide2)
    mccomp_posa[8] = mcposaGuide2;
    mccomp_posr[8] = mcposrGuide2;
    mcNCounter[8]  = mcPCounter[8] = mcP2Counter[8] = 0;
    mcAbsorbProp[8]= 0;
    /* Component Guide3. */
    SIG_MESSAGE("Guide3 (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 9996 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaModerator, mcrotaGuide3);
    rot_transpose(mcrotaGuide2, mctr1);
    rot_mul(mcrotaGuide3, mctr1, mcrotrGuide3);
    mctc1 = coords_set(
#line 222 "TOFexercise42.instr"
      0,
#line 222 "TOFexercise42.instr"
      0,
#line 222 "TOFexercise42.instr"
      6.01);
#line 10007 "TOFexercise42.c"
    rot_transpose(mcrotaModerator, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaGuide3 = coords_add(mcposaModerator, mctc2);
    mctc1 = coords_sub(mcposaGuide2, mcposaGuide3);
    mcposrGuide3 = rot_apply(mcrotaGuide3, mctc1);
    mcDEBUG_COMPONENT("Guide3", mcposaGuide3, mcrotaGuide3)
    mccomp_posa[9] = mcposaGuide3;
    mccomp_posr[9] = mcposrGuide3;
    mcNCounter[9]  = mcPCounter[9] = mcP2Counter[9] = 0;
    mcAbsorbProp[9]= 0;
    /* Component Guide4a. */
    SIG_MESSAGE("Guide4a (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 10024 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaModerator, mcrotaGuide4a);
    rot_transpose(mcrotaGuide3, mctr1);
    rot_mul(mcrotaGuide4a, mctr1, mcrotrGuide4a);
    mctc1 = coords_set(
#line 230 "TOFexercise42.instr"
      0,
#line 230 "TOFexercise42.instr"
      0,
#line 230 "TOFexercise42.instr"
      6.01);
#line 10035 "TOFexercise42.c"
    rot_transpose(mcrotaModerator, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaGuide4a = coords_add(mcposaModerator, mctc2);
    mctc1 = coords_sub(mcposaGuide3, mcposaGuide4a);
    mcposrGuide4a = rot_apply(mcrotaGuide4a, mctc1);
    mcDEBUG_COMPONENT("Guide4a", mcposaGuide4a, mcrotaGuide4a)
    mccomp_posa[10] = mcposaGuide4a;
    mccomp_posr[10] = mcposrGuide4a;
    mcNCounter[10]  = mcPCounter[10] = mcP2Counter[10] = 0;
    mcAbsorbProp[10]= 0;
    /* Component Guide4b. */
    SIG_MESSAGE("Guide4b (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 10052 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaGuide4a, mcrotaGuide4b);
    rot_transpose(mcrotaGuide4a, mctr1);
    rot_mul(mcrotaGuide4b, mctr1, mcrotrGuide4b);
    mctc1 = coords_set(
#line 238 "TOFexercise42.instr"
      0,
#line 238 "TOFexercise42.instr"
      0,
#line 238 "TOFexercise42.instr"
      mcipguide_bal_d);
#line 10063 "TOFexercise42.c"
    rot_transpose(mcrotaGuide4a, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaGuide4b = coords_add(mcposaGuide4a, mctc2);
    mctc1 = coords_sub(mcposaGuide4a, mcposaGuide4b);
    mcposrGuide4b = rot_apply(mcrotaGuide4b, mctc1);
    mcDEBUG_COMPONENT("Guide4b", mcposaGuide4b, mcrotaGuide4b)
    mccomp_posa[11] = mcposaGuide4b;
    mccomp_posr[11] = mcposrGuide4b;
    mcNCounter[11]  = mcPCounter[11] = mcP2Counter[11] = 0;
    mcAbsorbProp[11]= 0;
    /* Component Guide4c. */
    SIG_MESSAGE("Guide4c (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 10080 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaGuide4b, mcrotaGuide4c);
    rot_transpose(mcrotaGuide4b, mctr1);
    rot_mul(mcrotaGuide4c, mctr1, mcrotrGuide4c);
    mctc1 = coords_set(
#line 246 "TOFexercise42.instr"
      0,
#line 246 "TOFexercise42.instr"
      0,
#line 246 "TOFexercise42.instr"
      guide_bal_ml);
#line 10091 "TOFexercise42.c"
    rot_transpose(mcrotaGuide4b, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaGuide4c = coords_add(mcposaGuide4b, mctc2);
    mctc1 = coords_sub(mcposaGuide4b, mcposaGuide4c);
    mcposrGuide4c = rot_apply(mcrotaGuide4c, mctc1);
    mcDEBUG_COMPONENT("Guide4c", mcposaGuide4c, mcrotaGuide4c)
    mccomp_posa[12] = mcposaGuide4c;
    mccomp_posr[12] = mcposrGuide4c;
    mcNCounter[12]  = mcPCounter[12] = mcP2Counter[12] = 0;
    mcAbsorbProp[12]= 0;
    /* Component TOF_mon_3. */
    SIG_MESSAGE("TOF_mon_3 (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 10108 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaModerator, mcrotaTOF_mon_3);
    rot_transpose(mcrotaGuide4c, mctr1);
    rot_mul(mcrotaTOF_mon_3, mctr1, mcrotrTOF_mon_3);
    mctc1 = coords_set(
#line 257 "TOFexercise42.instr"
      0,
#line 257 "TOFexercise42.instr"
      0,
#line 257 "TOFexercise42.instr"
      149.9);
#line 10119 "TOFexercise42.c"
    rot_transpose(mcrotaModerator, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaTOF_mon_3 = coords_add(mcposaModerator, mctc2);
    mctc1 = coords_sub(mcposaGuide4c, mcposaTOF_mon_3);
    mcposrTOF_mon_3 = rot_apply(mcrotaTOF_mon_3, mctc1);
    mcDEBUG_COMPONENT("TOF_mon_3", mcposaTOF_mon_3, mcrotaTOF_mon_3)
    mccomp_posa[13] = mcposaTOF_mon_3;
    mccomp_posr[13] = mcposrTOF_mon_3;
    mcNCounter[13]  = mcPCounter[13] = mcP2Counter[13] = 0;
    mcAbsorbProp[13]= 0;
    /* Component TOF_lmon_3. */
    SIG_MESSAGE("TOF_lmon_3 (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 10136 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaModerator, mcrotaTOF_lmon_3);
    rot_transpose(mcrotaTOF_mon_3, mctr1);
    rot_mul(mcrotaTOF_lmon_3, mctr1, mcrotrTOF_lmon_3);
    mctc1 = coords_set(
#line 270 "TOFexercise42.instr"
      0,
#line 270 "TOFexercise42.instr"
      0,
#line 270 "TOFexercise42.instr"
      149.9);
#line 10147 "TOFexercise42.c"
    rot_transpose(mcrotaModerator, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaTOF_lmon_3 = coords_add(mcposaModerator, mctc2);
    mctc1 = coords_sub(mcposaTOF_mon_3, mcposaTOF_lmon_3);
    mcposrTOF_lmon_3 = rot_apply(mcrotaTOF_lmon_3, mctc1);
    mcDEBUG_COMPONENT("TOF_lmon_3", mcposaTOF_lmon_3, mcrotaTOF_lmon_3)
    mccomp_posa[14] = mcposaTOF_lmon_3;
    mccomp_posr[14] = mcposrTOF_lmon_3;
    mcNCounter[14]  = mcPCounter[14] = mcP2Counter[14] = 0;
    mcAbsorbProp[14]= 0;
    /* Component DivLambda_mon. */
    SIG_MESSAGE("DivLambda_mon (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 10164 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaModerator, mcrotaDivLambda_mon);
    rot_transpose(mcrotaTOF_lmon_3, mctr1);
    rot_mul(mcrotaDivLambda_mon, mctr1, mcrotrDivLambda_mon);
    mctc1 = coords_set(
#line 281 "TOFexercise42.instr"
      0,
#line 281 "TOFexercise42.instr"
      0,
#line 281 "TOFexercise42.instr"
      149.9);
#line 10175 "TOFexercise42.c"
    rot_transpose(mcrotaModerator, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaDivLambda_mon = coords_add(mcposaModerator, mctc2);
    mctc1 = coords_sub(mcposaTOF_lmon_3, mcposaDivLambda_mon);
    mcposrDivLambda_mon = rot_apply(mcrotaDivLambda_mon, mctc1);
    mcDEBUG_COMPONENT("DivLambda_mon", mcposaDivLambda_mon, mcrotaDivLambda_mon)
    mccomp_posa[15] = mcposaDivLambda_mon;
    mccomp_posr[15] = mcposrDivLambda_mon;
    mcNCounter[15]  = mcPCounter[15] = mcP2Counter[15] = 0;
    mcAbsorbProp[15]= 0;
    /* Component Sample. */
    SIG_MESSAGE("Sample (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 10192 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaModerator, mcrotaSample);
    rot_transpose(mcrotaDivLambda_mon, mctr1);
    rot_mul(mcrotaSample, mctr1, mcrotrSample);
    mctc1 = coords_set(
#line 287 "TOFexercise42.instr"
      0,
#line 287 "TOFexercise42.instr"
      0,
#line 287 "TOFexercise42.instr"
      150);
#line 10203 "TOFexercise42.c"
    rot_transpose(mcrotaModerator, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaSample = coords_add(mcposaModerator, mctc2);
    mctc1 = coords_sub(mcposaDivLambda_mon, mcposaSample);
    mcposrSample = rot_apply(mcrotaSample, mctc1);
    mcDEBUG_COMPONENT("Sample", mcposaSample, mcrotaSample)
    mccomp_posa[16] = mcposaSample;
    mccomp_posr[16] = mcposrSample;
    mcNCounter[16]  = mcPCounter[16] = mcP2Counter[16] = 0;
    mcAbsorbProp[16]= 0;
    /* Component Detector. */
    SIG_MESSAGE("Detector (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 10220 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaSample, mcrotaDetector);
    rot_transpose(mcrotaSample, mctr1);
    rot_mul(mcrotaDetector, mctr1, mcrotrDetector);
    mctc1 = coords_set(
#line 299 "TOFexercise42.instr"
      0,
#line 299 "TOFexercise42.instr"
      0,
#line 299 "TOFexercise42.instr"
      0);
#line 10231 "TOFexercise42.c"
    rot_transpose(mcrotaSample, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaDetector = coords_add(mcposaSample, mctc2);
    mctc1 = coords_sub(mcposaSample, mcposaDetector);
    mcposrDetector = rot_apply(mcrotaDetector, mctc1);
    mcDEBUG_COMPONENT("Detector", mcposaDetector, mcrotaDetector)
    mccomp_posa[17] = mcposaDetector;
    mccomp_posr[17] = mcposrDetector;
    mcNCounter[17]  = mcPCounter[17] = mcP2Counter[17] = 0;
    mcAbsorbProp[17]= 0;
    /* Component arm1. */
    SIG_MESSAGE("arm1 (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
#line 304 "TOFexercise42.instr"
      (0)*DEG2RAD,
#line 304 "TOFexercise42.instr"
      (mcipTOFdetectorAngle)*DEG2RAD,
#line 304 "TOFexercise42.instr"
      (0)*DEG2RAD);
#line 10251 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaSample, mcrotaarm1);
    rot_transpose(mcrotaDetector, mctr1);
    rot_mul(mcrotaarm1, mctr1, mcrotrarm1);
    mctc1 = coords_set(
#line 303 "TOFexercise42.instr"
      0,
#line 303 "TOFexercise42.instr"
      0,
#line 303 "TOFexercise42.instr"
      0);
#line 10262 "TOFexercise42.c"
    rot_transpose(mcrotaSample, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaarm1 = coords_add(mcposaSample, mctc2);
    mctc1 = coords_sub(mcposaDetector, mcposaarm1);
    mcposrarm1 = rot_apply(mcrotaarm1, mctc1);
    mcDEBUG_COMPONENT("arm1", mcposaarm1, mcrotaarm1)
    mccomp_posa[18] = mcposaarm1;
    mccomp_posr[18] = mcposrarm1;
    mcNCounter[18]  = mcPCounter[18] = mcP2Counter[18] = 0;
    mcAbsorbProp[18]= 0;
    /* Component LineDetector. */
    SIG_MESSAGE("LineDetector (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 10279 "TOFexercise42.c"
    rot_mul(mctr1, mcrotaarm1, mcrotaLineDetector);
    rot_transpose(mcrotaarm1, mctr1);
    rot_mul(mcrotaLineDetector, mctr1, mcrotrLineDetector);
    mctc1 = coords_set(
#line 313 "TOFexercise42.instr"
      0,
#line 313 "TOFexercise42.instr"
      0,
#line 313 "TOFexercise42.instr"
      1.01);
#line 10290 "TOFexercise42.c"
    rot_transpose(mcrotaarm1, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaLineDetector = coords_add(mcposaarm1, mctc2);
    mctc1 = coords_sub(mcposaarm1, mcposaLineDetector);
    mcposrLineDetector = rot_apply(mcrotaLineDetector, mctc1);
    mcDEBUG_COMPONENT("LineDetector", mcposaLineDetector, mcrotaLineDetector)
    mccomp_posa[19] = mcposaLineDetector;
    mccomp_posr[19] = mcposrLineDetector;
    mcNCounter[19]  = mcPCounter[19] = mcP2Counter[19] = 0;
    mcAbsorbProp[19]= 0;
  /* Component initializations. */
  /* Initializations for component Origin. */
  SIG_MESSAGE("Origin (Init)");
#line 42 "TOFexercise42.instr"
  mccOrigin_percent = 10;
#line 42 "TOFexercise42.instr"
  mccOrigin_flag_save = 0;
#line 42 "TOFexercise42.instr"
  mccOrigin_minutes = 0;
#line 10310 "TOFexercise42.c"

#define mccompcurname  Origin
#define mccompcurtype  Progress_bar
#define mccompcurindex 1
#define profile mccOrigin_profile
#define IntermediateCnts mccOrigin_IntermediateCnts
#define StartTime mccOrigin_StartTime
#define EndTime mccOrigin_EndTime
#define percent mccOrigin_percent
#define flag_save mccOrigin_flag_save
#define minutes mccOrigin_minutes
#line 61 "/usr/local/lib/mcstas/misc/Progress_bar.comp"
{
  fprintf(stdout, "[%s] Initialize\n", mcinstrument_name);
  if (percent*mcget_ncount()/100 < 1e5) {
    percent=1e5*100.0/mcget_ncount();
  }
}
#line 10329 "TOFexercise42.c"
#undef minutes
#undef flag_save
#undef percent
#undef EndTime
#undef StartTime
#undef IntermediateCnts
#undef profile
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Moderator. */
  SIG_MESSAGE("Moderator (Init)");
#line 119 "TOFexercise42.instr"
  mccModerator_size = 0.02;
#line 120 "TOFexercise42.instr"
  mccModerator_l_low = mciplmin;
#line 121 "TOFexercise42.instr"
  mccModerator_l_high = mciplmax;
#line 122 "TOFexercise42.instr"
  mccModerator_dist = sourcefocus_dist;
#line 123 "TOFexercise42.instr"
  mccModerator_xw = sourcefocus_xw;
#line 124 "TOFexercise42.instr"
  mccModerator_yh = sourcefocus_yh;
#line 125 "TOFexercise42.instr"
  mccModerator_freq = mcipfrequency;
#line 127 "TOFexercise42.instr"
  mccModerator_T = 325;
#line 128 "TOFexercise42.instr"
  mccModerator_tau = 80e-6;
#line 129 "TOFexercise42.instr"
  mccModerator_tau1 = 400e-6;
#line 130 "TOFexercise42.instr"
  mccModerator_tau2 = 12e-6;
#line 126 "TOFexercise42.instr"
  mccModerator_d = mcippulselength;
#line 131 "TOFexercise42.instr"
  mccModerator_n = 20;
#line 132 "TOFexercise42.instr"
  mccModerator_n2 = 5;
#line 133 "TOFexercise42.instr"
  mccModerator_chi2 = 2.5;
#line 134 "TOFexercise42.instr"
  mccModerator_I0 = 13.5e11;
#line 135 "TOFexercise42.instr"
  mccModerator_I2 = 27.6e10;
#line 136 "TOFexercise42.instr"
  mccModerator_branch1 = 0.5;
#line 137 "TOFexercise42.instr"
  mccModerator_branch2 = 0.5;
#line 96 "TOFexercise42.instr"
  mccModerator_branch_tail = 0.14350;
#line 138 "TOFexercise42.instr"
  mccModerator_twopulses = mcipmorepulses;
#line 10385 "TOFexercise42.c"

#define mccompcurname  Moderator
#define mccompcurtype  ESS_moderator_long
#define mccompcurindex 2
#define M mccModerator_M
#define F mccModerator_F
#define l_range mccModerator_l_range
#define w_mult mccModerator_w_mult
#define size mccModerator_size
#define l_low mccModerator_l_low
#define l_high mccModerator_l_high
#define dist mccModerator_dist
#define xw mccModerator_xw
#define yh mccModerator_yh
#define freq mccModerator_freq
#define T mccModerator_T
#define tau mccModerator_tau
#define tau1 mccModerator_tau1
#define tau2 mccModerator_tau2
#define d mccModerator_d
#define n mccModerator_n
#define n2 mccModerator_n2
#define chi2 mccModerator_chi2
#define I0 mccModerator_I0
#define I2 mccModerator_I2
#define branch1 mccModerator_branch1
#define branch2 mccModerator_branch2
#define branch_tail mccModerator_branch_tail
#define twopulses mccModerator_twopulses
#line 117 "/usr/local/lib/mcstas/sources/ESS_moderator_long.comp"
{
  if (n == 1 || n2 == 1 || l_low<=0 || l_high <=0 || dist == 0
    || branch2 == 0 || branch_tail == 0 || tau == 0)
  {
    printf("ESS_moderator_long: %s: Check parameters (lead to Math Error).\n Avoid 0 value for {l_low l_high dist d tau branch1/2/tail} and 1 value for {n n2 branch1/2/tail}\n", NAME_CURRENT_COMP);
    exit(-1);
  }

  if (tau1==0 && !(branch1==1)) {
    branch1=1;
    printf("ESS_moderator_long: %s: WARNING: Setting tau1 to zero implies branch 1=1.\n", NAME_CURRENT_COMP);
  }

  if (twopulses) {
    branchframe = 0.5;
    printf("ESS_moderator_long: %s: INFO: Running with TWO pulses\n", NAME_CURRENT_COMP);
  } else {
    branchframe = 0;
    printf("ESS_moderator_long: %s: INFO: Running with ONE pulse\n", NAME_CURRENT_COMP);
  }

  l_range = l_high-l_low;
  w_mult = size*size*1.0e4;     /* source area correction */
  w_mult *= l_range;            /* wavelength range correction */
  w_mult *= 1.0/mcget_ncount();   /* Correct for number of rays */
  w_mult *= 50.0/3.0;           /* Correct for baseline frequency setting */
}
#line 10443 "TOFexercise42.c"
#undef twopulses
#undef branch_tail
#undef branch2
#undef branch1
#undef I2
#undef I0
#undef chi2
#undef n2
#undef n
#undef d
#undef tau2
#undef tau1
#undef tau
#undef T
#undef freq
#undef yh
#undef xw
#undef dist
#undef l_high
#undef l_low
#undef size
#undef w_mult
#undef l_range
#undef F
#undef M
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component TOF_mon_1. */
  SIG_MESSAGE("TOF_mon_1 (Init)");
#line 46 "TOFexercise42.instr"
  mccTOF_mon_1_xmin = 0;
#line 46 "TOFexercise42.instr"
  mccTOF_mon_1_xmax = 0;
#line 46 "TOFexercise42.instr"
  mccTOF_mon_1_ymin = 0;
#line 46 "TOFexercise42.instr"
  mccTOF_mon_1_ymax = 0;
#line 145 "TOFexercise42.instr"
  mccTOF_mon_1_xwidth = 0.02;
#line 146 "TOFexercise42.instr"
  mccTOF_mon_1_yheight = 0.02;
#line 147 "TOFexercise42.instr"
  mccTOF_mon_1_t0 = mcipTOF1min;
#line 148 "TOFexercise42.instr"
  mccTOF_mon_1_t1 = mcipTOF1max;
#line 46 "TOFexercise42.instr"
  mccTOF_mon_1_dt = 1.0;
#line 149 "TOFexercise42.instr"
  mccTOF_mon_1_restore_neutron = 1;
#line 10495 "TOFexercise42.c"

#define mccompcurname  TOF_mon_1
#define mccompcurtype  TOF_monitor
#define mccompcurindex 3
#define nchan mccTOF_mon_1_nchan
#define filename mccTOF_mon_1_filename
#define TOF_N mccTOF_mon_1_TOF_N
#define TOF_p mccTOF_mon_1_TOF_p
#define TOF_p2 mccTOF_mon_1_TOF_p2
#define t_min mccTOF_mon_1_t_min
#define t_max mccTOF_mon_1_t_max
#define delta_t mccTOF_mon_1_delta_t
#define xmin mccTOF_mon_1_xmin
#define xmax mccTOF_mon_1_xmax
#define ymin mccTOF_mon_1_ymin
#define ymax mccTOF_mon_1_ymax
#define xwidth mccTOF_mon_1_xwidth
#define yheight mccTOF_mon_1_yheight
#define t0 mccTOF_mon_1_t0
#define t1 mccTOF_mon_1_t1
#define dt mccTOF_mon_1_dt
#define restore_neutron mccTOF_mon_1_restore_neutron
#line 59 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
    int i;

    if (xwidth  > 0) { xmax = xwidth/2;  xmin = -xmax; }
    if (yheight > 0) { ymax = yheight/2; ymin = -ymax; }

    if ((xmin >= xmax) || (ymin >= ymax)) {
            printf("TOF_monitor: %s: Null detection area !\n"
                   "ERROR        (xwidth,yheight,xmin,xmax,ymin,ymax). Exiting",
           NAME_CURRENT_COMP);
      exit(0);
    }

    for (i=0; i<nchan; i++)
    {
      TOF_N[i] = 0;
      TOF_p[i] = 0;
      TOF_p2[i] = 0;
    }
    if (t1!=0)
    {
      t_max=t1;
      t_min=t0;
      delta_t=(t_max-t_min)/nchan;
    }
    else
    {
     delta_t=dt;
     t_min=0;
     t_max=nchan*dt+t0;
    }
}
#line 10551 "TOFexercise42.c"
#undef restore_neutron
#undef dt
#undef t1
#undef t0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component TOF_lmon_1. */
  SIG_MESSAGE("TOF_lmon_1 (Init)");
#line 51 "TOFexercise42.instr"
  mccTOF_lmon_1_xmin = 0;
#line 51 "TOFexercise42.instr"
  mccTOF_lmon_1_xmax = 0;
#line 51 "TOFexercise42.instr"
  mccTOF_lmon_1_ymin = 0;
#line 51 "TOFexercise42.instr"
  mccTOF_lmon_1_ymax = 0;
#line 158 "TOFexercise42.instr"
  mccTOF_lmon_1_xwidth = 0.02;
#line 159 "TOFexercise42.instr"
  mccTOF_lmon_1_yheight = 0.02;
#line 160 "TOFexercise42.instr"
  mccTOF_lmon_1_lambda_0 = mciplmin;
#line 161 "TOFexercise42.instr"
  mccTOF_lmon_1_lambda_1 = mciplmax;
#line 162 "TOFexercise42.instr"
  mccTOF_lmon_1_restore_neutron = 1;
#line 10594 "TOFexercise42.c"

#define mccompcurname  TOF_lmon_1
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 4
#define nlam mccTOF_lmon_1_nlam
#define nt mccTOF_lmon_1_nt
#define filename mccTOF_lmon_1_filename
#define t_0 mccTOF_lmon_1_t_0
#define t_1 mccTOF_lmon_1_t_1
#define tt_0 mccTOF_lmon_1_tt_0
#define tt_1 mccTOF_lmon_1_tt_1
#define TOFL_N mccTOF_lmon_1_TOFL_N
#define TOFL_p mccTOF_lmon_1_TOFL_p
#define TOFL_p2 mccTOF_lmon_1_TOFL_p2
#define xmin mccTOF_lmon_1_xmin
#define xmax mccTOF_lmon_1_xmax
#define ymin mccTOF_lmon_1_ymin
#define ymax mccTOF_lmon_1_ymax
#define xwidth mccTOF_lmon_1_xwidth
#define yheight mccTOF_lmon_1_yheight
#define lambda_0 mccTOF_lmon_1_lambda_0
#define lambda_1 mccTOF_lmon_1_lambda_1
#define restore_neutron mccTOF_lmon_1_restore_neutron
#line 63 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
{
    int i,j;

    if (xwidth  > 0) { xmax = xwidth/2;  xmin = -xmax; }
    if (yheight > 0) { ymax = yheight/2; ymin = -ymax; }

    if ((xmin >= xmax) || (ymin >= ymax)) {
            printf("TOFLambda_monitor: %s: Null detection area !\n"
                   "ERROR              (xwidth,yheight,xmin,xmax,ymin,ymax). Exiting",
           NAME_CURRENT_COMP);
      exit(0);
    }

    tt_0 = t_0*1e-6;
    tt_1 = t_1*1e-6;
    for (i=0; i<nlam; i++)
     for (j=0; j<nt; j++)
     {
      TOFL_N[j][i] = 0;
      TOFL_p[j][i] = 0;
      TOFL_p2[j][i] = 0;
     }
}
#line 10642 "TOFexercise42.c"
#undef restore_neutron
#undef lambda_1
#undef lambda_0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component TOF_mon_2. */
  SIG_MESSAGE("TOF_mon_2 (Init)");
#line 46 "TOFexercise42.instr"
  mccTOF_mon_2_xmin = 0;
#line 46 "TOFexercise42.instr"
  mccTOF_mon_2_xmax = 0;
#line 46 "TOFexercise42.instr"
  mccTOF_mon_2_ymin = 0;
#line 46 "TOFexercise42.instr"
  mccTOF_mon_2_ymax = 0;
#line 169 "TOFexercise42.instr"
  mccTOF_mon_2_xwidth = 0.02;
#line 170 "TOFexercise42.instr"
  mccTOF_mon_2_yheight = 0.02;
#line 171 "TOFexercise42.instr"
  mccTOF_mon_2_t0 = mcipTOF2min;
#line 172 "TOFexercise42.instr"
  mccTOF_mon_2_t1 = mcipTOF2max;
#line 46 "TOFexercise42.instr"
  mccTOF_mon_2_dt = 1.0;
#line 173 "TOFexercise42.instr"
  mccTOF_mon_2_restore_neutron = 1;
#line 10688 "TOFexercise42.c"

#define mccompcurname  TOF_mon_2
#define mccompcurtype  TOF_monitor
#define mccompcurindex 5
#define nchan mccTOF_mon_2_nchan
#define filename mccTOF_mon_2_filename
#define TOF_N mccTOF_mon_2_TOF_N
#define TOF_p mccTOF_mon_2_TOF_p
#define TOF_p2 mccTOF_mon_2_TOF_p2
#define t_min mccTOF_mon_2_t_min
#define t_max mccTOF_mon_2_t_max
#define delta_t mccTOF_mon_2_delta_t
#define xmin mccTOF_mon_2_xmin
#define xmax mccTOF_mon_2_xmax
#define ymin mccTOF_mon_2_ymin
#define ymax mccTOF_mon_2_ymax
#define xwidth mccTOF_mon_2_xwidth
#define yheight mccTOF_mon_2_yheight
#define t0 mccTOF_mon_2_t0
#define t1 mccTOF_mon_2_t1
#define dt mccTOF_mon_2_dt
#define restore_neutron mccTOF_mon_2_restore_neutron
#line 59 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
    int i;

    if (xwidth  > 0) { xmax = xwidth/2;  xmin = -xmax; }
    if (yheight > 0) { ymax = yheight/2; ymin = -ymax; }

    if ((xmin >= xmax) || (ymin >= ymax)) {
            printf("TOF_monitor: %s: Null detection area !\n"
                   "ERROR        (xwidth,yheight,xmin,xmax,ymin,ymax). Exiting",
           NAME_CURRENT_COMP);
      exit(0);
    }

    for (i=0; i<nchan; i++)
    {
      TOF_N[i] = 0;
      TOF_p[i] = 0;
      TOF_p2[i] = 0;
    }
    if (t1!=0)
    {
      t_max=t1;
      t_min=t0;
      delta_t=(t_max-t_min)/nchan;
    }
    else
    {
     delta_t=dt;
     t_min=0;
     t_max=nchan*dt+t0;
    }
}
#line 10744 "TOFexercise42.c"
#undef restore_neutron
#undef dt
#undef t1
#undef t0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component TOF_lmon_2. */
  SIG_MESSAGE("TOF_lmon_2 (Init)");
#line 51 "TOFexercise42.instr"
  mccTOF_lmon_2_xmin = 0;
#line 51 "TOFexercise42.instr"
  mccTOF_lmon_2_xmax = 0;
#line 51 "TOFexercise42.instr"
  mccTOF_lmon_2_ymin = 0;
#line 51 "TOFexercise42.instr"
  mccTOF_lmon_2_ymax = 0;
#line 182 "TOFexercise42.instr"
  mccTOF_lmon_2_xwidth = 0.02;
#line 183 "TOFexercise42.instr"
  mccTOF_lmon_2_yheight = 0.02;
#line 184 "TOFexercise42.instr"
  mccTOF_lmon_2_lambda_0 = mciplmin;
#line 185 "TOFexercise42.instr"
  mccTOF_lmon_2_lambda_1 = mciplmax;
#line 186 "TOFexercise42.instr"
  mccTOF_lmon_2_restore_neutron = 1;
#line 10787 "TOFexercise42.c"

#define mccompcurname  TOF_lmon_2
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 6
#define nlam mccTOF_lmon_2_nlam
#define nt mccTOF_lmon_2_nt
#define filename mccTOF_lmon_2_filename
#define t_0 mccTOF_lmon_2_t_0
#define t_1 mccTOF_lmon_2_t_1
#define tt_0 mccTOF_lmon_2_tt_0
#define tt_1 mccTOF_lmon_2_tt_1
#define TOFL_N mccTOF_lmon_2_TOFL_N
#define TOFL_p mccTOF_lmon_2_TOFL_p
#define TOFL_p2 mccTOF_lmon_2_TOFL_p2
#define xmin mccTOF_lmon_2_xmin
#define xmax mccTOF_lmon_2_xmax
#define ymin mccTOF_lmon_2_ymin
#define ymax mccTOF_lmon_2_ymax
#define xwidth mccTOF_lmon_2_xwidth
#define yheight mccTOF_lmon_2_yheight
#define lambda_0 mccTOF_lmon_2_lambda_0
#define lambda_1 mccTOF_lmon_2_lambda_1
#define restore_neutron mccTOF_lmon_2_restore_neutron
#line 63 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
{
    int i,j;

    if (xwidth  > 0) { xmax = xwidth/2;  xmin = -xmax; }
    if (yheight > 0) { ymax = yheight/2; ymin = -ymax; }

    if ((xmin >= xmax) || (ymin >= ymax)) {
            printf("TOFLambda_monitor: %s: Null detection area !\n"
                   "ERROR              (xwidth,yheight,xmin,xmax,ymin,ymax). Exiting",
           NAME_CURRENT_COMP);
      exit(0);
    }

    tt_0 = t_0*1e-6;
    tt_1 = t_1*1e-6;
    for (i=0; i<nlam; i++)
     for (j=0; j<nt; j++)
     {
      TOFL_N[j][i] = 0;
      TOFL_p[j][i] = 0;
      TOFL_p2[j][i] = 0;
     }
}
#line 10835 "TOFexercise42.c"
#undef restore_neutron
#undef lambda_1
#undef lambda_0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Guide1. */
  SIG_MESSAGE("Guide1 (Init)");
#line 191 "TOFexercise42.instr"
  mccGuide1_w1 = 0.05;
#line 192 "TOFexercise42.instr"
  mccGuide1_h1 = 0.05;
#line 193 "TOFexercise42.instr"
  mccGuide1_w2 = 0.05;
#line 194 "TOFexercise42.instr"
  mccGuide1_h2 = 0.05;
#line 195 "TOFexercise42.instr"
  mccGuide1_l = 141.9;
#line 61 "TOFexercise42.instr"
  mccGuide1_R0 = 0.99;
#line 61 "TOFexercise42.instr"
  mccGuide1_Qc = 0.0219;
#line 61 "TOFexercise42.instr"
  mccGuide1_alpha = 6.07;
#line 61 "TOFexercise42.instr"
  mccGuide1_m = 2;
#line 61 "TOFexercise42.instr"
  mccGuide1_W = 0.003;
#line 10881 "TOFexercise42.c"

#define mccompcurname  Guide1
#define mccompcurtype  Guide
#define mccompcurindex 7
#define reflect mccGuide1_reflect
#define pTable mccGuide1_pTable
#define w1 mccGuide1_w1
#define h1 mccGuide1_h1
#define w2 mccGuide1_w2
#define h2 mccGuide1_h2
#define l mccGuide1_l
#define R0 mccGuide1_R0
#define Qc mccGuide1_Qc
#define alpha mccGuide1_alpha
#define m mccGuide1_m
#define W mccGuide1_W
#line 76 "/usr/local/lib/mcstas/optics/Guide.comp"
{
  if (mcgravitation) fprintf(stderr,"WARNING: Guide: %s: "
    "This component produces wrong results with gravitation !\n"
    "Use Guide_gravity.\n",
    NAME_CURRENT_COMP);

  if (reflect && strlen(reflect)) {
    if (Table_Read(&pTable, reflect, 1) <= 0) /* read 1st block data from file into pTable */
      exit(fprintf(stderr,"Guide: %s: can not read file %s\n", NAME_CURRENT_COMP, reflect));
  } else {
    if (W < 0 || R0 < 0 || Qc < 0 || m < 0)
    { fprintf(stderr,"Guide: %s: W R0 Qc must be >0.\n", NAME_CURRENT_COMP);
      exit(-1); }
    if (m < 1 && m != 0) fprintf(stderr,"WARNING: Guide: %s: m < 1 behaves as if m=1.\n",
      NAME_CURRENT_COMP);
  }
}
#line 10916 "TOFexercise42.c"
#undef W
#undef m
#undef alpha
#undef Qc
#undef R0
#undef l
#undef h2
#undef w2
#undef h1
#undef w1
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Guide2. */
  SIG_MESSAGE("Guide2 (Init)");
#line 201 "TOFexercise42.instr"
  mccGuide2_w1 = 0.05;
#line 202 "TOFexercise42.instr"
  mccGuide2_h1 = 0.05;
#line 209 "TOFexercise42.instr"
  mccGuide2_l = 141.9;
#line 203 "TOFexercise42.instr"
  mccGuide2_linw = mcipguide_ell_fdin;
#line 206 "TOFexercise42.instr"
  mccGuide2_loutw = mcipguide_ell_fdout;
#line 204 "TOFexercise42.instr"
  mccGuide2_linh = mcipguide_ell_fdin;
#line 205 "TOFexercise42.instr"
  mccGuide2_louth = mcipguide_ell_fdout;
#line 98 "TOFexercise42.instr"
  mccGuide2_R0 = 0.99;
#line 99 "TOFexercise42.instr"
  mccGuide2_Qcx = 0.021;
#line 99 "TOFexercise42.instr"
  mccGuide2_Qcy = 0.021;
#line 99 "TOFexercise42.instr"
  mccGuide2_alphax = 6.07;
#line 99 "TOFexercise42.instr"
  mccGuide2_alphay = 6.07;
#line 99 "TOFexercise42.instr"
  mccGuide2_W = 0.003;
#line 207 "TOFexercise42.instr"
  mccGuide2_mx = 2;
#line 208 "TOFexercise42.instr"
  mccGuide2_my = 2;
#line 10965 "TOFexercise42.c"

#define mccompcurname  Guide2
#define mccompcurtype  Guide_tapering
#define mccompcurindex 8
#define option mccGuide2_option
#define segno mccGuide2_segno
#define w1c mccGuide2_w1c
#define w2c mccGuide2_w2c
#define ww mccGuide2_ww
#define hh mccGuide2_hh
#define whalf mccGuide2_whalf
#define hhalf mccGuide2_hhalf
#define lwhalf mccGuide2_lwhalf
#define lhhalf mccGuide2_lhhalf
#define h1_in mccGuide2_h1_in
#define h2_out mccGuide2_h2_out
#define w1_in mccGuide2_w1_in
#define w2_out mccGuide2_w2_out
#define l_seg mccGuide2_l_seg
#define seg mccGuide2_seg
#define h12 mccGuide2_h12
#define h2 mccGuide2_h2
#define w12 mccGuide2_w12
#define w2 mccGuide2_w2
#define a_ell_q mccGuide2_a_ell_q
#define b_ell_q mccGuide2_b_ell_q
#define lbw mccGuide2_lbw
#define lbh mccGuide2_lbh
#define mxi mccGuide2_mxi
#define u1 mccGuide2_u1
#define u2 mccGuide2_u2
#define div1 mccGuide2_div1
#define p2_para mccGuide2_p2_para
#define test mccGuide2_test
#define Div1 mccGuide2_Div1
#define i mccGuide2_i
#define ii mccGuide2_ii
#define seg mccGuide2_seg
#define fu mccGuide2_fu
#define pos mccGuide2_pos
#define file_name mccGuide2_file_name
#define ep mccGuide2_ep
#define num mccGuide2_num
#define w1 mccGuide2_w1
#define h1 mccGuide2_h1
#define l mccGuide2_l
#define linw mccGuide2_linw
#define loutw mccGuide2_loutw
#define linh mccGuide2_linh
#define louth mccGuide2_louth
#define R0 mccGuide2_R0
#define Qcx mccGuide2_Qcx
#define Qcy mccGuide2_Qcy
#define alphax mccGuide2_alphax
#define alphay mccGuide2_alphay
#define W mccGuide2_W
#define mx mccGuide2_mx
#define my mccGuide2_my
#line 127 "/usr/local/lib/mcstas/optics/Guide_tapering.comp"
{
  // dynamic memory allocation is good
  w1c = (double*)malloc(sizeof(double)*segno);
  w2c = (double*)malloc(sizeof(double)*segno);
  ww = (double*)malloc(sizeof(double)*segno);
  hh = (double*)malloc(sizeof(double)*segno);
  whalf = (double*)malloc(sizeof(double)*segno);
  hhalf = (double*)malloc(sizeof(double)*segno);
  lwhalf = (double*)malloc(sizeof(double)*segno);
  lhhalf = (double*)malloc(sizeof(double)*segno);
  h1_in = (double*)malloc(sizeof(double)*(segno+1));
  h2_out = (double*)malloc(sizeof(double)*(segno+1));
  w1_in = (double*)malloc(sizeof(double)*(segno+1));
  w2_out = (double*)malloc(sizeof(double)*(segno+1));

  struct para {
    char st[128];
  } segment[800];
  if (W <=0)
  {
    fprintf(stderr,"Component: %s (Guide_tapering) W must \n", NAME_CURRENT_COMP);
    fprintf(stderr,"           be positive\n");
    exit(-1);
  }
  if (l <= 0)
  {
    fprintf(stderr,"Component: %s (Guide_tapering) real guide length \n",
    NAME_CURRENT_COMP);
    fprintf(stderr,"           is <= ZERO ! \n");
    exit(-1);
  }
  if (mcgravitation) fprintf(stderr,"WARNING: Guide_tapering: %s: "
    "This component produces wrong results with gravitation !\n"
    "Use Guide_gravity.\n",
    NAME_CURRENT_COMP);
  seg=segno;
  l_seg=l/(seg);
  h12 = h1/2.0;
  if (option != NULL)
  {
     fu = (char*)malloc(sizeof(char)*(strlen(option)+1));
     strcpy(fu,option);
  } else {
     exit(-1);
  }
  if (!strcmp(fu,"elliptical"))
  {
     /* calculate parameter b of elliptical equestion - vertical mirrors */
     /* (l+linh+louth) -> distance between focal points */
     /*  printf("A1 \n"); */
     lbh = l + linh + louth;
     if (linh == 0 && louth == 0 )
     {
        /* plane mirrors (vertical) */
        b_ell_q = 0;
        h2 = h1;
     } else {
        /* elliptical mirrors */
        u1 = sqrt((linh*linh)+(h12*h12));
        u2 = sqrt((h12*h12) + ((l+louth)*(l+louth)));
        a_ell_q = ((u1 + u2)/2.0)*((u1 + u2)/2.0);
        b_ell_q = a_ell_q - ((lbh/2.0)*(lbh/2.0));
        /* calculate heigth of guide exit (h2) */
        div1 = ((lbh/2.0-louth)*(lbh/2.0-louth))/a_ell_q;
        h2 = sqrt(b_ell_q*(1.0-div1));
        h2 = h2*2.0;
     }
  } else if (!strcmp(fu,"parabolical")) {
     if ((linh > 0) && (louth > 0))
     {
       fprintf(stderr,"Component: %s (Guide_tapering) Two focal\n",NAME_CURRENT_COMP);
       fprintf(stderr,"            points lout and linh are not allowed! \n");
        free(fu);exit(-1);
     }
     if (louth == 0 && linh == 0)
     {
        /* plane mirrors (vertical) */
        h2 = h1;
     } else {
        /* parabolical mirrors */
        if (linh == 0)
        {
           Div1=((2.0*louth+2.0*l)*(2.0*louth+2.0*l))/4.0;
           p2_para=((sqrt(Div1+(h12*h12)))-(louth+l))*2.0;
           /* calculate heigth of guide exit (h2) */
           h2 = sqrt(p2_para*(louth+p2_para/4.0));
           h2 = h2*2.0;
         } else {
            /* anti-trompete */
           Div1=((2.0*linh)*(2.0*linh))/4.0;
           p2_para=((sqrt(Div1+(h12*h12)))-linh)*2.0;
           /* calculate heigth of guide exit (h2) */
           h2 = sqrt(p2_para*(l+linh+p2_para/4.0));
           h2 = h2*2.0;
         }
     }
  } else if (!strncmp(fu,"file",4)) {
     pos = strtok(fu,"=");
     while (pos=strtok(0,"="))
     {
        strcpy(file_name,pos);
     }
     if ((num=fopen(file_name,"r")) == NULL)
     {
        fprintf(stderr,"Component: %s (Guide_tapering)\n",NAME_CURRENT_COMP);
        fprintf(stderr,"           File %s not found! \n", file_name);
         free(fu);exit(-1);
     } else {
        ii = 0;
        while (!feof(num))
        {
          fgets(segment[ii].st,128,num);
          if (ii >  799) {
             fprintf(stderr,"%s: Number of segments is limited to 800 !! \n",NAME_CURRENT_COMP);
              free(fu);exit(-1);
          }
          ii++;
        }
        fclose(num);
        ii--;
     }
     seg = ii-3;
     l_seg=l/seg;
     for (i=3;i<ii;i++)
     {
        if (strlen(segment[i].st) < 4)
        {
          fprintf(stderr,"Component: %s (Guide_tapering)\n",NAME_CURRENT_COMP);
          fprintf(stderr,"           Data Format Error! \n");
          free(fu);exit(-1);
        }
        h1_in[i-3] = strtod(strtok(segment[i].st," "), &ep);
        h2_out[i-3] = strtod(strtok(0," "), &ep);
        w1_in[i-3] = strtod(strtok(0," "), &ep);
        w2_out[i-3] = strtod(strtok(0," "), &ep);
     }
     h1 = h1_in[0];
     h2 = h2_out[seg-1];
     w1 = w1_in[0];
     w2 = w2_out[seg-1];
     for (i=0;i<seg;i++)
     {
      fprintf(stderr,"%d: %lf %lf %lf %lf \n",i,h1_in[i],h2_out[i],w1_in[i],w2_out[i]);
     }
  } else {
     fprintf(stderr,"Component: %s (Guide_tapering)\n",NAME_CURRENT_COMP);
     fprintf(stderr,"           Unknown KEYWORD: %s \n", fu);
     free(fu);exit(-1);
  }
  fprintf(stderr,"Component: %s (Guide_tapering)\n",NAME_CURRENT_COMP);
  fprintf(stderr,"           Height at the guide exit (h2): %lf \n", h2);
  if (h2 <= 0)
  {
   fprintf(stderr,"Component: %s (Guide_tapering)\n", NAME_CURRENT_COMP);
   fprintf(stderr,"           Height at the guide exit (h2) was calculated\n");
   fprintf(stderr,"           <=0; Please change the parameter h1 and/or\n");
   fprintf(stderr,"           linh and/or louth! \n");
    free(fu);exit(-1);
  }
  if (!strcmp(fu,"elliptical"))
  {
     h1_in[0] = h1;
     for (i=1;i<seg;i++)
     {
       if (b_ell_q == 0)
       {
         h1_in[i]=h1;
       } else {
         mxi = (((lbh/2.0)-linh) - (l_seg * i));
         h1_in[i] = (sqrt((1.0-((mxi*mxi)/a_ell_q))*b_ell_q))*2.0;
       }
     h2_out[i-1] = h1_in[i];
     }
     h2_out[seg-1]=h2;
  } else if (!strcmp(fu,"parabolical")) {
     h1_in[0] = h1;
     ii=seg-1;
     if (louth == 0 && linh == 0)
     {
        for (i=1;i<(seg+1);i++)
        {
           h1_in[i]=h1;
           ii=ii-1;
           h2_out[i-1] = h1_in[i];
        }
     } else {
        if ((linh == 0) && (louth > 0))
        {
           for (i=1;i<(seg+1);i++)
           {
             h1_in[i] = (sqrt((p2_para/4.0+louth+(l_seg*ii))*p2_para))*2.0;
             ii=ii-1;
             h2_out[i-1] = h1_in[i];
           }
        } else {
           for (i=1;i<(seg+1);i++)
           {
             h1_in[i] = (sqrt((p2_para/4.0+linh+(l_seg*i))*p2_para))*2.0;
             h2_out[i-1] = h1_in[i];
           }
        }
     }
  }
  /* compute each value for horizontal mirrors */
  w12 = w1/2.0;
  if (!strcmp(fu,"elliptical"))
  {
    /* calculate lbw the distance between focal points of horizontal mirrors */
    lbw = l + linw + loutw;
    /* calculate parameter b of elliptical equestion - horizontal mirrors */
    if (linw == 0 && loutw == 0 )
    {
       /* plane mirrors (horizontal) */
       b_ell_q = 0;
       w2 = w1;
    } else {
       /* elliptical mirrors */
       u1 = sqrt((linw*linw)+(w12*w12));
       u2 = sqrt((w12*w12) + ((l+loutw)*(l+loutw)));
       a_ell_q = ((u1 + u2)/2.0)*((u1 + u2)/2.0);
       b_ell_q = a_ell_q - ((lbw/2.0)*(lbw/2.0));
       /* calculate weigth of guide exit (w2) */
       div1 = ((lbw/2.0-loutw)*(lbw/2.0-loutw))/a_ell_q;
       w2 = sqrt(b_ell_q*(1.0-div1));
       w2 = w2*2.0;
     }
  } else if (!strcmp(fu,"parabolical")) {
     if ((linw > 0) && (loutw > 0))
     {
       fprintf(stderr,"Component: %s (Guide_tapering) Two focal\n",NAME_CURRENT_COMP);
       fprintf(stderr,"           points linw and loutw are not allowed! \n");
         free(fu);exit(-1);
     }
     if (loutw == 0 && linw == 0)
     {
        /* plane mirrors (horizontal) */
        w2 = w1;
     } else {
       if (linw == 0)
       {
          /* parabolical mirrors */
          Div1=((2.0*loutw+2.0*l)*(2.0*loutw+2.0*l))/4.0;
          p2_para=((sqrt(Div1+(w12*w12)))-(loutw+l))*2.0;
          /* calculate weigth of guide exit (w2) */
          w2 = sqrt(p2_para*(loutw+p2_para/4.0));
          w2 = w2*2.0;
       } else {
          /* anti-trompete */
          Div1=((2.0*linw)*(2.0*linw))/4.0;
          p2_para=((sqrt(Div1+(w12*w12)))-linw)*2.0;
          /* calculate heigth of guide exit (w2) */
          w2 = sqrt(p2_para*(l+linw+p2_para/4.0));
          w2 = w2*2.0;
       }
     }
  }
  fprintf(stderr,"Component: %s (Guide_tapering)\n",NAME_CURRENT_COMP);
  fprintf(stderr,"           Weigth at the guide exit (w2): %lf \n", w2);
  if (w2 <= 0)
  {
   fprintf(stderr,"Component: %s (Guide_tapering)\n", NAME_CURRENT_COMP);
   fprintf(stderr,"           Weigth at the guide exit (w2) was calculated\n");
   fprintf(stderr,"           <=0; Please change the parameter w1 and/or\n");
   fprintf(stderr,"           l! \n");
    free(fu);exit(-1);
  }
  if (!strcmp(fu,"elliptical"))
  {
     w1_in[0]=w1;
     for (i=1;i<seg;i++)
     {
       if (b_ell_q == 0)
       {
         w1_in[i]=w1;
       } else {
         mxi = (((lbw/2.0)-linw) - (l_seg * i));
         w1_in[i] = (sqrt((1.0-((mxi*mxi)/a_ell_q))*b_ell_q))*2.0;
       }
       w2_out[i-1] = w1_in[i];
     }
     w2_out[seg-1]=w2;
  } else if (!strcmp(fu,"parabolical")) {
     w1_in[0]=w1;
     ii=seg-1;
     if (loutw == 0 && linw == 0)
     {
        for (i=1;i<(seg+1);i++)
        {
           w1_in[i]=w1;
           ii=ii-1;
           w2_out[i-1] = w1_in[i];
        }
     } else {
        if ((linw == 0) && (loutw > 0))
        {
           for (i=1;i<(seg+1);i++)
           {
             w1_in[i] = (sqrt((p2_para/4+loutw+(l_seg*ii))*p2_para))*2;
             ii=ii-1;
             w2_out[i-1] = w1_in[i];
           }
        } else {
           for (i=1;i<(seg+1);i++)
           {
             w1_in[i] = (sqrt((p2_para/4+linw+(l_seg*i))*p2_para))*2;
             w2_out[i-1] = w1_in[i];
           }
        }
     }
  }
  free(fu);
  for (i=0;i<seg;i++)
  {
    w1c[i] = w1_in[i];
    w2c[i] = w2_out[i];
    ww[i] = .5*(w2c[i] - w1c[i]);
    hh[i] = .5*(h2_out[i] - h1_in[i]);
    whalf[i] = .5*w1c[i];
    hhalf[i] = .5*h1_in[i];
    lwhalf[i] = l_seg*whalf[i];
    lhhalf[i] = l_seg*hhalf[i];
  }
}
#line 11348 "TOFexercise42.c"
#undef my
#undef mx
#undef W
#undef alphay
#undef alphax
#undef Qcy
#undef Qcx
#undef R0
#undef louth
#undef linh
#undef loutw
#undef linw
#undef l
#undef h1
#undef w1
#undef num
#undef ep
#undef file_name
#undef pos
#undef fu
#undef seg
#undef ii
#undef i
#undef Div1
#undef test
#undef p2_para
#undef div1
#undef u2
#undef u1
#undef mxi
#undef lbh
#undef lbw
#undef b_ell_q
#undef a_ell_q
#undef w2
#undef w12
#undef h2
#undef h12
#undef seg
#undef l_seg
#undef w2_out
#undef w1_in
#undef h2_out
#undef h1_in
#undef lhhalf
#undef lwhalf
#undef hhalf
#undef whalf
#undef hh
#undef ww
#undef w2c
#undef w1c
#undef segno
#undef option
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Guide3. */
  SIG_MESSAGE("Guide3 (Init)");
#line 215 "TOFexercise42.instr"
  mccGuide3_w1 = 0.05;
#line 216 "TOFexercise42.instr"
  mccGuide3_h1 = 0.05;
#line 221 "TOFexercise42.instr"
  mccGuide3_l = 141.9;
#line 98 "TOFexercise42.instr"
  mccGuide3_linw = 0;
#line 218 "TOFexercise42.instr"
  mccGuide3_loutw = mcipguide_par_fdout;
#line 98 "TOFexercise42.instr"
  mccGuide3_linh = 0;
#line 217 "TOFexercise42.instr"
  mccGuide3_louth = mcipguide_par_fdout;
#line 98 "TOFexercise42.instr"
  mccGuide3_R0 = 0.99;
#line 99 "TOFexercise42.instr"
  mccGuide3_Qcx = 0.021;
#line 99 "TOFexercise42.instr"
  mccGuide3_Qcy = 0.021;
#line 99 "TOFexercise42.instr"
  mccGuide3_alphax = 6.07;
#line 99 "TOFexercise42.instr"
  mccGuide3_alphay = 6.07;
#line 99 "TOFexercise42.instr"
  mccGuide3_W = 0.003;
#line 219 "TOFexercise42.instr"
  mccGuide3_mx = 2;
#line 220 "TOFexercise42.instr"
  mccGuide3_my = 2;
#line 11439 "TOFexercise42.c"

#define mccompcurname  Guide3
#define mccompcurtype  Guide_tapering
#define mccompcurindex 9
#define option mccGuide3_option
#define segno mccGuide3_segno
#define w1c mccGuide3_w1c
#define w2c mccGuide3_w2c
#define ww mccGuide3_ww
#define hh mccGuide3_hh
#define whalf mccGuide3_whalf
#define hhalf mccGuide3_hhalf
#define lwhalf mccGuide3_lwhalf
#define lhhalf mccGuide3_lhhalf
#define h1_in mccGuide3_h1_in
#define h2_out mccGuide3_h2_out
#define w1_in mccGuide3_w1_in
#define w2_out mccGuide3_w2_out
#define l_seg mccGuide3_l_seg
#define seg mccGuide3_seg
#define h12 mccGuide3_h12
#define h2 mccGuide3_h2
#define w12 mccGuide3_w12
#define w2 mccGuide3_w2
#define a_ell_q mccGuide3_a_ell_q
#define b_ell_q mccGuide3_b_ell_q
#define lbw mccGuide3_lbw
#define lbh mccGuide3_lbh
#define mxi mccGuide3_mxi
#define u1 mccGuide3_u1
#define u2 mccGuide3_u2
#define div1 mccGuide3_div1
#define p2_para mccGuide3_p2_para
#define test mccGuide3_test
#define Div1 mccGuide3_Div1
#define i mccGuide3_i
#define ii mccGuide3_ii
#define seg mccGuide3_seg
#define fu mccGuide3_fu
#define pos mccGuide3_pos
#define file_name mccGuide3_file_name
#define ep mccGuide3_ep
#define num mccGuide3_num
#define w1 mccGuide3_w1
#define h1 mccGuide3_h1
#define l mccGuide3_l
#define linw mccGuide3_linw
#define loutw mccGuide3_loutw
#define linh mccGuide3_linh
#define louth mccGuide3_louth
#define R0 mccGuide3_R0
#define Qcx mccGuide3_Qcx
#define Qcy mccGuide3_Qcy
#define alphax mccGuide3_alphax
#define alphay mccGuide3_alphay
#define W mccGuide3_W
#define mx mccGuide3_mx
#define my mccGuide3_my
#line 127 "/usr/local/lib/mcstas/optics/Guide_tapering.comp"
{
  // dynamic memory allocation is good
  w1c = (double*)malloc(sizeof(double)*segno);
  w2c = (double*)malloc(sizeof(double)*segno);
  ww = (double*)malloc(sizeof(double)*segno);
  hh = (double*)malloc(sizeof(double)*segno);
  whalf = (double*)malloc(sizeof(double)*segno);
  hhalf = (double*)malloc(sizeof(double)*segno);
  lwhalf = (double*)malloc(sizeof(double)*segno);
  lhhalf = (double*)malloc(sizeof(double)*segno);
  h1_in = (double*)malloc(sizeof(double)*(segno+1));
  h2_out = (double*)malloc(sizeof(double)*(segno+1));
  w1_in = (double*)malloc(sizeof(double)*(segno+1));
  w2_out = (double*)malloc(sizeof(double)*(segno+1));

  struct para {
    char st[128];
  } segment[800];
  if (W <=0)
  {
    fprintf(stderr,"Component: %s (Guide_tapering) W must \n", NAME_CURRENT_COMP);
    fprintf(stderr,"           be positive\n");
    exit(-1);
  }
  if (l <= 0)
  {
    fprintf(stderr,"Component: %s (Guide_tapering) real guide length \n",
    NAME_CURRENT_COMP);
    fprintf(stderr,"           is <= ZERO ! \n");
    exit(-1);
  }
  if (mcgravitation) fprintf(stderr,"WARNING: Guide_tapering: %s: "
    "This component produces wrong results with gravitation !\n"
    "Use Guide_gravity.\n",
    NAME_CURRENT_COMP);
  seg=segno;
  l_seg=l/(seg);
  h12 = h1/2.0;
  if (option != NULL)
  {
     fu = (char*)malloc(sizeof(char)*(strlen(option)+1));
     strcpy(fu,option);
  } else {
     exit(-1);
  }
  if (!strcmp(fu,"elliptical"))
  {
     /* calculate parameter b of elliptical equestion - vertical mirrors */
     /* (l+linh+louth) -> distance between focal points */
     /*  printf("A1 \n"); */
     lbh = l + linh + louth;
     if (linh == 0 && louth == 0 )
     {
        /* plane mirrors (vertical) */
        b_ell_q = 0;
        h2 = h1;
     } else {
        /* elliptical mirrors */
        u1 = sqrt((linh*linh)+(h12*h12));
        u2 = sqrt((h12*h12) + ((l+louth)*(l+louth)));
        a_ell_q = ((u1 + u2)/2.0)*((u1 + u2)/2.0);
        b_ell_q = a_ell_q - ((lbh/2.0)*(lbh/2.0));
        /* calculate heigth of guide exit (h2) */
        div1 = ((lbh/2.0-louth)*(lbh/2.0-louth))/a_ell_q;
        h2 = sqrt(b_ell_q*(1.0-div1));
        h2 = h2*2.0;
     }
  } else if (!strcmp(fu,"parabolical")) {
     if ((linh > 0) && (louth > 0))
     {
       fprintf(stderr,"Component: %s (Guide_tapering) Two focal\n",NAME_CURRENT_COMP);
       fprintf(stderr,"            points lout and linh are not allowed! \n");
        free(fu);exit(-1);
     }
     if (louth == 0 && linh == 0)
     {
        /* plane mirrors (vertical) */
        h2 = h1;
     } else {
        /* parabolical mirrors */
        if (linh == 0)
        {
           Div1=((2.0*louth+2.0*l)*(2.0*louth+2.0*l))/4.0;
           p2_para=((sqrt(Div1+(h12*h12)))-(louth+l))*2.0;
           /* calculate heigth of guide exit (h2) */
           h2 = sqrt(p2_para*(louth+p2_para/4.0));
           h2 = h2*2.0;
         } else {
            /* anti-trompete */
           Div1=((2.0*linh)*(2.0*linh))/4.0;
           p2_para=((sqrt(Div1+(h12*h12)))-linh)*2.0;
           /* calculate heigth of guide exit (h2) */
           h2 = sqrt(p2_para*(l+linh+p2_para/4.0));
           h2 = h2*2.0;
         }
     }
  } else if (!strncmp(fu,"file",4)) {
     pos = strtok(fu,"=");
     while (pos=strtok(0,"="))
     {
        strcpy(file_name,pos);
     }
     if ((num=fopen(file_name,"r")) == NULL)
     {
        fprintf(stderr,"Component: %s (Guide_tapering)\n",NAME_CURRENT_COMP);
        fprintf(stderr,"           File %s not found! \n", file_name);
         free(fu);exit(-1);
     } else {
        ii = 0;
        while (!feof(num))
        {
          fgets(segment[ii].st,128,num);
          if (ii >  799) {
             fprintf(stderr,"%s: Number of segments is limited to 800 !! \n",NAME_CURRENT_COMP);
              free(fu);exit(-1);
          }
          ii++;
        }
        fclose(num);
        ii--;
     }
     seg = ii-3;
     l_seg=l/seg;
     for (i=3;i<ii;i++)
     {
        if (strlen(segment[i].st) < 4)
        {
          fprintf(stderr,"Component: %s (Guide_tapering)\n",NAME_CURRENT_COMP);
          fprintf(stderr,"           Data Format Error! \n");
          free(fu);exit(-1);
        }
        h1_in[i-3] = strtod(strtok(segment[i].st," "), &ep);
        h2_out[i-3] = strtod(strtok(0," "), &ep);
        w1_in[i-3] = strtod(strtok(0," "), &ep);
        w2_out[i-3] = strtod(strtok(0," "), &ep);
     }
     h1 = h1_in[0];
     h2 = h2_out[seg-1];
     w1 = w1_in[0];
     w2 = w2_out[seg-1];
     for (i=0;i<seg;i++)
     {
      fprintf(stderr,"%d: %lf %lf %lf %lf \n",i,h1_in[i],h2_out[i],w1_in[i],w2_out[i]);
     }
  } else {
     fprintf(stderr,"Component: %s (Guide_tapering)\n",NAME_CURRENT_COMP);
     fprintf(stderr,"           Unknown KEYWORD: %s \n", fu);
     free(fu);exit(-1);
  }
  fprintf(stderr,"Component: %s (Guide_tapering)\n",NAME_CURRENT_COMP);
  fprintf(stderr,"           Height at the guide exit (h2): %lf \n", h2);
  if (h2 <= 0)
  {
   fprintf(stderr,"Component: %s (Guide_tapering)\n", NAME_CURRENT_COMP);
   fprintf(stderr,"           Height at the guide exit (h2) was calculated\n");
   fprintf(stderr,"           <=0; Please change the parameter h1 and/or\n");
   fprintf(stderr,"           linh and/or louth! \n");
    free(fu);exit(-1);
  }
  if (!strcmp(fu,"elliptical"))
  {
     h1_in[0] = h1;
     for (i=1;i<seg;i++)
     {
       if (b_ell_q == 0)
       {
         h1_in[i]=h1;
       } else {
         mxi = (((lbh/2.0)-linh) - (l_seg * i));
         h1_in[i] = (sqrt((1.0-((mxi*mxi)/a_ell_q))*b_ell_q))*2.0;
       }
     h2_out[i-1] = h1_in[i];
     }
     h2_out[seg-1]=h2;
  } else if (!strcmp(fu,"parabolical")) {
     h1_in[0] = h1;
     ii=seg-1;
     if (louth == 0 && linh == 0)
     {
        for (i=1;i<(seg+1);i++)
        {
           h1_in[i]=h1;
           ii=ii-1;
           h2_out[i-1] = h1_in[i];
        }
     } else {
        if ((linh == 0) && (louth > 0))
        {
           for (i=1;i<(seg+1);i++)
           {
             h1_in[i] = (sqrt((p2_para/4.0+louth+(l_seg*ii))*p2_para))*2.0;
             ii=ii-1;
             h2_out[i-1] = h1_in[i];
           }
        } else {
           for (i=1;i<(seg+1);i++)
           {
             h1_in[i] = (sqrt((p2_para/4.0+linh+(l_seg*i))*p2_para))*2.0;
             h2_out[i-1] = h1_in[i];
           }
        }
     }
  }
  /* compute each value for horizontal mirrors */
  w12 = w1/2.0;
  if (!strcmp(fu,"elliptical"))
  {
    /* calculate lbw the distance between focal points of horizontal mirrors */
    lbw = l + linw + loutw;
    /* calculate parameter b of elliptical equestion - horizontal mirrors */
    if (linw == 0 && loutw == 0 )
    {
       /* plane mirrors (horizontal) */
       b_ell_q = 0;
       w2 = w1;
    } else {
       /* elliptical mirrors */
       u1 = sqrt((linw*linw)+(w12*w12));
       u2 = sqrt((w12*w12) + ((l+loutw)*(l+loutw)));
       a_ell_q = ((u1 + u2)/2.0)*((u1 + u2)/2.0);
       b_ell_q = a_ell_q - ((lbw/2.0)*(lbw/2.0));
       /* calculate weigth of guide exit (w2) */
       div1 = ((lbw/2.0-loutw)*(lbw/2.0-loutw))/a_ell_q;
       w2 = sqrt(b_ell_q*(1.0-div1));
       w2 = w2*2.0;
     }
  } else if (!strcmp(fu,"parabolical")) {
     if ((linw > 0) && (loutw > 0))
     {
       fprintf(stderr,"Component: %s (Guide_tapering) Two focal\n",NAME_CURRENT_COMP);
       fprintf(stderr,"           points linw and loutw are not allowed! \n");
         free(fu);exit(-1);
     }
     if (loutw == 0 && linw == 0)
     {
        /* plane mirrors (horizontal) */
        w2 = w1;
     } else {
       if (linw == 0)
       {
          /* parabolical mirrors */
          Div1=((2.0*loutw+2.0*l)*(2.0*loutw+2.0*l))/4.0;
          p2_para=((sqrt(Div1+(w12*w12)))-(loutw+l))*2.0;
          /* calculate weigth of guide exit (w2) */
          w2 = sqrt(p2_para*(loutw+p2_para/4.0));
          w2 = w2*2.0;
       } else {
          /* anti-trompete */
          Div1=((2.0*linw)*(2.0*linw))/4.0;
          p2_para=((sqrt(Div1+(w12*w12)))-linw)*2.0;
          /* calculate heigth of guide exit (w2) */
          w2 = sqrt(p2_para*(l+linw+p2_para/4.0));
          w2 = w2*2.0;
       }
     }
  }
  fprintf(stderr,"Component: %s (Guide_tapering)\n",NAME_CURRENT_COMP);
  fprintf(stderr,"           Weigth at the guide exit (w2): %lf \n", w2);
  if (w2 <= 0)
  {
   fprintf(stderr,"Component: %s (Guide_tapering)\n", NAME_CURRENT_COMP);
   fprintf(stderr,"           Weigth at the guide exit (w2) was calculated\n");
   fprintf(stderr,"           <=0; Please change the parameter w1 and/or\n");
   fprintf(stderr,"           l! \n");
    free(fu);exit(-1);
  }
  if (!strcmp(fu,"elliptical"))
  {
     w1_in[0]=w1;
     for (i=1;i<seg;i++)
     {
       if (b_ell_q == 0)
       {
         w1_in[i]=w1;
       } else {
         mxi = (((lbw/2.0)-linw) - (l_seg * i));
         w1_in[i] = (sqrt((1.0-((mxi*mxi)/a_ell_q))*b_ell_q))*2.0;
       }
       w2_out[i-1] = w1_in[i];
     }
     w2_out[seg-1]=w2;
  } else if (!strcmp(fu,"parabolical")) {
     w1_in[0]=w1;
     ii=seg-1;
     if (loutw == 0 && linw == 0)
     {
        for (i=1;i<(seg+1);i++)
        {
           w1_in[i]=w1;
           ii=ii-1;
           w2_out[i-1] = w1_in[i];
        }
     } else {
        if ((linw == 0) && (loutw > 0))
        {
           for (i=1;i<(seg+1);i++)
           {
             w1_in[i] = (sqrt((p2_para/4+loutw+(l_seg*ii))*p2_para))*2;
             ii=ii-1;
             w2_out[i-1] = w1_in[i];
           }
        } else {
           for (i=1;i<(seg+1);i++)
           {
             w1_in[i] = (sqrt((p2_para/4+linw+(l_seg*i))*p2_para))*2;
             w2_out[i-1] = w1_in[i];
           }
        }
     }
  }
  free(fu);
  for (i=0;i<seg;i++)
  {
    w1c[i] = w1_in[i];
    w2c[i] = w2_out[i];
    ww[i] = .5*(w2c[i] - w1c[i]);
    hh[i] = .5*(h2_out[i] - h1_in[i]);
    whalf[i] = .5*w1c[i];
    hhalf[i] = .5*h1_in[i];
    lwhalf[i] = l_seg*whalf[i];
    lhhalf[i] = l_seg*hhalf[i];
  }
}
#line 11822 "TOFexercise42.c"
#undef my
#undef mx
#undef W
#undef alphay
#undef alphax
#undef Qcy
#undef Qcx
#undef R0
#undef louth
#undef linh
#undef loutw
#undef linw
#undef l
#undef h1
#undef w1
#undef num
#undef ep
#undef file_name
#undef pos
#undef fu
#undef seg
#undef ii
#undef i
#undef Div1
#undef test
#undef p2_para
#undef div1
#undef u2
#undef u1
#undef mxi
#undef lbh
#undef lbw
#undef b_ell_q
#undef a_ell_q
#undef w2
#undef w12
#undef h2
#undef h12
#undef seg
#undef l_seg
#undef w2_out
#undef w1_in
#undef h2_out
#undef h1_in
#undef lhhalf
#undef lwhalf
#undef hhalf
#undef whalf
#undef hh
#undef ww
#undef w2c
#undef w1c
#undef segno
#undef option
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Guide4a. */
  SIG_MESSAGE("Guide4a (Init)");
#line 225 "TOFexercise42.instr"
  mccGuide4a_w1 = 0.05;
#line 226 "TOFexercise42.instr"
  mccGuide4a_h1 = 0.05;
#line 227 "TOFexercise42.instr"
  mccGuide4a_w2 = 0.08;
#line 228 "TOFexercise42.instr"
  mccGuide4a_h2 = 0.08;
#line 229 "TOFexercise42.instr"
  mccGuide4a_l = mcipguide_bal_d;
#line 61 "TOFexercise42.instr"
  mccGuide4a_R0 = 0.99;
#line 61 "TOFexercise42.instr"
  mccGuide4a_Qc = 0.0219;
#line 61 "TOFexercise42.instr"
  mccGuide4a_alpha = 6.07;
#line 61 "TOFexercise42.instr"
  mccGuide4a_m = 2;
#line 61 "TOFexercise42.instr"
  mccGuide4a_W = 0.003;
#line 11903 "TOFexercise42.c"

#define mccompcurname  Guide4a
#define mccompcurtype  Guide
#define mccompcurindex 10
#define reflect mccGuide4a_reflect
#define pTable mccGuide4a_pTable
#define w1 mccGuide4a_w1
#define h1 mccGuide4a_h1
#define w2 mccGuide4a_w2
#define h2 mccGuide4a_h2
#define l mccGuide4a_l
#define R0 mccGuide4a_R0
#define Qc mccGuide4a_Qc
#define alpha mccGuide4a_alpha
#define m mccGuide4a_m
#define W mccGuide4a_W
#line 76 "/usr/local/lib/mcstas/optics/Guide.comp"
{
  if (mcgravitation) fprintf(stderr,"WARNING: Guide: %s: "
    "This component produces wrong results with gravitation !\n"
    "Use Guide_gravity.\n",
    NAME_CURRENT_COMP);

  if (reflect && strlen(reflect)) {
    if (Table_Read(&pTable, reflect, 1) <= 0) /* read 1st block data from file into pTable */
      exit(fprintf(stderr,"Guide: %s: can not read file %s\n", NAME_CURRENT_COMP, reflect));
  } else {
    if (W < 0 || R0 < 0 || Qc < 0 || m < 0)
    { fprintf(stderr,"Guide: %s: W R0 Qc must be >0.\n", NAME_CURRENT_COMP);
      exit(-1); }
    if (m < 1 && m != 0) fprintf(stderr,"WARNING: Guide: %s: m < 1 behaves as if m=1.\n",
      NAME_CURRENT_COMP);
  }
}
#line 11938 "TOFexercise42.c"
#undef W
#undef m
#undef alpha
#undef Qc
#undef R0
#undef l
#undef h2
#undef w2
#undef h1
#undef w1
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Guide4b. */
  SIG_MESSAGE("Guide4b (Init)");
#line 233 "TOFexercise42.instr"
  mccGuide4b_w1 = 0.08;
#line 234 "TOFexercise42.instr"
  mccGuide4b_h1 = 0.08;
#line 235 "TOFexercise42.instr"
  mccGuide4b_w2 = 0.08;
#line 236 "TOFexercise42.instr"
  mccGuide4b_h2 = 0.08;
#line 237 "TOFexercise42.instr"
  mccGuide4b_l = guide_bal_ml;
#line 61 "TOFexercise42.instr"
  mccGuide4b_R0 = 0.99;
#line 61 "TOFexercise42.instr"
  mccGuide4b_Qc = 0.0219;
#line 61 "TOFexercise42.instr"
  mccGuide4b_alpha = 6.07;
#line 61 "TOFexercise42.instr"
  mccGuide4b_m = 2;
#line 61 "TOFexercise42.instr"
  mccGuide4b_W = 0.003;
#line 11977 "TOFexercise42.c"

#define mccompcurname  Guide4b
#define mccompcurtype  Guide
#define mccompcurindex 11
#define reflect mccGuide4b_reflect
#define pTable mccGuide4b_pTable
#define w1 mccGuide4b_w1
#define h1 mccGuide4b_h1
#define w2 mccGuide4b_w2
#define h2 mccGuide4b_h2
#define l mccGuide4b_l
#define R0 mccGuide4b_R0
#define Qc mccGuide4b_Qc
#define alpha mccGuide4b_alpha
#define m mccGuide4b_m
#define W mccGuide4b_W
#line 76 "/usr/local/lib/mcstas/optics/Guide.comp"
{
  if (mcgravitation) fprintf(stderr,"WARNING: Guide: %s: "
    "This component produces wrong results with gravitation !\n"
    "Use Guide_gravity.\n",
    NAME_CURRENT_COMP);

  if (reflect && strlen(reflect)) {
    if (Table_Read(&pTable, reflect, 1) <= 0) /* read 1st block data from file into pTable */
      exit(fprintf(stderr,"Guide: %s: can not read file %s\n", NAME_CURRENT_COMP, reflect));
  } else {
    if (W < 0 || R0 < 0 || Qc < 0 || m < 0)
    { fprintf(stderr,"Guide: %s: W R0 Qc must be >0.\n", NAME_CURRENT_COMP);
      exit(-1); }
    if (m < 1 && m != 0) fprintf(stderr,"WARNING: Guide: %s: m < 1 behaves as if m=1.\n",
      NAME_CURRENT_COMP);
  }
}
#line 12012 "TOFexercise42.c"
#undef W
#undef m
#undef alpha
#undef Qc
#undef R0
#undef l
#undef h2
#undef w2
#undef h1
#undef w1
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Guide4c. */
  SIG_MESSAGE("Guide4c (Init)");
#line 241 "TOFexercise42.instr"
  mccGuide4c_w1 = 0.08;
#line 242 "TOFexercise42.instr"
  mccGuide4c_h1 = 0.08;
#line 243 "TOFexercise42.instr"
  mccGuide4c_w2 = 0.05;
#line 244 "TOFexercise42.instr"
  mccGuide4c_h2 = 0.05;
#line 245 "TOFexercise42.instr"
  mccGuide4c_l = mcipguide_bal_d;
#line 61 "TOFexercise42.instr"
  mccGuide4c_R0 = 0.99;
#line 61 "TOFexercise42.instr"
  mccGuide4c_Qc = 0.0219;
#line 61 "TOFexercise42.instr"
  mccGuide4c_alpha = 6.07;
#line 61 "TOFexercise42.instr"
  mccGuide4c_m = 2;
#line 61 "TOFexercise42.instr"
  mccGuide4c_W = 0.003;
#line 12051 "TOFexercise42.c"

#define mccompcurname  Guide4c
#define mccompcurtype  Guide
#define mccompcurindex 12
#define reflect mccGuide4c_reflect
#define pTable mccGuide4c_pTable
#define w1 mccGuide4c_w1
#define h1 mccGuide4c_h1
#define w2 mccGuide4c_w2
#define h2 mccGuide4c_h2
#define l mccGuide4c_l
#define R0 mccGuide4c_R0
#define Qc mccGuide4c_Qc
#define alpha mccGuide4c_alpha
#define m mccGuide4c_m
#define W mccGuide4c_W
#line 76 "/usr/local/lib/mcstas/optics/Guide.comp"
{
  if (mcgravitation) fprintf(stderr,"WARNING: Guide: %s: "
    "This component produces wrong results with gravitation !\n"
    "Use Guide_gravity.\n",
    NAME_CURRENT_COMP);

  if (reflect && strlen(reflect)) {
    if (Table_Read(&pTable, reflect, 1) <= 0) /* read 1st block data from file into pTable */
      exit(fprintf(stderr,"Guide: %s: can not read file %s\n", NAME_CURRENT_COMP, reflect));
  } else {
    if (W < 0 || R0 < 0 || Qc < 0 || m < 0)
    { fprintf(stderr,"Guide: %s: W R0 Qc must be >0.\n", NAME_CURRENT_COMP);
      exit(-1); }
    if (m < 1 && m != 0) fprintf(stderr,"WARNING: Guide: %s: m < 1 behaves as if m=1.\n",
      NAME_CURRENT_COMP);
  }
}
#line 12086 "TOFexercise42.c"
#undef W
#undef m
#undef alpha
#undef Qc
#undef R0
#undef l
#undef h2
#undef w2
#undef h1
#undef w1
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component TOF_mon_3. */
  SIG_MESSAGE("TOF_mon_3 (Init)");
#line 46 "TOFexercise42.instr"
  mccTOF_mon_3_xmin = 0;
#line 46 "TOFexercise42.instr"
  mccTOF_mon_3_xmax = 0;
#line 46 "TOFexercise42.instr"
  mccTOF_mon_3_ymin = 0;
#line 46 "TOFexercise42.instr"
  mccTOF_mon_3_ymax = 0;
#line 252 "TOFexercise42.instr"
  mccTOF_mon_3_xwidth = 0.02;
#line 253 "TOFexercise42.instr"
  mccTOF_mon_3_yheight = 0.02;
#line 254 "TOFexercise42.instr"
  mccTOF_mon_3_t0 = mcipTOF3min;
#line 255 "TOFexercise42.instr"
  mccTOF_mon_3_t1 = mcipTOF3max;
#line 46 "TOFexercise42.instr"
  mccTOF_mon_3_dt = 1.0;
#line 256 "TOFexercise42.instr"
  mccTOF_mon_3_restore_neutron = 1;
#line 12125 "TOFexercise42.c"

#define mccompcurname  TOF_mon_3
#define mccompcurtype  TOF_monitor
#define mccompcurindex 13
#define nchan mccTOF_mon_3_nchan
#define filename mccTOF_mon_3_filename
#define TOF_N mccTOF_mon_3_TOF_N
#define TOF_p mccTOF_mon_3_TOF_p
#define TOF_p2 mccTOF_mon_3_TOF_p2
#define t_min mccTOF_mon_3_t_min
#define t_max mccTOF_mon_3_t_max
#define delta_t mccTOF_mon_3_delta_t
#define xmin mccTOF_mon_3_xmin
#define xmax mccTOF_mon_3_xmax
#define ymin mccTOF_mon_3_ymin
#define ymax mccTOF_mon_3_ymax
#define xwidth mccTOF_mon_3_xwidth
#define yheight mccTOF_mon_3_yheight
#define t0 mccTOF_mon_3_t0
#define t1 mccTOF_mon_3_t1
#define dt mccTOF_mon_3_dt
#define restore_neutron mccTOF_mon_3_restore_neutron
#line 59 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
    int i;

    if (xwidth  > 0) { xmax = xwidth/2;  xmin = -xmax; }
    if (yheight > 0) { ymax = yheight/2; ymin = -ymax; }

    if ((xmin >= xmax) || (ymin >= ymax)) {
            printf("TOF_monitor: %s: Null detection area !\n"
                   "ERROR        (xwidth,yheight,xmin,xmax,ymin,ymax). Exiting",
           NAME_CURRENT_COMP);
      exit(0);
    }

    for (i=0; i<nchan; i++)
    {
      TOF_N[i] = 0;
      TOF_p[i] = 0;
      TOF_p2[i] = 0;
    }
    if (t1!=0)
    {
      t_max=t1;
      t_min=t0;
      delta_t=(t_max-t_min)/nchan;
    }
    else
    {
     delta_t=dt;
     t_min=0;
     t_max=nchan*dt+t0;
    }
}
#line 12181 "TOFexercise42.c"
#undef restore_neutron
#undef dt
#undef t1
#undef t0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component TOF_lmon_3. */
  SIG_MESSAGE("TOF_lmon_3 (Init)");
#line 51 "TOFexercise42.instr"
  mccTOF_lmon_3_xmin = 0;
#line 51 "TOFexercise42.instr"
  mccTOF_lmon_3_xmax = 0;
#line 51 "TOFexercise42.instr"
  mccTOF_lmon_3_ymin = 0;
#line 51 "TOFexercise42.instr"
  mccTOF_lmon_3_ymax = 0;
#line 265 "TOFexercise42.instr"
  mccTOF_lmon_3_xwidth = 0.02;
#line 266 "TOFexercise42.instr"
  mccTOF_lmon_3_yheight = 0.02;
#line 267 "TOFexercise42.instr"
  mccTOF_lmon_3_lambda_0 = mciplmin;
#line 268 "TOFexercise42.instr"
  mccTOF_lmon_3_lambda_1 = mciplmax;
#line 269 "TOFexercise42.instr"
  mccTOF_lmon_3_restore_neutron = 1;
#line 12224 "TOFexercise42.c"

#define mccompcurname  TOF_lmon_3
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 14
#define nlam mccTOF_lmon_3_nlam
#define nt mccTOF_lmon_3_nt
#define filename mccTOF_lmon_3_filename
#define t_0 mccTOF_lmon_3_t_0
#define t_1 mccTOF_lmon_3_t_1
#define tt_0 mccTOF_lmon_3_tt_0
#define tt_1 mccTOF_lmon_3_tt_1
#define TOFL_N mccTOF_lmon_3_TOFL_N
#define TOFL_p mccTOF_lmon_3_TOFL_p
#define TOFL_p2 mccTOF_lmon_3_TOFL_p2
#define xmin mccTOF_lmon_3_xmin
#define xmax mccTOF_lmon_3_xmax
#define ymin mccTOF_lmon_3_ymin
#define ymax mccTOF_lmon_3_ymax
#define xwidth mccTOF_lmon_3_xwidth
#define yheight mccTOF_lmon_3_yheight
#define lambda_0 mccTOF_lmon_3_lambda_0
#define lambda_1 mccTOF_lmon_3_lambda_1
#define restore_neutron mccTOF_lmon_3_restore_neutron
#line 63 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
{
    int i,j;

    if (xwidth  > 0) { xmax = xwidth/2;  xmin = -xmax; }
    if (yheight > 0) { ymax = yheight/2; ymin = -ymax; }

    if ((xmin >= xmax) || (ymin >= ymax)) {
            printf("TOFLambda_monitor: %s: Null detection area !\n"
                   "ERROR              (xwidth,yheight,xmin,xmax,ymin,ymax). Exiting",
           NAME_CURRENT_COMP);
      exit(0);
    }

    tt_0 = t_0*1e-6;
    tt_1 = t_1*1e-6;
    for (i=0; i<nlam; i++)
     for (j=0; j<nt; j++)
     {
      TOFL_N[j][i] = 0;
      TOFL_p[j][i] = 0;
      TOFL_p2[j][i] = 0;
     }
}
#line 12272 "TOFexercise42.c"
#undef restore_neutron
#undef lambda_1
#undef lambda_0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component DivLambda_mon. */
  SIG_MESSAGE("DivLambda_mon (Init)");
#line 55 "TOFexercise42.instr"
  mccDivLambda_mon_xmin = 0;
#line 55 "TOFexercise42.instr"
  mccDivLambda_mon_xmax = 0;
#line 55 "TOFexercise42.instr"
  mccDivLambda_mon_ymin = 0;
#line 55 "TOFexercise42.instr"
  mccDivLambda_mon_ymax = 0;
#line 278 "TOFexercise42.instr"
  mccDivLambda_mon_xwidth = divmon_w;
#line 278 "TOFexercise42.instr"
  mccDivLambda_mon_yheight = divmon_w;
#line 278 "TOFexercise42.instr"
  mccDivLambda_mon_maxdiv = divmon_maxdiv;
#line 279 "TOFexercise42.instr"
  mccDivLambda_mon_lambda_0 = mciplmin;
#line 280 "TOFexercise42.instr"
  mccDivLambda_mon_lambda_1 = mciplmax;
#line 12316 "TOFexercise42.c"

#define mccompcurname  DivLambda_mon
#define mccompcurtype  DivLambda_monitor
#define mccompcurindex 15
#define nlam mccDivLambda_mon_nlam
#define ndiv mccDivLambda_mon_ndiv
#define filename mccDivLambda_mon_filename
#define restore_neutron mccDivLambda_mon_restore_neutron
#define Div_N mccDivLambda_mon_Div_N
#define Div_p mccDivLambda_mon_Div_p
#define Div_p2 mccDivLambda_mon_Div_p2
#define xmin mccDivLambda_mon_xmin
#define xmax mccDivLambda_mon_xmax
#define ymin mccDivLambda_mon_ymin
#define ymax mccDivLambda_mon_ymax
#define xwidth mccDivLambda_mon_xwidth
#define yheight mccDivLambda_mon_yheight
#define maxdiv mccDivLambda_mon_maxdiv
#define lambda_0 mccDivLambda_mon_lambda_0
#define lambda_1 mccDivLambda_mon_lambda_1
#line 66 "/usr/local/lib/mcstas/monitors/DivLambda_monitor.comp"
{
    int i,j;

    if (xwidth  > 0) { xmax = xwidth/2;  xmin = -xmax; }
    if (yheight > 0) { ymax = yheight/2; ymin = -ymax; }

    if ((xmin >= xmax) || (ymin >= ymax)) {
            printf("DivLambda_monitor: %s: Null detection area !\n"
                   "ERROR              (xwidth,yheight,xmin,xmax,ymin,ymax). Exiting",
           NAME_CURRENT_COMP);
      exit(0);
    }

    for (i=0; i<nlam; i++)
     for (j=0; j<ndiv; j++)
     {
      Div_N[i][j] = 0;
      Div_p[i][j] = 0;
      Div_p2[i][j] = 0;
     }
}
#line 12359 "TOFexercise42.c"
#undef lambda_1
#undef lambda_0
#undef maxdiv
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef Div_p2
#undef Div_p
#undef Div_N
#undef restore_neutron
#undef filename
#undef ndiv
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Sample. */
  SIG_MESSAGE("Sample (Init)");
#line 285 "TOFexercise42.instr"
  mccSample_radius = 0.006;
#line 70 "TOFexercise42.instr"
  mccSample_yheight = 0.05;
#line 286 "TOFexercise42.instr"
  mccSample_q = 5;
#line 70 "TOFexercise42.instr"
  mccSample_d = 0;
#line 70 "TOFexercise42.instr"
  mccSample_d_phi = 0;
#line 71 "TOFexercise42.instr"
  mccSample_pack = 1;
#line 71 "TOFexercise42.instr"
  mccSample_j = 6;
#line 71 "TOFexercise42.instr"
  mccSample_DW = 1;
#line 71 "TOFexercise42.instr"
  mccSample_F2 = 56.8;
#line 71 "TOFexercise42.instr"
  mccSample_Vc = 85.0054;
#line 71 "TOFexercise42.instr"
  mccSample_sigma_a = 0.463;
#line 72 "TOFexercise42.instr"
  mccSample_xwidth = 0;
#line 72 "TOFexercise42.instr"
  mccSample_zthick = 0;
#line 72 "TOFexercise42.instr"
  mccSample_h = 0;
#line 12410 "TOFexercise42.c"

#define mccompcurname  Sample
#define mccompcurtype  Powder1
#define mccompcurindex 16
#define my_s_v2 mccSample_my_s_v2
#define my_a_v mccSample_my_a_v
#define q_v mccSample_q_v
#define isrect mccSample_isrect
#define radius mccSample_radius
#define yheight mccSample_yheight
#define q mccSample_q
#define d mccSample_d
#define d_phi mccSample_d_phi
#define pack mccSample_pack
#define j mccSample_j
#define DW mccSample_DW
#define F2 mccSample_F2
#define Vc mccSample_Vc
#define sigma_a mccSample_sigma_a
#define xwidth mccSample_xwidth
#define zthick mccSample_zthick
#define h mccSample_h
#line 82 "/usr/local/lib/mcstas/samples/Powder1.comp"
{
  if (h) yheight=h;
  if (!radius || !yheight) {
    if (!xwidth || !yheight || !zthick) exit(fprintf(stderr,"Powder1: %s: sample has no volume (zero dimensions)\n", NAME_CURRENT_COMP));
    else isrect=1; }

  my_a_v = pack*sigma_a/Vc*2200*100;        /* Is not yet divided by v */
  my_s_v2 = 4*PI*PI*PI*pack*j*F2*DW/(Vc*Vc*V2K*V2K*q)*100;
  /* Is not yet divided by v^2. 100: convert from barns to fm^2 */
  /* Squires [3.103] */
  if (d) q=2*PI/d;
  q_v = q*K2V;
}
#line 12447 "TOFexercise42.c"
#undef h
#undef zthick
#undef xwidth
#undef sigma_a
#undef Vc
#undef F2
#undef DW
#undef j
#undef pack
#undef d_phi
#undef d
#undef q
#undef yheight
#undef radius
#undef isrect
#undef q_v
#undef my_a_v
#undef my_s_v2
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Detector. */
  SIG_MESSAGE("Detector (Init)");
#line 294 "TOFexercise42.instr"
  mccDetector_radius = 2;
#line 295 "TOFexercise42.instr"
  mccDetector_height = 0.2;
#line 296 "TOFexercise42.instr"
  mccDetector_t_0 = mcipTOF3min;
#line 297 "TOFexercise42.instr"
  mccDetector_t_1 = mcipTOF3max;
#line 298 "TOFexercise42.instr"
  mccDetector_restore_neutron = 1;
#line 12482 "TOFexercise42.c"

#define mccompcurname  Detector
#define mccompcurtype  TOF_cylPSD_monitor
#define mccompcurindex 17
#define nt mccDetector_nt
#define filename mccDetector_filename
#define nphi mccDetector_nphi
#define TOF_N mccDetector_TOF_N
#define TOF_p mccDetector_TOF_p
#define TOF_p2 mccDetector_TOF_p2
#define radius mccDetector_radius
#define height mccDetector_height
#define t_0 mccDetector_t_0
#define t_1 mccDetector_t_1
#define restore_neutron mccDetector_restore_neutron
#line 55 "/usr/local/lib/mcstas/monitors/TOF_cylPSD_monitor.comp"
{
    int i,j;

    tt_0=t_0*1e-6;
    tt_1=t_1*1e-6;
    for (i=0; i<nt; i++)
      for (j=0; j<nphi; j++)
      {
        TOF_N[i][j] = 0;
        TOF_p[i][j] = 0;
        TOF_p2[i][j] = 0;
      }
    binphi=360.0/(double)nphi;

}
#line 12514 "TOFexercise42.c"
#undef restore_neutron
#undef t_1
#undef t_0
#undef height
#undef radius
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef nphi
#undef filename
#undef nt
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component arm1. */
  SIG_MESSAGE("arm1 (Init)");


  /* Initializations for component LineDetector. */
  SIG_MESSAGE("LineDetector (Init)");
#line 46 "TOFexercise42.instr"
  mccLineDetector_xmin = 0;
#line 46 "TOFexercise42.instr"
  mccLineDetector_xmax = 0;
#line 46 "TOFexercise42.instr"
  mccLineDetector_ymin = 0;
#line 46 "TOFexercise42.instr"
  mccLineDetector_ymax = 0;
#line 308 "TOFexercise42.instr"
  mccLineDetector_xwidth = 0.01;
#line 309 "TOFexercise42.instr"
  mccLineDetector_yheight = 0.2;
#line 310 "TOFexercise42.instr"
  mccLineDetector_t0 = mcipTOF3min;
#line 311 "TOFexercise42.instr"
  mccLineDetector_t1 = mcipTOF3max;
#line 46 "TOFexercise42.instr"
  mccLineDetector_dt = 1.0;
#line 312 "TOFexercise42.instr"
  mccLineDetector_restore_neutron = 1;
#line 12556 "TOFexercise42.c"

#define mccompcurname  LineDetector
#define mccompcurtype  TOF_monitor
#define mccompcurindex 19
#define nchan mccLineDetector_nchan
#define filename mccLineDetector_filename
#define TOF_N mccLineDetector_TOF_N
#define TOF_p mccLineDetector_TOF_p
#define TOF_p2 mccLineDetector_TOF_p2
#define t_min mccLineDetector_t_min
#define t_max mccLineDetector_t_max
#define delta_t mccLineDetector_delta_t
#define xmin mccLineDetector_xmin
#define xmax mccLineDetector_xmax
#define ymin mccLineDetector_ymin
#define ymax mccLineDetector_ymax
#define xwidth mccLineDetector_xwidth
#define yheight mccLineDetector_yheight
#define t0 mccLineDetector_t0
#define t1 mccLineDetector_t1
#define dt mccLineDetector_dt
#define restore_neutron mccLineDetector_restore_neutron
#line 59 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
    int i;

    if (xwidth  > 0) { xmax = xwidth/2;  xmin = -xmax; }
    if (yheight > 0) { ymax = yheight/2; ymin = -ymax; }

    if ((xmin >= xmax) || (ymin >= ymax)) {
            printf("TOF_monitor: %s: Null detection area !\n"
                   "ERROR        (xwidth,yheight,xmin,xmax,ymin,ymax). Exiting",
           NAME_CURRENT_COMP);
      exit(0);
    }

    for (i=0; i<nchan; i++)
    {
      TOF_N[i] = 0;
      TOF_p[i] = 0;
      TOF_p2[i] = 0;
    }
    if (t1!=0)
    {
      t_max=t1;
      t_min=t0;
      delta_t=(t_max-t_min)/nchan;
    }
    else
    {
     delta_t=dt;
     t_min=0;
     t_max=nchan*dt+t0;
    }
}
#line 12612 "TOFexercise42.c"
#undef restore_neutron
#undef dt
#undef t1
#undef t0
#undef yheight
#undef xwidth
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

    if(mcdotrace) mcdisplay();
    mcDEBUG_INSTR_END()
  }

/* NeXus support */

#ifdef USE_NEXUS

strncmp(mcnxversion,"5 zip",128);

#endif

} /* end init */

void mcraytrace(void) {
  /* Copy neutron state to local variables. */
  MCNUM mcnlx = mcnx;
  MCNUM mcnly = mcny;
  MCNUM mcnlz = mcnz;
  MCNUM mcnlvx = mcnvx;
  MCNUM mcnlvy = mcnvy;
  MCNUM mcnlvz = mcnvz;
  MCNUM mcnlt = mcnt;
  MCNUM mcnlsx = mcnsx;
  MCNUM mcnlsy = mcnsy;
  MCNUM mcnlsz = mcnsz;
  MCNUM mcnlp = mcnp;

  mcDEBUG_ENTER()
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define mcabsorb mcabsorbAll
  /* TRACE Component Origin [1] */
  mccoordschange(mcposrOrigin, mcrotrOrigin,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrOrigin, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Origin (without coords transformations) */
  mcJumpTrace_Origin:
  SIG_MESSAGE("Origin (Trace)");
  mcDEBUG_COMP("Origin")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
  STORE_NEUTRON(1,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[1]++;
  mcPCounter[1] += p;
  mcP2Counter[1] += p*p;
#define mccompcurname  Origin
#define mccompcurtype  Progress_bar
#define mccompcurindex 1
#define profile mccOrigin_profile
#define IntermediateCnts mccOrigin_IntermediateCnts
#define StartTime mccOrigin_StartTime
#define EndTime mccOrigin_EndTime
{   /* Declarations of SETTING parameters. */
MCNUM percent = mccOrigin_percent;
MCNUM flag_save = mccOrigin_flag_save;
MCNUM minutes = mccOrigin_minutes;
#line 69 "/usr/local/lib/mcstas/misc/Progress_bar.comp"
{
  double ncount;
  ncount = mcget_run_num();
  if (!StartTime) {
    time(&StartTime); /* compute starting time */
    IntermediateCnts = 1e3;
  }
  time_t NowTime;
  time(&NowTime);
  if (!EndTime && ncount >= IntermediateCnts) {
    CurrentTime = NowTime;
    if (difftime(NowTime,StartTime) > 10) { /* wait 10 sec before writing ETA */
      EndTime = StartTime + (time_t)(difftime(NowTime,StartTime)
				     *(double)mcget_ncount()/ncount);
      IntermediateCnts = 0;
      fprintf(stdout, "\nTrace ETA ");
      if (difftime(EndTime,StartTime) < 60.0)
        fprintf(stdout, "%g [s] %% ", difftime(EndTime,StartTime));
      else if (difftime(EndTime,StartTime) > 3600.0)
        fprintf(stdout, "%g [h] %% ", difftime(EndTime,StartTime));
      else
        fprintf(stdout, "%g [min] %% ", difftime(EndTime,StartTime)/60.0);
    } else IntermediateCnts += 1e3;
    fflush(stdout);
  }

  if (EndTime &&
    (    (minutes && difftime(NowTime,CurrentTime) > minutes*60)
      || (percent && !minutes && ncount >= IntermediateCnts))   )
  {
    fprintf(stdout, "%d ", (int)(ncount*100.0/mcget_ncount())); fflush(stdout);
    CurrentTime = NowTime;
    IntermediateCnts = ncount + percent*mcget_ncount()/100;
    if (IntermediateCnts >= mcget_ncount()) fprintf(stdout, "\n");
    if (flag_save) mcsave(NULL);
  }
}
#line 12737 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef EndTime
#undef StartTime
#undef IntermediateCnts
#undef profile
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component Moderator [2] */
  mccoordschange(mcposrModerator, mcrotrModerator,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrModerator, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Moderator (without coords transformations) */
  mcJumpTrace_Moderator:
  SIG_MESSAGE("Moderator (Trace)");
  mcDEBUG_COMP("Moderator")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
  STORE_NEUTRON(2,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[2]++;
  mcPCounter[2] += p;
  mcP2Counter[2] += p*p;
#define mccompcurname  Moderator
#define mccompcurtype  ESS_moderator_long
#define mccompcurindex 2
#define M mccModerator_M
#define F mccModerator_F
#define l_range mccModerator_l_range
#define w_mult mccModerator_w_mult
{   /* Declarations of SETTING parameters. */
MCNUM size = mccModerator_size;
MCNUM l_low = mccModerator_l_low;
MCNUM l_high = mccModerator_l_high;
MCNUM dist = mccModerator_dist;
MCNUM xw = mccModerator_xw;
MCNUM yh = mccModerator_yh;
MCNUM freq = mccModerator_freq;
MCNUM T = mccModerator_T;
MCNUM tau = mccModerator_tau;
MCNUM tau1 = mccModerator_tau1;
MCNUM tau2 = mccModerator_tau2;
MCNUM d = mccModerator_d;
MCNUM n = mccModerator_n;
MCNUM n2 = mccModerator_n2;
MCNUM chi2 = mccModerator_chi2;
MCNUM I0 = mccModerator_I0;
MCNUM I2 = mccModerator_I2;
MCNUM branch1 = mccModerator_branch1;
MCNUM branch2 = mccModerator_branch2;
MCNUM branch_tail = mccModerator_branch_tail;
MCNUM twopulses = mccModerator_twopulses;
#line 145 "/usr/local/lib/mcstas/sources/ESS_moderator_long.comp"
{
  double v,tau_l,E,lambda,k,r,xf,yf,dx,dy,w_focus,tail_flag;

  z=0;

  x = 0.5*size*randpm1();
  y = 0.5*size*randpm1();         /* Choose initial position */

  randvec_target_rect_real(&xf, &yf, &r, &w_focus,
			   0, 0, dist, xw, yh, ROT_A_CURRENT_COMP, x, y, z, 2);

  dx = xf-x;
  dy = yf-y;
  r = sqrt(dx*dx+dy*dy+dist*dist);

  lambda = l_low+l_range*rand01();    /* Choose from uniform distribution */
  k = 2*PI/lambda;
  v = K2V*k;

  vz = v*dist/r;
  vy = v*dy/r;
  vx = v*dx/r;


/*  printf("pos0 (%g %g %g), pos1 (%g %g %g), r: %g, v (%g %g %g), v %g\n",
  x,y,z,xf,yf,dist,r,vx,vy,vz, v);
  printf("l %g, w_focus %g \n", lambda, w_focus);  */

  tail_flag = (rand01()<branch_tail);   /* Choose tail/bulk */
 if (tail_flag)
 {
  if (rand01() < branch2)
  {
    if (tau1>0)
      if (rand01() < branch1)     /* Quick and dirty non-general solution */
      {  /* FIRST CASE a */
        tau_l = tau;
        p = 1/(branch1*branch2*branch_tail); /* Correct for switching prob. */
      }
      else
      {  /* FIRST CASE b */
        tau_l = tau1;
        p = 1/((1-branch1)*branch2*branch_tail); /* Correct for switching prob. */
      }
    else
      {
        tau_l = tau;
        p = 1/(branch2*branch_tail); /* Correct for switching prob. */
      }
    t = -tau_l*log(1e-12+rand01());       /* Sample from long-time tail a */
 /* Correct for true pulse shape */
    p *= w_focus;                         /* Correct for target focusing */
    p *= tau_l/d;                         /* Correct for tail part */
    p *= I0*w_mult*M(lambda,T);           /* Calculate true intensity */
  }
  else
  {
    /* SECOND CASE */
    tau_l = tau2*lambda;
    t = -tau_l*log(1e-12+rand01());       /* Sample from long-time tail */
    p = n2/(n2-1)*((1-exp(-d/tau_l))-(1-exp(-n2*d/tau_l))*exp(-(n2-1)*t/tau_l)/n);
                                          /* Correct for true pulse shape */
    p /= (1-branch2)*branch_tail;          /* Correct for switching prob. */
    p *= tau_l/d;                         /* Correct for tail part */
    p *= w_focus;                         /* Correct for target focusing */
    p *= I2*w_mult/(1+exp(chi2*lambda-2.2))/lambda;
                                          /* Calculate true intensity */
  }
  t += d;                                 /* Add pulse length */
 }
 else
 {
  t = d*rand01();                        /* Sample from bulk pulse */
  if (rand01() < branch2)
  {
    if (rand01() < branch1)     /* Quick and dirty non-general solution */
    {  /* FIRST CASE a */
      tau_l = tau;
      p = 1/(branch1*branch2*(1-branch_tail)); /* Correct for switching prob. */
    }
    else
    {  /* FIRST CASE b */
      tau_l = tau1;
      p = 1/((1-branch1)*branch2*(1-branch_tail)); /* Correct for switching prob. */
    }
    p *= 1-n/(n-1)*(exp(-t/tau_l)-exp(-n*t/tau_l)/n); /* Correct for true pulse shape */
    p *= w_focus;                         /* Correct for target focusing */
    p *= I0*w_mult*M(lambda,T);           /* Calculate true intensity */
  }
  else
  {
    /* SECOND CASE */
    tau_l = tau2*lambda;
    p = 1-n2/(n2-1)*(exp(-t/tau_l)-exp(-n2*t/tau_l)/n2); /* Correct for true pulse shape */
    p /= (1-branch2)*(1-branch_tail);      /* Correct for switching prob. */
    p *= w_focus;                         /* Correct for target focusing */
    p *= I2*w_mult/(1+exp(chi2*lambda-2.2))/lambda;
                                          /* Calculate true intensity */
  }
 }
 if (rand01()<branchframe){
   t+=1/freq;
 }
}
#line 12918 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef w_mult
#undef l_range
#undef F
#undef M
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component TOF_mon_1 [3] */
  mccoordschange(mcposrTOF_mon_1, mcrotrTOF_mon_1,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrTOF_mon_1, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component TOF_mon_1 (without coords transformations) */
  mcJumpTrace_TOF_mon_1:
  SIG_MESSAGE("TOF_mon_1 (Trace)");
  mcDEBUG_COMP("TOF_mon_1")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
#define sx mcnlsx
#define sy mcnlsy
#define sz mcnlsz
  STORE_NEUTRON(3,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[3]++;
  mcPCounter[3] += p;
  mcP2Counter[3] += p*p;
#define mccompcurname  TOF_mon_1
#define mccompcurtype  TOF_monitor
#define mccompcurindex 3
#define nchan mccTOF_mon_1_nchan
#define filename mccTOF_mon_1_filename
#define TOF_N mccTOF_mon_1_TOF_N
#define TOF_p mccTOF_mon_1_TOF_p
#define TOF_p2 mccTOF_mon_1_TOF_p2
#define t_min mccTOF_mon_1_t_min
#define t_max mccTOF_mon_1_t_max
#define delta_t mccTOF_mon_1_delta_t
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_mon_1_xmin;
MCNUM xmax = mccTOF_mon_1_xmax;
MCNUM ymin = mccTOF_mon_1_ymin;
MCNUM ymax = mccTOF_mon_1_ymax;
MCNUM xwidth = mccTOF_mon_1_xwidth;
MCNUM yheight = mccTOF_mon_1_yheight;
MCNUM t0 = mccTOF_mon_1_t0;
MCNUM t1 = mccTOF_mon_1_t1;
MCNUM dt = mccTOF_mon_1_dt;
MCNUM restore_neutron = mccTOF_mon_1_restore_neutron;
#line 92 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
    int i;

    PROP_Z0;
    if (x>xmin && x<xmax && y>ymin && y<ymax)
    { 
      i = floor((1E6*t-t_min)/delta_t);              /* Bin number */
      if(i >= 0 && i < nchan) {
	TOF_N[i]++;
	TOF_p[i] += p;
	TOF_p2[i] += p*p;
	SCATTER;
      }
    }
    if (restore_neutron) {
      RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
    }
}
#line 13009 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef sz
#undef sy
#undef sx
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component TOF_lmon_1 [4] */
  mccoordschange(mcposrTOF_lmon_1, mcrotrTOF_lmon_1,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrTOF_lmon_1, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component TOF_lmon_1 (without coords transformations) */
  mcJumpTrace_TOF_lmon_1:
  SIG_MESSAGE("TOF_lmon_1 (Trace)");
  mcDEBUG_COMP("TOF_lmon_1")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
#define sx mcnlsx
#define sy mcnlsy
#define sz mcnlsz
  STORE_NEUTRON(4,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[4]++;
  mcPCounter[4] += p;
  mcP2Counter[4] += p*p;
#define mccompcurname  TOF_lmon_1
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 4
#define nlam mccTOF_lmon_1_nlam
#define nt mccTOF_lmon_1_nt
#define filename mccTOF_lmon_1_filename
#define t_0 mccTOF_lmon_1_t_0
#define t_1 mccTOF_lmon_1_t_1
#define tt_0 mccTOF_lmon_1_tt_0
#define tt_1 mccTOF_lmon_1_tt_1
#define TOFL_N mccTOF_lmon_1_TOFL_N
#define TOFL_p mccTOF_lmon_1_TOFL_p
#define TOFL_p2 mccTOF_lmon_1_TOFL_p2
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_lmon_1_xmin;
MCNUM xmax = mccTOF_lmon_1_xmax;
MCNUM ymin = mccTOF_lmon_1_ymin;
MCNUM ymax = mccTOF_lmon_1_ymax;
MCNUM xwidth = mccTOF_lmon_1_xwidth;
MCNUM yheight = mccTOF_lmon_1_yheight;
MCNUM lambda_0 = mccTOF_lmon_1_lambda_0;
MCNUM lambda_1 = mccTOF_lmon_1_lambda_1;
MCNUM restore_neutron = mccTOF_lmon_1_restore_neutron;
#line 87 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
{
    int i,j;
    double div;
    double lambda;

    PROP_Z0;
    lambda = (2*PI/V2K)/sqrt(vx*vx + vy*vy + vz*vz);
    if (x>xmin && x<xmax && y>ymin && y<ymax &&
        lambda > lambda_0 && lambda < lambda_1)
    {
      if (t < tt_1 && t > tt_0)
      {
        i = floor((lambda - lambda_0)*nlam/(lambda_1 - lambda_0));
        j = floor((t-tt_0)*nt/(tt_1-tt_0));
/*  printf("tt_0, tt_1, nt %g %g %i t j %g %i \n",tt_0,tt_1,nt,t,j);
*/        TOFL_N[j][i]++;
        TOFL_p[j][i] += p;
        TOFL_p2[j][i] += p*p;
      }
    } 
    if (restore_neutron) {
      RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
    }  
}
#line 13114 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef sz
#undef sy
#undef sx
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component TOF_mon_2 [5] */
  mccoordschange(mcposrTOF_mon_2, mcrotrTOF_mon_2,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrTOF_mon_2, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component TOF_mon_2 (without coords transformations) */
  mcJumpTrace_TOF_mon_2:
  SIG_MESSAGE("TOF_mon_2 (Trace)");
  mcDEBUG_COMP("TOF_mon_2")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
#define sx mcnlsx
#define sy mcnlsy
#define sz mcnlsz
  STORE_NEUTRON(5,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[5]++;
  mcPCounter[5] += p;
  mcP2Counter[5] += p*p;
#define mccompcurname  TOF_mon_2
#define mccompcurtype  TOF_monitor
#define mccompcurindex 5
#define nchan mccTOF_mon_2_nchan
#define filename mccTOF_mon_2_filename
#define TOF_N mccTOF_mon_2_TOF_N
#define TOF_p mccTOF_mon_2_TOF_p
#define TOF_p2 mccTOF_mon_2_TOF_p2
#define t_min mccTOF_mon_2_t_min
#define t_max mccTOF_mon_2_t_max
#define delta_t mccTOF_mon_2_delta_t
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_mon_2_xmin;
MCNUM xmax = mccTOF_mon_2_xmax;
MCNUM ymin = mccTOF_mon_2_ymin;
MCNUM ymax = mccTOF_mon_2_ymax;
MCNUM xwidth = mccTOF_mon_2_xwidth;
MCNUM yheight = mccTOF_mon_2_yheight;
MCNUM t0 = mccTOF_mon_2_t0;
MCNUM t1 = mccTOF_mon_2_t1;
MCNUM dt = mccTOF_mon_2_dt;
MCNUM restore_neutron = mccTOF_mon_2_restore_neutron;
#line 92 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
    int i;

    PROP_Z0;
    if (x>xmin && x<xmax && y>ymin && y<ymax)
    { 
      i = floor((1E6*t-t_min)/delta_t);              /* Bin number */
      if(i >= 0 && i < nchan) {
	TOF_N[i]++;
	TOF_p[i] += p;
	TOF_p2[i] += p*p;
	SCATTER;
      }
    }
    if (restore_neutron) {
      RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
    }
}
#line 13214 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef sz
#undef sy
#undef sx
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component TOF_lmon_2 [6] */
  mccoordschange(mcposrTOF_lmon_2, mcrotrTOF_lmon_2,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrTOF_lmon_2, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component TOF_lmon_2 (without coords transformations) */
  mcJumpTrace_TOF_lmon_2:
  SIG_MESSAGE("TOF_lmon_2 (Trace)");
  mcDEBUG_COMP("TOF_lmon_2")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
#define sx mcnlsx
#define sy mcnlsy
#define sz mcnlsz
  STORE_NEUTRON(6,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[6]++;
  mcPCounter[6] += p;
  mcP2Counter[6] += p*p;
#define mccompcurname  TOF_lmon_2
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 6
#define nlam mccTOF_lmon_2_nlam
#define nt mccTOF_lmon_2_nt
#define filename mccTOF_lmon_2_filename
#define t_0 mccTOF_lmon_2_t_0
#define t_1 mccTOF_lmon_2_t_1
#define tt_0 mccTOF_lmon_2_tt_0
#define tt_1 mccTOF_lmon_2_tt_1
#define TOFL_N mccTOF_lmon_2_TOFL_N
#define TOFL_p mccTOF_lmon_2_TOFL_p
#define TOFL_p2 mccTOF_lmon_2_TOFL_p2
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_lmon_2_xmin;
MCNUM xmax = mccTOF_lmon_2_xmax;
MCNUM ymin = mccTOF_lmon_2_ymin;
MCNUM ymax = mccTOF_lmon_2_ymax;
MCNUM xwidth = mccTOF_lmon_2_xwidth;
MCNUM yheight = mccTOF_lmon_2_yheight;
MCNUM lambda_0 = mccTOF_lmon_2_lambda_0;
MCNUM lambda_1 = mccTOF_lmon_2_lambda_1;
MCNUM restore_neutron = mccTOF_lmon_2_restore_neutron;
#line 87 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
{
    int i,j;
    double div;
    double lambda;

    PROP_Z0;
    lambda = (2*PI/V2K)/sqrt(vx*vx + vy*vy + vz*vz);
    if (x>xmin && x<xmax && y>ymin && y<ymax &&
        lambda > lambda_0 && lambda < lambda_1)
    {
      if (t < tt_1 && t > tt_0)
      {
        i = floor((lambda - lambda_0)*nlam/(lambda_1 - lambda_0));
        j = floor((t-tt_0)*nt/(tt_1-tt_0));
/*  printf("tt_0, tt_1, nt %g %g %i t j %g %i \n",tt_0,tt_1,nt,t,j);
*/        TOFL_N[j][i]++;
        TOFL_p[j][i] += p;
        TOFL_p2[j][i] += p*p;
      }
    } 
    if (restore_neutron) {
      RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
    }  
}
#line 13319 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef sz
#undef sy
#undef sx
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component Guide1 [7] */
  mccoordschange(mcposrGuide1, mcrotrGuide1,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrGuide1, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Guide1 (without coords transformations) */
  mcJumpTrace_Guide1:
  SIG_MESSAGE("Guide1 (Trace)");
  mcDEBUG_COMP("Guide1")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
  STORE_NEUTRON(7,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[7]++;
  mcPCounter[7] += p;
  mcP2Counter[7] += p*p;
#define mccompcurname  Guide1
#define mccompcurtype  Guide
#define mccompcurindex 7
#define reflect mccGuide1_reflect
#define pTable mccGuide1_pTable
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide1_w1;
MCNUM h1 = mccGuide1_h1;
MCNUM w2 = mccGuide1_w2;
MCNUM h2 = mccGuide1_h2;
MCNUM l = mccGuide1_l;
MCNUM R0 = mccGuide1_R0;
MCNUM Qc = mccGuide1_Qc;
MCNUM alpha = mccGuide1_alpha;
MCNUM m = mccGuide1_m;
MCNUM W = mccGuide1_W;
/* 'Guide1' component has conditional execution */
if (( mcipguidetype == 1 ))

#line 95 "/usr/local/lib/mcstas/optics/Guide.comp"
{
  double t1,t2;                                 /* Intersection times. */
  double av,ah,bv,bh,cv1,cv2,ch1,ch2,d;         /* Intermediate values */
  double weight;                                /* Internal probability weight */
  double vdotn_v1,vdotn_v2,vdotn_h1,vdotn_h2;   /* Dot products. */
  int i;                                        /* Which mirror hit? */
  double q;                                     /* Q [1/AA] of reflection */
  double nlen2;                                 /* Vector lengths squared */

  /* ToDo: These could be precalculated. */
  double ww = .5*(w2 - w1), hh = .5*(h2 - h1);
  double whalf = .5*w1, hhalf = .5*h1;

  /* Propagate neutron to guide entrance. */
  PROP_Z0;
  /* Scatter here to ensure that fully transmitted neutrons will not be
     absorbed in a GROUP construction, e.g. all neutrons - even the
     later absorbed ones are scattered at the guide entry. */
  SCATTER;
  if(x <= -whalf || x >= whalf || y <= -hhalf || y >= hhalf)
    ABSORB;
  for(;;)
  {
    /* Compute the dot products of v and n for the four mirrors. */
    av = l*vx; bv = ww*vz;
    ah = l*vy; bh = hh*vz;
    vdotn_v1 = bv + av;         /* Left vertical */
    vdotn_v2 = bv - av;         /* Right vertical */
    vdotn_h1 = bh + ah;         /* Lower horizontal */
    vdotn_h2 = bh - ah;         /* Upper horizontal */
    /* Compute the dot products of (O - r) and n as c1+c2 and c1-c2 */
    cv1 = -whalf*l - z*ww; cv2 = x*l;
    ch1 = -hhalf*l - z*hh; ch2 = y*l;
    /* Compute intersection times. */
    t1 = (l - z)/vz;
    i = 0;
    if(vdotn_v1 < 0 && (t2 = (cv1 - cv2)/vdotn_v1) < t1)
    {
      t1 = t2;
      i = 1;
    }
    if(vdotn_v2 < 0 && (t2 = (cv1 + cv2)/vdotn_v2) < t1)
    {
      t1 = t2;
      i = 2;
    }
    if(vdotn_h1 < 0 && (t2 = (ch1 - ch2)/vdotn_h1) < t1)
    {
      t1 = t2;
      i = 3;
    }
    if(vdotn_h2 < 0 && (t2 = (ch1 + ch2)/vdotn_h2) < t1)
    {
      t1 = t2;
      i = 4;
    }
    if(i == 0)
      break;                    /* Neutron left guide. */
    PROP_DT(t1);
    switch(i)
    {
      case 1:                   /* Left vertical mirror */
        nlen2 = l*l + ww*ww;
        q = V2Q*(-2)*vdotn_v1/sqrt(nlen2);
        d = 2*vdotn_v1/nlen2;
        vx = vx - d*l;
        vz = vz - d*ww;
        break;
      case 2:                   /* Right vertical mirror */
        nlen2 = l*l + ww*ww;
        q = V2Q*(-2)*vdotn_v2/sqrt(nlen2);
        d = 2*vdotn_v2/nlen2;
        vx = vx + d*l;
        vz = vz - d*ww;
        break;
      case 3:                   /* Lower horizontal mirror */
        nlen2 = l*l + hh*hh;
        q = V2Q*(-2)*vdotn_h1/sqrt(nlen2);
        d = 2*vdotn_h1/nlen2;
        vy = vy - d*l;
        vz = vz - d*hh;
        break;
      case 4:                   /* Upper horizontal mirror */
        nlen2 = l*l + hh*hh;
        q = V2Q*(-2)*vdotn_h2/sqrt(nlen2);
        d = 2*vdotn_h2/nlen2;
        vy = vy + d*l;
        vz = vz - d*hh;
        break;
    }
    /* Now compute reflectivity. */
    weight = 1.0; /* Initial internal weight factor */
    if(m == 0)
      ABSORB;
    if (reflect && strlen(reflect))
      weight = Table_Value(pTable, q, 1);
    else if(q > Qc)
    {
      double arg = (q-m*Qc)/W;
      if(arg < 10)
        weight = .5*(1-tanh(arg))*(1-alpha*(q-Qc));
      else
        ABSORB;                               /* Cutoff ~ 1E-10 */
      weight *= R0;
    } else { /* q <= Qc */
      weight *= R0;
    }
    p *= weight;
    SCATTER;
  }
}
#line 13505 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component Guide2 [8] */
  mccoordschange(mcposrGuide2, mcrotrGuide2,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrGuide2, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Guide2 (without coords transformations) */
  mcJumpTrace_Guide2:
  SIG_MESSAGE("Guide2 (Trace)");
  mcDEBUG_COMP("Guide2")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define sx mcnlsx
#define sy mcnlsy
#define p mcnlp
  STORE_NEUTRON(8,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[8]++;
  mcPCounter[8] += p;
  mcP2Counter[8] += p*p;
#define mccompcurname  Guide2
#define mccompcurtype  Guide_tapering
#define mccompcurindex 8
#define option mccGuide2_option
#define segno mccGuide2_segno
#define w1c mccGuide2_w1c
#define w2c mccGuide2_w2c
#define ww mccGuide2_ww
#define hh mccGuide2_hh
#define whalf mccGuide2_whalf
#define hhalf mccGuide2_hhalf
#define lwhalf mccGuide2_lwhalf
#define lhhalf mccGuide2_lhhalf
#define h1_in mccGuide2_h1_in
#define h2_out mccGuide2_h2_out
#define w1_in mccGuide2_w1_in
#define w2_out mccGuide2_w2_out
#define l_seg mccGuide2_l_seg
#define seg mccGuide2_seg
#define h12 mccGuide2_h12
#define h2 mccGuide2_h2
#define w12 mccGuide2_w12
#define w2 mccGuide2_w2
#define a_ell_q mccGuide2_a_ell_q
#define b_ell_q mccGuide2_b_ell_q
#define lbw mccGuide2_lbw
#define lbh mccGuide2_lbh
#define mxi mccGuide2_mxi
#define u1 mccGuide2_u1
#define u2 mccGuide2_u2
#define div1 mccGuide2_div1
#define p2_para mccGuide2_p2_para
#define test mccGuide2_test
#define Div1 mccGuide2_Div1
#define i mccGuide2_i
#define ii mccGuide2_ii
#define seg mccGuide2_seg
#define fu mccGuide2_fu
#define pos mccGuide2_pos
#define file_name mccGuide2_file_name
#define ep mccGuide2_ep
#define num mccGuide2_num
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide2_w1;
MCNUM h1 = mccGuide2_h1;
MCNUM l = mccGuide2_l;
MCNUM linw = mccGuide2_linw;
MCNUM loutw = mccGuide2_loutw;
MCNUM linh = mccGuide2_linh;
MCNUM louth = mccGuide2_louth;
MCNUM R0 = mccGuide2_R0;
MCNUM Qcx = mccGuide2_Qcx;
MCNUM Qcy = mccGuide2_Qcy;
MCNUM alphax = mccGuide2_alphax;
MCNUM alphay = mccGuide2_alphay;
MCNUM W = mccGuide2_W;
MCNUM mx = mccGuide2_mx;
MCNUM my = mccGuide2_my;
/* 'Guide2' component has conditional execution */
if (( mcipguidetype == 2 ))

#line 452 "/usr/local/lib/mcstas/optics/Guide_tapering.comp"
{
  double t1,t2,ts,zr;                           /* Intersection times. */
  double av,ah,bv,bh,cv1,cv2,ch1,ch2,dd;        /* Intermediate values */
  double vdotn_v1,vdotn_v2,vdotn_h1,vdotn_h2;   /* Dot products. */
  int i;                                        /* Which mirror hit? */
  double q;                                     /* Q [1/AA] of reflection */
  double vlen2,nlen2;                           /* Vector lengths squared */
  double edge;
  double hadj;                                  /* Channel displacement */
  double sz=0;
  int ii;
  Coords mctc1,mctc2;
  Rotation mctr1;

  /* Propagate neutron to guide entrance. */
  PROP_Z0;
  for (ii=0;ii<seg;ii++)
  {
    zr=ii*l_seg;
    /* Propagate neutron to segment entrance. */
    ts=(zr-z)/vz;
    PROP_DT(ts);
    if(x <= w1_in[ii]/-2.0 || x >= w1_in[ii]/2.0 || y <= -hhalf[ii] || y >= hhalf[ii])
      ABSORB;
    /* Shift origin to center of channel hit (absorb if hit dividing walls) */
    x += w1_in[ii]/2.0;
    edge = floor(x/w1c[ii])*w1c[ii];
    if(x - edge > w1c[ii])
    {
      x -= w1_in[ii]/2.0; /* Re-adjust origin */
      ABSORB;
    }
    x -= (edge + (w1c[ii]/2.0));
    hadj = edge + (w1c[ii]/2.0) - w1_in[ii]/2.0;
    for(;;)
    {
      /* Compute the dot products of v and n for the four mirrors. */
      ts=(zr-z)/vz;
      av = l_seg*vx; bv = ww[ii]*vz;
      ah = l_seg*vy; bh = hh[ii]*vz;
      vdotn_v1 = bv + av;         /* Left vertical */
      vdotn_v2 = bv - av;         /* Right vertical */
      vdotn_h1 = bh + ah;         /* Lower horizontal */
      vdotn_h2 = bh - ah;         /* Upper horizontal */
      /* Compute the dot products of (O - r) and n as c1+c2 and c1-c2 */
      cv1 = -whalf[ii]*l_seg - (z-zr)*ww[ii]; cv2 = x*l_seg;
      ch1 = -hhalf[ii]*l_seg - (z-zr)*hh[ii]; ch2 = y*l_seg;
      /* Compute intersection times. */
      t1 = (zr + l_seg - z)/vz;
      i = 0;
      if(vdotn_v1 < 0 && (t2 = (cv1 - cv2)/vdotn_v1) < t1)
      {
        t1 = t2;
        i = 1;
      }
      if(vdotn_v2 < 0 && (t2 = (cv1 + cv2)/vdotn_v2) < t1)
      {
        t1 = t2;
        i = 2;
      }
      if(vdotn_h1 < 0 && (t2 = (ch1 - ch2)/vdotn_h1) < t1)
      {
        t1 = t2;
        i = 3;
      }
      if(vdotn_h2 < 0 && (t2 = (ch1 + ch2)/vdotn_h2) < t1)
      {
        t1 = t2;
        i = 4;
      }
      if(i == 0)
      {
        break;                    /* Neutron left guide. */
      }
      PROP_DT(t1);
      switch(i)
      {
        case 1:                   /* Left vertical mirror */
          nlen2 = l_seg*l_seg + ww[ii]*ww[ii];
          q = V2Q*(-2)*vdotn_v1/sqrt(nlen2);
          dd = 2*vdotn_v1/nlen2;
          vx = vx - dd*l_seg;
          vz = vz - dd*ww[ii];
          break;
        case 2:                   /* Right vertical mirror */
          nlen2 = l_seg*l_seg + ww[ii]*ww[ii];
          q = V2Q*(-2)*vdotn_v2/sqrt(nlen2);
          dd = 2*vdotn_v2/nlen2;
          vx = vx + dd*l_seg;
          vz = vz - dd*ww[ii];
          break;
        case 3:                   /* Lower horizontal mirror */
          nlen2 = l_seg*l_seg + hh[ii]*hh[ii];
          q = V2Q*(-2)*vdotn_h1/sqrt(nlen2);
          dd = 2*vdotn_h1/nlen2;
          vy = vy - dd*l_seg;
          vz = vz - dd*hh[ii];
          break;
        case 4:                   /* Upper horizontal mirror */
          nlen2 = l_seg*l_seg + hh[ii]*hh[ii];
          q = V2Q*(-2)*vdotn_h2/sqrt(nlen2);
          dd = 2*vdotn_h2/nlen2;
          vy = vy + dd*l_seg;
          vz = vz - dd*hh[ii];
          break;
      }
      /* Now compute reflectivity. */
      if((i <= 2 && mx == 0) || (i > 2 && my == 0))
      {
        x += hadj; /* Re-adjust origin */
        ABSORB;
      }
      if((i <= 2 && q > Qcx) || (i > 2 && q > Qcy))
      {
        if (i <= 2)
        {
          double arg = (q - mx*Qcx)/W;
          if(arg < 10)
            p *= .5*(1-tanh(arg))*(1-alphax*(q-Qcx));
          else
          {
            x += hadj; /* Re-adjust origin */
            ABSORB;                               /* Cutoff ~ 1E-10 */
          }
        } else {
          double arg = (q - my*Qcy)/W;
          if(arg < 10)
            p *= .5*(1-tanh(arg))*(1-alphay*(q-Qcy));
          else
          {
            x += hadj; /* Re-adjust origin */
            ABSORB;                               /* Cutoff ~ 1E-10 */
          }
        }
      }
      p *= R0;
      x += hadj; SCATTER; x -= hadj;
    }
    x += hadj; /* Re-adjust origin */
  }

}
#line 13753 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef num
#undef ep
#undef file_name
#undef pos
#undef fu
#undef seg
#undef ii
#undef i
#undef Div1
#undef test
#undef p2_para
#undef div1
#undef u2
#undef u1
#undef mxi
#undef lbh
#undef lbw
#undef b_ell_q
#undef a_ell_q
#undef w2
#undef w12
#undef h2
#undef h12
#undef seg
#undef l_seg
#undef w2_out
#undef w1_in
#undef h2_out
#undef h1_in
#undef lhhalf
#undef lwhalf
#undef hhalf
#undef whalf
#undef hh
#undef ww
#undef w2c
#undef w1c
#undef segno
#undef option
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef p
#undef sy
#undef sx
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component Guide3 [9] */
  mccoordschange(mcposrGuide3, mcrotrGuide3,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrGuide3, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Guide3 (without coords transformations) */
  mcJumpTrace_Guide3:
  SIG_MESSAGE("Guide3 (Trace)");
  mcDEBUG_COMP("Guide3")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define sx mcnlsx
#define sy mcnlsy
#define p mcnlp
  STORE_NEUTRON(9,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[9]++;
  mcPCounter[9] += p;
  mcP2Counter[9] += p*p;
#define mccompcurname  Guide3
#define mccompcurtype  Guide_tapering
#define mccompcurindex 9
#define option mccGuide3_option
#define segno mccGuide3_segno
#define w1c mccGuide3_w1c
#define w2c mccGuide3_w2c
#define ww mccGuide3_ww
#define hh mccGuide3_hh
#define whalf mccGuide3_whalf
#define hhalf mccGuide3_hhalf
#define lwhalf mccGuide3_lwhalf
#define lhhalf mccGuide3_lhhalf
#define h1_in mccGuide3_h1_in
#define h2_out mccGuide3_h2_out
#define w1_in mccGuide3_w1_in
#define w2_out mccGuide3_w2_out
#define l_seg mccGuide3_l_seg
#define seg mccGuide3_seg
#define h12 mccGuide3_h12
#define h2 mccGuide3_h2
#define w12 mccGuide3_w12
#define w2 mccGuide3_w2
#define a_ell_q mccGuide3_a_ell_q
#define b_ell_q mccGuide3_b_ell_q
#define lbw mccGuide3_lbw
#define lbh mccGuide3_lbh
#define mxi mccGuide3_mxi
#define u1 mccGuide3_u1
#define u2 mccGuide3_u2
#define div1 mccGuide3_div1
#define p2_para mccGuide3_p2_para
#define test mccGuide3_test
#define Div1 mccGuide3_Div1
#define i mccGuide3_i
#define ii mccGuide3_ii
#define seg mccGuide3_seg
#define fu mccGuide3_fu
#define pos mccGuide3_pos
#define file_name mccGuide3_file_name
#define ep mccGuide3_ep
#define num mccGuide3_num
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide3_w1;
MCNUM h1 = mccGuide3_h1;
MCNUM l = mccGuide3_l;
MCNUM linw = mccGuide3_linw;
MCNUM loutw = mccGuide3_loutw;
MCNUM linh = mccGuide3_linh;
MCNUM louth = mccGuide3_louth;
MCNUM R0 = mccGuide3_R0;
MCNUM Qcx = mccGuide3_Qcx;
MCNUM Qcy = mccGuide3_Qcy;
MCNUM alphax = mccGuide3_alphax;
MCNUM alphay = mccGuide3_alphay;
MCNUM W = mccGuide3_W;
MCNUM mx = mccGuide3_mx;
MCNUM my = mccGuide3_my;
/* 'Guide3' component has conditional execution */
if (( mcipguidetype == 3 ))

#line 452 "/usr/local/lib/mcstas/optics/Guide_tapering.comp"
{
  double t1,t2,ts,zr;                           /* Intersection times. */
  double av,ah,bv,bh,cv1,cv2,ch1,ch2,dd;        /* Intermediate values */
  double vdotn_v1,vdotn_v2,vdotn_h1,vdotn_h2;   /* Dot products. */
  int i;                                        /* Which mirror hit? */
  double q;                                     /* Q [1/AA] of reflection */
  double vlen2,nlen2;                           /* Vector lengths squared */
  double edge;
  double hadj;                                  /* Channel displacement */
  double sz=0;
  int ii;
  Coords mctc1,mctc2;
  Rotation mctr1;

  /* Propagate neutron to guide entrance. */
  PROP_Z0;
  for (ii=0;ii<seg;ii++)
  {
    zr=ii*l_seg;
    /* Propagate neutron to segment entrance. */
    ts=(zr-z)/vz;
    PROP_DT(ts);
    if(x <= w1_in[ii]/-2.0 || x >= w1_in[ii]/2.0 || y <= -hhalf[ii] || y >= hhalf[ii])
      ABSORB;
    /* Shift origin to center of channel hit (absorb if hit dividing walls) */
    x += w1_in[ii]/2.0;
    edge = floor(x/w1c[ii])*w1c[ii];
    if(x - edge > w1c[ii])
    {
      x -= w1_in[ii]/2.0; /* Re-adjust origin */
      ABSORB;
    }
    x -= (edge + (w1c[ii]/2.0));
    hadj = edge + (w1c[ii]/2.0) - w1_in[ii]/2.0;
    for(;;)
    {
      /* Compute the dot products of v and n for the four mirrors. */
      ts=(zr-z)/vz;
      av = l_seg*vx; bv = ww[ii]*vz;
      ah = l_seg*vy; bh = hh[ii]*vz;
      vdotn_v1 = bv + av;         /* Left vertical */
      vdotn_v2 = bv - av;         /* Right vertical */
      vdotn_h1 = bh + ah;         /* Lower horizontal */
      vdotn_h2 = bh - ah;         /* Upper horizontal */
      /* Compute the dot products of (O - r) and n as c1+c2 and c1-c2 */
      cv1 = -whalf[ii]*l_seg - (z-zr)*ww[ii]; cv2 = x*l_seg;
      ch1 = -hhalf[ii]*l_seg - (z-zr)*hh[ii]; ch2 = y*l_seg;
      /* Compute intersection times. */
      t1 = (zr + l_seg - z)/vz;
      i = 0;
      if(vdotn_v1 < 0 && (t2 = (cv1 - cv2)/vdotn_v1) < t1)
      {
        t1 = t2;
        i = 1;
      }
      if(vdotn_v2 < 0 && (t2 = (cv1 + cv2)/vdotn_v2) < t1)
      {
        t1 = t2;
        i = 2;
      }
      if(vdotn_h1 < 0 && (t2 = (ch1 - ch2)/vdotn_h1) < t1)
      {
        t1 = t2;
        i = 3;
      }
      if(vdotn_h2 < 0 && (t2 = (ch1 + ch2)/vdotn_h2) < t1)
      {
        t1 = t2;
        i = 4;
      }
      if(i == 0)
      {
        break;                    /* Neutron left guide. */
      }
      PROP_DT(t1);
      switch(i)
      {
        case 1:                   /* Left vertical mirror */
          nlen2 = l_seg*l_seg + ww[ii]*ww[ii];
          q = V2Q*(-2)*vdotn_v1/sqrt(nlen2);
          dd = 2*vdotn_v1/nlen2;
          vx = vx - dd*l_seg;
          vz = vz - dd*ww[ii];
          break;
        case 2:                   /* Right vertical mirror */
          nlen2 = l_seg*l_seg + ww[ii]*ww[ii];
          q = V2Q*(-2)*vdotn_v2/sqrt(nlen2);
          dd = 2*vdotn_v2/nlen2;
          vx = vx + dd*l_seg;
          vz = vz - dd*ww[ii];
          break;
        case 3:                   /* Lower horizontal mirror */
          nlen2 = l_seg*l_seg + hh[ii]*hh[ii];
          q = V2Q*(-2)*vdotn_h1/sqrt(nlen2);
          dd = 2*vdotn_h1/nlen2;
          vy = vy - dd*l_seg;
          vz = vz - dd*hh[ii];
          break;
        case 4:                   /* Upper horizontal mirror */
          nlen2 = l_seg*l_seg + hh[ii]*hh[ii];
          q = V2Q*(-2)*vdotn_h2/sqrt(nlen2);
          dd = 2*vdotn_h2/nlen2;
          vy = vy + dd*l_seg;
          vz = vz - dd*hh[ii];
          break;
      }
      /* Now compute reflectivity. */
      if((i <= 2 && mx == 0) || (i > 2 && my == 0))
      {
        x += hadj; /* Re-adjust origin */
        ABSORB;
      }
      if((i <= 2 && q > Qcx) || (i > 2 && q > Qcy))
      {
        if (i <= 2)
        {
          double arg = (q - mx*Qcx)/W;
          if(arg < 10)
            p *= .5*(1-tanh(arg))*(1-alphax*(q-Qcx));
          else
          {
            x += hadj; /* Re-adjust origin */
            ABSORB;                               /* Cutoff ~ 1E-10 */
          }
        } else {
          double arg = (q - my*Qcy)/W;
          if(arg < 10)
            p *= .5*(1-tanh(arg))*(1-alphay*(q-Qcy));
          else
          {
            x += hadj; /* Re-adjust origin */
            ABSORB;                               /* Cutoff ~ 1E-10 */
          }
        }
      }
      p *= R0;
      x += hadj; SCATTER; x -= hadj;
    }
    x += hadj; /* Re-adjust origin */
  }

}
#line 14038 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef num
#undef ep
#undef file_name
#undef pos
#undef fu
#undef seg
#undef ii
#undef i
#undef Div1
#undef test
#undef p2_para
#undef div1
#undef u2
#undef u1
#undef mxi
#undef lbh
#undef lbw
#undef b_ell_q
#undef a_ell_q
#undef w2
#undef w12
#undef h2
#undef h12
#undef seg
#undef l_seg
#undef w2_out
#undef w1_in
#undef h2_out
#undef h1_in
#undef lhhalf
#undef lwhalf
#undef hhalf
#undef whalf
#undef hh
#undef ww
#undef w2c
#undef w1c
#undef segno
#undef option
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef p
#undef sy
#undef sx
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component Guide4a [10] */
  mccoordschange(mcposrGuide4a, mcrotrGuide4a,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrGuide4a, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Guide4a (without coords transformations) */
  mcJumpTrace_Guide4a:
  SIG_MESSAGE("Guide4a (Trace)");
  mcDEBUG_COMP("Guide4a")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
  STORE_NEUTRON(10,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[10]++;
  mcPCounter[10] += p;
  mcP2Counter[10] += p*p;
#define mccompcurname  Guide4a
#define mccompcurtype  Guide
#define mccompcurindex 10
#define reflect mccGuide4a_reflect
#define pTable mccGuide4a_pTable
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide4a_w1;
MCNUM h1 = mccGuide4a_h1;
MCNUM w2 = mccGuide4a_w2;
MCNUM h2 = mccGuide4a_h2;
MCNUM l = mccGuide4a_l;
MCNUM R0 = mccGuide4a_R0;
MCNUM Qc = mccGuide4a_Qc;
MCNUM alpha = mccGuide4a_alpha;
MCNUM m = mccGuide4a_m;
MCNUM W = mccGuide4a_W;
/* 'Guide4a' component has conditional execution */
if (( mcipguidetype == 4 ))

#line 95 "/usr/local/lib/mcstas/optics/Guide.comp"
{
  double t1,t2;                                 /* Intersection times. */
  double av,ah,bv,bh,cv1,cv2,ch1,ch2,d;         /* Intermediate values */
  double weight;                                /* Internal probability weight */
  double vdotn_v1,vdotn_v2,vdotn_h1,vdotn_h2;   /* Dot products. */
  int i;                                        /* Which mirror hit? */
  double q;                                     /* Q [1/AA] of reflection */
  double nlen2;                                 /* Vector lengths squared */

  /* ToDo: These could be precalculated. */
  double ww = .5*(w2 - w1), hh = .5*(h2 - h1);
  double whalf = .5*w1, hhalf = .5*h1;

  /* Propagate neutron to guide entrance. */
  PROP_Z0;
  /* Scatter here to ensure that fully transmitted neutrons will not be
     absorbed in a GROUP construction, e.g. all neutrons - even the
     later absorbed ones are scattered at the guide entry. */
  SCATTER;
  if(x <= -whalf || x >= whalf || y <= -hhalf || y >= hhalf)
    ABSORB;
  for(;;)
  {
    /* Compute the dot products of v and n for the four mirrors. */
    av = l*vx; bv = ww*vz;
    ah = l*vy; bh = hh*vz;
    vdotn_v1 = bv + av;         /* Left vertical */
    vdotn_v2 = bv - av;         /* Right vertical */
    vdotn_h1 = bh + ah;         /* Lower horizontal */
    vdotn_h2 = bh - ah;         /* Upper horizontal */
    /* Compute the dot products of (O - r) and n as c1+c2 and c1-c2 */
    cv1 = -whalf*l - z*ww; cv2 = x*l;
    ch1 = -hhalf*l - z*hh; ch2 = y*l;
    /* Compute intersection times. */
    t1 = (l - z)/vz;
    i = 0;
    if(vdotn_v1 < 0 && (t2 = (cv1 - cv2)/vdotn_v1) < t1)
    {
      t1 = t2;
      i = 1;
    }
    if(vdotn_v2 < 0 && (t2 = (cv1 + cv2)/vdotn_v2) < t1)
    {
      t1 = t2;
      i = 2;
    }
    if(vdotn_h1 < 0 && (t2 = (ch1 - ch2)/vdotn_h1) < t1)
    {
      t1 = t2;
      i = 3;
    }
    if(vdotn_h2 < 0 && (t2 = (ch1 + ch2)/vdotn_h2) < t1)
    {
      t1 = t2;
      i = 4;
    }
    if(i == 0)
      break;                    /* Neutron left guide. */
    PROP_DT(t1);
    switch(i)
    {
      case 1:                   /* Left vertical mirror */
        nlen2 = l*l + ww*ww;
        q = V2Q*(-2)*vdotn_v1/sqrt(nlen2);
        d = 2*vdotn_v1/nlen2;
        vx = vx - d*l;
        vz = vz - d*ww;
        break;
      case 2:                   /* Right vertical mirror */
        nlen2 = l*l + ww*ww;
        q = V2Q*(-2)*vdotn_v2/sqrt(nlen2);
        d = 2*vdotn_v2/nlen2;
        vx = vx + d*l;
        vz = vz - d*ww;
        break;
      case 3:                   /* Lower horizontal mirror */
        nlen2 = l*l + hh*hh;
        q = V2Q*(-2)*vdotn_h1/sqrt(nlen2);
        d = 2*vdotn_h1/nlen2;
        vy = vy - d*l;
        vz = vz - d*hh;
        break;
      case 4:                   /* Upper horizontal mirror */
        nlen2 = l*l + hh*hh;
        q = V2Q*(-2)*vdotn_h2/sqrt(nlen2);
        d = 2*vdotn_h2/nlen2;
        vy = vy + d*l;
        vz = vz - d*hh;
        break;
    }
    /* Now compute reflectivity. */
    weight = 1.0; /* Initial internal weight factor */
    if(m == 0)
      ABSORB;
    if (reflect && strlen(reflect))
      weight = Table_Value(pTable, q, 1);
    else if(q > Qc)
    {
      double arg = (q-m*Qc)/W;
      if(arg < 10)
        weight = .5*(1-tanh(arg))*(1-alpha*(q-Qc));
      else
        ABSORB;                               /* Cutoff ~ 1E-10 */
      weight *= R0;
    } else { /* q <= Qc */
      weight *= R0;
    }
    p *= weight;
    SCATTER;
  }
}
#line 14250 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component Guide4b [11] */
  mccoordschange(mcposrGuide4b, mcrotrGuide4b,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrGuide4b, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Guide4b (without coords transformations) */
  mcJumpTrace_Guide4b:
  SIG_MESSAGE("Guide4b (Trace)");
  mcDEBUG_COMP("Guide4b")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
  STORE_NEUTRON(11,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[11]++;
  mcPCounter[11] += p;
  mcP2Counter[11] += p*p;
#define mccompcurname  Guide4b
#define mccompcurtype  Guide
#define mccompcurindex 11
#define reflect mccGuide4b_reflect
#define pTable mccGuide4b_pTable
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide4b_w1;
MCNUM h1 = mccGuide4b_h1;
MCNUM w2 = mccGuide4b_w2;
MCNUM h2 = mccGuide4b_h2;
MCNUM l = mccGuide4b_l;
MCNUM R0 = mccGuide4b_R0;
MCNUM Qc = mccGuide4b_Qc;
MCNUM alpha = mccGuide4b_alpha;
MCNUM m = mccGuide4b_m;
MCNUM W = mccGuide4b_W;
/* 'Guide4b' component has conditional execution */
if (( mcipguidetype == 4 ))

#line 95 "/usr/local/lib/mcstas/optics/Guide.comp"
{
  double t1,t2;                                 /* Intersection times. */
  double av,ah,bv,bh,cv1,cv2,ch1,ch2,d;         /* Intermediate values */
  double weight;                                /* Internal probability weight */
  double vdotn_v1,vdotn_v2,vdotn_h1,vdotn_h2;   /* Dot products. */
  int i;                                        /* Which mirror hit? */
  double q;                                     /* Q [1/AA] of reflection */
  double nlen2;                                 /* Vector lengths squared */

  /* ToDo: These could be precalculated. */
  double ww = .5*(w2 - w1), hh = .5*(h2 - h1);
  double whalf = .5*w1, hhalf = .5*h1;

  /* Propagate neutron to guide entrance. */
  PROP_Z0;
  /* Scatter here to ensure that fully transmitted neutrons will not be
     absorbed in a GROUP construction, e.g. all neutrons - even the
     later absorbed ones are scattered at the guide entry. */
  SCATTER;
  if(x <= -whalf || x >= whalf || y <= -hhalf || y >= hhalf)
    ABSORB;
  for(;;)
  {
    /* Compute the dot products of v and n for the four mirrors. */
    av = l*vx; bv = ww*vz;
    ah = l*vy; bh = hh*vz;
    vdotn_v1 = bv + av;         /* Left vertical */
    vdotn_v2 = bv - av;         /* Right vertical */
    vdotn_h1 = bh + ah;         /* Lower horizontal */
    vdotn_h2 = bh - ah;         /* Upper horizontal */
    /* Compute the dot products of (O - r) and n as c1+c2 and c1-c2 */
    cv1 = -whalf*l - z*ww; cv2 = x*l;
    ch1 = -hhalf*l - z*hh; ch2 = y*l;
    /* Compute intersection times. */
    t1 = (l - z)/vz;
    i = 0;
    if(vdotn_v1 < 0 && (t2 = (cv1 - cv2)/vdotn_v1) < t1)
    {
      t1 = t2;
      i = 1;
    }
    if(vdotn_v2 < 0 && (t2 = (cv1 + cv2)/vdotn_v2) < t1)
    {
      t1 = t2;
      i = 2;
    }
    if(vdotn_h1 < 0 && (t2 = (ch1 - ch2)/vdotn_h1) < t1)
    {
      t1 = t2;
      i = 3;
    }
    if(vdotn_h2 < 0 && (t2 = (ch1 + ch2)/vdotn_h2) < t1)
    {
      t1 = t2;
      i = 4;
    }
    if(i == 0)
      break;                    /* Neutron left guide. */
    PROP_DT(t1);
    switch(i)
    {
      case 1:                   /* Left vertical mirror */
        nlen2 = l*l + ww*ww;
        q = V2Q*(-2)*vdotn_v1/sqrt(nlen2);
        d = 2*vdotn_v1/nlen2;
        vx = vx - d*l;
        vz = vz - d*ww;
        break;
      case 2:                   /* Right vertical mirror */
        nlen2 = l*l + ww*ww;
        q = V2Q*(-2)*vdotn_v2/sqrt(nlen2);
        d = 2*vdotn_v2/nlen2;
        vx = vx + d*l;
        vz = vz - d*ww;
        break;
      case 3:                   /* Lower horizontal mirror */
        nlen2 = l*l + hh*hh;
        q = V2Q*(-2)*vdotn_h1/sqrt(nlen2);
        d = 2*vdotn_h1/nlen2;
        vy = vy - d*l;
        vz = vz - d*hh;
        break;
      case 4:                   /* Upper horizontal mirror */
        nlen2 = l*l + hh*hh;
        q = V2Q*(-2)*vdotn_h2/sqrt(nlen2);
        d = 2*vdotn_h2/nlen2;
        vy = vy + d*l;
        vz = vz - d*hh;
        break;
    }
    /* Now compute reflectivity. */
    weight = 1.0; /* Initial internal weight factor */
    if(m == 0)
      ABSORB;
    if (reflect && strlen(reflect))
      weight = Table_Value(pTable, q, 1);
    else if(q > Qc)
    {
      double arg = (q-m*Qc)/W;
      if(arg < 10)
        weight = .5*(1-tanh(arg))*(1-alpha*(q-Qc));
      else
        ABSORB;                               /* Cutoff ~ 1E-10 */
      weight *= R0;
    } else { /* q <= Qc */
      weight *= R0;
    }
    p *= weight;
    SCATTER;
  }
}
#line 14425 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component Guide4c [12] */
  mccoordschange(mcposrGuide4c, mcrotrGuide4c,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrGuide4c, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Guide4c (without coords transformations) */
  mcJumpTrace_Guide4c:
  SIG_MESSAGE("Guide4c (Trace)");
  mcDEBUG_COMP("Guide4c")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
  STORE_NEUTRON(12,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[12]++;
  mcPCounter[12] += p;
  mcP2Counter[12] += p*p;
#define mccompcurname  Guide4c
#define mccompcurtype  Guide
#define mccompcurindex 12
#define reflect mccGuide4c_reflect
#define pTable mccGuide4c_pTable
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide4c_w1;
MCNUM h1 = mccGuide4c_h1;
MCNUM w2 = mccGuide4c_w2;
MCNUM h2 = mccGuide4c_h2;
MCNUM l = mccGuide4c_l;
MCNUM R0 = mccGuide4c_R0;
MCNUM Qc = mccGuide4c_Qc;
MCNUM alpha = mccGuide4c_alpha;
MCNUM m = mccGuide4c_m;
MCNUM W = mccGuide4c_W;
/* 'Guide4c' component has conditional execution */
if (( mcipguidetype == 4 ))

#line 95 "/usr/local/lib/mcstas/optics/Guide.comp"
{
  double t1,t2;                                 /* Intersection times. */
  double av,ah,bv,bh,cv1,cv2,ch1,ch2,d;         /* Intermediate values */
  double weight;                                /* Internal probability weight */
  double vdotn_v1,vdotn_v2,vdotn_h1,vdotn_h2;   /* Dot products. */
  int i;                                        /* Which mirror hit? */
  double q;                                     /* Q [1/AA] of reflection */
  double nlen2;                                 /* Vector lengths squared */

  /* ToDo: These could be precalculated. */
  double ww = .5*(w2 - w1), hh = .5*(h2 - h1);
  double whalf = .5*w1, hhalf = .5*h1;

  /* Propagate neutron to guide entrance. */
  PROP_Z0;
  /* Scatter here to ensure that fully transmitted neutrons will not be
     absorbed in a GROUP construction, e.g. all neutrons - even the
     later absorbed ones are scattered at the guide entry. */
  SCATTER;
  if(x <= -whalf || x >= whalf || y <= -hhalf || y >= hhalf)
    ABSORB;
  for(;;)
  {
    /* Compute the dot products of v and n for the four mirrors. */
    av = l*vx; bv = ww*vz;
    ah = l*vy; bh = hh*vz;
    vdotn_v1 = bv + av;         /* Left vertical */
    vdotn_v2 = bv - av;         /* Right vertical */
    vdotn_h1 = bh + ah;         /* Lower horizontal */
    vdotn_h2 = bh - ah;         /* Upper horizontal */
    /* Compute the dot products of (O - r) and n as c1+c2 and c1-c2 */
    cv1 = -whalf*l - z*ww; cv2 = x*l;
    ch1 = -hhalf*l - z*hh; ch2 = y*l;
    /* Compute intersection times. */
    t1 = (l - z)/vz;
    i = 0;
    if(vdotn_v1 < 0 && (t2 = (cv1 - cv2)/vdotn_v1) < t1)
    {
      t1 = t2;
      i = 1;
    }
    if(vdotn_v2 < 0 && (t2 = (cv1 + cv2)/vdotn_v2) < t1)
    {
      t1 = t2;
      i = 2;
    }
    if(vdotn_h1 < 0 && (t2 = (ch1 - ch2)/vdotn_h1) < t1)
    {
      t1 = t2;
      i = 3;
    }
    if(vdotn_h2 < 0 && (t2 = (ch1 + ch2)/vdotn_h2) < t1)
    {
      t1 = t2;
      i = 4;
    }
    if(i == 0)
      break;                    /* Neutron left guide. */
    PROP_DT(t1);
    switch(i)
    {
      case 1:                   /* Left vertical mirror */
        nlen2 = l*l + ww*ww;
        q = V2Q*(-2)*vdotn_v1/sqrt(nlen2);
        d = 2*vdotn_v1/nlen2;
        vx = vx - d*l;
        vz = vz - d*ww;
        break;
      case 2:                   /* Right vertical mirror */
        nlen2 = l*l + ww*ww;
        q = V2Q*(-2)*vdotn_v2/sqrt(nlen2);
        d = 2*vdotn_v2/nlen2;
        vx = vx + d*l;
        vz = vz - d*ww;
        break;
      case 3:                   /* Lower horizontal mirror */
        nlen2 = l*l + hh*hh;
        q = V2Q*(-2)*vdotn_h1/sqrt(nlen2);
        d = 2*vdotn_h1/nlen2;
        vy = vy - d*l;
        vz = vz - d*hh;
        break;
      case 4:                   /* Upper horizontal mirror */
        nlen2 = l*l + hh*hh;
        q = V2Q*(-2)*vdotn_h2/sqrt(nlen2);
        d = 2*vdotn_h2/nlen2;
        vy = vy + d*l;
        vz = vz - d*hh;
        break;
    }
    /* Now compute reflectivity. */
    weight = 1.0; /* Initial internal weight factor */
    if(m == 0)
      ABSORB;
    if (reflect && strlen(reflect))
      weight = Table_Value(pTable, q, 1);
    else if(q > Qc)
    {
      double arg = (q-m*Qc)/W;
      if(arg < 10)
        weight = .5*(1-tanh(arg))*(1-alpha*(q-Qc));
      else
        ABSORB;                               /* Cutoff ~ 1E-10 */
      weight *= R0;
    } else { /* q <= Qc */
      weight *= R0;
    }
    p *= weight;
    SCATTER;
  }
}
#line 14600 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component TOF_mon_3 [13] */
  mccoordschange(mcposrTOF_mon_3, mcrotrTOF_mon_3,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrTOF_mon_3, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component TOF_mon_3 (without coords transformations) */
  mcJumpTrace_TOF_mon_3:
  SIG_MESSAGE("TOF_mon_3 (Trace)");
  mcDEBUG_COMP("TOF_mon_3")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
#define sx mcnlsx
#define sy mcnlsy
#define sz mcnlsz
  STORE_NEUTRON(13,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[13]++;
  mcPCounter[13] += p;
  mcP2Counter[13] += p*p;
#define mccompcurname  TOF_mon_3
#define mccompcurtype  TOF_monitor
#define mccompcurindex 13
#define nchan mccTOF_mon_3_nchan
#define filename mccTOF_mon_3_filename
#define TOF_N mccTOF_mon_3_TOF_N
#define TOF_p mccTOF_mon_3_TOF_p
#define TOF_p2 mccTOF_mon_3_TOF_p2
#define t_min mccTOF_mon_3_t_min
#define t_max mccTOF_mon_3_t_max
#define delta_t mccTOF_mon_3_delta_t
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_mon_3_xmin;
MCNUM xmax = mccTOF_mon_3_xmax;
MCNUM ymin = mccTOF_mon_3_ymin;
MCNUM ymax = mccTOF_mon_3_ymax;
MCNUM xwidth = mccTOF_mon_3_xwidth;
MCNUM yheight = mccTOF_mon_3_yheight;
MCNUM t0 = mccTOF_mon_3_t0;
MCNUM t1 = mccTOF_mon_3_t1;
MCNUM dt = mccTOF_mon_3_dt;
MCNUM restore_neutron = mccTOF_mon_3_restore_neutron;
#line 92 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
    int i;

    PROP_Z0;
    if (x>xmin && x<xmax && y>ymin && y<ymax)
    { 
      i = floor((1E6*t-t_min)/delta_t);              /* Bin number */
      if(i >= 0 && i < nchan) {
	TOF_N[i]++;
	TOF_p[i] += p;
	TOF_p2[i] += p*p;
	SCATTER;
      }
    }
    if (restore_neutron) {
      RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
    }
}
#line 14689 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef sz
#undef sy
#undef sx
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component TOF_lmon_3 [14] */
  mccoordschange(mcposrTOF_lmon_3, mcrotrTOF_lmon_3,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrTOF_lmon_3, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component TOF_lmon_3 (without coords transformations) */
  mcJumpTrace_TOF_lmon_3:
  SIG_MESSAGE("TOF_lmon_3 (Trace)");
  mcDEBUG_COMP("TOF_lmon_3")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
#define sx mcnlsx
#define sy mcnlsy
#define sz mcnlsz
  STORE_NEUTRON(14,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[14]++;
  mcPCounter[14] += p;
  mcP2Counter[14] += p*p;
#define mccompcurname  TOF_lmon_3
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 14
#define nlam mccTOF_lmon_3_nlam
#define nt mccTOF_lmon_3_nt
#define filename mccTOF_lmon_3_filename
#define t_0 mccTOF_lmon_3_t_0
#define t_1 mccTOF_lmon_3_t_1
#define tt_0 mccTOF_lmon_3_tt_0
#define tt_1 mccTOF_lmon_3_tt_1
#define TOFL_N mccTOF_lmon_3_TOFL_N
#define TOFL_p mccTOF_lmon_3_TOFL_p
#define TOFL_p2 mccTOF_lmon_3_TOFL_p2
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_lmon_3_xmin;
MCNUM xmax = mccTOF_lmon_3_xmax;
MCNUM ymin = mccTOF_lmon_3_ymin;
MCNUM ymax = mccTOF_lmon_3_ymax;
MCNUM xwidth = mccTOF_lmon_3_xwidth;
MCNUM yheight = mccTOF_lmon_3_yheight;
MCNUM lambda_0 = mccTOF_lmon_3_lambda_0;
MCNUM lambda_1 = mccTOF_lmon_3_lambda_1;
MCNUM restore_neutron = mccTOF_lmon_3_restore_neutron;
#line 87 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
{
    int i,j;
    double div;
    double lambda;

    PROP_Z0;
    lambda = (2*PI/V2K)/sqrt(vx*vx + vy*vy + vz*vz);
    if (x>xmin && x<xmax && y>ymin && y<ymax &&
        lambda > lambda_0 && lambda < lambda_1)
    {
      if (t < tt_1 && t > tt_0)
      {
        i = floor((lambda - lambda_0)*nlam/(lambda_1 - lambda_0));
        j = floor((t-tt_0)*nt/(tt_1-tt_0));
/*  printf("tt_0, tt_1, nt %g %g %i t j %g %i \n",tt_0,tt_1,nt,t,j);
*/        TOFL_N[j][i]++;
        TOFL_p[j][i] += p;
        TOFL_p2[j][i] += p*p;
      }
    } 
    if (restore_neutron) {
      RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
    }  
}
#line 14794 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef sz
#undef sy
#undef sx
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component DivLambda_mon [15] */
  mccoordschange(mcposrDivLambda_mon, mcrotrDivLambda_mon,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrDivLambda_mon, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component DivLambda_mon (without coords transformations) */
  mcJumpTrace_DivLambda_mon:
  SIG_MESSAGE("DivLambda_mon (Trace)");
  mcDEBUG_COMP("DivLambda_mon")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
#define sx mcnlsx
#define sy mcnlsy
#define sz mcnlsz
  STORE_NEUTRON(15,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[15]++;
  mcPCounter[15] += p;
  mcP2Counter[15] += p*p;
#define mccompcurname  DivLambda_mon
#define mccompcurtype  DivLambda_monitor
#define mccompcurindex 15
#define nlam mccDivLambda_mon_nlam
#define ndiv mccDivLambda_mon_ndiv
#define filename mccDivLambda_mon_filename
#define restore_neutron mccDivLambda_mon_restore_neutron
#define Div_N mccDivLambda_mon_Div_N
#define Div_p mccDivLambda_mon_Div_p
#define Div_p2 mccDivLambda_mon_Div_p2
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccDivLambda_mon_xmin;
MCNUM xmax = mccDivLambda_mon_xmax;
MCNUM ymin = mccDivLambda_mon_ymin;
MCNUM ymax = mccDivLambda_mon_ymax;
MCNUM xwidth = mccDivLambda_mon_xwidth;
MCNUM yheight = mccDivLambda_mon_yheight;
MCNUM maxdiv = mccDivLambda_mon_maxdiv;
MCNUM lambda_0 = mccDivLambda_mon_lambda_0;
MCNUM lambda_1 = mccDivLambda_mon_lambda_1;
#line 88 "/usr/local/lib/mcstas/monitors/DivLambda_monitor.comp"
{
    int i,j;
    double div;
    double lambda;

    PROP_Z0;
    lambda = (2*PI/V2K)/sqrt(vx*vx + vy*vy + vz*vz);
    if (x>xmin && x<xmax && y>ymin && y<ymax &&
        lambda > lambda_0 && lambda < lambda_1)
    {
      div = RAD2DEG*atan2(vx,vz);
      if (div < maxdiv && div > -maxdiv)
      {
        i = floor((lambda - lambda_0)*nlam/(lambda_1 - lambda_0));
        j = floor((div + maxdiv)*ndiv/(2.0*maxdiv));
        Div_N[i][j]++;
        Div_p[i][j] += p;
        Div_p2[i][j] += p*p;
        SCATTER;
      }
    }
    if (restore_neutron) {
      RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
    }
}
#line 14899 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef Div_p2
#undef Div_p
#undef Div_N
#undef restore_neutron
#undef filename
#undef ndiv
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef sz
#undef sy
#undef sx
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component Sample [16] */
  mccoordschange(mcposrSample, mcrotrSample,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrSample, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Sample (without coords transformations) */
  mcJumpTrace_Sample:
  SIG_MESSAGE("Sample (Trace)");
  mcDEBUG_COMP("Sample")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
  STORE_NEUTRON(16,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[16]++;
  mcPCounter[16] += p;
  mcP2Counter[16] += p*p;
#define mccompcurname  Sample
#define mccompcurtype  Powder1
#define mccompcurindex 16
#define my_s_v2 mccSample_my_s_v2
#define my_a_v mccSample_my_a_v
#define q_v mccSample_q_v
#define isrect mccSample_isrect
{   /* Declarations of SETTING parameters. */
MCNUM radius = mccSample_radius;
MCNUM yheight = mccSample_yheight;
MCNUM q = mccSample_q;
MCNUM d = mccSample_d;
MCNUM d_phi = mccSample_d_phi;
MCNUM pack = mccSample_pack;
MCNUM j = mccSample_j;
MCNUM DW = mccSample_DW;
MCNUM F2 = mccSample_F2;
MCNUM Vc = mccSample_Vc;
MCNUM sigma_a = mccSample_sigma_a;
MCNUM xwidth = mccSample_xwidth;
MCNUM zthick = mccSample_zthick;
MCNUM h = mccSample_h;
#line 96 "/usr/local/lib/mcstas/samples/Powder1.comp"
{
  double t0, t1, v, l_full, l, l_1, dt, d_phi0, theta, my_s;
  double arg, tmp_vx, tmp_vy, tmp_vz, vout_x, vout_y, vout_z;
  char   intersect=0;

  if (isrect)
    intersect = box_intersect(&t0, &t1, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
  else
    intersect = cylinder_intersect(&t0, &t1, x, y, z, vx, vy, vz, radius, yheight);
  if(intersect)
  {
    if(t0 < 0)
      ABSORB;
    /* Neutron enters at t=t0. */
    v = sqrt(vx*vx + vy*vy + vz*vz);
    l_full = v * (t1 - t0);        /* Length of full path through sample */
    dt = rand01()*(t1 - t0);       /* Time of scattering */
    PROP_DT(dt+t0);                /* Point of scattering */
    l = v*dt;                      /* Penetration in sample */

    /* choose line theta */
    arg = q_v/(2.0*v);
    if(arg > 1)
      ABSORB;                   /* No bragg scattering possible*/
    theta = asin(arg);          /* Bragg scattering law */

/* Choose point on Debye-Scherrer cone */
      if (d_phi)
      { /* relate height of detector to the height on DS cone */
        arg = sin(d_phi*DEG2RAD/2)/sin(2*theta);
        if (arg < -1 || arg > 1) d_phi = 0;
        else d_phi = 2*asin(arg);
      }
      if (d_phi) {
        d_phi = fabs(d_phi);
        d_phi0= 2*rand01()*d_phi;
        if (d_phi0 > d_phi) arg = 1; else arg = 0;
        if (arg) {
          d_phi0=PI+(d_phi0-1.5*d_phi);
        } else {
          d_phi0=d_phi0-0.5*d_phi;
        }
        p *= d_phi/PI;
      }
      else
        d_phi0 = PI*randpm1();

    /* now find a nearly vertical rotation axis:
      *  (v along Z) x (X axis) -> nearly Y axis
      */
    vec_prod(tmp_vx,tmp_vy,tmp_vz, vx,vy,vz, 1,0,0);

    /* handle case where v and aim are parallel */
    if (!tmp_vx && !tmp_vy && !tmp_vz) { tmp_vx=tmp_vz=0; tmp_vy=1; }

    /* v_out = rotate 'v' by 2*theta around tmp_v: Bragg angle */
    rotate(vout_x,vout_y,vout_z, vx,vy,vz, 2*theta, tmp_vx,tmp_vy,tmp_vz);

    /* tmp_v = rotate v_out by d_phi0 around 'v' (Debye-Scherrer cone) */
    rotate(tmp_vx,tmp_vy,tmp_vz, vout_x,vout_y,vout_z, d_phi0, vx, vy, vz);
    vx = tmp_vx;
    vy = tmp_vy;
    vz = tmp_vz;

    arg=0;
    if (isrect && !box_intersect(&t0, &t1, x, y, z, vx, vy, vz, xwidth, yheight, zthick)) arg=1;
    else if(!isrect && !cylinder_intersect(&t0, &t1, x, y, z,
                          vx, vy, vz, radius, yheight)) arg=1;

    if (arg) {
      /* Strange error: did not hit cylinder */
      fprintf(stderr, "PowderN: FATAL ERROR: Did not hit sample from inside.\n");
      ABSORB;
    }
    l_1 = v*t1; /* go to exit */

    my_s = my_s_v2/(v*v);
    p *= l_full*my_s*exp(-(my_a_v/v+my_s)*(l+l_1));
    SCATTER;
  }
}
#line 15056 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef isrect
#undef q_v
#undef my_a_v
#undef my_s_v2
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component Detector [17] */
  mccoordschange(mcposrDetector, mcrotrDetector,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrDetector, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Detector (without coords transformations) */
  mcJumpTrace_Detector:
  SIG_MESSAGE("Detector (Trace)");
  mcDEBUG_COMP("Detector")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
#define sx mcnlsx
#define sy mcnlsy
#define sz mcnlsz
  STORE_NEUTRON(17,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[17]++;
  mcPCounter[17] += p;
  mcP2Counter[17] += p*p;
#define mccompcurname  Detector
#define mccompcurtype  TOF_cylPSD_monitor
#define mccompcurindex 17
#define nt mccDetector_nt
#define filename mccDetector_filename
#define nphi mccDetector_nphi
#define TOF_N mccDetector_TOF_N
#define TOF_p mccDetector_TOF_p
#define TOF_p2 mccDetector_TOF_p2
{   /* Declarations of SETTING parameters. */
MCNUM radius = mccDetector_radius;
MCNUM height = mccDetector_height;
MCNUM t_0 = mccDetector_t_0;
MCNUM t_1 = mccDetector_t_1;
MCNUM restore_neutron = mccDetector_restore_neutron;
#line 71 "/usr/local/lib/mcstas/monitors/TOF_cylPSD_monitor.comp"
{
    int i,j;
    double cyl_t0,cyl_t1,dt,phi;

    if(!cylinder_intersect(&cyl_t0, &cyl_t1, x,y,z,vx,vy,vz, radius, height))
     /* No hit */
      ABSORB;
    if(cyl_t0>0)  /* Neutron hits cylinder from the outside */
      ABSORB;
    dt=cyl_t1;
    PROP_DT(dt);
    if(y>=height/2 || y<= -height/2)
      ABSORB;  /* Neutron hits cylinder ends; no detectors here */

    i = floor((t-tt_0)*nt/(tt_1-tt_0));              /* Bin number */

    if (i < 0 || i >= nt)        /* Do not detect */
    {
    }
    else
     {
      phi = atan2(x,z);
      j = floor((double)nphi/2.0 + RAD2DEG*phi/(double)binphi);
      TOF_N[i][j]++;
      TOF_p[i][j] += p;
      TOF_p2[i][j] += p*p;
     } 
    if (restore_neutron) {
      RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
    }
}
#line 15153 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef nphi
#undef filename
#undef nt
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef sz
#undef sy
#undef sx
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component arm1 [18] */
  mccoordschange(mcposrarm1, mcrotrarm1,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrarm1, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component arm1 (without coords transformations) */
  mcJumpTrace_arm1:
  SIG_MESSAGE("arm1 (Trace)");
  mcDEBUG_COMP("arm1")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
  STORE_NEUTRON(18,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[18]++;
  mcPCounter[18] += p;
  mcP2Counter[18] += p*p;
#define mccompcurname  arm1
#define mccompcurtype  Arm
#define mccompcurindex 18
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  /* TRACE Component LineDetector [19] */
  mccoordschange(mcposrLineDetector, mcrotrLineDetector,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrLineDetector, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component LineDetector (without coords transformations) */
  mcJumpTrace_LineDetector:
  SIG_MESSAGE("LineDetector (Trace)");
  mcDEBUG_COMP("LineDetector")
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
#define x mcnlx
#define y mcnly
#define z mcnlz
#define vx mcnlvx
#define vy mcnlvy
#define vz mcnlvz
#define t mcnlt
#define s1 mcnlsx
#define s2 mcnlsy
#define p mcnlp
#define sx mcnlsx
#define sy mcnlsy
#define sz mcnlsz
  STORE_NEUTRON(19,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  mcScattered=0;
  mcNCounter[19]++;
  mcPCounter[19] += p;
  mcP2Counter[19] += p*p;
#define mccompcurname  LineDetector
#define mccompcurtype  TOF_monitor
#define mccompcurindex 19
#define nchan mccLineDetector_nchan
#define filename mccLineDetector_filename
#define TOF_N mccLineDetector_TOF_N
#define TOF_p mccLineDetector_TOF_p
#define TOF_p2 mccLineDetector_TOF_p2
#define t_min mccLineDetector_t_min
#define t_max mccLineDetector_t_max
#define delta_t mccLineDetector_delta_t
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccLineDetector_xmin;
MCNUM xmax = mccLineDetector_xmax;
MCNUM ymin = mccLineDetector_ymin;
MCNUM ymax = mccLineDetector_ymax;
MCNUM xwidth = mccLineDetector_xwidth;
MCNUM yheight = mccLineDetector_yheight;
MCNUM t0 = mccLineDetector_t0;
MCNUM t1 = mccLineDetector_t1;
MCNUM dt = mccLineDetector_dt;
MCNUM restore_neutron = mccLineDetector_restore_neutron;
#line 92 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
    int i;

    PROP_Z0;
    if (x>xmin && x<xmax && y>ymin && y<ymax)
    { 
      i = floor((1E6*t-t_min)/delta_t);              /* Bin number */
      if(i >= 0 && i < nchan) {
	TOF_N[i]++;
	TOF_p[i] += p;
	TOF_p2[i] += p*p;
	SCATTER;
      }
    }
    if (restore_neutron) {
      RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
    }
}
#line 15293 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
#undef sz
#undef sy
#undef sx
#undef p
#undef s2
#undef s1
#undef t
#undef vz
#undef vy
#undef vx
#undef z
#undef y
#undef x
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)

  mcabsorbAll:
  mcDEBUG_LEAVE()
  mcDEBUG_STATE(mcnlx, mcnly, mcnlz, mcnlvx, mcnlvy, mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlp)
  /* Copy neutron state to global variables. */
  mcnx = mcnlx;
  mcny = mcnly;
  mcnz = mcnlz;
  mcnvx = mcnlvx;
  mcnvy = mcnlvy;
  mcnvz = mcnlvz;
  mcnt = mcnlt;
  mcnsx = mcnlsx;
  mcnsy = mcnlsy;
  mcnsz = mcnlsz;
  mcnp = mcnlp;
} /* end trace */

void mcsave(FILE *handle) {
  if (!handle) mcsiminfo_init(NULL);
  /* User component SAVE code. */

  /* User SAVE code for component 'Origin'. */
  SIG_MESSAGE("Origin (Save)");
#define mccompcurname  Origin
#define mccompcurtype  Progress_bar
#define mccompcurindex 1
#define profile mccOrigin_profile
#define IntermediateCnts mccOrigin_IntermediateCnts
#define StartTime mccOrigin_StartTime
#define EndTime mccOrigin_EndTime
{   /* Declarations of SETTING parameters. */
MCNUM percent = mccOrigin_percent;
MCNUM flag_save = mccOrigin_flag_save;
MCNUM minutes = mccOrigin_minutes;
#line 108 "/usr/local/lib/mcstas/misc/Progress_bar.comp"
{
  MPI_MASTER(fprintf(stdout, "\nSave [%s]\n", mcinstrument_name););
  if (profile && strlen(profile)) {
    char filename[256];
    if (!strlen(profile)) strcpy(filename, mcinstrument_name);
    else strcpy(filename, profile);
    DETECTOR_OUT_1D(
        "Intensity profiler",
        "Component index [1]",
        "Intensity",
        "prof", 1, mcNUMCOMP, mcNUMCOMP-1,
        &mcNCounter[1],&mcPCounter[1],&mcP2Counter[1],
        filename);

  }
}
#line 15372 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef EndTime
#undef StartTime
#undef IntermediateCnts
#undef profile
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* User SAVE code for component 'TOF_mon_1'. */
  SIG_MESSAGE("TOF_mon_1 (Save)");
#define mccompcurname  TOF_mon_1
#define mccompcurtype  TOF_monitor
#define mccompcurindex 3
#define nchan mccTOF_mon_1_nchan
#define filename mccTOF_mon_1_filename
#define TOF_N mccTOF_mon_1_TOF_N
#define TOF_p mccTOF_mon_1_TOF_p
#define TOF_p2 mccTOF_mon_1_TOF_p2
#define t_min mccTOF_mon_1_t_min
#define t_max mccTOF_mon_1_t_max
#define delta_t mccTOF_mon_1_delta_t
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_mon_1_xmin;
MCNUM xmax = mccTOF_mon_1_xmax;
MCNUM ymin = mccTOF_mon_1_ymin;
MCNUM ymax = mccTOF_mon_1_ymax;
MCNUM xwidth = mccTOF_mon_1_xwidth;
MCNUM yheight = mccTOF_mon_1_yheight;
MCNUM t0 = mccTOF_mon_1_t0;
MCNUM t1 = mccTOF_mon_1_t1;
MCNUM dt = mccTOF_mon_1_dt;
MCNUM restore_neutron = mccTOF_mon_1_restore_neutron;
#line 111 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
    DETECTOR_OUT_1D(
        "Time-of-flight monitor",
        "Time-of-flight [\\gms]",
        "Intensity",
        "t", t_min, t_max, nchan,
        &TOF_N[0],&TOF_p[0],&TOF_p2[0],
        filename);
}
#line 15416 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* User SAVE code for component 'TOF_lmon_1'. */
  SIG_MESSAGE("TOF_lmon_1 (Save)");
#define mccompcurname  TOF_lmon_1
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 4
#define nlam mccTOF_lmon_1_nlam
#define nt mccTOF_lmon_1_nt
#define filename mccTOF_lmon_1_filename
#define t_0 mccTOF_lmon_1_t_0
#define t_1 mccTOF_lmon_1_t_1
#define tt_0 mccTOF_lmon_1_tt_0
#define tt_1 mccTOF_lmon_1_tt_1
#define TOFL_N mccTOF_lmon_1_TOFL_N
#define TOFL_p mccTOF_lmon_1_TOFL_p
#define TOFL_p2 mccTOF_lmon_1_TOFL_p2
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_lmon_1_xmin;
MCNUM xmax = mccTOF_lmon_1_xmax;
MCNUM ymin = mccTOF_lmon_1_ymin;
MCNUM ymax = mccTOF_lmon_1_ymax;
MCNUM xwidth = mccTOF_lmon_1_xwidth;
MCNUM yheight = mccTOF_lmon_1_yheight;
MCNUM lambda_0 = mccTOF_lmon_1_lambda_0;
MCNUM lambda_1 = mccTOF_lmon_1_lambda_1;
MCNUM restore_neutron = mccTOF_lmon_1_restore_neutron;
#line 112 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
{
    DETECTOR_OUT_2D(
        "TOF-wavelength monitor",
        "Time-of-flight [\\gms]", "Wavelength [AA]",
        t_0, t_1, lambda_0, lambda_1,
        nt, nlam,
        &TOFL_N[0][0],&TOFL_p[0][0],&TOFL_p2[0][0],
        filename);
}
#line 15465 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* User SAVE code for component 'TOF_mon_2'. */
  SIG_MESSAGE("TOF_mon_2 (Save)");
#define mccompcurname  TOF_mon_2
#define mccompcurtype  TOF_monitor
#define mccompcurindex 5
#define nchan mccTOF_mon_2_nchan
#define filename mccTOF_mon_2_filename
#define TOF_N mccTOF_mon_2_TOF_N
#define TOF_p mccTOF_mon_2_TOF_p
#define TOF_p2 mccTOF_mon_2_TOF_p2
#define t_min mccTOF_mon_2_t_min
#define t_max mccTOF_mon_2_t_max
#define delta_t mccTOF_mon_2_delta_t
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_mon_2_xmin;
MCNUM xmax = mccTOF_mon_2_xmax;
MCNUM ymin = mccTOF_mon_2_ymin;
MCNUM ymax = mccTOF_mon_2_ymax;
MCNUM xwidth = mccTOF_mon_2_xwidth;
MCNUM yheight = mccTOF_mon_2_yheight;
MCNUM t0 = mccTOF_mon_2_t0;
MCNUM t1 = mccTOF_mon_2_t1;
MCNUM dt = mccTOF_mon_2_dt;
MCNUM restore_neutron = mccTOF_mon_2_restore_neutron;
#line 111 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
    DETECTOR_OUT_1D(
        "Time-of-flight monitor",
        "Time-of-flight [\\gms]",
        "Intensity",
        "t", t_min, t_max, nchan,
        &TOF_N[0],&TOF_p[0],&TOF_p2[0],
        filename);
}
#line 15515 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* User SAVE code for component 'TOF_lmon_2'. */
  SIG_MESSAGE("TOF_lmon_2 (Save)");
#define mccompcurname  TOF_lmon_2
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 6
#define nlam mccTOF_lmon_2_nlam
#define nt mccTOF_lmon_2_nt
#define filename mccTOF_lmon_2_filename
#define t_0 mccTOF_lmon_2_t_0
#define t_1 mccTOF_lmon_2_t_1
#define tt_0 mccTOF_lmon_2_tt_0
#define tt_1 mccTOF_lmon_2_tt_1
#define TOFL_N mccTOF_lmon_2_TOFL_N
#define TOFL_p mccTOF_lmon_2_TOFL_p
#define TOFL_p2 mccTOF_lmon_2_TOFL_p2
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_lmon_2_xmin;
MCNUM xmax = mccTOF_lmon_2_xmax;
MCNUM ymin = mccTOF_lmon_2_ymin;
MCNUM ymax = mccTOF_lmon_2_ymax;
MCNUM xwidth = mccTOF_lmon_2_xwidth;
MCNUM yheight = mccTOF_lmon_2_yheight;
MCNUM lambda_0 = mccTOF_lmon_2_lambda_0;
MCNUM lambda_1 = mccTOF_lmon_2_lambda_1;
MCNUM restore_neutron = mccTOF_lmon_2_restore_neutron;
#line 112 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
{
    DETECTOR_OUT_2D(
        "TOF-wavelength monitor",
        "Time-of-flight [\\gms]", "Wavelength [AA]",
        t_0, t_1, lambda_0, lambda_1,
        nt, nlam,
        &TOFL_N[0][0],&TOFL_p[0][0],&TOFL_p2[0][0],
        filename);
}
#line 15564 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* User SAVE code for component 'TOF_mon_3'. */
  SIG_MESSAGE("TOF_mon_3 (Save)");
#define mccompcurname  TOF_mon_3
#define mccompcurtype  TOF_monitor
#define mccompcurindex 13
#define nchan mccTOF_mon_3_nchan
#define filename mccTOF_mon_3_filename
#define TOF_N mccTOF_mon_3_TOF_N
#define TOF_p mccTOF_mon_3_TOF_p
#define TOF_p2 mccTOF_mon_3_TOF_p2
#define t_min mccTOF_mon_3_t_min
#define t_max mccTOF_mon_3_t_max
#define delta_t mccTOF_mon_3_delta_t
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_mon_3_xmin;
MCNUM xmax = mccTOF_mon_3_xmax;
MCNUM ymin = mccTOF_mon_3_ymin;
MCNUM ymax = mccTOF_mon_3_ymax;
MCNUM xwidth = mccTOF_mon_3_xwidth;
MCNUM yheight = mccTOF_mon_3_yheight;
MCNUM t0 = mccTOF_mon_3_t0;
MCNUM t1 = mccTOF_mon_3_t1;
MCNUM dt = mccTOF_mon_3_dt;
MCNUM restore_neutron = mccTOF_mon_3_restore_neutron;
#line 111 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
    DETECTOR_OUT_1D(
        "Time-of-flight monitor",
        "Time-of-flight [\\gms]",
        "Intensity",
        "t", t_min, t_max, nchan,
        &TOF_N[0],&TOF_p[0],&TOF_p2[0],
        filename);
}
#line 15614 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* User SAVE code for component 'TOF_lmon_3'. */
  SIG_MESSAGE("TOF_lmon_3 (Save)");
#define mccompcurname  TOF_lmon_3
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 14
#define nlam mccTOF_lmon_3_nlam
#define nt mccTOF_lmon_3_nt
#define filename mccTOF_lmon_3_filename
#define t_0 mccTOF_lmon_3_t_0
#define t_1 mccTOF_lmon_3_t_1
#define tt_0 mccTOF_lmon_3_tt_0
#define tt_1 mccTOF_lmon_3_tt_1
#define TOFL_N mccTOF_lmon_3_TOFL_N
#define TOFL_p mccTOF_lmon_3_TOFL_p
#define TOFL_p2 mccTOF_lmon_3_TOFL_p2
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_lmon_3_xmin;
MCNUM xmax = mccTOF_lmon_3_xmax;
MCNUM ymin = mccTOF_lmon_3_ymin;
MCNUM ymax = mccTOF_lmon_3_ymax;
MCNUM xwidth = mccTOF_lmon_3_xwidth;
MCNUM yheight = mccTOF_lmon_3_yheight;
MCNUM lambda_0 = mccTOF_lmon_3_lambda_0;
MCNUM lambda_1 = mccTOF_lmon_3_lambda_1;
MCNUM restore_neutron = mccTOF_lmon_3_restore_neutron;
#line 112 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
{
    DETECTOR_OUT_2D(
        "TOF-wavelength monitor",
        "Time-of-flight [\\gms]", "Wavelength [AA]",
        t_0, t_1, lambda_0, lambda_1,
        nt, nlam,
        &TOFL_N[0][0],&TOFL_p[0][0],&TOFL_p2[0][0],
        filename);
}
#line 15663 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* User SAVE code for component 'DivLambda_mon'. */
  SIG_MESSAGE("DivLambda_mon (Save)");
#define mccompcurname  DivLambda_mon
#define mccompcurtype  DivLambda_monitor
#define mccompcurindex 15
#define nlam mccDivLambda_mon_nlam
#define ndiv mccDivLambda_mon_ndiv
#define filename mccDivLambda_mon_filename
#define restore_neutron mccDivLambda_mon_restore_neutron
#define Div_N mccDivLambda_mon_Div_N
#define Div_p mccDivLambda_mon_Div_p
#define Div_p2 mccDivLambda_mon_Div_p2
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccDivLambda_mon_xmin;
MCNUM xmax = mccDivLambda_mon_xmax;
MCNUM ymin = mccDivLambda_mon_ymin;
MCNUM ymax = mccDivLambda_mon_ymax;
MCNUM xwidth = mccDivLambda_mon_xwidth;
MCNUM yheight = mccDivLambda_mon_yheight;
MCNUM maxdiv = mccDivLambda_mon_maxdiv;
MCNUM lambda_0 = mccDivLambda_mon_lambda_0;
MCNUM lambda_1 = mccDivLambda_mon_lambda_1;
#line 114 "/usr/local/lib/mcstas/monitors/DivLambda_monitor.comp"
{
    DETECTOR_OUT_2D(
        "Wavelength-divergence monitor",
        "Wavelength [AA]",
        "divergence [deg]",
        lambda_0, lambda_1, -maxdiv, maxdiv,
        nlam, ndiv,
        &Div_N[0][0],&Div_p[0][0],&Div_p2[0][0],
        filename);
}
#line 15712 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef Div_p2
#undef Div_p
#undef Div_N
#undef restore_neutron
#undef filename
#undef ndiv
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* User SAVE code for component 'Detector'. */
  SIG_MESSAGE("Detector (Save)");
#define mccompcurname  Detector
#define mccompcurtype  TOF_cylPSD_monitor
#define mccompcurindex 17
#define nt mccDetector_nt
#define filename mccDetector_filename
#define nphi mccDetector_nphi
#define TOF_N mccDetector_TOF_N
#define TOF_p mccDetector_TOF_p
#define TOF_p2 mccDetector_TOF_p2
{   /* Declarations of SETTING parameters. */
MCNUM radius = mccDetector_radius;
MCNUM height = mccDetector_height;
MCNUM t_0 = mccDetector_t_0;
MCNUM t_1 = mccDetector_t_1;
MCNUM restore_neutron = mccDetector_restore_neutron;
#line 103 "/usr/local/lib/mcstas/monitors/TOF_cylPSD_monitor.comp"
{
    DETECTOR_OUT_2D(
        "Cylindrical Time-of-flight PSD monitor",
        "Time-of-flight [\\gms]",
        "Angle [deg]",
        t_0, t_1, -180, 180,
        nt, nphi,
        &TOF_N[0][0],&TOF_p[0][0],&TOF_p2[0][0],
        filename);
}
#line 15753 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef nphi
#undef filename
#undef nt
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* User SAVE code for component 'LineDetector'. */
  SIG_MESSAGE("LineDetector (Save)");
#define mccompcurname  LineDetector
#define mccompcurtype  TOF_monitor
#define mccompcurindex 19
#define nchan mccLineDetector_nchan
#define filename mccLineDetector_filename
#define TOF_N mccLineDetector_TOF_N
#define TOF_p mccLineDetector_TOF_p
#define TOF_p2 mccLineDetector_TOF_p2
#define t_min mccLineDetector_t_min
#define t_max mccLineDetector_t_max
#define delta_t mccLineDetector_delta_t
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccLineDetector_xmin;
MCNUM xmax = mccLineDetector_xmax;
MCNUM ymin = mccLineDetector_ymin;
MCNUM ymax = mccLineDetector_ymax;
MCNUM xwidth = mccLineDetector_xwidth;
MCNUM yheight = mccLineDetector_yheight;
MCNUM t0 = mccLineDetector_t0;
MCNUM t1 = mccLineDetector_t1;
MCNUM dt = mccLineDetector_dt;
MCNUM restore_neutron = mccLineDetector_restore_neutron;
#line 111 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
    DETECTOR_OUT_1D(
        "Time-of-flight monitor",
        "Time-of-flight [\\gms]",
        "Intensity",
        "t", t_min, t_max, nchan,
        &TOF_N[0],&TOF_p[0],&TOF_p2[0],
        filename);
}
#line 15799 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  if (!handle) mcsiminfo_close(); 
} /* end save */
void mcfinally(void) {
  /* User component FINALLY code. */
  mcsiminfo_init(NULL);
  mcsave(mcsiminfo_file); /* save data when simulation ends */

  /* User FINALLY code for component 'Origin'. */
  SIG_MESSAGE("Origin (Finally)");
#define mccompcurname  Origin
#define mccompcurtype  Progress_bar
#define mccompcurindex 1
#define profile mccOrigin_profile
#define IntermediateCnts mccOrigin_IntermediateCnts
#define StartTime mccOrigin_StartTime
#define EndTime mccOrigin_EndTime
{   /* Declarations of SETTING parameters. */
MCNUM percent = mccOrigin_percent;
MCNUM flag_save = mccOrigin_flag_save;
MCNUM minutes = mccOrigin_minutes;
#line 126 "/usr/local/lib/mcstas/misc/Progress_bar.comp"
{
  time_t NowTime;
  time(&NowTime);
  fprintf(stdout, "\nFinally. Time: ");
  if (difftime(NowTime,StartTime) < 60.0)
    fprintf(stdout, "%g [s] ", difftime(NowTime,StartTime));
  else if (difftime(NowTime,StartTime) > 3600.0)
    fprintf(stdout, "%g [h] ", difftime(NowTime,StartTime)/3660.0);
  else
    fprintf(stdout, "%g [min] ", difftime(NowTime,StartTime)/60.0);
  fprintf(stdout, "\n");
}
#line 15846 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef EndTime
#undef StartTime
#undef IntermediateCnts
#undef profile
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

    if (!mcNCounter[1]) fprintf(stderr, "Warning: No neutron could reach Component[1] Origin\n");
    if (mcAbsorbProp[1]) fprintf(stderr, "Warning: %g events were removed in Component[1] Origin\n""         (negative time, rounding errors).\n", mcAbsorbProp[1]);
    if (!mcNCounter[2]) fprintf(stderr, "Warning: No neutron could reach Component[2] Moderator\n");
    if (mcAbsorbProp[2]) fprintf(stderr, "Warning: %g events were removed in Component[2] Moderator\n""         (negative time, rounding errors).\n", mcAbsorbProp[2]);
    if (!mcNCounter[3]) fprintf(stderr, "Warning: No neutron could reach Component[3] TOF_mon_1\n");
    if (mcAbsorbProp[3]) fprintf(stderr, "Warning: %g events were removed in Component[3] TOF_mon_1\n""         (negative time, rounding errors).\n", mcAbsorbProp[3]);
    if (!mcNCounter[4]) fprintf(stderr, "Warning: No neutron could reach Component[4] TOF_lmon_1\n");
    if (mcAbsorbProp[4]) fprintf(stderr, "Warning: %g events were removed in Component[4] TOF_lmon_1\n""         (negative time, rounding errors).\n", mcAbsorbProp[4]);
    if (!mcNCounter[5]) fprintf(stderr, "Warning: No neutron could reach Component[5] TOF_mon_2\n");
    if (mcAbsorbProp[5]) fprintf(stderr, "Warning: %g events were removed in Component[5] TOF_mon_2\n""         (negative time, rounding errors).\n", mcAbsorbProp[5]);
    if (!mcNCounter[6]) fprintf(stderr, "Warning: No neutron could reach Component[6] TOF_lmon_2\n");
    if (mcAbsorbProp[6]) fprintf(stderr, "Warning: %g events were removed in Component[6] TOF_lmon_2\n""         (negative time, rounding errors).\n", mcAbsorbProp[6]);
    if (!mcNCounter[7]) fprintf(stderr, "Warning: No neutron could reach Component[7] Guide1\n");
    if (mcAbsorbProp[7]) fprintf(stderr, "Warning: %g events were removed in Component[7] Guide1\n""         (negative time, rounding errors).\n", mcAbsorbProp[7]);
  /* User FINALLY code for component 'Guide2'. */
  SIG_MESSAGE("Guide2 (Finally)");
#define mccompcurname  Guide2
#define mccompcurtype  Guide_tapering
#define mccompcurindex 8
#define option mccGuide2_option
#define segno mccGuide2_segno
#define w1c mccGuide2_w1c
#define w2c mccGuide2_w2c
#define ww mccGuide2_ww
#define hh mccGuide2_hh
#define whalf mccGuide2_whalf
#define hhalf mccGuide2_hhalf
#define lwhalf mccGuide2_lwhalf
#define lhhalf mccGuide2_lhhalf
#define h1_in mccGuide2_h1_in
#define h2_out mccGuide2_h2_out
#define w1_in mccGuide2_w1_in
#define w2_out mccGuide2_w2_out
#define l_seg mccGuide2_l_seg
#define seg mccGuide2_seg
#define h12 mccGuide2_h12
#define h2 mccGuide2_h2
#define w12 mccGuide2_w12
#define w2 mccGuide2_w2
#define a_ell_q mccGuide2_a_ell_q
#define b_ell_q mccGuide2_b_ell_q
#define lbw mccGuide2_lbw
#define lbh mccGuide2_lbh
#define mxi mccGuide2_mxi
#define u1 mccGuide2_u1
#define u2 mccGuide2_u2
#define div1 mccGuide2_div1
#define p2_para mccGuide2_p2_para
#define test mccGuide2_test
#define Div1 mccGuide2_Div1
#define i mccGuide2_i
#define ii mccGuide2_ii
#define seg mccGuide2_seg
#define fu mccGuide2_fu
#define pos mccGuide2_pos
#define file_name mccGuide2_file_name
#define ep mccGuide2_ep
#define num mccGuide2_num
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide2_w1;
MCNUM h1 = mccGuide2_h1;
MCNUM l = mccGuide2_l;
MCNUM linw = mccGuide2_linw;
MCNUM loutw = mccGuide2_loutw;
MCNUM linh = mccGuide2_linh;
MCNUM louth = mccGuide2_louth;
MCNUM R0 = mccGuide2_R0;
MCNUM Qcx = mccGuide2_Qcx;
MCNUM Qcy = mccGuide2_Qcy;
MCNUM alphax = mccGuide2_alphax;
MCNUM alphay = mccGuide2_alphay;
MCNUM W = mccGuide2_W;
MCNUM mx = mccGuide2_mx;
MCNUM my = mccGuide2_my;
#line 596 "/usr/local/lib/mcstas/optics/Guide_tapering.comp"
{
  free(w1c);
  free(w2c);
  free(ww);
  free(hh);
  free(whalf);
  free(hhalf);
  free(lwhalf);
  free(lhhalf);
  free(h1_in);
  free(h2_out);
  free(w1_in);
  free(w2_out);
}
#line 15945 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef num
#undef ep
#undef file_name
#undef pos
#undef fu
#undef seg
#undef ii
#undef i
#undef Div1
#undef test
#undef p2_para
#undef div1
#undef u2
#undef u1
#undef mxi
#undef lbh
#undef lbw
#undef b_ell_q
#undef a_ell_q
#undef w2
#undef w12
#undef h2
#undef h12
#undef seg
#undef l_seg
#undef w2_out
#undef w1_in
#undef h2_out
#undef h1_in
#undef lhhalf
#undef lwhalf
#undef hhalf
#undef whalf
#undef hh
#undef ww
#undef w2c
#undef w1c
#undef segno
#undef option
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

    if (!mcNCounter[8]) fprintf(stderr, "Warning: No neutron could reach Component[8] Guide2\n");
    if (mcAbsorbProp[8]) fprintf(stderr, "Warning: %g events were removed in Component[8] Guide2\n""         (negative time, rounding errors).\n", mcAbsorbProp[8]);
  /* User FINALLY code for component 'Guide3'. */
  SIG_MESSAGE("Guide3 (Finally)");
#define mccompcurname  Guide3
#define mccompcurtype  Guide_tapering
#define mccompcurindex 9
#define option mccGuide3_option
#define segno mccGuide3_segno
#define w1c mccGuide3_w1c
#define w2c mccGuide3_w2c
#define ww mccGuide3_ww
#define hh mccGuide3_hh
#define whalf mccGuide3_whalf
#define hhalf mccGuide3_hhalf
#define lwhalf mccGuide3_lwhalf
#define lhhalf mccGuide3_lhhalf
#define h1_in mccGuide3_h1_in
#define h2_out mccGuide3_h2_out
#define w1_in mccGuide3_w1_in
#define w2_out mccGuide3_w2_out
#define l_seg mccGuide3_l_seg
#define seg mccGuide3_seg
#define h12 mccGuide3_h12
#define h2 mccGuide3_h2
#define w12 mccGuide3_w12
#define w2 mccGuide3_w2
#define a_ell_q mccGuide3_a_ell_q
#define b_ell_q mccGuide3_b_ell_q
#define lbw mccGuide3_lbw
#define lbh mccGuide3_lbh
#define mxi mccGuide3_mxi
#define u1 mccGuide3_u1
#define u2 mccGuide3_u2
#define div1 mccGuide3_div1
#define p2_para mccGuide3_p2_para
#define test mccGuide3_test
#define Div1 mccGuide3_Div1
#define i mccGuide3_i
#define ii mccGuide3_ii
#define seg mccGuide3_seg
#define fu mccGuide3_fu
#define pos mccGuide3_pos
#define file_name mccGuide3_file_name
#define ep mccGuide3_ep
#define num mccGuide3_num
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide3_w1;
MCNUM h1 = mccGuide3_h1;
MCNUM l = mccGuide3_l;
MCNUM linw = mccGuide3_linw;
MCNUM loutw = mccGuide3_loutw;
MCNUM linh = mccGuide3_linh;
MCNUM louth = mccGuide3_louth;
MCNUM R0 = mccGuide3_R0;
MCNUM Qcx = mccGuide3_Qcx;
MCNUM Qcy = mccGuide3_Qcy;
MCNUM alphax = mccGuide3_alphax;
MCNUM alphay = mccGuide3_alphay;
MCNUM W = mccGuide3_W;
MCNUM mx = mccGuide3_mx;
MCNUM my = mccGuide3_my;
#line 596 "/usr/local/lib/mcstas/optics/Guide_tapering.comp"
{
  free(w1c);
  free(w2c);
  free(ww);
  free(hh);
  free(whalf);
  free(hhalf);
  free(lwhalf);
  free(lhhalf);
  free(h1_in);
  free(h2_out);
  free(w1_in);
  free(w2_out);
}
#line 16067 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef num
#undef ep
#undef file_name
#undef pos
#undef fu
#undef seg
#undef ii
#undef i
#undef Div1
#undef test
#undef p2_para
#undef div1
#undef u2
#undef u1
#undef mxi
#undef lbh
#undef lbw
#undef b_ell_q
#undef a_ell_q
#undef w2
#undef w12
#undef h2
#undef h12
#undef seg
#undef l_seg
#undef w2_out
#undef w1_in
#undef h2_out
#undef h1_in
#undef lhhalf
#undef lwhalf
#undef hhalf
#undef whalf
#undef hh
#undef ww
#undef w2c
#undef w1c
#undef segno
#undef option
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

    if (!mcNCounter[9]) fprintf(stderr, "Warning: No neutron could reach Component[9] Guide3\n");
    if (mcAbsorbProp[9]) fprintf(stderr, "Warning: %g events were removed in Component[9] Guide3\n""         (negative time, rounding errors).\n", mcAbsorbProp[9]);
    if (!mcNCounter[10]) fprintf(stderr, "Warning: No neutron could reach Component[10] Guide4a\n");
    if (mcAbsorbProp[10]) fprintf(stderr, "Warning: %g events were removed in Component[10] Guide4a\n""         (negative time, rounding errors).\n", mcAbsorbProp[10]);
    if (!mcNCounter[11]) fprintf(stderr, "Warning: No neutron could reach Component[11] Guide4b\n");
    if (mcAbsorbProp[11]) fprintf(stderr, "Warning: %g events were removed in Component[11] Guide4b\n""         (negative time, rounding errors).\n", mcAbsorbProp[11]);
    if (!mcNCounter[12]) fprintf(stderr, "Warning: No neutron could reach Component[12] Guide4c\n");
    if (mcAbsorbProp[12]) fprintf(stderr, "Warning: %g events were removed in Component[12] Guide4c\n""         (negative time, rounding errors).\n", mcAbsorbProp[12]);
    if (!mcNCounter[13]) fprintf(stderr, "Warning: No neutron could reach Component[13] TOF_mon_3\n");
    if (mcAbsorbProp[13]) fprintf(stderr, "Warning: %g events were removed in Component[13] TOF_mon_3\n""         (negative time, rounding errors).\n", mcAbsorbProp[13]);
    if (!mcNCounter[14]) fprintf(stderr, "Warning: No neutron could reach Component[14] TOF_lmon_3\n");
    if (mcAbsorbProp[14]) fprintf(stderr, "Warning: %g events were removed in Component[14] TOF_lmon_3\n""         (negative time, rounding errors).\n", mcAbsorbProp[14]);
    if (!mcNCounter[15]) fprintf(stderr, "Warning: No neutron could reach Component[15] DivLambda_mon\n");
    if (mcAbsorbProp[15]) fprintf(stderr, "Warning: %g events were removed in Component[15] DivLambda_mon\n""         (negative time, rounding errors).\n", mcAbsorbProp[15]);
    if (!mcNCounter[16]) fprintf(stderr, "Warning: No neutron could reach Component[16] Sample\n");
    if (mcAbsorbProp[16]) fprintf(stderr, "Warning: %g events were removed in Component[16] Sample\n""         (negative time, rounding errors).\n", mcAbsorbProp[16]);
    if (!mcNCounter[17]) fprintf(stderr, "Warning: No neutron could reach Component[17] Detector\n");
    if (mcAbsorbProp[17]) fprintf(stderr, "Warning: %g events were removed in Component[17] Detector\n""         (negative time, rounding errors).\n", mcAbsorbProp[17]);
    if (!mcNCounter[18]) fprintf(stderr, "Warning: No neutron could reach Component[18] arm1\n");
    if (mcAbsorbProp[18]) fprintf(stderr, "Warning: %g events were removed in Component[18] arm1\n""         (negative time, rounding errors).\n", mcAbsorbProp[18]);
    if (!mcNCounter[19]) fprintf(stderr, "Warning: No neutron could reach Component[19] LineDetector\n");
    if (mcAbsorbProp[19]) fprintf(stderr, "Warning: %g events were removed in Component[19] LineDetector\n""         (negative time, rounding errors).\n", mcAbsorbProp[19]);
  mcsiminfo_close(); 
} /* end finally */
#define magnify mcdis_magnify
#define line mcdis_line
#define dashed_line mcdis_dashed_line
#define multiline mcdis_multiline
#define rectangle mcdis_rectangle
#define box mcdis_box
#define circle mcdis_circle
void mcdisplay(void) {
  printf("MCDISPLAY: start\n");
  /* Components MCDISPLAY code. */

  /* MCDISPLAY code for component 'Moderator'. */
  SIG_MESSAGE("Moderator (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Moderator");
#define mccompcurname  Moderator
#define mccompcurtype  ESS_moderator_long
#define mccompcurindex 2
#define M mccModerator_M
#define F mccModerator_F
#define l_range mccModerator_l_range
#define w_mult mccModerator_w_mult
{   /* Declarations of SETTING parameters. */
MCNUM size = mccModerator_size;
MCNUM l_low = mccModerator_l_low;
MCNUM l_high = mccModerator_l_high;
MCNUM dist = mccModerator_dist;
MCNUM xw = mccModerator_xw;
MCNUM yh = mccModerator_yh;
MCNUM freq = mccModerator_freq;
MCNUM T = mccModerator_T;
MCNUM tau = mccModerator_tau;
MCNUM tau1 = mccModerator_tau1;
MCNUM tau2 = mccModerator_tau2;
MCNUM d = mccModerator_d;
MCNUM n = mccModerator_n;
MCNUM n2 = mccModerator_n2;
MCNUM chi2 = mccModerator_chi2;
MCNUM I0 = mccModerator_I0;
MCNUM I2 = mccModerator_I2;
MCNUM branch1 = mccModerator_branch1;
MCNUM branch2 = mccModerator_branch2;
MCNUM branch_tail = mccModerator_branch_tail;
MCNUM twopulses = mccModerator_twopulses;
#line 251 "/usr/local/lib/mcstas/sources/ESS_moderator_long.comp"
{
  magnify("xy");
  rectangle("xy", 0, 0, 0, size, size);
}
#line 16184 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef w_mult
#undef l_range
#undef F
#undef M
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'TOF_mon_1'. */
  SIG_MESSAGE("TOF_mon_1 (McDisplay)");
  printf("MCDISPLAY: component %s\n", "TOF_mon_1");
#define mccompcurname  TOF_mon_1
#define mccompcurtype  TOF_monitor
#define mccompcurindex 3
#define nchan mccTOF_mon_1_nchan
#define filename mccTOF_mon_1_filename
#define TOF_N mccTOF_mon_1_TOF_N
#define TOF_p mccTOF_mon_1_TOF_p
#define TOF_p2 mccTOF_mon_1_TOF_p2
#define t_min mccTOF_mon_1_t_min
#define t_max mccTOF_mon_1_t_max
#define delta_t mccTOF_mon_1_delta_t
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_mon_1_xmin;
MCNUM xmax = mccTOF_mon_1_xmax;
MCNUM ymin = mccTOF_mon_1_ymin;
MCNUM ymax = mccTOF_mon_1_ymax;
MCNUM xwidth = mccTOF_mon_1_xwidth;
MCNUM yheight = mccTOF_mon_1_yheight;
MCNUM t0 = mccTOF_mon_1_t0;
MCNUM t1 = mccTOF_mon_1_t1;
MCNUM dt = mccTOF_mon_1_dt;
MCNUM restore_neutron = mccTOF_mon_1_restore_neutron;
#line 122 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
  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);
}
#line 16228 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'TOF_lmon_1'. */
  SIG_MESSAGE("TOF_lmon_1 (McDisplay)");
  printf("MCDISPLAY: component %s\n", "TOF_lmon_1");
#define mccompcurname  TOF_lmon_1
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 4
#define nlam mccTOF_lmon_1_nlam
#define nt mccTOF_lmon_1_nt
#define filename mccTOF_lmon_1_filename
#define t_0 mccTOF_lmon_1_t_0
#define t_1 mccTOF_lmon_1_t_1
#define tt_0 mccTOF_lmon_1_tt_0
#define tt_1 mccTOF_lmon_1_tt_1
#define TOFL_N mccTOF_lmon_1_TOFL_N
#define TOFL_p mccTOF_lmon_1_TOFL_p
#define TOFL_p2 mccTOF_lmon_1_TOFL_p2
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_lmon_1_xmin;
MCNUM xmax = mccTOF_lmon_1_xmax;
MCNUM ymin = mccTOF_lmon_1_ymin;
MCNUM ymax = mccTOF_lmon_1_ymax;
MCNUM xwidth = mccTOF_lmon_1_xwidth;
MCNUM yheight = mccTOF_lmon_1_yheight;
MCNUM lambda_0 = mccTOF_lmon_1_lambda_0;
MCNUM lambda_1 = mccTOF_lmon_1_lambda_1;
MCNUM restore_neutron = mccTOF_lmon_1_restore_neutron;
#line 123 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
{
    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);
}
#line 16277 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'TOF_mon_2'. */
  SIG_MESSAGE("TOF_mon_2 (McDisplay)");
  printf("MCDISPLAY: component %s\n", "TOF_mon_2");
#define mccompcurname  TOF_mon_2
#define mccompcurtype  TOF_monitor
#define mccompcurindex 5
#define nchan mccTOF_mon_2_nchan
#define filename mccTOF_mon_2_filename
#define TOF_N mccTOF_mon_2_TOF_N
#define TOF_p mccTOF_mon_2_TOF_p
#define TOF_p2 mccTOF_mon_2_TOF_p2
#define t_min mccTOF_mon_2_t_min
#define t_max mccTOF_mon_2_t_max
#define delta_t mccTOF_mon_2_delta_t
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_mon_2_xmin;
MCNUM xmax = mccTOF_mon_2_xmax;
MCNUM ymin = mccTOF_mon_2_ymin;
MCNUM ymax = mccTOF_mon_2_ymax;
MCNUM xwidth = mccTOF_mon_2_xwidth;
MCNUM yheight = mccTOF_mon_2_yheight;
MCNUM t0 = mccTOF_mon_2_t0;
MCNUM t1 = mccTOF_mon_2_t1;
MCNUM dt = mccTOF_mon_2_dt;
MCNUM restore_neutron = mccTOF_mon_2_restore_neutron;
#line 122 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
  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);
}
#line 16327 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'TOF_lmon_2'. */
  SIG_MESSAGE("TOF_lmon_2 (McDisplay)");
  printf("MCDISPLAY: component %s\n", "TOF_lmon_2");
#define mccompcurname  TOF_lmon_2
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 6
#define nlam mccTOF_lmon_2_nlam
#define nt mccTOF_lmon_2_nt
#define filename mccTOF_lmon_2_filename
#define t_0 mccTOF_lmon_2_t_0
#define t_1 mccTOF_lmon_2_t_1
#define tt_0 mccTOF_lmon_2_tt_0
#define tt_1 mccTOF_lmon_2_tt_1
#define TOFL_N mccTOF_lmon_2_TOFL_N
#define TOFL_p mccTOF_lmon_2_TOFL_p
#define TOFL_p2 mccTOF_lmon_2_TOFL_p2
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_lmon_2_xmin;
MCNUM xmax = mccTOF_lmon_2_xmax;
MCNUM ymin = mccTOF_lmon_2_ymin;
MCNUM ymax = mccTOF_lmon_2_ymax;
MCNUM xwidth = mccTOF_lmon_2_xwidth;
MCNUM yheight = mccTOF_lmon_2_yheight;
MCNUM lambda_0 = mccTOF_lmon_2_lambda_0;
MCNUM lambda_1 = mccTOF_lmon_2_lambda_1;
MCNUM restore_neutron = mccTOF_lmon_2_restore_neutron;
#line 123 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
{
    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);
}
#line 16376 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Guide1'. */
  SIG_MESSAGE("Guide1 (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Guide1");
#define mccompcurname  Guide1
#define mccompcurtype  Guide
#define mccompcurindex 7
#define reflect mccGuide1_reflect
#define pTable mccGuide1_pTable
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide1_w1;
MCNUM h1 = mccGuide1_h1;
MCNUM w2 = mccGuide1_w2;
MCNUM h2 = mccGuide1_h2;
MCNUM l = mccGuide1_l;
MCNUM R0 = mccGuide1_R0;
MCNUM Qc = mccGuide1_Qc;
MCNUM alpha = mccGuide1_alpha;
MCNUM m = mccGuide1_m;
MCNUM W = mccGuide1_W;
#line 208 "/usr/local/lib/mcstas/optics/Guide.comp"
{
  magnify("xy");
  multiline(5,
            -w1/2.0, -h1/2.0, 0.0,
             w1/2.0, -h1/2.0, 0.0,
             w1/2.0,  h1/2.0, 0.0,
            -w1/2.0,  h1/2.0, 0.0,
            -w1/2.0, -h1/2.0, 0.0);
  multiline(5,
            -w2/2.0, -h2/2.0, (double)l,
             w2/2.0, -h2/2.0, (double)l,
             w2/2.0,  h2/2.0, (double)l,
            -w2/2.0,  h2/2.0, (double)l,
            -w2/2.0, -h2/2.0, (double)l);
  line(-w1/2.0, -h1/2.0, 0, -w2/2.0, -h2/2.0, (double)l);
  line( w1/2.0, -h1/2.0, 0,  w2/2.0, -h2/2.0, (double)l);
  line( w1/2.0,  h1/2.0, 0,  w2/2.0,  h2/2.0, (double)l);
  line(-w1/2.0,  h1/2.0, 0, -w2/2.0,  h2/2.0, (double)l);
}
#line 16431 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Guide2'. */
  SIG_MESSAGE("Guide2 (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Guide2");
#define mccompcurname  Guide2
#define mccompcurtype  Guide_tapering
#define mccompcurindex 8
#define option mccGuide2_option
#define segno mccGuide2_segno
#define w1c mccGuide2_w1c
#define w2c mccGuide2_w2c
#define ww mccGuide2_ww
#define hh mccGuide2_hh
#define whalf mccGuide2_whalf
#define hhalf mccGuide2_hhalf
#define lwhalf mccGuide2_lwhalf
#define lhhalf mccGuide2_lhhalf
#define h1_in mccGuide2_h1_in
#define h2_out mccGuide2_h2_out
#define w1_in mccGuide2_w1_in
#define w2_out mccGuide2_w2_out
#define l_seg mccGuide2_l_seg
#define seg mccGuide2_seg
#define h12 mccGuide2_h12
#define h2 mccGuide2_h2
#define w12 mccGuide2_w12
#define w2 mccGuide2_w2
#define a_ell_q mccGuide2_a_ell_q
#define b_ell_q mccGuide2_b_ell_q
#define lbw mccGuide2_lbw
#define lbh mccGuide2_lbh
#define mxi mccGuide2_mxi
#define u1 mccGuide2_u1
#define u2 mccGuide2_u2
#define div1 mccGuide2_div1
#define p2_para mccGuide2_p2_para
#define test mccGuide2_test
#define Div1 mccGuide2_Div1
#define i mccGuide2_i
#define ii mccGuide2_ii
#define seg mccGuide2_seg
#define fu mccGuide2_fu
#define pos mccGuide2_pos
#define file_name mccGuide2_file_name
#define ep mccGuide2_ep
#define num mccGuide2_num
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide2_w1;
MCNUM h1 = mccGuide2_h1;
MCNUM l = mccGuide2_l;
MCNUM linw = mccGuide2_linw;
MCNUM loutw = mccGuide2_loutw;
MCNUM linh = mccGuide2_linh;
MCNUM louth = mccGuide2_louth;
MCNUM R0 = mccGuide2_R0;
MCNUM Qcx = mccGuide2_Qcx;
MCNUM Qcy = mccGuide2_Qcy;
MCNUM alphax = mccGuide2_alphax;
MCNUM alphay = mccGuide2_alphay;
MCNUM W = mccGuide2_W;
MCNUM mx = mccGuide2_mx;
MCNUM my = mccGuide2_my;
#line 612 "/usr/local/lib/mcstas/optics/Guide_tapering.comp"
{
  double x;
  int i,ii;

  magnify("xy");
  
  for (ii=0; ii < segno; ii++)
  {
     multiline(5,
        -w1_in[ii]/2.0, -h1_in[ii]/2.0,l_seg*(double)ii,
        -w2_out[ii]/2.0, -h2_out[ii]/2.0,l_seg*((double)ii+1.0),
        -w2_out[ii]/2.0,  h2_out[ii]/2.0,l_seg*((double)ii+1.0),
        -w1_in[ii]/2.0,  h1_in[ii]/2.0,l_seg*(double)ii,
        -w1_in[ii]/2.0, -h1_in[ii]/2.0,l_seg*(double)ii);
     multiline(5,
        w1_in[ii]/2.0, -h1_in[ii]/2.0,l_seg*(double)ii,
        w2_out[ii]/2.0, -h2_out[ii]/2.0,l_seg*((double)ii+1.0),
        w2_out[ii]/2.0,  h2_out[ii]/2.0,l_seg*((double)ii+1.0),
        w1_in[ii]/2.0,  h1_in[ii]/2.0,l_seg*(double)ii,
        w1_in[ii]/2.0, -h1_in[ii]/2.0,l_seg*(double)ii);
  }
  line(-w1/2.0, -h1/2.0, 0.0, w1/2.0, -h1/2.0, 0.0);
  line(-w1/2.0, h1/2.0, 0.0, w1/2.0, h1/2.0, 0.0);
  for(i=0; i<segno;i++)   
  {
     line(-w2_out[i]/2.0, -h2_out[i]/2.0, l_seg*(double)(i+1),
     w2_out[i]/2.0, -h2_out[i]/2.0, l_seg*(double)(i+1));
     line(-w2_out[i]/2.0, h2_out[i]/2.0, l_seg*(double)(i+1),
     w2_out[i]/2.0, h2_out[i]/2.0, l_seg*(double)(i+1));
  }

}
#line 16533 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef num
#undef ep
#undef file_name
#undef pos
#undef fu
#undef seg
#undef ii
#undef i
#undef Div1
#undef test
#undef p2_para
#undef div1
#undef u2
#undef u1
#undef mxi
#undef lbh
#undef lbw
#undef b_ell_q
#undef a_ell_q
#undef w2
#undef w12
#undef h2
#undef h12
#undef seg
#undef l_seg
#undef w2_out
#undef w1_in
#undef h2_out
#undef h1_in
#undef lhhalf
#undef lwhalf
#undef hhalf
#undef whalf
#undef hh
#undef ww
#undef w2c
#undef w1c
#undef segno
#undef option
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Guide3'. */
  SIG_MESSAGE("Guide3 (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Guide3");
#define mccompcurname  Guide3
#define mccompcurtype  Guide_tapering
#define mccompcurindex 9
#define option mccGuide3_option
#define segno mccGuide3_segno
#define w1c mccGuide3_w1c
#define w2c mccGuide3_w2c
#define ww mccGuide3_ww
#define hh mccGuide3_hh
#define whalf mccGuide3_whalf
#define hhalf mccGuide3_hhalf
#define lwhalf mccGuide3_lwhalf
#define lhhalf mccGuide3_lhhalf
#define h1_in mccGuide3_h1_in
#define h2_out mccGuide3_h2_out
#define w1_in mccGuide3_w1_in
#define w2_out mccGuide3_w2_out
#define l_seg mccGuide3_l_seg
#define seg mccGuide3_seg
#define h12 mccGuide3_h12
#define h2 mccGuide3_h2
#define w12 mccGuide3_w12
#define w2 mccGuide3_w2
#define a_ell_q mccGuide3_a_ell_q
#define b_ell_q mccGuide3_b_ell_q
#define lbw mccGuide3_lbw
#define lbh mccGuide3_lbh
#define mxi mccGuide3_mxi
#define u1 mccGuide3_u1
#define u2 mccGuide3_u2
#define div1 mccGuide3_div1
#define p2_para mccGuide3_p2_para
#define test mccGuide3_test
#define Div1 mccGuide3_Div1
#define i mccGuide3_i
#define ii mccGuide3_ii
#define seg mccGuide3_seg
#define fu mccGuide3_fu
#define pos mccGuide3_pos
#define file_name mccGuide3_file_name
#define ep mccGuide3_ep
#define num mccGuide3_num
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide3_w1;
MCNUM h1 = mccGuide3_h1;
MCNUM l = mccGuide3_l;
MCNUM linw = mccGuide3_linw;
MCNUM loutw = mccGuide3_loutw;
MCNUM linh = mccGuide3_linh;
MCNUM louth = mccGuide3_louth;
MCNUM R0 = mccGuide3_R0;
MCNUM Qcx = mccGuide3_Qcx;
MCNUM Qcy = mccGuide3_Qcy;
MCNUM alphax = mccGuide3_alphax;
MCNUM alphay = mccGuide3_alphay;
MCNUM W = mccGuide3_W;
MCNUM mx = mccGuide3_mx;
MCNUM my = mccGuide3_my;
#line 612 "/usr/local/lib/mcstas/optics/Guide_tapering.comp"
{
  double x;
  int i,ii;

  magnify("xy");
  
  for (ii=0; ii < segno; ii++)
  {
     multiline(5,
        -w1_in[ii]/2.0, -h1_in[ii]/2.0,l_seg*(double)ii,
        -w2_out[ii]/2.0, -h2_out[ii]/2.0,l_seg*((double)ii+1.0),
        -w2_out[ii]/2.0,  h2_out[ii]/2.0,l_seg*((double)ii+1.0),
        -w1_in[ii]/2.0,  h1_in[ii]/2.0,l_seg*(double)ii,
        -w1_in[ii]/2.0, -h1_in[ii]/2.0,l_seg*(double)ii);
     multiline(5,
        w1_in[ii]/2.0, -h1_in[ii]/2.0,l_seg*(double)ii,
        w2_out[ii]/2.0, -h2_out[ii]/2.0,l_seg*((double)ii+1.0),
        w2_out[ii]/2.0,  h2_out[ii]/2.0,l_seg*((double)ii+1.0),
        w1_in[ii]/2.0,  h1_in[ii]/2.0,l_seg*(double)ii,
        w1_in[ii]/2.0, -h1_in[ii]/2.0,l_seg*(double)ii);
  }
  line(-w1/2.0, -h1/2.0, 0.0, w1/2.0, -h1/2.0, 0.0);
  line(-w1/2.0, h1/2.0, 0.0, w1/2.0, h1/2.0, 0.0);
  for(i=0; i<segno;i++)   
  {
     line(-w2_out[i]/2.0, -h2_out[i]/2.0, l_seg*(double)(i+1),
     w2_out[i]/2.0, -h2_out[i]/2.0, l_seg*(double)(i+1));
     line(-w2_out[i]/2.0, h2_out[i]/2.0, l_seg*(double)(i+1),
     w2_out[i]/2.0, h2_out[i]/2.0, l_seg*(double)(i+1));
  }

}
#line 16672 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef num
#undef ep
#undef file_name
#undef pos
#undef fu
#undef seg
#undef ii
#undef i
#undef Div1
#undef test
#undef p2_para
#undef div1
#undef u2
#undef u1
#undef mxi
#undef lbh
#undef lbw
#undef b_ell_q
#undef a_ell_q
#undef w2
#undef w12
#undef h2
#undef h12
#undef seg
#undef l_seg
#undef w2_out
#undef w1_in
#undef h2_out
#undef h1_in
#undef lhhalf
#undef lwhalf
#undef hhalf
#undef whalf
#undef hh
#undef ww
#undef w2c
#undef w1c
#undef segno
#undef option
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Guide4a'. */
  SIG_MESSAGE("Guide4a (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Guide4a");
#define mccompcurname  Guide4a
#define mccompcurtype  Guide
#define mccompcurindex 10
#define reflect mccGuide4a_reflect
#define pTable mccGuide4a_pTable
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide4a_w1;
MCNUM h1 = mccGuide4a_h1;
MCNUM w2 = mccGuide4a_w2;
MCNUM h2 = mccGuide4a_h2;
MCNUM l = mccGuide4a_l;
MCNUM R0 = mccGuide4a_R0;
MCNUM Qc = mccGuide4a_Qc;
MCNUM alpha = mccGuide4a_alpha;
MCNUM m = mccGuide4a_m;
MCNUM W = mccGuide4a_W;
#line 208 "/usr/local/lib/mcstas/optics/Guide.comp"
{
  magnify("xy");
  multiline(5,
            -w1/2.0, -h1/2.0, 0.0,
             w1/2.0, -h1/2.0, 0.0,
             w1/2.0,  h1/2.0, 0.0,
            -w1/2.0,  h1/2.0, 0.0,
            -w1/2.0, -h1/2.0, 0.0);
  multiline(5,
            -w2/2.0, -h2/2.0, (double)l,
             w2/2.0, -h2/2.0, (double)l,
             w2/2.0,  h2/2.0, (double)l,
            -w2/2.0,  h2/2.0, (double)l,
            -w2/2.0, -h2/2.0, (double)l);
  line(-w1/2.0, -h1/2.0, 0, -w2/2.0, -h2/2.0, (double)l);
  line( w1/2.0, -h1/2.0, 0,  w2/2.0, -h2/2.0, (double)l);
  line( w1/2.0,  h1/2.0, 0,  w2/2.0,  h2/2.0, (double)l);
  line(-w1/2.0,  h1/2.0, 0, -w2/2.0,  h2/2.0, (double)l);
}
#line 16756 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Guide4b'. */
  SIG_MESSAGE("Guide4b (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Guide4b");
#define mccompcurname  Guide4b
#define mccompcurtype  Guide
#define mccompcurindex 11
#define reflect mccGuide4b_reflect
#define pTable mccGuide4b_pTable
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide4b_w1;
MCNUM h1 = mccGuide4b_h1;
MCNUM w2 = mccGuide4b_w2;
MCNUM h2 = mccGuide4b_h2;
MCNUM l = mccGuide4b_l;
MCNUM R0 = mccGuide4b_R0;
MCNUM Qc = mccGuide4b_Qc;
MCNUM alpha = mccGuide4b_alpha;
MCNUM m = mccGuide4b_m;
MCNUM W = mccGuide4b_W;
#line 208 "/usr/local/lib/mcstas/optics/Guide.comp"
{
  magnify("xy");
  multiline(5,
            -w1/2.0, -h1/2.0, 0.0,
             w1/2.0, -h1/2.0, 0.0,
             w1/2.0,  h1/2.0, 0.0,
            -w1/2.0,  h1/2.0, 0.0,
            -w1/2.0, -h1/2.0, 0.0);
  multiline(5,
            -w2/2.0, -h2/2.0, (double)l,
             w2/2.0, -h2/2.0, (double)l,
             w2/2.0,  h2/2.0, (double)l,
            -w2/2.0,  h2/2.0, (double)l,
            -w2/2.0, -h2/2.0, (double)l);
  line(-w1/2.0, -h1/2.0, 0, -w2/2.0, -h2/2.0, (double)l);
  line( w1/2.0, -h1/2.0, 0,  w2/2.0, -h2/2.0, (double)l);
  line( w1/2.0,  h1/2.0, 0,  w2/2.0,  h2/2.0, (double)l);
  line(-w1/2.0,  h1/2.0, 0, -w2/2.0,  h2/2.0, (double)l);
}
#line 16803 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Guide4c'. */
  SIG_MESSAGE("Guide4c (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Guide4c");
#define mccompcurname  Guide4c
#define mccompcurtype  Guide
#define mccompcurindex 12
#define reflect mccGuide4c_reflect
#define pTable mccGuide4c_pTable
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccGuide4c_w1;
MCNUM h1 = mccGuide4c_h1;
MCNUM w2 = mccGuide4c_w2;
MCNUM h2 = mccGuide4c_h2;
MCNUM l = mccGuide4c_l;
MCNUM R0 = mccGuide4c_R0;
MCNUM Qc = mccGuide4c_Qc;
MCNUM alpha = mccGuide4c_alpha;
MCNUM m = mccGuide4c_m;
MCNUM W = mccGuide4c_W;
#line 208 "/usr/local/lib/mcstas/optics/Guide.comp"
{
  magnify("xy");
  multiline(5,
            -w1/2.0, -h1/2.0, 0.0,
             w1/2.0, -h1/2.0, 0.0,
             w1/2.0,  h1/2.0, 0.0,
            -w1/2.0,  h1/2.0, 0.0,
            -w1/2.0, -h1/2.0, 0.0);
  multiline(5,
            -w2/2.0, -h2/2.0, (double)l,
             w2/2.0, -h2/2.0, (double)l,
             w2/2.0,  h2/2.0, (double)l,
            -w2/2.0,  h2/2.0, (double)l,
            -w2/2.0, -h2/2.0, (double)l);
  line(-w1/2.0, -h1/2.0, 0, -w2/2.0, -h2/2.0, (double)l);
  line( w1/2.0, -h1/2.0, 0,  w2/2.0, -h2/2.0, (double)l);
  line( w1/2.0,  h1/2.0, 0,  w2/2.0,  h2/2.0, (double)l);
  line(-w1/2.0,  h1/2.0, 0, -w2/2.0,  h2/2.0, (double)l);
}
#line 16850 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef pTable
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'TOF_mon_3'. */
  SIG_MESSAGE("TOF_mon_3 (McDisplay)");
  printf("MCDISPLAY: component %s\n", "TOF_mon_3");
#define mccompcurname  TOF_mon_3
#define mccompcurtype  TOF_monitor
#define mccompcurindex 13
#define nchan mccTOF_mon_3_nchan
#define filename mccTOF_mon_3_filename
#define TOF_N mccTOF_mon_3_TOF_N
#define TOF_p mccTOF_mon_3_TOF_p
#define TOF_p2 mccTOF_mon_3_TOF_p2
#define t_min mccTOF_mon_3_t_min
#define t_max mccTOF_mon_3_t_max
#define delta_t mccTOF_mon_3_delta_t
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_mon_3_xmin;
MCNUM xmax = mccTOF_mon_3_xmax;
MCNUM ymin = mccTOF_mon_3_ymin;
MCNUM ymax = mccTOF_mon_3_ymax;
MCNUM xwidth = mccTOF_mon_3_xwidth;
MCNUM yheight = mccTOF_mon_3_yheight;
MCNUM t0 = mccTOF_mon_3_t0;
MCNUM t1 = mccTOF_mon_3_t1;
MCNUM dt = mccTOF_mon_3_dt;
MCNUM restore_neutron = mccTOF_mon_3_restore_neutron;
#line 122 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
  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);
}
#line 16892 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'TOF_lmon_3'. */
  SIG_MESSAGE("TOF_lmon_3 (McDisplay)");
  printf("MCDISPLAY: component %s\n", "TOF_lmon_3");
#define mccompcurname  TOF_lmon_3
#define mccompcurtype  TOFLambda_monitor
#define mccompcurindex 14
#define nlam mccTOF_lmon_3_nlam
#define nt mccTOF_lmon_3_nt
#define filename mccTOF_lmon_3_filename
#define t_0 mccTOF_lmon_3_t_0
#define t_1 mccTOF_lmon_3_t_1
#define tt_0 mccTOF_lmon_3_tt_0
#define tt_1 mccTOF_lmon_3_tt_1
#define TOFL_N mccTOF_lmon_3_TOFL_N
#define TOFL_p mccTOF_lmon_3_TOFL_p
#define TOFL_p2 mccTOF_lmon_3_TOFL_p2
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccTOF_lmon_3_xmin;
MCNUM xmax = mccTOF_lmon_3_xmax;
MCNUM ymin = mccTOF_lmon_3_ymin;
MCNUM ymax = mccTOF_lmon_3_ymax;
MCNUM xwidth = mccTOF_lmon_3_xwidth;
MCNUM yheight = mccTOF_lmon_3_yheight;
MCNUM lambda_0 = mccTOF_lmon_3_lambda_0;
MCNUM lambda_1 = mccTOF_lmon_3_lambda_1;
MCNUM restore_neutron = mccTOF_lmon_3_restore_neutron;
#line 123 "/usr/local/lib/mcstas/monitors/TOFLambda_monitor.comp"
{
    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);
}
#line 16941 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef TOFL_p2
#undef TOFL_p
#undef TOFL_N
#undef tt_1
#undef tt_0
#undef t_1
#undef t_0
#undef filename
#undef nt
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'DivLambda_mon'. */
  SIG_MESSAGE("DivLambda_mon (McDisplay)");
  printf("MCDISPLAY: component %s\n", "DivLambda_mon");
#define mccompcurname  DivLambda_mon
#define mccompcurtype  DivLambda_monitor
#define mccompcurindex 15
#define nlam mccDivLambda_mon_nlam
#define ndiv mccDivLambda_mon_ndiv
#define filename mccDivLambda_mon_filename
#define restore_neutron mccDivLambda_mon_restore_neutron
#define Div_N mccDivLambda_mon_Div_N
#define Div_p mccDivLambda_mon_Div_p
#define Div_p2 mccDivLambda_mon_Div_p2
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccDivLambda_mon_xmin;
MCNUM xmax = mccDivLambda_mon_xmax;
MCNUM ymin = mccDivLambda_mon_ymin;
MCNUM ymax = mccDivLambda_mon_ymax;
MCNUM xwidth = mccDivLambda_mon_xwidth;
MCNUM yheight = mccDivLambda_mon_yheight;
MCNUM maxdiv = mccDivLambda_mon_maxdiv;
MCNUM lambda_0 = mccDivLambda_mon_lambda_0;
MCNUM lambda_1 = mccDivLambda_mon_lambda_1;
#line 126 "/usr/local/lib/mcstas/monitors/DivLambda_monitor.comp"
{
    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);
}
#line 16989 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef Div_p2
#undef Div_p
#undef Div_N
#undef restore_neutron
#undef filename
#undef ndiv
#undef nlam
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Sample'. */
  SIG_MESSAGE("Sample (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Sample");
#define mccompcurname  Sample
#define mccompcurtype  Powder1
#define mccompcurindex 16
#define my_s_v2 mccSample_my_s_v2
#define my_a_v mccSample_my_a_v
#define q_v mccSample_q_v
#define isrect mccSample_isrect
{   /* Declarations of SETTING parameters. */
MCNUM radius = mccSample_radius;
MCNUM yheight = mccSample_yheight;
MCNUM q = mccSample_q;
MCNUM d = mccSample_d;
MCNUM d_phi = mccSample_d_phi;
MCNUM pack = mccSample_pack;
MCNUM j = mccSample_j;
MCNUM DW = mccSample_DW;
MCNUM F2 = mccSample_F2;
MCNUM Vc = mccSample_Vc;
MCNUM sigma_a = mccSample_sigma_a;
MCNUM xwidth = mccSample_xwidth;
MCNUM zthick = mccSample_zthick;
MCNUM h = mccSample_h;
#line 179 "/usr/local/lib/mcstas/samples/Powder1.comp"
{
  double h;
  h=yheight;
  magnify("xyz");
  if (!isrect) {
    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);
  } else {
    double xmin = -0.5*xwidth;
    double xmax =  0.5*xwidth;
    double ymin = -0.5*yheight;
    double ymax =  0.5*yheight;
    double zmin = -0.5*zthick;
    double zmax =  0.5*zthick;
    multiline(5, xmin, ymin, zmin,
                 xmax, ymin, zmin,
                 xmax, ymax, zmin,
                 xmin, ymax, zmin,
                 xmin, ymin, zmin);
    multiline(5, xmin, ymin, zmax,
                 xmax, ymin, zmax,
                 xmax, ymax, zmax,
                 xmin, ymax, zmax,
                 xmin, ymin, zmax);
    line(xmin, ymin, zmin, xmin, ymin, zmax);
    line(xmax, ymin, zmin, xmax, ymin, zmax);
    line(xmin, ymax, zmin, xmin, ymax, zmax);
    line(xmax, ymax, zmin, xmax, ymax, zmax);
  }
}
#line 17062 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef isrect
#undef q_v
#undef my_a_v
#undef my_s_v2
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Detector'. */
  SIG_MESSAGE("Detector (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Detector");
#define mccompcurname  Detector
#define mccompcurtype  TOF_cylPSD_monitor
#define mccompcurindex 17
#define nt mccDetector_nt
#define filename mccDetector_filename
#define nphi mccDetector_nphi
#define TOF_N mccDetector_TOF_N
#define TOF_p mccDetector_TOF_p
#define TOF_p2 mccDetector_TOF_p2
{   /* Declarations of SETTING parameters. */
MCNUM radius = mccDetector_radius;
MCNUM height = mccDetector_height;
MCNUM t_0 = mccDetector_t_0;
MCNUM t_1 = mccDetector_t_1;
MCNUM restore_neutron = mccDetector_restore_neutron;
#line 115 "/usr/local/lib/mcstas/monitors/TOF_cylPSD_monitor.comp"
{
  magnify("y");
  circle("xz", 0,0,0,radius);
}
#line 17095 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef nphi
#undef filename
#undef nt
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'arm1'. */
  SIG_MESSAGE("arm1 (McDisplay)");
  printf("MCDISPLAY: component %s\n", "arm1");
#define mccompcurname  arm1
#define mccompcurtype  Arm
#define mccompcurindex 18
#line 43 "/usr/local/lib/mcstas/optics/Arm.comp"
{
  /* A bit ugly; hard-coded dimensions. */
  magnify("");
  line(0,0,0,0.2,0,0);
  line(0,0,0,0,0.2,0);
  line(0,0,0,0,0,0.2);
}
#line 17121 "TOFexercise42.c"
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'LineDetector'. */
  SIG_MESSAGE("LineDetector (McDisplay)");
  printf("MCDISPLAY: component %s\n", "LineDetector");
#define mccompcurname  LineDetector
#define mccompcurtype  TOF_monitor
#define mccompcurindex 19
#define nchan mccLineDetector_nchan
#define filename mccLineDetector_filename
#define TOF_N mccLineDetector_TOF_N
#define TOF_p mccLineDetector_TOF_p
#define TOF_p2 mccLineDetector_TOF_p2
#define t_min mccLineDetector_t_min
#define t_max mccLineDetector_t_max
#define delta_t mccLineDetector_delta_t
{   /* Declarations of SETTING parameters. */
MCNUM xmin = mccLineDetector_xmin;
MCNUM xmax = mccLineDetector_xmax;
MCNUM ymin = mccLineDetector_ymin;
MCNUM ymax = mccLineDetector_ymax;
MCNUM xwidth = mccLineDetector_xwidth;
MCNUM yheight = mccLineDetector_yheight;
MCNUM t0 = mccLineDetector_t0;
MCNUM t1 = mccLineDetector_t1;
MCNUM dt = mccLineDetector_dt;
MCNUM restore_neutron = mccLineDetector_restore_neutron;
#line 122 "/usr/local/lib/mcstas/monitors/TOF_monitor.comp"
{
  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);
}
#line 17160 "TOFexercise42.c"
}   /* End of SETTING parameter declarations. */
#undef delta_t
#undef t_max
#undef t_min
#undef TOF_p2
#undef TOF_p
#undef TOF_N
#undef filename
#undef nchan
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  printf("MCDISPLAY: end\n");
} /* end display */
#undef magnify
#undef line
#undef dashed_line
#undef multiline
#undef rectangle
#undef box
#undef circle
