/* Automatically generated file. Do not edit. 
 * Format:     ANSI C source code
 * Creator:    McStas <http://neutron.risoe.dk>
 * Instrument: D1A.instr (D1A)
 * Date:       Mon Jun 22 10:37:08 2009
 */


#define MCSTAS_VERSION "1.12a - Apr. 02, 2009"
#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-2009, 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.12a
*
*       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(double count);
double mcget_ncount(void);
double 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 "D1A.c"

#line 1 "nexus-lib.h"
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2009, 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 "D1A.c"

#line 1 "nexus-lib.c"
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2009, 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.12a
* 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 "D1A.c"

#line 1 "mcstas-r.c"
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2009, 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.12a
*
* 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 double mcncount             = 1e6;
mcstatic double 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/N - pmean*pmean));
}

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

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

/* mcget_run_num: get curent number of neutrons in TRACE */
double 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=%i, 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=%i, 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=%i, 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 */

#if defined(NL_ARGMAX) || defined(WIN32)
/*******************************************************************************
* pfprintf: just as fprintf, but with (char *)fmt_args being the list of arg type
*   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
*******************************************************************************/
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)
    {
      arg_posE[this_arg] = (char *)strchr(tmp, '$');
      if (arg_posE[this_arg] && tmp[1] != '%')
      {
        char  this_arg_chr[10];
        char  printf_formats[]="dliouxXeEfgGcs\0";

        /* extract positional argument index %*$ in fmt */
        strncpy(this_arg_chr, arg_posB[this_arg]+1, arg_posE[this_arg]-arg_posB[this_arg]-1);
        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 (<=0 or >=%i) %s.\n", MyNL_ARGMAX, arg_posB[this_arg]));
        /* get type of positional argument: follows '%' -> arg_posE[this_arg]+1 */
        fmt_pos = arg_posE[this_arg]+1;
        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++;
        arg_posT[this_arg] = fmt_pos;
        /* get next argument... */
        this_arg++;
      }
      else
      {
        if  (tmp[1] != '%')
          return(-fprintf(stderr,"pfprintf: must use only positional arguments (%s).\n", arg_posB[this_arg]));
        else fmt_pos = arg_posB[this_arg]+2;  /* found %% */
      }
    } 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(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':                       /* int */
              arg_long[this_arg] = va_arg(ap, long int);
              break;
      case 'f':
      case 'g':
      case 'G':                      /* 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, 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(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 'G':                       /* 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);
}
#else
static int pfprintf(FILE *f, char *fmt, char *fmt_args, ...)
{ /* wrapper to standard fprintf when the library function is OK (linux) */
  va_list ap;
  int tmp;

  va_start(ap, fmt_args);
  tmp=vfprintf(f, fmt, ap);
  va_end(ap);
  return(tmp);
}
#endif

/*******************************************************************************
* 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;
  }
#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;
  Coords b;
  if ((t=scalar_prod(n.x,n.y,n.z, n.x,n.y,n.z))!=1)
    n.x/=sqrt(t);n.y/=sqrt(t);n.z/=sqrt(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 intersction with a cylinder
 * returns 0 when no intersection is found
 *      or 2/4/8/16 bits depending on intersection,
 *     and resulting times t0 and tdt_out1
 * 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;
    } 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);

    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(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*mcget_run_num()/mcget_ncount(), mcget_run_num(), 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 */
    srandom(time(&t) + mpi_node_rank);
    t += mpi_node_rank;
  }
#else /* !USE_MPI */
  srandom(time(&t));
#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 6942 "D1A.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[] = "D1A";
char mcinstrument_source[] = "D1A.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 'Monochromator_curved'. */
#line 105 "/usr/local/lib/mcstas/optics/Monochromator_curved.comp"
#ifndef GAUSS
  /* Define these arrays only once for all instances. */
  /* Values for Gauss quadrature. Taken from Brice Carnahan, H. A. Luther and
     James O Wilkes, "Applied numerical methods", Wiley, 1969, page 103.
     This reference is available from the Copenhagen UB2 library */
  double Gauss_X[] = {-0.987992518020485, -0.937273392400706, -0.848206583410427,
                -0.724417731360170, -0.570972172608539, -0.394151347077563,
                -0.201194093997435, 0, 0.201194093997435,
                0.394151347077563, 0.570972172608539, 0.724417731360170,
                0.848206583410427, 0.937273392400706, 0.987992518020485};
  double Gauss_W[] = {0.030753241996117, 0.070366047488108, 0.107159220467172,
                0.139570677926154, 0.166269205816994, 0.186161000115562,
                0.198431485327111, 0.202578241925561, 0.198431485327111,
                0.186161000115562, 0.166269205816994, 0.139570677926154,
                0.107159220467172, 0.070366047488108, 0.030753241996117};


#define GAUSS(x,mean,rms) \
  (exp(-((x)-(mean))*((x)-(mean))/(2*(rms)*(rms)))/(sqrt(2*PI)*(rms)))
#endif

/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2009, 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.12a
* 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-2009, 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.12a
* 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[64*1024];
      long  mc_rt_back_pos=0;   /* ftell start of line */

      mc_rt_back_pos = ftell(mc_rt_hfile);
      if (fgets(mc_rt_line, 64*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 8258 "D1A.c"

/* Shared user declarations for all components 'Monitor_nD'. */
#line 215 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2009, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Library: share/monitor_nd-lib.h
*
* %Identification
* Written by: EF
* Date: Aug 28, 2002
* Origin: ILL
* Release: McStas 1.12a
* Version: $Revision: 1.17 $
*
* This file is to be imported by the monitor_nd related components
* It handles some shared functions.
*
* Usage: within SHARE
* %include "monitor_nd-lib"
*
* $Id: monitor_nd-lib.h,v 1.17 2008/04/01 09:15:04 farhi Exp $
*
* $Log: monitor_nd-lib.h,v $
* Revision 1.17  2008/04/01 09:15:04  farhi
* Monitor_nD now accepts up to 3 user variables, e.g. for coordinates
* to be stored into "list".
*
* Revision 1.16  2006/07/21 14:09:07  farhi
* Fix wrong structure member
*
* Revision 1.15  2006/07/21 09:03:23  farhi
* Added in options'per steradian' flux estimate, and possibility to glue the
* monitor to the shape of the 'previous' component (unactivate propagation), so
* that we can mnonitor what's going on at the output surface of the previous comp.
*
* Revision 1.14  2005/08/24 13:14:40  lieutenant
* new option 'exclusive'
*
* Revision 1.13  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.12  2005/07/04 08:20:16  farhi
* added support for radial distributions vxy kxy and xy=radius
*
* Revision 1.11  2005/02/22 16:11:03  farhi
* Now saving absolute position of monitors as "position" field in header
* Useful for plotting e.g. flux vs distance
*
* Revision 1.10  2005/01/18 10:35:56  farhi
* Intall new MACROs for easy User Variable usage in Monitor_nD
* MONND_DECLARE(comp)
* MONND_USER_TITLE(comp, num, title)
* MONND_USER_VALUE(comp, num, value)
* comp is the name of a Monitor_nD component; num is 1 or 2 for UserVariable
*
* Revision 1.9  2004/11/30 16:11:37  farhi
* defined some macros for an easier User variable handling. Should be updated in the header and Comp doc
*
* 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/28 11:39:00 ef
* Initial revision extracted from lib/monitors/Monitor_nD.comp
*******************************************************************************/

#ifndef MONITOR_ND_LIB_H

#define MONITOR_ND_LIB_H "1.1.1"
#define MONnD_COORD_NMAX  30  /* max number of variables to record */

  typedef struct MonitornD_Defines
  {
    char COORD_NONE  ;
    char COORD_X     ;
    char COORD_Y     ;
    char COORD_Z     ;
    char COORD_VX    ;
    char COORD_VY    ;
    char COORD_VZ    ;
    char COORD_T     ;
    char COORD_P     ;
    char COORD_SX    ;
    char COORD_SY    ;
    char COORD_SZ    ;
    char COORD_KX    ;
    char COORD_KY    ;
    char COORD_KZ    ;
    char COORD_K     ;
    char COORD_V     ;
    char COORD_ENERGY;
    char COORD_LAMBDA;
    char COORD_RADIUS;
    char COORD_KXY   ;
    char COORD_VXY   ;
    char COORD_HDIV  ;
    char COORD_VDIV  ;
    char COORD_ANGLE ;
    char COORD_NCOUNT;
    char COORD_THETA ;
    char COORD_PHI   ;
    char COORD_USER1 ;
    char COORD_USER2 ;
    char COORD_USER3 ;

    /* token modifiers */
    char COORD_VAR   ; /* next token should be a variable or normal option */
    char COORD_MIN   ; /* next token is a min value */
    char COORD_MAX   ; /* next token is a max value */
    char COORD_DIM   ; /* next token is a bin value */
    char COORD_FIL   ; /* next token is a filename */
    char COORD_EVNT  ; /* next token is a buffer size value */
    char COORD_3HE   ; /* next token is a 3He pressure value */
    char COORD_INTERM; /* next token is an intermediate save value (percent) */
    char COORD_LOG   ; /* next variable will be in log scale */
    char COORD_ABS   ; /* next variable will be in abs scale */
    char COORD_SIGNAL; /* next variable will be the signal var */
    int  COORD_AUTO  ; /* set auto limits */

    char TOKEN_DEL[32]; /* token separators */

    char SHAPE_SQUARE; /* shape of the monitor */
    char SHAPE_DISK  ;
    char SHAPE_SPHERE;
    char SHAPE_CYLIND;
    char SHAPE_BANANA; /* cylinder without top/bottom, on restricted angular area */
    char SHAPE_BOX   ;
    char SHAPE_PREVIOUS;

  } MonitornD_Defines_type;

  typedef struct MonitornD_Variables
  {
    double area, steradian;
    double Sphere_Radius     ;
    double Cylinder_Height   ;
    char   Flag_With_Borders ;   /* 2 means xy borders too */
    char   Flag_List         ;   /* 1 store 1 buffer, 2 is list all, 3 list all+append */
    char   Flag_Multiple     ;   /* 1 when n1D, 0 for 2D */
    char   Flag_Verbose      ;
    int    Flag_Shape        ;
    char   Flag_Auto_Limits  ;   /* get limits from first Buffer */
    char   Flag_Absorb       ;   /* monitor is also a slit */
    char   Flag_Exclusive    ;   /* absorb neutrons out of monitor limits */
    char   Flag_per_cm2      ;   /* flux is per cm2 */
    char   Flag_per_st       ;   /* flux is per steradian */
    char   Flag_log          ;   /* log10 of the flux */
    char   Flag_parallel     ;   /* set neutron state back after detection (parallel components) */
    char   Flag_Binary_List  ;
    char   Flag_capture      ;   /* lambda monitor with lambda/lambda(2200m/s = 1.7985 Angs) weightening */
    int    Flag_signal       ;   /* 0:monitor p, else monitor a mean value */

    long   Coord_Number      ;   /* total number of variables to monitor, plus intensity (0) */
    long   Buffer_Block      ;   /* Buffer size for list or auto limits */
    long   Neutron_Counter   ;   /* event counter, simulation total counts is mcget_ncount() */
    long   Buffer_Counter    ;   /* index in Buffer size (for realloc) */
    long   Buffer_Size       ;
    int    Coord_Type[MONnD_COORD_NMAX];    /* type of variable */
    char   Coord_Label[MONnD_COORD_NMAX][30];       /* label of variable */
    char   Coord_Var[MONnD_COORD_NMAX][30]; /* short id of variable */
    long   Coord_Bin[MONnD_COORD_NMAX];             /* bins of variable array */
    double Coord_Min[MONnD_COORD_NMAX];
    double Coord_Max[MONnD_COORD_NMAX];
    char   Monitor_Label[MONnD_COORD_NMAX*30];      /* Label for monitor */
    char   Mon_File[128];    /* output file name */

    double cx,cy,cz;
    double cvx, cvy, cvz;
    double csx, csy, csz;
    double cs1, cs2, ct, cp;
    double He3_pressure;
    char   Flag_UsePreMonitor    ;   /* use a previously stored neutron parameter set */
    char   UserName1[128];
    char   UserName2[128];
    char   UserName3[128];
    double UserVariable1;
    double UserVariable2;
    double UserVariable3;
    double Intermediate;
    double IntermediateCnts;
    char   option[1024];

    double Nsum;
    double psum, p2sum;
    double **Mon2D_N;
    double **Mon2D_p;
    double **Mon2D_p2;
    double *Mon2D_Buffer;

    double mxmin,mxmax,mymin,mymax,mzmin,mzmax;
    double mean_dx, mean_dy, min_x, min_y, max_x, max_y, mean_p;

    char   compcurname[128];
    Coords compcurpos;

  } MonitornD_Variables_type;

/* monitor_nd-lib function prototypes */
/* ========================================================================= */

void Monitor_nD_Init(MonitornD_Defines_type *, MonitornD_Variables_type *, MCNUM, MCNUM, MCNUM, MCNUM, MCNUM, MCNUM, MCNUM, MCNUM, MCNUM);
double Monitor_nD_Trace(MonitornD_Defines_type *, MonitornD_Variables_type *);
void Monitor_nD_Save(MonitornD_Defines_type *, MonitornD_Variables_type *);
void Monitor_nD_Finally(MonitornD_Defines_type *, MonitornD_Variables_type *);
void Monitor_nD_McDisplay(MonitornD_Defines_type *,
 MonitornD_Variables_type *);

#define MONND_DECLARE(monname) \
  struct MonitornD_Variables *mcmonnd ## monname;
#define MONND_USER_TITLE(monname, num, title) \
  { mcmonnd ## monname = &(MC_GETPAR(monname, Vars)); \
    strcpy(mcmonnd ## monname->UserName ## num, title); }
#define MONND_USER_VALUE(monname, num, value) \
  { mcmonnd ## monname = &(MC_GETPAR(monname, Vars)); \
    mcmonnd ## monname->UserVariable ## num = (value); }

#endif

/* end of monitor_nd-lib.h */
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2009, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Library: share/monitor_nd-lib.c
*
* %Identification
* Written by: EF
* Date: Aug 28, 2002
* Origin: ILL
* Release: McStas 1.12a
* Version: $Revision: 1.41 $
*
* This file is to be imported by the monitor_nd related components
* It handles some shared functions. Embedded within instrument in runtime mode.
* Variable names have prefix 'mc_mn_' for 'McStas Monitor' to avoid conflicts
*
* Usage: within SHARE
* %include "monitor_nd-lib"
*
* $Id: monitor_nd-lib.c,v 1.41 2008/07/01 20:28:13 farhi Exp $
*
* $Log: monitor_nd-lib.c,v $
* Revision 1.41  2008/07/01 20:28:13  farhi
* Fixed zthick -> zdepth
*
* Revision 1.40  2008/07/01 19:50:23  farhi
* Common naming convention for components:
*   xwidth, yheight, zdepth, radius, thickness
*   sigma_abs, sigma_inc
*
* Revision 1.39  2008/04/06 14:02:41  pkwi
* Intel C compiler version 10.1 series fail with Monitor_nD (All events absorbed)....
* The inserted empty printf seems to solve this?!
*
* I will try to file a support request at Intel on this problem...
*
* Revision 1.38  2008/04/01 09:15:04  farhi
* Monitor_nD now accepts up to 3 user variables, e.g. for coordinates
* to be stored into "list".
*
* Revision 1.37  2007/04/02 12:13:13  farhi
* Fixed length of username1|2 to avoid buffer overflow.
*
* Revision 1.36  2006/11/16 10:14:21  farhi
* Correct mcdisplay section with restricted banana/sphere (skipped last monitored variable)
*
* Revision 1.35  2006/07/21 09:03:23  farhi
* Added in options'per steradian' flux estimate, and possibility to glue the
* monitor to the shape of the 'previous' component (unactivate propagation), so
* that we can mnonitor what's going on at the output surface of the previous comp.
*
* Revision 1.34  2006/03/15 16:01:43  farhi
* 'keyword ignored' warning only in verbose mode
*
* Revision 1.33  2005/12/12 13:42:11  farhi
* Corrected bug on multiple limits specifications (K. Lieutenant)
*
* Revision 1.32  2005/09/19 15:13:53  farhi
* using 'y' variable also sets limits to detector dimensions, to enable 'banana' view without troubles.
*
* Revision 1.31  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.30  2005/08/24 13:14:00  lieutenant
* new option 'exclusive'
*
* Revision 1.29  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.28  2005/07/18 14:38:00  farhi
* Added 0.5 top all floor's so that bin are centered (at last)
*
* Revision 1.27  2005/07/06 08:16:28  farhi
* Misprint for Kxy/Vxy. Better Variable name as well.
*
* Revision 1.26  2005/07/04 08:19:50  farhi
* added support for kxy and vxy radial distributions
*
* Revision 1.25  2005/04/11 11:40:44  farhi
* Added missing n-dims argument to printf for capture flux warning
*
* Revision 1.24  2005/03/14 10:48:54  farhi
* Added warning when setting capture flux (meaningful with integral flux) for
* more than 1 bin.
*
* Revision 1.23  2005/02/25 15:26:02  farhi
* Removed usage of round function
* made Guide_honeycomb work with gravitation
*
* Revision 1.22  2005/02/22 16:11:03  farhi
* Now saving absolute position of monitors as "position" field in header
* Useful for plotting e.g. flux vs distance
*
* Revision 1.21  2005/02/21 16:05:13  farhi
* Misprint correction
*
* Revision 1.20  2005/02/21 12:38:03  farhi
* Removed warning in Monitor_nD for global scope keywords in options
*
* Revision 1.19  2005/02/17 16:06:32  farhi
* Added 'per bin' to labels if more than 1 bin, and a message for unknow keywords found in options parameter. Requested by R. Cubitt.
*
* Revision 1.18  2004/11/16 13:36:35  farhi
* Paging update
*
* Revision 1.17  2004/09/01 13:54:18  farhi
* Corrected bug when using list=EVNTS large values written as float, read as int.
* E.g. 1e6 gave 1 as number of events to save !
*
* Revision 1.16  2004/06/30 12:13:47  farhi
* For lists (and Res_monitor), uses 'list' 'no header' and 'no footer' options
* in mcformat.Name so that catenated file does contain only one instance of
* footer and header.
*
* Revision 1.15  2004/02/26 12:55:41  farhi
* Handles 0d monitor outputs for bins=0, and limits are restrictive (i.e. neutron must be within all limits to be stored in monitor)
*
* Revision 1.14  2004/02/04 18:01:12  farhi
* Use hdiv=theta and vdiv=phi for banana.
*
* Revision 1.13  2003/08/26 12:33:27  farhi
* Corrected computation of angle PHI (was projected on vertical plane)
*
* Revision 1.12  2003/04/15 16:01:28  farhi
* incoming/outgoing syntax mismatch correction
*
* Revision 1.11  2003/04/15 15:45:56  farhi
* outgoing time is default (vs. incoming)
*
* Revision 1.10  2003/04/09 15:49:25  farhi
* corrected bug when no signal and auto limits requested
*
* Revision 1.9  2003/02/18 09:11:36  farhi
* Corrected binary format for lists
*
* Revision 1.1 2002/08/28 11:39:00 ef
* Initial revision extracted from lib/monitors/Monitor_nD.comp
*******************************************************************************/

#ifndef MONITOR_ND_LIB_H
#error McStas : please import this library with %include "monitor_nd-lib"
#endif

/* ========================================================================= */
/* ADD: E.Farhi, Aug 6th, 2001: Monitor_nD section */
/* this routine is used to parse options */
/* ========================================================================= */

void Monitor_nD_Init(MonitornD_Defines_type *mc_mn_DEFS,
  MonitornD_Variables_type *mc_mn_Vars,
  MCNUM mc_mn_xwidth,
  MCNUM mc_mn_yheight,
  MCNUM mc_mn_zdepth,
  MCNUM mc_mn_xmin,
  MCNUM mc_mn_xmax,
  MCNUM mc_mn_ymin,
  MCNUM mc_mn_ymax,
  MCNUM mc_mn_zmin,
  MCNUM mc_mn_zmax)
  {
    long mc_mn_carg = 1;
    char *mc_mn_option_copy, *mc_mn_token;
    char mc_mn_Flag_New_token = 1;
    char mc_mn_Flag_End       = 1;
    char mc_mn_Flag_All       = 0;
    char mc_mn_Flag_No        = 0;
    char mc_mn_Flag_abs       = 0;
    int  mc_mn_Flag_auto      = 0;  /* -1: all, 1: the current variable */
    int  mc_mn_Set_Vars_Coord_Type;
    char mc_mn_Set_Vars_Coord_Label[64];
    char mc_mn_Set_Vars_Coord_Var[64];
    char mc_mn_Short_Label[MONnD_COORD_NMAX][64];
    int  mc_mn_Set_Coord_Mode;
    long mc_mn_i=0, mc_mn_j=0;
    double mc_mn_lmin, mc_mn_lmax, mc_mn_XY;
    long mc_mn_t;


    mc_mn_t = (long)time(NULL);

    mc_mn_DEFS->COORD_NONE   =0;
    mc_mn_DEFS->COORD_X      =1;
    mc_mn_DEFS->COORD_Y      =2;
    mc_mn_DEFS->COORD_Z      =3;
    mc_mn_DEFS->COORD_VX     =4;
    mc_mn_DEFS->COORD_VY     =5;
    mc_mn_DEFS->COORD_VZ     =6;
    mc_mn_DEFS->COORD_T      =7;
    mc_mn_DEFS->COORD_P      =8;
    mc_mn_DEFS->COORD_SX     =9;
    mc_mn_DEFS->COORD_SY     =10;
    mc_mn_DEFS->COORD_SZ     =11;
    mc_mn_DEFS->COORD_KX     =12;
    mc_mn_DEFS->COORD_KY     =13;
    mc_mn_DEFS->COORD_KZ     =14;
    mc_mn_DEFS->COORD_K      =15;
    mc_mn_DEFS->COORD_V      =16;
    mc_mn_DEFS->COORD_ENERGY =17;
    mc_mn_DEFS->COORD_LAMBDA =18;
    mc_mn_DEFS->COORD_RADIUS =19;
    mc_mn_DEFS->COORD_HDIV   =20;
    mc_mn_DEFS->COORD_VDIV   =21;
    mc_mn_DEFS->COORD_ANGLE  =22;
    mc_mn_DEFS->COORD_NCOUNT =23;
    mc_mn_DEFS->COORD_THETA  =24;
    mc_mn_DEFS->COORD_PHI    =25;
    mc_mn_DEFS->COORD_USER1  =26;
    mc_mn_DEFS->COORD_USER2  =27;
    mc_mn_DEFS->COORD_USER3  =28;
    mc_mn_DEFS->COORD_KXY    =29;
    mc_mn_DEFS->COORD_VXY    =30;

/* mc_mn_token modifiers */
    mc_mn_DEFS->COORD_VAR    =0;    /* next mc_mn_token should be a variable or normal option */
    mc_mn_DEFS->COORD_MIN    =1;    /* next mc_mn_token is a min value */
    mc_mn_DEFS->COORD_MAX    =2;    /* next mc_mn_token is a max value */
    mc_mn_DEFS->COORD_DIM    =3;    /* next mc_mn_token is a bin value */
    mc_mn_DEFS->COORD_FIL    =4;    /* next mc_mn_token is a filename */
    mc_mn_DEFS->COORD_EVNT   =5;    /* next mc_mn_token is a buffer size value */
    mc_mn_DEFS->COORD_3HE    =6;    /* next mc_mn_token is a 3He pressure value */
    mc_mn_DEFS->COORD_INTERM =7;    /* next mc_mn_token is an intermediate save value (%) */
    mc_mn_DEFS->COORD_LOG    =32;   /* next variable will be in log scale */
    mc_mn_DEFS->COORD_ABS    =64;   /* next variable will be in abs scale */
    mc_mn_DEFS->COORD_SIGNAL =128;  /* next variable will be the signal var */
    mc_mn_DEFS->COORD_AUTO   =256;  /* set auto limits */

    strcpy(mc_mn_DEFS->TOKEN_DEL, " =,;[](){}:");  /* mc_mn_token separators */

    mc_mn_DEFS->SHAPE_SQUARE =0;    /* shape of the monitor */
    mc_mn_DEFS->SHAPE_DISK   =1;
    mc_mn_DEFS->SHAPE_SPHERE =2;
    mc_mn_DEFS->SHAPE_CYLIND =3;
    mc_mn_DEFS->SHAPE_BANANA =4;
    mc_mn_DEFS->SHAPE_BOX    =5;
    mc_mn_DEFS->SHAPE_PREVIOUS=6;

    mc_mn_Vars->Sphere_Radius     = 0;
    mc_mn_Vars->Cylinder_Height   = 0;
    mc_mn_Vars->Flag_With_Borders = 0;   /* 2 means xy borders too */
    mc_mn_Vars->Flag_List         = 0;   /* 1=store 1 buffer, 2=list all, 3=re-use buffer */
    mc_mn_Vars->Flag_Multiple     = 0;   /* 1 when n1D, 0 for 2D */
    mc_mn_Vars->Flag_Verbose      = 0;
    mc_mn_Vars->Flag_Shape        = mc_mn_DEFS->SHAPE_SQUARE;
    mc_mn_Vars->Flag_Auto_Limits  = 0;   /* get limits from first Buffer */
    mc_mn_Vars->Flag_Absorb       = 0;   /* monitor is also a slit */
    mc_mn_Vars->Flag_Exclusive    = 0;   /* absorb neutrons out of monitor limits */
    mc_mn_Vars->Flag_per_cm2      = 0;   /* flux is per cm2 */
    mc_mn_Vars->Flag_per_st       = 0;   /* flux is per steradian (in Auto mode only) */
    mc_mn_Vars->Flag_log          = 0;   /* log10 of the flux */
    mc_mn_Vars->Flag_parallel     = 0;   /* set neutron state back after detection (parallel components) */
    mc_mn_Vars->Flag_Binary_List  = 0;   /* save list as a binary file (smaller) */
    mc_mn_Vars->Coord_Number      = 0;   /* total number of variables to monitor, plus intensity (0) */
    mc_mn_Vars->Buffer_Block      = 10000;     /* Buffer size for list or auto limits */
    mc_mn_Vars->Neutron_Counter   = 0;   /* event counter, simulation total counts is mcget_ncount() */
    mc_mn_Vars->Buffer_Counter    = 0;   /* mc_mn_index in Buffer size (for realloc) */
    mc_mn_Vars->Buffer_Size       = 0;
    mc_mn_Vars->UserVariable1     = 0;
    mc_mn_Vars->UserVariable2     = 0;
    mc_mn_Vars->He3_pressure      = 0;
    mc_mn_Vars->IntermediateCnts  = 0;
    mc_mn_Vars->Flag_capture      = 0;
    mc_mn_Vars->Flag_signal       = mc_mn_DEFS->COORD_P;
    mc_mn_Vars->mean_dx=mc_mn_Vars->mean_dy=0;
    mc_mn_Vars->min_x = mc_mn_Vars->max_x  =0;
    mc_mn_Vars->min_y = mc_mn_Vars->max_y  =0;
    mc_mn_Vars->steradian=0;

    mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_NONE;
    mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_VAR;

    /* handle size parameters */
    /* normal use is with xwidth, yheight, zdepth */
    /* if xmin,xmax,ymin,ymax,zmin,zmax are non 0, use them */
    if (fabs(mc_mn_xmin-mc_mn_xmax) == 0)
      { mc_mn_Vars->mxmin = -fabs(mc_mn_xwidth)/2; mc_mn_Vars->mxmax = fabs(mc_mn_xwidth)/2; }
    else
      { if (mc_mn_xmin < mc_mn_xmax) {mc_mn_Vars->mxmin = mc_mn_xmin; mc_mn_Vars->mxmax = mc_mn_xmax;}
        else {mc_mn_Vars->mxmin = mc_mn_xmax; mc_mn_Vars->mxmax = mc_mn_xmin;}
      }
    if (fabs(mc_mn_ymin-mc_mn_ymax) == 0)
      { mc_mn_Vars->mymin = -fabs(mc_mn_yheight)/2; mc_mn_Vars->mymax = fabs(mc_mn_yheight)/2; }
    else
      { if (mc_mn_ymin < mc_mn_ymax) {mc_mn_Vars->mymin = mc_mn_ymin; mc_mn_Vars->mymax = mc_mn_ymax;}
        else {mc_mn_Vars->mymin = mc_mn_ymax; mc_mn_Vars->mymax = mc_mn_ymin;}
      }
    if (fabs(mc_mn_zmin-mc_mn_zmax) == 0)
      { mc_mn_Vars->mzmin = -fabs(mc_mn_zdepth)/2; mc_mn_Vars->mzmax = fabs(mc_mn_zdepth)/2; }
    else
      { if (mc_mn_zmin < mc_mn_zmax) {mc_mn_Vars->mzmin = mc_mn_zmin; mc_mn_Vars->mzmax = mc_mn_zmax; }
        else {mc_mn_Vars->mzmin = mc_mn_zmax; mc_mn_Vars->mzmax = mc_mn_zmin; }
      }

    if (fabs(mc_mn_Vars->mzmax-mc_mn_Vars->mzmin) == 0)
      mc_mn_Vars->Flag_Shape        = mc_mn_DEFS->SHAPE_SQUARE;
    else
      mc_mn_Vars->Flag_Shape        = mc_mn_DEFS->SHAPE_BOX;

    /* parse option string */

    mc_mn_option_copy = (char*)malloc(strlen(mc_mn_Vars->option)+1);
    if (mc_mn_option_copy == NULL)
    {
      fprintf(stderr,"Monitor_nD: %s cannot allocate mc_mn_option_copy (%li). Fatal.\n", mc_mn_Vars->compcurname, strlen(mc_mn_Vars->option));
      exit(-1);
    }

    if (strlen(mc_mn_Vars->option))
    {
      mc_mn_Flag_End = 0;
      strcpy(mc_mn_option_copy, mc_mn_Vars->option);
    }

    if (strstr(mc_mn_Vars->option, "cm2") || strstr(mc_mn_Vars->option, "cm^2")) mc_mn_Vars->Flag_per_cm2 = 1;
    if (strstr(mc_mn_Vars->option, "steradian")) mc_mn_Vars->Flag_per_st = 1;

    if (strstr(mc_mn_Vars->option, "binary") || strstr(mc_mn_Vars->option, "float"))
      mc_mn_Vars->Flag_Binary_List  = 1;
    if (strstr(mc_mn_Vars->option, "double"))
      mc_mn_Vars->Flag_Binary_List  = 2;

    strcpy(mc_mn_Vars->Coord_Label[0],"Intensity");
    strncpy(mc_mn_Vars->Coord_Var[0],"p",30);
    mc_mn_Vars->Coord_Type[0] = mc_mn_DEFS->COORD_P;
    mc_mn_Vars->Coord_Bin[0] = 1;
    mc_mn_Vars->Coord_Min[0] = 0;
    mc_mn_Vars->Coord_Max[0] = FLT_MAX;

    /* default file name is comp name+dateID */
    sprintf(mc_mn_Vars->Mon_File, "%s_%li", mc_mn_Vars->compcurname, mc_mn_t);

    mc_mn_carg = 1;
    while((mc_mn_Flag_End == 0) && (mc_mn_carg < 128))
    {

      if (mc_mn_Flag_New_token) /* to get the previous mc_mn_token sometimes */
      {
        if (mc_mn_carg == 1) mc_mn_token=(char *)strtok(mc_mn_option_copy,mc_mn_DEFS->TOKEN_DEL);
        else mc_mn_token=(char *)strtok(NULL,mc_mn_DEFS->TOKEN_DEL);
        if (mc_mn_token == NULL) mc_mn_Flag_End=1;
      }
      mc_mn_Flag_New_token = 1;
      if ((mc_mn_token != NULL) && (strlen(mc_mn_token) != 0))
      {
        char mc_mn_iskeyword=0;
        int  mc_mn_old_Mode;
        /* first handle option values from preceeding keyword mc_mn_token detected */
        mc_mn_old_Mode = mc_mn_Set_Coord_Mode;
        if (mc_mn_Set_Coord_Mode == mc_mn_DEFS->COORD_MAX)
        {
          if (!mc_mn_Flag_All)
            mc_mn_Vars->Coord_Max[mc_mn_Vars->Coord_Number] = atof(mc_mn_token);
          else
            for (mc_mn_i = 0; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_Vars->Coord_Max[mc_mn_i++] = atof(mc_mn_token));
          mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_VAR; mc_mn_Flag_All = 0;
        }
        if (mc_mn_Set_Coord_Mode == mc_mn_DEFS->COORD_MIN)
        {
          if (!mc_mn_Flag_All)
            mc_mn_Vars->Coord_Min[mc_mn_Vars->Coord_Number] = atof(mc_mn_token);
          else
            for (mc_mn_i = 0; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_Vars->Coord_Min[mc_mn_i++] = atof(mc_mn_token));
          mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_MAX;
        }
        if (mc_mn_Set_Coord_Mode == mc_mn_DEFS->COORD_DIM)
        {
          if (!mc_mn_Flag_All)
            mc_mn_Vars->Coord_Bin[mc_mn_Vars->Coord_Number] = atoi(mc_mn_token);
          else
            for (mc_mn_i = 0; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_Vars->Coord_Bin[mc_mn_i++] = atoi(mc_mn_token));
          mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_VAR; mc_mn_Flag_All = 0;
        }
        if (mc_mn_Set_Coord_Mode == mc_mn_DEFS->COORD_FIL)
        {
          if (!mc_mn_Flag_No) strncpy(mc_mn_Vars->Mon_File,mc_mn_token,128);
          else { strcpy(mc_mn_Vars->Mon_File,""); mc_mn_Vars->Coord_Number = 0; mc_mn_Flag_End = 1;}
          mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_VAR;
        }
        if (mc_mn_Set_Coord_Mode == mc_mn_DEFS->COORD_EVNT)
        {
          if (!strcmp(mc_mn_token, "all") || mc_mn_Flag_All) mc_mn_Vars->Flag_List = 2;
          else { mc_mn_i = (long)ceil(atof(mc_mn_token)); if (mc_mn_i) mc_mn_Vars->Buffer_Block = mc_mn_i;
            mc_mn_Vars->Flag_List = 1; }
          mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_VAR; mc_mn_Flag_All = 0;
        }
        if (mc_mn_Set_Coord_Mode == mc_mn_DEFS->COORD_3HE)
        {
            mc_mn_Vars->He3_pressure = atof(mc_mn_token);
            mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_VAR; mc_mn_Flag_All = 0;
        }
        if (mc_mn_Set_Coord_Mode == mc_mn_DEFS->COORD_INTERM)
        {
            mc_mn_Vars->Intermediate = atof(mc_mn_token);
            mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_VAR; mc_mn_Flag_All = 0;
        }

        /* now look for general option keywords */
        if (!strcmp(mc_mn_token, "borders"))  {mc_mn_Vars->Flag_With_Borders = 1; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "verbose"))  {mc_mn_Vars->Flag_Verbose      = 1; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "log"))      {mc_mn_Vars->Flag_log          = 1; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "abs"))      {mc_mn_Flag_abs                = 1; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "multiple")) {mc_mn_Vars->Flag_Multiple     = 1; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "exclusive")){mc_mn_Vars->Flag_Exclusive    = 1; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "list")) {
          mc_mn_Vars->Flag_List = 1; mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_EVNT;  }
        if (!strcmp(mc_mn_token, "limits") || !strcmp(mc_mn_token, "min"))
          mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_MIN;
        if (!strcmp(mc_mn_token, "slit") || !strcmp(mc_mn_token, "absorb")) {
          mc_mn_Vars->Flag_Absorb = 1;  mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "max"))  mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_MAX;
        if (!strcmp(mc_mn_token, "bins")) mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_DIM;
        if (!strcmp(mc_mn_token, "file")) {
          mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_FIL;
          if (mc_mn_Flag_No) { strcpy(mc_mn_Vars->Mon_File,""); mc_mn_Vars->Coord_Number = 0; mc_mn_Flag_End = 1; }
        }
        if (!strcmp(mc_mn_token, "unactivate")) {
          mc_mn_Flag_End = 1; mc_mn_Vars->Coord_Number = 0; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "all"))    { mc_mn_Flag_All = 1;  mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "sphere")) { mc_mn_Vars->Flag_Shape = mc_mn_DEFS->SHAPE_SPHERE; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "cylinder")) { mc_mn_Vars->Flag_Shape = mc_mn_DEFS->SHAPE_CYLIND; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "banana")) { mc_mn_Vars->Flag_Shape = mc_mn_DEFS->SHAPE_BANANA; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "square")) { mc_mn_Vars->Flag_Shape = mc_mn_DEFS->SHAPE_SQUARE; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "disk"))   { mc_mn_Vars->Flag_Shape = mc_mn_DEFS->SHAPE_DISK; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "box"))     { mc_mn_Vars->Flag_Shape = mc_mn_DEFS->SHAPE_BOX; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "previous")) { mc_mn_Vars->Flag_Shape = mc_mn_DEFS->SHAPE_PREVIOUS; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "parallel")){ mc_mn_Vars->Flag_parallel = 1; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "capture")) { mc_mn_Vars->Flag_capture = 1; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "auto") && (mc_mn_Flag_auto != -1)) {
          mc_mn_Vars->Flag_Auto_Limits = 1;
          if (mc_mn_Flag_All) mc_mn_Flag_auto = -1;
          else mc_mn_Flag_auto = 1;
          mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "premonitor")) {
          mc_mn_Vars->Flag_UsePreMonitor = 1; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "3He_pressure")) {
          mc_mn_Vars->He3_pressure = 3; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "intermediate")) {
          mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_INTERM;
          mc_mn_Vars->Intermediate = 5; mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "no") || !strcmp(mc_mn_token, "not")) { mc_mn_Flag_No = 1;  mc_mn_iskeyword=1; }
        if (!strcmp(mc_mn_token, "signal")) mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_SIGNAL;

        /* Mode has changed: this was a keyword or value */
        if (mc_mn_Set_Coord_Mode != mc_mn_old_Mode) mc_mn_iskeyword=1;

        /* now look for variable names to monitor */
        mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_NONE; mc_mn_lmin = 0; mc_mn_lmax = 0;

        if (!strcmp(mc_mn_token, "x"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_X; strcpy(mc_mn_Set_Vars_Coord_Label,"x [m]"); strcpy(mc_mn_Set_Vars_Coord_Var,"x");
          mc_mn_lmin = mc_mn_Vars->mxmin; mc_mn_lmax = mc_mn_Vars->mxmax;
          mc_mn_Vars->Coord_Min[mc_mn_Vars->Coord_Number+1] = mc_mn_Vars->mxmin;
          mc_mn_Vars->Coord_Max[mc_mn_Vars->Coord_Number+1] = mc_mn_Vars->mxmax;}
        if (!strcmp(mc_mn_token, "y"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_Y; strcpy(mc_mn_Set_Vars_Coord_Label,"y [m]"); strcpy(mc_mn_Set_Vars_Coord_Var,"y");
          mc_mn_lmin = mc_mn_Vars->mymin; mc_mn_lmax = mc_mn_Vars->mymax;
          mc_mn_Vars->Coord_Min[mc_mn_Vars->Coord_Number+1] = mc_mn_Vars->mymin;
          mc_mn_Vars->Coord_Max[mc_mn_Vars->Coord_Number+1] = mc_mn_Vars->mymax;}
        if (!strcmp(mc_mn_token, "z"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_Z; strcpy(mc_mn_Set_Vars_Coord_Label,"z [m]"); strcpy(mc_mn_Set_Vars_Coord_Var,"z"); mc_mn_lmin = mc_mn_Vars->mzmin; mc_mn_lmax = mc_mn_Vars->mzmax; }
        if (!strcmp(mc_mn_token, "k") || !strcmp(mc_mn_token, "wavevector"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_K; strcpy(mc_mn_Set_Vars_Coord_Label,"|k| [Angs-1]"); strcpy(mc_mn_Set_Vars_Coord_Var,"k"); mc_mn_lmin = 0; mc_mn_lmax = 10; }
        if (!strcmp(mc_mn_token, "v"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_V; strcpy(mc_mn_Set_Vars_Coord_Label,"Velocity [m/s]"); strcpy(mc_mn_Set_Vars_Coord_Var,"v"); mc_mn_lmin = 0; mc_mn_lmax = 10000; }
        if (!strcmp(mc_mn_token, "t") || !strcmp(mc_mn_token, "time"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_T; strcpy(mc_mn_Set_Vars_Coord_Label,"TOF [s]"); strcpy(mc_mn_Set_Vars_Coord_Var,"t"); mc_mn_lmin = 0; mc_mn_lmax = .1; }
        if ((!strcmp(mc_mn_token, "p") || !strcmp(mc_mn_token, "intensity") || !strcmp(mc_mn_token, "flux")))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_P;
            strcpy(mc_mn_Set_Vars_Coord_Label,"Intensity");
            strncat(mc_mn_Set_Vars_Coord_Label, " [n/s", 30);
            if (mc_mn_Vars->Flag_per_cm2) strncat(mc_mn_Set_Vars_Coord_Label, "/cm2", 30);
            if (mc_mn_Vars->Flag_per_st) {
              if (mc_mn_Vars->Flag_Auto_Limits)
                strncat(mc_mn_Set_Vars_Coord_Label, "/st", 30);
            }
            if (mc_mn_XY > 1 && mc_mn_Vars->Coord_Number)
              strncat(mc_mn_Set_Vars_Coord_Label, "/bin", 30);
            strncat(mc_mn_Set_Vars_Coord_Label, "]", 30);
            strcpy(mc_mn_Set_Vars_Coord_Var,"I");
            mc_mn_lmin = 0; mc_mn_lmax = FLT_MAX;
          }

        if (!strcmp(mc_mn_token, "vx"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_VX; strcpy(mc_mn_Set_Vars_Coord_Label,"vx [m/s]"); strcpy(mc_mn_Set_Vars_Coord_Var,"vx"); mc_mn_lmin = -1000; mc_mn_lmax = 1000; }
        if (!strcmp(mc_mn_token, "vy"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_VY; strcpy(mc_mn_Set_Vars_Coord_Label,"vy [m/s]"); strcpy(mc_mn_Set_Vars_Coord_Var,"vy"); mc_mn_lmin = -1000; mc_mn_lmax = 1000; }
        if (!strcmp(mc_mn_token, "vz"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_VZ; strcpy(mc_mn_Set_Vars_Coord_Label,"vz [m/s]"); strcpy(mc_mn_Set_Vars_Coord_Var,"vz"); mc_mn_lmin = -10000; mc_mn_lmax = 10000; }
        if (!strcmp(mc_mn_token, "kx"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_KX; strcpy(mc_mn_Set_Vars_Coord_Label,"kx [Angs-1]"); strcpy(mc_mn_Set_Vars_Coord_Var,"kx"); mc_mn_lmin = -1; mc_mn_lmax = 1; }
        if (!strcmp(mc_mn_token, "ky"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_KY; strcpy(mc_mn_Set_Vars_Coord_Label,"ky [Angs-1]"); strcpy(mc_mn_Set_Vars_Coord_Var,"ky"); mc_mn_lmin = -1; mc_mn_lmax = 1; }
        if (!strcmp(mc_mn_token, "kz"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_KZ; strcpy(mc_mn_Set_Vars_Coord_Label,"kz [Angs-1]"); strcpy(mc_mn_Set_Vars_Coord_Var,"kz"); mc_mn_lmin = -10; mc_mn_lmax = 10; }
        if (!strcmp(mc_mn_token, "sx"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_SX; strcpy(mc_mn_Set_Vars_Coord_Label,"sx [1]"); strcpy(mc_mn_Set_Vars_Coord_Var,"sx"); mc_mn_lmin = -1; mc_mn_lmax = 1; }
        if (!strcmp(mc_mn_token, "sy"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_SY; strcpy(mc_mn_Set_Vars_Coord_Label,"sy [1]"); strcpy(mc_mn_Set_Vars_Coord_Var,"sy"); mc_mn_lmin = -1; mc_mn_lmax = 1; }
        if (!strcmp(mc_mn_token, "sz"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_SZ; strcpy(mc_mn_Set_Vars_Coord_Label,"sz [1]"); strcpy(mc_mn_Set_Vars_Coord_Var,"sz"); mc_mn_lmin = -1; mc_mn_lmax = 1; }

        if (!strcmp(mc_mn_token, "energy") || !strcmp(mc_mn_token, "omega"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_ENERGY; strcpy(mc_mn_Set_Vars_Coord_Label,"Energy [meV]"); strcpy(mc_mn_Set_Vars_Coord_Var,"E"); mc_mn_lmin = 0; mc_mn_lmax = 100; }
        if (!strcmp(mc_mn_token, "lambda") || !strcmp(mc_mn_token, "wavelength"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_LAMBDA; strcpy(mc_mn_Set_Vars_Coord_Label,"Wavelength [Angs]"); strcpy(mc_mn_Set_Vars_Coord_Var,"L"); mc_mn_lmin = 0; mc_mn_lmax = 100; }
        if (!strcmp(mc_mn_token, "radius") || !strcmp(mc_mn_token, "xy"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_RADIUS; strcpy(mc_mn_Set_Vars_Coord_Label,"Radius [m]"); strcpy(mc_mn_Set_Vars_Coord_Var,"R"); mc_mn_lmin = 0; mc_mn_lmax = mc_mn_xmax; }
        if (!strcmp(mc_mn_token, "vxy"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_VXY; strcpy(mc_mn_Set_Vars_Coord_Label,"Radial Velocity [m]"); strcpy(mc_mn_Set_Vars_Coord_Var,"Vxy"); mc_mn_lmin = 0; mc_mn_lmax = 2000; }
        if (!strcmp(mc_mn_token, "kxy"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_KXY; strcpy(mc_mn_Set_Vars_Coord_Label,"Radial Wavevector [Angs-1]"); strcpy(mc_mn_Set_Vars_Coord_Var,"Kxy"); mc_mn_lmin = 0; mc_mn_lmax = 2; }
        if (!strcmp(mc_mn_token, "angle"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_ANGLE; strcpy(mc_mn_Set_Vars_Coord_Label,"Angle [deg]"); strcpy(mc_mn_Set_Vars_Coord_Var,"A"); mc_mn_lmin = -5; mc_mn_lmax = 5; }
        if (!strcmp(mc_mn_token, "hdiv")|| !strcmp(mc_mn_token, "divergence") || !strcmp(mc_mn_token, "xdiv") || !strcmp(mc_mn_token, "dx"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_HDIV; strcpy(mc_mn_Set_Vars_Coord_Label,"Hor. Divergence [deg]"); strcpy(mc_mn_Set_Vars_Coord_Var,"HD"); mc_mn_lmin = -5; mc_mn_lmax = 5; }
        if (!strcmp(mc_mn_token, "vdiv") || !strcmp(mc_mn_token, "ydiv") || !strcmp(mc_mn_token, "dy"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_VDIV; strcpy(mc_mn_Set_Vars_Coord_Label,"Vert. Divergence [deg]"); strcpy(mc_mn_Set_Vars_Coord_Var,"VD"); mc_mn_lmin = -5; mc_mn_lmax = 5; }
        if (!strcmp(mc_mn_token, "theta") || !strcmp(mc_mn_token, "longitude"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_THETA; strcpy(mc_mn_Set_Vars_Coord_Label,"Longitude [deg]"); strcpy(mc_mn_Set_Vars_Coord_Var,"th"); mc_mn_lmin = -180; mc_mn_lmax = 180; }
        if (!strcmp(mc_mn_token, "phi") || !strcmp(mc_mn_token, "lattitude"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_PHI; strcpy(mc_mn_Set_Vars_Coord_Label,"Lattitude [deg]"); strcpy(mc_mn_Set_Vars_Coord_Var,"ph"); mc_mn_lmin = -180; mc_mn_lmax = 180; }
        if (!strcmp(mc_mn_token, "ncounts"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_NCOUNT; strcpy(mc_mn_Set_Vars_Coord_Label,"Neutrons [1]"); strcpy(mc_mn_Set_Vars_Coord_Var,"N"); mc_mn_lmin = 0; mc_mn_lmax = 1e10; }
        if (!strcmp(mc_mn_token, "user") || !strcmp(mc_mn_token, "user1"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_USER1; strncpy(mc_mn_Set_Vars_Coord_Label,mc_mn_Vars->UserName1,30); strcpy(mc_mn_Set_Vars_Coord_Var,"U1"); mc_mn_lmin = -1e10; mc_mn_lmax = 1e10; }
        if (!strcmp(mc_mn_token, "user2"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_USER2; strncpy(mc_mn_Set_Vars_Coord_Label,mc_mn_Vars->UserName2,30); strcpy(mc_mn_Set_Vars_Coord_Var,"U2"); mc_mn_lmin = -1e10; mc_mn_lmax = 1e10; }
        if (!strcmp(mc_mn_token, "user3"))
          { mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_USER3; strncpy(mc_mn_Set_Vars_Coord_Label,mc_mn_Vars->UserName3,30); strcpy(mc_mn_Set_Vars_Coord_Var,"U3"); mc_mn_lmin = -1e10; mc_mn_lmax = 1e10; }

        /* now stores variable keywords detected, if any */
        if (mc_mn_Set_Vars_Coord_Type != mc_mn_DEFS->COORD_NONE)
        {
          int mc_mn_Coord_Number = mc_mn_Vars->Coord_Number;
          if (mc_mn_Vars->Flag_log) { mc_mn_Set_Vars_Coord_Type |= mc_mn_DEFS->COORD_LOG; mc_mn_Vars->Flag_log = 0; }
          if (mc_mn_Flag_abs) { mc_mn_Set_Vars_Coord_Type |= mc_mn_DEFS->COORD_ABS; mc_mn_Flag_abs = 0; }
          if (mc_mn_Flag_auto != 0) { mc_mn_Set_Vars_Coord_Type |= mc_mn_DEFS->COORD_AUTO; mc_mn_Flag_auto = 0; }
          if (mc_mn_Set_Coord_Mode == mc_mn_DEFS->COORD_SIGNAL)
          {
            mc_mn_Coord_Number = 0;
            mc_mn_Vars->Flag_signal = mc_mn_Set_Vars_Coord_Type;
          }
          else
          {
            if (mc_mn_Coord_Number < MONnD_COORD_NMAX)
            { mc_mn_Coord_Number++;
              mc_mn_Vars->Coord_Number = mc_mn_Coord_Number; }
            else if (mc_mn_Vars->Flag_Verbose) printf("Monitor_nD: %s reached max number of variables (%i).\n", mc_mn_Vars->compcurname, MONnD_COORD_NMAX);
          }
          mc_mn_Vars->Coord_Type[mc_mn_Coord_Number] = mc_mn_Set_Vars_Coord_Type;
          strncpy(mc_mn_Vars->Coord_Label[mc_mn_Coord_Number], mc_mn_Set_Vars_Coord_Label,30);
          strncpy(mc_mn_Vars->Coord_Var[mc_mn_Coord_Number], mc_mn_Set_Vars_Coord_Var,30);
          if (mc_mn_lmin > mc_mn_lmax) { mc_mn_XY = mc_mn_lmin; mc_mn_lmin=mc_mn_lmax; mc_mn_lmax = mc_mn_XY; }
          mc_mn_Vars->Coord_Min[mc_mn_Coord_Number] = mc_mn_lmin;
          mc_mn_Vars->Coord_Max[mc_mn_Coord_Number] = mc_mn_lmax;
          if (mc_mn_Set_Coord_Mode != mc_mn_DEFS->COORD_SIGNAL) mc_mn_Vars->Coord_Bin[mc_mn_Coord_Number] = 20;
          mc_mn_Set_Coord_Mode = mc_mn_DEFS->COORD_VAR;
          mc_mn_Flag_All = 0;
          mc_mn_Flag_No  = 0;
        } else {
          /* no variable name could be read from options */
          if (!mc_mn_iskeyword) {
            if (strcmp(mc_mn_token, "cm2") && strcmp(mc_mn_token, "incoming")
             && strcmp(mc_mn_token, "outgoing") && strcmp(mc_mn_token, "cm2")
             && strcmp(mc_mn_token, "cm^2") && strcmp(mc_mn_token, "float")
             && strcmp(mc_mn_token, "double") && strcmp(mc_mn_token, "binary")
             && strcmp(mc_mn_token, "steradian") && mc_mn_Vars->Flag_Verbose)
              printf("Monitor_nD: %s: unknown '%s' keyword in 'options'. Ignoring.\n", mc_mn_Vars->compcurname, mc_mn_token);
          }
        }
      mc_mn_carg++;
      } /* end if mc_mn_token */
    } /* end while mc_mn_carg */
    free(mc_mn_option_copy);
    if (mc_mn_carg == 128) printf("Monitor_nD: %s reached max number of mc_mn_tokens (%i). Skipping.\n", mc_mn_Vars->compcurname, 128);

    if ((mc_mn_Vars->Flag_Shape == mc_mn_DEFS->SHAPE_BOX) && (fabs(mc_mn_Vars->mzmax - mc_mn_Vars->mzmin) == 0)) mc_mn_Vars->Flag_Shape = mc_mn_DEFS->SHAPE_SQUARE;

    if (mc_mn_Vars->Flag_log == 1) mc_mn_Vars->Coord_Type[0] |= mc_mn_DEFS->COORD_LOG;
    if (mc_mn_Vars->Coord_Number == 0)
    { mc_mn_Vars->Flag_Auto_Limits=0; mc_mn_Vars->Flag_Multiple=0; mc_mn_Vars->Flag_List=0; }

    /* now setting Monitor Name from variable mc_mn_labels */
    strcpy(mc_mn_Vars->Monitor_Label,"");
    mc_mn_XY = 1; /* will contain total bin number */
    for (mc_mn_i = 0; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_i++)
    {
      if (mc_mn_Flag_auto != 0) mc_mn_Vars->Coord_Type[mc_mn_i] |= mc_mn_DEFS->COORD_AUTO;
      mc_mn_Set_Vars_Coord_Type = (mc_mn_Vars->Coord_Type[mc_mn_i] & 31);
      if ((mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_THETA)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_PHI)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_X)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_Y)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_Z)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_RADIUS))
       strcpy(mc_mn_Short_Label[mc_mn_i],"Position");
      else
      if ((mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_VX)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_VY)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_VZ)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_V)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_VXY))
       strcpy(mc_mn_Short_Label[mc_mn_i],"Velocity");
      else
      if ((mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_KX)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_KY)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_KZ)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_KXY)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_K))
       strcpy(mc_mn_Short_Label[mc_mn_i],"Wavevector");
      else
      if ((mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_SX)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_SY)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_SZ))
       strcpy(mc_mn_Short_Label[mc_mn_i],"Spin");
      else
      if ((mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_HDIV)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_VDIV)
       || (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_ANGLE))
       strcpy(mc_mn_Short_Label[mc_mn_i],"Divergence");
      else
      if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_ENERGY)
       strcpy(mc_mn_Short_Label[mc_mn_i],"Energy");
      else
      if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_LAMBDA)
       strcpy(mc_mn_Short_Label[mc_mn_i],"Wavelength");
      else
      if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_NCOUNT)
       strcpy(mc_mn_Short_Label[mc_mn_i],"Neutron counts");
      else
      if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_T)
          strcpy(mc_mn_Short_Label[mc_mn_i],"Time Of Flight");
      else
      if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_P)
          strcpy(mc_mn_Short_Label[mc_mn_i],"Intensity");
      else
      if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_USER1)
          strncpy(mc_mn_Short_Label[mc_mn_i],mc_mn_Vars->UserName1,30);
      else
      if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_USER2)
          strncpy(mc_mn_Short_Label[mc_mn_i],mc_mn_Vars->UserName2,30);
      else
      if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_USER3)
          strncpy(mc_mn_Short_Label[mc_mn_i],mc_mn_Vars->UserName3,30);
      else
          strcpy(mc_mn_Short_Label[mc_mn_i],"Unknown");

      if (mc_mn_Vars->Coord_Type[mc_mn_i] & mc_mn_DEFS->COORD_ABS)
      { strcat(mc_mn_Vars->Coord_Label[mc_mn_i]," (abs)"); }

      if (mc_mn_Vars->Coord_Type[mc_mn_i] & mc_mn_DEFS->COORD_LOG)
      { strcat(mc_mn_Vars->Coord_Label[mc_mn_i]," (log)"); }

      strcat(mc_mn_Vars->Monitor_Label, " ");
      strcat(mc_mn_Vars->Monitor_Label, mc_mn_Short_Label[mc_mn_i]);
      mc_mn_XY *= mc_mn_Vars->Coord_Bin[mc_mn_i];
    } /* end for mc_mn_Short_Label */

    if ((mc_mn_Vars->Coord_Type[0] & 31) == mc_mn_DEFS->COORD_P) {
      strncat(mc_mn_Vars->Coord_Label[0], " [n/s", 30);
      if (mc_mn_Vars->Flag_per_cm2) strncat(mc_mn_Vars->Coord_Label[0], "/cm2", 30);
      if (mc_mn_Vars->Flag_per_st) {
        if (mc_mn_Vars->Flag_Auto_Limits)
          strncat(mc_mn_Vars->Coord_Label[0], "/st", 30);
        else
          printf("Monitor_nD: %s: Flux per steradian requires Auto limits mode\n"
                 "WARNING     use options='.. auto ...'\n", mc_mn_Vars->compcurname);
      }
      if (mc_mn_XY > 1 && mc_mn_Vars->Coord_Number)
        strncat(mc_mn_Vars->Coord_Label[0], "/bin", 30);
      strncat(mc_mn_Vars->Coord_Label[0], "]", 30);
    }

    /* update label 'signal per bin' if more than 1 bin */
    if (mc_mn_XY > 1 && mc_mn_Vars->Coord_Number) {
      if (mc_mn_Vars->Flag_capture)
        printf("Monitor_nD: %s: Using capture flux weightening on %ld bins.\n"
               "            Use binned data with caution, and prefer monitor integral value (I,Ierr).\n", mc_mn_Vars->compcurname, (long)mc_mn_XY);
    }

    strcat(mc_mn_Vars->Monitor_Label, " Monitor");
    if (mc_mn_Vars->Flag_Shape == mc_mn_DEFS->SHAPE_SQUARE) strcat(mc_mn_Vars->Monitor_Label, " (Square)");
    if (mc_mn_Vars->Flag_Shape == mc_mn_DEFS->SHAPE_DISK)   strcat(mc_mn_Vars->Monitor_Label, " (Disk)");
    if (mc_mn_Vars->Flag_Shape == mc_mn_DEFS->SHAPE_SPHERE) strcat(mc_mn_Vars->Monitor_Label, " (Sphere)");
    if (mc_mn_Vars->Flag_Shape == mc_mn_DEFS->SHAPE_CYLIND) strcat(mc_mn_Vars->Monitor_Label, " (Cylinder)");
    if (mc_mn_Vars->Flag_Shape == mc_mn_DEFS->SHAPE_BANANA) strcat(mc_mn_Vars->Monitor_Label, " (Banana)");
    if (mc_mn_Vars->Flag_Shape == mc_mn_DEFS->SHAPE_BOX)    strcat(mc_mn_Vars->Monitor_Label, " (Box)");
    if (mc_mn_Vars->Flag_Shape == mc_mn_DEFS->SHAPE_PREVIOUS) strcat(mc_mn_Vars->Monitor_Label, " (on PREVIOUS)");
    if ((mc_mn_Vars->Flag_Shape == mc_mn_DEFS->SHAPE_CYLIND) || (mc_mn_Vars->Flag_Shape == mc_mn_DEFS->SHAPE_BANANA) || (mc_mn_Vars->Flag_Shape == mc_mn_DEFS->SHAPE_SPHERE) || (mc_mn_Vars->Flag_Shape == mc_mn_DEFS->SHAPE_BOX))
    {
      if (strstr(mc_mn_Vars->option, "incoming"))
      {
        mc_mn_Vars->Flag_Shape = abs(mc_mn_Vars->Flag_Shape);
        strcat(mc_mn_Vars->Monitor_Label, " [in]");
      }
      else /* if strstr(mc_mn_Vars->option, "outgoing")) */
      {
        mc_mn_Vars->Flag_Shape = -abs(mc_mn_Vars->Flag_Shape);
        strcat(mc_mn_Vars->Monitor_Label, " [out]");
      }
    }
    if (mc_mn_Vars->Flag_UsePreMonitor == 1)
    {
        strcat(mc_mn_Vars->Monitor_Label, " at ");
        strncat(mc_mn_Vars->Monitor_Label, mc_mn_Vars->UserName1,30);
    }
    if (mc_mn_Vars->Flag_log == 1) strcat(mc_mn_Vars->Monitor_Label, " [log] ");

    /* mc_mn_Vars->Coord_Number  0   : intensity or signal
     * mc_mn_Vars->Coord_Number  1:n : detector variables */

    /* now allocate memory to store variables in TRACE */
    if ((mc_mn_Vars->Coord_Number != 2) && !mc_mn_Vars->Flag_Multiple && !mc_mn_Vars->Flag_List)
    { mc_mn_Vars->Flag_Multiple = 1; mc_mn_Vars->Flag_List = 0; } /* default is n1D */

   /* list and auto limits case : mc_mn_Vars->Flag_List or mc_mn_Vars->Flag_Auto_Limits
    * -> Buffer to flush and suppress after mc_mn_Vars->Flag_Auto_Limits
    */
    if ((mc_mn_Vars->Flag_Auto_Limits || mc_mn_Vars->Flag_List) && mc_mn_Vars->Coord_Number)
    { /* Dim : (mc_mn_Vars->Coord_Number+1)*mc_mn_Vars->Buffer_Block matrix (for p, dp) */
      mc_mn_Vars->Mon2D_Buffer = (double *)malloc((mc_mn_Vars->Coord_Number+1)*mc_mn_Vars->Buffer_Block*sizeof(double));
      if (mc_mn_Vars->Mon2D_Buffer == NULL)
      { printf("Monitor_nD: %s cannot allocate mc_mn_Vars->Mon2D_Buffer (%li). No list and auto limits.\n", mc_mn_Vars->compcurname, mc_mn_Vars->Buffer_Block*(mc_mn_Vars->Coord_Number+1)*sizeof(double)); mc_mn_Vars->Flag_List = 0; mc_mn_Vars->Flag_Auto_Limits = 0; }
      else
      {
        for (mc_mn_i=0; mc_mn_i < (mc_mn_Vars->Coord_Number+1)*mc_mn_Vars->Buffer_Block; mc_mn_Vars->Mon2D_Buffer[mc_mn_i++] = (double)0);
      }
      mc_mn_Vars->Buffer_Size = mc_mn_Vars->Buffer_Block;
    }

    /* 1D and n1D case : mc_mn_Vars->Flag_Multiple */
    if (mc_mn_Vars->Flag_Multiple && mc_mn_Vars->Coord_Number)
    { /* Dim : mc_mn_Vars->Coord_Number*mc_mn_Vars->Coord_Bin[mc_mn_i] vectors */
      mc_mn_Vars->Mon2D_N  = (double **)malloc((mc_mn_Vars->Coord_Number)*sizeof(double *));
      mc_mn_Vars->Mon2D_p  = (double **)malloc((mc_mn_Vars->Coord_Number)*sizeof(double *));
      mc_mn_Vars->Mon2D_p2 = (double **)malloc((mc_mn_Vars->Coord_Number)*sizeof(double *));
      if ((mc_mn_Vars->Mon2D_N == NULL) || (mc_mn_Vars->Mon2D_p == NULL) || (mc_mn_Vars->Mon2D_p2 == NULL))
      { fprintf(stderr,"Monitor_nD: %s n1D cannot allocate mc_mn_Vars->Mon2D_N/p/2p (%li). Fatal.\n", mc_mn_Vars->compcurname, (mc_mn_Vars->Coord_Number)*sizeof(double *)); exit(-1); }
      for (mc_mn_i= 1; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_i++)
      {
        mc_mn_Vars->Mon2D_N[mc_mn_i-1]  = (double *)malloc(mc_mn_Vars->Coord_Bin[mc_mn_i]*sizeof(double));
        mc_mn_Vars->Mon2D_p[mc_mn_i-1]  = (double *)malloc(mc_mn_Vars->Coord_Bin[mc_mn_i]*sizeof(double));
        mc_mn_Vars->Mon2D_p2[mc_mn_i-1] = (double *)malloc(mc_mn_Vars->Coord_Bin[mc_mn_i]*sizeof(double));
        if ((mc_mn_Vars->Mon2D_N == NULL) || (mc_mn_Vars->Mon2D_p == NULL) || (mc_mn_Vars->Mon2D_p2 == NULL))
        { fprintf(stderr,"Monitor_nD: %s n1D cannot allocate %s mc_mn_Vars->Mon2D_N/p/2p[%li] (%li). Fatal.\n", mc_mn_Vars->compcurname, mc_mn_Vars->Coord_Var[mc_mn_i], mc_mn_i, (mc_mn_Vars->Coord_Bin[mc_mn_i])*sizeof(double *)); exit(-1); }
        else
        {
          for (mc_mn_j=0; mc_mn_j < mc_mn_Vars->Coord_Bin[mc_mn_i]; mc_mn_j++ )
          { mc_mn_Vars->Mon2D_N[mc_mn_i-1][mc_mn_j] = (double)0; mc_mn_Vars->Mon2D_p[mc_mn_i-1][mc_mn_j] = (double)0; mc_mn_Vars->Mon2D_p2[mc_mn_i-1][mc_mn_j] = (double)0; }
        }
      }
    }
    else /* 2D case : mc_mn_Vars->Coord_Number==2 and !mc_mn_Vars->Flag_Multiple and !mc_mn_Vars->Flag_List */
    if ((mc_mn_Vars->Coord_Number == 2) && !mc_mn_Vars->Flag_Multiple)
    { /* Dim : mc_mn_Vars->Coord_Bin[1]*mc_mn_Vars->Coord_Bin[2] matrix */
      mc_mn_Vars->Mon2D_N  = (double **)malloc((mc_mn_Vars->Coord_Bin[1])*sizeof(double *));
      mc_mn_Vars->Mon2D_p  = (double **)malloc((mc_mn_Vars->Coord_Bin[1])*sizeof(double *));
      mc_mn_Vars->Mon2D_p2 = (double **)malloc((mc_mn_Vars->Coord_Bin[1])*sizeof(double *));
      if ((mc_mn_Vars->Mon2D_N == NULL) || (mc_mn_Vars->Mon2D_p == NULL) || (mc_mn_Vars->Mon2D_p2 == NULL))
      { fprintf(stderr,"Monitor_nD: %s 2D cannot allocate %s mc_mn_Vars->Mon2D_N/p/2p (%li). Fatal.\n", mc_mn_Vars->compcurname, mc_mn_Vars->Coord_Var[1], (mc_mn_Vars->Coord_Bin[1])*sizeof(double *)); exit(-1); }
      for (mc_mn_i= 0; mc_mn_i < mc_mn_Vars->Coord_Bin[1]; mc_mn_i++)
      {
        mc_mn_Vars->Mon2D_N[mc_mn_i]  = (double *)malloc(mc_mn_Vars->Coord_Bin[2]*sizeof(double));
        mc_mn_Vars->Mon2D_p[mc_mn_i]  = (double *)malloc(mc_mn_Vars->Coord_Bin[2]*sizeof(double));
        mc_mn_Vars->Mon2D_p2[mc_mn_i] = (double *)malloc(mc_mn_Vars->Coord_Bin[2]*sizeof(double));
        if ((mc_mn_Vars->Mon2D_N == NULL) || (mc_mn_Vars->Mon2D_p == NULL) || (mc_mn_Vars->Mon2D_p2 == NULL))
        { fprintf(stderr,"Monitor_nD: %s 2D cannot allocate %s mc_mn_Vars->Mon2D_N/p/2p[%li] (%li). Fatal.\n", mc_mn_Vars->compcurname, mc_mn_Vars->Coord_Var[1], mc_mn_i, (mc_mn_Vars->Coord_Bin[2])*sizeof(double *)); exit(-1); }
        else
        {
          for (mc_mn_j=0; mc_mn_j < mc_mn_Vars->Coord_Bin[2]; mc_mn_j++ )
          { mc_mn_Vars->Mon2D_N[mc_mn_i][mc_mn_j] = (double)0; mc_mn_Vars->Mon2D_p[mc_mn_i][mc_mn_j] = (double)0; mc_mn_Vars->Mon2D_p2[mc_mn_i][mc_mn_j] = (double)0; }
        }
      }
    }
      /* no Mon2D allocated for
       * (mc_mn_Vars->Coord_Number != 2) && !mc_mn_Vars->Flag_Multiple && mc_mn_Vars->Flag_List */

    mc_mn_Vars->psum  = 0;
    mc_mn_Vars->p2sum = 0;
    mc_mn_Vars->Nsum  = 0;

    mc_mn_Vars->area  = fabs(mc_mn_Vars->mxmax - mc_mn_Vars->mxmin)*fabs(mc_mn_Vars->mymax - mc_mn_Vars->mymin)*1E4; /* in cm**2 for square and box shapes */
    mc_mn_Vars->Sphere_Radius = fabs(mc_mn_Vars->mxmax - mc_mn_Vars->mxmin)/2;
    if ((abs(mc_mn_Vars->Flag_Shape) == mc_mn_DEFS->SHAPE_DISK) || (abs(mc_mn_Vars->Flag_Shape) == mc_mn_DEFS->SHAPE_SPHERE))
    {
      mc_mn_Vars->area = PI*mc_mn_Vars->Sphere_Radius*mc_mn_Vars->Sphere_Radius; /* disk shapes */
    }
    if (mc_mn_Vars->area == 0) mc_mn_Vars->Coord_Number = 0;
    if (mc_mn_Vars->Coord_Number == 0 && mc_mn_Vars->Flag_Verbose)
      printf("Monitor_nD: %s is unactivated (0D)\n", mc_mn_Vars->compcurname);
    mc_mn_Vars->Cylinder_Height = fabs(mc_mn_Vars->mymax - mc_mn_Vars->mymin);

    if (mc_mn_Vars->Intermediate < 0) mc_mn_Vars->Intermediate = 0;
    if (mc_mn_Vars->Intermediate > 1) mc_mn_Vars->Intermediate /= 100;
    mc_mn_Vars->IntermediateCnts = mc_mn_Vars->Intermediate*mcget_ncount();

    if (mc_mn_Vars->Flag_Verbose)
    {
      printf("Monitor_nD: %s is a %s.\n", mc_mn_Vars->compcurname, mc_mn_Vars->Monitor_Label);
      printf("Monitor_nD: version %s with options=%s\n", MONITOR_ND_LIB_H, mc_mn_Vars->option);
    }
  } /* end Monitor_nD_Init */

/* ========================================================================= */
/* ADD: E.Farhi, Aug 6th, 2001: Monitor_nD section */
/* this routine is used to monitor one propagating neutron */
/* ========================================================================= */

double Monitor_nD_Trace(MonitornD_Defines_type *mc_mn_DEFS, MonitornD_Variables_type *mc_mn_Vars)
{

  double  mc_mn_XY=0;
  long    mc_mn_i,mc_mn_j;
  double  mc_mn_pp;
  double  mc_mn_Coord[MONnD_COORD_NMAX];
  long    mc_mn_Coord_Index[MONnD_COORD_NMAX];
  char    mc_mn_While_End   =0;
  long    mc_mn_While_Buffer=0;
  char    mc_mn_Set_Vars_Coord_Type = mc_mn_DEFS->COORD_NONE;

  /* mc_mn_Vars->Flag_Auto_Limits */
  if ((mc_mn_Vars->Buffer_Counter >= mc_mn_Vars->Buffer_Block) && (mc_mn_Vars->Flag_Auto_Limits == 1) && (mc_mn_Vars->Coord_Number > 0))
  {
    /* auto limits case : get limits in Buffer for each variable */
          /* Dim : (mc_mn_Vars->Coord_Number+1)*mc_mn_Vars->Buffer_Block matrix (for p, dp) */
    if (mc_mn_Vars->Flag_Verbose) printf("Monitor_nD: %s getting %li Auto Limits from List (%li).\n", mc_mn_Vars->compcurname, mc_mn_Vars->Coord_Number, mc_mn_Vars->Buffer_Counter);
    for (mc_mn_i = 1; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_i++)
    {
      if (mc_mn_Vars->Coord_Type[mc_mn_i] & mc_mn_DEFS->COORD_AUTO)
      {
        mc_mn_Vars->Coord_Min[mc_mn_i] = FLT_MAX;
        mc_mn_Vars->Coord_Max[mc_mn_i] = -FLT_MAX;
        for (mc_mn_j = 0; mc_mn_j < mc_mn_Vars->Buffer_Block; mc_mn_j++)
        {
          mc_mn_XY = mc_mn_Vars->Mon2D_Buffer[mc_mn_i+mc_mn_j*(mc_mn_Vars->Coord_Number+1)];  /* scanning variables in Buffer */
          if (mc_mn_XY < mc_mn_Vars->Coord_Min[mc_mn_i]) mc_mn_Vars->Coord_Min[mc_mn_i] = mc_mn_XY;
          if (mc_mn_XY > mc_mn_Vars->Coord_Max[mc_mn_i]) mc_mn_Vars->Coord_Max[mc_mn_i] = mc_mn_XY;
        }
      }
    }
    mc_mn_Vars->Flag_Auto_Limits = 2;  /* pass to 2nd auto limits step */
  }

  /* manage realloc for list all if Buffer size exceeded */
  if ((mc_mn_Vars->Buffer_Counter >= mc_mn_Vars->Buffer_Block) && (mc_mn_Vars->Flag_List >= 2))
  {
    if (mc_mn_Vars->Buffer_Size >= 20000 || mc_mn_Vars->Flag_List == 3)
    { /* save current (possibly append) and re-use Buffer */
      Monitor_nD_Save(mc_mn_DEFS, mc_mn_Vars);
      mc_mn_Vars->Flag_List = 3;
      mc_mn_Vars->Buffer_Block = mc_mn_Vars->Buffer_Size;
      mc_mn_Vars->Buffer_Counter  = 0;
      mc_mn_Vars->Neutron_Counter = 0;
    }
    else
    {
      mc_mn_Vars->Mon2D_Buffer  = (double *)realloc(mc_mn_Vars->Mon2D_Buffer, (mc_mn_Vars->Coord_Number+1)*(mc_mn_Vars->Neutron_Counter+mc_mn_Vars->Buffer_Block)*sizeof(double));
      if (mc_mn_Vars->Mon2D_Buffer == NULL)
            { printf("Monitor_nD: %s cannot reallocate mc_mn_Vars->Mon2D_Buffer[%li] (%li). Skipping.\n", mc_mn_Vars->compcurname, mc_mn_i, (mc_mn_Vars->Neutron_Counter+mc_mn_Vars->Buffer_Block)*sizeof(double)); mc_mn_Vars->Flag_List = 1; }
      else { mc_mn_Vars->Buffer_Counter = 0; mc_mn_Vars->Buffer_Size = mc_mn_Vars->Neutron_Counter+mc_mn_Vars->Buffer_Block; }
    }
  }

  while (!mc_mn_While_End)
  { /* we generate mc_mn_Coord[] and Coord_mc_mn_index[] from Buffer (auto limits) or passing neutron */
    if ((mc_mn_Vars->Flag_Auto_Limits == 2) && (mc_mn_Vars->Coord_Number > 0))
    {
      if (mc_mn_While_Buffer < mc_mn_Vars->Buffer_Block)
      {
        /* first while loops (mc_mn_While_Buffer) */
        /* auto limits case : scan Buffer within limits and store in Mon2D */
        mc_mn_pp = mc_mn_Vars->Mon2D_Buffer[mc_mn_While_Buffer*(mc_mn_Vars->Coord_Number+1)];
	/* For some reason the Intel c compiler version 10.1 gives 0 counts with Monitor_nD!
	   An ugly patch seems to be the following printf */
	printf("");
        mc_mn_Coord[0] = mc_mn_pp;

        for (mc_mn_i = 1; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_i++)
        {
          /* scanning variables in Buffer */
          mc_mn_XY = (mc_mn_Vars->Coord_Max[mc_mn_i]-mc_mn_Vars->Coord_Min[mc_mn_i]);

          mc_mn_Coord[mc_mn_i] = mc_mn_Vars->Mon2D_Buffer[mc_mn_i+mc_mn_While_Buffer*(mc_mn_Vars->Coord_Number+1)];
          if (mc_mn_XY > 0) mc_mn_Coord_Index[mc_mn_i] = floor((mc_mn_Coord[mc_mn_i]-mc_mn_Vars->Coord_Min[mc_mn_i])*mc_mn_Vars->Coord_Bin[mc_mn_i]/mc_mn_XY);
          else mc_mn_Coord_Index[mc_mn_i] = 0;
          if (mc_mn_Vars->Flag_With_Borders)
          {
            if (mc_mn_Coord_Index[mc_mn_i] < 0) mc_mn_Coord_Index[mc_mn_i] = 0;
            if (mc_mn_Coord_Index[mc_mn_i] >= mc_mn_Vars->Coord_Bin[mc_mn_i]) mc_mn_Coord_Index[mc_mn_i] = mc_mn_Vars->Coord_Bin[mc_mn_i] - 1;
          }
        } /* end for */
        mc_mn_While_Buffer++;
      } /* end if in Buffer */
      else /* (mc_mn_While_Buffer >= mc_mn_Vars->Buffer_Block) && (mc_mn_Vars->Flag_Auto_Limits == 2) */
      {
        mc_mn_Vars->Flag_Auto_Limits = 0;
        if (!mc_mn_Vars->Flag_List) /* free Buffer not needed (no list to output) */
        { /* Dim : (mc_mn_Vars->Coord_Number+1)*mc_mn_Vars->Buffer_Block matrix (for p, dp) */
          free(mc_mn_Vars->Mon2D_Buffer); mc_mn_Vars->Mon2D_Buffer = NULL;
        }
      }
    }
    else /* mc_mn_Vars->Flag_Auto_Limits == 0 or 1 */
    {
      for (mc_mn_i = 0; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_i++)
      { /* handle current neutron : last while */
        if (mc_mn_Vars->Flag_Auto_Limits==1) {
          double v;
          v=sqrt(mc_mn_Vars->cvx*mc_mn_Vars->cvx
                +mc_mn_Vars->cvy*mc_mn_Vars->cvy
                +mc_mn_Vars->cvz*mc_mn_Vars->cvz);
          if (mc_mn_Vars->min_x > mc_mn_Vars->cx) mc_mn_Vars->min_x = mc_mn_Vars->cx;
          if (mc_mn_Vars->max_x < mc_mn_Vars->cx) mc_mn_Vars->max_x = mc_mn_Vars->cx;
          if (mc_mn_Vars->min_y > mc_mn_Vars->cy) mc_mn_Vars->min_y = mc_mn_Vars->cy;
          if (mc_mn_Vars->max_y < mc_mn_Vars->cy) mc_mn_Vars->max_y = mc_mn_Vars->cy;
          mc_mn_Vars->mean_p  += mc_mn_Vars->cp;
          if (v) {
            mc_mn_Vars->mean_dx += mc_mn_Vars->cp*fabs(mc_mn_Vars->cvx/v);
            mc_mn_Vars->mean_dy += mc_mn_Vars->cp*fabs(mc_mn_Vars->cvy/v);
          }
          mc_mn_Vars->area =(mc_mn_Vars->max_x-mc_mn_Vars->min_x)
                           *(mc_mn_Vars->max_y-mc_mn_Vars->min_y)*1E4; /* cm2 */
          if (mc_mn_Vars->Flag_per_st)
          mc_mn_Vars->steradian = 2*fabs(2*atan(mc_mn_Vars->mean_dx/mc_mn_Vars->mean_p)
                                    *sin(2*atan(mc_mn_Vars->mean_dy/mc_mn_Vars->mean_p)/2));
        }

        mc_mn_XY = 0;
        mc_mn_Set_Vars_Coord_Type = (mc_mn_Vars->Coord_Type[mc_mn_i] & 31);
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_X) mc_mn_XY = mc_mn_Vars->cx;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_Y) mc_mn_XY = mc_mn_Vars->cy;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_Z) mc_mn_XY = mc_mn_Vars->cz;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_VX) mc_mn_XY = mc_mn_Vars->cvx;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_VY) mc_mn_XY = mc_mn_Vars->cvy;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_VZ) mc_mn_XY = mc_mn_Vars->cvz;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_KX) mc_mn_XY = V2K*mc_mn_Vars->cvx;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_KY) mc_mn_XY = V2K*mc_mn_Vars->cvy;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_KZ) mc_mn_XY = V2K*mc_mn_Vars->cvz;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_SX) mc_mn_XY = mc_mn_Vars->csx;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_SY) mc_mn_XY = mc_mn_Vars->csy;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_SZ) mc_mn_XY = mc_mn_Vars->csz;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_T) mc_mn_XY = mc_mn_Vars->ct;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_P) mc_mn_XY = mc_mn_Vars->cp;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_HDIV) mc_mn_XY = RAD2DEG*atan2(mc_mn_Vars->cvx,mc_mn_Vars->cvz);
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_VDIV) mc_mn_XY = RAD2DEG*atan2(mc_mn_Vars->cvy,mc_mn_Vars->cvz);
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_V) mc_mn_XY = sqrt(mc_mn_Vars->cvx*mc_mn_Vars->cvx+mc_mn_Vars->cvy*mc_mn_Vars->cvy+mc_mn_Vars->cvz*mc_mn_Vars->cvz);
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_RADIUS) mc_mn_XY = sqrt(mc_mn_Vars->cx*mc_mn_Vars->cx+mc_mn_Vars->cy*mc_mn_Vars->cy);
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_VXY) mc_mn_XY = sqrt(mc_mn_Vars->cvx*mc_mn_Vars->cvx+mc_mn_Vars->cvy*mc_mn_Vars->cvy);
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_K) { mc_mn_XY = sqrt(mc_mn_Vars->cvx*mc_mn_Vars->cvx+mc_mn_Vars->cvy*mc_mn_Vars->cvy+mc_mn_Vars->cvz*mc_mn_Vars->cvz);  mc_mn_XY *= V2K; }
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_KXY) { mc_mn_XY = sqrt(mc_mn_Vars->cvx*mc_mn_Vars->cvx+mc_mn_Vars->cvy*mc_mn_Vars->cvy);  mc_mn_XY *= V2K; }
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_ENERGY) { mc_mn_XY = mc_mn_Vars->cvx*mc_mn_Vars->cvx+mc_mn_Vars->cvy*mc_mn_Vars->cvy+mc_mn_Vars->cvz*mc_mn_Vars->cvz;  mc_mn_XY *= VS2E; }
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_LAMBDA) { mc_mn_XY = sqrt(mc_mn_Vars->cvx*mc_mn_Vars->cvx+mc_mn_Vars->cvy*mc_mn_Vars->cvy+mc_mn_Vars->cvz*mc_mn_Vars->cvz);  mc_mn_XY *= V2K; if (mc_mn_XY != 0) mc_mn_XY = 2*PI/mc_mn_XY; }
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_NCOUNT) mc_mn_XY = mc_mn_Coord[mc_mn_i]+1;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_ANGLE)
        {  mc_mn_XY = sqrt(mc_mn_Vars->cvx*mc_mn_Vars->cvx+mc_mn_Vars->cvy*mc_mn_Vars->cvy);
           if (mc_mn_Vars->cvz != 0)
           {
             mc_mn_XY= RAD2DEG*atan2(mc_mn_XY,mc_mn_Vars->cvz);
           } else mc_mn_XY = 0;
        }
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_THETA)  { if (mc_mn_Vars->cz != 0) mc_mn_XY = RAD2DEG*atan2(mc_mn_Vars->cx,mc_mn_Vars->cz); }
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_PHI) { if (mc_mn_Vars->cz != 0) mc_mn_XY = RAD2DEG*asin(mc_mn_Vars->cy/mc_mn_Vars->cz); }
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_USER1) mc_mn_XY = mc_mn_Vars->UserVariable1;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_USER2) mc_mn_XY = mc_mn_Vars->UserVariable2;
        else
        if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_USER3) mc_mn_XY = mc_mn_Vars->UserVariable3;
        else
        mc_mn_XY = 0;

        if (mc_mn_Vars->Coord_Type[mc_mn_i] & mc_mn_DEFS->COORD_ABS) mc_mn_XY=fabs(mc_mn_XY);

        if (mc_mn_i && (mc_mn_Vars->Coord_Type[mc_mn_i] & mc_mn_DEFS->COORD_LOG)) /* not for the flux */
        {  if (mc_mn_XY > 0) mc_mn_XY = log(mc_mn_XY)/log(10);
           else mc_mn_XY = -100; }

        mc_mn_Coord[mc_mn_i] = mc_mn_XY;
        if (mc_mn_i == 0) { mc_mn_pp = mc_mn_XY; mc_mn_Coord_Index[mc_mn_i] = 0; }
        else if (!mc_mn_Vars->Flag_Auto_Limits)
        {
          mc_mn_XY = (mc_mn_Vars->Coord_Max[mc_mn_i]-mc_mn_Vars->Coord_Min[mc_mn_i]);
          if (mc_mn_XY > 0) mc_mn_Coord_Index[mc_mn_i] = floor((mc_mn_Coord[mc_mn_i]-mc_mn_Vars->Coord_Min[mc_mn_i])*mc_mn_Vars->Coord_Bin[mc_mn_i]/mc_mn_XY);
          else mc_mn_Coord_Index[mc_mn_i] = 0;
          if (mc_mn_Vars->Flag_With_Borders)
          {
            if (mc_mn_Coord_Index[mc_mn_i] < 0) mc_mn_Coord_Index[mc_mn_i] = 0;
            if (mc_mn_Coord_Index[mc_mn_i] >= mc_mn_Vars->Coord_Bin[mc_mn_i]) mc_mn_Coord_Index[mc_mn_i] = mc_mn_Vars->Coord_Bin[mc_mn_i] - 1;
          }
        } /* else Auto_Limits will get Index later from Buffer */
      } /* end for mc_mn_i */
      mc_mn_While_End = 1;
    } /* end else if mc_mn_Vars->Flag_Auto_Limits == 2 */

    if (mc_mn_Vars->Flag_Auto_Limits != 2) /* not when reading auto limits Buffer */
    { /* now store Coord into Buffer (no mc_mn_index needed) if necessary */
      if ((mc_mn_Vars->Buffer_Counter < mc_mn_Vars->Buffer_Block) && ((mc_mn_Vars->Flag_List) || (mc_mn_Vars->Flag_Auto_Limits == 1)))
      {
        for (mc_mn_i = 0; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_i++)
        {
          mc_mn_Vars->Mon2D_Buffer[mc_mn_i + mc_mn_Vars->Neutron_Counter*(mc_mn_Vars->Coord_Number+1)] = mc_mn_Coord[mc_mn_i];
        }
        mc_mn_Vars->Buffer_Counter++;
        if (mc_mn_Vars->Flag_Verbose && (mc_mn_Vars->Buffer_Counter >= mc_mn_Vars->Buffer_Block) && (mc_mn_Vars->Flag_List == 1)) printf("Monitor_nD: %s %li neutrons stored in List.\n", mc_mn_Vars->compcurname, mc_mn_Vars->Buffer_Counter);
      }
      mc_mn_Vars->Neutron_Counter++;
    } /* end (mc_mn_Vars->Flag_Auto_Limits != 2) */

    /* store n1d/2d section for Buffer or current neutron in while */
    if (mc_mn_Vars->Flag_Auto_Limits != 1) /* not when storing auto limits Buffer */
    {

      if (mc_mn_Vars->Flag_per_cm2 && mc_mn_Vars->area      != 0)
        mc_mn_pp /= mc_mn_Vars->area;
      if (mc_mn_Vars->Flag_per_st  && mc_mn_Vars->steradian != 0)
        mc_mn_pp /= mc_mn_Vars->steradian;

    /* 1D and n1D case : mc_mn_Vars->Flag_Multiple */
      if (mc_mn_Vars->Flag_Multiple)
      { /* Dim : mc_mn_Vars->Coord_Number*mc_mn_Vars->Coord_Bin[mc_mn_i] vectors (intensity is not included) */
        /* check limits: monitors define a phase space to record */
        char within_limits=1;
        for (mc_mn_i= 1; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_i++)
        {
          mc_mn_j = mc_mn_Coord_Index[mc_mn_i];
          if (mc_mn_j < 0 || mc_mn_j >= mc_mn_Vars->Coord_Bin[mc_mn_i])
            within_limits=0;
        }
        if (within_limits)
        { for (mc_mn_i= 1; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_i++)
          {
            mc_mn_j = mc_mn_Coord_Index[mc_mn_i];
            if (mc_mn_j >= 0 && mc_mn_j < mc_mn_Vars->Coord_Bin[mc_mn_i])
            {
              mc_mn_Vars->Mon2D_N[mc_mn_i-1][mc_mn_j]++;
              mc_mn_Vars->Mon2D_p[mc_mn_i-1][mc_mn_j] += mc_mn_pp;
              mc_mn_Vars->Mon2D_p2[mc_mn_i-1][mc_mn_j] += mc_mn_pp*mc_mn_pp;
            }
          }
        }
        else if (mc_mn_Vars->Flag_Exclusive)
        { mc_mn_pp = 0.0;
        }
      }
      else /* 2D case : mc_mn_Vars->Coord_Number==2 and !mc_mn_Vars->Flag_Multiple and !mc_mn_Vars->Flag_List */
      if ((mc_mn_Vars->Coord_Number == 2) && !mc_mn_Vars->Flag_Multiple)
      { /* Dim : mc_mn_Vars->Coord_Bin[1]*mc_mn_Vars->Coord_Bin[2] matrix */
        mc_mn_i = mc_mn_Coord_Index[1];
        mc_mn_j = mc_mn_Coord_Index[2];
        if (mc_mn_i >= 0 && mc_mn_i < mc_mn_Vars->Coord_Bin[1] && mc_mn_j >= 0 && mc_mn_j < mc_mn_Vars->Coord_Bin[2])
        {
          mc_mn_Vars->Mon2D_N[mc_mn_i][mc_mn_j]++;
          mc_mn_Vars->Mon2D_p[mc_mn_i][mc_mn_j] += mc_mn_pp;
          mc_mn_Vars->Mon2D_p2[mc_mn_i][mc_mn_j] += mc_mn_pp*mc_mn_pp;
        }
        else if (mc_mn_Vars->Flag_Exclusive)
        { mc_mn_pp = 0.0;
        }
      }
    } /* end (mc_mn_Vars->Flag_Auto_Limits != 1) */
  } /* end while */
  return mc_mn_pp;
} /* end Monitor_nD_Trace */

/* ========================================================================= */
/* ADD: E.Farhi, Aug 6th, 2001: Monitor_nD section */
/* this routine is used to save data files */
/* ========================================================================= */

void Monitor_nD_Save(MonitornD_Defines_type *mc_mn_DEFS, MonitornD_Variables_type *mc_mn_Vars)
  {
    char   *mc_mn_fname;
    long    mc_mn_i,mc_mn_j;
    double *mc_mn_p0m = NULL;
    double *mc_mn_p1m = NULL;
    double *mc_mn_p2m = NULL;
    char    mc_mn_Coord_X_Label[1024];
    double  mc_mn_min1d, mc_mn_max1d;
    double  mc_mn_min2d, mc_mn_max2d;
    long    mc_mn_bin1d, mc_mn_bin2d;
    char    mc_mn_While_End = 0;
    long    mc_mn_While_Buffer = 0;
    double  mc_mn_XY, mc_mn_pp;
    double  mc_mn_Coord[MONnD_COORD_NMAX];
    long    mc_mn_Coord_Index[MONnD_COORD_NMAX];
    char    mc_mn_label[1024];
    double  mc_mn_ratio;

    mc_mn_ratio = 100*mcget_run_num()/mcget_ncount();
    if (mc_mn_Vars->Flag_per_cm2 && mc_mn_Vars->area && mc_mn_Vars->Flag_Verbose)
      printf("Monitor_nD: %s: detector area is %g [cm2]\n",
        mc_mn_Vars->compcurname, mc_mn_Vars->area);
    if (mc_mn_Vars->Flag_per_st && mc_mn_Vars->steradian && mc_mn_Vars->Flag_Verbose)
      printf("Monitor_nD: %s: beam solid angle is %g [st] (%g x %g [deg2])\n",
        mc_mn_Vars->compcurname, mc_mn_Vars->steradian,
        atan(mc_mn_Vars->mean_dx/mc_mn_Vars->mean_p)*RAD2DEG,
        atan(mc_mn_Vars->mean_dy/mc_mn_Vars->mean_p)*RAD2DEG);

    if (mc_mn_ratio < 99)
    {
      if (mc_mn_Vars->Flag_Verbose) printf("Monitor_nD: %s save intermediate results (%.2f %%).\n", mc_mn_Vars->compcurname, mc_mn_ratio);
    }
    /* check Buffer flush when end of simulation reached */
    if ((mc_mn_Vars->Buffer_Counter <= mc_mn_Vars->Buffer_Block) && mc_mn_Vars->Flag_Auto_Limits && mc_mn_Vars->Mon2D_Buffer && mc_mn_Vars->Buffer_Counter)
    {
      /* Get Auto Limits */
      if (mc_mn_Vars->Flag_Verbose) printf("Monitor_nD: %s getting %li Auto Limits from List (%li).\n", mc_mn_Vars->compcurname, mc_mn_Vars->Coord_Number, mc_mn_Vars->Buffer_Counter);
      for (mc_mn_i = 1; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_i++)
      {
        if (mc_mn_Vars->Coord_Type[mc_mn_i] & mc_mn_DEFS->COORD_AUTO)
        {
          mc_mn_Vars->Coord_Min[mc_mn_i] = FLT_MAX;
          mc_mn_Vars->Coord_Max[mc_mn_i] = -FLT_MAX;

          for (mc_mn_j = 0; mc_mn_j < mc_mn_Vars->Buffer_Counter; mc_mn_j++)
          {
            mc_mn_XY = mc_mn_Vars->Mon2D_Buffer[mc_mn_i+mc_mn_j*(mc_mn_Vars->Coord_Number+1)];  /* scanning variables in Buffer */
            if (mc_mn_XY < mc_mn_Vars->Coord_Min[mc_mn_i]) mc_mn_Vars->Coord_Min[mc_mn_i] = mc_mn_XY;
            if (mc_mn_XY > mc_mn_Vars->Coord_Max[mc_mn_i]) mc_mn_Vars->Coord_Max[mc_mn_i] = mc_mn_XY;

          }
        }
      }
      mc_mn_Vars->Flag_Auto_Limits = 2;  /* pass to 2nd auto limits step */
      mc_mn_Vars->Buffer_Block = mc_mn_Vars->Buffer_Counter;

      while (!mc_mn_While_End)
      { /* we generate mc_mn_Coord[] and Coord_mc_mn_index[] from Buffer (auto limits) or passing neutron */
        if (mc_mn_While_Buffer < mc_mn_Vars->Buffer_Block)
        {
          /* first while loops (mc_mn_While_Buffer) */
          mc_mn_Coord[0] = mc_mn_Vars->Mon2D_Buffer[mc_mn_While_Buffer*(mc_mn_Vars->Coord_Number+1)];

          /* auto limits case : scan Buffer within limits and store in Mon2D */
          for (mc_mn_i = 1; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_i++)
          {
            /* scanning variables in Buffer */
            mc_mn_XY = (mc_mn_Vars->Coord_Max[mc_mn_i]-mc_mn_Vars->Coord_Min[mc_mn_i]);
            mc_mn_Coord[mc_mn_i] = mc_mn_Vars->Mon2D_Buffer[mc_mn_i+mc_mn_While_Buffer*(mc_mn_Vars->Coord_Number+1)];
            if (mc_mn_XY > 0) mc_mn_Coord_Index[mc_mn_i] = floor((mc_mn_Coord[mc_mn_i]-mc_mn_Vars->Coord_Min[mc_mn_i])*mc_mn_Vars->Coord_Bin[mc_mn_i]/mc_mn_XY);
            else mc_mn_Coord_Index[mc_mn_i] = 0;
            if (mc_mn_Vars->Flag_With_Borders)
            {
              if (mc_mn_Coord_Index[mc_mn_i] < 0) mc_mn_Coord_Index[mc_mn_i] = 0;
              if (mc_mn_Coord_Index[mc_mn_i] >= mc_mn_Vars->Coord_Bin[mc_mn_i]) mc_mn_Coord_Index[mc_mn_i] = mc_mn_Vars->Coord_Bin[mc_mn_i] - 1;
            }
          } /* end for */
          mc_mn_While_Buffer++;
        } /* end if in Buffer */
        else /* (mc_mn_While_Buffer >= mc_mn_Vars->Buffer_Block) && (mc_mn_Vars->Flag_Auto_Limits == 2) */
        {
          mc_mn_Vars->Flag_Auto_Limits = 0;
          mc_mn_While_End = 1;
        }

        /* store n1d/2d section from Buffer */

        mc_mn_pp = mc_mn_Coord[0];
        /* 1D and n1D case : mc_mn_Vars->Flag_Multiple */
        if (mc_mn_Vars->Flag_Multiple)
        { /* Dim : mc_mn_Vars->Coord_Number*mc_mn_Vars->Coord_Bin[mc_mn_i] vectors (intensity is not included) */
          for (mc_mn_i= 0; mc_mn_i < mc_mn_Vars->Coord_Number; mc_mn_i++)
          {
            mc_mn_j = mc_mn_Coord_Index[mc_mn_i+1];
            if (mc_mn_j >= 0 && mc_mn_j < mc_mn_Vars->Coord_Bin[mc_mn_i+1])
            {
              mc_mn_Vars->Mon2D_N[mc_mn_i][mc_mn_j]++;
              mc_mn_Vars->Mon2D_p[mc_mn_i][mc_mn_j] += mc_mn_pp;
              mc_mn_Vars->Mon2D_p2[mc_mn_i][mc_mn_j] += mc_mn_pp*mc_mn_pp;
            }
          }
        }
        else /* 2D case : mc_mn_Vars->Coord_Number==2 and !mc_mn_Vars->Flag_Multiple and !mc_mn_Vars->Flag_List */
        if ((mc_mn_Vars->Coord_Number == 2) && !mc_mn_Vars->Flag_Multiple)
        { /* Dim : mc_mn_Vars->Coord_Bin[1]*mc_mn_Vars->Coord_Bin[2] matrix */
          mc_mn_i = mc_mn_Coord_Index[1];
          mc_mn_j = mc_mn_Coord_Index[2];
          if (mc_mn_i >= 0 && mc_mn_i < mc_mn_Vars->Coord_Bin[1] && mc_mn_j >= 0 && mc_mn_j < mc_mn_Vars->Coord_Bin[2])
          {
            mc_mn_Vars->Mon2D_N[mc_mn_i][mc_mn_j]++;
            mc_mn_Vars->Mon2D_p[mc_mn_i][mc_mn_j] += mc_mn_pp;
            mc_mn_Vars->Mon2D_p2[mc_mn_i][mc_mn_j] += mc_mn_pp*mc_mn_pp;
          }
        } /* end store 2D/1D */
      } /* end while */
    } /* end Force Get Limits */

    /* write output files (sent to file as p[i*n + j] vectors) */
    if (mc_mn_Vars->Coord_Number == 0)
    {
      double mc_mn_Nsum;
      double mc_mn_psum, mc_mn_p2sum;
      mc_mn_Nsum = mc_mn_Vars->Nsum;
      mc_mn_psum = mc_mn_Vars->psum;
      mc_mn_p2sum= mc_mn_Vars->p2sum;
      if (mc_mn_Vars->Flag_signal != mc_mn_DEFS->COORD_P && mc_mn_Nsum > 0)
      { mc_mn_psum /=mc_mn_Nsum; mc_mn_p2sum /= mc_mn_Nsum*mc_mn_Nsum; }
      /* DETECTOR_OUT_0D(mc_mn_Vars->Monitor_Label, mc_mn_Vars->Nsum, mc_mn_Vars->psum, mc_mn_Vars->p2sum); */
      mcdetector_out_0D(mc_mn_Vars->Monitor_Label, mc_mn_Nsum, mc_mn_psum, mc_mn_p2sum, mc_mn_Vars->compcurname, mc_mn_Vars->compcurpos);
    }
    else
    if (strlen(mc_mn_Vars->Mon_File) > 0)
    {
      mc_mn_fname = (char*)malloc(strlen(mc_mn_Vars->Mon_File)+10*mc_mn_Vars->Coord_Number);
      if (mc_mn_Vars->Flag_List && mc_mn_Vars->Mon2D_Buffer) /* List: DETECTOR_OUT_2D */
      {
        int  ascii_only_orig;
        char formatName[64];
        char *formatName_orig;

        if (mc_mn_Vars->Flag_List >= 2) mc_mn_Vars->Buffer_Size = mc_mn_Vars->Neutron_Counter;
        if (mc_mn_Vars->Buffer_Size >= mc_mn_Vars->Neutron_Counter)
          mc_mn_Vars->Buffer_Size = mc_mn_Vars->Neutron_Counter;
        strcpy(mc_mn_fname,mc_mn_Vars->Mon_File);
        if (strchr(mc_mn_Vars->Mon_File,'.') == NULL) strcat(mc_mn_fname, "_list");

        mc_mn_min1d = 1; mc_mn_max1d = mc_mn_Vars->Coord_Number+1;
        mc_mn_min2d = 0; mc_mn_max2d = mc_mn_Vars->Buffer_Size;
        mc_mn_bin1d = mc_mn_Vars->Coord_Number+1; mc_mn_bin2d = mc_mn_Vars->Buffer_Size;
        strcpy(mc_mn_Coord_X_Label,"");
        for (mc_mn_i= 0; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_i++)
        {
          if (mc_mn_min2d < mc_mn_Vars->Coord_Min[mc_mn_i]) mc_mn_min2d = mc_mn_Vars->Coord_Min[mc_mn_i];
          if (mc_mn_max2d < mc_mn_Vars->Coord_Max[mc_mn_i]) mc_mn_max2d = mc_mn_Vars->Coord_Max[mc_mn_i];
          strcat(mc_mn_Coord_X_Label, mc_mn_Vars->Coord_Var[mc_mn_i]);
          strcat(mc_mn_Coord_X_Label, " ");
          if (strchr(mc_mn_Vars->Mon_File,'.') == NULL)
          { strcat(mc_mn_fname, "."); strcat(mc_mn_fname, mc_mn_Vars->Coord_Var[mc_mn_i]); }
        }
        if (mc_mn_Vars->Flag_Verbose) printf("Monitor_nD: %s write monitor file %s List (%lix%li).\n", mc_mn_Vars->compcurname, mc_mn_fname,mc_mn_bin2d,mc_mn_bin1d);

        /* handle the type of list output */
        ascii_only_orig = mcascii_only;
        formatName_orig = mcformat.Name;  /* copy the pointer position */
        strcpy(formatName, mcformat.Name);
        if (mc_mn_Vars->Flag_List >= 1)
        { /* Flag_List mode:
               1=store 1 buffer
               2=list all, triggers 3 when 1st buffer reallocated
               3=re-used buffer (file already opened)
             Format modifiers for Flag_List
               1= normal monitor file (no modifier, export in one go)
               2= write data+header, and footer if buffer not full (mc_mn_Vars->Buffer_Counter < mc_mn_Vars->Buffer_Block)
               3= write data, and footer if buffer not full (final)
           */
          strcat(formatName, " list ");
          if (mc_mn_Vars->Flag_List == 3) strcat(formatName, " no header ");
          if (mc_mn_Vars->Flag_List >= 2 && mc_mn_Vars->Buffer_Counter >= mc_mn_Vars->Buffer_Block)
            strcat(formatName, " no footer ");

          if (mc_mn_Vars->Flag_Binary_List) mcascii_only = 1;
          if (mc_mn_Vars->Flag_Binary_List == 1)
            strcat(formatName, " binary float ");
          else if (mc_mn_Vars->Flag_Binary_List == 2)
            strcat(formatName, " binary double ");
        }
        if (mc_mn_min2d == mc_mn_max2d) mc_mn_max2d = mc_mn_min2d+1e-6;
        if (mc_mn_min1d == mc_mn_max1d) mc_mn_max1d = mc_mn_min1d+1e-6;
        strcpy(mc_mn_label, mc_mn_Vars->Monitor_Label);
        if (!mc_mn_Vars->Flag_Binary_List)
        { mc_mn_bin2d=-mc_mn_bin2d; }
        mcformat.Name = formatName;
        mcdetector_out_2D(
              mc_mn_label,
              "List of neutron events",
              mc_mn_Coord_X_Label,
              mc_mn_min2d, mc_mn_max2d,
              mc_mn_min1d, mc_mn_max1d,
              mc_mn_bin2d,
              mc_mn_bin1d,
            NULL,mc_mn_Vars->Mon2D_Buffer,NULL,
            mc_mn_fname, mc_mn_Vars->compcurname, mc_mn_Vars->compcurpos);

        /* reset the original type of output */
        mcascii_only = ascii_only_orig;
        mcformat.Name= formatName_orig;
      }
      if (mc_mn_Vars->Flag_Multiple) /* n1D: DETECTOR_OUT_1D */
      {
        for (mc_mn_i= 0; mc_mn_i < mc_mn_Vars->Coord_Number; mc_mn_i++)
        {

          strcpy(mc_mn_fname,mc_mn_Vars->Mon_File);
          if (strchr(mc_mn_Vars->Mon_File,'.') == NULL)
          { strcat(mc_mn_fname, "."); strcat(mc_mn_fname, mc_mn_Vars->Coord_Var[mc_mn_i+1]); }
          sprintf(mc_mn_Coord_X_Label, "%s monitor", mc_mn_Vars->Coord_Label[mc_mn_i+1]);
          strcpy(mc_mn_label, mc_mn_Coord_X_Label);
          if (mc_mn_Vars->Coord_Bin[mc_mn_i+1] > 0) { /* 1D monitor */
            if (mc_mn_Vars->Flag_Verbose) printf("Monitor_nD: %s write monitor file %s 1D (%li).\n", mc_mn_Vars->compcurname, mc_mn_fname, mc_mn_Vars->Coord_Bin[mc_mn_i+1]);
            mc_mn_min1d = mc_mn_Vars->Coord_Min[mc_mn_i+1];
            mc_mn_max1d = mc_mn_Vars->Coord_Max[mc_mn_i+1];
            if (mc_mn_min1d == mc_mn_max1d) mc_mn_max1d = mc_mn_min1d+1e-6;
            mc_mn_p1m = (double *)malloc(mc_mn_Vars->Coord_Bin[mc_mn_i+1]*sizeof(double));
            mc_mn_p2m = (double *)malloc(mc_mn_Vars->Coord_Bin[mc_mn_i+1]*sizeof(double));
            if (mc_mn_p2m == NULL) /* use Raw Buffer line output */
            {
              if (mc_mn_Vars->Flag_Verbose) printf("Monitor_nD: %s cannot allocate memory for output. Using raw data.\n", mc_mn_Vars->compcurname);
              if (mc_mn_p1m != NULL) free(mc_mn_p1m);
              mcdetector_out_1D(
              mc_mn_label,
              mc_mn_Vars->Coord_Label[mc_mn_i+1],
              mc_mn_Vars->Coord_Label[0],
              mc_mn_Vars->Coord_Var[mc_mn_i+1],
              mc_mn_min1d, mc_mn_max1d,
              mc_mn_Vars->Coord_Bin[mc_mn_i+1],
              mc_mn_Vars->Mon2D_N[mc_mn_i],mc_mn_Vars->Mon2D_p[mc_mn_i],mc_mn_Vars->Mon2D_p2[mc_mn_i],
              mc_mn_fname, mc_mn_Vars->compcurname, mc_mn_Vars->compcurpos);
            } /* if (mc_mn_p2m == NULL) */
            else
            {
              if (mc_mn_Vars->Flag_log != 0)
              {
                mc_mn_XY = FLT_MAX;
                for (mc_mn_j=0; mc_mn_j < mc_mn_Vars->Coord_Bin[mc_mn_i+1]; mc_mn_j++) /* search min of signal */
                  if ((mc_mn_XY > mc_mn_Vars->Mon2D_p[mc_mn_i][mc_mn_j]) && (mc_mn_Vars->Mon2D_p[mc_mn_i][mc_mn_j] > 0)) mc_mn_XY = mc_mn_Vars->Mon2D_p[mc_mn_i][mc_mn_j];
                if (mc_mn_XY <= 0) mc_mn_XY = -log(FLT_MAX)/log(10); else mc_mn_XY = log(mc_mn_XY)/log(10)-1;
              } /* if */

              for (mc_mn_j=0; mc_mn_j < mc_mn_Vars->Coord_Bin[mc_mn_i+1]; mc_mn_j++)
              {
                mc_mn_p1m[mc_mn_j] = mc_mn_Vars->Mon2D_p[mc_mn_i][mc_mn_j];
                mc_mn_p2m[mc_mn_j] = mc_mn_Vars->Mon2D_p2[mc_mn_i][mc_mn_j];
                if (mc_mn_Vars->Flag_signal != mc_mn_DEFS->COORD_P && mc_mn_Vars->Mon2D_N[mc_mn_i][mc_mn_j] > 0)
                { /* normalize mean signal to the number of events */
                  mc_mn_p1m[mc_mn_j] /= mc_mn_Vars->Mon2D_N[mc_mn_i][mc_mn_j];
                  mc_mn_p2m[mc_mn_j] /= mc_mn_Vars->Mon2D_N[mc_mn_i][mc_mn_j]*mc_mn_Vars->Mon2D_N[mc_mn_i][mc_mn_j];
                }
                if (mc_mn_Vars->Flag_log != 0)
                {
                  if ((mc_mn_p1m[mc_mn_j] > 0) && (mc_mn_p2m[mc_mn_j] > 0))
                  {
                    mc_mn_p2m[mc_mn_j] /= mc_mn_p1m[mc_mn_j]*mc_mn_p1m[mc_mn_j];
                    mc_mn_p1m[mc_mn_j] = log(mc_mn_p1m[mc_mn_j])/log(10);
                  }
                  else
                  {
                    mc_mn_p1m[mc_mn_j] = mc_mn_XY;
                    mc_mn_p2m[mc_mn_j] = 0;
                  }
                }
              } /* for */
              mcdetector_out_1D(
                mc_mn_label,
                mc_mn_Vars->Coord_Label[mc_mn_i+1],
                mc_mn_Vars->Coord_Label[0],
                mc_mn_Vars->Coord_Var[mc_mn_i+1],
                mc_mn_min1d, mc_mn_max1d,
                mc_mn_Vars->Coord_Bin[mc_mn_i+1],
                mc_mn_Vars->Mon2D_N[mc_mn_i],mc_mn_p1m,mc_mn_p2m,
                mc_mn_fname, mc_mn_Vars->compcurname, mc_mn_Vars->compcurpos);

            } /* else */
            if (mc_mn_p1m != NULL) free(mc_mn_p1m); mc_mn_p1m=NULL;
            if (mc_mn_p2m != NULL) free(mc_mn_p2m); mc_mn_p2m=NULL;
          } else { /* 0d monitor */
            mcdetector_out_0D(mc_mn_label, mc_mn_Vars->Mon2D_p[mc_mn_i][0], mc_mn_Vars->Mon2D_p2[mc_mn_i][0], mc_mn_Vars->Mon2D_N[mc_mn_i][0], mc_mn_Vars->compcurname, mc_mn_Vars->compcurpos);
          }


        } /* for */
      } /* if 1D */
      else
      if (mc_mn_Vars->Coord_Number == 2)  /* 2D: DETECTOR_OUT_2D */
      {
        strcpy(mc_mn_fname,mc_mn_Vars->Mon_File);

        mc_mn_p0m = (double *)malloc(mc_mn_Vars->Coord_Bin[1]*mc_mn_Vars->Coord_Bin[2]*sizeof(double));
        mc_mn_p1m = (double *)malloc(mc_mn_Vars->Coord_Bin[1]*mc_mn_Vars->Coord_Bin[2]*sizeof(double));
        mc_mn_p2m = (double *)malloc(mc_mn_Vars->Coord_Bin[1]*mc_mn_Vars->Coord_Bin[2]*sizeof(double));
        if (mc_mn_p2m == NULL)
        {
          if (mc_mn_Vars->Flag_Verbose) printf("Monitor_nD: %s cannot allocate memory for 2D array (%li). Skipping.\n", mc_mn_Vars->compcurname, 3*mc_mn_Vars->Coord_Bin[1]*mc_mn_Vars->Coord_Bin[2]*sizeof(double));
          if (mc_mn_p0m != NULL) free(mc_mn_p0m);
          if (mc_mn_p1m != NULL) free(mc_mn_p1m);
        }
        else
        {
          if (mc_mn_Vars->Flag_log != 0)
          {
            mc_mn_XY = FLT_MAX;
            for (mc_mn_i= 0; mc_mn_i < mc_mn_Vars->Coord_Bin[1]; mc_mn_i++)
              for (mc_mn_j= 0; mc_mn_j < mc_mn_Vars->Coord_Bin[2]; mc_mn_j++) /* search min of signal */
                if ((mc_mn_XY > mc_mn_Vars->Mon2D_p[mc_mn_i][mc_mn_j]) && (mc_mn_Vars->Mon2D_p[mc_mn_i][mc_mn_j]>0)) mc_mn_XY = mc_mn_Vars->Mon2D_p[mc_mn_i][mc_mn_j];
            if (mc_mn_XY <= 0) mc_mn_XY = -log(FLT_MAX)/log(10); else mc_mn_XY = log(mc_mn_XY)/log(10)-1;
          }
          for (mc_mn_i= 0; mc_mn_i < mc_mn_Vars->Coord_Bin[1]; mc_mn_i++)
          {
            for (mc_mn_j= 0; mc_mn_j < mc_mn_Vars->Coord_Bin[2]; mc_mn_j++)
            {
              long mc_mn_index;
              mc_mn_index = mc_mn_j + mc_mn_i*mc_mn_Vars->Coord_Bin[2];
              mc_mn_p0m[mc_mn_index] = mc_mn_Vars->Mon2D_N[mc_mn_i][mc_mn_j];
              mc_mn_p1m[mc_mn_index] = mc_mn_Vars->Mon2D_p[mc_mn_i][mc_mn_j];
              mc_mn_p2m[mc_mn_index] = mc_mn_Vars->Mon2D_p2[mc_mn_i][mc_mn_j];
              if (mc_mn_Vars->Flag_signal != mc_mn_DEFS->COORD_P && mc_mn_p0m[mc_mn_index] > 0)
              {
                  mc_mn_p1m[mc_mn_index] /= mc_mn_p0m[mc_mn_index];
                  mc_mn_p2m[mc_mn_index] /= mc_mn_p0m[mc_mn_index]*mc_mn_p0m[mc_mn_index];
              }

              if (mc_mn_Vars->Flag_log != 0)
              {
                if ((mc_mn_p1m[mc_mn_index] > 0) && (mc_mn_p2m[mc_mn_index] > 0))
                {
                  mc_mn_p2m[mc_mn_index] /= (mc_mn_p1m[mc_mn_index]*mc_mn_p1m[mc_mn_index]);
                  mc_mn_p1m[mc_mn_index] = log(mc_mn_p1m[mc_mn_index])/log(10);

                }
                else
                {
                  mc_mn_p1m[mc_mn_index] = mc_mn_XY;
                  mc_mn_p2m[mc_mn_index] = 0;
                }
              }
            }
          }
          if (strchr(mc_mn_Vars->Mon_File,'.') == NULL)
          { strcat(mc_mn_fname, "."); strcat(mc_mn_fname, mc_mn_Vars->Coord_Var[1]);
              strcat(mc_mn_fname, "_"); strcat(mc_mn_fname, mc_mn_Vars->Coord_Var[2]); }
          if (mc_mn_Vars->Flag_Verbose) printf("Monitor_nD: %s write monitor file %s 2D (%lix%li).\n", mc_mn_Vars->compcurname, mc_mn_fname, mc_mn_Vars->Coord_Bin[1], mc_mn_Vars->Coord_Bin[2]);

          mc_mn_min1d = mc_mn_Vars->Coord_Min[1];
          mc_mn_max1d = mc_mn_Vars->Coord_Max[1];
          if (mc_mn_min1d == mc_mn_max1d) mc_mn_max1d = mc_mn_min1d+1e-6;
          mc_mn_min2d = mc_mn_Vars->Coord_Min[2];
          mc_mn_max2d = mc_mn_Vars->Coord_Max[2];
          if (mc_mn_min2d == mc_mn_max2d) mc_mn_max2d = mc_mn_min2d+1e-6;
          strcpy(mc_mn_label, mc_mn_Vars->Monitor_Label);
          if (mc_mn_Vars->Coord_Bin[1]*mc_mn_Vars->Coord_Bin[2] > 1
           && mc_mn_Vars->Flag_signal == mc_mn_DEFS->COORD_P)
            strcat(mc_mn_label, " per bin");

          mcdetector_out_2D(
            mc_mn_label,
            mc_mn_Vars->Coord_Label[1],
            mc_mn_Vars->Coord_Label[2],
            mc_mn_min1d, mc_mn_max1d,
            mc_mn_min2d, mc_mn_max2d,
            mc_mn_Vars->Coord_Bin[1],
            mc_mn_Vars->Coord_Bin[2],
            mc_mn_p0m,mc_mn_p1m,mc_mn_p2m,
            mc_mn_fname, mc_mn_Vars->compcurname, mc_mn_Vars->compcurpos);

          if (mc_mn_p0m != NULL) free(mc_mn_p0m);
          if (mc_mn_p1m != NULL) free(mc_mn_p1m);
          if (mc_mn_p2m != NULL) free(mc_mn_p2m);
        }
      }
      free(mc_mn_fname);
    }
  } /* end Monitor_nD_Save */

/* ========================================================================= */
/* ADD: E.Farhi, Aug 6th, 2001: Monitor_nD section */
/* this routine is used to free memory */
/* ========================================================================= */

void Monitor_nD_Finally(MonitornD_Defines_type *mc_mn_DEFS,
  MonitornD_Variables_type *mc_mn_Vars)
  {
    int mc_mn_i;

    /* Now Free memory Mon2D.. */
    if ((mc_mn_Vars->Flag_Auto_Limits || mc_mn_Vars->Flag_List) && mc_mn_Vars->Coord_Number)
    { /* Dim : (mc_mn_Vars->Coord_Number+1)*mc_mn_Vars->Buffer_Block matrix (for p, dp) */
      if (mc_mn_Vars->Mon2D_Buffer != NULL) free(mc_mn_Vars->Mon2D_Buffer);
    }

    /* 1D and n1D case : mc_mn_Vars->Flag_Multiple */
    if (mc_mn_Vars->Flag_Multiple && mc_mn_Vars->Coord_Number)
    { /* Dim : mc_mn_Vars->Coord_Number*mc_mn_Vars->Coord_Bin[mc_mn_i] vectors */
      for (mc_mn_i= 0; mc_mn_i < mc_mn_Vars->Coord_Number; mc_mn_i++)
      {
        free(mc_mn_Vars->Mon2D_N[mc_mn_i]);
        free(mc_mn_Vars->Mon2D_p[mc_mn_i]);
        free(mc_mn_Vars->Mon2D_p2[mc_mn_i]);
      }
      free(mc_mn_Vars->Mon2D_N);
      free(mc_mn_Vars->Mon2D_p);
      free(mc_mn_Vars->Mon2D_p2);
    }


    /* 2D case : mc_mn_Vars->Coord_Number==2 and !mc_mn_Vars->Flag_Multiple and !mc_mn_Vars->Flag_List */
    if ((mc_mn_Vars->Coord_Number == 2) && !mc_mn_Vars->Flag_Multiple)
    { /* Dim : mc_mn_Vars->Coord_Bin[1]*mc_mn_Vars->Coord_Bin[2] matrix */
      for (mc_mn_i= 0; mc_mn_i < mc_mn_Vars->Coord_Bin[1]; mc_mn_i++)
      {
        free(mc_mn_Vars->Mon2D_N[mc_mn_i]);
        free(mc_mn_Vars->Mon2D_p[mc_mn_i]);
        free(mc_mn_Vars->Mon2D_p2[mc_mn_i]);
      }
      free(mc_mn_Vars->Mon2D_N);
      free(mc_mn_Vars->Mon2D_p);
      free(mc_mn_Vars->Mon2D_p2);
    }
  } /* end Monitor_nD_Finally */

/* ========================================================================= */
/* ADD: E.Farhi, Aug 6th, 2001: Monitor_nD section */
/* this routine is used to display component */
/* ========================================================================= */

void Monitor_nD_McDisplay(MonitornD_Defines_type *mc_mn_DEFS,
  MonitornD_Variables_type *mc_mn_Vars)
  {
    double mc_mn_radius, mc_mn_h;
    double mc_mn_xmin;
    double mc_mn_xmax;
    double mc_mn_ymin;
    double mc_mn_ymax;
    double mc_mn_zmin;
    double mc_mn_zmax;
    int    mc_mn_i;
    double mc_mn_hdiv_min=-180, mc_mn_hdiv_max=180, mc_mn_vdiv_min=-180, mc_mn_vdiv_max=180;
    char   mc_mn_restricted = 0;

    mc_mn_radius = mc_mn_Vars->Sphere_Radius;
    mc_mn_h = mc_mn_Vars->Cylinder_Height;
    mc_mn_xmin = mc_mn_Vars->mxmin;
    mc_mn_xmax = mc_mn_Vars->mxmax;
    mc_mn_ymin = mc_mn_Vars->mymin;
    mc_mn_ymax = mc_mn_Vars->mymax;
    mc_mn_zmin = mc_mn_Vars->mzmin;
    mc_mn_zmax = mc_mn_Vars->mzmax;

    /* determine if there are angular limits set at start (no auto) in coord_types
     * cylinder/banana: look for hdiv
     * sphere: look for angle, radius (->atan2(val,mc_mn_radius)), hdiv, vdiv
     * this activates a 'restricted' flag, to draw a region as blades on cylinder/sphere
     */
    for (mc_mn_i= 0; mc_mn_i <= mc_mn_Vars->Coord_Number; mc_mn_i++)
    {
      int mc_mn_Set_Vars_Coord_Type;
      mc_mn_Set_Vars_Coord_Type = (mc_mn_Vars->Coord_Type[mc_mn_i] & 31);
      if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_HDIV || mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_THETA)
      { mc_mn_hdiv_min = mc_mn_Vars->Coord_Min[mc_mn_i]; mc_mn_hdiv_max = mc_mn_Vars->Coord_Max[mc_mn_i]; mc_mn_restricted = 1; }
      else if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_VDIV || mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_PHI)
      { mc_mn_vdiv_min = mc_mn_Vars->Coord_Min[mc_mn_i]; mc_mn_vdiv_max = mc_mn_Vars->Coord_Max[mc_mn_i];mc_mn_restricted = 1;  }
      else if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_ANGLE)
      { mc_mn_hdiv_min = mc_mn_vdiv_min = mc_mn_Vars->Coord_Min[mc_mn_i];
        mc_mn_hdiv_max = mc_mn_vdiv_max = mc_mn_Vars->Coord_Max[mc_mn_i];
        mc_mn_restricted = 1; }
      else if (mc_mn_Set_Vars_Coord_Type == mc_mn_DEFS->COORD_RADIUS)
      { double angle;
        angle = RAD2DEG*atan2(mc_mn_Vars->Coord_Max[mc_mn_i], mc_mn_radius);
        mc_mn_hdiv_min = mc_mn_vdiv_min = angle;
        mc_mn_hdiv_max = mc_mn_vdiv_max = angle;
        mc_mn_restricted = 1; }
    }

    if ((!mc_mn_restricted && (abs(mc_mn_Vars->Flag_Shape) == mc_mn_DEFS->SHAPE_SPHERE))
    || abs(mc_mn_Vars->Flag_Shape) == mc_mn_DEFS->SHAPE_PREVIOUS)
    {
      mcdis_magnify("");
      mcdis_circle("xy",0,0,0,mc_mn_radius);
      mcdis_circle("xz",0,0,0,mc_mn_radius);
      mcdis_circle("yz",0,0,0,mc_mn_radius);
    }
    else if (mc_mn_restricted && ((abs(mc_mn_Vars->Flag_Shape) == mc_mn_DEFS->SHAPE_CYLIND) || (abs(mc_mn_Vars->Flag_Shape) == mc_mn_DEFS->SHAPE_BANANA) || (abs(mc_mn_Vars->Flag_Shape) == mc_mn_DEFS->SHAPE_SPHERE)))
    {
      int NH=24, NV=24;
      int ih, iv;
      double width, height;
      int issphere;
      issphere = (abs(mc_mn_Vars->Flag_Shape) == mc_mn_DEFS->SHAPE_SPHERE);
      width = (mc_mn_hdiv_max-mc_mn_hdiv_min)/NH;
      height= (mc_mn_vdiv_max-mc_mn_vdiv_min)/NV;
      mcdis_magnify("xyz");
      for(ih = 0; ih < NH; ih++)
        for(iv = 0; iv < NV; iv++)
        {
          double theta0, phi0, theta1, phi1;
          double x0,y0,z0,x1,y1,z1,x2,y2,z2,x3,y3,z3;
          double ymin, ymax;
          phi0 = (mc_mn_hdiv_min+ width*ih)*DEG2RAD; /* in xz plane */
          phi1 = (mc_mn_hdiv_min+ width*(ih+1))*DEG2RAD;
          if (issphere)
          {
            theta0= (90-mc_mn_vdiv_min+height*iv)*DEG2RAD;
            theta1= (90-mc_mn_vdiv_min+height*(iv+1))*DEG2RAD;
          } else
          {
            theta0= theta1 = PI/2;
            ymin  = mc_mn_ymin+(mc_mn_ymax-mc_mn_ymin)*(iv/NV);
            ymax  = mc_mn_ymin+(mc_mn_ymax-mc_mn_ymin)*((iv+1)/NV);
          }
          z0 = mc_mn_radius*sin(theta0)*cos(phi0);
          x0 = mc_mn_radius*sin(theta0)*sin(phi0);
          if (issphere) y0 = mc_mn_radius*cos(theta0); else y0 = ymin;
          z1 = mc_mn_radius*sin(theta1)*cos(phi0);
          x1 = mc_mn_radius*sin(theta1)*sin(phi0);
          if (issphere) y1 = mc_mn_radius*cos(theta1); else y1 = ymax;
          z2 = mc_mn_radius*sin(theta1)*cos(phi1);
          x2 = mc_mn_radius*sin(theta1)*sin(phi1);
          y2 = y1;
          z3 = mc_mn_radius*sin(theta0)*cos(phi1);
          x3 = mc_mn_radius*sin(theta0)*sin(phi1);
          y3 = y0;
          mcdis_multiline(5,
            x0,y0,z0,
            x1,y1,z1,
            x2,y2,z2,
            x3,y3,z3,
            x0,y0,z0);
        }
    }
    else
    if (abs(mc_mn_Vars->Flag_Shape) == mc_mn_DEFS->SHAPE_DISK)
    {
      mcdis_magnify("");
      mcdis_circle("xy",0,0,0,mc_mn_radius);
    }
    else
    if (abs(mc_mn_Vars->Flag_Shape) == mc_mn_DEFS->SHAPE_SQUARE)
    {
      mcdis_magnify("xy");
      mcdis_multiline(5, (double)mc_mn_xmin, (double)mc_mn_ymin, 0.0,
             (double)mc_mn_xmax, (double)mc_mn_ymin, 0.0,
             (double)mc_mn_xmax, (double)mc_mn_ymax, 0.0,
             (double)mc_mn_xmin, (double)mc_mn_ymax, 0.0,
             (double)mc_mn_xmin, (double)mc_mn_ymin, 0.0);
    }
    else
    if (!mc_mn_restricted && ((abs(mc_mn_Vars->Flag_Shape) == mc_mn_DEFS->SHAPE_CYLIND) || (abs(mc_mn_Vars->Flag_Shape) == mc_mn_DEFS->SHAPE_BANANA)))
    {
      mcdis_magnify("xyz");
      mcdis_circle("xz", 0,  mc_mn_h/2.0, 0, mc_mn_radius);
      mcdis_circle("xz", 0, -mc_mn_h/2.0, 0, mc_mn_radius);
      mcdis_line(-mc_mn_radius, -mc_mn_h/2.0, 0, -mc_mn_radius, +mc_mn_h/2.0, 0);
      mcdis_line(+mc_mn_radius, -mc_mn_h/2.0, 0, +mc_mn_radius, +mc_mn_h/2.0, 0);
      mcdis_line(0, -mc_mn_h/2.0, -mc_mn_radius, 0, +mc_mn_h/2.0, -mc_mn_radius);
      mcdis_line(0, -mc_mn_h/2.0, +mc_mn_radius, 0, +mc_mn_h/2.0, +mc_mn_radius);
    }
    else
    if (abs(mc_mn_Vars->Flag_Shape) == mc_mn_DEFS->SHAPE_BOX)
    {
      mcdis_magnify("xyz");
      mcdis_multiline(5, mc_mn_xmin, mc_mn_ymin, mc_mn_zmin,
                   mc_mn_xmax, mc_mn_ymin, mc_mn_zmin,
                   mc_mn_xmax, mc_mn_ymax, mc_mn_zmin,
                   mc_mn_xmin, mc_mn_ymax, mc_mn_zmin,
                   mc_mn_xmin, mc_mn_ymin, mc_mn_zmin);
      mcdis_multiline(5, mc_mn_xmin, mc_mn_ymin, mc_mn_zmax,
                   mc_mn_xmax, mc_mn_ymin, mc_mn_zmax,
                   mc_mn_xmax, mc_mn_ymax, mc_mn_zmax,
                   mc_mn_xmin, mc_mn_ymax, mc_mn_zmax,
                   mc_mn_xmin, mc_mn_ymin, mc_mn_zmax);
      mcdis_line(mc_mn_xmin, mc_mn_ymin, mc_mn_zmin, mc_mn_xmin, mc_mn_ymin, mc_mn_zmax);
      mcdis_line(mc_mn_xmax, mc_mn_ymin, mc_mn_zmin, mc_mn_xmax, mc_mn_ymin, mc_mn_zmax);
      mcdis_line(mc_mn_xmin, mc_mn_ymax, mc_mn_zmin, mc_mn_xmin, mc_mn_ymax, mc_mn_zmax);
      mcdis_line(mc_mn_xmax, mc_mn_ymax, mc_mn_zmin, mc_mn_xmax, mc_mn_ymax, mc_mn_zmax);
    }
  } /* end Monitor_nD_McDisplay */

/* end of monitor_nd-lib.c */

#line 10179 "D1A.c"

/* Shared user declarations for all components 'PowderN'. */
#line 165 "/usr/local/lib/mcstas/samples/PowderN.comp"
  /* used for reading data table from file */

/* Declare structures and functions only once in each instrument. */
#ifndef POWDERN_DECL
#define POWDERN_DECL
/* format definitions in the order {j d F2 DW Dd inv2d q F} */
#ifndef Crystallographica
#define Crystallographica { 4,5,7,0,0,0,0,0 }
#define Fullprof          { 4,0,8,0,0,5,0,0 }
#define Lazy              {17,6,0,0,0,0,0,13 }
#define Undefined         { 0,0,0,0,0,0,0,0 }
#endif

  struct line_data
    {
      double F2;                  /* Value of structure factor */
      double q;                   /* Qvector */
      int j;                      /* Multiplicity */
      double DWfactor;            /* Debye-Waller factor */
      double w;                   /* Intrinsic line width */
    };

  struct line_info_struct
    {
      struct line_data *list;     /* Reflection array */
      int  count;                  /* Number of reflections */
      double Dd;
      double DWfactor;
      double V_0;
      double rho;
      double at_weight;
      double at_nb;
      double sigma_a;
      double sigma_i;
      char   compname[256];
      double flag_barns;
      int    column_order[8]; /* column signification */
    };

  int read_line_data(char *SC_file, struct line_info_struct *info)
  {
    struct line_data *list = NULL;
    int    size = 0;
    t_Table sTable; /* sample data table structure from SC_file */
    int    i=0;
    int    mult_count  =0;
    char   flag=0;
    double q_count=0, j_count=0, F2_count=0;
    char **parsing;
    int    list_count=0;

    if (!SC_file || !strlen(SC_file) || !strcmp(SC_file, "NULL")) {
      printf("PowderN: %s: Using incoherent elastic scattering only\n",
          info->compname);
      info->count = 0;
      return(0);
    }
    Table_Read(&sTable, SC_file, 1); /* read 1st block data from SC_file into sTable*/

    /* parsing of header */
    parsing = Table_ParseHeader(sTable.header,
      "Vc","V_0",
      "sigma_abs","sigma_a ",
      "sigma_inc","sigma_i ",
      "column_j",
      "column_d",
      "column_F2",
      "column_DW",
      "column_Dd",
      "column_inv2d", "column_1/2d", "column_sintheta/lambda",
      "column_q", /* 14 */
      "DW", "Debye_Waller",
      "Detla_d/d",
      "column_F ",
      "V_rho",
      "density",
      "weight",
      "nb_atoms",
      NULL);

    if (parsing) {
      if (parsing[0] && !info->V_0)     info->V_0    =atof(parsing[0]);
      if (parsing[1] && !info->V_0)     info->V_0    =atof(parsing[1]);
      if (parsing[2] && !info->sigma_a) info->sigma_a=atof(parsing[2]);
      if (parsing[3] && !info->sigma_a) info->sigma_a=atof(parsing[3]);
      if (parsing[4] && !info->sigma_i) info->sigma_i=atof(parsing[4]);
      if (parsing[5] && !info->sigma_i) info->sigma_i=atof(parsing[5]);
      if (parsing[6])                   info->column_order[0]=atoi(parsing[6]);
      if (parsing[7])                   info->column_order[1]=atoi(parsing[7]);
      if (parsing[8])                   info->column_order[2]=atoi(parsing[8]);
      if (parsing[9])                   info->column_order[3]=atoi(parsing[9]);
      if (parsing[10])                  info->column_order[4]=atoi(parsing[10]);
      if (parsing[11])                  info->column_order[5]=atoi(parsing[11]);
      if (parsing[12])                  info->column_order[5]=atoi(parsing[12]);
      if (parsing[13])                  info->column_order[5]=atoi(parsing[13]);
      if (parsing[14])                  info->column_order[6]=atoi(parsing[14]);
      if (parsing[15] && info->DWfactor<=0)    info->DWfactor=atof(parsing[15]);
      if (parsing[16] && info->DWfactor<=0)    info->DWfactor=atof(parsing[16]);
      if (parsing[17] && info->Dd <0)          info->Dd      =atof(parsing[17]);
      if (parsing[18])                  info->column_order[7]=atoi(parsing[18]);
      if (parsing[19] && !info->V_0)    info->V_0    =1/atof(parsing[19]);
      if (parsing[20] && !info->rho)    info->rho    =atof(parsing[20]);
      if (parsing[21] && !info->at_weight)     info->at_weight    =atof(parsing[21]);
      if (parsing[22] && info->at_nb <= 1)  info->at_nb    =atof(parsing[22]);
      for (i=0; i<=22; i++) if (parsing[i]) free(parsing[i]);
      free(parsing);
    }

    if (!sTable.rows)
      exit(fprintf(stderr, "PowderN: %s: Error: The number of rows in %s "
       "should be at least %d\n", info->compname, SC_file, 1));
    else size = sTable.rows;
    Table_Info(sTable);
    printf("PowderN: %s: Reading %d rows from %s\n",
          info->compname, size, SC_file);
          
    if (info->column_order[0] == 4 && info->flag_barns !=0)
    printf("PowderN: %s: Powder file probably of type Crystallographica/Fullprof (lau)\n"
           "WARNING: but F2 unit is set to barns=1 (barns). Intensity might be 100 times too high.\n", 
           info->compname);
  if (info->column_order[0] == 17 && info->flag_barns == 0)
    printf("PowderN: %s: Powder file probably of type Lazy Pulver (laz)\n"
           "WARNING: but F2 unit is set to barns=0 (fm^2). Intensity might be 100 times too low.\n", 
           info->compname);
    /* allocate line_data array */
    list = (struct line_data*)malloc(size*sizeof(struct line_data));

    for (i=0; i<size; i++)
    {
      /*      printf("Reading in line %i\n",i);*/
      double j=0, d=0, w=0, q=0, DWfactor=0, F2=0;
      int index;

      if (info->Dd >= 0)      w         = info->Dd;
      if (info->DWfactor > 0) DWfactor  = info->DWfactor;

      /* get data from table using columns {j d F2 DW Dd inv2d q F} */
      /* column indexes start at 1, thus need to substract 1 */
      if (info->column_order[0] >0)
        j = Table_Index(sTable, i, info->column_order[0]-1);
      if (info->column_order[1] >0)
        d = Table_Index(sTable, i, info->column_order[1]-1);
      if (info->column_order[2] >0)
        F2 = Table_Index(sTable, i, info->column_order[2]-1);
      if (info->column_order[3] >0)
        DWfactor = Table_Index(sTable, i, info->column_order[3]-1);
      if (info->column_order[4] >0)
        w = Table_Index(sTable, i, info->column_order[4]-1);
      if (info->column_order[5] >0)
        { d = Table_Index(sTable, i, info->column_order[5]-1);
          d = (d > 0? 1/d/2 : 0); }
      if (info->column_order[6] >0)
        { q = Table_Index(sTable, i, info->column_order[6]-1);
          d = (q > 0 ? 2*PI/q : 0); }
      if (info->column_order[7] >0  && !F2)
        { F2 = Table_Index(sTable, i, info->column_order[7]-1); F2 *= F2; }

      /* assign and check values */
      j = (j > 0 ? j : 0);
      q = (d > 0 ? 2*PI/d : 0); /* this is q */
      DWfactor = (DWfactor > 0 ? DWfactor : 1);
      w = (w>0 ? w : 0); /* this is q and d relative spreading */
      F2 = (F2 >= 0 ? F2 : 0);
      if (j == 0 || q == 0) {
        printf("PowderN: %s: line %i has invalid definition\n"
               "         (mult=0 or q=0 or d=0)\n", info->compname, i);
        continue;
      }
      list[list_count].j = j;
      list[list_count].q = q;
      list[list_count].DWfactor = DWfactor;
      list[list_count].w = w;
      list[list_count].F2= F2;

      /* adjust multiplicity if j-column + multiple d-spacing lines */
      /* if  d = previous d, increase line duplication index */
      if (!q_count)     q_count = q;
      if (!j_count)     j_count = j;
      if (!F2_count)     F2_count = F2;
      if (fabs(q_count-q) < 0.0001*fabs(q)
       && fabs(F2_count-F2) < 0.0001*fabs(F2) && j_count == j) {
       mult_count++; flag=0; }
      else flag=1;
      if (i == size-1) flag=1;
      /* else if d != previous d : just passed equivalent lines */
      if (flag) {
        if (i == size-1) list_count++;
      /*   if duplication index == previous multiplicity */
      /*      set back multiplicity of previous lines to 1 */
        if (mult_count && list_count>0 &&
          (mult_count == list[list_count-1].j
          || (mult_count == list[list_count].j && i == size-1)) ) {
          printf("PowderN: %s: Set multiplicity to 1 for lines [%i:%i]\n"
                  "         (d-spacing %g is duplicated %i times)\n",
            info->compname, list_count-mult_count, list_count-1, list[list_count-1].q, mult_count);
          for (index=list_count-mult_count; index<list_count; list[index++].j = 1);
          mult_count   = 1;
          q_count = q;
          j_count = j;
          F2_count = F2;
        }
        if (i == size-1) list_count--;
        flag=0;
      }
      list_count++;
    } /* end for */
    printf("PowderN: %s: File %s done (%i valid lines).\n", info->compname, SC_file, list_count);
    Table_Free(&sTable);
    info->list  = list;
    info->count = list_count;

    return(list_count);
  }
#endif /* !POWDERN_DECL */

#line 10398 "D1A.c"

/* Shared user declarations for all components 'Isotropic_Sqw'. */
#line 267 "/usr/local/lib/mcstas/samples/Isotropic_Sqw.comp"

#ifndef ISOTROPIC_SQW
#define ISOTROPIC_SQW $Revision: 1.74 $

/* {j d F2 DW Dd inv2d q F} + { Sq if j == -1}*/
#ifndef Crystallographica
#define Crystallographica { 4,5,7,0,0,0,0,0 }
#define Fullprof          { 4,0,8,0,0,5,0,0 }
#define Undefined         { 0,0,0,0,0,0,0,0 }
#define Lazy              {17,6,0,0,0,0,0,13}
#endif
/* special case for [q,Sq] table */
#define qSq               {-1,0,0,0,0,0,1,0 }


/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2009, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Runtime: share/interoff.h
*
* %Identification
* Written by: Reynald Arnerin
* Date:    Jun 12, 2008
* Release: 
* Version: 
*
* Object File Format intersection header for McStas.
*
*******************************************************************************/

#ifndef INTEROFF_LIB_H
#define INTEROFF_LIB_H "$Revision: 1.4 $"

#ifndef EPSILON
#define EPSILON 10e-13
#endif

//#include <float.h>

#define GEOMVIEW 0
#define buf 256
#define MAX_POL_SIZE 256
#define N_VERTEX_DISPLAYED 5000
#define MAX_INTERSECTION_SIZE 256

/*
typedef struct vertex {
  double x,y,z;
} vertex;
*/
typedef struct intersection {
	MCNUM time;  	//time of the intersection
	Coords v;	//intersection point
	Coords normal;  //normal vector of the surface intersected
	short in_out;	//1 if the ray enters the volume, -1 otherwise
	short edge;	//1 if the intersection is on the boundary of the polygon, and error is possible
} intersection;

typedef struct polygon {
  MCNUM* p; //vertices of the polygon in adjacent order, this way : x1 | y1 | z1 | x2 | y2 | z2 ...
  int npol;  //number of vertex
  Coords normal;
} polygon;

typedef struct off_struct {
    long vtxSize;
    long polySize;
    long faceSize;
    Coords* vtxArray;
    Coords* normalArray;
    unsigned long* faceArray;
} off_struct;

#define F(x,y,z,A,B,C,D)  ( (A)*(x) + (B)*(y) + (C)*(z) + (D) )
#ifndef sign
#define sign(a) ( ((a)<0)?-1:((a)!=0) )
#endif

long off_init(char*, double, double, double, off_struct*);

int  off_intersect(double*, double*, double, double, double, double, double, double, off_struct);

void off_display(off_struct);

#endif

/* end of interoff-lib.h */
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright (C) 1997-2009, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Runtime: share/interoff-lib.c
*
* %Identification
* Written by: Reynald Arnerin
* Date:    Jun 12, 2008
* Origin: ILL
* Release: $Revision: 1.5 $
* Version: McStas X.Y
*
* Object File Format intersection library for McStas.
*
*******************************************************************************/

#ifndef INTEROFF_LIB_H
#include "interoff-lib.h"
#endif

//gives the normal vector of p
void off_normal(Coords* n, polygon p)
{
        //using Newell method  
	int i,j;
	n->x=0;n->y=0;n->z=0;
	for(i = 0, j = p.npol-1; i < p.npol; j = i++)
	{
		MCNUM x1=p.p[3*i],
		       y1=p.p[3*i+1], 
		       z1=p.p[3*i+2];
		MCNUM x2=p.p[3*j],
		       y2=p.p[3*j+1], 
		       z2=p.p[3*j+2];
		// n is the cross product of v1*v2
		n->x += (y1 - y2) * (z1 + z2);
        	n->y += (z1 - z2) * (x1 + x2);
        	n->z += (x1 - x2) * (y1 + y2);
	}
}


//based on http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
//return 0 if the vertex is out
//	  1 if it is in
//	 -1 if on the boundary
int off_pnpoly(polygon p, Coords v)
{
      int i, j, c = 0;
      MCNUM minx=FLT_MAX,maxx=-FLT_MAX,miny=FLT_MAX,maxy=-FLT_MAX,minz=FLT_MAX,maxz=-FLT_MAX;
      MCNUM rangex,rangey,rangez;

      int pol2dx,pol2dy;			    //2d restriction of the poly
      MCNUM x=v.x,y=v.y;


      //take the most relevant 2D projection (prevent from instability)
      for(i=0;i<p.npol;++i)
      {
	      if(p.p[3*i]<minx)minx=p.p[3*i];
	      if(p.p[3*i]>maxx)maxx=p.p[3*i];
	      if(p.p[3*i+1]<miny)miny=p.p[3*i+1];
	      if(p.p[3*i+1]>maxy)maxy=p.p[3*i+1];
	      if(p.p[3*i+2]<minz)minz=p.p[3*i+2];
	      if(p.p[3*i+2]>maxz)maxz=p.p[3*i+2];	
      }
      rangex=maxx-minx;
      rangey=maxy-miny;
      rangez=maxz-minz;

      pol2dx=0;
      pol2dy=1;
      if(rangex<rangez)
      {
	      if(rangex<rangey) {
	        pol2dx=2;		
          x=v.z;
        } else {
		      pol2dy=2;
          y=v.z;
        }
      }
      else if(rangey<rangez) {
	      pol2dy=2;
        y=v.z;	  
      }
 
      //trace rays and test number of intersection
      for (i = 0, j = p.npol-1; i < p.npol; j = i++) {
        if (((((p.p[3*i+pol2dy])<=y) && (y<(p.p[3*j+pol2dy]))) ||
             (((p.p[3*j+pol2dy])<=y) && (y<(p.p[3*i+pol2dy])))) &&
            (x < ( (p.p[3*j+pol2dx] - p.p[3*i+pol2dx]) * (y - p.p[3*i+pol2dy]) 
                 / (p.p[3*j+pol2dy] - p.p[3*i+pol2dy]) + p.p[3*i+pol2dx]) ))	
          c = !c;

	      if (((fabs(p.p[3*i+pol2dy]-y)<=EPSILON) || ((fabs(p.p[3*j+pol2dy]-y)<=EPSILON))) &&
            fabs(x -((p.p[3*j+pol2dx] - p.p[3*i+pol2dx]) * (y - p.p[3*i+pol2dy]) 
              / (p.p[3*j+pol2dy] - p.p[3*i+pol2dy]) + p.p[3*i+pol2dx])) < EPSILON)
	      {
		      //the point lies on the edge
		      c=-1;
		      break;
	      }
      }
      //free(polx);
      //free(poly);

      return c;
}

//gives the intersection vertex between ray [a,b) and polygon p and its parametric value on (a b)
//based on http://geometryalgorithms.com/Archive/algorithm_0105/algorithm_0105.htm
int off_intersectPoly(intersection *inter, Coords a, Coords b, polygon p)
{
  //direction vector of [a,b]
  Coords dir;
  dir.x = (b.x-a.x);
  dir.y = (b.y-a.y);
  dir.z = (b.z-a.z);
  
  //the normal vector to the polygon
  Coords normale=p.normal;
  //off_normal(&normale, p);       
  
  //direction vector from a to a vertex of the polygon
  Coords w0;
  w0.x = (a.x-p.p[0]);
  w0.y = (a.y-p.p[1]);
  w0.z = (a.z-p.p[2]);

  //scalar product
  MCNUM nw0 = -scalar_prod(normale.x,normale.y,normale.z,w0.x,w0.y,w0.z);
  MCNUM ndir = scalar_prod(normale.x,normale.y,normale.z,dir.x,dir.y,dir.z);
  if (fabs(ndir) < EPSILON)          // ray is parallel to polygon plane
  {     
    if (nw0 == 0)                // ray lies in polygon plane (infinite number of solution)
        return 0;
    else return 0;             // ray disjoint from plane (no solution)
  }

  // get intersect point of ray with polygon plane
  inter->time = nw0 / ndir;            //parametric value the point on line (a,b)

	//printf("----------t=%f",*t);
  inter->v.x = a.x + inter->time * dir.x;// intersect point of ray and plane
  inter->v.y = a.y + inter->time * dir.y;//
  inter->v.z = a.z + inter->time * dir.z;//
        
	int res=off_pnpoly(p,inter->v);
	
	inter->edge=(res==-1);
	if(ndir<0)
		inter->in_out=1;		//the negative dot product means we enter the surface
	else
		inter->in_out=-1;
	
	inter->normal=p.normal;

	return res;	//true if the intersection point lies inside the poly
}



/*reads the indexes at the beginning of the off file as this :
line 1  OFF
line 2  nbVertex nbFaces nbEdges
*/
long off_getBlocksIndex(char* filename, long* vtxIndex, long* vtxSize, long* faceIndex, long* polySize )
{
  if (!filename)  return(0);
  if (strlen(filename) == 0) return (0);
  if (!strcmp(filename,"NULL") || !strcmp(filename,"0"))  return(0);
  FILE* f = fopen(filename,"r");
  if(!f) {
    char mc_rt_path[256];
    char mc_rt_dir[256];

    if (!f)
    {
      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, filename);
      f = fopen(mc_rt_path, "r");
    }
    if (!f)
    {
      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, filename);
      f = fopen(mc_rt_path, "r");
    }
    if(!f)
    {
      fprintf(stderr, "Error: Could not open input file '%s' (interoff/off_getBlocksIndex)\n", filename);
      return (0);
    }
  }
  
  printf("Loading file: %s\n",filename);
	char line[buf];
 	*vtxIndex=0;
  *vtxSize=0;
  *faceIndex=0;
  fgets(line,buf , f);// line 1 = "OFF"

	if(strncmp(line,"OFF",3))
	{
		fprintf(stderr, "Error: %s is probably not an OFF or NOFF file (interoff/off_getBlocksIndex)\n",filename);
		return(0);
	}

  *vtxIndex+= strlen(line);
        
	do
	{
		fgets(line,buf , f);
		*vtxIndex+= strlen(line);
	}
	while(line[0]=='#');
  
  //line = nblines of vertex,faces and edges arrays
  sscanf(line,"%lu %lu",vtxSize,polySize);

  *faceIndex=*vtxIndex;
  int i;
  for(i=0;i<*vtxSize;)
  {                              
    fgets(line,buf,f);
    *faceIndex+=strlen(line); 
    if(line[0]!='#')i++;               
  }
 
  fclose(f);
  return(*vtxIndex);
}


//gives the equations of 2 perpandicular planes of [ab]
void off_init_planes(Coords a, Coords b, 
  MCNUM* A1, MCNUM* C1, MCNUM* D1, MCNUM *A2, MCNUM* B2, MCNUM* C2, MCNUM* D2)
{
	//direction vector of [a b]	
	Coords dir={b.x-a.x, b.y-a.y, b.z-a.z};
	
	//the plane parallel to the 'y' is computed with the normal vector of the projection of [ab] on plane 'xz'	
	*A1=dir.z;
	*C1=-dir.x;
	if(*A1!=0 || *C1!=0)
		*D1=-(a.x)**A1-(a.z)**C1;
	else
	{
		//the plane do not suppoindPolyrt the vector, take the one parallel to 'z''
		*A1=1;
		//B1=dir.x=0
		*D1=-(a.x);
	}
	//the plane parallel to the 'x' is computed with the normal vector of the projection of [ab] on plane 'yz'	
	*B2=dir.z;
	*C2=-dir.y;
	*A2=0;
	if(*B2==0 && *C2==0)
	{
		//the plane do not support the vector, take the one parallel to 'z'
		*B2=1;
		//B1=dir.x=0
		*D2=-(a.y);
	}
	else if(dir.z==0)
	{
		//the planes are the same, take the one parallel to 'z'
		*A2=dir.y;
		*B2=-dir.x;
		*D2=-(a.x)**A2-(a.y)**B2; 
	}
	else
		*D2=-(a.y)**B2-(a.z)**C2;

	//printf("F1=%f\n",F(b,*A1,0,*C1,*D1));
	//printf("F2=%f\n",F(b,*A2,*B2,*C2,*D2));
}


int off_clip_3D_mod(intersection* t, Coords a, Coords b, 
  Coords* vtxArray, unsigned long vtxSize, unsigned long* faceArray, 
  unsigned long faceSize, Coords* normalArray)
{
	MCNUM A1, C1, D1, A2, B2, C2, D2;			//perpendicular plane equations to [a,b]
	off_init_planes(a, b, &A1, &C1, &D1, &A2, &B2, &C2, &D2);	//	
	
	int t_size=0;
	//unsigned long vtxSize=vtxTable.rows, faceSize=faceTable.columns;	//Size of the corresponding tables
	char sg[vtxSize];	//array telling if vertex is left or right of the plane
	MCNUM popol[3*MAX_POL_SIZE];
	unsigned long i,indPoly;
	for(i=0; i < vtxSize;++i)
	{
		sg[i]=sign(F(vtxArray[i].x,vtxArray[i].y,vtxArray[i].z,A1,0,C1,D1));
	}
	
	//exploring the polygons :
	i=0;indPoly=0;
	while(i<faceSize)
	{	
		polygon pol;
		pol.npol=faceArray[i];					//nb vertex of polygon
				
		pol.p=popol;
		unsigned long indVertP1=faceArray[++i];			//polygon's first vertex index in vtxTable
		int j=1;
		while(j<pol.npol)
		{
									//polygon's j-th vertex index in vtxTable
			if(sg[indVertP1]!=sg[faceArray[i+j]])		//if the plane intersect the polygon
				break;	

			++j;
		}
		
		if((j<pol.npol))					//ok, let's test with the second plane
		{	
			char sg1=sign(F(vtxArray[indVertP1].x,vtxArray[indVertP1].y,vtxArray[indVertP1].z,A2,B2,C2,D2));//tells if vertex is left or right of the plane	
			
			j=1;		
			while(j<pol.npol)
			{
				//unsigned long indVertPi=faceArray[i+j];	//polyg's j-th vertex index in vtxTable		
				Coords vertPi=vtxArray[faceArray[i+j]];
				if(sg1!=sign(F(vertPi.x,vertPi.y,vertPi.z,A2,B2,C2,D2)))//if the plane intersect the polygon
					break;
				++j;
			}
			if(j<pol.npol)
			{	
				if(t_size>MAX_INTERSECTION_SIZE)
				{
					fprintf(stderr, "Error: number of intersection exceeded (%d)\n", MAX_INTERSECTION_SIZE);
      					return (0);
				}
				//both planes intersect the polygon, let's find the intersection point
				//our polygon :
				int k;
				for(k=0;k<pol.npol;++k)
				{	
					Coords vertPk=vtxArray[faceArray[i+k]];
					pol.p[3*k]=vertPk.x;
					pol.p[3*k+1]=vertPk.y;
					pol.p[3*k+2]=vertPk.z;
				}
				pol.normal=normalArray[indPoly];	
				intersection x;
				if(off_intersectPoly(&x, a, b, pol))
				{						
					t[t_size++]=x;
				}					
			}	
		}
		i+=pol.npol;
		indPoly++;
	}
	return t_size;
}



int off_compare (void const *a, void const *b)
{
   intersection const *pa = a;
   intersection const *pb = b;

   return sign(pa->time - pb->time);
}

//given an array of intesction throw those which appear several times
//returns 1 if there is a possibility of error
int off_cleanDouble(intersection* t, int* t_size)
{
	int i=1;
	intersection prev;
	prev=t[0];
	while(i<*t_size)	
	{
		int j=i;
		//for each intersection with the same time
		while(j<*t_size && fabs(prev.time-t[j].time)<EPSILON)
		{
			//if the intersection is the exact same erase it
			if(prev.in_out==t[j].in_out)
			{
				int k;			
				for(k=j+1;k<*t_size;++k)
				{
					t[k-1]=t[k];
				}
				*t_size-=1;	
			}
			else
				++j;		
		}
		prev=t[i];			
		++i;
				
	}
	return 1;
}


//given an array of intesction throw those which enter and exit in the same time
//Meaning the ray passes very close to the volume
//returns 1 if there is a possibility of error
int off_cleanInOut(intersection* t, int* t_size)
{
	int i=1;
	intersection prev;
	prev=t[0];
	while(i<*t_size)	
	{
		//if two intersection have the same time but one enters and the other exits erase both
		//(such intersections must be adjacent in the array : run off_cleanDouble before)
		if(fabs(prev.time-t[i].time)<EPSILON && prev.in_out!=t[i].in_out)
		{
			int j;		
			for(j=i+1;j<*t_size;++j)
			{
				t[j-2]=t[j];
			}
			*t_size-=2;
			prev=t[i-1];			
		}
		else
		{
			prev=t[i];			
			++i;
		}		
	}
	return 1;
}

/* PUBLIC functions ******************************************************** */

long off_init(	char *offfile, double xwidth, double yheight, double zdepth, off_struct* datas)
{
  //datas to be initialized
  long faceSize;
  long vtxSize;
  long polySize;	 
  Coords* vtxArray;
  Coords* normalArray;
  unsigned long* faceArray;

  t_Table vtxTable, faceTable;
  long vtxIndex, faceIndex;

  double minx=FLT_MAX,maxx=-FLT_MAX,miny=FLT_MAX,maxy=-FLT_MAX,minz=FLT_MAX,maxz=-FLT_MAX;

  // get the indexes
  if (off_getBlocksIndex(offfile,&vtxIndex,&vtxSize,&faceIndex, &polySize) <=0) 
    return(0);
  printf("  Number of polygons: %ld\n",polySize);
 
  //read vertex table = [x y z | x y z | ...]
  Table_Read_Offset(&vtxTable, offfile, 0, &vtxIndex, vtxSize);

  //read face table = [nbvertex v1 v2 vn nbvertex v1 v2 vn ...]
  Table_Read_Offset(&faceTable, offfile, 0, &faceIndex, 0);

  //initialize Arrays
  faceSize=faceTable.columns;
  vtxArray=malloc(vtxSize*sizeof(Coords));
  normalArray=malloc(polySize*sizeof(Coords));

  long i,j;
  for(i=0;i<vtxSize;++i)
  {
	  vtxArray[i].x=Table_Index(vtxTable, i,0);
	  vtxArray[i].y=Table_Index(vtxTable, i,1);
	  vtxArray[i].z=Table_Index(vtxTable, i,2);
	
	  //bounding box
	  if(vtxArray[i].x<minx)minx=vtxArray[i].x;
    if(vtxArray[i].x>maxx)maxx=vtxArray[i].x;
	  if(vtxArray[i].y<miny)miny=vtxArray[i].y;
	  if(vtxArray[i].y>maxy)maxy=vtxArray[i].y;
	  if(vtxArray[i].z<minz)minz=vtxArray[i].z;
	  if(vtxArray[i].z>maxz)maxz=vtxArray[i].z;
  }

        //resizing and repositioning params
  double centrex=(minx+maxx)*0.5,
  centrey=(miny+maxy)*0.5,
  centrez=(minz+maxz)*0.5;
  
  double rangex=-minx+maxx,
  rangey=-miny+maxy,
  rangez=-minz+maxz;

  double ratiox=1,ratioy=1,ratioz=1;

  if(xwidth)
  {
    ratiox=xwidth/rangex;
    ratioy=ratiox;
    ratioz=ratiox;
  }

  if(yheight)
  {
	  ratioy=yheight/rangey;
	  if(!xwidth)  ratiox=ratioy;
	  ratioz=ratioy;
  }

  if(zdepth)
  {
	  ratioz=zdepth/rangez;
	  if(!xwidth)  ratiox=ratioz;
	  if(!yheight) ratioy=ratioz;
  }
	
   

  //center  and resize the object 
  for(i=0;i<vtxSize;++i)
  {
	  vtxArray[i].x=(vtxArray[i].x-centrex)*ratiox;
	  vtxArray[i].y=(vtxArray[i].y-centrey)*ratioy;
	  vtxArray[i].z=(vtxArray[i].z-centrez)*ratioz;        
  }


  //table_read create a table on one line if the number of columns is not constant, so there are 2 cases :
  if(faceTable.rows==1)
  {
	  //copy the table in a 1-row array
	  faceArray=malloc(faceSize*sizeof(unsigned long));
	  for(i=0;i<faceSize;++i)
	  {
		  faceArray[i]=Table_Index(faceTable, 0, i);
	  }
  }
  else
  {
	  //read each row of the table and concatenate in a 1-row array
	  faceArray=malloc(polySize*(faceSize)*sizeof(unsigned long));
	  for(i=0;i<polySize;++i)
	  {
		  for(j=0;j<faceSize;++j)
			  faceArray[i*(faceSize)+j]=Table_Index(faceTable, i, j);
	  }
	  faceSize*=polySize;	
  }

  //precomputes normals
  long indNormal=0;//index in polyArray
  i=0;		//index in faceArray
  while(i<faceSize)
  {	
	  int nbVertex=faceArray[i];//nb of vertices of this polygon
	  double vertices[3*nbVertex];
	  int j;
	
	  for(j=0;j<nbVertex;++j)
	  {
		  unsigned long indVertPj=faceArray[i+j+1];
		  vertices[3*j]=vtxArray[indVertPj].x;
		  vertices[3*j+1]=vtxArray[indVertPj].y;
		  vertices[3*j+2]=vtxArray[indVertPj].z;
	  }
	  
	  polygon p;		
	  p.p=vertices;
	  p.npol=nbVertex;
	  off_normal(&(p.normal),p);
		
	  normalArray[indNormal]=p.normal;
	
	  i+=nbVertex+1;
	  indNormal++;	
	
  }

  
  if(ratiox!=ratioy || ratiox!=ratioz || ratioy!=ratioz)
	  printf("Warning: Aspect ratio of the sample were modified.\n"
	         "         If you want to keep the originial proportions, specifiy only one of the dimensions.\n");
  printf("  Bounding box dimensions:\n");
  printf("    Length=%f (%.3f%%)\n",rangex*ratiox,ratiox*100);
  printf("    Width= %f (%.3f%%)\n",rangey*ratioy,ratioy*100);
  printf("    Depth= %f (%.3f%%)\n",rangez*ratioz,ratioz*100);

  datas->vtxArray=vtxArray;
  datas->normalArray=normalArray;
  datas->faceArray=faceArray;
  datas->vtxSize=vtxSize;
  datas->polySize=polySize;
  datas->faceSize=faceSize;
}


int off_intersect(double* t0, double* t3, double x, double y, double z, double vx, double vy, double vz, off_struct datas )
{
    intersection t[MAX_INTERSECTION_SIZE];
    Coords A={x, y, z};
    Coords B={x+vx, y+vy, z+vz};
    int t_size=off_clip_3D_mod(t, A, B,
      datas.vtxArray, datas.vtxSize, datas.faceArray, datas.faceSize, datas.normalArray );
    qsort(t,t_size,sizeof(intersection),off_compare);
    off_cleanDouble(t,&t_size);
    off_cleanInOut(t,&t_size);

    if(t_size>1)	
    {		
	    *t0 = t[0].time;
	    *t3 = t[1].time;
	    return t_size;
    }
    return 0;
}

void off_display(off_struct datas)
{
	int step=ceil((double)datas.vtxSize/N_VERTEX_DISPLAYED);
	unsigned int i;
	for (i=0; i<datas.vtxSize-1; i+=step) {
		double x1,y1,z1,x2,y2,z2;
		x1 = datas.vtxArray[i].x;
		y1 = datas.vtxArray[i].y;
		z1 = datas.vtxArray[i].z;
		x2 = datas.vtxArray[i].x+.0001;
		y2 = datas.vtxArray[i].y+.0001;
		z2 = datas.vtxArray[i].z+.0001;

		mcdis_line(x1,y1,z1,x2,y2,z2);
	}
}
/* end of interoff-lib.c */



/* For the density of states */
struct Sqw_D_struct
{
  double omega;    /* omega value for the data block */
  double value;        /* intensity for the current SW block */
  double cumul_proba;  /* cumulated intensity (between 0 and 1) */
};

/* For the Q(w) probabilities */
struct Sqw_Q_struct
{
   double Q;           /* omega value for the data block */
   double value;       /* normalized probability for the current SW block */
   double cumul_proba; /* normalized cumulated probability */
};

struct Sqw_Data_struct /* contains normalized Sqw data for probabilities */
{
  struct Sqw_D_struct  *SW;     /* P(w)  = density of states */
  struct Sqw_Q_struct **SQW;    /* P(Q|w)= probability of each Q with w */

  long  *SW_lookup;
  long **QW_lookup;
  double*Sq;  /* S(q) = \int_w S(q,w) */
  double*iqSq; /* \int q S(q) dq */
  t_Table Sqw;
  long   nb_q;
  long   nb_w; /* length of q and w vectors/axes on restricted range */
  long   nb_q_data; /* on total range */
  long   nb_w_data;
  double q_min, q_max;
  double w_min, w_max;
  long   lookup_length;
  char   filename[80];
  double intensity;
  double intensity_total;
  double alpha; /* ratio for S(q,w) normalization */
};

struct Sqw_sample_struct { /* global parameters gathered as a structure */
  char   compname[256];

  struct Sqw_Data_struct Data_inc;
  struct Sqw_Data_struct Data_coh;

  double s_abs, s_coh, s_inc;
  double my_s;
  double my_a_v;
  double rho;
  double T2E;
  double sqSE2K;
  int    maxloop;
  int    minevents;
  long   neutron_removed;
  long   neutron_enter;
  long   neutron_pmult;
  long   neutron_exit;
  double Dd, DWfactor;

  double sqw_threshold;

  char   verbose_output;
  int    shape; /* 0:cylinder, 1:box, 2:sphere 3:any shape*/

  double dq, dw; /* q/w transfert */
  char   type; /* interaction type: c(coherent), i(incoherent),
                                  V(isotropic incoherent), t(transmitted) */
  /* store information from the last event */
  double ki_x,ki_y,ki_z,kf_x,kf_y,kf_z;
  double ti, tf;
  double vi, vf;
  double ki, kf;
  double theta;

  double w_max, w_min, q_max, q_min;
  int    column_order[9]; /* column signification */
  double Temperature;
  double sqw_norm;
  char   sqw_auto;
  double mean_scatt;
  double mean_abs;
  double psum_scatt;
  double single;
  double multi;
  double barns;
};

#include <stdio.h>
#include <math.h>

/* sets a Data S(q,w) to 'NULL' */
void Sqw_Data_init(struct Sqw_Data_struct *Sqw_Data)
{
  Sqw_Data->nb_q         =0;
  Sqw_Data->nb_w         =0;
  Sqw_Data->nb_q_data    =0;
  Sqw_Data->nb_w_data    =0;
  Sqw_Data->q_min        =0;
  Sqw_Data->q_max        =0;
  Sqw_Data->w_min        =0;
  Sqw_Data->w_max        =0;
  Sqw_Data->alpha        =0;
  Sqw_Data->lookup_length=100; /* length of lookup tables */
  Sqw_Data->intensity    =0;
  Sqw_Data->intensity_total=0;
  strcpy(Sqw_Data->filename, "");
  Sqw_Data->SW           =NULL;
  Sqw_Data->SQW          =NULL;
  Sqw_Data->SW_lookup    =NULL;
  Sqw_Data->QW_lookup    =NULL;
  Sqw_Data->Sq           =NULL;
  Sqw_Data->iqSq         =NULL;
}

off_struct offdata;

/* gaussian distribution to appply around Bragg peaks in a powder */
double Sqw_powder_gauss(double x, double mean, double rms) {
  return (exp(-((x)-(mean))*((x)-(mean))/(2*(rms)*(rms)))/(sqrt(2*PI)*(rms)));
}

/*****************************************************************************
* Sqw_read_PowderN: Read PowderN data files
*   Returns t_Table array or NULL in case of error
* Used in : Sqw_readfile (1)
*****************************************************************************/
t_Table *Sqw_read_PowderN(struct Sqw_sample_struct *Sqw, t_Table sqwTable)
{
  struct line_data
  {
    double F2;                  /* Value of structure factor */
    double q;                   /* Q vector */
    int j;                      /* Multiplicity */
    double DWfactor;            /* Debye-Waller factor */
    double w;                   /* Intrinsic line width */
  };
  struct line_data *list = NULL;
  double q_count=0, j_count=0, F2_count=0;
  int    mult_count  =0;
  double q_step      =FLT_MAX;
  long   size        =0;
  int    i, index;
  double q_min=0, q_max=0;
  char   flag=0;
  int    list_count=0;
  double q_step_cur;
  char   flag_qSq = 0;

  t_Table *retTable;

  flag_qSq = (Sqw->column_order[8]>0 && Sqw->column_order[6]>0);
  
  if (Sqw->column_order[0] == 4 && Sqw->barns !=0)
    printf("Isotropic_sqw: %s: Powder file probably of type Crystallographica/Fullprof (lau)\n"
           "WARNING:       but F2 unit is set to powder_barns=1 (barns). Intensity might be 100 times too high.\n", 
           Sqw->compname);
  if (Sqw->column_order[0] == 17 && Sqw->barns == 0)
    printf("Isotropic_sqw: %s: Powder file probably of type Lazy Pulver (laz)\n"
           "WARNING:       but F2 unit is set to powder_barns=0 (fm^2). Intensity might be 100 times too low.\n", 
           Sqw->compname);

  size = sqwTable.rows;
  if (Sqw->verbose_output > 0) Table_Info(sqwTable);
  if (Sqw->verbose_output > 0)
    printf("Isotropic_sqw: Converting %ld powder lines from %s into S(q,w) data\n",
        size, sqwTable.filename);
  /* allocate line_data array */
  list = (struct line_data*)malloc(size*sizeof(struct line_data));

  for (i=0; i<size; i++)
    {
      /*      printf("Reading in line %i\n",i);*/
      double j=0, d=0, w=0, DWfactor=0, F2=0, Sq=-1, q=0;
      int index;

      if (Sqw->Dd >= 0)      w         = Sqw->Dd;
      if (Sqw->DWfactor > 0) DWfactor  = Sqw->DWfactor;

      /* get data from table using columns {j d F2 DW Dd inv2d q} + { Sq }*/
      /* column indexes start at 1, thus need to substract 1 */
      if (Sqw->column_order[0]>0)
        j = Table_Index(sqwTable, i, Sqw->column_order[0]-1);
      if (Sqw->column_order[1]>0)
        d = Table_Index(sqwTable, i, Sqw->column_order[1]-1);
      if (Sqw->column_order[2]>0)
        F2 = Table_Index(sqwTable, i, Sqw->column_order[2]-1);
      if (Sqw->column_order[3]>0)
        DWfactor = Table_Index(sqwTable, i, Sqw->column_order[3]-1);
      if (Sqw->column_order[4]>0)
        w = Table_Index(sqwTable, i, Sqw->column_order[4]-1);
      if (Sqw->column_order[5]>0)  {
        d = Table_Index(sqwTable, i, Sqw->column_order[5]-1); if (d) d = 1/d/2; }
      if (Sqw->column_order[6]>0)
        q = Table_Index(sqwTable, i, Sqw->column_order[6]-1);
      if (Sqw->column_order[7]>0 && !F2)
        {F2= Table_Index(sqwTable, i, Sqw->column_order[7]-1); F2 *= F2;}

      if (Sqw->column_order[8]>0)
        Sq= Table_Index(sqwTable, i, Sqw->column_order[8]-1);

      if (q > 0 && Sq >= 0) F2 = Sq;
      if (d > 0 && q <= 0)  q = 2*PI/d;

      /* assign and check values */
      j = (j > 0 ? j : 0);
      if (flag_qSq) j=1;
      DWfactor = (DWfactor > 0 ? DWfactor : 1);
      w = (w>0 ? w : 0);
      F2 = (F2 >= 0 ? F2 : 0);
      d = (q > 0 ? 2*PI/d : 0);
      if (j == 0 || d == 0 || q == 0) {
        printf("Isotropic_sqw: %s: Warning: line %i has invalid definition\n"
               "         (mult=0 or q=0 or d=0)\n", Sqw->compname, i);
        continue;
      }
      list[list_count].j = j;
      list[list_count].q = q;
      list[list_count].DWfactor = DWfactor;
      list[list_count].w = w;
      list[list_count].F2= F2; /* or S(q) if flag_qSq */

      if (q_max < d) q_max = q;
      if (q_min > d) q_min = q;
      if (list_count > 1) {
        q_step_cur = fabs(list[list_count].q - list[list_count-1].q);
        if (q_step_cur > 1e-5 && (!q_step || q_step_cur < q_step))
         q_step = q_step_cur;
      }

      /* adjust multiplicity if j-column + multiple d-spacing lines */
      /* if  d = previous d, increase line duplication index */
      if (!q_count)     q_count = q;
      if (!j_count)     j_count = j;
      if (!F2_count)    F2_count= F2;
      if (fabs(q_count-q) < 0.0001*fabs(q)
       && fabs(F2_count-F2) < 0.0001*fabs(F2) && j_count == j) {
       mult_count++; flag=0; }
      else flag=1;
      if (i == size-1) flag=1;
      /* else if d != previous d : just passed equivalent lines */
      if (flag) {
        if (i == size-1) list_count++;
      /*   if duplication index == previous multiplicity */
      /*      set back multiplicity of previous lines to 1 */
        if (Sqw->verbose_output > 1 && (mult_count == list[list_count-1].j
        || (mult_count == list[list_count].j && i == size-1))) {
          printf("Isotropic_Sqw: %s: Setting multiplicity to 1 for lines [%i:%i]\n"
                  "         (d-spacing %g is duplicated %i times)\n",
            Sqw->compname, list_count-mult_count, list_count-1, list[list_count-1].q, mult_count);
          for (index=list_count-mult_count; index<list_count; list[index++].j = 1);
          mult_count   = 1;
          q_count = q;
          j_count = j;
          F2_count= F2;
        }
        if (i == size-1) list_count--;
        flag=0;
      }
      list_count++;
    } /* end for */

  /* now builds new Table_Array to continue with Sqw_readfile */
  if (q_max == q_min || !q_step) return(NULL);
  if (!flag_qSq)
    size = 3*(q_max - q_min)/q_step; /* set a default of 3 q values per line */
  else size = list_count;

  if (Sqw->verbose_output > 0)
    printf("Isotropic_sqw: q range [%g:%g], creating %li elements vector\n",
        q_min, q_max, size);

  retTable = (t_Table*)calloc(4, sizeof(t_Table));
  if (!retTable) printf("Isotropic_Sqw: ERROR: Cannot allocate PowderN->Sqw table.\n");
  else {
    char *header;
    if (!Table_Init(&retTable[0], size, 1))
      { printf("Isotropic_Sqw: ERROR Cannot allocate q-axis [%li] from Powder lines.\n", size); return(NULL); }
    if (!Table_Init(&retTable[1], 1, 1))
      { printf("Isotropic_Sqw: ERROR Cannot allocate w-axis from Powder lines.\n"); return(NULL); }
    if (!Table_Init(&retTable[2], size, 1))
      { printf("Isotropic_Sqw: ERROR Cannot allocate Sqw [%li] from Powder lines.\n", size); return(NULL); }
    Table_Init(&retTable[3], 0,0);

    header = malloc(64); if (header)
    { retTable[0].header = header; strcpy(retTable[0].header, "q"); }
    header = malloc(64); if (header)
    { retTable[1].header = header; strcpy(retTable[1].header, "w"); }
    header = malloc(64); if (header)
    { retTable[2].header = header; strcpy(retTable[2].header, "Sqw"); }
    for (i=0; i < 4; i++) {
      retTable[i].array_length = 3;
      retTable[i].block_number = i+1;
    }
    if (!flag_qSq)
      for (i=0; i<size; i++)
        retTable[0].data[i]  = q_min + i*(q_max - q_min)/size;
    for (i=0; i<list_count; i++) { /* loop on each Bragg peak */
      double peak_qmin, peak_qmax,factor,q;
      if (list[i].w > 0 && !flag_qSq) {
        peak_qmin = list[i].q*(1 - list[i].w*3);
        peak_qmax = list[i].q*(1 + list[i].w*3);
      } else { /* Dirac peak, no width */
        peak_qmin = peak_qmax = list[i].q;
      }
      /* S(q) intensity is here */
      factor = list[i].j*(list[i].DWfactor ? list[i].DWfactor : 1)
               *Sqw->rho*PI/2
               /(Sqw->type == 'c' ? Sqw->s_coh : Sqw->s_inc)*list[i].F2/list[i].q;
      if (Sqw->barns) factor *= 100;
      for (q=peak_qmin; q <= peak_qmax; q += q_step) {
        index = (long)floor(size*(q - q_min)/(q_max - q_min));
        if (index < 0) index=0;
        else if (index >= size) index = size-1;
        if (flag_qSq) {
          retTable[2].data[index] += list[i].F2;
          retTable[0].data[index]  = list[i].q;
        } else {
          if (list[i].w <=0 || list[i].w*q < q_step) /* step function */
            retTable[2].data[index] += factor/q_step;
          else /* gaussian */
            retTable[2].data[index] += factor
                  * Sqw_powder_gauss(q, list[i].q, list[i].w*list[i].q);
        }
      }
    } /* end for i */
    Table_Stat(&retTable[0]); Table_Stat(&retTable[1]); Table_Stat(&retTable[2]);
    Sqw->sqw_norm = 0; /* F2 are normalized already */
  }

  return(retTable);
} /* Sqw_read_PowderN */

/*****************************************************************************
*  Sqw_search_root: Search for the roots of A*x**2 + B*x + C
*   The roots are returned as x1 and x2
* Used in : TRACE (1)
*****************************************************************************/
int Sqw_search_root(double A, double B, double C,
             double *x1, double *x2)
{
  double delta, sqrtdelta, inv_2A;
  int    OK = 0;

  if (fabs(A) < 1E-10) {
    if (B) {  *x1 = -C/B; *x2 = *x1; OK=3; }
    return 1;
  } else {
    delta = B*B - 4*A*C;
    if (delta < 0) {
      /* Imaginary roots */
      OK=0;
    } else {
      /* Real roots */
      sqrtdelta = sqrt(delta);
      inv_2A = 1/(2*A);
      *x1 = inv_2A*(-B - sqrtdelta);
      *x2 = inv_2A*(-B + sqrtdelta);
      OK = 1;
    }
    return(OK);
  }
}

/*****************************************************************************
*  Sqw_search_SW: For a given random number 'randnum', search for the bin
*   containing  the corresponding Sqw->SW
* Used in : TRACE (1)
*****************************************************************************/
int Sqw_search_SW(struct Sqw_Data_struct Sqw, double randnum)
{
  int i=0;

  if (randnum <0) randnum=0;
  if (randnum >1) randnum=1;

  if (Sqw.nb_w == 1) return(0);
  /* benefit from fast lookup table if exists */
  if (Sqw.SW_lookup) {
    i = Sqw.SW_lookup[(long)floor(randnum*Sqw.lookup_length)]-1;
    if (i<0) i=0;
  }

  while (i < Sqw.nb_w && (&(Sqw.SW[i]) != NULL) && (randnum > Sqw.SW[i].cumul_proba))
      i++;
  if (i >= Sqw.nb_w) i = Sqw.nb_w;

  if (&(Sqw.SW[i]) == NULL)
  {
      fprintf(stderr, "Isotropic_Sqw: Warning: No corresponding value in the SW. randnum too big.\n");
      fprintf(stderr, "  i=%i ; randnum=%f ; Sqw.SW[i-1].cumul_proba=%f (Sqw_search_SW)\n",
            i, randnum, Sqw.SW[i-1].cumul_proba);
      return i-1;
  }
  else
      return (i < Sqw.nb_w ? i : Sqw.nb_w-1);
}

/*****************************************************************************
*  Sqw_search_Q_proba_per_w: For a given random number randnum, search for
*   the bin containing the corresponding Sqw.SW in the Q probablility grid
* Used in : TRACE (1)
*****************************************************************************/
int Sqw_search_Q_proba_per_w(struct Sqw_Data_struct Sqw,
                             double randnum, int index)
{
  int i=0;
  /* benefit from fast lookup table if exists */
  if (Sqw.QW_lookup && Sqw.QW_lookup[index]) {
    i = Sqw.QW_lookup[index][(long)floor(randnum*Sqw.lookup_length)]-1;
    if (i<0) i=0;
  }

  while (i < Sqw.nb_q && (&(Sqw.SQW[index][i]) != NULL)
    && (randnum > Sqw.SQW[index][i].cumul_proba)) {
      i++;
  }

  if (&(Sqw.SQW[index][i]) == NULL)
    return -1;
  else
    return i;
}

/*****************************************************************************
* Sqw_readfile: Read Sqw data files
*   Returns Sqw_Data_struct or NULL in case of error
* Used in : Sqw_init (2)
*****************************************************************************/
struct Sqw_Data_struct *Sqw_readfile(
  struct Sqw_sample_struct *Sqw, char *file, struct Sqw_Data_struct *Sqw_Data)
{

  t_Table *Table_Array= NULL;
  t_Table *newTable;
  long     nblocks     = 0;

  t_Table  Sqw_restrict;

  long     i, j;
  char     flag=1; /* exit_flag */
  double   q, w, val, sum;
  double   mat_density=0, mat_weight=0, mat_at_nb=1;
  double   iq2Sq=1, iqSq=0;
  long    *SW_lookup;
  long   **QW_lookup;
  char   **parsing;
  double   q_min_data, q_max_data;
  double   w_min_data, w_max_data;
  long     nb_q_data=0, nb_w_data=0;

  /* setup default */
  if (Sqw->sqw_auto < 2) Sqw_Data_init(Sqw_Data);
  else { /* we are re-optimizing range */
    if (Sqw_Data->Sq) free(Sqw_Data->Sq);
    if (Sqw_Data->SW) free(Sqw_Data->SW);

    if (Sqw_Data->SQW) {
      for (j=0; j < (Sqw_Data->nb_w) ; j++)
        if (Sqw_Data->SQW[j]) free(Sqw_Data->SQW[j]);
      free(Sqw_Data->SQW);
    }
    if (Sqw_Data->SW_lookup) free(Sqw_Data->SW_lookup);
    if (Sqw_Data->QW_lookup) {
      for (j=0; j < (Sqw_Data->nb_w) ; j++)
        if (Sqw_Data->QW_lookup[j]) free(Sqw_Data->QW_lookup[j]);
      free(Sqw_Data->QW_lookup);
    }
    Sqw_Data->SW_lookup = NULL;
    Sqw_Data->QW_lookup = NULL;
    Sqw_Data->Sq        = NULL;
    Sqw_Data->SW        = NULL;
    Sqw_Data->SQW       = NULL;
  }

  if (!file || !strlen(file) || !strcmp(file, "NULL") || !strcmp(file, "0")) return(Sqw_Data);
  Table_Array = Table_Read_Array(file, &nblocks);
  strncpy(Sqw_Data->filename, file, 80);
  if (!Table_Array) return(NULL);

  /* parsing of header */
  parsing = Table_ParseHeader(Table_Array[0].header,
    "Vc","V_0",
    "sigma_abs","sigma_a ",
    "sigma_inc","sigma_i ",
    "column_j", /* 6 */
    "column_d",
    "column_F2",
    "column_DW",
    "column_Dd",
    "column_inv2d", "column_1/2d", "column_sintheta_lambda",
    "column_q", /* 14 */
    "sigma_coh","sigma_c ",
    "Temperature",
    "column_Sq",
    "column_F ", /* 19 */
    "V_rho",
    "density",
    "weight",
    "nb_atoms",
    NULL);
  if (parsing) {
    if (parsing[0] && !Sqw->rho)   Sqw->rho    =1/atof(parsing[0]);
    if (parsing[1] && !Sqw->rho)   Sqw->rho    =1/atof(parsing[1]);
    if (parsing[2] && !Sqw->s_abs) Sqw->s_abs  =  atof(parsing[2]);
    if (parsing[3] && !Sqw->s_abs) Sqw->s_abs  =  atof(parsing[3]);
    if (parsing[4] && !Sqw->s_inc) Sqw->s_inc  =  atof(parsing[4]);
    if (parsing[5] && !Sqw->s_inc) Sqw->s_inc  =  atof(parsing[5]);
    if (parsing[6])                   Sqw->column_order[0]=atoi(parsing[6]);
    if (parsing[7])                   Sqw->column_order[1]=atoi(parsing[7]);
    if (parsing[8])                   Sqw->column_order[2]=atoi(parsing[8]);
    if (parsing[9])                   Sqw->column_order[3]=atoi(parsing[9]);
    if (parsing[10])                  Sqw->column_order[4]=atoi(parsing[10]);
    if (parsing[11])                  Sqw->column_order[5]=atoi(parsing[11]);
    if (parsing[12])                  Sqw->column_order[5]=atoi(parsing[12]);
    if (parsing[13])                  Sqw->column_order[5]=atoi(parsing[13]);
    if (parsing[14])                  Sqw->column_order[6]=atoi(parsing[14]);
    if (parsing[15] && !Sqw->s_coh)   Sqw->s_coh=atof(parsing[15]);
    if (parsing[16] && !Sqw->s_coh)   Sqw->s_coh=atof(parsing[16]);
    if (parsing[17] && !Sqw->Temperature) Sqw->Temperature=atof(parsing[17]);
    if (parsing[18])                  Sqw->column_order[8]=atoi(parsing[18]);
    if (parsing[19])                  Sqw->column_order[7]=atoi(parsing[19]);
    if (parsing[20] && !Sqw->rho)     Sqw->rho    =atof(parsing[20]);
    if (parsing[21] )     mat_density =atof(parsing[21]);
    if (parsing[22] )     mat_weight  =atof(parsing[22]);
    if (parsing[23] )     mat_at_nb   =atof(parsing[23]);
    for (i=0; i<=23; i++) if (parsing[i]) free(parsing[i]);
    free(parsing);
  }

  if (!Sqw->rho && mat_density > 0 && mat_weight > 0 && mat_at_nb > 0) {
    /* molar volume [cm^3/mol] = weight [g/mol] / density [g/cm^3] */
    /* atom density per Angs^3 = [mol/cm^3] * N_Avogadro *(1e-8)^3 */
    Sqw->rho = mat_density/mat_weight/1e24*6.02214199e23/mat_at_nb;
    if (Sqw->verbose_output > 0) printf("Isotropic_Sqw: %s: Computing atom density V_rho=%g [AA^-3] from file %s\n", Sqw->compname, Sqw->rho, file);
  }

  if (nblocks) {
    if (nblocks == 1) {
      /* import Powder file */
      newTable = Sqw_read_PowderN(Sqw, Table_Array[0]);
      if (!newTable) {
        printf("Isotropic_Sqw: %s: ERROR importing powder line file %s.\n"
               "               Check format definition.\n",
              Sqw->compname, file);
        exit(-1);
      } else flag=0;
      Table_Free_Array(Table_Array);
      Table_Array = newTable;
    } else if (nblocks != 3) {
      printf("Isotropic_Sqw: %s: ERROR "
             "File %s contains %li block%s instead of 3.\n",
              Sqw->compname, file, nblocks, (nblocks == 1 ? "" : "s"));
    } else { flag=0; Sqw->barns=0; /* Sqw files do not use powder_barns */ }
  }

  /* print some info about Sqw files */
  if (flag) Sqw->verbose_output = 2;
  if (nblocks && Sqw->verbose_output > 1) {
    printf("Isotropic_Sqw: %s file read, analysing...\n", file);
    Table_Info_Array(Table_Array);
  }
  if (flag) {
    if (nblocks) printf("ERROR          Wrong file format.\n"
      "               Disabling contribution.\n"
      "               File must contain 3 blocks for [q,w,sqw] or Powder file\n");
    return(Sqw_Data);
  }

  /* restrict gridding range to q and omega min/max */
  for (i=0; i< 2; i++) { /* i=[q,w] */
    long    index;
    double  val_min, val_max;
    double *usr_min,*usr_max;
    t_Table Table;

    Table  = Table_Array[i];
    /* make q,w axes a single row */
    if (Table.columns == 1) { Table.columns = Table.rows; Table.rows = 1; }
    index  = Table.rows*Table.columns; /* full length of q,w */
    val_min= Table.min_x;
    val_max= Table.max_x;

    /* update min/max according to input parameters */
    if (i == 0) { /* q */
      q_min_data = val_min; /* full range */
      q_max_data = val_max;
      nb_q_data = index;
      val_min = (val_min < Sqw->q_min ? Sqw->q_min : val_min); /* restricted */
      val_max = (val_max > Sqw->q_max ? Sqw->q_max : val_max);
    } else { /* w */
      w_min_data = val_min;
      w_max_data = val_max;
      nb_w_data = index;
      val_min = (val_min < Sqw->w_min ? Sqw->w_min : val_min);
      val_max = (val_max > Sqw->w_max ? Sqw->w_max : val_max);
    }

    /* set restricted range */
    usr_min = (i == 0 ? &(Sqw_Data->q_min) : &(Sqw_Data->w_min));
    usr_max = (i == 0 ? &(Sqw_Data->q_max) : &(Sqw_Data->w_max));
    if (!*usr_min && !*usr_max) {
      *usr_min = val_min; *usr_max = val_max;
    }
    if (*usr_max > val_max) *usr_max=val_max;
  }

  /* get q and w restricted dimensions */
  for (i = Sqw_Data->nb_q = 0; i < nb_q_data; i++)
    if (Table_Index(Table_Array[0], 0, i) >= Sqw_Data->q_min
     && Table_Index(Table_Array[0], 0, i) <= Sqw_Data->q_max) Sqw_Data->nb_q++;

  for (j = Sqw_Data->nb_w = 0; j < nb_w_data; j++)
    if (Table_Index(Table_Array[1], 0, j) >= Sqw_Data->w_min
     && Table_Index(Table_Array[1], 0, j) <= Sqw_Data->w_max) Sqw_Data->nb_w++;

  if (!nb_q_data  || !nb_w_data) {
    printf("Isotropic_Sqw: %s: Data file %s has null q or omega information (%lix%li).\n"
           "ERROR          Exiting.\n",
      Sqw->compname, file, nb_q_data, nb_w_data);
    return(NULL);
  }

  if (!Sqw_Data->nb_q || !Sqw_Data->nb_w) {
    printf("Isotropic_Sqw: %s: File %s selected range has null q or omega dimension (%lix%li).\n"
           "ERROR          Exiting.\n",
      Sqw->compname, file, Sqw_Data->nb_w, Sqw_Data->nb_q);
    return(NULL);
  }

  /* test if sampling is regular */
  if (!Table_Array[0].constantstep || !Table_Array[1].constantstep) {
    printf("Isotropic_Sqw: %s: File %s %s sampling is not regular. Check and re-sample Sqw data.\n"
           "WARNING        Ignoring.\n",
      Sqw->compname, file,
      !Table_Array[0].constantstep ? "q" : "energy");
  }

  /* build the 'total' = Sqw table in restricted range */
  Table_Init(&Sqw_restrict, Sqw_Data->nb_q, Sqw_Data->nb_w);
  Sqw_restrict.block_number = 1;

  if (!Sqw_restrict.data || !Sqw_restrict.rows*Sqw_restrict.columns) {
    printf("Isotropic_Sqw: %s: Cannot allocate Sqw_restrict Table (%lix%li).\n"
           "ERROR          Exiting.\n",
      Sqw->compname, Sqw_Data->nb_q, Sqw_Data->nb_w);
    return(NULL);
  }
  sprintf(Sqw_restrict.filename, "S(q,w) from %s", file);

  Sqw_Data->nb_q_data = nb_q_data;
  Sqw_Data->nb_w_data = nb_w_data;
  /* now compute S(q) and normalize */
  Sqw_Data->Sq = (double *)calloc(nb_q_data, sizeof(double));
  if (!Sqw_Data->Sq) {
    printf("Isotropic_Sqw: %s: Cannot allocate S(Q) array (%li bytes).\n"
           "ERROR          Exiting.\n",
      Sqw->compname, nb_q_data*sizeof(double));
    return(NULL);
  }
  Sqw_Data->iqSq = (double *)calloc(nb_q_data, sizeof(double));
  if (!Sqw_Data->iqSq) {
    printf("Isotropic_Sqw: %s: Cannot allocate [\\int q S(Q)] array (%li bytes).\n"
           "ERROR          Exiting.\n",
      Sqw->compname, nb_q_data*sizeof(double));
    return(NULL);
  }
  sum = val = iq2Sq = iqSq = 0;
  for (i=0; i < nb_q_data ; i++) {
    double sqw=0, sq=0;
    q  = Table_Index(Table_Array[0], 0, i);
    for (j=0; j < nb_w_data ; j++) {
      flag = 1;
      if (nblocks) sqw = Table_Index(Table_Array[2], i, j);

      if (sqw < Sqw->sqw_threshold) flag = 0; /* Sqw lower than threshold */
      /* check for q,w within min/max */
      w  = Table_Index(Table_Array[1], 0, j);
      if (q < Sqw_Data->q_min || q > Sqw_Data->q_max) flag = 0; /* within q range  ? */
      if (w < Sqw_Data->w_min || w > Sqw_Data->w_max) flag = 0; /* within w range  ? */
      if (flag) val += sqw; /* only on restricted range */
      sum += sqw;           /* on total Sqw range */
      if (!Table_SetElement(&Sqw_restrict, i, j, (flag ? sqw : 0) ))
        printf("Isotropic_Sqw: %s: "
               "Error when setting Sqw[%li,%li]=%g from file %s\n",
               Sqw->compname, i,j, sqw, file);
      sq += sqw;
    }
    Sqw_Data->Sq[i] = sq;
    iq2Sq += q*q*sq;
    iqSq  += q*sq;
    Sqw_Data->iqSq[i] = iqSq*(q_max_data-q_min_data)/nb_q_data;
  }
  /* iq2Sq is \int q^2 S(q) dq */
  iq2Sq *= (q_max_data-q_min_data)/nb_q_data;

  /* norm S(q ,w) = sum(S)*q_range/nb_q */
  val *= (Sqw_Data->q_max-Sqw_Data->q_min)/Sqw_Data->nb_q; /* restricted q,w range */
  sum *= (q_max_data-q_min_data)/nb_q_data;                /* total q,w range      */

  if      (Sqw->sqw_norm >0) Sqw_Data->alpha=Sqw->sqw_norm;
  else if (!Sqw->sqw_norm)   Sqw_Data->alpha=1;

  if (!Sqw_Data->alpha) {
    if (iq2Sq && Sqw->type == 'c') { /* compute theoretical |S| norm */
      Sqw_Data->alpha =
        (q_max_data*q_max_data*q_max_data/3 - 2*PI*PI*Sqw->rho)
        /iq2Sq; /* this is only valid for coherent scattering */
    } else if (Sqw_Data->Sq[Sqw_Data->nb_q_data-1]) {
      /* alternate approx normalization to 1 */
      Sqw_Data->alpha = 1/Sqw_Data->Sq[Sqw_Data->nb_q_data-1];
    }
  }

  if (Sqw_Data->alpha) { /* apply normalization */
    val *= Sqw_Data->alpha;
    sum *= Sqw_Data->alpha;
    for (i=0; i < (Sqw_Data->nb_q_data) ; i++) {
      Sqw_Data->Sq[i]   *= Sqw_Data->alpha;
      Sqw_Data->iqSq[i] *= Sqw_Data->alpha;
    }
  }

  Sqw_Data->intensity       = val;
  Sqw_Data->intensity_total = sum;

  if (!val || !sum) {
    printf("Isotropic_Sqw: %s: No valid data in the selected (Q,w) range.\n"
           "ERROR          Available Sqw data is\n",
      Sqw->compname);
    printf("                 q=[%g:%g] w=[%g:%g]\n",
           q_min_data, q_max_data,
           w_min_data, w_max_data);
    return(NULL);
  }

  if (Sqw->verbose_output > 1 || !Sqw_Data->alpha)
    printf("Isotropic_Sqw: %s: Generated %scoherent S(Q)[%li]\n",
      Sqw->compname, (Sqw->type=='c' ? "" : "in"),
      Sqw_Data->nb_q_data);

  Table_Stat(&Sqw_restrict);

  if (Sqw->verbose_output > 0) {
    printf("Isotropic_Sqw: %s: Generated %s %scoherent Sqw\n"
           "                   q=[%g:%g] w=[%g:%g] |S|=%g size=[%lix%li] sigma=%g [barns]\n",
           Sqw->compname, file, (Sqw->type == 'i' ? "in" : ""),
           Sqw_Data->q_min, Sqw_Data->q_max,
           Sqw_Data->w_min, Sqw_Data->w_max, Sqw_Data->intensity,
           Sqw_Data->nb_q, Sqw_Data->nb_w,
           (Sqw->type == 'i' ? Sqw->s_inc : Sqw->s_coh));
    if (Sqw_Data->w_max < 1e-2 && Sqw_Data->w_min < 1e-2)
      printf("               Mainly elastic scattering.\n");
    if (Sqw->sqw_norm >0)
      printf("                   normalization factor S(q,w)*%g (user)\n", Sqw->sqw_norm);
    else if (Sqw->sqw_norm<0)
      printf("                   normalization factor S(q,w)*%g (auto)\n", Sqw_Data->alpha);
  }

  /* set up 'density of states' and index_wconst */
  /* uses: Sqw_restrict and w axes */
  Sqw_Data->SW =
    (struct Sqw_D_struct*)calloc(Sqw_Data->nb_w, sizeof(struct Sqw_D_struct));

  if (!Sqw_Data->SW) {
    printf("Isotropic_Sqw: %s: Cannot allocate SW (%li bytes).\n"
           "ERROR          Exiting.\n",
      Sqw->compname, Sqw_Data->nb_w*sizeof(struct Sqw_D_struct));
    return(NULL);
  }
  val = 0;
  for (j=0; j < (Sqw_Data->nb_w) ; j++) {
    double local_val=0;
    w  = Table_Index(Table_Array[1], 0, j);
    for (i=0; i < (Sqw_Data->nb_q) ; i++) { /* integrate on all q values */
      local_val += Table_Index(Sqw_restrict, i, j)*Sqw_Data->alpha; /* S(q,w) */
    }
    Sqw_Data->SW[j].omega = w;
    Sqw_Data->SW[j].value = local_val; /* S(w) */
    val                  += local_val; /* total intensity */
  }
  if (!val) {
    printf("Isotropic_Sqw: %s: Total S(q,w) intensity is NULL.\n"
           "ERROR          Exiting.\n",
      Sqw->compname);
    return(NULL);
  }

  /* compute normalized cumulated probability */
  for (j=0; j < (Sqw_Data->nb_w) ; j++) {
    Sqw_Data->SW[j].cumul_proba = Sqw_Data->SW[j].value/val;
    /* cumulated probabilities for the random choice */
    if (j) Sqw_Data->SW[j].cumul_proba += Sqw_Data->SW[j-1].cumul_proba;
  }
  if (Sqw->verbose_output > 1)
    printf("Isotropic_Sqw: %s: Generated normalized SW[%li] in range [0:%g]\n",
      Sqw->compname, Sqw_Data->nb_w, Sqw_Data->SW[Sqw_Data->nb_w-1].cumul_proba);

  /* set up Q probability table per w bin */
  /* uses:  Sqw_restrict */
  Sqw_Data->SQW =
    (struct Sqw_Q_struct**)calloc(Sqw_Data->nb_w, sizeof(struct Sqw_Q_struct*));

  if (!Sqw_Data->SQW) {
    printf("Isotropic_Sqw: %s: Cannot allocate P(Q|w) array (%li bytes).\n"
           "ERROR          Exiting.\n",
      Sqw->compname, Sqw_Data->nb_w*sizeof(struct Sqw_Q_struct*));
    return(NULL);
  }
  for (j=0; j < (Sqw_Data->nb_w) ; j++) {
    Sqw_Data->SQW[j]=
        (struct Sqw_Q_struct*)calloc(Sqw_Data->nb_q, sizeof(struct Sqw_Q_struct));

    if (!Sqw_Data->SQW[j]) {
      printf("Isotropic_Sqw: %s: Cannot allocate P(Q|w)[%li] (%li bytes).\n"
             "ERROR          Exiting.\n",
        Sqw->compname, j, Sqw_Data->nb_q*sizeof(struct Sqw_Q_struct));
      return(NULL);
    }
    /* set P(Q|W) and compute total intensity */
    for (i=0; i < (Sqw_Data->nb_q) ; i++) {
      q  = Table_Index(Table_Array[0], 0, i);
      Sqw_Data->SQW[j][i].Q     = q;
      Sqw_Data->SQW[j][i].value = Table_Index(Sqw_restrict, i, j)*Sqw_Data->alpha; /* S(q,w) */
    }
    for (i=0; i < (Sqw_Data->nb_q) ; i++) {
      Sqw_Data->SQW[j][i].cumul_proba = Sqw_Data->SQW[j][i].value/Sqw_Data->SW[j].value; 
      /* compute cumulated probability */
      if (i) Sqw_Data->SQW[j][i].cumul_proba += Sqw_Data->SQW[j][i-1].cumul_proba;
    }
    /* modify cumulated S(q,w) distribution to include the Jacobian dOmega/dq */
    for (i=0; i < (Sqw_Data->nb_q) ; i++) {
      q  = Table_Index(Table_Array[0], 0, i);
      Sqw_Data->SQW[j][i].cumul_proba *= q;
    }
    /* normalize distribution to 0:1 range */
    for (i=0; i < (Sqw_Data->nb_q) ; 
    	Sqw_Data->SQW[j][i++].cumul_proba /= Sqw_Data->SQW[j][Sqw_Data->nb_q-1].cumul_proba);
    
  }
  if (Sqw->verbose_output > 1)
    printf("Isotropic_Sqw: %s: Generated P(Q|w)\n",
      Sqw->compname);

  /* generate quick lookup tables for SW and SQW */
  SW_lookup = (long*)calloc(Sqw_Data->lookup_length, sizeof(long));

  if (!SW_lookup) {
    printf("Isotropic_Sqw: %s: Cannot allocate SW_lookup (%li bytes).\n"
           "Warning        Will be slower.\n",
      Sqw->compname, Sqw_Data->lookup_length*sizeof(long));
  } else {
    for (i=0; i < Sqw_Data->lookup_length; i++) {
      w = (double)i/(double)Sqw_Data->lookup_length;
      SW_lookup[i] = Sqw_search_SW(*Sqw_Data, w);
    }
    Sqw_Data->SW_lookup = SW_lookup;
  }
  QW_lookup = (long**)calloc(Sqw_Data->nb_w, sizeof(long*));

  if (!QW_lookup) {
    printf("Isotropic_Sqw: %s: Cannot allocate QW_lookup (%li bytes).\n"
           "Warning        Will be slower.\n",
      Sqw->compname, Sqw_Data->nb_w*sizeof(long*));
  } else {
    for (j=0; j < (Sqw_Data->nb_w) ; j++) {
      QW_lookup[j] =
        (long*)calloc(Sqw_Data->lookup_length, sizeof(long));
      if (!QW_lookup[j]) {
        printf("Isotropic_Sqw: %s: Cannot allocate QW_lookup[%li] (%li bytes).\n"
               "Warning        Will be slower.\n",
        Sqw->compname, j, Sqw_Data->lookup_length*sizeof(long));
        free(QW_lookup); Sqw_Data->QW_lookup = QW_lookup = NULL; break;
      } else {
        for (i=0; i < Sqw_Data->lookup_length; i++) {
          w = (double)i/(double)Sqw_Data->lookup_length;
          QW_lookup[j][i] = Sqw_search_Q_proba_per_w(*Sqw_Data, w, j);
        }
      }
    }
    Sqw_Data->QW_lookup = QW_lookup;
  }
  if ((Sqw_Data->QW_lookup || Sqw_Data->SW_lookup) && Sqw->verbose_output > 1)
    printf("Isotropic_Sqw: %s: Generated lookup tables with %li entries\n",
      Sqw->compname, Sqw_Data->lookup_length);

  Table_Free_Array(Table_Array);
  Sqw_Data->Sqw = Sqw_restrict;

  return(Sqw_Data);
} /* end Sqw_readfile */

/*****************************************************************************
* Sqw_init_read: Read coherent/incoherent Sqw data files
*   Returns Sqw total intensity, or 0 (error)
* Used in : INITIALIZE (1)
*****************************************************************************/
double Sqw_init(struct Sqw_sample_struct *Sqw, char *file_coh, char *file_inc)
{
  double ret=0;

  struct Sqw_Data_struct *d_inc, *d_coh;
  Sqw->type = 'i';
  d_inc = Sqw_readfile(Sqw, file_inc, &(Sqw->Data_inc));
  Sqw->type = 'c';
  d_coh = Sqw_readfile(Sqw, file_coh, &(Sqw->Data_coh));
  if (d_inc && !d_inc->intensity && Sqw->s_inc>0) {
    if (Sqw->verbose_output > 0)
      printf("Isotropic_Sqw: %s: Using Isotropic elastic incoherent scattering (sigma=%g [barns])\n", Sqw->compname, Sqw->s_inc);
    ret=1;
  }
  if (!d_inc || !d_coh) return(0);
  if (d_coh && !d_coh->intensity && Sqw->s_coh)
    printf("Isotropic_Sqw: %s: Coherent scattering Sqw intensity is null.\n"
           "Warning        Disabling coherent scattering.\n", Sqw->compname);
  if (d_inc && d_coh && d_inc->intensity && d_coh->intensity) {
    char msg[80];
    strcpy(msg, "");
    /* check dimensions/limits for Q, Energy in coh and inc Tables */
    if (d_inc->nb_q  != d_coh->nb_q)
      strcpy(msg, "Q axis size");
    if (d_inc->nb_w  != d_coh->nb_w)
      strcpy(msg, "Energy axis size");
    if ((d_inc->q_min != d_coh->q_min)
     || (d_inc->q_max != d_coh->q_max))
      strcpy(msg, "Q axis limits");
    if ((d_inc->w_min != d_coh->w_min)
     || (d_inc->w_max != d_coh->w_max))
      strcpy(msg, "Energy axis limits");
    if (strlen(msg)) {
      printf("Isotropic_Sqw: %s: Sqw data from files %s and %s do not match\n"
             "WARNING        wrong %s\n",
             Sqw->compname, file_coh, file_inc, msg);
    }
  }
  if (!ret) ret=d_inc->intensity+d_coh->intensity;
  return(ret);
}
#endif
#line 12071 "D1A.c"

/* Instrument parameters. */
MCNUM mciplambda;
MCNUM mcipDM;
char* mcippowder;
MCNUM mcipTemperature;

#define mcNUMIPAR 4
int mcnumipar = 4;
struct mcinputtable_struct mcinputtable[mcNUMIPAR+1] = {
  "lambda", &mciplambda, instr_type_double, "1.911", 
  "DM", &mcipDM, instr_type_double, "0", 
  "powder", &mcippowder, instr_type_string, "SiO2", 
  "Temperature", &mcipTemperature, instr_type_double, "300", 
  NULL, NULL, instr_type_double, ""
};

/* User declarations from instrument definition. */
#define mccompcurname D1A
#define lambda mciplambda
#define DM mcipDM
#define powder mcippowder
#define Temperature mcipTemperature
#line 62 "D1A.instr"
double A1; /* rotation of monok and d-spacing */
double RV; /* vertical curvature of monochromator */
double flag_container,flag_sample,flag_env;
double verbose=1;
double L1=17, L2=1.25, L3=0.5;
double RV=-1;
char container[]="V.laz";
char   Powder[256];
#line 12104 "D1A.c"
#undef Temperature
#undef powder
#undef DM
#undef lambda
#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*19];
/* Components position table (absolute and relative coords) */
Coords mccomp_posa[19];
Coords mccomp_posr[19];
/* Counter for each comp to check for inactive ones */
MCNUM  mcNCounter[19];
MCNUM  mcPCounter[19];
MCNUM  mcP2Counter[19];
#define mcNUMCOMP 18 /* number of components */
/* Counter for PROP ABSORB */
MCNUM  mcAbsorbProp[19];
/* 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 'Source' [2]. */
MCNUM mccSource_radius;
MCNUM mccSource_height;
MCNUM mccSource_width;
MCNUM mccSource_dist;
MCNUM mccSource_xw;
MCNUM mccSource_yh;
MCNUM mccSource_E0;
MCNUM mccSource_dE;
MCNUM mccSource_Lambda0;
MCNUM mccSource_dLambda;
MCNUM mccSource_flux;
MCNUM mccSource_gauss;
MCNUM mccSource_compat;

/* Definition parameters for component 'Monok' [4]. */
#define mccMonok_reflect 0
#define mccMonok_transmit 0
/* Setting parameters for component 'Monok' [4]. */
MCNUM mccMonok_zwidth;
MCNUM mccMonok_yheight;
MCNUM mccMonok_gap;
MCNUM mccMonok_NH;
MCNUM mccMonok_NV;
MCNUM mccMonok_mosaich;
MCNUM mccMonok_mosaicv;
MCNUM mccMonok_r0;
MCNUM mccMonok_t0;
MCNUM mccMonok_Q;
MCNUM mccMonok_RV;
MCNUM mccMonok_RH;
MCNUM mccMonok_DM;
MCNUM mccMonok_mosaic;
MCNUM mccMonok_width;
MCNUM mccMonok_height;
MCNUM mccMonok_verbose;

/* Definition parameters for component 'Lmon' [6]. */
#define mccLmon_options "auto lambda"
#define mccLmon_filename 0
#define mccLmon_user1 FLT_MAX
#define mccLmon_user2 FLT_MAX
#define mccLmon_user3 FLT_MAX
#define mccLmon_username1 0
#define mccLmon_username2 0
#define mccLmon_username3 0
/* Setting parameters for component 'Lmon' [6]. */
MCNUM mccLmon_xwidth;
MCNUM mccLmon_yheight;
MCNUM mccLmon_zthick;
MCNUM mccLmon_xmin;
MCNUM mccLmon_xmax;
MCNUM mccLmon_ymin;
MCNUM mccLmon_ymax;
MCNUM mccLmon_zmin;
MCNUM mccLmon_zmax;
MCNUM mccLmon_bins;
MCNUM mccLmon_min;
MCNUM mccLmon_max;
MCNUM mccLmon_restore_neutron;

/* Definition parameters for component 'PSDsample' [7]. */
#define mccPSDsample_options "x y"
#define mccPSDsample_filename 0
#define mccPSDsample_user1 FLT_MAX
#define mccPSDsample_user2 FLT_MAX
#define mccPSDsample_user3 FLT_MAX
#define mccPSDsample_username1 0
#define mccPSDsample_username2 0
#define mccPSDsample_username3 0
/* Setting parameters for component 'PSDsample' [7]. */
MCNUM mccPSDsample_xwidth;
MCNUM mccPSDsample_yheight;
MCNUM mccPSDsample_zthick;
MCNUM mccPSDsample_xmin;
MCNUM mccPSDsample_xmax;
MCNUM mccPSDsample_ymin;
MCNUM mccPSDsample_ymax;
MCNUM mccPSDsample_zmin;
MCNUM mccPSDsample_zmax;
MCNUM mccPSDsample_bins;
MCNUM mccPSDsample_min;
MCNUM mccPSDsample_max;
MCNUM mccPSDsample_restore_neutron;

/* Definition parameters for component 'Environment_in' [9]. */
#define mccEnvironment_in_reflections "Al.laz"
#define mccEnvironment_in_format Undefined
/* Setting parameters for component 'Environment_in' [9]. */
MCNUM mccEnvironment_in_d_phi;
MCNUM mccEnvironment_in_radius;
MCNUM mccEnvironment_in_radius_i;
MCNUM mccEnvironment_in_yheight;
MCNUM mccEnvironment_in_pack;
MCNUM mccEnvironment_in_Vc;
MCNUM mccEnvironment_in_sigma_abs;
MCNUM mccEnvironment_in_sigma_inc;
MCNUM mccEnvironment_in_Delta_d;
MCNUM mccEnvironment_in_frac;
MCNUM mccEnvironment_in_tfrac;
MCNUM mccEnvironment_in_xwidth;
MCNUM mccEnvironment_in_zthick;
MCNUM mccEnvironment_in_xwidth_i;
MCNUM mccEnvironment_in_yheight_i;
MCNUM mccEnvironment_in_zthick_i;
MCNUM mccEnvironment_in_h;
MCNUM mccEnvironment_in_DW;
MCNUM mccEnvironment_in_nb_atoms;
MCNUM mccEnvironment_in_concentric;
MCNUM mccEnvironment_in_density;
MCNUM mccEnvironment_in_weight;
MCNUM mccEnvironment_in_barns;

/* Definition parameters for component 'Container_in' [10]. */
#define mccContainer_in_reflections container
#define mccContainer_in_format Undefined
/* Setting parameters for component 'Container_in' [10]. */
MCNUM mccContainer_in_d_phi;
MCNUM mccContainer_in_radius;
MCNUM mccContainer_in_radius_i;
MCNUM mccContainer_in_yheight;
MCNUM mccContainer_in_pack;
MCNUM mccContainer_in_Vc;
MCNUM mccContainer_in_sigma_abs;
MCNUM mccContainer_in_sigma_inc;
MCNUM mccContainer_in_Delta_d;
MCNUM mccContainer_in_frac;
MCNUM mccContainer_in_tfrac;
MCNUM mccContainer_in_xwidth;
MCNUM mccContainer_in_zthick;
MCNUM mccContainer_in_xwidth_i;
MCNUM mccContainer_in_yheight_i;
MCNUM mccContainer_in_zthick_i;
MCNUM mccContainer_in_h;
MCNUM mccContainer_in_DW;
MCNUM mccContainer_in_nb_atoms;
MCNUM mccContainer_in_concentric;
MCNUM mccContainer_in_density;
MCNUM mccContainer_in_weight;
MCNUM mccContainer_in_barns;

/* Definition parameters for component 'Sample_liq' [11]. */
#define mccSample_liq_Sqw_coh Powder
#define mccSample_liq_Sqw_inc 0
#define mccSample_liq_powder_format Undefined
#define mccSample_liq_geometry 0
/* Setting parameters for component 'Sample_liq' [11]. */
MCNUM mccSample_liq_radius;
MCNUM mccSample_liq_thickness;
MCNUM mccSample_liq_xwidth;
MCNUM mccSample_liq_yheight;
MCNUM mccSample_liq_zdepth;
MCNUM mccSample_liq_qmin;
MCNUM mccSample_liq_qmax;
MCNUM mccSample_liq_wmin;
MCNUM mccSample_liq_wmax;
MCNUM mccSample_liq_auto_qw;
MCNUM mccSample_liq_threshold;
int mccSample_liq_order;
MCNUM mccSample_liq_T;
MCNUM mccSample_liq_verbose;
MCNUM mccSample_liq_d_phi;
int mccSample_liq_concentric;
MCNUM mccSample_liq_V_rho;
MCNUM mccSample_liq_sigma_abs;
MCNUM mccSample_liq_sigma_coh;
MCNUM mccSample_liq_sigma_inc;
MCNUM mccSample_liq_save_sqw;
MCNUM mccSample_liq_powder_Dd;
MCNUM mccSample_liq_powder_DW;
MCNUM mccSample_liq_powder_Vc;
MCNUM mccSample_liq_density;
MCNUM mccSample_liq_weight;
MCNUM mccSample_liq_p_interact;
MCNUM mccSample_liq_auto_norm;
MCNUM mccSample_liq_powder_barns;

/* Definition parameters for component 'Sample' [12]. */
#define mccSample_reflections Powder
#define mccSample_format Undefined
/* Setting parameters for component 'Sample' [12]. */
MCNUM mccSample_d_phi;
MCNUM mccSample_radius;
MCNUM mccSample_radius_i;
MCNUM mccSample_yheight;
MCNUM mccSample_pack;
MCNUM mccSample_Vc;
MCNUM mccSample_sigma_abs;
MCNUM mccSample_sigma_inc;
MCNUM mccSample_Delta_d;
MCNUM mccSample_frac;
MCNUM mccSample_tfrac;
MCNUM mccSample_xwidth;
MCNUM mccSample_zthick;
MCNUM mccSample_xwidth_i;
MCNUM mccSample_yheight_i;
MCNUM mccSample_zthick_i;
MCNUM mccSample_h;
MCNUM mccSample_DW;
MCNUM mccSample_nb_atoms;
MCNUM mccSample_concentric;
MCNUM mccSample_density;
MCNUM mccSample_weight;
MCNUM mccSample_barns;

/* Definition parameters for component 'Container_out' [13]. */
#define mccContainer_out_reflections container
#define mccContainer_out_format Undefined
/* Setting parameters for component 'Container_out' [13]. */
MCNUM mccContainer_out_d_phi;
MCNUM mccContainer_out_radius;
MCNUM mccContainer_out_radius_i;
MCNUM mccContainer_out_yheight;
MCNUM mccContainer_out_pack;
MCNUM mccContainer_out_Vc;
MCNUM mccContainer_out_sigma_abs;
MCNUM mccContainer_out_sigma_inc;
MCNUM mccContainer_out_Delta_d;
MCNUM mccContainer_out_frac;
MCNUM mccContainer_out_tfrac;
MCNUM mccContainer_out_xwidth;
MCNUM mccContainer_out_zthick;
MCNUM mccContainer_out_xwidth_i;
MCNUM mccContainer_out_yheight_i;
MCNUM mccContainer_out_zthick_i;
MCNUM mccContainer_out_h;
MCNUM mccContainer_out_DW;
MCNUM mccContainer_out_nb_atoms;
MCNUM mccContainer_out_concentric;
MCNUM mccContainer_out_density;
MCNUM mccContainer_out_weight;
MCNUM mccContainer_out_barns;

/* Definition parameters for component 'Environment_out' [14]. */
#define mccEnvironment_out_reflections "Al.laz"
#define mccEnvironment_out_format Undefined
/* Setting parameters for component 'Environment_out' [14]. */
MCNUM mccEnvironment_out_d_phi;
MCNUM mccEnvironment_out_radius;
MCNUM mccEnvironment_out_radius_i;
MCNUM mccEnvironment_out_yheight;
MCNUM mccEnvironment_out_pack;
MCNUM mccEnvironment_out_Vc;
MCNUM mccEnvironment_out_sigma_abs;
MCNUM mccEnvironment_out_sigma_inc;
MCNUM mccEnvironment_out_Delta_d;
MCNUM mccEnvironment_out_frac;
MCNUM mccEnvironment_out_tfrac;
MCNUM mccEnvironment_out_xwidth;
MCNUM mccEnvironment_out_zthick;
MCNUM mccEnvironment_out_xwidth_i;
MCNUM mccEnvironment_out_yheight_i;
MCNUM mccEnvironment_out_zthick_i;
MCNUM mccEnvironment_out_h;
MCNUM mccEnvironment_out_DW;
MCNUM mccEnvironment_out_nb_atoms;
MCNUM mccEnvironment_out_concentric;
MCNUM mccEnvironment_out_density;
MCNUM mccEnvironment_out_weight;
MCNUM mccEnvironment_out_barns;

/* Setting parameters for component 'Collimator' [15]. */
MCNUM mccCollimator_w1;
MCNUM mccCollimator_h1;
MCNUM mccCollimator_w2;
MCNUM mccCollimator_h2;
MCNUM mccCollimator_len;
MCNUM mccCollimator_divergence;
MCNUM mccCollimator_transmission;
MCNUM mccCollimator_theta_min;
MCNUM mccCollimator_theta_max;
MCNUM mccCollimator_nchan;
MCNUM mccCollimator_radius;
MCNUM mccCollimator_nblades;
MCNUM mccCollimator_roc;
MCNUM mccCollimator_verbose;

/* Definition parameters for component 'BananaTheta' [16]. */
#define mccBananaTheta_options "banana, theta limits=[3 160], bins=380"
#define mccBananaTheta_filename 0
#define mccBananaTheta_user1 FLT_MAX
#define mccBananaTheta_user2 FLT_MAX
#define mccBananaTheta_user3 FLT_MAX
#define mccBananaTheta_username1 0
#define mccBananaTheta_username2 0
#define mccBananaTheta_username3 0
/* Setting parameters for component 'BananaTheta' [16]. */
MCNUM mccBananaTheta_xwidth;
MCNUM mccBananaTheta_yheight;
MCNUM mccBananaTheta_zthick;
MCNUM mccBananaTheta_xmin;
MCNUM mccBananaTheta_xmax;
MCNUM mccBananaTheta_ymin;
MCNUM mccBananaTheta_ymax;
MCNUM mccBananaTheta_zmin;
MCNUM mccBananaTheta_zmax;
MCNUM mccBananaTheta_bins;
MCNUM mccBananaTheta_min;
MCNUM mccBananaTheta_max;
MCNUM mccBananaTheta_restore_neutron;

/* Definition parameters for component 'BananaPSD' [17]. */
#define mccBananaPSD_options "banana, theta limits=[5 160] bins=380, y bins=25"
#define mccBananaPSD_filename 0
#define mccBananaPSD_user1 FLT_MAX
#define mccBananaPSD_user2 FLT_MAX
#define mccBananaPSD_user3 FLT_MAX
#define mccBananaPSD_username1 0
#define mccBananaPSD_username2 0
#define mccBananaPSD_username3 0
/* Setting parameters for component 'BananaPSD' [17]. */
MCNUM mccBananaPSD_xwidth;
MCNUM mccBananaPSD_yheight;
MCNUM mccBananaPSD_zthick;
MCNUM mccBananaPSD_xmin;
MCNUM mccBananaPSD_xmax;
MCNUM mccBananaPSD_ymin;
MCNUM mccBananaPSD_ymax;
MCNUM mccBananaPSD_zmin;
MCNUM mccBananaPSD_zmax;
MCNUM mccBananaPSD_bins;
MCNUM mccBananaPSD_min;
MCNUM mccBananaPSD_max;
MCNUM mccBananaPSD_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 12484 "D1A.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 'Source' [2]. */
#define mccompcurname  Source
#define mccompcurtype  Source_simple
#define mccompcurindex 2
#define pmul mccSource_pmul
#define radius mccSource_radius
#define height mccSource_height
#define width mccSource_width
#define dist mccSource_dist
#define xw mccSource_xw
#define yh mccSource_yh
#define E0 mccSource_E0
#define dE mccSource_dE
#define Lambda0 mccSource_Lambda0
#define dLambda mccSource_dLambda
#define flux mccSource_flux
#define gauss mccSource_gauss
#define compat mccSource_compat
#line 60 "/usr/local/lib/mcstas/sources/Source_simple.comp"
  double pmul, srcArea;
  int square;
#line 12517 "D1A.c"
#undef compat
#undef gauss
#undef flux
#undef dLambda
#undef Lambda0
#undef dE
#undef E0
#undef yh
#undef xw
#undef dist
#undef width
#undef height
#undef radius
#undef pmul
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

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

/* User declarations for component 'Monok' [4]. */
#define mccompcurname  Monok
#define mccompcurtype  Monochromator_curved
#define mccompcurindex 4
#define reflect mccMonok_reflect
#define transmit mccMonok_transmit
#define mos_rms_y mccMonok_mos_rms_y
#define mos_rms_z mccMonok_mos_rms_z
#define mos_rms_max mccMonok_mos_rms_max
#define mono_Q mccMonok_mono_Q
#define SlabWidth mccMonok_SlabWidth
#define SlabHeight mccMonok_SlabHeight
#define rTable mccMonok_rTable
#define tTable mccMonok_tTable
#define row mccMonok_row
#define col mccMonok_col
#define zwidth mccMonok_zwidth
#define yheight mccMonok_yheight
#define gap mccMonok_gap
#define NH mccMonok_NH
#define NV mccMonok_NV
#define mosaich mccMonok_mosaich
#define mosaicv mccMonok_mosaicv
#define r0 mccMonok_r0
#define t0 mccMonok_t0
#define Q mccMonok_Q
#define RV mccMonok_RV
#define RH mccMonok_RH
#define DM mccMonok_DM
#define mosaic mccMonok_mosaic
#define width mccMonok_width
#define height mccMonok_height
#define verbose mccMonok_verbose
#line 131 "/usr/local/lib/mcstas/optics/Monochromator_curved.comp"
  double mos_rms_y; /* root-mean-square of mosaic, in radians */
  double mos_rms_z;
  double mos_rms_max;
  double mono_Q;
  double SlabWidth, SlabHeight;
  t_Table rTable, tTable;
  double row,col;
#line 12585 "D1A.c"
#undef verbose
#undef height
#undef width
#undef mosaic
#undef DM
#undef RH
#undef RV
#undef Q
#undef t0
#undef r0
#undef mosaicv
#undef mosaich
#undef NV
#undef NH
#undef gap
#undef yheight
#undef zwidth
#undef col
#undef row
#undef tTable
#undef rTable
#undef SlabHeight
#undef SlabWidth
#undef mono_Q
#undef mos_rms_max
#undef mos_rms_z
#undef mos_rms_y
#undef transmit
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

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

/* User declarations for component 'Lmon' [6]. */
#define mccompcurname  Lmon
#define mccompcurtype  Monitor_nD
#define mccompcurindex 6
#define options mccLmon_options
#define filename mccLmon_filename
#define user1 mccLmon_user1
#define user2 mccLmon_user2
#define user3 mccLmon_user3
#define username1 mccLmon_username1
#define username2 mccLmon_username2
#define username3 mccLmon_username3
#define DEFS mccLmon_DEFS
#define Vars mccLmon_Vars
#define xwidth mccLmon_xwidth
#define yheight mccLmon_yheight
#define zthick mccLmon_zthick
#define xmin mccLmon_xmin
#define xmax mccLmon_xmax
#define ymin mccLmon_ymin
#define ymax mccLmon_ymax
#define zmin mccLmon_zmin
#define zmax mccLmon_zmax
#define bins mccLmon_bins
#define min mccLmon_min
#define max mccLmon_max
#define restore_neutron mccLmon_restore_neutron
#line 220 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
  MonitornD_Defines_type DEFS;
  MonitornD_Variables_type Vars;
#line 12657 "D1A.c"
#undef restore_neutron
#undef max
#undef min
#undef bins
#undef zmax
#undef zmin
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef zthick
#undef yheight
#undef xwidth
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'PSDsample' [7]. */
#define mccompcurname  PSDsample
#define mccompcurtype  Monitor_nD
#define mccompcurindex 7
#define options mccPSDsample_options
#define filename mccPSDsample_filename
#define user1 mccPSDsample_user1
#define user2 mccPSDsample_user2
#define user3 mccPSDsample_user3
#define username1 mccPSDsample_username1
#define username2 mccPSDsample_username2
#define username3 mccPSDsample_username3
#define DEFS mccPSDsample_DEFS
#define Vars mccPSDsample_Vars
#define xwidth mccPSDsample_xwidth
#define yheight mccPSDsample_yheight
#define zthick mccPSDsample_zthick
#define xmin mccPSDsample_xmin
#define xmax mccPSDsample_xmax
#define ymin mccPSDsample_ymin
#define ymax mccPSDsample_ymax
#define zmin mccPSDsample_zmin
#define zmax mccPSDsample_zmax
#define bins mccPSDsample_bins
#define min mccPSDsample_min
#define max mccPSDsample_max
#define restore_neutron mccPSDsample_restore_neutron
#line 220 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
  MonitornD_Defines_type DEFS;
  MonitornD_Variables_type Vars;
#line 12715 "D1A.c"
#undef restore_neutron
#undef max
#undef min
#undef bins
#undef zmax
#undef zmin
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef zthick
#undef yheight
#undef xwidth
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

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

/* User declarations for component 'Environment_in' [9]. */
#define mccompcurname  Environment_in
#define mccompcurtype  PowderN
#define mccompcurindex 9
#define reflections mccEnvironment_in_reflections
#define format mccEnvironment_in_format
#define line_info mccEnvironment_in_line_info
#define Nq mccEnvironment_in_Nq
#define my_s_v2 mccEnvironment_in_my_s_v2
#define my_s_v2_sum mccEnvironment_in_my_s_v2_sum
#define my_a_v mccEnvironment_in_my_a_v
#define my_inc mccEnvironment_in_my_inc
#define q_v mccEnvironment_in_q_v
#define w_v mccEnvironment_in_w_v
#define isrect mccEnvironment_in_isrect
#define columns mccEnvironment_in_columns
#define d_phi mccEnvironment_in_d_phi
#define radius mccEnvironment_in_radius
#define radius_i mccEnvironment_in_radius_i
#define yheight mccEnvironment_in_yheight
#define pack mccEnvironment_in_pack
#define Vc mccEnvironment_in_Vc
#define sigma_abs mccEnvironment_in_sigma_abs
#define sigma_inc mccEnvironment_in_sigma_inc
#define Delta_d mccEnvironment_in_Delta_d
#define frac mccEnvironment_in_frac
#define tfrac mccEnvironment_in_tfrac
#define xwidth mccEnvironment_in_xwidth
#define zthick mccEnvironment_in_zthick
#define xwidth_i mccEnvironment_in_xwidth_i
#define yheight_i mccEnvironment_in_yheight_i
#define zthick_i mccEnvironment_in_zthick_i
#define h mccEnvironment_in_h
#define DW mccEnvironment_in_DW
#define nb_atoms mccEnvironment_in_nb_atoms
#define concentric mccEnvironment_in_concentric
#define density mccEnvironment_in_density
#define weight mccEnvironment_in_weight
#define barns mccEnvironment_in_barns
#line 385 "/usr/local/lib/mcstas/samples/PowderN.comp"
  struct line_info_struct line_info;
  int Nq=0;
  double my_s_v2_sum;
  double my_a_v, my_inc;
  double *w_v,*q_v, *my_s_v2;
  char   isrect=0;
  int    columns[8] = format;
  double XsectionFactor;
#line 12799 "D1A.c"
#undef barns
#undef weight
#undef density
#undef concentric
#undef nb_atoms
#undef DW
#undef h
#undef zthick_i
#undef yheight_i
#undef xwidth_i
#undef zthick
#undef xwidth
#undef tfrac
#undef frac
#undef Delta_d
#undef sigma_inc
#undef sigma_abs
#undef Vc
#undef pack
#undef yheight
#undef radius_i
#undef radius
#undef d_phi
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Container_in' [10]. */
#define mccompcurname  Container_in
#define mccompcurtype  PowderN
#define mccompcurindex 10
#define reflections mccContainer_in_reflections
#define format mccContainer_in_format
#define line_info mccContainer_in_line_info
#define Nq mccContainer_in_Nq
#define my_s_v2 mccContainer_in_my_s_v2
#define my_s_v2_sum mccContainer_in_my_s_v2_sum
#define my_a_v mccContainer_in_my_a_v
#define my_inc mccContainer_in_my_inc
#define q_v mccContainer_in_q_v
#define w_v mccContainer_in_w_v
#define isrect mccContainer_in_isrect
#define columns mccContainer_in_columns
#define d_phi mccContainer_in_d_phi
#define radius mccContainer_in_radius
#define radius_i mccContainer_in_radius_i
#define yheight mccContainer_in_yheight
#define pack mccContainer_in_pack
#define Vc mccContainer_in_Vc
#define sigma_abs mccContainer_in_sigma_abs
#define sigma_inc mccContainer_in_sigma_inc
#define Delta_d mccContainer_in_Delta_d
#define frac mccContainer_in_frac
#define tfrac mccContainer_in_tfrac
#define xwidth mccContainer_in_xwidth
#define zthick mccContainer_in_zthick
#define xwidth_i mccContainer_in_xwidth_i
#define yheight_i mccContainer_in_yheight_i
#define zthick_i mccContainer_in_zthick_i
#define h mccContainer_in_h
#define DW mccContainer_in_DW
#define nb_atoms mccContainer_in_nb_atoms
#define concentric mccContainer_in_concentric
#define density mccContainer_in_density
#define weight mccContainer_in_weight
#define barns mccContainer_in_barns
#line 385 "/usr/local/lib/mcstas/samples/PowderN.comp"
  struct line_info_struct line_info;
  int Nq=0;
  double my_s_v2_sum;
  double my_a_v, my_inc;
  double *w_v,*q_v, *my_s_v2;
  char   isrect=0;
  int    columns[8] = format;
  double XsectionFactor;
#line 12887 "D1A.c"
#undef barns
#undef weight
#undef density
#undef concentric
#undef nb_atoms
#undef DW
#undef h
#undef zthick_i
#undef yheight_i
#undef xwidth_i
#undef zthick
#undef xwidth
#undef tfrac
#undef frac
#undef Delta_d
#undef sigma_inc
#undef sigma_abs
#undef Vc
#undef pack
#undef yheight
#undef radius_i
#undef radius
#undef d_phi
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Sample_liq' [11]. */
#define mccompcurname  Sample_liq
#define mccompcurtype  Isotropic_Sqw
#define mccompcurindex 11
#define Sqw_coh mccSample_liq_Sqw_coh
#define Sqw_inc mccSample_liq_Sqw_inc
#define powder_format mccSample_liq_powder_format
#define geometry mccSample_liq_geometry
#define VarSqw mccSample_liq_VarSqw
#define columns mccSample_liq_columns
#define offdata mccSample_liq_offdata
#define radius mccSample_liq_radius
#define thickness mccSample_liq_thickness
#define xwidth mccSample_liq_xwidth
#define yheight mccSample_liq_yheight
#define zdepth mccSample_liq_zdepth
#define qmin mccSample_liq_qmin
#define qmax mccSample_liq_qmax
#define wmin mccSample_liq_wmin
#define wmax mccSample_liq_wmax
#define auto_qw mccSample_liq_auto_qw
#define threshold mccSample_liq_threshold
#define order mccSample_liq_order
#define T mccSample_liq_T
#define verbose mccSample_liq_verbose
#define d_phi mccSample_liq_d_phi
#define concentric mccSample_liq_concentric
#define V_rho mccSample_liq_V_rho
#define sigma_abs mccSample_liq_sigma_abs
#define sigma_coh mccSample_liq_sigma_coh
#define sigma_inc mccSample_liq_sigma_inc
#define save_sqw mccSample_liq_save_sqw
#define powder_Dd mccSample_liq_powder_Dd
#define powder_DW mccSample_liq_powder_DW
#define powder_Vc mccSample_liq_powder_Vc
#define density mccSample_liq_density
#define weight mccSample_liq_weight
#define p_interact mccSample_liq_p_interact
#define auto_norm mccSample_liq_auto_norm
#define powder_barns mccSample_liq_powder_barns
#line 1231 "/usr/local/lib/mcstas/samples/Isotropic_Sqw.comp"

  struct Sqw_sample_struct VarSqw;
  int    columns[8] = powder_format;
  off_struct offdata;
/* end DECLARE */
#line 12973 "D1A.c"
#undef powder_barns
#undef auto_norm
#undef p_interact
#undef weight
#undef density
#undef powder_Vc
#undef powder_DW
#undef powder_Dd
#undef save_sqw
#undef sigma_inc
#undef sigma_coh
#undef sigma_abs
#undef V_rho
#undef concentric
#undef d_phi
#undef verbose
#undef T
#undef order
#undef threshold
#undef auto_qw
#undef wmax
#undef wmin
#undef qmax
#undef qmin
#undef zdepth
#undef yheight
#undef xwidth
#undef thickness
#undef radius
#undef offdata
#undef columns
#undef VarSqw
#undef geometry
#undef powder_format
#undef Sqw_inc
#undef Sqw_coh
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Sample' [12]. */
#define mccompcurname  Sample
#define mccompcurtype  PowderN
#define mccompcurindex 12
#define reflections mccSample_reflections
#define format mccSample_format
#define line_info mccSample_line_info
#define Nq mccSample_Nq
#define my_s_v2 mccSample_my_s_v2
#define my_s_v2_sum mccSample_my_s_v2_sum
#define my_a_v mccSample_my_a_v
#define my_inc mccSample_my_inc
#define q_v mccSample_q_v
#define w_v mccSample_w_v
#define isrect mccSample_isrect
#define columns mccSample_columns
#define d_phi mccSample_d_phi
#define radius mccSample_radius
#define radius_i mccSample_radius_i
#define yheight mccSample_yheight
#define pack mccSample_pack
#define Vc mccSample_Vc
#define sigma_abs mccSample_sigma_abs
#define sigma_inc mccSample_sigma_inc
#define Delta_d mccSample_Delta_d
#define frac mccSample_frac
#define tfrac mccSample_tfrac
#define xwidth mccSample_xwidth
#define zthick mccSample_zthick
#define xwidth_i mccSample_xwidth_i
#define yheight_i mccSample_yheight_i
#define zthick_i mccSample_zthick_i
#define h mccSample_h
#define DW mccSample_DW
#define nb_atoms mccSample_nb_atoms
#define concentric mccSample_concentric
#define density mccSample_density
#define weight mccSample_weight
#define barns mccSample_barns
#line 385 "/usr/local/lib/mcstas/samples/PowderN.comp"
  struct line_info_struct line_info;
  int Nq=0;
  double my_s_v2_sum;
  double my_a_v, my_inc;
  double *w_v,*q_v, *my_s_v2;
  char   isrect=0;
  int    columns[8] = format;
  double XsectionFactor;
#line 13062 "D1A.c"
#undef barns
#undef weight
#undef density
#undef concentric
#undef nb_atoms
#undef DW
#undef h
#undef zthick_i
#undef yheight_i
#undef xwidth_i
#undef zthick
#undef xwidth
#undef tfrac
#undef frac
#undef Delta_d
#undef sigma_inc
#undef sigma_abs
#undef Vc
#undef pack
#undef yheight
#undef radius_i
#undef radius
#undef d_phi
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Container_out' [13]. */
#define mccompcurname  Container_out
#define mccompcurtype  PowderN
#define mccompcurindex 13
#define reflections mccContainer_out_reflections
#define format mccContainer_out_format
#define line_info mccContainer_out_line_info
#define Nq mccContainer_out_Nq
#define my_s_v2 mccContainer_out_my_s_v2
#define my_s_v2_sum mccContainer_out_my_s_v2_sum
#define my_a_v mccContainer_out_my_a_v
#define my_inc mccContainer_out_my_inc
#define q_v mccContainer_out_q_v
#define w_v mccContainer_out_w_v
#define isrect mccContainer_out_isrect
#define columns mccContainer_out_columns
#define d_phi mccContainer_out_d_phi
#define radius mccContainer_out_radius
#define radius_i mccContainer_out_radius_i
#define yheight mccContainer_out_yheight
#define pack mccContainer_out_pack
#define Vc mccContainer_out_Vc
#define sigma_abs mccContainer_out_sigma_abs
#define sigma_inc mccContainer_out_sigma_inc
#define Delta_d mccContainer_out_Delta_d
#define frac mccContainer_out_frac
#define tfrac mccContainer_out_tfrac
#define xwidth mccContainer_out_xwidth
#define zthick mccContainer_out_zthick
#define xwidth_i mccContainer_out_xwidth_i
#define yheight_i mccContainer_out_yheight_i
#define zthick_i mccContainer_out_zthick_i
#define h mccContainer_out_h
#define DW mccContainer_out_DW
#define nb_atoms mccContainer_out_nb_atoms
#define concentric mccContainer_out_concentric
#define density mccContainer_out_density
#define weight mccContainer_out_weight
#define barns mccContainer_out_barns
#line 385 "/usr/local/lib/mcstas/samples/PowderN.comp"
  struct line_info_struct line_info;
  int Nq=0;
  double my_s_v2_sum;
  double my_a_v, my_inc;
  double *w_v,*q_v, *my_s_v2;
  char   isrect=0;
  int    columns[8] = format;
  double XsectionFactor;
#line 13150 "D1A.c"
#undef barns
#undef weight
#undef density
#undef concentric
#undef nb_atoms
#undef DW
#undef h
#undef zthick_i
#undef yheight_i
#undef xwidth_i
#undef zthick
#undef xwidth
#undef tfrac
#undef frac
#undef Delta_d
#undef sigma_inc
#undef sigma_abs
#undef Vc
#undef pack
#undef yheight
#undef radius_i
#undef radius
#undef d_phi
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Environment_out' [14]. */
#define mccompcurname  Environment_out
#define mccompcurtype  PowderN
#define mccompcurindex 14
#define reflections mccEnvironment_out_reflections
#define format mccEnvironment_out_format
#define line_info mccEnvironment_out_line_info
#define Nq mccEnvironment_out_Nq
#define my_s_v2 mccEnvironment_out_my_s_v2
#define my_s_v2_sum mccEnvironment_out_my_s_v2_sum
#define my_a_v mccEnvironment_out_my_a_v
#define my_inc mccEnvironment_out_my_inc
#define q_v mccEnvironment_out_q_v
#define w_v mccEnvironment_out_w_v
#define isrect mccEnvironment_out_isrect
#define columns mccEnvironment_out_columns
#define d_phi mccEnvironment_out_d_phi
#define radius mccEnvironment_out_radius
#define radius_i mccEnvironment_out_radius_i
#define yheight mccEnvironment_out_yheight
#define pack mccEnvironment_out_pack
#define Vc mccEnvironment_out_Vc
#define sigma_abs mccEnvironment_out_sigma_abs
#define sigma_inc mccEnvironment_out_sigma_inc
#define Delta_d mccEnvironment_out_Delta_d
#define frac mccEnvironment_out_frac
#define tfrac mccEnvironment_out_tfrac
#define xwidth mccEnvironment_out_xwidth
#define zthick mccEnvironment_out_zthick
#define xwidth_i mccEnvironment_out_xwidth_i
#define yheight_i mccEnvironment_out_yheight_i
#define zthick_i mccEnvironment_out_zthick_i
#define h mccEnvironment_out_h
#define DW mccEnvironment_out_DW
#define nb_atoms mccEnvironment_out_nb_atoms
#define concentric mccEnvironment_out_concentric
#define density mccEnvironment_out_density
#define weight mccEnvironment_out_weight
#define barns mccEnvironment_out_barns
#line 385 "/usr/local/lib/mcstas/samples/PowderN.comp"
  struct line_info_struct line_info;
  int Nq=0;
  double my_s_v2_sum;
  double my_a_v, my_inc;
  double *w_v,*q_v, *my_s_v2;
  char   isrect=0;
  int    columns[8] = format;
  double XsectionFactor;
#line 13238 "D1A.c"
#undef barns
#undef weight
#undef density
#undef concentric
#undef nb_atoms
#undef DW
#undef h
#undef zthick_i
#undef yheight_i
#undef xwidth_i
#undef zthick
#undef xwidth
#undef tfrac
#undef frac
#undef Delta_d
#undef sigma_inc
#undef sigma_abs
#undef Vc
#undef pack
#undef yheight
#undef radius_i
#undef radius
#undef d_phi
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'Collimator' [15]. */
#define mccompcurname  Collimator
#define mccompcurtype  Collimator_radial
#define mccompcurindex 15
#define soller_theta1 mccCollimator_soller_theta1
#define soller_theta2 mccCollimator_soller_theta2
#define window_theta mccCollimator_window_theta
#define use_approx mccCollimator_use_approx
#define ideal mccCollimator_ideal
#define w1 mccCollimator_w1
#define h1 mccCollimator_h1
#define w2 mccCollimator_w2
#define h2 mccCollimator_h2
#define len mccCollimator_len
#define divergence mccCollimator_divergence
#define transmission mccCollimator_transmission
#define theta_min mccCollimator_theta_min
#define theta_max mccCollimator_theta_max
#define nchan mccCollimator_nchan
#define radius mccCollimator_radius
#define nblades mccCollimator_nblades
#define roc mccCollimator_roc
#define verbose mccCollimator_verbose
#line 84 "/usr/local/lib/mcstas/optics/Collimator_radial.comp"
  double soller_theta1, soller_theta2, window_theta;
  char   use_approx=1;
  char   ideal     =0;
#line 13305 "D1A.c"
#undef verbose
#undef roc
#undef nblades
#undef radius
#undef nchan
#undef theta_max
#undef theta_min
#undef transmission
#undef divergence
#undef len
#undef h2
#undef w2
#undef h1
#undef w1
#undef ideal
#undef use_approx
#undef window_theta
#undef soller_theta2
#undef soller_theta1
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'BananaTheta' [16]. */
#define mccompcurname  BananaTheta
#define mccompcurtype  Monitor_nD
#define mccompcurindex 16
#define options mccBananaTheta_options
#define filename mccBananaTheta_filename
#define user1 mccBananaTheta_user1
#define user2 mccBananaTheta_user2
#define user3 mccBananaTheta_user3
#define username1 mccBananaTheta_username1
#define username2 mccBananaTheta_username2
#define username3 mccBananaTheta_username3
#define DEFS mccBananaTheta_DEFS
#define Vars mccBananaTheta_Vars
#define xwidth mccBananaTheta_xwidth
#define yheight mccBananaTheta_yheight
#define zthick mccBananaTheta_zthick
#define xmin mccBananaTheta_xmin
#define xmax mccBananaTheta_xmax
#define ymin mccBananaTheta_ymin
#define ymax mccBananaTheta_ymax
#define zmin mccBananaTheta_zmin
#define zmax mccBananaTheta_zmax
#define bins mccBananaTheta_bins
#define min mccBananaTheta_min
#define max mccBananaTheta_max
#define restore_neutron mccBananaTheta_restore_neutron
#line 220 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
  MonitornD_Defines_type DEFS;
  MonitornD_Variables_type Vars;
#line 13359 "D1A.c"
#undef restore_neutron
#undef max
#undef min
#undef bins
#undef zmax
#undef zmin
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef zthick
#undef yheight
#undef xwidth
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

/* User declarations for component 'BananaPSD' [17]. */
#define mccompcurname  BananaPSD
#define mccompcurtype  Monitor_nD
#define mccompcurindex 17
#define options mccBananaPSD_options
#define filename mccBananaPSD_filename
#define user1 mccBananaPSD_user1
#define user2 mccBananaPSD_user2
#define user3 mccBananaPSD_user3
#define username1 mccBananaPSD_username1
#define username2 mccBananaPSD_username2
#define username3 mccBananaPSD_username3
#define DEFS mccBananaPSD_DEFS
#define Vars mccBananaPSD_Vars
#define xwidth mccBananaPSD_xwidth
#define yheight mccBananaPSD_yheight
#define zthick mccBananaPSD_zthick
#define xmin mccBananaPSD_xmin
#define xmax mccBananaPSD_xmax
#define ymin mccBananaPSD_ymin
#define ymax mccBananaPSD_ymax
#define zmin mccBananaPSD_zmin
#define zmax mccBananaPSD_zmax
#define bins mccBananaPSD_bins
#define min mccBananaPSD_min
#define max mccBananaPSD_max
#define restore_neutron mccBananaPSD_restore_neutron
#line 220 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
  MonitornD_Defines_type DEFS;
  MonitornD_Variables_type Vars;
#line 13417 "D1A.c"
#undef restore_neutron
#undef max
#undef min
#undef bins
#undef zmax
#undef zmin
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef zthick
#undef yheight
#undef xwidth
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

Coords mcposaOrigin, mcposrOrigin;
Rotation mcrotaOrigin, mcrotrOrigin;
Coords mcposaSource, mcposrSource;
Rotation mcrotaSource, mcrotrSource;
Coords mcposamono_cradle, mcposrmono_cradle;
Rotation mcrotamono_cradle, mcrotrmono_cradle;
Coords mcposaMonok, mcposrMonok;
Rotation mcrotaMonok, mcrotrMonok;
Coords mcposamono_out, mcposrmono_out;
Rotation mcrotamono_out, mcrotrmono_out;
Coords mcposaLmon, mcposrLmon;
Rotation mcrotaLmon, mcrotrLmon;
Coords mcposaPSDsample, mcposrPSDsample;
Rotation mcrotaPSDsample, mcrotrPSDsample;
Coords mcposaSamplePos, mcposrSamplePos;
Rotation mcrotaSamplePos, mcrotrSamplePos;
Coords mcposaEnvironment_in, mcposrEnvironment_in;
Rotation mcrotaEnvironment_in, mcrotrEnvironment_in;
Coords mcposaContainer_in, mcposrContainer_in;
Rotation mcrotaContainer_in, mcrotrContainer_in;
Coords mcposaSample_liq, mcposrSample_liq;
Rotation mcrotaSample_liq, mcrotrSample_liq;
Coords mcposaSample, mcposrSample;
Rotation mcrotaSample, mcrotrSample;
Coords mcposaContainer_out, mcposrContainer_out;
Rotation mcrotaContainer_out, mcrotrContainer_out;
Coords mcposaEnvironment_out, mcposrEnvironment_out;
Rotation mcrotaEnvironment_out, mcrotrEnvironment_out;
Coords mcposaCollimator, mcposrCollimator;
Rotation mcrotaCollimator, mcrotrCollimator;
Coords mcposaBananaTheta, mcposrBananaTheta;
Rotation mcrotaBananaTheta, mcrotrBananaTheta;
Coords mcposaBananaPSD, mcposrBananaPSD;
Rotation mcrotaBananaPSD, mcrotrBananaPSD;

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

/* end declare */

void mcinit(void) {
#define mccompcurname D1A
#define lambda mciplambda
#define DM mcipDM
#define powder mcippowder
#define Temperature mcipTemperature
#line 75 "D1A.instr"
{
double L;
double KI, Vi, EI;

A1 =122/2;
if (!lambda && DM)
  lambda=sin(A1*DEG2RAD)*2*DM;
else if (lambda && !DM)
  DM=lambda/2/sin(A1*DEG2RAD);
  
if (!lambda || !DM)
  exit(printf("%s: ERROR: wavelength and DM are unset. Exit.\n", NAME_CURRENT_COMP));

L = 1/(1/L1+1/L2);
if (RV < 0) RV=2*L*sin(DEG2RAD*A1);
KI=2*PI/lambda;
Vi = K2V*fabs(KI);
EI = VS2E*Vi*Vi;
A1 *= -1;

/* handling silica sample with temperature */
if (strstr(powder, "SiO2") || strstr(powder, "sio2")) {
  /* liquid T_m=1650 C */
  /* α-quartz converts to β-quartz at 573°C */
  if (Temperature < 573+273) strcpy(Powder, "SiO2_quartza.laz");
  else if (Temperature < 1650+273) strcpy(Powder, "SiO2_quartzb.laz");
  else strcpy(Powder, "SiO2.qSq");
} else strcpy(Powder,powder);

if (verbose) {
  printf("%s: Detailed DIF configuration\n", NAME_CURRENT_COMP);
  printf("* Incoming beam: lambda=%.4g [Angs] EI=%.4g [meV]  KI=%.4g [Angs-1] Vi=%g [m/s]\n",
    lambda, EI, KI, Vi);
  printf("* Monochromator:  DM=%.4g [Angs] RV=%.4g [m] %s, take-off A2=%.4g [deg]\n",
    DM, RV, (!RV ? "flat" : "curved"), 2*A1);
  printf("* Sample: %s in %s cylinder container\n", powder, container);
}
}
#line 13529 "D1A.c"
#undef Temperature
#undef powder
#undef DM
#undef lambda
#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 13547 "D1A.c"
    rot_copy(mcrotrOrigin, mcrotaOrigin);
    mcposaOrigin = coords_set(
#line 119 "D1A.instr"
      0,
#line 119 "D1A.instr"
      0,
#line 119 "D1A.instr"
      0);
#line 13556 "D1A.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 Source. */
    SIG_MESSAGE("Source (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13570 "D1A.c"
    rot_mul(mctr1, mcrotaOrigin, mcrotaSource);
    rot_transpose(mcrotaOrigin, mctr1);
    rot_mul(mcrotaSource, mctr1, mcrotrSource);
    mctc1 = coords_set(
#line 125 "D1A.instr"
      0,
#line 125 "D1A.instr"
      0,
#line 125 "D1A.instr"
      0);
#line 13581 "D1A.c"
    rot_transpose(mcrotaOrigin, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaSource = coords_add(mcposaOrigin, mctc2);
    mctc1 = coords_sub(mcposaOrigin, mcposaSource);
    mcposrSource = rot_apply(mcrotaSource, mctc1);
    mcDEBUG_COMPONENT("Source", mcposaSource, mcrotaSource)
    mccomp_posa[2] = mcposaSource;
    mccomp_posr[2] = mcposrSource;
    mcNCounter[2]  = mcPCounter[2] = mcP2Counter[2] = 0;
    mcAbsorbProp[2]= 0;
    /* Component mono_cradle. */
    SIG_MESSAGE("mono_cradle (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
#line 130 "D1A.instr"
      (0)*DEG2RAD,
#line 130 "D1A.instr"
      (A1)*DEG2RAD,
#line 130 "D1A.instr"
      (0)*DEG2RAD);
#line 13601 "D1A.c"
    rot_mul(mctr1, mcrotaOrigin, mcrotamono_cradle);
    rot_transpose(mcrotaSource, mctr1);
    rot_mul(mcrotamono_cradle, mctr1, mcrotrmono_cradle);
    mctc1 = coords_set(
#line 129 "D1A.instr"
      0,
#line 129 "D1A.instr"
      0,
#line 129 "D1A.instr"
      L1);
#line 13612 "D1A.c"
    rot_transpose(mcrotaOrigin, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposamono_cradle = coords_add(mcposaOrigin, mctc2);
    mctc1 = coords_sub(mcposaSource, mcposamono_cradle);
    mcposrmono_cradle = rot_apply(mcrotamono_cradle, mctc1);
    mcDEBUG_COMPONENT("mono_cradle", mcposamono_cradle, mcrotamono_cradle)
    mccomp_posa[3] = mcposamono_cradle;
    mccomp_posr[3] = mcposrmono_cradle;
    mcNCounter[3]  = mcPCounter[3] = mcP2Counter[3] = 0;
    mcAbsorbProp[3]= 0;
    /* Component Monok. */
    SIG_MESSAGE("Monok (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13629 "D1A.c"
    rot_mul(mctr1, mcrotamono_cradle, mcrotaMonok);
    rot_transpose(mcrotamono_cradle, mctr1);
    rot_mul(mcrotaMonok, mctr1, mcrotrMonok);
    mctc1 = coords_set(
#line 136 "D1A.instr"
      0,
#line 136 "D1A.instr"
      0,
#line 136 "D1A.instr"
      0);
#line 13640 "D1A.c"
    rot_transpose(mcrotamono_cradle, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaMonok = coords_add(mcposamono_cradle, mctc2);
    mctc1 = coords_sub(mcposamono_cradle, mcposaMonok);
    mcposrMonok = rot_apply(mcrotaMonok, mctc1);
    mcDEBUG_COMPONENT("Monok", mcposaMonok, mcrotaMonok)
    mccomp_posa[4] = mcposaMonok;
    mccomp_posr[4] = mcposrMonok;
    mcNCounter[4]  = mcPCounter[4] = mcP2Counter[4] = 0;
    mcAbsorbProp[4]= 0;
    /* Component mono_out. */
    SIG_MESSAGE("mono_out (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
#line 141 "D1A.instr"
      (0)*DEG2RAD,
#line 141 "D1A.instr"
      (2 * A1)*DEG2RAD,
#line 141 "D1A.instr"
      (0)*DEG2RAD);
#line 13660 "D1A.c"
    rot_mul(mctr1, mcrotaOrigin, mcrotamono_out);
    rot_transpose(mcrotaMonok, mctr1);
    rot_mul(mcrotamono_out, mctr1, mcrotrmono_out);
    mctc1 = coords_set(
#line 140 "D1A.instr"
      0,
#line 140 "D1A.instr"
      0,
#line 140 "D1A.instr"
      0);
#line 13671 "D1A.c"
    rot_transpose(mcrotamono_cradle, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposamono_out = coords_add(mcposamono_cradle, mctc2);
    mctc1 = coords_sub(mcposaMonok, mcposamono_out);
    mcposrmono_out = rot_apply(mcrotamono_out, mctc1);
    mcDEBUG_COMPONENT("mono_out", mcposamono_out, mcrotamono_out)
    mccomp_posa[5] = mcposamono_out;
    mccomp_posr[5] = mcposrmono_out;
    mcNCounter[5]  = mcPCounter[5] = mcP2Counter[5] = 0;
    mcAbsorbProp[5]= 0;
    /* Component Lmon. */
    SIG_MESSAGE("Lmon (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13688 "D1A.c"
    rot_mul(mctr1, mcrotamono_out, mcrotaLmon);
    rot_transpose(mcrotamono_out, mctr1);
    rot_mul(mcrotaLmon, mctr1, mcrotrLmon);
    mctc1 = coords_set(
#line 145 "D1A.instr"
      0,
#line 145 "D1A.instr"
      0,
#line 145 "D1A.instr"
      0.2);
#line 13699 "D1A.c"
    rot_transpose(mcrotamono_out, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaLmon = coords_add(mcposamono_out, mctc2);
    mctc1 = coords_sub(mcposamono_out, mcposaLmon);
    mcposrLmon = rot_apply(mcrotaLmon, mctc1);
    mcDEBUG_COMPONENT("Lmon", mcposaLmon, mcrotaLmon)
    mccomp_posa[6] = mcposaLmon;
    mccomp_posr[6] = mcposrLmon;
    mcNCounter[6]  = mcPCounter[6] = mcP2Counter[6] = 0;
    mcAbsorbProp[6]= 0;
    /* Component PSDsample. */
    SIG_MESSAGE("PSDsample (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13716 "D1A.c"
    rot_mul(mctr1, mcrotamono_out, mcrotaPSDsample);
    rot_transpose(mcrotaLmon, mctr1);
    rot_mul(mcrotaPSDsample, mctr1, mcrotrPSDsample);
    mctc1 = coords_set(
#line 149 "D1A.instr"
      0,
#line 149 "D1A.instr"
      0,
#line 149 "D1A.instr"
      L2 -0.1);
#line 13727 "D1A.c"
    rot_transpose(mcrotamono_out, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaPSDsample = coords_add(mcposamono_out, mctc2);
    mctc1 = coords_sub(mcposaLmon, mcposaPSDsample);
    mcposrPSDsample = rot_apply(mcrotaPSDsample, mctc1);
    mcDEBUG_COMPONENT("PSDsample", mcposaPSDsample, mcrotaPSDsample)
    mccomp_posa[7] = mcposaPSDsample;
    mccomp_posr[7] = mcposrPSDsample;
    mcNCounter[7]  = mcPCounter[7] = mcP2Counter[7] = 0;
    mcAbsorbProp[7]= 0;
    /* Component SamplePos. */
    SIG_MESSAGE("SamplePos (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13744 "D1A.c"
    rot_mul(mctr1, mcrotamono_out, mcrotaSamplePos);
    rot_transpose(mcrotaPSDsample, mctr1);
    rot_mul(mcrotaSamplePos, mctr1, mcrotrSamplePos);
    mctc1 = coords_set(
#line 153 "D1A.instr"
      0,
#line 153 "D1A.instr"
      0,
#line 153 "D1A.instr"
      L2);
#line 13755 "D1A.c"
    rot_transpose(mcrotamono_out, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaSamplePos = coords_add(mcposamono_out, mctc2);
    mctc1 = coords_sub(mcposaPSDsample, mcposaSamplePos);
    mcposrSamplePos = rot_apply(mcrotaSamplePos, mctc1);
    mcDEBUG_COMPONENT("SamplePos", mcposaSamplePos, mcrotaSamplePos)
    mccomp_posa[8] = mcposaSamplePos;
    mccomp_posr[8] = mcposrSamplePos;
    mcNCounter[8]  = mcPCounter[8] = mcP2Counter[8] = 0;
    mcAbsorbProp[8]= 0;
    /* Component Environment_in. */
    SIG_MESSAGE("Environment_in (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13772 "D1A.c"
    rot_mul(mctr1, mcrotaSamplePos, mcrotaEnvironment_in);
    rot_transpose(mcrotaSamplePos, mctr1);
    rot_mul(mcrotaEnvironment_in, mctr1, mcrotrEnvironment_in);
    mctc1 = coords_set(
#line 162 "D1A.instr"
      0,
#line 162 "D1A.instr"
      0,
#line 162 "D1A.instr"
      0);
#line 13783 "D1A.c"
    rot_transpose(mcrotaSamplePos, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaEnvironment_in = coords_add(mcposaSamplePos, mctc2);
    mctc1 = coords_sub(mcposaSamplePos, mcposaEnvironment_in);
    mcposrEnvironment_in = rot_apply(mcrotaEnvironment_in, mctc1);
    mcDEBUG_COMPONENT("Environment_in", mcposaEnvironment_in, mcrotaEnvironment_in)
    mccomp_posa[9] = mcposaEnvironment_in;
    mccomp_posr[9] = mcposrEnvironment_in;
    mcNCounter[9]  = mcPCounter[9] = mcP2Counter[9] = 0;
    mcAbsorbProp[9]= 0;
    /* Component Container_in. */
    SIG_MESSAGE("Container_in (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13800 "D1A.c"
    rot_mul(mctr1, mcrotaSamplePos, mcrotaContainer_in);
    rot_transpose(mcrotaEnvironment_in, mctr1);
    rot_mul(mcrotaContainer_in, mctr1, mcrotrContainer_in);
    mctc1 = coords_set(
#line 170 "D1A.instr"
      0,
#line 170 "D1A.instr"
      0,
#line 170 "D1A.instr"
      0);
#line 13811 "D1A.c"
    rot_transpose(mcrotaSamplePos, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaContainer_in = coords_add(mcposaSamplePos, mctc2);
    mctc1 = coords_sub(mcposaEnvironment_in, mcposaContainer_in);
    mcposrContainer_in = rot_apply(mcrotaContainer_in, mctc1);
    mcDEBUG_COMPONENT("Container_in", mcposaContainer_in, mcrotaContainer_in)
    mccomp_posa[10] = mcposaContainer_in;
    mccomp_posr[10] = mcposrContainer_in;
    mcNCounter[10]  = mcPCounter[10] = mcP2Counter[10] = 0;
    mcAbsorbProp[10]= 0;
    /* Component Sample_liq. */
    SIG_MESSAGE("Sample_liq (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13828 "D1A.c"
    rot_mul(mctr1, mcrotaSamplePos, mcrotaSample_liq);
    rot_transpose(mcrotaContainer_in, mctr1);
    rot_mul(mcrotaSample_liq, mctr1, mcrotrSample_liq);
    mctc1 = coords_set(
#line 178 "D1A.instr"
      0,
#line 178 "D1A.instr"
      0,
#line 178 "D1A.instr"
      0);
#line 13839 "D1A.c"
    rot_transpose(mcrotaSamplePos, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaSample_liq = coords_add(mcposaSamplePos, mctc2);
    mctc1 = coords_sub(mcposaContainer_in, mcposaSample_liq);
    mcposrSample_liq = rot_apply(mcrotaSample_liq, mctc1);
    mcDEBUG_COMPONENT("Sample_liq", mcposaSample_liq, mcrotaSample_liq)
    mccomp_posa[11] = mcposaSample_liq;
    mccomp_posr[11] = mcposrSample_liq;
    mcNCounter[11]  = mcPCounter[11] = mcP2Counter[11] = 0;
    mcAbsorbProp[11]= 0;
    /* Component Sample. */
    SIG_MESSAGE("Sample (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13856 "D1A.c"
    rot_mul(mctr1, mcrotaSamplePos, mcrotaSample);
    rot_transpose(mcrotaSample_liq, mctr1);
    rot_mul(mcrotaSample, mctr1, mcrotrSample);
    mctc1 = coords_set(
#line 188 "D1A.instr"
      0,
#line 188 "D1A.instr"
      0,
#line 188 "D1A.instr"
      0);
#line 13867 "D1A.c"
    rot_transpose(mcrotaSamplePos, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaSample = coords_add(mcposaSamplePos, mctc2);
    mctc1 = coords_sub(mcposaSample_liq, mcposaSample);
    mcposrSample = rot_apply(mcrotaSample, mctc1);
    mcDEBUG_COMPONENT("Sample", mcposaSample, mcrotaSample)
    mccomp_posa[12] = mcposaSample;
    mccomp_posr[12] = mcposrSample;
    mcNCounter[12]  = mcPCounter[12] = mcP2Counter[12] = 0;
    mcAbsorbProp[12]= 0;
    /* Component Container_out. */
    SIG_MESSAGE("Container_out (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13884 "D1A.c"
    rot_mul(mctr1, mcrotaSamplePos, mcrotaContainer_out);
    rot_transpose(mcrotaSample, mctr1);
    rot_mul(mcrotaContainer_out, mctr1, mcrotrContainer_out);
    mctc1 = coords_set(
#line 195 "D1A.instr"
      0,
#line 195 "D1A.instr"
      0,
#line 195 "D1A.instr"
      0);
#line 13895 "D1A.c"
    rot_transpose(mcrotaSamplePos, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaContainer_out = coords_add(mcposaSamplePos, mctc2);
    mctc1 = coords_sub(mcposaSample, mcposaContainer_out);
    mcposrContainer_out = rot_apply(mcrotaContainer_out, mctc1);
    mcDEBUG_COMPONENT("Container_out", mcposaContainer_out, mcrotaContainer_out)
    mccomp_posa[13] = mcposaContainer_out;
    mccomp_posr[13] = mcposrContainer_out;
    mcNCounter[13]  = mcPCounter[13] = mcP2Counter[13] = 0;
    mcAbsorbProp[13]= 0;
    /* Component Environment_out. */
    SIG_MESSAGE("Environment_out (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13912 "D1A.c"
    rot_mul(mctr1, mcrotaSamplePos, mcrotaEnvironment_out);
    rot_transpose(mcrotaContainer_out, mctr1);
    rot_mul(mcrotaEnvironment_out, mctr1, mcrotrEnvironment_out);
    mctc1 = coords_set(
#line 201 "D1A.instr"
      0,
#line 201 "D1A.instr"
      0,
#line 201 "D1A.instr"
      0);
#line 13923 "D1A.c"
    rot_transpose(mcrotaSamplePos, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaEnvironment_out = coords_add(mcposaSamplePos, mctc2);
    mctc1 = coords_sub(mcposaContainer_out, mcposaEnvironment_out);
    mcposrEnvironment_out = rot_apply(mcrotaEnvironment_out, mctc1);
    mcDEBUG_COMPONENT("Environment_out", mcposaEnvironment_out, mcrotaEnvironment_out)
    mccomp_posa[14] = mcposaEnvironment_out;
    mccomp_posr[14] = mcposrEnvironment_out;
    mcNCounter[14]  = mcPCounter[14] = mcP2Counter[14] = 0;
    mcAbsorbProp[14]= 0;
    /* Component Collimator. */
    SIG_MESSAGE("Collimator (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13940 "D1A.c"
    rot_mul(mctr1, mcrotaSamplePos, mcrotaCollimator);
    rot_transpose(mcrotaEnvironment_out, mctr1);
    rot_mul(mcrotaCollimator, mctr1, mcrotrCollimator);
    mctc1 = coords_set(
#line 211 "D1A.instr"
      0,
#line 211 "D1A.instr"
      0,
#line 211 "D1A.instr"
      0);
#line 13951 "D1A.c"
    rot_transpose(mcrotaSamplePos, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaCollimator = coords_add(mcposaSamplePos, mctc2);
    mctc1 = coords_sub(mcposaEnvironment_out, mcposaCollimator);
    mcposrCollimator = rot_apply(mcrotaCollimator, mctc1);
    mcDEBUG_COMPONENT("Collimator", mcposaCollimator, mcrotaCollimator)
    mccomp_posa[15] = mcposaCollimator;
    mccomp_posr[15] = mcposrCollimator;
    mcNCounter[15]  = mcPCounter[15] = mcP2Counter[15] = 0;
    mcAbsorbProp[15]= 0;
    /* Component BananaTheta. */
    SIG_MESSAGE("BananaTheta (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13968 "D1A.c"
    rot_mul(mctr1, mcrotaSamplePos, mcrotaBananaTheta);
    rot_transpose(mcrotaCollimator, mctr1);
    rot_mul(mcrotaBananaTheta, mctr1, mcrotrBananaTheta);
    mctc1 = coords_set(
#line 220 "D1A.instr"
      0,
#line 220 "D1A.instr"
      0,
#line 220 "D1A.instr"
      0);
#line 13979 "D1A.c"
    rot_transpose(mcrotaSamplePos, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaBananaTheta = coords_add(mcposaSamplePos, mctc2);
    mctc1 = coords_sub(mcposaCollimator, mcposaBananaTheta);
    mcposrBananaTheta = rot_apply(mcrotaBananaTheta, mctc1);
    mcDEBUG_COMPONENT("BananaTheta", mcposaBananaTheta, mcrotaBananaTheta)
    mccomp_posa[16] = mcposaBananaTheta;
    mccomp_posr[16] = mcposrBananaTheta;
    mcNCounter[16]  = mcPCounter[16] = mcP2Counter[16] = 0;
    mcAbsorbProp[16]= 0;
    /* Component BananaPSD. */
    SIG_MESSAGE("BananaPSD (Init:Place/Rotate)");
    rot_set_rotation(mctr1,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD,
      (0.0)*DEG2RAD);
#line 13996 "D1A.c"
    rot_mul(mctr1, mcrotaSamplePos, mcrotaBananaPSD);
    rot_transpose(mcrotaBananaTheta, mctr1);
    rot_mul(mcrotaBananaPSD, mctr1, mcrotrBananaPSD);
    mctc1 = coords_set(
#line 226 "D1A.instr"
      0,
#line 226 "D1A.instr"
      0,
#line 226 "D1A.instr"
      0);
#line 14007 "D1A.c"
    rot_transpose(mcrotaSamplePos, mctr1);
    mctc2 = rot_apply(mctr1, mctc1);
    mcposaBananaPSD = coords_add(mcposaSamplePos, mctc2);
    mctc1 = coords_sub(mcposaBananaTheta, mcposaBananaPSD);
    mcposrBananaPSD = rot_apply(mcrotaBananaPSD, mctc1);
    mcDEBUG_COMPONENT("BananaPSD", mcposaBananaPSD, mcrotaBananaPSD)
    mccomp_posa[17] = mcposaBananaPSD;
    mccomp_posr[17] = mcposrBananaPSD;
    mcNCounter[17]  = mcPCounter[17] = mcP2Counter[17] = 0;
    mcAbsorbProp[17]= 0;
  /* Component initializations. */
  /* Initializations for component Origin. */
  SIG_MESSAGE("Origin (Init)");
#line 42 "D1A.instr"
  mccOrigin_percent = 10;
#line 42 "D1A.instr"
  mccOrigin_flag_save = 0;
#line 42 "D1A.instr"
  mccOrigin_minutes = 0;
#line 14027 "D1A.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 14046 "D1A.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 Source. */
  SIG_MESSAGE("Source (Init)");
#line 123 "D1A.instr"
  mccSource_radius = 0.05;
#line 55 "D1A.instr"
  mccSource_height = 0;
#line 55 "D1A.instr"
  mccSource_width = 0;
#line 123 "D1A.instr"
  mccSource_dist = L1;
#line 123 "D1A.instr"
  mccSource_xw = 0.1;
#line 123 "D1A.instr"
  mccSource_yh = 0.1;
#line 55 "D1A.instr"
  mccSource_E0 = 0;
#line 55 "D1A.instr"
  mccSource_dE = 0;
#line 124 "D1A.instr"
  mccSource_Lambda0 = mciplambda;
#line 124 "D1A.instr"
  mccSource_dLambda = mciplambda * 0.01;
#line 55 "D1A.instr"
  mccSource_flux = 1;
#line 55 "D1A.instr"
  mccSource_gauss = 0;
#line 55 "D1A.instr"
  mccSource_compat = 0;
#line 14086 "D1A.c"

#define mccompcurname  Source
#define mccompcurtype  Source_simple
#define mccompcurindex 2
#define pmul mccSource_pmul
#define radius mccSource_radius
#define height mccSource_height
#define width mccSource_width
#define dist mccSource_dist
#define xw mccSource_xw
#define yh mccSource_yh
#define E0 mccSource_E0
#define dE mccSource_dE
#define Lambda0 mccSource_Lambda0
#define dLambda mccSource_dLambda
#define flux mccSource_flux
#define gauss mccSource_gauss
#define compat mccSource_compat
#line 64 "/usr/local/lib/mcstas/sources/Source_simple.comp"
{
  square = 0;
  /* Determine source area: */
  if (!radius == 0 && height == 0 && width == 0) {
    square = 0;
    srcArea = PI*radius*radius;
  } else if(radius == 0 && !height ==0 && !width==0) {
    square = 1;
    srcArea = width * height;
  }
  
  if (!compat) {
    pmul=flux*1e4*srcArea/mcget_ncount();
  } else {
    gauss = 0;
    pmul=1.0/(mcget_ncount()*4*PI);
  }
  if (srcArea <= 0) {
    printf("Source_simple: %s: Source area is <= 0 !\n ERROR - Exiting\n",
           NAME_CURRENT_COMP);
    exit(0);
  }
  if (dist < 0 || xw < 0 || yh < 0) {
    printf("Source_simple: %s: Target area unmeaningful! (negative dist / xw / yh)\n ERROR - Exiting\n",
           NAME_CURRENT_COMP);
    exit(0);
  }
  
  if ((!Lambda0 && !E0 && !dE && !dLambda)) {
    printf("Source_simple: %s: You must specify either a wavelength or energy range!\n ERROR - Exiting\n",
           NAME_CURRENT_COMP);
    exit(0);
  }
  if ((!Lambda0 && !dLambda && (E0 <= 0 || dE < 0 || E0-dE <= 0))
    || (!E0 && !dE && (Lambda0 <= 0 || dLambda < 0 || Lambda0-dLambda <= 0))) {
    printf("Source_simple: %s: Unmeaningful definition of wavelength or energy range!\n ERROR - Exiting\n",
           NAME_CURRENT_COMP);
      exit(0);
  }
}
#line 14146 "D1A.c"
#undef compat
#undef gauss
#undef flux
#undef dLambda
#undef Lambda0
#undef dE
#undef E0
#undef yh
#undef xw
#undef dist
#undef width
#undef height
#undef radius
#undef pmul
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

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


  /* Initializations for component Monok. */
  SIG_MESSAGE("Monok (Init)");
#line 98 "D1A.instr"
  mccMonok_zwidth = 0.01;
#line 98 "D1A.instr"
  mccMonok_yheight = 0.01;
#line 98 "D1A.instr"
  mccMonok_gap = 0.0005;
#line 134 "D1A.instr"
  mccMonok_NH = 1;
#line 134 "D1A.instr"
  mccMonok_NV = 11;
#line 135 "D1A.instr"
  mccMonok_mosaich = 30;
#line 135 "D1A.instr"
  mccMonok_mosaicv = 30;
#line 98 "D1A.instr"
  mccMonok_r0 = 0.7;
#line 98 "D1A.instr"
  mccMonok_t0 = 1.0;
#line 98 "D1A.instr"
  mccMonok_Q = 1.8734;
#line 134 "D1A.instr"
  mccMonok_RV = RV;
#line 98 "D1A.instr"
  mccMonok_RH = 0;
#line 135 "D1A.instr"
  mccMonok_DM = mcipDM;
#line 98 "D1A.instr"
  mccMonok_mosaic = 0;
#line 134 "D1A.instr"
  mccMonok_width = 0.1;
#line 134 "D1A.instr"
  mccMonok_height = 0.1;
#line 98 "D1A.instr"
  mccMonok_verbose = 0;
#line 14205 "D1A.c"

#define mccompcurname  Monok
#define mccompcurtype  Monochromator_curved
#define mccompcurindex 4
#define reflect mccMonok_reflect
#define transmit mccMonok_transmit
#define mos_rms_y mccMonok_mos_rms_y
#define mos_rms_z mccMonok_mos_rms_z
#define mos_rms_max mccMonok_mos_rms_max
#define mono_Q mccMonok_mono_Q
#define SlabWidth mccMonok_SlabWidth
#define SlabHeight mccMonok_SlabHeight
#define rTable mccMonok_rTable
#define tTable mccMonok_tTable
#define row mccMonok_row
#define col mccMonok_col
#define zwidth mccMonok_zwidth
#define yheight mccMonok_yheight
#define gap mccMonok_gap
#define NH mccMonok_NH
#define NV mccMonok_NV
#define mosaich mccMonok_mosaich
#define mosaicv mccMonok_mosaicv
#define r0 mccMonok_r0
#define t0 mccMonok_t0
#define Q mccMonok_Q
#define RV mccMonok_RV
#define RH mccMonok_RH
#define DM mccMonok_DM
#define mosaic mccMonok_mosaic
#define width mccMonok_width
#define height mccMonok_height
#define verbose mccMonok_verbose
#line 141 "/usr/local/lib/mcstas/optics/Monochromator_curved.comp"
{
  if (mosaic != 0) {
    mos_rms_y = MIN2RAD*mosaic/sqrt(8*log(2));
    mos_rms_z = mos_rms_y; }
  else {
    mos_rms_y = MIN2RAD*mosaich/sqrt(8*log(2));
    mos_rms_z = MIN2RAD*mosaicv/sqrt(8*log(2)); }
  mos_rms_max = mos_rms_y > mos_rms_z ? mos_rms_y : mos_rms_z;

  mono_Q = Q;
  if (DM != 0) mono_Q = 2*PI/DM;

  if (mono_Q <= 0) { fprintf(stderr,"Monochromator_curved: %s: Error scattering vector Q = 0\n", NAME_CURRENT_COMP); exit(-1); }
  if (r0 <  0) { fprintf(stderr,"Monochromator_curved: %s: Error reflectivity r0 is negative\n", NAME_CURRENT_COMP); exit(-1); }
  if (r0 == 0) { fprintf(stderr,"Monochromator_curved: %s: Reflectivity r0 is null. Ingnoring component.\n", NAME_CURRENT_COMP); }
  if (NH*NV == 0) { fprintf(stderr,"Monochromator_curved: %s: no slabs ??? (NH or NV=0)\n", NAME_CURRENT_COMP); exit(-1); }


  if (verbose && r0)
  {
    printf("Monochromator_curved: component %s Q=%.3g Angs-1 (DM=%.4g Angs)\n", NAME_CURRENT_COMP, mono_Q, 2*PI/mono_Q);
    if (NH*NV == 1) printf("            flat.\n");
    else
    { if (NH > 1)
      { printf("            horizontal: %i blades", (int)NH);
        if (RH != 0) printf(" focusing with RH=%.3g [m]", RH);
        printf("\n");
      }
      if (NV > 1)
      { printf("            vertical:   %i blades", (int)NV);
        if (RV != 0) printf(" focusing with RV=%.3g [m]", RV);
        printf("\n");
      }
    }
  }

  if (reflect != NULL && r0)
  {
    if (verbose) fprintf(stdout, "Monochromator_curved : %s : Reflectivity data (k, R)\n", NAME_CURRENT_COMP);
    Table_Read(&rTable, reflect, 1); /* read 1st block data from file into rTable */
    Table_Rebin(&rTable);         /* rebin as evenly, increasing array */
    if (rTable.rows < 2) Table_Free(&rTable);
    if (verbose) Table_Info(rTable);
  } else rTable.data = NULL;

  if (transmit != NULL)
  {
    if (verbose) fprintf(stdout, "Monochromator_curved : %s : Transmission data (k, T)\n", NAME_CURRENT_COMP);
    Table_Read(&tTable, transmit, 1); /* read 1st block data from file into rTable */
    Table_Rebin(&tTable);         /* rebin as evenly, increasing array */
    if (tTable.rows < 2) Table_Free(&tTable);
    if (verbose) Table_Info(tTable);
  } else tTable.data = NULL;

  if (width == 0) SlabWidth = zwidth;
  else SlabWidth = (width+gap)/NH - gap;
  if (height == 0) SlabHeight = yheight;
  else SlabHeight = (height+gap)/NV - gap;

}
#line 14300 "D1A.c"
#undef verbose
#undef height
#undef width
#undef mosaic
#undef DM
#undef RH
#undef RV
#undef Q
#undef t0
#undef r0
#undef mosaicv
#undef mosaich
#undef NV
#undef NH
#undef gap
#undef yheight
#undef zwidth
#undef col
#undef row
#undef tTable
#undef rTable
#undef SlabHeight
#undef SlabWidth
#undef mono_Q
#undef mos_rms_max
#undef mos_rms_z
#undef mos_rms_y
#undef transmit
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

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


  /* Initializations for component Lmon. */
  SIG_MESSAGE("Lmon (Init)");
#line 144 "D1A.instr"
  mccLmon_xwidth = 0.05;
#line 144 "D1A.instr"
  mccLmon_yheight = 0.05;
#line 207 "D1A.instr"
  mccLmon_zthick = 0;
#line 207 "D1A.instr"
  mccLmon_xmin = 0;
#line 207 "D1A.instr"
  mccLmon_xmax = 0;
#line 207 "D1A.instr"
  mccLmon_ymin = 0;
#line 207 "D1A.instr"
  mccLmon_ymax = 0;
#line 207 "D1A.instr"
  mccLmon_zmin = 0;
#line 207 "D1A.instr"
  mccLmon_zmax = 0;
#line 144 "D1A.instr"
  mccLmon_bins = 50;
#line 207 "D1A.instr"
  mccLmon_min = -1e40;
#line 207 "D1A.instr"
  mccLmon_max = 1e40;
#line 207 "D1A.instr"
  mccLmon_restore_neutron = 0;
#line 14366 "D1A.c"

#define mccompcurname  Lmon
#define mccompcurtype  Monitor_nD
#define mccompcurindex 6
#define options mccLmon_options
#define filename mccLmon_filename
#define user1 mccLmon_user1
#define user2 mccLmon_user2
#define user3 mccLmon_user3
#define username1 mccLmon_username1
#define username2 mccLmon_username2
#define username3 mccLmon_username3
#define DEFS mccLmon_DEFS
#define Vars mccLmon_Vars
#define xwidth mccLmon_xwidth
#define yheight mccLmon_yheight
#define zthick mccLmon_zthick
#define xmin mccLmon_xmin
#define xmax mccLmon_xmax
#define ymin mccLmon_ymin
#define ymax mccLmon_ymax
#define zmin mccLmon_zmin
#define zmax mccLmon_zmax
#define bins mccLmon_bins
#define min mccLmon_min
#define max mccLmon_max
#define restore_neutron mccLmon_restore_neutron
#line 225 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  char tmp[256];
  strcpy(Vars.compcurname, NAME_CURRENT_COMP);
  if (options != NULL)
    strncpy(Vars.option, options, 1024);
  else {
    strcpy(Vars.option, "x y");
    printf("Monitor_nD: %s has no option specified. Setting to PSD ('x y') monitor.\n", NAME_CURRENT_COMP);
  }
  Vars.compcurpos = POS_A_CURRENT_COMP;

  if (strstr(Vars.option, "source"))
    strcat(Vars.option, " list, x y z vx vy vz t sx sy sz ");

  if (bins) { sprintf(tmp, " all bins=%ld ", (long)bins); strcat(Vars.option, tmp); }
  if (min > -FLT_MAX && max < FLT_MAX) { sprintf(tmp, " all limits=[%g %g]", min, max); strcat(Vars.option, tmp); }
  else if (min > -FLT_MAX) { sprintf(tmp, " all min=%g", min); strcat(Vars.option, tmp); }
  else if (max <  FLT_MAX) { sprintf(tmp, " all max=%g", max); strcat(Vars.option, tmp); }

  strncpy(Vars.UserName1, username1 && strlen(username1) ? username1 : "", 32);
  strncpy(Vars.UserName2, username2 && strlen(username2) ? username2 : "", 32);
  strncpy(Vars.UserName3, username3 && strlen(username3) ? username3 : "", 32);

  Monitor_nD_Init(&DEFS, &Vars, xwidth, yheight, zthick, xmin,xmax,ymin,ymax,zmin,zmax);

  if (filename != NULL) strncpy(Vars.Mon_File, filename, 128);

  /* check if user given filename with ext will be used more than once */
  if ( ((Vars.Flag_Multiple && Vars.Coord_Number > 1) || Vars.Flag_List) && strchr(Vars.Mon_File,'.') )
  { char *XY; XY = strrchr(Vars.Mon_File,'.'); *XY='_'; }
  
  if (restore_neutron) Vars.Flag_parallel=1;
}
#line 14428 "D1A.c"
#undef restore_neutron
#undef max
#undef min
#undef bins
#undef zmax
#undef zmin
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef zthick
#undef yheight
#undef xwidth
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component PSDsample. */
  SIG_MESSAGE("PSDsample (Init)");
#line 148 "D1A.instr"
  mccPSDsample_xwidth = 0.1;
#line 148 "D1A.instr"
  mccPSDsample_yheight = 0.1;
#line 207 "D1A.instr"
  mccPSDsample_zthick = 0;
#line 207 "D1A.instr"
  mccPSDsample_xmin = 0;
#line 207 "D1A.instr"
  mccPSDsample_xmax = 0;
#line 207 "D1A.instr"
  mccPSDsample_ymin = 0;
#line 207 "D1A.instr"
  mccPSDsample_ymax = 0;
#line 207 "D1A.instr"
  mccPSDsample_zmin = 0;
#line 207 "D1A.instr"
  mccPSDsample_zmax = 0;
#line 148 "D1A.instr"
  mccPSDsample_bins = 20;
#line 207 "D1A.instr"
  mccPSDsample_min = -1e40;
#line 207 "D1A.instr"
  mccPSDsample_max = 1e40;
#line 207 "D1A.instr"
  mccPSDsample_restore_neutron = 0;
#line 14484 "D1A.c"

#define mccompcurname  PSDsample
#define mccompcurtype  Monitor_nD
#define mccompcurindex 7
#define options mccPSDsample_options
#define filename mccPSDsample_filename
#define user1 mccPSDsample_user1
#define user2 mccPSDsample_user2
#define user3 mccPSDsample_user3
#define username1 mccPSDsample_username1
#define username2 mccPSDsample_username2
#define username3 mccPSDsample_username3
#define DEFS mccPSDsample_DEFS
#define Vars mccPSDsample_Vars
#define xwidth mccPSDsample_xwidth
#define yheight mccPSDsample_yheight
#define zthick mccPSDsample_zthick
#define xmin mccPSDsample_xmin
#define xmax mccPSDsample_xmax
#define ymin mccPSDsample_ymin
#define ymax mccPSDsample_ymax
#define zmin mccPSDsample_zmin
#define zmax mccPSDsample_zmax
#define bins mccPSDsample_bins
#define min mccPSDsample_min
#define max mccPSDsample_max
#define restore_neutron mccPSDsample_restore_neutron
#line 225 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  char tmp[256];
  strcpy(Vars.compcurname, NAME_CURRENT_COMP);
  if (options != NULL)
    strncpy(Vars.option, options, 1024);
  else {
    strcpy(Vars.option, "x y");
    printf("Monitor_nD: %s has no option specified. Setting to PSD ('x y') monitor.\n", NAME_CURRENT_COMP);
  }
  Vars.compcurpos = POS_A_CURRENT_COMP;

  if (strstr(Vars.option, "source"))
    strcat(Vars.option, " list, x y z vx vy vz t sx sy sz ");

  if (bins) { sprintf(tmp, " all bins=%ld ", (long)bins); strcat(Vars.option, tmp); }
  if (min > -FLT_MAX && max < FLT_MAX) { sprintf(tmp, " all limits=[%g %g]", min, max); strcat(Vars.option, tmp); }
  else if (min > -FLT_MAX) { sprintf(tmp, " all min=%g", min); strcat(Vars.option, tmp); }
  else if (max <  FLT_MAX) { sprintf(tmp, " all max=%g", max); strcat(Vars.option, tmp); }

  strncpy(Vars.UserName1, username1 && strlen(username1) ? username1 : "", 32);
  strncpy(Vars.UserName2, username2 && strlen(username2) ? username2 : "", 32);
  strncpy(Vars.UserName3, username3 && strlen(username3) ? username3 : "", 32);

  Monitor_nD_Init(&DEFS, &Vars, xwidth, yheight, zthick, xmin,xmax,ymin,ymax,zmin,zmax);

  if (filename != NULL) strncpy(Vars.Mon_File, filename, 128);

  /* check if user given filename with ext will be used more than once */
  if ( ((Vars.Flag_Multiple && Vars.Coord_Number > 1) || Vars.Flag_List) && strchr(Vars.Mon_File,'.') )
  { char *XY; XY = strrchr(Vars.Mon_File,'.'); *XY='_'; }
  
  if (restore_neutron) Vars.Flag_parallel=1;
}
#line 14546 "D1A.c"
#undef restore_neutron
#undef max
#undef min
#undef bins
#undef zmax
#undef zmin
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef zthick
#undef yheight
#undef xwidth
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

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


  /* Initializations for component Environment_in. */
  SIG_MESSAGE("Environment_in (Init)");
#line 160 "D1A.instr"
  mccEnvironment_in_d_phi = RAD2DEG * atan2 ( 0.5 , L3 );
#line 159 "D1A.instr"
  mccEnvironment_in_radius = 0.05;
#line 159 "D1A.instr"
  mccEnvironment_in_radius_i = 0.05 -0.002;
#line 159 "D1A.instr"
  mccEnvironment_in_yheight = 0.1;
#line 156 "D1A.instr"
  mccEnvironment_in_pack = 1;
#line 156 "D1A.instr"
  mccEnvironment_in_Vc = 0;
#line 156 "D1A.instr"
  mccEnvironment_in_sigma_abs = 0;
#line 156 "D1A.instr"
  mccEnvironment_in_sigma_inc = 0;
#line 156 "D1A.instr"
  mccEnvironment_in_Delta_d = 0;
#line 161 "D1A.instr"
  mccEnvironment_in_frac = 0;
#line 161 "D1A.instr"
  mccEnvironment_in_tfrac = 0.95;
#line 157 "D1A.instr"
  mccEnvironment_in_xwidth = 0;
#line 157 "D1A.instr"
  mccEnvironment_in_zthick = 0;
#line 157 "D1A.instr"
  mccEnvironment_in_xwidth_i = 0;
#line 157 "D1A.instr"
  mccEnvironment_in_yheight_i = 0;
#line 157 "D1A.instr"
  mccEnvironment_in_zthick_i = 0;
#line 157 "D1A.instr"
  mccEnvironment_in_h = 0;
#line 157 "D1A.instr"
  mccEnvironment_in_DW = 0;
#line 157 "D1A.instr"
  mccEnvironment_in_nb_atoms = 1;
#line 160 "D1A.instr"
  mccEnvironment_in_concentric = 1;
#line 158 "D1A.instr"
  mccEnvironment_in_density = 0;
#line 158 "D1A.instr"
  mccEnvironment_in_weight = 0;
#line 161 "D1A.instr"
  mccEnvironment_in_barns = 1;
#line 14626 "D1A.c"

#define mccompcurname  Environment_in
#define mccompcurtype  PowderN
#define mccompcurindex 9
#define reflections mccEnvironment_in_reflections
#define format mccEnvironment_in_format
#define line_info mccEnvironment_in_line_info
#define Nq mccEnvironment_in_Nq
#define my_s_v2 mccEnvironment_in_my_s_v2
#define my_s_v2_sum mccEnvironment_in_my_s_v2_sum
#define my_a_v mccEnvironment_in_my_a_v
#define my_inc mccEnvironment_in_my_inc
#define q_v mccEnvironment_in_q_v
#define w_v mccEnvironment_in_w_v
#define isrect mccEnvironment_in_isrect
#define columns mccEnvironment_in_columns
#define d_phi mccEnvironment_in_d_phi
#define radius mccEnvironment_in_radius
#define radius_i mccEnvironment_in_radius_i
#define yheight mccEnvironment_in_yheight
#define pack mccEnvironment_in_pack
#define Vc mccEnvironment_in_Vc
#define sigma_abs mccEnvironment_in_sigma_abs
#define sigma_inc mccEnvironment_in_sigma_inc
#define Delta_d mccEnvironment_in_Delta_d
#define frac mccEnvironment_in_frac
#define tfrac mccEnvironment_in_tfrac
#define xwidth mccEnvironment_in_xwidth
#define zthick mccEnvironment_in_zthick
#define xwidth_i mccEnvironment_in_xwidth_i
#define yheight_i mccEnvironment_in_yheight_i
#define zthick_i mccEnvironment_in_zthick_i
#define h mccEnvironment_in_h
#define DW mccEnvironment_in_DW
#define nb_atoms mccEnvironment_in_nb_atoms
#define concentric mccEnvironment_in_concentric
#define density mccEnvironment_in_density
#define weight mccEnvironment_in_weight
#define barns mccEnvironment_in_barns
#line 395 "/usr/local/lib/mcstas/samples/PowderN.comp"
{
  int i;
  struct line_data *L;
  line_info.Dd       = Delta_d;
  line_info.DWfactor = DW;
  line_info.V_0      = Vc;
  line_info.rho      = density;
  line_info.at_weight= weight;
  line_info.at_nb    = nb_atoms;
  line_info.sigma_a  = sigma_abs;
  line_info.sigma_i  = sigma_inc;
  line_info.flag_barns=barns;
  for (i=0; i< 8; i++) line_info.column_order[i] = columns[i];
  strncpy(line_info.compname, NAME_CURRENT_COMP, 256);
  
  /* Early cross-copy yheight and h */
  if (h && !yheight) {
    yheight = h;
  } else if (yheight && !h) {
    h = yheight;
  }
  
  if (!radius || !yheight ) {
    if (!xwidth || !yheight || !zthick) exit(fprintf(stderr,"PowderN: %s: sample has no volume (zero dimensions)\n", NAME_CURRENT_COMP));
    else isrect=1; }
  
  if (!yheight_i) {
    yheight_i = yheight;
  }
  
  if ((isrect && ((zthick_i > zthick) || (xwidth_i > xwidth) || (yheight_i > yheight))) || (!isrect && (radius_i > radius) || (yheight_i > yheight))) {
    exit(fprintf(stderr,"PowderN: %s: Inner hollow exeeds sample volume\n", NAME_CURRENT_COMP));
  }
  
  if (frac + tfrac > 1) {
    exit(fprintf(stderr,"PowderN: %s: You have requested an unmeaningful choice of the 'frac' and 'tfrac' parameters (sum is %g, exeeding 1)\n", 
		 NAME_CURRENT_COMP, frac+tfrac));
  } else if (frac + tfrac == 1) {
    printf("PowderN %s WARNING: You have requested all neutrons be attenuated or incoherently scattered!\n", NAME_CURRENT_COMP);
  }

  if (concentric) {
    printf("PowderN %s WARNING: Concentric mode - remember to include the 'opposite' copy of this component !\n (The equivalent, 'opposite' comp should have concentric=0)\n", NAME_CURRENT_COMP);
    if (tfrac == 0) {
      printf("PowderN %s WARNING: Concentric mode and tfrac==0 !? Don't you want any transmitted neutrons?\n", NAME_CURRENT_COMP);
    }
  }
  
  i = read_line_data(reflections, &line_info);
  
  if (frac && !line_info.sigma_i) {
    printf("PowderN %s WARNING: You have requested statistics for incoherent scattering but not defined sigma_inc!\n", NAME_CURRENT_COMP);
  }

  if (!line_info.V_0 && line_info.at_nb > 0
    && line_info.at_weight > 0 && line_info.rho > 0) {
    /* molar volume [cm^3/mol] = weight [g/mol] / density [g/cm^3] */
    /* atom density per Angs^3 = [mol/cm^3] * N_Avogadro *(1e-8)^3 */
    line_info.V_0 = line_info.at_nb
      /(line_info.rho/line_info.at_weight/1e24*6.02214199e23);
  }

  if (line_info.V_0 <= 0)
    exit(fprintf(stderr,"PowderN: %s: density/unit cell volume is NULL (Vc)\n", NAME_CURRENT_COMP));

  if (line_info.flag_barns) { /* Factor 100 to convert from barns to fm^2 */
    XsectionFactor = 100;
  } else {
    XsectionFactor = 1;
  }
  
  if (i) {
    L = line_info.list;

    Nq  = line_info.count;
    q_v = malloc(Nq*sizeof(double));
    w_v = malloc(Nq*sizeof(double));
    my_s_v2 = malloc(Nq*sizeof(double));
    if (!q_v || !w_v || !my_s_v2)
      exit(fprintf(stderr,"PowderN: %s: ERROR allocating memory (init)\n", NAME_CURRENT_COMP));
    for(i=0; i<Nq; i++)
    {
      my_s_v2[i] = 4*PI*PI*PI*pack*(L[i].DWfactor ? L[i].DWfactor : 1)
                 /(line_info.V_0*line_info.V_0*V2K*V2K)
                 *(L[i].j * L[i].F2 / L[i].q)*XsectionFactor;
      /* Is not yet divided by v^2 */
      /* Squires [3.103] */
      q_v[i] = L[i].q*K2V;
      w_v[i] = L[i].w;
    }
  }

  /* Is not yet divided by v */
  my_a_v = pack*line_info.sigma_a/line_info.V_0*2200*100;   // Factor 100 to convert from barns to fm^2
  my_inc = pack*line_info.sigma_i/line_info.V_0*100;   // Factor 100 to convert from barns to fm^2

  printf("PowderN: %s: Vc=%g [Angs] sigma_abs=%g [barn] sigma_inc=%g [barn]\n",
    NAME_CURRENT_COMP, line_info.V_0, line_info.sigma_a, line_info.sigma_i);

}
#line 14767 "D1A.c"
#undef barns
#undef weight
#undef density
#undef concentric
#undef nb_atoms
#undef DW
#undef h
#undef zthick_i
#undef yheight_i
#undef xwidth_i
#undef zthick
#undef xwidth
#undef tfrac
#undef frac
#undef Delta_d
#undef sigma_inc
#undef sigma_abs
#undef Vc
#undef pack
#undef yheight
#undef radius_i
#undef radius
#undef d_phi
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Container_in. */
  SIG_MESSAGE("Container_in (Init)");
#line 168 "D1A.instr"
  mccContainer_in_d_phi = RAD2DEG * atan2 ( 0.5 , L3 );
#line 167 "D1A.instr"
  mccContainer_in_radius = 0.008 / 2 + 1e-4;
#line 167 "D1A.instr"
  mccContainer_in_radius_i = 0.008 / 2;
#line 167 "D1A.instr"
  mccContainer_in_yheight = 0.05;
#line 156 "D1A.instr"
  mccContainer_in_pack = 1;
#line 156 "D1A.instr"
  mccContainer_in_Vc = 0;
#line 156 "D1A.instr"
  mccContainer_in_sigma_abs = 0;
#line 156 "D1A.instr"
  mccContainer_in_sigma_inc = 0;
#line 156 "D1A.instr"
  mccContainer_in_Delta_d = 0;
#line 169 "D1A.instr"
  mccContainer_in_frac = 0.05;
#line 169 "D1A.instr"
  mccContainer_in_tfrac = 0.93;
#line 157 "D1A.instr"
  mccContainer_in_xwidth = 0;
#line 157 "D1A.instr"
  mccContainer_in_zthick = 0;
#line 157 "D1A.instr"
  mccContainer_in_xwidth_i = 0;
#line 157 "D1A.instr"
  mccContainer_in_yheight_i = 0;
#line 157 "D1A.instr"
  mccContainer_in_zthick_i = 0;
#line 157 "D1A.instr"
  mccContainer_in_h = 0;
#line 157 "D1A.instr"
  mccContainer_in_DW = 0;
#line 157 "D1A.instr"
  mccContainer_in_nb_atoms = 1;
#line 168 "D1A.instr"
  mccContainer_in_concentric = 1;
#line 158 "D1A.instr"
  mccContainer_in_density = 0;
#line 158 "D1A.instr"
  mccContainer_in_weight = 0;
#line 158 "D1A.instr"
  mccContainer_in_barns = 1;
#line 14855 "D1A.c"

#define mccompcurname  Container_in
#define mccompcurtype  PowderN
#define mccompcurindex 10
#define reflections mccContainer_in_reflections
#define format mccContainer_in_format
#define line_info mccContainer_in_line_info
#define Nq mccContainer_in_Nq
#define my_s_v2 mccContainer_in_my_s_v2
#define my_s_v2_sum mccContainer_in_my_s_v2_sum
#define my_a_v mccContainer_in_my_a_v
#define my_inc mccContainer_in_my_inc
#define q_v mccContainer_in_q_v
#define w_v mccContainer_in_w_v
#define isrect mccContainer_in_isrect
#define columns mccContainer_in_columns
#define d_phi mccContainer_in_d_phi
#define radius mccContainer_in_radius
#define radius_i mccContainer_in_radius_i
#define yheight mccContainer_in_yheight
#define pack mccContainer_in_pack
#define Vc mccContainer_in_Vc
#define sigma_abs mccContainer_in_sigma_abs
#define sigma_inc mccContainer_in_sigma_inc
#define Delta_d mccContainer_in_Delta_d
#define frac mccContainer_in_frac
#define tfrac mccContainer_in_tfrac
#define xwidth mccContainer_in_xwidth
#define zthick mccContainer_in_zthick
#define xwidth_i mccContainer_in_xwidth_i
#define yheight_i mccContainer_in_yheight_i
#define zthick_i mccContainer_in_zthick_i
#define h mccContainer_in_h
#define DW mccContainer_in_DW
#define nb_atoms mccContainer_in_nb_atoms
#define concentric mccContainer_in_concentric
#define density mccContainer_in_density
#define weight mccContainer_in_weight
#define barns mccContainer_in_barns
#line 395 "/usr/local/lib/mcstas/samples/PowderN.comp"
{
  int i;
  struct line_data *L;
  line_info.Dd       = Delta_d;
  line_info.DWfactor = DW;
  line_info.V_0      = Vc;
  line_info.rho      = density;
  line_info.at_weight= weight;
  line_info.at_nb    = nb_atoms;
  line_info.sigma_a  = sigma_abs;
  line_info.sigma_i  = sigma_inc;
  line_info.flag_barns=barns;
  for (i=0; i< 8; i++) line_info.column_order[i] = columns[i];
  strncpy(line_info.compname, NAME_CURRENT_COMP, 256);
  
  /* Early cross-copy yheight and h */
  if (h && !yheight) {
    yheight = h;
  } else if (yheight && !h) {
    h = yheight;
  }
  
  if (!radius || !yheight ) {
    if (!xwidth || !yheight || !zthick) exit(fprintf(stderr,"PowderN: %s: sample has no volume (zero dimensions)\n", NAME_CURRENT_COMP));
    else isrect=1; }
  
  if (!yheight_i) {
    yheight_i = yheight;
  }
  
  if ((isrect && ((zthick_i > zthick) || (xwidth_i > xwidth) || (yheight_i > yheight))) || (!isrect && (radius_i > radius) || (yheight_i > yheight))) {
    exit(fprintf(stderr,"PowderN: %s: Inner hollow exeeds sample volume\n", NAME_CURRENT_COMP));
  }
  
  if (frac + tfrac > 1) {
    exit(fprintf(stderr,"PowderN: %s: You have requested an unmeaningful choice of the 'frac' and 'tfrac' parameters (sum is %g, exeeding 1)\n", 
		 NAME_CURRENT_COMP, frac+tfrac));
  } else if (frac + tfrac == 1) {
    printf("PowderN %s WARNING: You have requested all neutrons be attenuated or incoherently scattered!\n", NAME_CURRENT_COMP);
  }

  if (concentric) {
    printf("PowderN %s WARNING: Concentric mode - remember to include the 'opposite' copy of this component !\n (The equivalent, 'opposite' comp should have concentric=0)\n", NAME_CURRENT_COMP);
    if (tfrac == 0) {
      printf("PowderN %s WARNING: Concentric mode and tfrac==0 !? Don't you want any transmitted neutrons?\n", NAME_CURRENT_COMP);
    }
  }
  
  i = read_line_data(reflections, &line_info);
  
  if (frac && !line_info.sigma_i) {
    printf("PowderN %s WARNING: You have requested statistics for incoherent scattering but not defined sigma_inc!\n", NAME_CURRENT_COMP);
  }

  if (!line_info.V_0 && line_info.at_nb > 0
    && line_info.at_weight > 0 && line_info.rho > 0) {
    /* molar volume [cm^3/mol] = weight [g/mol] / density [g/cm^3] */
    /* atom density per Angs^3 = [mol/cm^3] * N_Avogadro *(1e-8)^3 */
    line_info.V_0 = line_info.at_nb
      /(line_info.rho/line_info.at_weight/1e24*6.02214199e23);
  }

  if (line_info.V_0 <= 0)
    exit(fprintf(stderr,"PowderN: %s: density/unit cell volume is NULL (Vc)\n", NAME_CURRENT_COMP));

  if (line_info.flag_barns) { /* Factor 100 to convert from barns to fm^2 */
    XsectionFactor = 100;
  } else {
    XsectionFactor = 1;
  }
  
  if (i) {
    L = line_info.list;

    Nq  = line_info.count;
    q_v = malloc(Nq*sizeof(double));
    w_v = malloc(Nq*sizeof(double));
    my_s_v2 = malloc(Nq*sizeof(double));
    if (!q_v || !w_v || !my_s_v2)
      exit(fprintf(stderr,"PowderN: %s: ERROR allocating memory (init)\n", NAME_CURRENT_COMP));
    for(i=0; i<Nq; i++)
    {
      my_s_v2[i] = 4*PI*PI*PI*pack*(L[i].DWfactor ? L[i].DWfactor : 1)
                 /(line_info.V_0*line_info.V_0*V2K*V2K)
                 *(L[i].j * L[i].F2 / L[i].q)*XsectionFactor;
      /* Is not yet divided by v^2 */
      /* Squires [3.103] */
      q_v[i] = L[i].q*K2V;
      w_v[i] = L[i].w;
    }
  }

  /* Is not yet divided by v */
  my_a_v = pack*line_info.sigma_a/line_info.V_0*2200*100;   // Factor 100 to convert from barns to fm^2
  my_inc = pack*line_info.sigma_i/line_info.V_0*100;   // Factor 100 to convert from barns to fm^2

  printf("PowderN: %s: Vc=%g [Angs] sigma_abs=%g [barn] sigma_inc=%g [barn]\n",
    NAME_CURRENT_COMP, line_info.V_0, line_info.sigma_a, line_info.sigma_i);

}
#line 14996 "D1A.c"
#undef barns
#undef weight
#undef density
#undef concentric
#undef nb_atoms
#undef DW
#undef h
#undef zthick_i
#undef yheight_i
#undef xwidth_i
#undef zthick
#undef xwidth
#undef tfrac
#undef frac
#undef Delta_d
#undef sigma_inc
#undef sigma_abs
#undef Vc
#undef pack
#undef yheight
#undef radius_i
#undef radius
#undef d_phi
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Sample_liq. */
  SIG_MESSAGE("Sample_liq (Init)");
#line 175 "D1A.instr"
  mccSample_liq_radius = 0.008 / 2;
#line 252 "D1A.instr"
  mccSample_liq_thickness = 0;
#line 253 "D1A.instr"
  mccSample_liq_xwidth = 0;
#line 175 "D1A.instr"
  mccSample_liq_yheight = 0.03;
#line 253 "D1A.instr"
  mccSample_liq_zdepth = 0;
#line 254 "D1A.instr"
  mccSample_liq_qmin = 0;
#line 254 "D1A.instr"
  mccSample_liq_qmax = 0;
#line 254 "D1A.instr"
  mccSample_liq_wmin = 0;
#line 254 "D1A.instr"
  mccSample_liq_wmax = 0;
#line 254 "D1A.instr"
  mccSample_liq_auto_qw = 0;
#line 255 "D1A.instr"
  mccSample_liq_threshold = 1e-10;
#line 176 "D1A.instr"
  mccSample_liq_order = 1;
#line 255 "D1A.instr"
  mccSample_liq_T = 0;
#line 255 "D1A.instr"
  mccSample_liq_verbose = 1;
#line 176 "D1A.instr"
  mccSample_liq_d_phi = RAD2DEG * atan2 ( 0.5 , L3 );
#line 255 "D1A.instr"
  mccSample_liq_concentric = 0;
#line 256 "D1A.instr"
  mccSample_liq_V_rho = 0;
#line 256 "D1A.instr"
  mccSample_liq_sigma_abs = 0;
#line 256 "D1A.instr"
  mccSample_liq_sigma_coh = 0;
#line 256 "D1A.instr"
  mccSample_liq_sigma_inc = 0;
#line 256 "D1A.instr"
  mccSample_liq_save_sqw = 0;
#line 257 "D1A.instr"
  mccSample_liq_powder_Dd = 0;
#line 257 "D1A.instr"
  mccSample_liq_powder_DW = 0;
#line 257 "D1A.instr"
  mccSample_liq_powder_Vc = 0;
#line 257 "D1A.instr"
  mccSample_liq_density = 0;
#line 257 "D1A.instr"
  mccSample_liq_weight = 0;
#line 176 "D1A.instr"
  mccSample_liq_p_interact = 0.99;
#line 258 "D1A.instr"
  mccSample_liq_auto_norm = 0;
#line 258 "D1A.instr"
  mccSample_liq_powder_barns = 1;
#line 15096 "D1A.c"

#define mccompcurname  Sample_liq
#define mccompcurtype  Isotropic_Sqw
#define mccompcurindex 11
#define Sqw_coh mccSample_liq_Sqw_coh
#define Sqw_inc mccSample_liq_Sqw_inc
#define powder_format mccSample_liq_powder_format
#define geometry mccSample_liq_geometry
#define VarSqw mccSample_liq_VarSqw
#define columns mccSample_liq_columns
#define offdata mccSample_liq_offdata
#define radius mccSample_liq_radius
#define thickness mccSample_liq_thickness
#define xwidth mccSample_liq_xwidth
#define yheight mccSample_liq_yheight
#define zdepth mccSample_liq_zdepth
#define qmin mccSample_liq_qmin
#define qmax mccSample_liq_qmax
#define wmin mccSample_liq_wmin
#define wmax mccSample_liq_wmax
#define auto_qw mccSample_liq_auto_qw
#define threshold mccSample_liq_threshold
#define order mccSample_liq_order
#define T mccSample_liq_T
#define verbose mccSample_liq_verbose
#define d_phi mccSample_liq_d_phi
#define concentric mccSample_liq_concentric
#define V_rho mccSample_liq_V_rho
#define sigma_abs mccSample_liq_sigma_abs
#define sigma_coh mccSample_liq_sigma_coh
#define sigma_inc mccSample_liq_sigma_inc
#define save_sqw mccSample_liq_save_sqw
#define powder_Dd mccSample_liq_powder_Dd
#define powder_DW mccSample_liq_powder_DW
#define powder_Vc mccSample_liq_powder_Vc
#define density mccSample_liq_density
#define weight mccSample_liq_weight
#define p_interact mccSample_liq_p_interact
#define auto_norm mccSample_liq_auto_norm
#define powder_barns mccSample_liq_powder_barns
#line 1242 "/usr/local/lib/mcstas/samples/Isotropic_Sqw.comp"
{
  int i;
  /* check for parameters */

  VarSqw.verbose_output= verbose;
  VarSqw.shape = -1; /* -1:no shape, 0:cyl, 1:box, 2:sphere, 3:any-shape  */
  if (geometry && strlen(geometry) && strcmp(geometry, "NULL") && strcmp(geometry, "0")) {
	  if (off_init(geometry, xwidth, yheight, zdepth, &offdata)) {
      VarSqw.shape=3; thickness=0; concentric=0;
    }
  }
  else if (xwidth && yheight && zdepth)  VarSqw.shape=1; /* box */
  else if (radius > 0 && yheight)        VarSqw.shape=0; /* cylinder */
  else if (radius > 0 && !yheight)       VarSqw.shape=2; /* sphere */

  if (VarSqw.shape < 0) 
    exit(fprintf(stderr,"Isotropic_Sqw: %s: sample has invalid dimensions.\n"
                        "ERROR          Please check parameter values (xwidth, yheight, zdepth, radius).\n", NAME_CURRENT_COMP));
  
  if (thickness) {
    if (radius && (radius < thickness || (yheight && yheight < 2*thickness))) {
      fprintf(stderr,"Isotropic_Sqw: %s: hollow sample thickness is larger than its volume (sphere/cylinder).\n"
                     "WARNING        Please check parameter values. Using bulk sample (thickness=0).\n", NAME_CURRENT_COMP);
      thickness=0;
    }
    else if (!radius && (xwidth < 2*thickness || yheight < 2*thickness || zdepth < 2*thickness)) {
      fprintf(stderr,"Isotropic_Sqw: %s: hollow sample thickness is larger than its volume (box).\n"
                     "WARNING        Please check parameter values. Using bulk sample (thickness=0).\n", NAME_CURRENT_COMP);
      thickness=0;
    }
  }
  
  if (VarSqw.verbose_output) {
    switch (VarSqw.shape) {
      case 0: printf("Isotropic_Sqw: %s: is a %s%s : radius=%f thickness=%f height=%f \n",
              NAME_CURRENT_COMP, (thickness > 0 ? "hollow ":""),
              "Cylinder",
              radius,thickness,yheight);
              break;
      case 1: printf("Isotropic_Sqw: %s: is a %sBox : width=%f height=%f depth=%f \n",
              NAME_CURRENT_COMP, (thickness>0 ? "hollow" : ""), xwidth,yheight,zdepth);
              break;
      case 2: printf("Isotropic_Sqw: %s: is a %s%s : radius=%f thickness=%f\n",
              NAME_CURRENT_COMP, (thickness > 0 ? "hollow ":""),
              "Sphere",
              radius,thickness);
              break;
      case 3: printf("Isotropic_Sqw: %s: is a volume defined from file %s\n",
              NAME_CURRENT_COMP, geometry);
    }
  }

  if (concentric && thickness<=0) {
    printf("Isotropic_Sqw: %s:Can not use concentric mode\n"
           "WARNING        on non hollow shape. Ignoring.\n",
           NAME_CURRENT_COMP);
    concentric=0;
  }

  strncpy(VarSqw.compname, NAME_CURRENT_COMP, 256);
  VarSqw.T2E       =(1/11.605);   /* Kelvin to meV */
  VarSqw.sqSE2K    = (V2K*SE2V)*(V2K*SE2V);
  VarSqw.sqw_threshold = (threshold > 0 ? threshold : 0);
  VarSqw.s_abs     = sigma_abs;
  VarSqw.s_coh     = sigma_coh;
  VarSqw.s_inc     = sigma_inc; /* s_scatt member initialized in Sqw_init */
  VarSqw.maxloop   = 100;       /* atempts to close triangle */
  VarSqw.minevents = 100;       /* minimal # of events required to get dynamical range */
  VarSqw.neutron_removed = 0;
  VarSqw.neutron_enter   = 0;
  VarSqw.neutron_pmult   = 0;
  VarSqw.neutron_exit    = 0;
  VarSqw.w_max     = (wmax > 0 ? wmax : FLT_MAX);
  VarSqw.w_min     = (wmin > 0 ? wmin : 0);
  VarSqw.q_max     = (qmax > 0 ? qmax : FLT_MAX);
  VarSqw.q_min     = (qmin > 0 ? qmin : 0);
  VarSqw.rho       = V_rho;
  VarSqw.sqw_norm  = auto_norm;
  VarSqw.sqw_auto  = auto_qw;
  VarSqw.mean_scatt= 0;
  VarSqw.mean_abs  = 0;
  VarSqw.psum_scatt= 0;
  VarSqw.single    = 0;
  VarSqw.multi     = 0;
  VarSqw.barns     = powder_barns;

  /* PowderN compatibility members */
  VarSqw.Dd        = powder_Dd;
  VarSqw.DWfactor  = powder_DW;
  VarSqw.Temperature= T;
  for (i=0; i< 9; i++) VarSqw.column_order[i] = columns[i];
  VarSqw.column_order[8] = (VarSqw.column_order[0] >= 0 ? 0 : 2);

  if (!V_rho && density && weight)
    VarSqw.rho = density/weight/1e24*6.02214199e23;

  /* optional ways to define rho */
  if (!VarSqw.rho && powder_Vc > 0)
    VarSqw.rho = 1/powder_Vc;
  if (!Sqw_init(&VarSqw, Sqw_coh, Sqw_inc)) {
    printf("Isotropic_Sqw: %s: ERROR importing data files (Sqw_init coh=%s inc=%s).\n",NAME_CURRENT_COMP, Sqw_coh, Sqw_inc);
  }
  if (VarSqw.s_coh < 0) VarSqw.s_coh=0;
  if (VarSqw.s_inc < 0) VarSqw.s_inc=0;
  if (VarSqw.s_abs < 0) VarSqw.s_abs=0;
  if ((VarSqw.s_coh > 0 || VarSqw.s_inc > 0) && VarSqw.rho <= 0) {
    printf("Isotropic_Sqw: %s: WARNING: Null density (V_rho). Unactivating component.\n",NAME_CURRENT_COMP);
    VarSqw.s_coh=VarSqw.s_inc=0;
  }
  /* 100: convert from barns to fm^2 */
  VarSqw.my_a_v  =(VarSqw.rho*100*VarSqw.s_abs*2200);
  VarSqw.my_s    =(VarSqw.rho*100*(VarSqw.s_coh>0 ? VarSqw.s_coh : 0
                                     +VarSqw.s_inc>0 ? VarSqw.s_inc : 0));
  if ((VarSqw.s_coh > 0 || VarSqw.s_inc > 0) && !VarSqw.Temperature
   && (VarSqw.Data_coh.intensity || VarSqw.Data_inc.intensity)
   && VarSqw.verbose_output)
    printf("Isotropic_Sqw: %s: Sample temperature not defined (T=0).\n"
           "Warning        Disabling detailed balance.\n", NAME_CURRENT_COMP);
  if (VarSqw.s_coh<=0 && VarSqw.s_inc<=0) {
    printf("Isotropic_Sqw: %s: Scattering cross section is zero\n"
           "ERROR          (sigma_coh, sigma_inc).\n",NAME_CURRENT_COMP);
  }
  if (d_phi) d_phi = fabs(d_phi)*DEG2RAD;

  if (d_phi > PI) d_phi = 0; /* V_scatt on 4*PI */

  if (d_phi && order != 1) {
    printf("Isotropic_Sqw: %s: Focusing can only apply for single\n"
           "               scattering. Setting to 4*PI mode.\n",
           NAME_CURRENT_COMP);
    d_phi = 0;
  }

  VarSqw.w_max     = (wmax > 0 ? wmax : 0);
  VarSqw.w_min     = (wmin > 0 ? wmin : 0);
  VarSqw.q_max     = (qmax > 0 ? qmax : 0);
  VarSqw.q_min     = (qmin > 0 ? qmin : 0);
/* end INITIALIZE */
}
#line 15277 "D1A.c"
#undef powder_barns
#undef auto_norm
#undef p_interact
#undef weight
#undef density
#undef powder_Vc
#undef powder_DW
#undef powder_Dd
#undef save_sqw
#undef sigma_inc
#undef sigma_coh
#undef sigma_abs
#undef V_rho
#undef concentric
#undef d_phi
#undef verbose
#undef T
#undef order
#undef threshold
#undef auto_qw
#undef wmax
#undef wmin
#undef qmax
#undef qmin
#undef zdepth
#undef yheight
#undef xwidth
#undef thickness
#undef radius
#undef offdata
#undef columns
#undef VarSqw
#undef geometry
#undef powder_format
#undef Sqw_inc
#undef Sqw_coh
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Sample. */
  SIG_MESSAGE("Sample (Init)");
#line 186 "D1A.instr"
  mccSample_d_phi = RAD2DEG * atan2 ( 0.5 , L3 );
#line 185 "D1A.instr"
  mccSample_radius = 0.008 / 2;
#line 155 "D1A.instr"
  mccSample_radius_i = 0;
#line 185 "D1A.instr"
  mccSample_yheight = 0.03;
#line 156 "D1A.instr"
  mccSample_pack = 1;
#line 156 "D1A.instr"
  mccSample_Vc = 0;
#line 156 "D1A.instr"
  mccSample_sigma_abs = 0;
#line 156 "D1A.instr"
  mccSample_sigma_inc = 0;
#line 156 "D1A.instr"
  mccSample_Delta_d = 0;
#line 186 "D1A.instr"
  mccSample_frac = 0.05;
#line 186 "D1A.instr"
  mccSample_tfrac = 0.08;
#line 157 "D1A.instr"
  mccSample_xwidth = 0;
#line 157 "D1A.instr"
  mccSample_zthick = 0;
#line 157 "D1A.instr"
  mccSample_xwidth_i = 0;
#line 157 "D1A.instr"
  mccSample_yheight_i = 0;
#line 157 "D1A.instr"
  mccSample_zthick_i = 0;
#line 157 "D1A.instr"
  mccSample_h = 0;
#line 157 "D1A.instr"
  mccSample_DW = 0;
#line 157 "D1A.instr"
  mccSample_nb_atoms = 1;
#line 158 "D1A.instr"
  mccSample_concentric = 0;
#line 158 "D1A.instr"
  mccSample_density = 0;
#line 158 "D1A.instr"
  mccSample_weight = 0;
#line 158 "D1A.instr"
  mccSample_barns = 1;
#line 15366 "D1A.c"

#define mccompcurname  Sample
#define mccompcurtype  PowderN
#define mccompcurindex 12
#define reflections mccSample_reflections
#define format mccSample_format
#define line_info mccSample_line_info
#define Nq mccSample_Nq
#define my_s_v2 mccSample_my_s_v2
#define my_s_v2_sum mccSample_my_s_v2_sum
#define my_a_v mccSample_my_a_v
#define my_inc mccSample_my_inc
#define q_v mccSample_q_v
#define w_v mccSample_w_v
#define isrect mccSample_isrect
#define columns mccSample_columns
#define d_phi mccSample_d_phi
#define radius mccSample_radius
#define radius_i mccSample_radius_i
#define yheight mccSample_yheight
#define pack mccSample_pack
#define Vc mccSample_Vc
#define sigma_abs mccSample_sigma_abs
#define sigma_inc mccSample_sigma_inc
#define Delta_d mccSample_Delta_d
#define frac mccSample_frac
#define tfrac mccSample_tfrac
#define xwidth mccSample_xwidth
#define zthick mccSample_zthick
#define xwidth_i mccSample_xwidth_i
#define yheight_i mccSample_yheight_i
#define zthick_i mccSample_zthick_i
#define h mccSample_h
#define DW mccSample_DW
#define nb_atoms mccSample_nb_atoms
#define concentric mccSample_concentric
#define density mccSample_density
#define weight mccSample_weight
#define barns mccSample_barns
#line 395 "/usr/local/lib/mcstas/samples/PowderN.comp"
{
  int i;
  struct line_data *L;
  line_info.Dd       = Delta_d;
  line_info.DWfactor = DW;
  line_info.V_0      = Vc;
  line_info.rho      = density;
  line_info.at_weight= weight;
  line_info.at_nb    = nb_atoms;
  line_info.sigma_a  = sigma_abs;
  line_info.sigma_i  = sigma_inc;
  line_info.flag_barns=barns;
  for (i=0; i< 8; i++) line_info.column_order[i] = columns[i];
  strncpy(line_info.compname, NAME_CURRENT_COMP, 256);
  
  /* Early cross-copy yheight and h */
  if (h && !yheight) {
    yheight = h;
  } else if (yheight && !h) {
    h = yheight;
  }
  
  if (!radius || !yheight ) {
    if (!xwidth || !yheight || !zthick) exit(fprintf(stderr,"PowderN: %s: sample has no volume (zero dimensions)\n", NAME_CURRENT_COMP));
    else isrect=1; }
  
  if (!yheight_i) {
    yheight_i = yheight;
  }
  
  if ((isrect && ((zthick_i > zthick) || (xwidth_i > xwidth) || (yheight_i > yheight))) || (!isrect && (radius_i > radius) || (yheight_i > yheight))) {
    exit(fprintf(stderr,"PowderN: %s: Inner hollow exeeds sample volume\n", NAME_CURRENT_COMP));
  }
  
  if (frac + tfrac > 1) {
    exit(fprintf(stderr,"PowderN: %s: You have requested an unmeaningful choice of the 'frac' and 'tfrac' parameters (sum is %g, exeeding 1)\n", 
		 NAME_CURRENT_COMP, frac+tfrac));
  } else if (frac + tfrac == 1) {
    printf("PowderN %s WARNING: You have requested all neutrons be attenuated or incoherently scattered!\n", NAME_CURRENT_COMP);
  }

  if (concentric) {
    printf("PowderN %s WARNING: Concentric mode - remember to include the 'opposite' copy of this component !\n (The equivalent, 'opposite' comp should have concentric=0)\n", NAME_CURRENT_COMP);
    if (tfrac == 0) {
      printf("PowderN %s WARNING: Concentric mode and tfrac==0 !? Don't you want any transmitted neutrons?\n", NAME_CURRENT_COMP);
    }
  }
  
  i = read_line_data(reflections, &line_info);
  
  if (frac && !line_info.sigma_i) {
    printf("PowderN %s WARNING: You have requested statistics for incoherent scattering but not defined sigma_inc!\n", NAME_CURRENT_COMP);
  }

  if (!line_info.V_0 && line_info.at_nb > 0
    && line_info.at_weight > 0 && line_info.rho > 0) {
    /* molar volume [cm^3/mol] = weight [g/mol] / density [g/cm^3] */
    /* atom density per Angs^3 = [mol/cm^3] * N_Avogadro *(1e-8)^3 */
    line_info.V_0 = line_info.at_nb
      /(line_info.rho/line_info.at_weight/1e24*6.02214199e23);
  }

  if (line_info.V_0 <= 0)
    exit(fprintf(stderr,"PowderN: %s: density/unit cell volume is NULL (Vc)\n", NAME_CURRENT_COMP));

  if (line_info.flag_barns) { /* Factor 100 to convert from barns to fm^2 */
    XsectionFactor = 100;
  } else {
    XsectionFactor = 1;
  }
  
  if (i) {
    L = line_info.list;

    Nq  = line_info.count;
    q_v = malloc(Nq*sizeof(double));
    w_v = malloc(Nq*sizeof(double));
    my_s_v2 = malloc(Nq*sizeof(double));
    if (!q_v || !w_v || !my_s_v2)
      exit(fprintf(stderr,"PowderN: %s: ERROR allocating memory (init)\n", NAME_CURRENT_COMP));
    for(i=0; i<Nq; i++)
    {
      my_s_v2[i] = 4*PI*PI*PI*pack*(L[i].DWfactor ? L[i].DWfactor : 1)
                 /(line_info.V_0*line_info.V_0*V2K*V2K)
                 *(L[i].j * L[i].F2 / L[i].q)*XsectionFactor;
      /* Is not yet divided by v^2 */
      /* Squires [3.103] */
      q_v[i] = L[i].q*K2V;
      w_v[i] = L[i].w;
    }
  }

  /* Is not yet divided by v */
  my_a_v = pack*line_info.sigma_a/line_info.V_0*2200*100;   // Factor 100 to convert from barns to fm^2
  my_inc = pack*line_info.sigma_i/line_info.V_0*100;   // Factor 100 to convert from barns to fm^2

  printf("PowderN: %s: Vc=%g [Angs] sigma_abs=%g [barn] sigma_inc=%g [barn]\n",
    NAME_CURRENT_COMP, line_info.V_0, line_info.sigma_a, line_info.sigma_i);

}
#line 15507 "D1A.c"
#undef barns
#undef weight
#undef density
#undef concentric
#undef nb_atoms
#undef DW
#undef h
#undef zthick_i
#undef yheight_i
#undef xwidth_i
#undef zthick
#undef xwidth
#undef tfrac
#undef frac
#undef Delta_d
#undef sigma_inc
#undef sigma_abs
#undef Vc
#undef pack
#undef yheight
#undef radius_i
#undef radius
#undef d_phi
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Container_out. */
  SIG_MESSAGE("Container_out (Init)");
#line 168 "D1A.instr"
  mccContainer_out_d_phi = RAD2DEG * atan2 ( 0.5 , L3 );
#line 167 "D1A.instr"
  mccContainer_out_radius = 0.008 / 2 + 1e-4;
#line 167 "D1A.instr"
  mccContainer_out_radius_i = 0.008 / 2;
#line 167 "D1A.instr"
  mccContainer_out_yheight = 0.05;
#line 156 "D1A.instr"
  mccContainer_out_pack = 1;
#line 156 "D1A.instr"
  mccContainer_out_Vc = 0;
#line 156 "D1A.instr"
  mccContainer_out_sigma_abs = 0;
#line 156 "D1A.instr"
  mccContainer_out_sigma_inc = 0;
#line 156 "D1A.instr"
  mccContainer_out_Delta_d = 0;
#line 169 "D1A.instr"
  mccContainer_out_frac = 0.05;
#line 169 "D1A.instr"
  mccContainer_out_tfrac = 0.93;
#line 157 "D1A.instr"
  mccContainer_out_xwidth = 0;
#line 157 "D1A.instr"
  mccContainer_out_zthick = 0;
#line 157 "D1A.instr"
  mccContainer_out_xwidth_i = 0;
#line 157 "D1A.instr"
  mccContainer_out_yheight_i = 0;
#line 157 "D1A.instr"
  mccContainer_out_zthick_i = 0;
#line 157 "D1A.instr"
  mccContainer_out_h = 0;
#line 157 "D1A.instr"
  mccContainer_out_DW = 0;
#line 157 "D1A.instr"
  mccContainer_out_nb_atoms = 1;
#line 194 "D1A.instr"
  mccContainer_out_concentric = 0;
#line 158 "D1A.instr"
  mccContainer_out_density = 0;
#line 158 "D1A.instr"
  mccContainer_out_weight = 0;
#line 158 "D1A.instr"
  mccContainer_out_barns = 1;
#line 15595 "D1A.c"

#define mccompcurname  Container_out
#define mccompcurtype  PowderN
#define mccompcurindex 13
#define reflections mccContainer_out_reflections
#define format mccContainer_out_format
#define line_info mccContainer_out_line_info
#define Nq mccContainer_out_Nq
#define my_s_v2 mccContainer_out_my_s_v2
#define my_s_v2_sum mccContainer_out_my_s_v2_sum
#define my_a_v mccContainer_out_my_a_v
#define my_inc mccContainer_out_my_inc
#define q_v mccContainer_out_q_v
#define w_v mccContainer_out_w_v
#define isrect mccContainer_out_isrect
#define columns mccContainer_out_columns
#define d_phi mccContainer_out_d_phi
#define radius mccContainer_out_radius
#define radius_i mccContainer_out_radius_i
#define yheight mccContainer_out_yheight
#define pack mccContainer_out_pack
#define Vc mccContainer_out_Vc
#define sigma_abs mccContainer_out_sigma_abs
#define sigma_inc mccContainer_out_sigma_inc
#define Delta_d mccContainer_out_Delta_d
#define frac mccContainer_out_frac
#define tfrac mccContainer_out_tfrac
#define xwidth mccContainer_out_xwidth
#define zthick mccContainer_out_zthick
#define xwidth_i mccContainer_out_xwidth_i
#define yheight_i mccContainer_out_yheight_i
#define zthick_i mccContainer_out_zthick_i
#define h mccContainer_out_h
#define DW mccContainer_out_DW
#define nb_atoms mccContainer_out_nb_atoms
#define concentric mccContainer_out_concentric
#define density mccContainer_out_density
#define weight mccContainer_out_weight
#define barns mccContainer_out_barns
#line 395 "/usr/local/lib/mcstas/samples/PowderN.comp"
{
  int i;
  struct line_data *L;
  line_info.Dd       = Delta_d;
  line_info.DWfactor = DW;
  line_info.V_0      = Vc;
  line_info.rho      = density;
  line_info.at_weight= weight;
  line_info.at_nb    = nb_atoms;
  line_info.sigma_a  = sigma_abs;
  line_info.sigma_i  = sigma_inc;
  line_info.flag_barns=barns;
  for (i=0; i< 8; i++) line_info.column_order[i] = columns[i];
  strncpy(line_info.compname, NAME_CURRENT_COMP, 256);
  
  /* Early cross-copy yheight and h */
  if (h && !yheight) {
    yheight = h;
  } else if (yheight && !h) {
    h = yheight;
  }
  
  if (!radius || !yheight ) {
    if (!xwidth || !yheight || !zthick) exit(fprintf(stderr,"PowderN: %s: sample has no volume (zero dimensions)\n", NAME_CURRENT_COMP));
    else isrect=1; }
  
  if (!yheight_i) {
    yheight_i = yheight;
  }
  
  if ((isrect && ((zthick_i > zthick) || (xwidth_i > xwidth) || (yheight_i > yheight))) || (!isrect && (radius_i > radius) || (yheight_i > yheight))) {
    exit(fprintf(stderr,"PowderN: %s: Inner hollow exeeds sample volume\n", NAME_CURRENT_COMP));
  }
  
  if (frac + tfrac > 1) {
    exit(fprintf(stderr,"PowderN: %s: You have requested an unmeaningful choice of the 'frac' and 'tfrac' parameters (sum is %g, exeeding 1)\n", 
		 NAME_CURRENT_COMP, frac+tfrac));
  } else if (frac + tfrac == 1) {
    printf("PowderN %s WARNING: You have requested all neutrons be attenuated or incoherently scattered!\n", NAME_CURRENT_COMP);
  }

  if (concentric) {
    printf("PowderN %s WARNING: Concentric mode - remember to include the 'opposite' copy of this component !\n (The equivalent, 'opposite' comp should have concentric=0)\n", NAME_CURRENT_COMP);
    if (tfrac == 0) {
      printf("PowderN %s WARNING: Concentric mode and tfrac==0 !? Don't you want any transmitted neutrons?\n", NAME_CURRENT_COMP);
    }
  }
  
  i = read_line_data(reflections, &line_info);
  
  if (frac && !line_info.sigma_i) {
    printf("PowderN %s WARNING: You have requested statistics for incoherent scattering but not defined sigma_inc!\n", NAME_CURRENT_COMP);
  }

  if (!line_info.V_0 && line_info.at_nb > 0
    && line_info.at_weight > 0 && line_info.rho > 0) {
    /* molar volume [cm^3/mol] = weight [g/mol] / density [g/cm^3] */
    /* atom density per Angs^3 = [mol/cm^3] * N_Avogadro *(1e-8)^3 */
    line_info.V_0 = line_info.at_nb
      /(line_info.rho/line_info.at_weight/1e24*6.02214199e23);
  }

  if (line_info.V_0 <= 0)
    exit(fprintf(stderr,"PowderN: %s: density/unit cell volume is NULL (Vc)\n", NAME_CURRENT_COMP));

  if (line_info.flag_barns) { /* Factor 100 to convert from barns to fm^2 */
    XsectionFactor = 100;
  } else {
    XsectionFactor = 1;
  }
  
  if (i) {
    L = line_info.list;

    Nq  = line_info.count;
    q_v = malloc(Nq*sizeof(double));
    w_v = malloc(Nq*sizeof(double));
    my_s_v2 = malloc(Nq*sizeof(double));
    if (!q_v || !w_v || !my_s_v2)
      exit(fprintf(stderr,"PowderN: %s: ERROR allocating memory (init)\n", NAME_CURRENT_COMP));
    for(i=0; i<Nq; i++)
    {
      my_s_v2[i] = 4*PI*PI*PI*pack*(L[i].DWfactor ? L[i].DWfactor : 1)
                 /(line_info.V_0*line_info.V_0*V2K*V2K)
                 *(L[i].j * L[i].F2 / L[i].q)*XsectionFactor;
      /* Is not yet divided by v^2 */
      /* Squires [3.103] */
      q_v[i] = L[i].q*K2V;
      w_v[i] = L[i].w;
    }
  }

  /* Is not yet divided by v */
  my_a_v = pack*line_info.sigma_a/line_info.V_0*2200*100;   // Factor 100 to convert from barns to fm^2
  my_inc = pack*line_info.sigma_i/line_info.V_0*100;   // Factor 100 to convert from barns to fm^2

  printf("PowderN: %s: Vc=%g [Angs] sigma_abs=%g [barn] sigma_inc=%g [barn]\n",
    NAME_CURRENT_COMP, line_info.V_0, line_info.sigma_a, line_info.sigma_i);

}
#line 15736 "D1A.c"
#undef barns
#undef weight
#undef density
#undef concentric
#undef nb_atoms
#undef DW
#undef h
#undef zthick_i
#undef yheight_i
#undef xwidth_i
#undef zthick
#undef xwidth
#undef tfrac
#undef frac
#undef Delta_d
#undef sigma_inc
#undef sigma_abs
#undef Vc
#undef pack
#undef yheight
#undef radius_i
#undef radius
#undef d_phi
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Environment_out. */
  SIG_MESSAGE("Environment_out (Init)");
#line 160 "D1A.instr"
  mccEnvironment_out_d_phi = RAD2DEG * atan2 ( 0.5 , L3 );
#line 159 "D1A.instr"
  mccEnvironment_out_radius = 0.05;
#line 159 "D1A.instr"
  mccEnvironment_out_radius_i = 0.05 -0.002;
#line 159 "D1A.instr"
  mccEnvironment_out_yheight = 0.1;
#line 156 "D1A.instr"
  mccEnvironment_out_pack = 1;
#line 156 "D1A.instr"
  mccEnvironment_out_Vc = 0;
#line 156 "D1A.instr"
  mccEnvironment_out_sigma_abs = 0;
#line 156 "D1A.instr"
  mccEnvironment_out_sigma_inc = 0;
#line 156 "D1A.instr"
  mccEnvironment_out_Delta_d = 0;
#line 161 "D1A.instr"
  mccEnvironment_out_frac = 0;
#line 161 "D1A.instr"
  mccEnvironment_out_tfrac = 0.95;
#line 157 "D1A.instr"
  mccEnvironment_out_xwidth = 0;
#line 157 "D1A.instr"
  mccEnvironment_out_zthick = 0;
#line 157 "D1A.instr"
  mccEnvironment_out_xwidth_i = 0;
#line 157 "D1A.instr"
  mccEnvironment_out_yheight_i = 0;
#line 157 "D1A.instr"
  mccEnvironment_out_zthick_i = 0;
#line 157 "D1A.instr"
  mccEnvironment_out_h = 0;
#line 157 "D1A.instr"
  mccEnvironment_out_DW = 0;
#line 157 "D1A.instr"
  mccEnvironment_out_nb_atoms = 1;
#line 200 "D1A.instr"
  mccEnvironment_out_concentric = 0;
#line 158 "D1A.instr"
  mccEnvironment_out_density = 0;
#line 158 "D1A.instr"
  mccEnvironment_out_weight = 0;
#line 161 "D1A.instr"
  mccEnvironment_out_barns = 1;
#line 15824 "D1A.c"

#define mccompcurname  Environment_out
#define mccompcurtype  PowderN
#define mccompcurindex 14
#define reflections mccEnvironment_out_reflections
#define format mccEnvironment_out_format
#define line_info mccEnvironment_out_line_info
#define Nq mccEnvironment_out_Nq
#define my_s_v2 mccEnvironment_out_my_s_v2
#define my_s_v2_sum mccEnvironment_out_my_s_v2_sum
#define my_a_v mccEnvironment_out_my_a_v
#define my_inc mccEnvironment_out_my_inc
#define q_v mccEnvironment_out_q_v
#define w_v mccEnvironment_out_w_v
#define isrect mccEnvironment_out_isrect
#define columns mccEnvironment_out_columns
#define d_phi mccEnvironment_out_d_phi
#define radius mccEnvironment_out_radius
#define radius_i mccEnvironment_out_radius_i
#define yheight mccEnvironment_out_yheight
#define pack mccEnvironment_out_pack
#define Vc mccEnvironment_out_Vc
#define sigma_abs mccEnvironment_out_sigma_abs
#define sigma_inc mccEnvironment_out_sigma_inc
#define Delta_d mccEnvironment_out_Delta_d
#define frac mccEnvironment_out_frac
#define tfrac mccEnvironment_out_tfrac
#define xwidth mccEnvironment_out_xwidth
#define zthick mccEnvironment_out_zthick
#define xwidth_i mccEnvironment_out_xwidth_i
#define yheight_i mccEnvironment_out_yheight_i
#define zthick_i mccEnvironment_out_zthick_i
#define h mccEnvironment_out_h
#define DW mccEnvironment_out_DW
#define nb_atoms mccEnvironment_out_nb_atoms
#define concentric mccEnvironment_out_concentric
#define density mccEnvironment_out_density
#define weight mccEnvironment_out_weight
#define barns mccEnvironment_out_barns
#line 395 "/usr/local/lib/mcstas/samples/PowderN.comp"
{
  int i;
  struct line_data *L;
  line_info.Dd       = Delta_d;
  line_info.DWfactor = DW;
  line_info.V_0      = Vc;
  line_info.rho      = density;
  line_info.at_weight= weight;
  line_info.at_nb    = nb_atoms;
  line_info.sigma_a  = sigma_abs;
  line_info.sigma_i  = sigma_inc;
  line_info.flag_barns=barns;
  for (i=0; i< 8; i++) line_info.column_order[i] = columns[i];
  strncpy(line_info.compname, NAME_CURRENT_COMP, 256);
  
  /* Early cross-copy yheight and h */
  if (h && !yheight) {
    yheight = h;
  } else if (yheight && !h) {
    h = yheight;
  }
  
  if (!radius || !yheight ) {
    if (!xwidth || !yheight || !zthick) exit(fprintf(stderr,"PowderN: %s: sample has no volume (zero dimensions)\n", NAME_CURRENT_COMP));
    else isrect=1; }
  
  if (!yheight_i) {
    yheight_i = yheight;
  }
  
  if ((isrect && ((zthick_i > zthick) || (xwidth_i > xwidth) || (yheight_i > yheight))) || (!isrect && (radius_i > radius) || (yheight_i > yheight))) {
    exit(fprintf(stderr,"PowderN: %s: Inner hollow exeeds sample volume\n", NAME_CURRENT_COMP));
  }
  
  if (frac + tfrac > 1) {
    exit(fprintf(stderr,"PowderN: %s: You have requested an unmeaningful choice of the 'frac' and 'tfrac' parameters (sum is %g, exeeding 1)\n", 
		 NAME_CURRENT_COMP, frac+tfrac));
  } else if (frac + tfrac == 1) {
    printf("PowderN %s WARNING: You have requested all neutrons be attenuated or incoherently scattered!\n", NAME_CURRENT_COMP);
  }

  if (concentric) {
    printf("PowderN %s WARNING: Concentric mode - remember to include the 'opposite' copy of this component !\n (The equivalent, 'opposite' comp should have concentric=0)\n", NAME_CURRENT_COMP);
    if (tfrac == 0) {
      printf("PowderN %s WARNING: Concentric mode and tfrac==0 !? Don't you want any transmitted neutrons?\n", NAME_CURRENT_COMP);
    }
  }
  
  i = read_line_data(reflections, &line_info);
  
  if (frac && !line_info.sigma_i) {
    printf("PowderN %s WARNING: You have requested statistics for incoherent scattering but not defined sigma_inc!\n", NAME_CURRENT_COMP);
  }

  if (!line_info.V_0 && line_info.at_nb > 0
    && line_info.at_weight > 0 && line_info.rho > 0) {
    /* molar volume [cm^3/mol] = weight [g/mol] / density [g/cm^3] */
    /* atom density per Angs^3 = [mol/cm^3] * N_Avogadro *(1e-8)^3 */
    line_info.V_0 = line_info.at_nb
      /(line_info.rho/line_info.at_weight/1e24*6.02214199e23);
  }

  if (line_info.V_0 <= 0)
    exit(fprintf(stderr,"PowderN: %s: density/unit cell volume is NULL (Vc)\n", NAME_CURRENT_COMP));

  if (line_info.flag_barns) { /* Factor 100 to convert from barns to fm^2 */
    XsectionFactor = 100;
  } else {
    XsectionFactor = 1;
  }
  
  if (i) {
    L = line_info.list;

    Nq  = line_info.count;
    q_v = malloc(Nq*sizeof(double));
    w_v = malloc(Nq*sizeof(double));
    my_s_v2 = malloc(Nq*sizeof(double));
    if (!q_v || !w_v || !my_s_v2)
      exit(fprintf(stderr,"PowderN: %s: ERROR allocating memory (init)\n", NAME_CURRENT_COMP));
    for(i=0; i<Nq; i++)
    {
      my_s_v2[i] = 4*PI*PI*PI*pack*(L[i].DWfactor ? L[i].DWfactor : 1)
                 /(line_info.V_0*line_info.V_0*V2K*V2K)
                 *(L[i].j * L[i].F2 / L[i].q)*XsectionFactor;
      /* Is not yet divided by v^2 */
      /* Squires [3.103] */
      q_v[i] = L[i].q*K2V;
      w_v[i] = L[i].w;
    }
  }

  /* Is not yet divided by v */
  my_a_v = pack*line_info.sigma_a/line_info.V_0*2200*100;   // Factor 100 to convert from barns to fm^2
  my_inc = pack*line_info.sigma_i/line_info.V_0*100;   // Factor 100 to convert from barns to fm^2

  printf("PowderN: %s: Vc=%g [Angs] sigma_abs=%g [barn] sigma_inc=%g [barn]\n",
    NAME_CURRENT_COMP, line_info.V_0, line_info.sigma_a, line_info.sigma_i);

}
#line 15965 "D1A.c"
#undef barns
#undef weight
#undef density
#undef concentric
#undef nb_atoms
#undef DW
#undef h
#undef zthick_i
#undef yheight_i
#undef xwidth_i
#undef zthick
#undef xwidth
#undef tfrac
#undef frac
#undef Delta_d
#undef sigma_inc
#undef sigma_abs
#undef Vc
#undef pack
#undef yheight
#undef radius_i
#undef radius
#undef d_phi
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component Collimator. */
  SIG_MESSAGE("Collimator (Init)");
#line 208 "D1A.instr"
  mccCollimator_w1 = 0;
#line 208 "D1A.instr"
  mccCollimator_h1 = .25;
#line 208 "D1A.instr"
  mccCollimator_w2 = 0;
#line 208 "D1A.instr"
  mccCollimator_h2 = .25;
#line 208 "D1A.instr"
  mccCollimator_len = .2;
#line 209 "D1A.instr"
  mccCollimator_divergence = 40;
#line 209 "D1A.instr"
  mccCollimator_transmission = 1;
#line 210 "D1A.instr"
  mccCollimator_theta_min = 0;
#line 210 "D1A.instr"
  mccCollimator_theta_max = 160;
#line 209 "D1A.instr"
  mccCollimator_nchan = 27;
#line 210 "D1A.instr"
  mccCollimator_radius = 0.25;
#line 77 "D1A.instr"
  mccCollimator_nblades = 0;
#line 77 "D1A.instr"
  mccCollimator_roc = 0;
#line 77 "D1A.instr"
  mccCollimator_verbose = 0;
#line 16035 "D1A.c"

#define mccompcurname  Collimator
#define mccompcurtype  Collimator_radial
#define mccompcurindex 15
#define soller_theta1 mccCollimator_soller_theta1
#define soller_theta2 mccCollimator_soller_theta2
#define window_theta mccCollimator_window_theta
#define use_approx mccCollimator_use_approx
#define ideal mccCollimator_ideal
#define w1 mccCollimator_w1
#define h1 mccCollimator_h1
#define w2 mccCollimator_w2
#define h2 mccCollimator_h2
#define len mccCollimator_len
#define divergence mccCollimator_divergence
#define transmission mccCollimator_transmission
#define theta_min mccCollimator_theta_min
#define theta_max mccCollimator_theta_max
#define nchan mccCollimator_nchan
#define radius mccCollimator_radius
#define nblades mccCollimator_nblades
#define roc mccCollimator_roc
#define verbose mccCollimator_verbose
#line 89 "/usr/local/lib/mcstas/optics/Collimator_radial.comp"
{
  double blades_thick;
  /* check for input parameters */
  if (radius <= 0) exit(printf("Collimator_radial: %s: incorrect radius\n", NAME_CURRENT_COMP));
  if (nchan <= 0)  exit(printf("Collimator_radial: %s: incorrect number of channels\n", NAME_CURRENT_COMP));
  nchan = ceil(nchan);
  if (len <= 0)    exit(printf("Collimator_radial: %s: invalid collimator length\n", NAME_CURRENT_COMP));

  theta_max *= DEG2RAD;
  theta_min *= DEG2RAD;

  if (!w1 && !w2) { ideal=1; nblades=0; }
  else {
    soller_theta1  = atan2(fabs(w1), radius    );
    soller_theta2  = atan2(fabs(w2), radius+len);
    window_theta   = fabs(theta_max-theta_min)/nchan;

    if (soller_theta1 > window_theta || soller_theta2 > window_theta)
      exit(printf("Collimator_radial: %s: the %f channels of size %f [deg]\n"
                "                   do not fit within the angular range %g [deg]\n",
      NAME_CURRENT_COMP, nchan, soller_theta1*RAD2DEG, window_theta*RAD2DEG));
  }

  if (divergence && !nblades) {
    divergence *= MIN2RAD;
    blades_thick= len*tan(divergence);
    nblades     = fabs(floor(w1/blades_thick));
    nchan       =ceil(fabs(theta_max-theta_min)/divergence);
    window_theta=divergence;
    use_approx  = 1;
  } else if (nblades) {
    blades_thick = w1/nblades;
    divergence   = fabs(atan2(blades_thick,len));
    use_approx   = 0;
  } else { divergence = 0; nblades = 0; }
  if (verbose) {
    printf("Collimator_radial: %s: divergence %g [min] %s\n"
             "    Total opening [%.2g:%.2g] [deg] in %g channels",
             NAME_CURRENT_COMP, divergence*RAD2MIN,
             (roc ? "oscillating" : ""),
              theta_min*RAD2DEG, theta_max*RAD2DEG, nchan);
    if (!ideal)
      printf(" as %g channels of %.2g layers %s\n"
           "    Channel Window=%g [deg] Soller=%g [deg]\n",
           nchan, nblades, (use_approx ? "(approx)" : ""),
           window_theta*RAD2DEG, soller_theta1*RAD2DEG);
    else printf(" (ideal)\n");
  }

}
#line 16110 "D1A.c"
#undef verbose
#undef roc
#undef nblades
#undef radius
#undef nchan
#undef theta_max
#undef theta_min
#undef transmission
#undef divergence
#undef len
#undef h2
#undef w2
#undef h1
#undef w1
#undef ideal
#undef use_approx
#undef window_theta
#undef soller_theta2
#undef soller_theta1
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component BananaTheta. */
  SIG_MESSAGE("BananaTheta (Init)");
#line 219 "D1A.instr"
  mccBananaTheta_xwidth = L3 * 2;
#line 219 "D1A.instr"
  mccBananaTheta_yheight = 0.15;
#line 207 "D1A.instr"
  mccBananaTheta_zthick = 0;
#line 207 "D1A.instr"
  mccBananaTheta_xmin = 0;
#line 207 "D1A.instr"
  mccBananaTheta_xmax = 0;
#line 207 "D1A.instr"
  mccBananaTheta_ymin = 0;
#line 207 "D1A.instr"
  mccBananaTheta_ymax = 0;
#line 207 "D1A.instr"
  mccBananaTheta_zmin = 0;
#line 207 "D1A.instr"
  mccBananaTheta_zmax = 0;
#line 207 "D1A.instr"
  mccBananaTheta_bins = 0;
#line 207 "D1A.instr"
  mccBananaTheta_min = -1e40;
#line 207 "D1A.instr"
  mccBananaTheta_max = 1e40;
#line 207 "D1A.instr"
  mccBananaTheta_restore_neutron = 0;
#line 16162 "D1A.c"

#define mccompcurname  BananaTheta
#define mccompcurtype  Monitor_nD
#define mccompcurindex 16
#define options mccBananaTheta_options
#define filename mccBananaTheta_filename
#define user1 mccBananaTheta_user1
#define user2 mccBananaTheta_user2
#define user3 mccBananaTheta_user3
#define username1 mccBananaTheta_username1
#define username2 mccBananaTheta_username2
#define username3 mccBananaTheta_username3
#define DEFS mccBananaTheta_DEFS
#define Vars mccBananaTheta_Vars
#define xwidth mccBananaTheta_xwidth
#define yheight mccBananaTheta_yheight
#define zthick mccBananaTheta_zthick
#define xmin mccBananaTheta_xmin
#define xmax mccBananaTheta_xmax
#define ymin mccBananaTheta_ymin
#define ymax mccBananaTheta_ymax
#define zmin mccBananaTheta_zmin
#define zmax mccBananaTheta_zmax
#define bins mccBananaTheta_bins
#define min mccBananaTheta_min
#define max mccBananaTheta_max
#define restore_neutron mccBananaTheta_restore_neutron
#line 225 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  char tmp[256];
  strcpy(Vars.compcurname, NAME_CURRENT_COMP);
  if (options != NULL)
    strncpy(Vars.option, options, 1024);
  else {
    strcpy(Vars.option, "x y");
    printf("Monitor_nD: %s has no option specified. Setting to PSD ('x y') monitor.\n", NAME_CURRENT_COMP);
  }
  Vars.compcurpos = POS_A_CURRENT_COMP;

  if (strstr(Vars.option, "source"))
    strcat(Vars.option, " list, x y z vx vy vz t sx sy sz ");

  if (bins) { sprintf(tmp, " all bins=%ld ", (long)bins); strcat(Vars.option, tmp); }
  if (min > -FLT_MAX && max < FLT_MAX) { sprintf(tmp, " all limits=[%g %g]", min, max); strcat(Vars.option, tmp); }
  else if (min > -FLT_MAX) { sprintf(tmp, " all min=%g", min); strcat(Vars.option, tmp); }
  else if (max <  FLT_MAX) { sprintf(tmp, " all max=%g", max); strcat(Vars.option, tmp); }

  strncpy(Vars.UserName1, username1 && strlen(username1) ? username1 : "", 32);
  strncpy(Vars.UserName2, username2 && strlen(username2) ? username2 : "", 32);
  strncpy(Vars.UserName3, username3 && strlen(username3) ? username3 : "", 32);

  Monitor_nD_Init(&DEFS, &Vars, xwidth, yheight, zthick, xmin,xmax,ymin,ymax,zmin,zmax);

  if (filename != NULL) strncpy(Vars.Mon_File, filename, 128);

  /* check if user given filename with ext will be used more than once */
  if ( ((Vars.Flag_Multiple && Vars.Coord_Number > 1) || Vars.Flag_List) && strchr(Vars.Mon_File,'.') )
  { char *XY; XY = strrchr(Vars.Mon_File,'.'); *XY='_'; }
  
  if (restore_neutron) Vars.Flag_parallel=1;
}
#line 16224 "D1A.c"
#undef restore_neutron
#undef max
#undef min
#undef bins
#undef zmax
#undef zmin
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef zthick
#undef yheight
#undef xwidth
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* Initializations for component BananaPSD. */
  SIG_MESSAGE("BananaPSD (Init)");
#line 225 "D1A.instr"
  mccBananaPSD_xwidth = L3 * 2 * 1.005;
#line 225 "D1A.instr"
  mccBananaPSD_yheight = 0.5;
#line 207 "D1A.instr"
  mccBananaPSD_zthick = 0;
#line 207 "D1A.instr"
  mccBananaPSD_xmin = 0;
#line 207 "D1A.instr"
  mccBananaPSD_xmax = 0;
#line 207 "D1A.instr"
  mccBananaPSD_ymin = 0;
#line 207 "D1A.instr"
  mccBananaPSD_ymax = 0;
#line 207 "D1A.instr"
  mccBananaPSD_zmin = 0;
#line 207 "D1A.instr"
  mccBananaPSD_zmax = 0;
#line 207 "D1A.instr"
  mccBananaPSD_bins = 0;
#line 207 "D1A.instr"
  mccBananaPSD_min = -1e40;
#line 207 "D1A.instr"
  mccBananaPSD_max = 1e40;
#line 207 "D1A.instr"
  mccBananaPSD_restore_neutron = 0;
#line 16280 "D1A.c"

#define mccompcurname  BananaPSD
#define mccompcurtype  Monitor_nD
#define mccompcurindex 17
#define options mccBananaPSD_options
#define filename mccBananaPSD_filename
#define user1 mccBananaPSD_user1
#define user2 mccBananaPSD_user2
#define user3 mccBananaPSD_user3
#define username1 mccBananaPSD_username1
#define username2 mccBananaPSD_username2
#define username3 mccBananaPSD_username3
#define DEFS mccBananaPSD_DEFS
#define Vars mccBananaPSD_Vars
#define xwidth mccBananaPSD_xwidth
#define yheight mccBananaPSD_yheight
#define zthick mccBananaPSD_zthick
#define xmin mccBananaPSD_xmin
#define xmax mccBananaPSD_xmax
#define ymin mccBananaPSD_ymin
#define ymax mccBananaPSD_ymax
#define zmin mccBananaPSD_zmin
#define zmax mccBananaPSD_zmax
#define bins mccBananaPSD_bins
#define min mccBananaPSD_min
#define max mccBananaPSD_max
#define restore_neutron mccBananaPSD_restore_neutron
#line 225 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  char tmp[256];
  strcpy(Vars.compcurname, NAME_CURRENT_COMP);
  if (options != NULL)
    strncpy(Vars.option, options, 1024);
  else {
    strcpy(Vars.option, "x y");
    printf("Monitor_nD: %s has no option specified. Setting to PSD ('x y') monitor.\n", NAME_CURRENT_COMP);
  }
  Vars.compcurpos = POS_A_CURRENT_COMP;

  if (strstr(Vars.option, "source"))
    strcat(Vars.option, " list, x y z vx vy vz t sx sy sz ");

  if (bins) { sprintf(tmp, " all bins=%ld ", (long)bins); strcat(Vars.option, tmp); }
  if (min > -FLT_MAX && max < FLT_MAX) { sprintf(tmp, " all limits=[%g %g]", min, max); strcat(Vars.option, tmp); }
  else if (min > -FLT_MAX) { sprintf(tmp, " all min=%g", min); strcat(Vars.option, tmp); }
  else if (max <  FLT_MAX) { sprintf(tmp, " all max=%g", max); strcat(Vars.option, tmp); }

  strncpy(Vars.UserName1, username1 && strlen(username1) ? username1 : "", 32);
  strncpy(Vars.UserName2, username2 && strlen(username2) ? username2 : "", 32);
  strncpy(Vars.UserName3, username3 && strlen(username3) ? username3 : "", 32);

  Monitor_nD_Init(&DEFS, &Vars, xwidth, yheight, zthick, xmin,xmax,ymin,ymax,zmin,zmax);

  if (filename != NULL) strncpy(Vars.Mon_File, filename, 128);

  /* check if user given filename with ext will be used more than once */
  if ( ((Vars.Flag_Multiple && Vars.Coord_Number > 1) || Vars.Flag_List) && strchr(Vars.Mon_File,'.') )
  { char *XY; XY = strrchr(Vars.Mon_File,'.'); *XY='_'; }
  
  if (restore_neutron) Vars.Flag_parallel=1;
}
#line 16342 "D1A.c"
#undef restore_neutron
#undef max
#undef min
#undef bins
#undef zmax
#undef zmin
#undef ymax
#undef ymin
#undef xmax
#undef xmin
#undef zthick
#undef yheight
#undef xwidth
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#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
  /* SPLIT counter for component Monok */
  int mcSplit_Monok=0;
  /* SPLIT counter for component SamplePos */
  int mcSplit_SamplePos=0;
  /* 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)
                           *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/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 16476 "D1A.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 Source [2] */
  mccoordschange(mcposrSource, mcrotrSource,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrSource, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Source (without coords transformations) */
  mcJumpTrace_Source:
  SIG_MESSAGE("Source (Trace)");
  mcDEBUG_COMP("Source")
  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  Source
#define mccompcurtype  Source_simple
#define mccompcurindex 2
#define pmul mccSource_pmul
{   /* Declarations of SETTING parameters. */
MCNUM radius = mccSource_radius;
MCNUM height = mccSource_height;
MCNUM width = mccSource_width;
MCNUM dist = mccSource_dist;
MCNUM xw = mccSource_xw;
MCNUM yh = mccSource_yh;
MCNUM E0 = mccSource_E0;
MCNUM dE = mccSource_dE;
MCNUM Lambda0 = mccSource_Lambda0;
MCNUM dLambda = mccSource_dLambda;
MCNUM flux = mccSource_flux;
MCNUM gauss = mccSource_gauss;
MCNUM compat = mccSource_compat;
#line 105 "/usr/local/lib/mcstas/sources/Source_simple.comp"
{
 double chi,E,Lambda,v,r, xf, yf, rf, dx, dy, pdir;

 t=0;
 z=0;
 
 if (square == 1) {
   x = width * (rand01() - 0.5);
   y = height * (rand01() - 0.5);
 } else {
   chi=2*PI*rand01();                          /* Choose point on source */
   r=sqrt(rand01())*radius;                    /* with uniform distribution. */
   x=r*cos(chi);
   y=r*sin(chi);
 }
 randvec_target_rect_real(&xf, &yf, &rf, &pdir,
			  0, 0, dist, xw, yh, ROT_A_CURRENT_COMP, x, y, z, 2);

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

 p = pdir*pmul;

 if(Lambda0==0) {
   if (!gauss) {
     E=E0+dE*randpm1();              /*  Choose from uniform distribution */
   } else {
     E=E0+randnorm()*dE;
   }
   v=sqrt(E)*SE2V;
 } else {
   if (!gauss) {
     Lambda=Lambda0+dLambda*randpm1();
   } else {
     Lambda=randnorm()*dLambda;
   }
   v = K2V*(2*PI/Lambda);
 }

 vz=v*dist/rf;
 vy=v*dy/rf;
 vx=v*dx/rf;
}
#line 16586 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef pmul
#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 mono_cradle [3] */
  mccoordschange(mcposrmono_cradle, mcrotrmono_cradle,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrmono_cradle, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component mono_cradle (without coords transformations) */
  mcJumpTrace_mono_cradle:
  SIG_MESSAGE("mono_cradle (Trace)");
  mcDEBUG_COMP("mono_cradle")
  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(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  mono_cradle
#define mccompcurtype  Arm
#define mccompcurindex 3
#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 Monok [4] */
  mccoordschange(mcposrMonok, mcrotrMonok,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrMonok, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Monok (without coords transformations) */
  mcJumpTrace_Monok:
  SIG_MESSAGE("Monok (Trace)");
  mcDEBUG_COMP("Monok")
  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
  if (!mcSplit_Monok) { /* STORE only the first time */
    STORE_NEUTRON(4,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  } else {
    RESTORE_NEUTRON(4,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp); }
  mcSplit_Monok++; /* SPLIT number */
  mcScattered=0;
  mcNCounter[4]++;
  mcPCounter[4] += p;
  mcP2Counter[4] += p*p;
#define mccompcurname  Monok
#define mccompcurtype  Monochromator_curved
#define mccompcurindex 4
#define reflect mccMonok_reflect
#define transmit mccMonok_transmit
#define mos_rms_y mccMonok_mos_rms_y
#define mos_rms_z mccMonok_mos_rms_z
#define mos_rms_max mccMonok_mos_rms_max
#define mono_Q mccMonok_mono_Q
#define SlabWidth mccMonok_SlabWidth
#define SlabHeight mccMonok_SlabHeight
#define rTable mccMonok_rTable
#define tTable mccMonok_tTable
#define row mccMonok_row
#define col mccMonok_col
{   /* Declarations of SETTING parameters. */
MCNUM zwidth = mccMonok_zwidth;
MCNUM yheight = mccMonok_yheight;
MCNUM gap = mccMonok_gap;
MCNUM NH = mccMonok_NH;
MCNUM NV = mccMonok_NV;
MCNUM mosaich = mccMonok_mosaich;
MCNUM mosaicv = mccMonok_mosaicv;
MCNUM r0 = mccMonok_r0;
MCNUM t0 = mccMonok_t0;
MCNUM Q = mccMonok_Q;
MCNUM RV = mccMonok_RV;
MCNUM RH = mccMonok_RH;
MCNUM DM = mccMonok_DM;
MCNUM mosaic = mccMonok_mosaic;
MCNUM width = mccMonok_width;
MCNUM height = mccMonok_height;
MCNUM verbose = mccMonok_verbose;
#line 203 "/usr/local/lib/mcstas/optics/Monochromator_curved.comp"
{
  double dt;

  if(vx != 0.0 && (dt = -x/vx) >= 0.0 && r0)
  {                             /* Moving towards crystal? */
    double zmin,zmax, ymin,ymax, zp,yp;

    /* Propagate to crystal plane */
    PROP_DT(dt);    /* now in the vertical plane of monochromator */

    zmax = ((NH*(SlabWidth+gap))-gap)/2;
    zmin = -zmax;
    ymax = ((NV*(SlabHeight+gap))-gap)/2;
    ymin = -ymax;

    /* hit a slab or a gap ? */

    if (z>zmin && z<zmax && y>ymin && y<ymax) { /* Intersect the crystal? */
      double tilth,tiltv;         /* used to calculate tilt angle of slab */
      double ratio, order, k, kux,kuy,kuz;
      double kix,kiy,kiz;
      int    do_transmit = 0;

      col = ceil ( (z-zmin)/(SlabWidth+gap));  /* which slab hit ? */
      row = ceil ( (y-ymin)/(SlabHeight+gap));
      if (RH != 0) tilth = asin((col-(NH+1)/2)*(SlabWidth+gap)/RH);
      else tilth=0;
      if (RV != 0) tiltv = -asin((row-(NV+1)/2)*(SlabHeight+gap)/RV);
      else tiltv=0;

      /* restore neutron in order to transform to slab coordinates */
      RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);

      /* rotate with tilth (around Y) and tiltv (around Z), center on plate */
      double center_z=zmin+(col-0.5)*(SlabWidth+gap) -gap/2;
      double center_y=ymin+(row-0.5)*(SlabHeight+gap)-gap/2;
      Rotation T;
      rot_set_rotation(T, 0, tilth,    tiltv);
      /* now make the coordinate system change */
      mccoordschange_polarisation(T, &vx, &vy, &vz);
      y-=center_y;
      z-=center_z;
      coords_get(rot_apply(T,coords_set(x,y,z)),&x,&y,&z);

      /* this is where polaisation should be handled, plus further down */
      /* mccoordschange_polarisation(t, &sx, &sy, &sz); */

      /* now propagate to slab plane */
      PROP_X0;

      if (fabs(z) <= SlabWidth/2 && fabs(y) <= SlabHeight/2) { /* not in gap ? */
        kix = V2K*vx;             /* Initial wave vector */
        kiy = V2K*vy;
        kiz = V2K*vz;
        /* Get reflection order and corresponding nominal scattering vector q0
          of correct length and direction. Only the order with the closest
          scattering vector is considered */
        ratio = -2*kix/mono_Q;
        order = floor(ratio + .5);
        if(order == 0.0) order = ratio < 0 ? -1 : 1;
        /* Order will be negative when the neutron enters from the back, in
          which case the direction of Q0 is flipped. */
        if(order < 0) order = -order;
        /* Make sure the order is small enough to allow Bragg scattering at the
          given neutron wavelength */
        k = sqrt(kix*kix + kiy*kiy + kiz*kiz);
        kux = kix/k;              /* Unit vector along ki */
        kuy = kiy/k;
        kuz = kiz/k;
        if(order > 2*k/mono_Q) order--;
        if(order > 0) {           /* Bragg scattering possible? */
          double q0, q0x, theta, delta, p_reflect, my_r0;

          q0 = order*mono_Q;
          q0x = ratio < 0 ? -q0 : q0;
          theta = asin(q0/(2*k)); /* Actual bragg angle */
          /* Make MC choice: reflect or transmit? */
          delta = asin(fabs(kux)) - theta;

          if (rTable.data != NULL)
          {
            my_r0 = r0*Table_Value(rTable, k, 1); /* 2nd column */
          }
          else my_r0 = r0;
          if (my_r0 > 1)
          {
            if (my_r0 > 1.01 && verbose) fprintf(stdout, "Warning: Monochromator_curved : lowered reflectivity from %f to 1 (k=%f)\n", my_r0, k);
            my_r0=0.999;
          }
          if (my_r0 < 0)
          {
            if (verbose) fprintf(stdout, "Warning: Monochromator_curved : raised reflectivity from %f to 0 (k=%f)\n", my_r0, k);
            my_r0=0;
          }

          p_reflect = fabs(my_r0)*exp(-kiz*kiz/(kiy*kiy + kiz*kiz)*(delta*delta)/
                            (2*mos_rms_y*mos_rms_y))*
                        exp(-kiy*kiy/(kiy*kiy + kiz*kiz)*(delta*delta)/
                            (2*mos_rms_z*mos_rms_z));

          if(rand01() <= p_reflect) { /* Reflect */
            double bx,by,bz,ax,ay,az,phi;
            double cos_2theta,k_sin_2theta,cos_phi,sin_phi,kfx,kfy,kfz,q_x,q_y,q_z;
            double total,c1x,c1y,c1z,width,mos_sample;
            int i=0;

            cos_2theta   = cos(2*theta);
            k_sin_2theta = k*sin(2*theta);
            /* Get unit normal to plane containing ki and most probable kf */
            vec_prod(bx, by, bz, kix, kiy, kiz, q0x, 0, 0);
            NORM(bx,by,bz);
            bx *= k_sin_2theta;
            by *= k_sin_2theta;
            bz *= k_sin_2theta;
            /* Get unit vector normal to ki and b */
            vec_prod(ax, ay, az, bx, by, bz, kux, kuy, kuz);
            /* Compute the total scattering probability at this ki */
            total = 0;
            /* Choose width of Gaussian distribution to sample the angle
            * phi on the Debye-Scherrer cone for the scattered neutron.
            * The radius of the Debye-Scherrer cone is smaller by a
            * factor 1/cos(theta) than the radius of the (partial) sphere
            * describing the possible orientations of Q due to mosaicity, so we
            * start with a width 1/cos(theta) greater than the largest of
            * the two mosaics. */
            mos_sample = mos_rms_max/cos(theta);
            c1x = kix*(cos_2theta-1);
            c1y = kiy*(cos_2theta-1);
            c1z = kiz*(cos_2theta-1);
            /* Loop, repeatedly reducing the sample width until it is small
            * enough to avoid sampling scattering directions with
            * ridiculously low scattering probability.
            * Use a cut-off at 5 times the gauss width for considering
            * scattering probability as well as for integration limits
            * when integrating the sampled distribution below. */
            for(i=0; i<100; i++) {
              width = 5*mos_sample;
              cos_phi = cos(width);
              sin_phi = sin(width);
              q_x =  c1x + cos_phi*ax + sin_phi*bx;
              q_y = (c1y + cos_phi*ay + sin_phi*by)/mos_rms_z;
              q_z = (c1z + cos_phi*az + sin_phi*bz)/mos_rms_y;
              /* Stop when we get near a factor of 25=5^2. */
              if(q_z*q_z + q_y*q_y < (25/(2.0/3.0))*(q_x*q_x))
                break;
              mos_sample *= (2.0/3.0);
            }
            /* Now integrate the chosen sampling distribution, using a
            * cut-off at five times sigma. */
            for(i = 0; i < (sizeof(Gauss_X)/sizeof(double)); i++)
            {
              phi = width*Gauss_X[i];
              cos_phi = cos(phi);
              sin_phi = sin(phi);
              q_x = c1x + cos_phi*ax + sin_phi*bx;
              q_y = c1y + cos_phi*ay + sin_phi*by;
              q_z = c1z + cos_phi*az + sin_phi*bz;
              p_reflect = GAUSS((q_z/q_x),0,mos_rms_y)*
                          GAUSS((q_y/q_x),0,mos_rms_z);
              total += Gauss_W[i]*p_reflect;
            }
            total *= width;
            /* Choose point on Debye-Scherrer cone. Sample from a Gaussian of
             * width 1/cos(theta) greater than the mosaic and correct for any
             * error by adjusting the neutron weight later. */
            phi = mos_sample*randnorm();
            /* Compute final wave vector kf and scattering vector q = ki - kf */
            cos_phi = cos(phi);
            sin_phi = sin(phi);
            q_x = c1x + cos_phi*ax + sin_phi*bx;
            q_y = c1y + cos_phi*ay + sin_phi*by;
            q_z = c1z + cos_phi*az + sin_phi*bz;
            p_reflect = GAUSS((q_z/q_x),0,mos_rms_y)*
                        GAUSS((q_y/q_x),0,mos_rms_z);

            vx = K2V*(kix+q_x);
            vy = K2V*(kiy+q_y);
            vz = K2V*(kiz+q_z);
            p *= p_reflect/(total*GAUSS(phi,0,mos_sample));

            SCATTER;
          } /* End MC choice to reflect or transmit neutron (if tmp<p_reflect) */
          else do_transmit = 1;
            /* else transmit neutron */
        } /* End bragg scattering possible (if order) */
        else do_transmit=1;
        if (do_transmit)
        {
          double my_t0;
          if (tTable.data != NULL)
          {
            my_t0 = t0*Table_Value(tTable, k, 1); /* 2nd column */
          }
          else my_t0 = t0;
          /* do not SCATTER, else GROUP does not work */
          if (my_t0 > 1)
          {
            if (my_t0 > 1.01 && verbose) fprintf(stdout, "Warning: Monochromator_curved : lowered transmission from %f to 1 (k=%f)\n", my_t0, k);
            my_t0=0.999;
          }
          if (my_t0 > 0) p*= my_t0;
          else ABSORB;
        }
      } /* end if not in gap */
      /* rotate back in component frame */
      Rotation TT;
      rot_transpose(T, TT);
      /* now make the coordinate system change */
      mccoordschange_polarisation(TT, &vx, &vy, &vz);
      coords_get(rot_apply(TT,coords_set(x,y,z)),&x,&y,&z);
      y+=center_y;
      z+=center_z;

      /* mccoordschange_polarisation(tt, &sx, &sy, &sz); */
    } /* End intersect the crystal (if z) */
    else {
      /* restore neutron state when no interaction */
      RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
    }
  } /* End neutron moving towards crystal (if vx)*/
}
#line 16936 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef col
#undef row
#undef tTable
#undef rTable
#undef SlabHeight
#undef SlabWidth
#undef mono_Q
#undef mos_rms_max
#undef mos_rms_z
#undef mos_rms_y
#undef transmit
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
  if (floor(10) > 1) p /= floor(10); /* adapt weight for SPLITed neutron */
#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 mono_out [5] */
  mccoordschange(mcposrmono_out, mcrotrmono_out,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrmono_out, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component mono_out (without coords transformations) */
  mcJumpTrace_mono_out:
  SIG_MESSAGE("mono_out (Trace)");
  mcDEBUG_COMP("mono_out")
  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(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  mono_out
#define mccompcurtype  Arm
#define mccompcurindex 5
#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 Lmon [6] */
  mccoordschange(mcposrLmon, mcrotrLmon,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrLmon, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Lmon (without coords transformations) */
  mcJumpTrace_Lmon:
  SIG_MESSAGE("Lmon (Trace)");
  mcDEBUG_COMP("Lmon")
  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  Lmon
#define mccompcurtype  Monitor_nD
#define mccompcurindex 6
#define options mccLmon_options
#define filename mccLmon_filename
#define user1 mccLmon_user1
#define user2 mccLmon_user2
#define user3 mccLmon_user3
#define username1 mccLmon_username1
#define username2 mccLmon_username2
#define username3 mccLmon_username3
#define DEFS mccLmon_DEFS
#define Vars mccLmon_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccLmon_xwidth;
MCNUM yheight = mccLmon_yheight;
MCNUM zthick = mccLmon_zthick;
MCNUM xmin = mccLmon_xmin;
MCNUM xmax = mccLmon_xmax;
MCNUM ymin = mccLmon_ymin;
MCNUM ymax = mccLmon_ymax;
MCNUM zmin = mccLmon_zmin;
MCNUM zmax = mccLmon_zmax;
MCNUM bins = mccLmon_bins;
MCNUM min = mccLmon_min;
MCNUM max = mccLmon_max;
MCNUM restore_neutron = mccLmon_restore_neutron;
#line 260 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  double  XY=0;
  double  t0 = 0;
  double  t1 = 0;
  double  pp;
  int     intersect   = 0;
  char    Flag_Restore = 0;

  if (user1 != FLT_MAX) Vars.UserVariable1 = user1;
  if (user2 != FLT_MAX) Vars.UserVariable2 = user2;
  if (user3 != FLT_MAX) Vars.UserVariable3 = user3;

  /* this is done automatically
    STORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
  */

  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SQUARE) /* square xy */
  {
    PROP_Z0;
    intersect = (x>=Vars.mxmin && x<=Vars.mxmax && y>=Vars.mymin && y<=Vars.mymax);
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_DISK)   /* disk xy */
  {
    PROP_Z0;
    intersect = ((x*x + y*y) <= Vars.Sphere_Radius*Vars.Sphere_Radius);
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) /* sphere */
  {
    intersect = sphere_intersect(&t0, &t1, x, y, z, vx, vy, vz, Vars.Sphere_Radius);
  /*      intersect = (intersect && t0 > 0); */
  }
  else if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BANANA)) /* cylinder */
  {
    intersect = cylinder_intersect(&t0, &t1, x, y, z, vx, vy, vz, Vars.Sphere_Radius, Vars.Cylinder_Height);
    if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_BANANA) && (intersect != 1)) intersect = 0; /* remove top/bottom for banana */
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_BOX) /* box */
  {
    intersect = box_intersect(&t0, &t1, x, y, z, vx, vy, vz, fabs(Vars.mxmax-Vars.mxmin), fabs(Vars.mymax-Vars.mymin), fabs(Vars.mzmax-Vars.mzmin));
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_PREVIOUS) /* previous comp */
  { intersect = 1; }

  if (intersect)
  {
    if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BOX) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BANANA))
    {
      if (t0 < 0 && t1 > 0)
        t0 = t;  /* neutron was already inside ! */
      if (t1 < 0 && t0 > 0) /* neutron exit before entering !! */
        t1 = t;
      /* t0 is now time of incoming intersection with the sphere. */
      if ((Vars.Flag_Shape < 0) && (t1 > 0))
        PROP_DT(t1); /* t1 outgoing beam */
      else
        PROP_DT(t0); /* t0 incoming beam */
    }

    /* Now get the data to monitor: current or keep from PreMonitor */
    if (Vars.Flag_UsePreMonitor != 1)
    {
      Vars.cp = p;
      Vars.cx = x;
      Vars.cvx = vx;
      Vars.csx = sx;
      Vars.cy = y;
      Vars.cvy = vy;
      Vars.csy = sy;
      Vars.cz = z;
      Vars.cvz = vz;
      Vars.csz = sz;
      Vars.ct = t;
    }

    if ((Vars.He3_pressure > 0) && (t1 != t0) && ((abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BOX)))
    {
      XY = exp(-7.417*Vars.He3_pressure*fabs(t1-t0)*2*PI*K2V);
      /* will monitor the absorbed part */
      Vars.cp *= 1-XY;
      /* and modify the neutron weight after monitor, only remains 1-p_detect */
      p *= XY;
    }

    if (Vars.Flag_capture)
    {
      XY = sqrt(Vars.cvx*Vars.cvx+Vars.cvy*Vars.cvy+Vars.cvz*Vars.cvz);
      XY *= V2K;
      if (XY != 0) XY = 2*PI/XY; /* lambda. lambda(2200 m/2) = 1.7985 Angs  */
      Vars.cp *= XY/1.7985;
    }

    pp = Monitor_nD_Trace(&DEFS, &Vars);
    if (pp==0.0)
    { ABSORB;
    }
    else
    { Vars.Nsum++;
      Vars.psum += pp;
      Vars.p2sum += pp*pp;
      SCATTER;
    }

    /* now handles intermediate results saving */
    if ((Vars.Intermediate > 0) && (mcget_run_num() > Vars.IntermediateCnts))
    {
      Vars.IntermediateCnts += Vars.Intermediate*mcget_ncount();
      /* save results for all monitors in the simulation */
      mcsave(NULL);
    }
    if (Vars.Flag_parallel) /* back to neutron state before detection */
      Flag_Restore = 1;
  } /* end if intersection */
  else {
    if (Vars.Flag_Absorb && !Vars.Flag_parallel) ABSORB;
    else Flag_Restore = 1;  /* no intersection, back to previous state */
  }

  if (Flag_Restore)
  {
    RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
  }
}
#line 17192 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#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 PSDsample [7] */
  mccoordschange(mcposrPSDsample, mcrotrPSDsample,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrPSDsample, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component PSDsample (without coords transformations) */
  mcJumpTrace_PSDsample:
  SIG_MESSAGE("PSDsample (Trace)");
  mcDEBUG_COMP("PSDsample")
  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(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  PSDsample
#define mccompcurtype  Monitor_nD
#define mccompcurindex 7
#define options mccPSDsample_options
#define filename mccPSDsample_filename
#define user1 mccPSDsample_user1
#define user2 mccPSDsample_user2
#define user3 mccPSDsample_user3
#define username1 mccPSDsample_username1
#define username2 mccPSDsample_username2
#define username3 mccPSDsample_username3
#define DEFS mccPSDsample_DEFS
#define Vars mccPSDsample_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccPSDsample_xwidth;
MCNUM yheight = mccPSDsample_yheight;
MCNUM zthick = mccPSDsample_zthick;
MCNUM xmin = mccPSDsample_xmin;
MCNUM xmax = mccPSDsample_xmax;
MCNUM ymin = mccPSDsample_ymin;
MCNUM ymax = mccPSDsample_ymax;
MCNUM zmin = mccPSDsample_zmin;
MCNUM zmax = mccPSDsample_zmax;
MCNUM bins = mccPSDsample_bins;
MCNUM min = mccPSDsample_min;
MCNUM max = mccPSDsample_max;
MCNUM restore_neutron = mccPSDsample_restore_neutron;
#line 260 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  double  XY=0;
  double  t0 = 0;
  double  t1 = 0;
  double  pp;
  int     intersect   = 0;
  char    Flag_Restore = 0;

  if (user1 != FLT_MAX) Vars.UserVariable1 = user1;
  if (user2 != FLT_MAX) Vars.UserVariable2 = user2;
  if (user3 != FLT_MAX) Vars.UserVariable3 = user3;

  /* this is done automatically
    STORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
  */

  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SQUARE) /* square xy */
  {
    PROP_Z0;
    intersect = (x>=Vars.mxmin && x<=Vars.mxmax && y>=Vars.mymin && y<=Vars.mymax);
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_DISK)   /* disk xy */
  {
    PROP_Z0;
    intersect = ((x*x + y*y) <= Vars.Sphere_Radius*Vars.Sphere_Radius);
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) /* sphere */
  {
    intersect = sphere_intersect(&t0, &t1, x, y, z, vx, vy, vz, Vars.Sphere_Radius);
  /*      intersect = (intersect && t0 > 0); */
  }
  else if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BANANA)) /* cylinder */
  {
    intersect = cylinder_intersect(&t0, &t1, x, y, z, vx, vy, vz, Vars.Sphere_Radius, Vars.Cylinder_Height);
    if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_BANANA) && (intersect != 1)) intersect = 0; /* remove top/bottom for banana */
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_BOX) /* box */
  {
    intersect = box_intersect(&t0, &t1, x, y, z, vx, vy, vz, fabs(Vars.mxmax-Vars.mxmin), fabs(Vars.mymax-Vars.mymin), fabs(Vars.mzmax-Vars.mzmin));
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_PREVIOUS) /* previous comp */
  { intersect = 1; }

  if (intersect)
  {
    if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BOX) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BANANA))
    {
      if (t0 < 0 && t1 > 0)
        t0 = t;  /* neutron was already inside ! */
      if (t1 < 0 && t0 > 0) /* neutron exit before entering !! */
        t1 = t;
      /* t0 is now time of incoming intersection with the sphere. */
      if ((Vars.Flag_Shape < 0) && (t1 > 0))
        PROP_DT(t1); /* t1 outgoing beam */
      else
        PROP_DT(t0); /* t0 incoming beam */
    }

    /* Now get the data to monitor: current or keep from PreMonitor */
    if (Vars.Flag_UsePreMonitor != 1)
    {
      Vars.cp = p;
      Vars.cx = x;
      Vars.cvx = vx;
      Vars.csx = sx;
      Vars.cy = y;
      Vars.cvy = vy;
      Vars.csy = sy;
      Vars.cz = z;
      Vars.cvz = vz;
      Vars.csz = sz;
      Vars.ct = t;
    }

    if ((Vars.He3_pressure > 0) && (t1 != t0) && ((abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BOX)))
    {
      XY = exp(-7.417*Vars.He3_pressure*fabs(t1-t0)*2*PI*K2V);
      /* will monitor the absorbed part */
      Vars.cp *= 1-XY;
      /* and modify the neutron weight after monitor, only remains 1-p_detect */
      p *= XY;
    }

    if (Vars.Flag_capture)
    {
      XY = sqrt(Vars.cvx*Vars.cvx+Vars.cvy*Vars.cvy+Vars.cvz*Vars.cvz);
      XY *= V2K;
      if (XY != 0) XY = 2*PI/XY; /* lambda. lambda(2200 m/2) = 1.7985 Angs  */
      Vars.cp *= XY/1.7985;
    }

    pp = Monitor_nD_Trace(&DEFS, &Vars);
    if (pp==0.0)
    { ABSORB;
    }
    else
    { Vars.Nsum++;
      Vars.psum += pp;
      Vars.p2sum += pp*pp;
      SCATTER;
    }

    /* now handles intermediate results saving */
    if ((Vars.Intermediate > 0) && (mcget_run_num() > Vars.IntermediateCnts))
    {
      Vars.IntermediateCnts += Vars.Intermediate*mcget_ncount();
      /* save results for all monitors in the simulation */
      mcsave(NULL);
    }
    if (Vars.Flag_parallel) /* back to neutron state before detection */
      Flag_Restore = 1;
  } /* end if intersection */
  else {
    if (Vars.Flag_Absorb && !Vars.Flag_parallel) ABSORB;
    else Flag_Restore = 1;  /* no intersection, back to previous state */
  }

  if (Flag_Restore)
  {
    RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
  }
}
#line 17401 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#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 SamplePos [8] */
  mccoordschange(mcposrSamplePos, mcrotrSamplePos,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrSamplePos, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component SamplePos (without coords transformations) */
  mcJumpTrace_SamplePos:
  SIG_MESSAGE("SamplePos (Trace)");
  mcDEBUG_COMP("SamplePos")
  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
  if (!mcSplit_SamplePos) { /* STORE only the first time */
    STORE_NEUTRON(8,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp);
  } else {
    RESTORE_NEUTRON(8,mcnlx, mcnly, mcnlz, mcnlvx,mcnlvy,mcnlvz,mcnlt,mcnlsx,mcnlsy, mcnlsz, mcnlp); }
  mcSplit_SamplePos++; /* SPLIT number */
  mcScattered=0;
  mcNCounter[8]++;
  mcPCounter[8] += p;
  mcP2Counter[8] += p*p;
#define mccompcurname  SamplePos
#define mccompcurtype  Arm
#define mccompcurindex 8
/* 'SamplePos' component extend code */
    SIG_MESSAGE("SamplePos (Trace:Extend)");
#line 155 "D1A.instr"
  flag_container=flag_sample=flag_env=0;
#line 17468 "D1A.c"
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex
  if (floor(10) > 1) p /= floor(10); /* adapt weight for SPLITed neutron */
#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 Environment_in [9] */
  mccoordschange(mcposrEnvironment_in, mcrotrEnvironment_in,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrEnvironment_in, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Environment_in (without coords transformations) */
  mcJumpTrace_Environment_in:
  SIG_MESSAGE("Environment_in (Trace)");
  mcDEBUG_COMP("Environment_in")
  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(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  Environment_in
#define mccompcurtype  PowderN
#define mccompcurindex 9
#define reflections mccEnvironment_in_reflections
#define format mccEnvironment_in_format
#define line_info mccEnvironment_in_line_info
#define Nq mccEnvironment_in_Nq
#define my_s_v2 mccEnvironment_in_my_s_v2
#define my_s_v2_sum mccEnvironment_in_my_s_v2_sum
#define my_a_v mccEnvironment_in_my_a_v
#define my_inc mccEnvironment_in_my_inc
#define q_v mccEnvironment_in_q_v
#define w_v mccEnvironment_in_w_v
#define isrect mccEnvironment_in_isrect
#define columns mccEnvironment_in_columns
{   /* Declarations of SETTING parameters. */
MCNUM d_phi = mccEnvironment_in_d_phi;
MCNUM radius = mccEnvironment_in_radius;
MCNUM radius_i = mccEnvironment_in_radius_i;
MCNUM yheight = mccEnvironment_in_yheight;
MCNUM pack = mccEnvironment_in_pack;
MCNUM Vc = mccEnvironment_in_Vc;
MCNUM sigma_abs = mccEnvironment_in_sigma_abs;
MCNUM sigma_inc = mccEnvironment_in_sigma_inc;
MCNUM Delta_d = mccEnvironment_in_Delta_d;
MCNUM frac = mccEnvironment_in_frac;
MCNUM tfrac = mccEnvironment_in_tfrac;
MCNUM xwidth = mccEnvironment_in_xwidth;
MCNUM zthick = mccEnvironment_in_zthick;
MCNUM xwidth_i = mccEnvironment_in_xwidth_i;
MCNUM yheight_i = mccEnvironment_in_yheight_i;
MCNUM zthick_i = mccEnvironment_in_zthick_i;
MCNUM h = mccEnvironment_in_h;
MCNUM DW = mccEnvironment_in_DW;
MCNUM nb_atoms = mccEnvironment_in_nb_atoms;
MCNUM concentric = mccEnvironment_in_concentric;
MCNUM density = mccEnvironment_in_density;
MCNUM weight = mccEnvironment_in_weight;
MCNUM barns = mccEnvironment_in_barns;
#line 496 "/usr/local/lib/mcstas/samples/PowderN.comp"
{
  double t0, t1, t2, t3, v, v1,l_full, l, l_1, dt, alpha0, alpha, theta, my_s, my_s_n;
  double solid_angle, neutrontype;
  double arg, tmp_vx, tmp_vy, tmp_vz, vout_x, vout_y, vout_z, nx, ny, nz, pmul=1;
  int    line;
  char   intersect=0;
  char   intersecti=0;

  if (isrect) {
    intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
    intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
  } else {
    intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
    intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
  }
  
  if(intersect && t3 >0)
    {
      
      if (concentric) {
	/* Set up for concentric case */
	/* 'Remove' the backside of this comp */
	if (!intersecti) {
	  t1 = (t3 + t0) /2;
	}
	t2 = t1;
	t3 = t1;
	dt = -1.0*rand01(); /* In case of scattering we will scatter on 'forward' part of sample */
      } else {
	if (!intersecti) {
	  t1 = (t3 + t0) /2;
	  t2 = t1;
	}
	dt = randpm1(); /* Possibility to scatter at all points in line of sight */
      }
      
      /* Neutron enters at t=t0. */
      if(t0 < 0) t0=0; /* already in sample */
      if(t1 < 0) t1=0; /* already in inner hollow */
      if(t2 < 0) t2=0; /* already past inner hollow */
      v = sqrt(vx*vx + vy*vy + vz*vz);
      l_full = v * (t3 - t2 + t1 - t0);

      /* Calculate total scattering cross section at relevant velocity */
      my_s_v2_sum=0;
      for(line=0; line<Nq; line++) {
	if (q_v[line] <= 2*v) {
	  my_s_v2_sum+=my_s_v2[line];
	}
      }
      
      if (t3 < 0) {
	t3=0; /* Already past sample?! */
	printf("PowderN %s Warning: Neutron has already passed us? (Skipped)\n", NAME_CURRENT_COMP);
      } else {
	if (dt<0) { /* Calculate scattering point position */
	  dt = fabs(dt)*(t1 - t0); /* 'Forward' part */
	} else {
	  dt = dt * (t3 - t2) + (t2-t0) ; /* Possibly also 'backside' part */
	}
	
	my_s = my_s_v2_sum/(v*v)+my_inc;
	/* Total attenuation from scattering */
	
	neutrontype = rand01();
	/* How to handle this one? Transmit (1) / Incoherent (2) / Coherent (3) ? */
	if (neutrontype < tfrac) {
	  neutrontype = 1; 
	  l = l_full; /* Passing through, full length */
	  PROP_DT(t3); 
	} else if (neutrontype >= tfrac && neutrontype < (tfrac + frac)) {
	  neutrontype = 2;
	  l = v*dt;       /* Penetration in sample */
	  PROP_DT(dt+t0); /* Point of scattering */
	  SCATTER;
	} else if (neutrontype >= tfrac + frac) {
	  neutrontype = 3;
	  l = v*dt;       /* Penetration in sample */
	  PROP_DT(dt+t0); /* Point of scattering */
	  SCATTER;
	} else {
	  exit(fprintf(stderr,"PowderN %s: DEAD - this shouldn't happen!\n", NAME_CURRENT_COMP));
	}
	
	if (neutrontype == 3)
	  { /* Make coherent scattering event */
	    
	    if (line_info.count > 0) {
	      /* choose line */
	      if (Nq > 1) line=floor(Nq*rand01());  /* Select between Nq powder lines */
	      else line = 0;
	      if (w_v[line])
		arg = q_v[line]*(1+w_v[line]*randnorm())/(2.0*v);
	      else
		arg = q_v[line]/(2.0*v);
	      my_s_n = my_s_v2[line]/(v*v);
	      if(fabs(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 full Debye-Scherrer cone is within d_phi, don't focus */
		  if (arg < -1 || arg > 1) d_phi = 0;
		  /* Otherwise, determine alpha to rotate from scattering plane
		     into d_phi focusing area*/
		  else alpha = 2*asin(arg);
		}
	      if (d_phi) {
		/* Focusing */
		alpha = fabs(alpha);
		/* Trick to get scattering for pos/neg theta's */
		alpha0= 2*rand01()*alpha;
		if (alpha0 > alpha) {
		  alpha0=PI+(alpha0-1.5*alpha);
		} else {
		  alpha0=alpha0-0.5*alpha;
		}
	      }
	      else
		alpha0 = PI*randpm1();
	      
	      /* now find a nearly vertical rotation axis:
	       * Either
	       *  (v along Z) x (X axis) -> nearly Y axis
	       * Or
	       *  (v along X) x (Z axis) -> nearly Y axis
	       */
	      if (fabs(scalar_prod(1,0,0,vx/v,vy/v,vz/v)) < fabs(scalar_prod(0,0,1,vx/v,vy/v,vz/v))) {
		nx = 1; ny = 0; nz = 0;
	      } else {
		nx = 0; ny = 0; nz = 1;
	      }
	      vec_prod(tmp_vx,tmp_vy,tmp_vz, vx,vy,vz, nx,ny,nz);
	      
	      /* 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 alpha0 around 'v' (Debye-Scherrer cone) */
	      rotate(tmp_vx,tmp_vy,tmp_vz, vout_x,vout_y,vout_z, alpha0, vx, vy, vz);
	      vx = tmp_vx;
	      vy = tmp_vy;
	      vz = tmp_vz;
	      
	      /* Since now scattered and new direction given, calculate path to exit */
	      if (isrect) {
		intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
		intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
	      } else {
		intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
		intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
	      }
	      
	      if (!intersect) {
		/* Strange error: did not hit cylinder */
		fprintf(stderr, "PowderN: FATAL ERROR: Did not hit sample from inside.\n");
		ABSORB;
	      }
	      
	      if (!intersecti) {
		t1 = (t3 + t0) /2;
		t2 = t1;
	      }
	      
	      if (concentric && intersecti) {
		/* In case of concentricity, 'remove' backward wall of sample */
		t2 = t1;
		t3 = t1;
	      }
	      
	      if(t0 < 0) t0=0; /* already in sample */
	      if(t1 < 0) t1=0; /* already in inner hollow */
	      if(t2 < 0) t2=0; /* already past inner hollow */
	      

	      l_1 = v*(t3 - t2 + t1 - t0); /* Length to exit */
	      
	      pmul  = Nq*l_full*my_s_n*exp(-(my_a_v/v+my_s)*(l+l_1))/(1-(frac+tfrac));
	      /* Correction in case of d_phi focusing - BUT only when d_phi != 0 */
	      if (d_phi) pmul *= alpha/PI;
	    } /* else transmit <-- No powder lines in file */
	  }  /* Coherent scattering event */
	else if (neutrontype == 2)
	  {  /* Make incoherent scattering event */
	    if(d_phi) {
	      randvec_target_rect_angular(&vx, &vy, &vz, &solid_angle,
					  0, 0, 1,
					  2*PI, d_phi*DEG2RAD, ROT_A_CURRENT_COMP);
	    } else {
	      randvec_target_circle(&vx, &vy, &vz,
				    &solid_angle, 0, 0, 1, 0);
	    }
	    v1 = sqrt(vx*vx+vy*vy+vz*vz);
	    vx *= v/v1;
	    vy *= v/v1;
	    vz *= v/v1;
	    
	    /* Since now scattered and new direction given, calculate path to exit */
	    if (isrect) {
	      intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
	      intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
	    } else {
	      intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
	      intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
	    }
	    
	    if (!intersect) {
	      /* Strange error: did not hit cylinder */
	      fprintf(stderr, "PowderN: FATAL ERROR: Did not hit sample from inside.\n");
	      ABSORB;
	    }  
	      
	    if (!intersecti) {
	      t1 = (t3 + t0) /2;
	      t2 = t1;
	    }
	      
	    if (concentric && intersecti) {
	      /* In case of concentricity, 'remove' backward wall of sample */
	      t2 = t1;
	      t3 = t1;
	    }
	      
	    if(t0 < 0) t0=0; /* already in sample */
	    if(t1 < 0) t1=0; /* already in inner hollow */
	    if(t2 < 0) t2=0; /* already past inner hollow */
	      

	    l_1 = v*(t3 - t2 + t1 - t0); /* Length to exit */
	    
	    pmul = l_full*my_inc*exp(-(my_a_v/v+my_s)*(l+l_1))/(frac);
	    pmul *= solid_angle/(4*PI);
	    
	  }  /* Incoherent scattering event */
	else if (neutrontype == 1) {
	  /* Make transmitted (absorption-corrected) event */
	  /* No coodinate changes here, simply change neutron weight */
	  pmul = exp(-(my_a_v/v+my_s)*(l))/(tfrac);
        }
	p *= pmul;
      } /* Neutron leaving since it has passed already */
    } /* else transmit non interacting neutrons */
  
}
#line 17797 "D1A.c"
/* 'Environment_in' component extend code */
    SIG_MESSAGE("Environment_in (Trace:Extend)");
#line 164 "D1A.instr"
  flag_env=SCATTERED;
#line 17802 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#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 Container_in [10] */
  mccoordschange(mcposrContainer_in, mcrotrContainer_in,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrContainer_in, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Container_in (without coords transformations) */
  mcJumpTrace_Container_in:
  SIG_MESSAGE("Container_in (Trace)");
  mcDEBUG_COMP("Container_in")
  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  Container_in
#define mccompcurtype  PowderN
#define mccompcurindex 10
#define reflections mccContainer_in_reflections
#define format mccContainer_in_format
#define line_info mccContainer_in_line_info
#define Nq mccContainer_in_Nq
#define my_s_v2 mccContainer_in_my_s_v2
#define my_s_v2_sum mccContainer_in_my_s_v2_sum
#define my_a_v mccContainer_in_my_a_v
#define my_inc mccContainer_in_my_inc
#define q_v mccContainer_in_q_v
#define w_v mccContainer_in_w_v
#define isrect mccContainer_in_isrect
#define columns mccContainer_in_columns
{   /* Declarations of SETTING parameters. */
MCNUM d_phi = mccContainer_in_d_phi;
MCNUM radius = mccContainer_in_radius;
MCNUM radius_i = mccContainer_in_radius_i;
MCNUM yheight = mccContainer_in_yheight;
MCNUM pack = mccContainer_in_pack;
MCNUM Vc = mccContainer_in_Vc;
MCNUM sigma_abs = mccContainer_in_sigma_abs;
MCNUM sigma_inc = mccContainer_in_sigma_inc;
MCNUM Delta_d = mccContainer_in_Delta_d;
MCNUM frac = mccContainer_in_frac;
MCNUM tfrac = mccContainer_in_tfrac;
MCNUM xwidth = mccContainer_in_xwidth;
MCNUM zthick = mccContainer_in_zthick;
MCNUM xwidth_i = mccContainer_in_xwidth_i;
MCNUM yheight_i = mccContainer_in_yheight_i;
MCNUM zthick_i = mccContainer_in_zthick_i;
MCNUM h = mccContainer_in_h;
MCNUM DW = mccContainer_in_DW;
MCNUM nb_atoms = mccContainer_in_nb_atoms;
MCNUM concentric = mccContainer_in_concentric;
MCNUM density = mccContainer_in_density;
MCNUM weight = mccContainer_in_weight;
MCNUM barns = mccContainer_in_barns;
#line 496 "/usr/local/lib/mcstas/samples/PowderN.comp"
{
  double t0, t1, t2, t3, v, v1,l_full, l, l_1, dt, alpha0, alpha, theta, my_s, my_s_n;
  double solid_angle, neutrontype;
  double arg, tmp_vx, tmp_vy, tmp_vz, vout_x, vout_y, vout_z, nx, ny, nz, pmul=1;
  int    line;
  char   intersect=0;
  char   intersecti=0;

  if (isrect) {
    intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
    intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
  } else {
    intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
    intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
  }
  
  if(intersect && t3 >0)
    {
      
      if (concentric) {
	/* Set up for concentric case */
	/* 'Remove' the backside of this comp */
	if (!intersecti) {
	  t1 = (t3 + t0) /2;
	}
	t2 = t1;
	t3 = t1;
	dt = -1.0*rand01(); /* In case of scattering we will scatter on 'forward' part of sample */
      } else {
	if (!intersecti) {
	  t1 = (t3 + t0) /2;
	  t2 = t1;
	}
	dt = randpm1(); /* Possibility to scatter at all points in line of sight */
      }
      
      /* Neutron enters at t=t0. */
      if(t0 < 0) t0=0; /* already in sample */
      if(t1 < 0) t1=0; /* already in inner hollow */
      if(t2 < 0) t2=0; /* already past inner hollow */
      v = sqrt(vx*vx + vy*vy + vz*vz);
      l_full = v * (t3 - t2 + t1 - t0);

      /* Calculate total scattering cross section at relevant velocity */
      my_s_v2_sum=0;
      for(line=0; line<Nq; line++) {
	if (q_v[line] <= 2*v) {
	  my_s_v2_sum+=my_s_v2[line];
	}
      }
      
      if (t3 < 0) {
	t3=0; /* Already past sample?! */
	printf("PowderN %s Warning: Neutron has already passed us? (Skipped)\n", NAME_CURRENT_COMP);
      } else {
	if (dt<0) { /* Calculate scattering point position */
	  dt = fabs(dt)*(t1 - t0); /* 'Forward' part */
	} else {
	  dt = dt * (t3 - t2) + (t2-t0) ; /* Possibly also 'backside' part */
	}
	
	my_s = my_s_v2_sum/(v*v)+my_inc;
	/* Total attenuation from scattering */
	
	neutrontype = rand01();
	/* How to handle this one? Transmit (1) / Incoherent (2) / Coherent (3) ? */
	if (neutrontype < tfrac) {
	  neutrontype = 1; 
	  l = l_full; /* Passing through, full length */
	  PROP_DT(t3); 
	} else if (neutrontype >= tfrac && neutrontype < (tfrac + frac)) {
	  neutrontype = 2;
	  l = v*dt;       /* Penetration in sample */
	  PROP_DT(dt+t0); /* Point of scattering */
	  SCATTER;
	} else if (neutrontype >= tfrac + frac) {
	  neutrontype = 3;
	  l = v*dt;       /* Penetration in sample */
	  PROP_DT(dt+t0); /* Point of scattering */
	  SCATTER;
	} else {
	  exit(fprintf(stderr,"PowderN %s: DEAD - this shouldn't happen!\n", NAME_CURRENT_COMP));
	}
	
	if (neutrontype == 3)
	  { /* Make coherent scattering event */
	    
	    if (line_info.count > 0) {
	      /* choose line */
	      if (Nq > 1) line=floor(Nq*rand01());  /* Select between Nq powder lines */
	      else line = 0;
	      if (w_v[line])
		arg = q_v[line]*(1+w_v[line]*randnorm())/(2.0*v);
	      else
		arg = q_v[line]/(2.0*v);
	      my_s_n = my_s_v2[line]/(v*v);
	      if(fabs(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 full Debye-Scherrer cone is within d_phi, don't focus */
		  if (arg < -1 || arg > 1) d_phi = 0;
		  /* Otherwise, determine alpha to rotate from scattering plane
		     into d_phi focusing area*/
		  else alpha = 2*asin(arg);
		}
	      if (d_phi) {
		/* Focusing */
		alpha = fabs(alpha);
		/* Trick to get scattering for pos/neg theta's */
		alpha0= 2*rand01()*alpha;
		if (alpha0 > alpha) {
		  alpha0=PI+(alpha0-1.5*alpha);
		} else {
		  alpha0=alpha0-0.5*alpha;
		}
	      }
	      else
		alpha0 = PI*randpm1();
	      
	      /* now find a nearly vertical rotation axis:
	       * Either
	       *  (v along Z) x (X axis) -> nearly Y axis
	       * Or
	       *  (v along X) x (Z axis) -> nearly Y axis
	       */
	      if (fabs(scalar_prod(1,0,0,vx/v,vy/v,vz/v)) < fabs(scalar_prod(0,0,1,vx/v,vy/v,vz/v))) {
		nx = 1; ny = 0; nz = 0;
	      } else {
		nx = 0; ny = 0; nz = 1;
	      }
	      vec_prod(tmp_vx,tmp_vy,tmp_vz, vx,vy,vz, nx,ny,nz);
	      
	      /* 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 alpha0 around 'v' (Debye-Scherrer cone) */
	      rotate(tmp_vx,tmp_vy,tmp_vz, vout_x,vout_y,vout_z, alpha0, vx, vy, vz);
	      vx = tmp_vx;
	      vy = tmp_vy;
	      vz = tmp_vz;
	      
	      /* Since now scattered and new direction given, calculate path to exit */
	      if (isrect) {
		intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
		intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
	      } else {
		intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
		intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
	      }
	      
	      if (!intersect) {
		/* Strange error: did not hit cylinder */
		fprintf(stderr, "PowderN: FATAL ERROR: Did not hit sample from inside.\n");
		ABSORB;
	      }
	      
	      if (!intersecti) {
		t1 = (t3 + t0) /2;
		t2 = t1;
	      }
	      
	      if (concentric && intersecti) {
		/* In case of concentricity, 'remove' backward wall of sample */
		t2 = t1;
		t3 = t1;
	      }
	      
	      if(t0 < 0) t0=0; /* already in sample */
	      if(t1 < 0) t1=0; /* already in inner hollow */
	      if(t2 < 0) t2=0; /* already past inner hollow */
	      

	      l_1 = v*(t3 - t2 + t1 - t0); /* Length to exit */
	      
	      pmul  = Nq*l_full*my_s_n*exp(-(my_a_v/v+my_s)*(l+l_1))/(1-(frac+tfrac));
	      /* Correction in case of d_phi focusing - BUT only when d_phi != 0 */
	      if (d_phi) pmul *= alpha/PI;
	    } /* else transmit <-- No powder lines in file */
	  }  /* Coherent scattering event */
	else if (neutrontype == 2)
	  {  /* Make incoherent scattering event */
	    if(d_phi) {
	      randvec_target_rect_angular(&vx, &vy, &vz, &solid_angle,
					  0, 0, 1,
					  2*PI, d_phi*DEG2RAD, ROT_A_CURRENT_COMP);
	    } else {
	      randvec_target_circle(&vx, &vy, &vz,
				    &solid_angle, 0, 0, 1, 0);
	    }
	    v1 = sqrt(vx*vx+vy*vy+vz*vz);
	    vx *= v/v1;
	    vy *= v/v1;
	    vz *= v/v1;
	    
	    /* Since now scattered and new direction given, calculate path to exit */
	    if (isrect) {
	      intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
	      intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
	    } else {
	      intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
	      intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
	    }
	    
	    if (!intersect) {
	      /* Strange error: did not hit cylinder */
	      fprintf(stderr, "PowderN: FATAL ERROR: Did not hit sample from inside.\n");
	      ABSORB;
	    }  
	      
	    if (!intersecti) {
	      t1 = (t3 + t0) /2;
	      t2 = t1;
	    }
	      
	    if (concentric && intersecti) {
	      /* In case of concentricity, 'remove' backward wall of sample */
	      t2 = t1;
	      t3 = t1;
	    }
	      
	    if(t0 < 0) t0=0; /* already in sample */
	    if(t1 < 0) t1=0; /* already in inner hollow */
	    if(t2 < 0) t2=0; /* already past inner hollow */
	      

	    l_1 = v*(t3 - t2 + t1 - t0); /* Length to exit */
	    
	    pmul = l_full*my_inc*exp(-(my_a_v/v+my_s)*(l+l_1))/(frac);
	    pmul *= solid_angle/(4*PI);
	    
	  }  /* Incoherent scattering event */
	else if (neutrontype == 1) {
	  /* Make transmitted (absorption-corrected) event */
	  /* No coodinate changes here, simply change neutron weight */
	  pmul = exp(-(my_a_v/v+my_s)*(l))/(tfrac);
        }
	p *= pmul;
      } /* Neutron leaving since it has passed already */
    } /* else transmit non interacting neutrons */
  
}
#line 18143 "D1A.c"
/* 'Container_in' component extend code */
    SIG_MESSAGE("Container_in (Trace:Extend)");
#line 172 "D1A.instr"
  flag_container=SCATTERED;
#line 18148 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#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 Sample_liq [11] */
  mccoordschange(mcposrSample_liq, mcrotrSample_liq,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrSample_liq, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Sample_liq (without coords transformations) */
  mcJumpTrace_Sample_liq:
  SIG_MESSAGE("Sample_liq (Trace)");
  mcDEBUG_COMP("Sample_liq")
  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  Sample_liq
#define mccompcurtype  Isotropic_Sqw
#define mccompcurindex 11
#define Sqw_coh mccSample_liq_Sqw_coh
#define Sqw_inc mccSample_liq_Sqw_inc
#define powder_format mccSample_liq_powder_format
#define geometry mccSample_liq_geometry
#define VarSqw mccSample_liq_VarSqw
#define columns mccSample_liq_columns
#define offdata mccSample_liq_offdata
{   /* Declarations of SETTING parameters. */
MCNUM radius = mccSample_liq_radius;
MCNUM thickness = mccSample_liq_thickness;
MCNUM xwidth = mccSample_liq_xwidth;
MCNUM yheight = mccSample_liq_yheight;
MCNUM zdepth = mccSample_liq_zdepth;
MCNUM qmin = mccSample_liq_qmin;
MCNUM qmax = mccSample_liq_qmax;
MCNUM wmin = mccSample_liq_wmin;
MCNUM wmax = mccSample_liq_wmax;
MCNUM auto_qw = mccSample_liq_auto_qw;
MCNUM threshold = mccSample_liq_threshold;
int order = mccSample_liq_order;
MCNUM T = mccSample_liq_T;
MCNUM verbose = mccSample_liq_verbose;
MCNUM d_phi = mccSample_liq_d_phi;
int concentric = mccSample_liq_concentric;
MCNUM V_rho = mccSample_liq_V_rho;
MCNUM sigma_abs = mccSample_liq_sigma_abs;
MCNUM sigma_coh = mccSample_liq_sigma_coh;
MCNUM sigma_inc = mccSample_liq_sigma_inc;
MCNUM save_sqw = mccSample_liq_save_sqw;
MCNUM powder_Dd = mccSample_liq_powder_Dd;
MCNUM powder_DW = mccSample_liq_powder_DW;
MCNUM powder_Vc = mccSample_liq_powder_Vc;
MCNUM density = mccSample_liq_density;
MCNUM weight = mccSample_liq_weight;
MCNUM p_interact = mccSample_liq_p_interact;
MCNUM auto_norm = mccSample_liq_auto_norm;
MCNUM powder_barns = mccSample_liq_powder_barns;
/* 'Sample_liq' component has conditional execution */
if (( strstr ( Powder , ".qSq" ) ))

#line 1385 "/usr/local/lib/mcstas/samples/Isotropic_Sqw.comp"
{

int    intersect=0;     /* flag to continue/stop */
double t0,  t1,  t2,  t3; /* times for intersections */
double dt0, dt1, dt2, dt; /* time intervals */
double k=0, kf, kf1, kf2;
double v=0, vf;
double d_path;        /* total path length for straight trajectory */
double my_a;          /* absorption cross-section scaled to velocity (2200) */
double ws, p_scatt;   /* probability for scattering/absorption and for */
                      /* interaction along d_path */
double tmp_rand;      /* temporary var */
double ratio_w=0, ratio_q=0; /* variables for bilinear interpolation */
double q11, q21, q22, q12;
double omega=0;       /* energy transfert */
double q=0;           /* wavevector transfert */
long   index_w;       /* energy index for table look-up SW */
long   index_q;       /* Q index for table look-up P(Q|w) */
double theta, costheta; /* for the choice of kf direction */
double u1x,u1y,u1z;
double u2x,u2y,u2z;
double u0x,u0y,u0z;
int    index_counter;
int    flag=0;
int    flag_concentric=0;
int    flag_ishollow=0;
double solid_angle=0;
double my_t=0;
double p_mult=1;
double alpha, alpha0;
double mc_trans, p_trans, mc_scatt;
double coh=0, inc=0;
struct Sqw_Data_struct Data_sqw;


/* Store Initial neutron state */

VarSqw.ki_x = V2K*vx;
VarSqw.ki_y = V2K*vy;
VarSqw.ki_z = V2K*vz;
VarSqw.ti   = t;
VarSqw.vi   = 0;
VarSqw.ki   = 0;
VarSqw.type = '\0';

do { /* Main interaction loop. Ends with intersect=0 */

  /* Intersection neutron trajectory / sample (sample surface) */
  if (VarSqw.s_coh > 0 || VarSqw.s_inc > 0) {
    if (VarSqw.shape==0)
      intersect=cylinder_intersect(&t0,&t3, x,y,z,vx,vy,vz, radius,yheight);
    else if (VarSqw.shape==1)
      intersect=box_intersect     (&t0,&t3, x,y,z,vx,vy,vz, xwidth,yheight,zdepth);
    else if (VarSqw.shape==2)
      intersect=sphere_intersect  (&t0,&t3, x,y,z,vx,vy,vz, radius);
    else if (VarSqw.shape == 3)
      intersect=off_intersect(&t0, &t3, x, y, z, vx, vy, vz, offdata );
  } else intersect=0;

  /* Computing the intermediate times */
  if (intersect) {
    flag_ishollow = 0;
    if (thickness>0) {
      if (VarSqw.shape==0 && cylinder_intersect(&t1,&t2, x,y,z,vx,vy,vz, radius-thickness,yheight-2*thickness))
        flag_ishollow=1;
      else if (VarSqw.shape==2 && sphere_intersect   (&t1,&t2, x,y,z,vx,vy,vz, radius-thickness))
        flag_ishollow=1;
      else if (VarSqw.shape==1 && box_intersect(&t1,&t2, x,y,z,vx,vy,vz, xwidth-2*thickness, yheight-2*thickness, zdepth-2*thickness))
        flag_ishollow=1;
    }
    if (!flag_ishollow) t1 = t2 = t3; /* no empty space inside */
  } else break; /* neutron does not hit sample: transmitted  */

  if (intersect) { /* the neutron hits the sample */

    if (t0 > 0) {  /* we are before the sample */
      PROP_DT(t0); /* propagates neutron to the entry of the sample */
    } else if (t1 > 0 && t1 > t0) { /* we are inside first part of the sample */
      /* no propagation, stay inside */
    } else if (t2 > 0 && t2 > t1) { /* we are in the hole */
      PROP_DT(t2); /* propagate to inner surface of 2nd part of sample */
    } else if (t3 > 0 && t3 > t2) { /* we are in the 2nd part of sample */
      /* no propagation, stay inside */
    }

    dt0=t1-(t0 > 0 ? t0 : 0); /* Time in first part of hollow/cylinder/box */
    dt1=t2-(t1 > 0 ? t1 : 0); /* Time in hole */
    dt2=t3-(t2 > 0 ? t2 : 0); /* Time in 2nd part of hollow cylinder */

    if (dt0 < 0) dt0 = 0;
    if (dt1 < 0) dt1 = 0;
    if (dt2 < 0) dt2 = 0;

    /* initialize concentric mode */
    if (concentric && !flag_concentric && t0 >= 0
     && VarSqw.shape==0 && thickness>0) {
      flag_concentric=1;
    }

    if (flag_concentric == 1) {
      dt1=dt2=0; /* force exit when reaching hole/2nd part */
    }

    if (!dt0 && !dt2) {
      intersect = 0; /* the sample was passed entirely */
      break;
    }

    VarSqw.neutron_enter++;
    p_mult = 1;
    if (!v) {
      v  = vx*vx+vy*vy+vz*vz;
      v = sqrt(v);
    }
    k  = V2K*v;

    if (!VarSqw.vi) VarSqw.vi = v;
    if (!VarSqw.ki) VarSqw.ki = k;

    if (v <= 0) {
      printf("Isotropic_Sqw: %s: ERROR: Null velocity\n",NAME_CURRENT_COMP);
      VarSqw.neutron_removed++;
      ABSORB; /* should never occur */
    }

    /* check for scattering event */
    my_a   = VarSqw.my_a_v / v; /* absorption 'mu' */
    /* compute total scattering X section */
    /* \int q S(q) dq /2 /ki^2 sigma  OR  bare Xsection*/
    /* contains the 4*PI*kf/ki factor */
    coh = VarSqw.s_coh;
    inc = VarSqw.s_inc;
    if (k && VarSqw.s_coh>0 && VarSqw.Data_coh.intensity) {
      int index_2k = (int)floor(VarSqw.Data_coh.nb_q_data
                   * (2*k - VarSqw.Data_coh.q_min)
                   / (VarSqw.Data_coh.q_max-VarSqw.Data_coh.q_min));
      if (index_2k < 0) index_2k=0;
      if (index_2k >= VarSqw.Data_coh.nb_q_data)
        index_2k=VarSqw.Data_coh.nb_q_data-1;
      coh = VarSqw.s_coh/2/k/k*VarSqw.Data_coh.iqSq[index_2k];
    }
    if (k && VarSqw.s_inc>0 && VarSqw.Data_inc.intensity) {
      int index_2k = (int)floor(VarSqw.Data_inc.nb_q_data
                   * (2*k - VarSqw.Data_inc.q_min)
                   / (VarSqw.Data_inc.q_max-VarSqw.Data_inc.q_min));
      if (index_2k < 0) index_2k=0;
      if (index_2k >= VarSqw.Data_inc.nb_q_data)
        index_2k=VarSqw.Data_inc.nb_q_data-1;
      inc = VarSqw.s_inc/2/k/k*VarSqw.Data_inc.iqSq[index_2k];
    }
    if (coh<0) coh=0;
    if (inc<0) inc=0;
    VarSqw.my_s    =(VarSqw.rho*100*(coh + inc));

    my_t = my_a + VarSqw.my_s;  /* total scattering Xsect */
    if (my_t <= 0) {
      if (VarSqw.neutron_removed<VarSqw.maxloop) printf("Isotropic_Sqw: %s: ERROR: Null total cross section %g. Removing event.\n",
        NAME_CURRENT_COMP, my_t);
      VarSqw.neutron_removed++;
      ABSORB; /* should never occur */
    } else if (VarSqw.my_s <= 0) {
      if (VarSqw.verbose_output > 1 && VarSqw.neutron_removed<VarSqw.maxloop)
        printf("Isotropic_Sqw: %s: Warning: Null scattering cross section %g. Ignoring.\n",
          NAME_CURRENT_COMP, VarSqw.my_s);
      VarSqw.my_s = 0;
    }

    /* Proba of scattering vs absorption (integrating along the whole trajectory) */
    ws = VarSqw.my_s/my_t;  /* (inc+coh)/(inc+coh+abs) */
    d_path = v*( dt0 +dt2 );    /* total path lenght in sample */
    /* Proba of transmission/interaction along length d_path */
    p_trans = exp(-my_t*d_path);
    p_scatt = 1 - p_trans; /* portion of beam which scatters */

    flag = 0; /* flag used for propagation to exit point before ending */

    /* are we next to the exit ? probably no scattering (avoid rounding errors) */
    if (VarSqw.my_s*d_path <= 4e-7) {
      flag = 1;           /* No interaction before the exit */
    }
    /* force a given fraction of the beam to scatter */
    if (p_interact>0 && p_interact<=1) {
      /* we force a portion of the beam to interact */
      /* This is used to improve statistics on single scattering (and multiple) */
      if (!SCATTERED) mc_trans = 1-p_interact;
      else            mc_trans = 1-p_interact/(4*SCATTERED+1); /* reduce effect on multi scatt */
    } else {
      mc_trans = p_trans; /* 1 - p_scatt */
    }
    mc_scatt = 1 - mc_trans; /* portion of beam to scatter (or force to) */
    if (mc_scatt <= 0 || mc_scatt>1) flag=1;
    /* MC choice: Interaction or transmission ? */
    if (!flag && mc_scatt > 0 && (mc_scatt >= 1 || rand01() < mc_scatt)) { /* Interaction neutron/sample */
      p_mult *= ws; /* Update weight ; account for absorption and retain scattered fraction */
      /* we have chosen portion mc_scatt of beam instead of p_scatt, so we compensate */
      p_mult *= fabs(p_scatt/mc_scatt); /* lower than 1 */
    } else {
      flag = 1; /* Transmission : no interaction neutron/sample */
      if (!VarSqw.type) VarSqw.type = 't';
      p_mult *= fabs(p_trans/mc_trans);  /* attenuate beam by portion which is scattered (and left along) */
    }

    if (flag) { /* propagate to exit of sample and finish */
      intersect = 0;
      p *= p_mult; /* apply absorption correction */
      PROP_DT(dt0+dt2);
      break; /* exit main multi scatt while loop */
    }
  } /* end if intersect the neutron hits the sample */
  else break;

  if (intersect) { /* scattering event */
    /* mean scattering probability and absorption fraction */
    VarSqw.mean_scatt += (1-exp(-VarSqw.my_s*d_path))*p;
    VarSqw.mean_abs   += (1-ws)*p;
    VarSqw.psum_scatt += p;

    /* Decaying exponential distribution of the path length before scattering */
    /* Select a point at which to scatter the neutron, taking
         secondary extinction into account. */
    if (my_t*d_path < 1e-6)
    /* For very weak scattering, use simple uniform sampling of scattering
       point to avoid rounding errors. */
      dt = rand0max(d_path); /* length */
    else
      dt = -log(1 - rand0max((1 - exp(-my_t*d_path)))) / my_t; /* length */
    dt /= v; /* Time from present position to scattering point */

    /* If t0 is in hole, propagate to next part of the hollow cylinder */
    if (dt1 > 0 && dt0 > 0 && dt > dt0) dt += dt1;

    /* Neutron propagation to the scattering point */
    PROP_DT(dt);

    /* choice between coherent/incoherent scattering */
    tmp_rand = rand01();
    /* local description at the scattering point (scat probability for atom) */
    tmp_rand *= (coh+inc);

    flag=0;
    if (VarSqw.s_inc>0 && tmp_rand < inc) {
      /* CASE 1: incoherent case */
      if (!VarSqw.Data_inc.intensity) {
        /* CASE 1a: no incoherent Sqw from file, use isotropic V-like */
        if (d_phi && order == 1) {
          randvec_target_rect_angular(&u1x, &u1y, &u1z, &solid_angle,
              vx, vy, vz, 2*PI, d_phi, ROT_A_CURRENT_COMP);
          p_mult *= solid_angle/4/PI; /* weighted by focused range to total range */
        } else
          randvec_target_circle(&u1x, &u1y, &u1z, NULL, vx, vy, vz, 0);

        vx = u1x; vy = u1y; vz = u1z;
        vf = v; kf = k;
        if (!VarSqw.type) VarSqw.type = 'v';
        SCATTER;
      } else {
        /* CASE 1b: incoherent Sqw from file */
        if (VarSqw.Data_inc.intensity) {
          Data_sqw = VarSqw.Data_inc;
          if (!VarSqw.type) VarSqw.type = 'i';
          flag = 1;
        }
      }
    } else if (VarSqw.s_coh>0 && tmp_rand > VarSqw.s_inc) {
      if (VarSqw.Data_coh.intensity) {
        /* CASE2: coherent case */
        Data_sqw = VarSqw.Data_coh;
        if (!VarSqw.type) VarSqw.type = 'c';
        flag = 1;
      }
    }

    if (flag) { /* true when S(q,w) table exists (Data_sqw) */

      /* give us a limited number of tries for scattering */
      for (index_counter=VarSqw.maxloop; index_counter > 0 ; index_counter--) {

        /* MC choice: energy transfer in the SW */
        tmp_rand = rand01();
        /* index for rand > cumul SW */
        index_w = Sqw_search_SW(Data_sqw, tmp_rand);
        if (&(Data_sqw.SW[index_w]) != NULL) {
          if (Data_sqw.nb_w > 1) {
            double w1, w2;
            if (index_w > 0) { /* interpolate linearly energy */
              ratio_w = (tmp_rand                              - Data_sqw.SW[index_w-1].cumul_proba)
                       /(Data_sqw.SW[index_w].cumul_proba - Data_sqw.SW[index_w-1].cumul_proba);
              /* ratio_w=0 omega[index_w-1], ratio=1 omega[index] */
              w1 = Data_sqw.SW[index_w-1].omega; w2 = Data_sqw.SW[index_w].omega;
            } else { /* index_w = 0 interpolate to 0 energy */
              /* ratio_w=0 omega=0, ratio=1 omega[index] */
              w1 = 0; w2= Data_sqw.SW[index_w].omega;
              if (!w2 && index_w+1 < Data_sqw.nb_w)
                w2= Data_sqw.SW[index_w+1].omega;
              if (Data_sqw.nb_w && Data_sqw.SW[index_w].cumul_proba) {
                ratio_w = tmp_rand/Data_sqw.SW[index_w].cumul_proba;
              } else ratio_w=0;
            }
            omega = (1-ratio_w)*w1 + ratio_w*w2;
          } else {
            omega = Data_sqw.SW[index_w].omega;
          }
        } else {
          if (VarSqw.verbose_output >= 3 && VarSqw.neutron_removed<VarSqw.maxloop)
            printf("Isotropic_Sqw: %s: Warning: No suitable w transfert\n"
                   "               for index_w=%li. Using w=0.\n",
              NAME_CURRENT_COMP, index_w);
          omega=0;
        }
        if (ratio_w<0 || ratio_w > 1) {
          if (VarSqw.verbose_output>1 && VarSqw.neutron_removed<VarSqw.maxloop)
            printf("Isotropic_Sqw: %s: Warning: interpolation ratio_w=%g is wrong, index_w=%li, rand01=%g cumul=%g\n",
            NAME_CURRENT_COMP, ratio_w, index_w, tmp_rand, Data_sqw.SW[index_w].cumul_proba);
          if (ratio_w<0) ratio_w=0; else if (ratio_w>1) ratio_w=1;
        }

        /* MC choice: detailed balance: choice between w and -w : w=Ei-Ef */
        if (omega && VarSqw.Temperature) {
          if (rand01() > 1/(1+exp(-omega/(VarSqw.Temperature*VarSqw.T2E))) )
            omega = -omega; /* anti Stokes: sample loose energy into the neutron */
          else {            /* else Stokes */
            if (omega >= VS2E*v*v) continue; /* neutron can not loose more than its own energy */
          }
        }

        /* MC choice: momentum transfer Q in P(Q|w) */
        tmp_rand = rand01();
        index_q = Sqw_search_Q_proba_per_w(Data_sqw, tmp_rand, index_w);
        if (index_q == -1) {
          if (VarSqw.verbose_output >= 3 && VarSqw.neutron_removed<VarSqw.maxloop)
            printf("Isotropic_Sqw: %s: Warning: No suitable (q|w) transfert\n"
               "               for w=%g index_w=%li\n",
            NAME_CURRENT_COMP, omega, index_w);
          VarSqw.neutron_removed++;
          continue; /* no Q value for this w choice */
        }
        if (&(Data_sqw.SQW[index_w]) != NULL) {
          if (Data_sqw.nb_q > 1 && index_q > 0) {
            if (index_w > 0 && Data_sqw.nb_w > 1) {
              /* bilinear interpolation on - side: index_w > 0, index_q > 0 */
              ratio_q = (tmp_rand - Data_sqw.SQW[index_w][index_q-1].cumul_proba)
                       /(Data_sqw.SQW[index_w][index_q].cumul_proba
                       - Data_sqw.SQW[index_w][index_q-1].cumul_proba);
              q22 = Data_sqw.SQW[index_w]  [index_q].Q;
              q11 = Data_sqw.SQW[index_w-1][index_q-1].Q;
              q21 = Data_sqw.SQW[index_w]  [index_q-1].Q;
              q12 = Data_sqw.SQW[index_w-1][index_q].Q;
              q = (1-ratio_w)*(1-ratio_q)*q11+ratio_w*(1-ratio_q)*q21
                + ratio_w*ratio_q*q22        +(1-ratio_w)*ratio_q*q12;
            } else { /* bilinear interpolation on + side: index_w=0, index_q > 0 */
              ratio_q = (tmp_rand - Data_sqw.SQW[index_w][index_q-1].cumul_proba)
                       /(Data_sqw.SQW[index_w][index_q].cumul_proba
                       - Data_sqw.SQW[index_w][index_q-1].cumul_proba);
              q11 = Data_sqw.SQW[index_w]  [index_q-1].Q;
              q12 = Data_sqw.SQW[index_w]  [index_q].Q;
              if (index_w < Data_sqw.nb_w-1 && Data_sqw.nb_w > 1) {
                q22 = Data_sqw.SQW[index_w+1][index_q].Q;
                q21 = Data_sqw.SQW[index_w+1][index_q-1].Q;
                q = (1-ratio_w)*(1-ratio_q)*q11+ratio_w*(1-ratio_q)*q21
                  + ratio_w*ratio_q*q22        +(1-ratio_w)*ratio_q*q12;
              } else {
                q    = (1-ratio_q)*q11  + ratio_q*q12;
              }
            }
          } else {
            q    = Data_sqw.SQW[index_w][index_q].Q;
          }
        } else {
          if (VarSqw.verbose_output >= 3 && VarSqw.neutron_removed<VarSqw.maxloop)
            printf("Isotropic_Sqw: %s: Warning: No suitable q transfert\n"
               "               for w=%g\n",
            NAME_CURRENT_COMP, omega);
          VarSqw.neutron_removed++;
          continue;
        }
        if (ratio_q<0 || ratio_q > 1) {
          if (VarSqw.verbose_output && VarSqw.neutron_removed<VarSqw.maxloop)
          printf("Isotropic_Sqw: %s: Warning: interpolation ratio_q=%g is wrong, index_q=%li\n"
                 "               ratio_w=%g, index_w=%li\n",
            NAME_CURRENT_COMP, ratio_q, index_q, ratio_w, index_w);
          if (ratio_q<0) ratio_q=0; else if (ratio_q>1) ratio_q=1;
        }

        /* Search for length of final wave vector kf */
        /* kf is such that : hbar*w = hbar*hbar/2/m*(k*k - kf*kf) */
        /* acceptable values for kf are kf1 and kf2 */
        if (!Sqw_search_root(1, 0, -k*k + VarSqw.sqSE2K*omega, &kf1, &kf2)) {
          if (VarSqw.verbose_output >= 3 && VarSqw.neutron_removed<VarSqw.maxloop)
            printf("Isotropic_Sqw: %s: Warning: imaginary root for\n"
                 "               w=%g q=%g (triangle can not close)\n",
            NAME_CURRENT_COMP, omega, q);
          VarSqw.neutron_removed++;
          continue; /* all roots are imaginary */
        }

        /* kf1 and kf2 are opposite */
        kf = fabs(kf1);
        vf = K2V*kf;

        /* Search of the direction of kf such that : q = ki - kf */
        /* cos theta = (ki2+kf2-q21)/(2ki kf) */

        costheta= (k*k+kf*kf-q*q)/(2*kf*k); /* this is cos(theta) */

        if (-1 < costheta && costheta < 1) {
          break; /* satisfies q momentum conservation */
        }
/*      else continue; */

        /* exit for loop on success */
      } /* end for index_counter */

      if (!index_counter) { /* for loop ended: failure for scattering */
        intersect=0; /* Could not scatter: finish multiple scattering loop */
        if (VarSqw.verbose_output >= 2 && VarSqw.neutron_removed<VarSqw.maxloop)
          printf("Isotropic_Sqw: %s: Warning: No scattering [q,w] conditions\n"
               "               last try (%i): type=%c w=%g q=%g cos(theta)=%g\n",
          NAME_CURRENT_COMP, VarSqw.maxloop, (VarSqw.type ? VarSqw.type : '-'), omega, q, costheta);
        VarSqw.neutron_removed++;
        if (order && SCATTERED != order) ABSORB;
        break;       /* finish multiple scattering loop */
      }

      /* scattering angle from ki to DS cone */
      theta = acos(costheta);

      /* Choose point on Debye-Scherrer cone */
      if (order == 1 && d_phi)
      { /* relate height of detector to the height on DS cone */
        double cone_focus;
        cone_focus = sin(d_phi/2)/sin(theta);
        /* If full Debye-Scherrer cone is within d_phi, don't focus */
        if (cone_focus < -1 || cone_focus > 1) d_phi = 0;
        /* Otherwise, determine alpha to rotate from scattering plane
            into d_phi focusing area*/
        else alpha = 2*asin(cone_focus);
        if (d_phi) p_mult *= alpha/PI;
      }
      if (d_phi) {
        /* Focusing */
        alpha = fabs(alpha);
        /* Trick to get scattering for pos/neg theta's */
        alpha0= 2*rand01()*alpha;
        if (alpha0 > alpha) {
          alpha0=PI+(alpha0-1.5*alpha);
        } else {
          alpha0=alpha0-0.5*alpha;
        }
      }
      else
        alpha0 = PI*randpm1();

      /* now find a nearly vertical rotation axis (u1) :
	       * Either
	       *  (v along Z) x (X axis) -> nearly Y axis
	       * Or
	       *  (v along X) x (Z axis) -> nearly Y axis
	       */
	    if (fabs(scalar_prod(1,0,0,vx/v,vy/v,vz/v)) < fabs(scalar_prod(0,0,1,vx/v,vy/v,vz/v))) {
        u1x = 1; u1y = u1z = 0;
	    } else {
        u1x = u1y = 0; u1z = 1;
	    }
	    vec_prod(u2x,u2y,u2z, vx,vy,vz, u1x,u1y,u1z);

      /* handle case where v and aim are parallel */
      if (!u2x && !u2y && !u2z) { u2x=u2z=0; u2y=1; }

      /* u1 = rotate 'v' by theta around u2: DS scattering angle, nearly in horz plane */
      rotate(u1x,u1y,u1z, vx,vy,vz, theta, u2x,u2y,u2z);

      /* u0 = rotate u1 by alpha0 around 'v' (Debye-Scherrer cone) */
      rotate(u0x,u0y,u0z, u1x,u1y,u1z, alpha0, vx, vy, vz);
      NORM(u0x,u0y,u0z);
      vx = u0x*vf;
      vy = u0y*vf;
      vz = u0z*vf;

      SCATTER;

      if      (fabs(omega) > VarSqw.w_max) VarSqw.w_max = fabs(omega);
      if      (fabs(q)     > VarSqw.q_max) VarSqw.q_max = fabs(q);

      v = vf; k = kf; /* for next iteration */

      if (VarSqw.neutron_exit > VarSqw.minevents
       && VarSqw.neutron_removed && VarSqw.sqw_auto) {
        double old_qmax_inc = VarSqw.Data_inc.q_max;
        double old_qmax_coh = VarSqw.Data_coh.q_max;
        double old_wmax_inc = VarSqw.Data_inc.w_max;
        double old_wmax_coh = VarSqw.Data_coh.w_max;
        if (VarSqw.verbose_output)
          printf("Isotropic_Sqw: %s: %li events monitored out of %li.\n"
                 "INFO:          Optimizing qmax=%g wmax=%g\n",
          NAME_CURRENT_COMP, VarSqw.neutron_removed, VarSqw.neutron_exit,
          VarSqw.q_max, VarSqw.w_max);
        /* VarSqw.Data_inc.q_min = VarSqw.Data_coh.q_min = VarSqw.q_min; */
        VarSqw.Data_inc.q_max = VarSqw.Data_coh.q_max = VarSqw.q_max*1.1;
        /* VarSqw.Data_inc.w_min = VarSqw.Data_coh.w_min = VarSqw.w_min; */
        VarSqw.Data_inc.w_max = VarSqw.Data_coh.w_max = VarSqw.w_max*1.1;
        VarSqw.sqw_auto = 2; /* request new probability tables */
        if (!Sqw_init(&VarSqw, Sqw_coh, Sqw_inc)) {

          VarSqw.Data_inc.q_max =  old_qmax_inc;
          VarSqw.Data_coh.q_max =  old_qmax_coh;
          VarSqw.Data_inc.w_max =  old_wmax_inc;
          VarSqw.Data_coh.w_max =  old_wmax_coh;
          VarSqw.q_max = FLT_MAX; /* restore full (q,w) range */
          VarSqw.w_max = FLT_MAX;
          if (!Sqw_init(&VarSqw, Sqw_coh, Sqw_inc)) {
            printf("Isotropic_Sqw: %s: ERROR re-importing data files (Sqw_init from TRACE)\n",NAME_CURRENT_COMP);
            exit(0);
          } else
            printf("Isotropic_Sqw: %s: Warning (q,w) range optimization failed. Ignoring.\n",NAME_CURRENT_COMP);
        }
        VarSqw.sqw_auto = 0;
      }

    } /* end if (flag) */

    VarSqw.neutron_exit++;
    p *= p_mult;
    if (p_mult > 1) VarSqw.neutron_pmult++;

    /* test for a given multiple order */
    if (order && SCATTERED >= order) {
      intersect=0; /* reached required number of SCATTERing */
      break;       /* finish multiple scattering loop */
    }

  } /* end if (intersect) scattering event  */

} while (intersect); /* end do (intersect) (multiple scattering loop) */

/* Store Final neutron state */
VarSqw.kf_x = V2K*vx;
VarSqw.kf_y = V2K*vy;
VarSqw.kf_z = V2K*vz;
VarSqw.tf   = t;
VarSqw.vf   = v;
VarSqw.kf   = k;
VarSqw.theta= theta;

if (SCATTERED) {

  VarSqw.dq = sqrt((VarSqw.kf_x-VarSqw.ki_x)*(VarSqw.kf_x-VarSqw.ki_x)
                  +(VarSqw.kf_y-VarSqw.ki_y)*(VarSqw.kf_y-VarSqw.ki_y)
                  +(VarSqw.kf_z-VarSqw.ki_z)*(VarSqw.kf_z-VarSqw.ki_z));
  VarSqw.dw = VS2E*(VarSqw.vf*VarSqw.vf - VarSqw.vi*VarSqw.vi);

  if (SCATTERED == 1) VarSqw.single += p;
  else VarSqw.multi += p;

} else VarSqw.dq=VarSqw.dw=0;

/* end TRACE */
}
#line 18803 "D1A.c"
/* 'Sample_liq' component extend code */
    SIG_MESSAGE("Sample_liq (Trace:Extend)");
if (( strstr ( Powder , ".qSq" ) ))

#line 180 "D1A.instr"
  if (SCATTERED)
    flag_sample=SCATTERED;
#line 18810 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef offdata
#undef columns
#undef VarSqw
#undef geometry
#undef powder_format
#undef Sqw_inc
#undef Sqw_coh
#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 Sample [12] */
  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(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  Sample
#define mccompcurtype  PowderN
#define mccompcurindex 12
#define reflections mccSample_reflections
#define format mccSample_format
#define line_info mccSample_line_info
#define Nq mccSample_Nq
#define my_s_v2 mccSample_my_s_v2
#define my_s_v2_sum mccSample_my_s_v2_sum
#define my_a_v mccSample_my_a_v
#define my_inc mccSample_my_inc
#define q_v mccSample_q_v
#define w_v mccSample_w_v
#define isrect mccSample_isrect
#define columns mccSample_columns
{   /* Declarations of SETTING parameters. */
MCNUM d_phi = mccSample_d_phi;
MCNUM radius = mccSample_radius;
MCNUM radius_i = mccSample_radius_i;
MCNUM yheight = mccSample_yheight;
MCNUM pack = mccSample_pack;
MCNUM Vc = mccSample_Vc;
MCNUM sigma_abs = mccSample_sigma_abs;
MCNUM sigma_inc = mccSample_sigma_inc;
MCNUM Delta_d = mccSample_Delta_d;
MCNUM frac = mccSample_frac;
MCNUM tfrac = mccSample_tfrac;
MCNUM xwidth = mccSample_xwidth;
MCNUM zthick = mccSample_zthick;
MCNUM xwidth_i = mccSample_xwidth_i;
MCNUM yheight_i = mccSample_yheight_i;
MCNUM zthick_i = mccSample_zthick_i;
MCNUM h = mccSample_h;
MCNUM DW = mccSample_DW;
MCNUM nb_atoms = mccSample_nb_atoms;
MCNUM concentric = mccSample_concentric;
MCNUM density = mccSample_density;
MCNUM weight = mccSample_weight;
MCNUM barns = mccSample_barns;
/* 'Sample' component has conditional execution */
if (( ! strstr ( Powder , ".qSq" ) ))

#line 496 "/usr/local/lib/mcstas/samples/PowderN.comp"
{
  double t0, t1, t2, t3, v, v1,l_full, l, l_1, dt, alpha0, alpha, theta, my_s, my_s_n;
  double solid_angle, neutrontype;
  double arg, tmp_vx, tmp_vy, tmp_vz, vout_x, vout_y, vout_z, nx, ny, nz, pmul=1;
  int    line;
  char   intersect=0;
  char   intersecti=0;

  if (isrect) {
    intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
    intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
  } else {
    intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
    intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
  }
  
  if(intersect && t3 >0)
    {
      
      if (concentric) {
	/* Set up for concentric case */
	/* 'Remove' the backside of this comp */
	if (!intersecti) {
	  t1 = (t3 + t0) /2;
	}
	t2 = t1;
	t3 = t1;
	dt = -1.0*rand01(); /* In case of scattering we will scatter on 'forward' part of sample */
      } else {
	if (!intersecti) {
	  t1 = (t3 + t0) /2;
	  t2 = t1;
	}
	dt = randpm1(); /* Possibility to scatter at all points in line of sight */
      }
      
      /* Neutron enters at t=t0. */
      if(t0 < 0) t0=0; /* already in sample */
      if(t1 < 0) t1=0; /* already in inner hollow */
      if(t2 < 0) t2=0; /* already past inner hollow */
      v = sqrt(vx*vx + vy*vy + vz*vz);
      l_full = v * (t3 - t2 + t1 - t0);

      /* Calculate total scattering cross section at relevant velocity */
      my_s_v2_sum=0;
      for(line=0; line<Nq; line++) {
	if (q_v[line] <= 2*v) {
	  my_s_v2_sum+=my_s_v2[line];
	}
      }
      
      if (t3 < 0) {
	t3=0; /* Already past sample?! */
	printf("PowderN %s Warning: Neutron has already passed us? (Skipped)\n", NAME_CURRENT_COMP);
      } else {
	if (dt<0) { /* Calculate scattering point position */
	  dt = fabs(dt)*(t1 - t0); /* 'Forward' part */
	} else {
	  dt = dt * (t3 - t2) + (t2-t0) ; /* Possibly also 'backside' part */
	}
	
	my_s = my_s_v2_sum/(v*v)+my_inc;
	/* Total attenuation from scattering */
	
	neutrontype = rand01();
	/* How to handle this one? Transmit (1) / Incoherent (2) / Coherent (3) ? */
	if (neutrontype < tfrac) {
	  neutrontype = 1; 
	  l = l_full; /* Passing through, full length */
	  PROP_DT(t3); 
	} else if (neutrontype >= tfrac && neutrontype < (tfrac + frac)) {
	  neutrontype = 2;
	  l = v*dt;       /* Penetration in sample */
	  PROP_DT(dt+t0); /* Point of scattering */
	  SCATTER;
	} else if (neutrontype >= tfrac + frac) {
	  neutrontype = 3;
	  l = v*dt;       /* Penetration in sample */
	  PROP_DT(dt+t0); /* Point of scattering */
	  SCATTER;
	} else {
	  exit(fprintf(stderr,"PowderN %s: DEAD - this shouldn't happen!\n", NAME_CURRENT_COMP));
	}
	
	if (neutrontype == 3)
	  { /* Make coherent scattering event */
	    
	    if (line_info.count > 0) {
	      /* choose line */
	      if (Nq > 1) line=floor(Nq*rand01());  /* Select between Nq powder lines */
	      else line = 0;
	      if (w_v[line])
		arg = q_v[line]*(1+w_v[line]*randnorm())/(2.0*v);
	      else
		arg = q_v[line]/(2.0*v);
	      my_s_n = my_s_v2[line]/(v*v);
	      if(fabs(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 full Debye-Scherrer cone is within d_phi, don't focus */
		  if (arg < -1 || arg > 1) d_phi = 0;
		  /* Otherwise, determine alpha to rotate from scattering plane
		     into d_phi focusing area*/
		  else alpha = 2*asin(arg);
		}
	      if (d_phi) {
		/* Focusing */
		alpha = fabs(alpha);
		/* Trick to get scattering for pos/neg theta's */
		alpha0= 2*rand01()*alpha;
		if (alpha0 > alpha) {
		  alpha0=PI+(alpha0-1.5*alpha);
		} else {
		  alpha0=alpha0-0.5*alpha;
		}
	      }
	      else
		alpha0 = PI*randpm1();
	      
	      /* now find a nearly vertical rotation axis:
	       * Either
	       *  (v along Z) x (X axis) -> nearly Y axis
	       * Or
	       *  (v along X) x (Z axis) -> nearly Y axis
	       */
	      if (fabs(scalar_prod(1,0,0,vx/v,vy/v,vz/v)) < fabs(scalar_prod(0,0,1,vx/v,vy/v,vz/v))) {
		nx = 1; ny = 0; nz = 0;
	      } else {
		nx = 0; ny = 0; nz = 1;
	      }
	      vec_prod(tmp_vx,tmp_vy,tmp_vz, vx,vy,vz, nx,ny,nz);
	      
	      /* 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 alpha0 around 'v' (Debye-Scherrer cone) */
	      rotate(tmp_vx,tmp_vy,tmp_vz, vout_x,vout_y,vout_z, alpha0, vx, vy, vz);
	      vx = tmp_vx;
	      vy = tmp_vy;
	      vz = tmp_vz;
	      
	      /* Since now scattered and new direction given, calculate path to exit */
	      if (isrect) {
		intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
		intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
	      } else {
		intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
		intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
	      }
	      
	      if (!intersect) {
		/* Strange error: did not hit cylinder */
		fprintf(stderr, "PowderN: FATAL ERROR: Did not hit sample from inside.\n");
		ABSORB;
	      }
	      
	      if (!intersecti) {
		t1 = (t3 + t0) /2;
		t2 = t1;
	      }
	      
	      if (concentric && intersecti) {
		/* In case of concentricity, 'remove' backward wall of sample */
		t2 = t1;
		t3 = t1;
	      }
	      
	      if(t0 < 0) t0=0; /* already in sample */
	      if(t1 < 0) t1=0; /* already in inner hollow */
	      if(t2 < 0) t2=0; /* already past inner hollow */
	      

	      l_1 = v*(t3 - t2 + t1 - t0); /* Length to exit */
	      
	      pmul  = Nq*l_full*my_s_n*exp(-(my_a_v/v+my_s)*(l+l_1))/(1-(frac+tfrac));
	      /* Correction in case of d_phi focusing - BUT only when d_phi != 0 */
	      if (d_phi) pmul *= alpha/PI;
	    } /* else transmit <-- No powder lines in file */
	  }  /* Coherent scattering event */
	else if (neutrontype == 2)
	  {  /* Make incoherent scattering event */
	    if(d_phi) {
	      randvec_target_rect_angular(&vx, &vy, &vz, &solid_angle,
					  0, 0, 1,
					  2*PI, d_phi*DEG2RAD, ROT_A_CURRENT_COMP);
	    } else {
	      randvec_target_circle(&vx, &vy, &vz,
				    &solid_angle, 0, 0, 1, 0);
	    }
	    v1 = sqrt(vx*vx+vy*vy+vz*vz);
	    vx *= v/v1;
	    vy *= v/v1;
	    vz *= v/v1;
	    
	    /* Since now scattered and new direction given, calculate path to exit */
	    if (isrect) {
	      intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
	      intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
	    } else {
	      intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
	      intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
	    }
	    
	    if (!intersect) {
	      /* Strange error: did not hit cylinder */
	      fprintf(stderr, "PowderN: FATAL ERROR: Did not hit sample from inside.\n");
	      ABSORB;
	    }  
	      
	    if (!intersecti) {
	      t1 = (t3 + t0) /2;
	      t2 = t1;
	    }
	      
	    if (concentric && intersecti) {
	      /* In case of concentricity, 'remove' backward wall of sample */
	      t2 = t1;
	      t3 = t1;
	    }
	      
	    if(t0 < 0) t0=0; /* already in sample */
	    if(t1 < 0) t1=0; /* already in inner hollow */
	    if(t2 < 0) t2=0; /* already past inner hollow */
	      

	    l_1 = v*(t3 - t2 + t1 - t0); /* Length to exit */
	    
	    pmul = l_full*my_inc*exp(-(my_a_v/v+my_s)*(l+l_1))/(frac);
	    pmul *= solid_angle/(4*PI);
	    
	  }  /* Incoherent scattering event */
	else if (neutrontype == 1) {
	  /* Make transmitted (absorption-corrected) event */
	  /* No coodinate changes here, simply change neutron weight */
	  pmul = exp(-(my_a_v/v+my_s)*(l))/(tfrac);
        }
	p *= pmul;
      } /* Neutron leaving since it has passed already */
    } /* else transmit non interacting neutrons */
  
}
#line 19148 "D1A.c"
/* 'Sample' component extend code */
    SIG_MESSAGE("Sample (Trace:Extend)");
if (( ! strstr ( Powder , ".qSq" ) ))

#line 190 "D1A.instr"
  if (SCATTERED)
    flag_sample=SCATTERED;
#line 19155 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#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 Container_out [13] */
  mccoordschange(mcposrContainer_out, mcrotrContainer_out,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrContainer_out, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Container_out (without coords transformations) */
  mcJumpTrace_Container_out:
  SIG_MESSAGE("Container_out (Trace)");
  mcDEBUG_COMP("Container_out")
  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(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  Container_out
#define mccompcurtype  PowderN
#define mccompcurindex 13
#define reflections mccContainer_out_reflections
#define format mccContainer_out_format
#define line_info mccContainer_out_line_info
#define Nq mccContainer_out_Nq
#define my_s_v2 mccContainer_out_my_s_v2
#define my_s_v2_sum mccContainer_out_my_s_v2_sum
#define my_a_v mccContainer_out_my_a_v
#define my_inc mccContainer_out_my_inc
#define q_v mccContainer_out_q_v
#define w_v mccContainer_out_w_v
#define isrect mccContainer_out_isrect
#define columns mccContainer_out_columns
{   /* Declarations of SETTING parameters. */
MCNUM d_phi = mccContainer_out_d_phi;
MCNUM radius = mccContainer_out_radius;
MCNUM radius_i = mccContainer_out_radius_i;
MCNUM yheight = mccContainer_out_yheight;
MCNUM pack = mccContainer_out_pack;
MCNUM Vc = mccContainer_out_Vc;
MCNUM sigma_abs = mccContainer_out_sigma_abs;
MCNUM sigma_inc = mccContainer_out_sigma_inc;
MCNUM Delta_d = mccContainer_out_Delta_d;
MCNUM frac = mccContainer_out_frac;
MCNUM tfrac = mccContainer_out_tfrac;
MCNUM xwidth = mccContainer_out_xwidth;
MCNUM zthick = mccContainer_out_zthick;
MCNUM xwidth_i = mccContainer_out_xwidth_i;
MCNUM yheight_i = mccContainer_out_yheight_i;
MCNUM zthick_i = mccContainer_out_zthick_i;
MCNUM h = mccContainer_out_h;
MCNUM DW = mccContainer_out_DW;
MCNUM nb_atoms = mccContainer_out_nb_atoms;
MCNUM concentric = mccContainer_out_concentric;
MCNUM density = mccContainer_out_density;
MCNUM weight = mccContainer_out_weight;
MCNUM barns = mccContainer_out_barns;
#line 496 "/usr/local/lib/mcstas/samples/PowderN.comp"
{
  double t0, t1, t2, t3, v, v1,l_full, l, l_1, dt, alpha0, alpha, theta, my_s, my_s_n;
  double solid_angle, neutrontype;
  double arg, tmp_vx, tmp_vy, tmp_vz, vout_x, vout_y, vout_z, nx, ny, nz, pmul=1;
  int    line;
  char   intersect=0;
  char   intersecti=0;

  if (isrect) {
    intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
    intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
  } else {
    intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
    intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
  }
  
  if(intersect && t3 >0)
    {
      
      if (concentric) {
	/* Set up for concentric case */
	/* 'Remove' the backside of this comp */
	if (!intersecti) {
	  t1 = (t3 + t0) /2;
	}
	t2 = t1;
	t3 = t1;
	dt = -1.0*rand01(); /* In case of scattering we will scatter on 'forward' part of sample */
      } else {
	if (!intersecti) {
	  t1 = (t3 + t0) /2;
	  t2 = t1;
	}
	dt = randpm1(); /* Possibility to scatter at all points in line of sight */
      }
      
      /* Neutron enters at t=t0. */
      if(t0 < 0) t0=0; /* already in sample */
      if(t1 < 0) t1=0; /* already in inner hollow */
      if(t2 < 0) t2=0; /* already past inner hollow */
      v = sqrt(vx*vx + vy*vy + vz*vz);
      l_full = v * (t3 - t2 + t1 - t0);

      /* Calculate total scattering cross section at relevant velocity */
      my_s_v2_sum=0;
      for(line=0; line<Nq; line++) {
	if (q_v[line] <= 2*v) {
	  my_s_v2_sum+=my_s_v2[line];
	}
      }
      
      if (t3 < 0) {
	t3=0; /* Already past sample?! */
	printf("PowderN %s Warning: Neutron has already passed us? (Skipped)\n", NAME_CURRENT_COMP);
      } else {
	if (dt<0) { /* Calculate scattering point position */
	  dt = fabs(dt)*(t1 - t0); /* 'Forward' part */
	} else {
	  dt = dt * (t3 - t2) + (t2-t0) ; /* Possibly also 'backside' part */
	}
	
	my_s = my_s_v2_sum/(v*v)+my_inc;
	/* Total attenuation from scattering */
	
	neutrontype = rand01();
	/* How to handle this one? Transmit (1) / Incoherent (2) / Coherent (3) ? */
	if (neutrontype < tfrac) {
	  neutrontype = 1; 
	  l = l_full; /* Passing through, full length */
	  PROP_DT(t3); 
	} else if (neutrontype >= tfrac && neutrontype < (tfrac + frac)) {
	  neutrontype = 2;
	  l = v*dt;       /* Penetration in sample */
	  PROP_DT(dt+t0); /* Point of scattering */
	  SCATTER;
	} else if (neutrontype >= tfrac + frac) {
	  neutrontype = 3;
	  l = v*dt;       /* Penetration in sample */
	  PROP_DT(dt+t0); /* Point of scattering */
	  SCATTER;
	} else {
	  exit(fprintf(stderr,"PowderN %s: DEAD - this shouldn't happen!\n", NAME_CURRENT_COMP));
	}
	
	if (neutrontype == 3)
	  { /* Make coherent scattering event */
	    
	    if (line_info.count > 0) {
	      /* choose line */
	      if (Nq > 1) line=floor(Nq*rand01());  /* Select between Nq powder lines */
	      else line = 0;
	      if (w_v[line])
		arg = q_v[line]*(1+w_v[line]*randnorm())/(2.0*v);
	      else
		arg = q_v[line]/(2.0*v);
	      my_s_n = my_s_v2[line]/(v*v);
	      if(fabs(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 full Debye-Scherrer cone is within d_phi, don't focus */
		  if (arg < -1 || arg > 1) d_phi = 0;
		  /* Otherwise, determine alpha to rotate from scattering plane
		     into d_phi focusing area*/
		  else alpha = 2*asin(arg);
		}
	      if (d_phi) {
		/* Focusing */
		alpha = fabs(alpha);
		/* Trick to get scattering for pos/neg theta's */
		alpha0= 2*rand01()*alpha;
		if (alpha0 > alpha) {
		  alpha0=PI+(alpha0-1.5*alpha);
		} else {
		  alpha0=alpha0-0.5*alpha;
		}
	      }
	      else
		alpha0 = PI*randpm1();
	      
	      /* now find a nearly vertical rotation axis:
	       * Either
	       *  (v along Z) x (X axis) -> nearly Y axis
	       * Or
	       *  (v along X) x (Z axis) -> nearly Y axis
	       */
	      if (fabs(scalar_prod(1,0,0,vx/v,vy/v,vz/v)) < fabs(scalar_prod(0,0,1,vx/v,vy/v,vz/v))) {
		nx = 1; ny = 0; nz = 0;
	      } else {
		nx = 0; ny = 0; nz = 1;
	      }
	      vec_prod(tmp_vx,tmp_vy,tmp_vz, vx,vy,vz, nx,ny,nz);
	      
	      /* 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 alpha0 around 'v' (Debye-Scherrer cone) */
	      rotate(tmp_vx,tmp_vy,tmp_vz, vout_x,vout_y,vout_z, alpha0, vx, vy, vz);
	      vx = tmp_vx;
	      vy = tmp_vy;
	      vz = tmp_vz;
	      
	      /* Since now scattered and new direction given, calculate path to exit */
	      if (isrect) {
		intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
		intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
	      } else {
		intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
		intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
	      }
	      
	      if (!intersect) {
		/* Strange error: did not hit cylinder */
		fprintf(stderr, "PowderN: FATAL ERROR: Did not hit sample from inside.\n");
		ABSORB;
	      }
	      
	      if (!intersecti) {
		t1 = (t3 + t0) /2;
		t2 = t1;
	      }
	      
	      if (concentric && intersecti) {
		/* In case of concentricity, 'remove' backward wall of sample */
		t2 = t1;
		t3 = t1;
	      }
	      
	      if(t0 < 0) t0=0; /* already in sample */
	      if(t1 < 0) t1=0; /* already in inner hollow */
	      if(t2 < 0) t2=0; /* already past inner hollow */
	      

	      l_1 = v*(t3 - t2 + t1 - t0); /* Length to exit */
	      
	      pmul  = Nq*l_full*my_s_n*exp(-(my_a_v/v+my_s)*(l+l_1))/(1-(frac+tfrac));
	      /* Correction in case of d_phi focusing - BUT only when d_phi != 0 */
	      if (d_phi) pmul *= alpha/PI;
	    } /* else transmit <-- No powder lines in file */
	  }  /* Coherent scattering event */
	else if (neutrontype == 2)
	  {  /* Make incoherent scattering event */
	    if(d_phi) {
	      randvec_target_rect_angular(&vx, &vy, &vz, &solid_angle,
					  0, 0, 1,
					  2*PI, d_phi*DEG2RAD, ROT_A_CURRENT_COMP);
	    } else {
	      randvec_target_circle(&vx, &vy, &vz,
				    &solid_angle, 0, 0, 1, 0);
	    }
	    v1 = sqrt(vx*vx+vy*vy+vz*vz);
	    vx *= v/v1;
	    vy *= v/v1;
	    vz *= v/v1;
	    
	    /* Since now scattered and new direction given, calculate path to exit */
	    if (isrect) {
	      intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
	      intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
	    } else {
	      intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
	      intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
	    }
	    
	    if (!intersect) {
	      /* Strange error: did not hit cylinder */
	      fprintf(stderr, "PowderN: FATAL ERROR: Did not hit sample from inside.\n");
	      ABSORB;
	    }  
	      
	    if (!intersecti) {
	      t1 = (t3 + t0) /2;
	      t2 = t1;
	    }
	      
	    if (concentric && intersecti) {
	      /* In case of concentricity, 'remove' backward wall of sample */
	      t2 = t1;
	      t3 = t1;
	    }
	      
	    if(t0 < 0) t0=0; /* already in sample */
	    if(t1 < 0) t1=0; /* already in inner hollow */
	    if(t2 < 0) t2=0; /* already past inner hollow */
	      

	    l_1 = v*(t3 - t2 + t1 - t0); /* Length to exit */
	    
	    pmul = l_full*my_inc*exp(-(my_a_v/v+my_s)*(l+l_1))/(frac);
	    pmul *= solid_angle/(4*PI);
	    
	  }  /* Incoherent scattering event */
	else if (neutrontype == 1) {
	  /* Make transmitted (absorption-corrected) event */
	  /* No coodinate changes here, simply change neutron weight */
	  pmul = exp(-(my_a_v/v+my_s)*(l))/(tfrac);
        }
	p *= pmul;
      } /* Neutron leaving since it has passed already */
    } /* else transmit non interacting neutrons */
  
}
#line 19496 "D1A.c"
/* 'Container_out' component extend code */
    SIG_MESSAGE("Container_out (Trace:Extend)");
#line 197 "D1A.instr"
  if (SCATTERED) flag_container=1;
#line 19501 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#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 Environment_out [14] */
  mccoordschange(mcposrEnvironment_out, mcrotrEnvironment_out,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrEnvironment_out, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Environment_out (without coords transformations) */
  mcJumpTrace_Environment_out:
  SIG_MESSAGE("Environment_out (Trace)");
  mcDEBUG_COMP("Environment_out")
  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(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  Environment_out
#define mccompcurtype  PowderN
#define mccompcurindex 14
#define reflections mccEnvironment_out_reflections
#define format mccEnvironment_out_format
#define line_info mccEnvironment_out_line_info
#define Nq mccEnvironment_out_Nq
#define my_s_v2 mccEnvironment_out_my_s_v2
#define my_s_v2_sum mccEnvironment_out_my_s_v2_sum
#define my_a_v mccEnvironment_out_my_a_v
#define my_inc mccEnvironment_out_my_inc
#define q_v mccEnvironment_out_q_v
#define w_v mccEnvironment_out_w_v
#define isrect mccEnvironment_out_isrect
#define columns mccEnvironment_out_columns
{   /* Declarations of SETTING parameters. */
MCNUM d_phi = mccEnvironment_out_d_phi;
MCNUM radius = mccEnvironment_out_radius;
MCNUM radius_i = mccEnvironment_out_radius_i;
MCNUM yheight = mccEnvironment_out_yheight;
MCNUM pack = mccEnvironment_out_pack;
MCNUM Vc = mccEnvironment_out_Vc;
MCNUM sigma_abs = mccEnvironment_out_sigma_abs;
MCNUM sigma_inc = mccEnvironment_out_sigma_inc;
MCNUM Delta_d = mccEnvironment_out_Delta_d;
MCNUM frac = mccEnvironment_out_frac;
MCNUM tfrac = mccEnvironment_out_tfrac;
MCNUM xwidth = mccEnvironment_out_xwidth;
MCNUM zthick = mccEnvironment_out_zthick;
MCNUM xwidth_i = mccEnvironment_out_xwidth_i;
MCNUM yheight_i = mccEnvironment_out_yheight_i;
MCNUM zthick_i = mccEnvironment_out_zthick_i;
MCNUM h = mccEnvironment_out_h;
MCNUM DW = mccEnvironment_out_DW;
MCNUM nb_atoms = mccEnvironment_out_nb_atoms;
MCNUM concentric = mccEnvironment_out_concentric;
MCNUM density = mccEnvironment_out_density;
MCNUM weight = mccEnvironment_out_weight;
MCNUM barns = mccEnvironment_out_barns;
#line 496 "/usr/local/lib/mcstas/samples/PowderN.comp"
{
  double t0, t1, t2, t3, v, v1,l_full, l, l_1, dt, alpha0, alpha, theta, my_s, my_s_n;
  double solid_angle, neutrontype;
  double arg, tmp_vx, tmp_vy, tmp_vz, vout_x, vout_y, vout_z, nx, ny, nz, pmul=1;
  int    line;
  char   intersect=0;
  char   intersecti=0;

  if (isrect) {
    intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
    intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
  } else {
    intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
    intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
  }
  
  if(intersect && t3 >0)
    {
      
      if (concentric) {
	/* Set up for concentric case */
	/* 'Remove' the backside of this comp */
	if (!intersecti) {
	  t1 = (t3 + t0) /2;
	}
	t2 = t1;
	t3 = t1;
	dt = -1.0*rand01(); /* In case of scattering we will scatter on 'forward' part of sample */
      } else {
	if (!intersecti) {
	  t1 = (t3 + t0) /2;
	  t2 = t1;
	}
	dt = randpm1(); /* Possibility to scatter at all points in line of sight */
      }
      
      /* Neutron enters at t=t0. */
      if(t0 < 0) t0=0; /* already in sample */
      if(t1 < 0) t1=0; /* already in inner hollow */
      if(t2 < 0) t2=0; /* already past inner hollow */
      v = sqrt(vx*vx + vy*vy + vz*vz);
      l_full = v * (t3 - t2 + t1 - t0);

      /* Calculate total scattering cross section at relevant velocity */
      my_s_v2_sum=0;
      for(line=0; line<Nq; line++) {
	if (q_v[line] <= 2*v) {
	  my_s_v2_sum+=my_s_v2[line];
	}
      }
      
      if (t3 < 0) {
	t3=0; /* Already past sample?! */
	printf("PowderN %s Warning: Neutron has already passed us? (Skipped)\n", NAME_CURRENT_COMP);
      } else {
	if (dt<0) { /* Calculate scattering point position */
	  dt = fabs(dt)*(t1 - t0); /* 'Forward' part */
	} else {
	  dt = dt * (t3 - t2) + (t2-t0) ; /* Possibly also 'backside' part */
	}
	
	my_s = my_s_v2_sum/(v*v)+my_inc;
	/* Total attenuation from scattering */
	
	neutrontype = rand01();
	/* How to handle this one? Transmit (1) / Incoherent (2) / Coherent (3) ? */
	if (neutrontype < tfrac) {
	  neutrontype = 1; 
	  l = l_full; /* Passing through, full length */
	  PROP_DT(t3); 
	} else if (neutrontype >= tfrac && neutrontype < (tfrac + frac)) {
	  neutrontype = 2;
	  l = v*dt;       /* Penetration in sample */
	  PROP_DT(dt+t0); /* Point of scattering */
	  SCATTER;
	} else if (neutrontype >= tfrac + frac) {
	  neutrontype = 3;
	  l = v*dt;       /* Penetration in sample */
	  PROP_DT(dt+t0); /* Point of scattering */
	  SCATTER;
	} else {
	  exit(fprintf(stderr,"PowderN %s: DEAD - this shouldn't happen!\n", NAME_CURRENT_COMP));
	}
	
	if (neutrontype == 3)
	  { /* Make coherent scattering event */
	    
	    if (line_info.count > 0) {
	      /* choose line */
	      if (Nq > 1) line=floor(Nq*rand01());  /* Select between Nq powder lines */
	      else line = 0;
	      if (w_v[line])
		arg = q_v[line]*(1+w_v[line]*randnorm())/(2.0*v);
	      else
		arg = q_v[line]/(2.0*v);
	      my_s_n = my_s_v2[line]/(v*v);
	      if(fabs(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 full Debye-Scherrer cone is within d_phi, don't focus */
		  if (arg < -1 || arg > 1) d_phi = 0;
		  /* Otherwise, determine alpha to rotate from scattering plane
		     into d_phi focusing area*/
		  else alpha = 2*asin(arg);
		}
	      if (d_phi) {
		/* Focusing */
		alpha = fabs(alpha);
		/* Trick to get scattering for pos/neg theta's */
		alpha0= 2*rand01()*alpha;
		if (alpha0 > alpha) {
		  alpha0=PI+(alpha0-1.5*alpha);
		} else {
		  alpha0=alpha0-0.5*alpha;
		}
	      }
	      else
		alpha0 = PI*randpm1();
	      
	      /* now find a nearly vertical rotation axis:
	       * Either
	       *  (v along Z) x (X axis) -> nearly Y axis
	       * Or
	       *  (v along X) x (Z axis) -> nearly Y axis
	       */
	      if (fabs(scalar_prod(1,0,0,vx/v,vy/v,vz/v)) < fabs(scalar_prod(0,0,1,vx/v,vy/v,vz/v))) {
		nx = 1; ny = 0; nz = 0;
	      } else {
		nx = 0; ny = 0; nz = 1;
	      }
	      vec_prod(tmp_vx,tmp_vy,tmp_vz, vx,vy,vz, nx,ny,nz);
	      
	      /* 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 alpha0 around 'v' (Debye-Scherrer cone) */
	      rotate(tmp_vx,tmp_vy,tmp_vz, vout_x,vout_y,vout_z, alpha0, vx, vy, vz);
	      vx = tmp_vx;
	      vy = tmp_vy;
	      vz = tmp_vz;
	      
	      /* Since now scattered and new direction given, calculate path to exit */
	      if (isrect) {
		intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
		intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
	      } else {
		intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
		intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
	      }
	      
	      if (!intersect) {
		/* Strange error: did not hit cylinder */
		fprintf(stderr, "PowderN: FATAL ERROR: Did not hit sample from inside.\n");
		ABSORB;
	      }
	      
	      if (!intersecti) {
		t1 = (t3 + t0) /2;
		t2 = t1;
	      }
	      
	      if (concentric && intersecti) {
		/* In case of concentricity, 'remove' backward wall of sample */
		t2 = t1;
		t3 = t1;
	      }
	      
	      if(t0 < 0) t0=0; /* already in sample */
	      if(t1 < 0) t1=0; /* already in inner hollow */
	      if(t2 < 0) t2=0; /* already past inner hollow */
	      

	      l_1 = v*(t3 - t2 + t1 - t0); /* Length to exit */
	      
	      pmul  = Nq*l_full*my_s_n*exp(-(my_a_v/v+my_s)*(l+l_1))/(1-(frac+tfrac));
	      /* Correction in case of d_phi focusing - BUT only when d_phi != 0 */
	      if (d_phi) pmul *= alpha/PI;
	    } /* else transmit <-- No powder lines in file */
	  }  /* Coherent scattering event */
	else if (neutrontype == 2)
	  {  /* Make incoherent scattering event */
	    if(d_phi) {
	      randvec_target_rect_angular(&vx, &vy, &vz, &solid_angle,
					  0, 0, 1,
					  2*PI, d_phi*DEG2RAD, ROT_A_CURRENT_COMP);
	    } else {
	      randvec_target_circle(&vx, &vy, &vz,
				    &solid_angle, 0, 0, 1, 0);
	    }
	    v1 = sqrt(vx*vx+vy*vy+vz*vz);
	    vx *= v/v1;
	    vy *= v/v1;
	    vz *= v/v1;
	    
	    /* Since now scattered and new direction given, calculate path to exit */
	    if (isrect) {
	      intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zthick);
	      intersecti = box_intersect(&t1, &t2, x, y, z, vx, vy, vz, xwidth_i, yheight_i, zthick_i);
	    } else {
	      intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);
	      intersecti = cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius_i, yheight_i);
	    }
	    
	    if (!intersect) {
	      /* Strange error: did not hit cylinder */
	      fprintf(stderr, "PowderN: FATAL ERROR: Did not hit sample from inside.\n");
	      ABSORB;
	    }  
	      
	    if (!intersecti) {
	      t1 = (t3 + t0) /2;
	      t2 = t1;
	    }
	      
	    if (concentric && intersecti) {
	      /* In case of concentricity, 'remove' backward wall of sample */
	      t2 = t1;
	      t3 = t1;
	    }
	      
	    if(t0 < 0) t0=0; /* already in sample */
	    if(t1 < 0) t1=0; /* already in inner hollow */
	    if(t2 < 0) t2=0; /* already past inner hollow */
	      

	    l_1 = v*(t3 - t2 + t1 - t0); /* Length to exit */
	    
	    pmul = l_full*my_inc*exp(-(my_a_v/v+my_s)*(l+l_1))/(frac);
	    pmul *= solid_angle/(4*PI);
	    
	  }  /* Incoherent scattering event */
	else if (neutrontype == 1) {
	  /* Make transmitted (absorption-corrected) event */
	  /* No coodinate changes here, simply change neutron weight */
	  pmul = exp(-(my_a_v/v+my_s)*(l))/(tfrac);
        }
	p *= pmul;
      } /* Neutron leaving since it has passed already */
    } /* else transmit non interacting neutrons */
  
}
#line 19842 "D1A.c"
/* 'Environment_out' component extend code */
    SIG_MESSAGE("Environment_out (Trace:Extend)");
#line 203 "D1A.instr"
  if (SCATTERED) flag_env=1;
#line 19847 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#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 Collimator [15] */
  mccoordschange(mcposrCollimator, mcrotrCollimator,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrCollimator, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component Collimator (without coords transformations) */
  mcJumpTrace_Collimator:
  SIG_MESSAGE("Collimator (Trace)");
  mcDEBUG_COMP("Collimator")
  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(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  Collimator
#define mccompcurtype  Collimator_radial
#define mccompcurindex 15
#define soller_theta1 mccCollimator_soller_theta1
#define soller_theta2 mccCollimator_soller_theta2
#define window_theta mccCollimator_window_theta
#define use_approx mccCollimator_use_approx
#define ideal mccCollimator_ideal
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccCollimator_w1;
MCNUM h1 = mccCollimator_h1;
MCNUM w2 = mccCollimator_w2;
MCNUM h2 = mccCollimator_h2;
MCNUM len = mccCollimator_len;
MCNUM divergence = mccCollimator_divergence;
MCNUM transmission = mccCollimator_transmission;
MCNUM theta_min = mccCollimator_theta_min;
MCNUM theta_max = mccCollimator_theta_max;
MCNUM nchan = mccCollimator_nchan;
MCNUM radius = mccCollimator_radius;
MCNUM nblades = mccCollimator_nblades;
MCNUM roc = mccCollimator_roc;
MCNUM verbose = mccCollimator_verbose;
#line 140 "/usr/local/lib/mcstas/optics/Collimator_radial.comp"
{
  double phi, t0, t1, t2, t3;
  int    intersect;
  long   input_chan,  output_chan;
  long   input_blade, output_blade;
  double input_theta, output_theta;
  double input_center,output_center;
  char   ok=0;
  double roc_theta=0;

  /* first compute intersection time with input cylinder */
  intersect=cylinder_intersect(&t0,&t3,x,y,z,vx,vy,vz,radius,h1);
  if (!intersect) ABSORB;
  else if (t3 > t0) t0 = t3;

  intersect=cylinder_intersect(&t1,&t2,x,y,z,vx,vy,vz,radius+len,h2);
  if (!intersect) ABSORB;
  else if (t2 > t1) t1 = t2;

  /* get index of input Soller */
  if (t0 > 0 && t1 > t0) {
    PROP_DT(t0);
    if (!ideal) {
      if (roc) roc_theta = roc*randpm1()*soller_theta1/2;

      input_theta = atan2(x, z) + roc_theta;
    /* channel number (start at 0) */
      input_chan  = floor((input_theta - theta_min)/window_theta);
      if (input_chan >= 0 && input_chan < nchan && fabs(y) <= h1/2) ok=1;
    } else if (fabs(y) < h1/2) ok = 1;

    if (ok) {
      if (ideal)
        input_center=atan2(x,z);
      else {
        input_center= theta_min + input_chan*window_theta
                  + (window_theta)/2;
        /* are we outside the soller ? */
        phi = input_theta - input_center;

        if (fabs(phi) > soller_theta1/2) ABSORB; /* outside input soller */
      /* get blade number in soller */
        input_blade = floor(phi/soller_theta1*nblades);
      }
      SCATTER;

      /* propagate to output radius */
      PROP_DT(t1-t0);
      SCATTER;
      if (!ideal) {
        output_theta = atan2(x, z) + roc_theta;
        /* channel number (start at 0) */
        output_chan  = floor((output_theta - theta_min)/window_theta);
        /* did we change channel ? */
        if (output_chan != input_chan) ABSORB; /* changed soller */
        output_center= theta_min + output_chan*window_theta
                    + (window_theta)/2;
        /* are we outside the soller */
        phi = output_theta -output_center;
        if (fabs(phi) > soller_theta2/2 || fabs(y) > h2/2) ABSORB; /* outside output soller */
        /* get blade number in soller */
        output_blade = floor(phi/soller_theta2*nblades);
      } else if (fabs(y) > h2/2) ABSORB;

      /* now handle blades or triangular approximation */
      if (divergence) {
        if (use_approx)
        {
          phi = fabs(atan2(vx,vz) - input_center); /* deviation from center */
          if (phi > divergence)
            ABSORB; /* get outside transmission */
          else
            p *= transmission*(1.0 - phi/divergence);
          SCATTER;
        } else {
          if (input_blade != output_blade) ABSORB; /* blade number has changed */
          p *= transmission;
          SCATTER;
        }
      }
    } /* else we pass aside radial collimator */
  } /* else did not encounter collimator */

}
#line 20010 "D1A.c"
/* 'Collimator' component extend code */
    SIG_MESSAGE("Collimator (Trace:Extend)");
#line 213 "D1A.instr"
  if (!flag_sample && !flag_container) ABSORB;
#line 20015 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef ideal
#undef use_approx
#undef window_theta
#undef soller_theta2
#undef soller_theta1
#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 BananaTheta [16] */
  mccoordschange(mcposrBananaTheta, mcrotrBananaTheta,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrBananaTheta, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component BananaTheta (without coords transformations) */
  mcJumpTrace_BananaTheta:
  SIG_MESSAGE("BananaTheta (Trace)");
  mcDEBUG_COMP("BananaTheta")
  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(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  BananaTheta
#define mccompcurtype  Monitor_nD
#define mccompcurindex 16
#define options mccBananaTheta_options
#define filename mccBananaTheta_filename
#define user1 mccBananaTheta_user1
#define user2 mccBananaTheta_user2
#define user3 mccBananaTheta_user3
#define username1 mccBananaTheta_username1
#define username2 mccBananaTheta_username2
#define username3 mccBananaTheta_username3
#define DEFS mccBananaTheta_DEFS
#define Vars mccBananaTheta_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccBananaTheta_xwidth;
MCNUM yheight = mccBananaTheta_yheight;
MCNUM zthick = mccBananaTheta_zthick;
MCNUM xmin = mccBananaTheta_xmin;
MCNUM xmax = mccBananaTheta_xmax;
MCNUM ymin = mccBananaTheta_ymin;
MCNUM ymax = mccBananaTheta_ymax;
MCNUM zmin = mccBananaTheta_zmin;
MCNUM zmax = mccBananaTheta_zmax;
MCNUM bins = mccBananaTheta_bins;
MCNUM min = mccBananaTheta_min;
MCNUM max = mccBananaTheta_max;
MCNUM restore_neutron = mccBananaTheta_restore_neutron;
#line 260 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  double  XY=0;
  double  t0 = 0;
  double  t1 = 0;
  double  pp;
  int     intersect   = 0;
  char    Flag_Restore = 0;

  if (user1 != FLT_MAX) Vars.UserVariable1 = user1;
  if (user2 != FLT_MAX) Vars.UserVariable2 = user2;
  if (user3 != FLT_MAX) Vars.UserVariable3 = user3;

  /* this is done automatically
    STORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
  */

  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SQUARE) /* square xy */
  {
    PROP_Z0;
    intersect = (x>=Vars.mxmin && x<=Vars.mxmax && y>=Vars.mymin && y<=Vars.mymax);
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_DISK)   /* disk xy */
  {
    PROP_Z0;
    intersect = ((x*x + y*y) <= Vars.Sphere_Radius*Vars.Sphere_Radius);
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) /* sphere */
  {
    intersect = sphere_intersect(&t0, &t1, x, y, z, vx, vy, vz, Vars.Sphere_Radius);
  /*      intersect = (intersect && t0 > 0); */
  }
  else if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BANANA)) /* cylinder */
  {
    intersect = cylinder_intersect(&t0, &t1, x, y, z, vx, vy, vz, Vars.Sphere_Radius, Vars.Cylinder_Height);
    if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_BANANA) && (intersect != 1)) intersect = 0; /* remove top/bottom for banana */
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_BOX) /* box */
  {
    intersect = box_intersect(&t0, &t1, x, y, z, vx, vy, vz, fabs(Vars.mxmax-Vars.mxmin), fabs(Vars.mymax-Vars.mymin), fabs(Vars.mzmax-Vars.mzmin));
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_PREVIOUS) /* previous comp */
  { intersect = 1; }

  if (intersect)
  {
    if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BOX) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BANANA))
    {
      if (t0 < 0 && t1 > 0)
        t0 = t;  /* neutron was already inside ! */
      if (t1 < 0 && t0 > 0) /* neutron exit before entering !! */
        t1 = t;
      /* t0 is now time of incoming intersection with the sphere. */
      if ((Vars.Flag_Shape < 0) && (t1 > 0))
        PROP_DT(t1); /* t1 outgoing beam */
      else
        PROP_DT(t0); /* t0 incoming beam */
    }

    /* Now get the data to monitor: current or keep from PreMonitor */
    if (Vars.Flag_UsePreMonitor != 1)
    {
      Vars.cp = p;
      Vars.cx = x;
      Vars.cvx = vx;
      Vars.csx = sx;
      Vars.cy = y;
      Vars.cvy = vy;
      Vars.csy = sy;
      Vars.cz = z;
      Vars.cvz = vz;
      Vars.csz = sz;
      Vars.ct = t;
    }

    if ((Vars.He3_pressure > 0) && (t1 != t0) && ((abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BOX)))
    {
      XY = exp(-7.417*Vars.He3_pressure*fabs(t1-t0)*2*PI*K2V);
      /* will monitor the absorbed part */
      Vars.cp *= 1-XY;
      /* and modify the neutron weight after monitor, only remains 1-p_detect */
      p *= XY;
    }

    if (Vars.Flag_capture)
    {
      XY = sqrt(Vars.cvx*Vars.cvx+Vars.cvy*Vars.cvy+Vars.cvz*Vars.cvz);
      XY *= V2K;
      if (XY != 0) XY = 2*PI/XY; /* lambda. lambda(2200 m/2) = 1.7985 Angs  */
      Vars.cp *= XY/1.7985;
    }

    pp = Monitor_nD_Trace(&DEFS, &Vars);
    if (pp==0.0)
    { ABSORB;
    }
    else
    { Vars.Nsum++;
      Vars.psum += pp;
      Vars.p2sum += pp*pp;
      SCATTER;
    }

    /* now handles intermediate results saving */
    if ((Vars.Intermediate > 0) && (mcget_run_num() > Vars.IntermediateCnts))
    {
      Vars.IntermediateCnts += Vars.Intermediate*mcget_ncount();
      /* save results for all monitors in the simulation */
      mcsave(NULL);
    }
    if (Vars.Flag_parallel) /* back to neutron state before detection */
      Flag_Restore = 1;
  } /* end if intersection */
  else {
    if (Vars.Flag_Absorb && !Vars.Flag_parallel) ABSORB;
    else Flag_Restore = 1;  /* no intersection, back to previous state */
  }

  if (Flag_Restore)
  {
    RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
  }
}
#line 20216 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#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 BananaPSD [17] */
  mccoordschange(mcposrBananaPSD, mcrotrBananaPSD,
    &mcnlx, &mcnly, &mcnlz,
    &mcnlvx, &mcnlvy, &mcnlvz,
    &mcnlt, &mcnlsx, &mcnlsy);
  mccoordschange_polarisation(mcrotrBananaPSD, &mcnlsx, &mcnlsy, &mcnlsz);
  /* define label inside component BananaPSD (without coords transformations) */
  mcJumpTrace_BananaPSD:
  SIG_MESSAGE("BananaPSD (Trace)");
  mcDEBUG_COMP("BananaPSD")
  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  BananaPSD
#define mccompcurtype  Monitor_nD
#define mccompcurindex 17
#define options mccBananaPSD_options
#define filename mccBananaPSD_filename
#define user1 mccBananaPSD_user1
#define user2 mccBananaPSD_user2
#define user3 mccBananaPSD_user3
#define username1 mccBananaPSD_username1
#define username2 mccBananaPSD_username2
#define username3 mccBananaPSD_username3
#define DEFS mccBananaPSD_DEFS
#define Vars mccBananaPSD_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccBananaPSD_xwidth;
MCNUM yheight = mccBananaPSD_yheight;
MCNUM zthick = mccBananaPSD_zthick;
MCNUM xmin = mccBananaPSD_xmin;
MCNUM xmax = mccBananaPSD_xmax;
MCNUM ymin = mccBananaPSD_ymin;
MCNUM ymax = mccBananaPSD_ymax;
MCNUM zmin = mccBananaPSD_zmin;
MCNUM zmax = mccBananaPSD_zmax;
MCNUM bins = mccBananaPSD_bins;
MCNUM min = mccBananaPSD_min;
MCNUM max = mccBananaPSD_max;
MCNUM restore_neutron = mccBananaPSD_restore_neutron;
#line 260 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  double  XY=0;
  double  t0 = 0;
  double  t1 = 0;
  double  pp;
  int     intersect   = 0;
  char    Flag_Restore = 0;

  if (user1 != FLT_MAX) Vars.UserVariable1 = user1;
  if (user2 != FLT_MAX) Vars.UserVariable2 = user2;
  if (user3 != FLT_MAX) Vars.UserVariable3 = user3;

  /* this is done automatically
    STORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
  */

  if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SQUARE) /* square xy */
  {
    PROP_Z0;
    intersect = (x>=Vars.mxmin && x<=Vars.mxmax && y>=Vars.mymin && y<=Vars.mymax);
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_DISK)   /* disk xy */
  {
    PROP_Z0;
    intersect = ((x*x + y*y) <= Vars.Sphere_Radius*Vars.Sphere_Radius);
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) /* sphere */
  {
    intersect = sphere_intersect(&t0, &t1, x, y, z, vx, vy, vz, Vars.Sphere_Radius);
  /*      intersect = (intersect && t0 > 0); */
  }
  else if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BANANA)) /* cylinder */
  {
    intersect = cylinder_intersect(&t0, &t1, x, y, z, vx, vy, vz, Vars.Sphere_Radius, Vars.Cylinder_Height);
    if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_BANANA) && (intersect != 1)) intersect = 0; /* remove top/bottom for banana */
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_BOX) /* box */
  {
    intersect = box_intersect(&t0, &t1, x, y, z, vx, vy, vz, fabs(Vars.mxmax-Vars.mxmin), fabs(Vars.mymax-Vars.mymin), fabs(Vars.mzmax-Vars.mzmin));
  }
  else if (abs(Vars.Flag_Shape) == DEFS.SHAPE_PREVIOUS) /* previous comp */
  { intersect = 1; }

  if (intersect)
  {
    if ((abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BOX) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BANANA))
    {
      if (t0 < 0 && t1 > 0)
        t0 = t;  /* neutron was already inside ! */
      if (t1 < 0 && t0 > 0) /* neutron exit before entering !! */
        t1 = t;
      /* t0 is now time of incoming intersection with the sphere. */
      if ((Vars.Flag_Shape < 0) && (t1 > 0))
        PROP_DT(t1); /* t1 outgoing beam */
      else
        PROP_DT(t0); /* t0 incoming beam */
    }

    /* Now get the data to monitor: current or keep from PreMonitor */
    if (Vars.Flag_UsePreMonitor != 1)
    {
      Vars.cp = p;
      Vars.cx = x;
      Vars.cvx = vx;
      Vars.csx = sx;
      Vars.cy = y;
      Vars.cvy = vy;
      Vars.csy = sy;
      Vars.cz = z;
      Vars.cvz = vz;
      Vars.csz = sz;
      Vars.ct = t;
    }

    if ((Vars.He3_pressure > 0) && (t1 != t0) && ((abs(Vars.Flag_Shape) == DEFS.SHAPE_SPHERE) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_CYLIND) || (abs(Vars.Flag_Shape) == DEFS.SHAPE_BOX)))
    {
      XY = exp(-7.417*Vars.He3_pressure*fabs(t1-t0)*2*PI*K2V);
      /* will monitor the absorbed part */
      Vars.cp *= 1-XY;
      /* and modify the neutron weight after monitor, only remains 1-p_detect */
      p *= XY;
    }

    if (Vars.Flag_capture)
    {
      XY = sqrt(Vars.cvx*Vars.cvx+Vars.cvy*Vars.cvy+Vars.cvz*Vars.cvz);
      XY *= V2K;
      if (XY != 0) XY = 2*PI/XY; /* lambda. lambda(2200 m/2) = 1.7985 Angs  */
      Vars.cp *= XY/1.7985;
    }

    pp = Monitor_nD_Trace(&DEFS, &Vars);
    if (pp==0.0)
    { ABSORB;
    }
    else
    { Vars.Nsum++;
      Vars.psum += pp;
      Vars.p2sum += pp*pp;
      SCATTER;
    }

    /* now handles intermediate results saving */
    if ((Vars.Intermediate > 0) && (mcget_run_num() > Vars.IntermediateCnts))
    {
      Vars.IntermediateCnts += Vars.Intermediate*mcget_ncount();
      /* save results for all monitors in the simulation */
      mcsave(NULL);
    }
    if (Vars.Flag_parallel) /* back to neutron state before detection */
      Flag_Restore = 1;
  } /* end if intersection */
  else {
    if (Vars.Flag_Absorb && !Vars.Flag_parallel) ABSORB;
    else Flag_Restore = 1;  /* no intersection, back to previous state */
  }

  if (Flag_Restore)
  {
    RESTORE_NEUTRON(INDEX_CURRENT_COMP, x, y, z, vx, vy, vz, t, sx, sy, sz, p);
  }
}
#line 20425 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#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:
  /* SPLIT loops in reverse order */
  if (mcSplit_SamplePos && mcSplit_SamplePos < (10)) {
    goto mcJumpTrace_SamplePos;
  }
    else mcSplit_SamplePos=0;
  if (mcSplit_Monok && mcSplit_Monok < (10)) {
    goto mcJumpTrace_Monok;
  }
    else mcSplit_Monok=0;

  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) {
    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 20507 "D1A.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 'Lmon'. */
  SIG_MESSAGE("Lmon (Save)");
#define mccompcurname  Lmon
#define mccompcurtype  Monitor_nD
#define mccompcurindex 6
#define options mccLmon_options
#define filename mccLmon_filename
#define user1 mccLmon_user1
#define user2 mccLmon_user2
#define user3 mccLmon_user3
#define username1 mccLmon_username1
#define username2 mccLmon_username2
#define username3 mccLmon_username3
#define DEFS mccLmon_DEFS
#define Vars mccLmon_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccLmon_xwidth;
MCNUM yheight = mccLmon_yheight;
MCNUM zthick = mccLmon_zthick;
MCNUM xmin = mccLmon_xmin;
MCNUM xmax = mccLmon_xmax;
MCNUM ymin = mccLmon_ymin;
MCNUM ymax = mccLmon_ymax;
MCNUM zmin = mccLmon_zmin;
MCNUM zmax = mccLmon_zmax;
MCNUM bins = mccLmon_bins;
MCNUM min = mccLmon_min;
MCNUM max = mccLmon_max;
MCNUM restore_neutron = mccLmon_restore_neutron;
#line 384 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  /* save results, but do not free pointers */
  Monitor_nD_Save(&DEFS, &Vars);
}
#line 20551 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* User SAVE code for component 'PSDsample'. */
  SIG_MESSAGE("PSDsample (Save)");
#define mccompcurname  PSDsample
#define mccompcurtype  Monitor_nD
#define mccompcurindex 7
#define options mccPSDsample_options
#define filename mccPSDsample_filename
#define user1 mccPSDsample_user1
#define user2 mccPSDsample_user2
#define user3 mccPSDsample_user3
#define username1 mccPSDsample_username1
#define username2 mccPSDsample_username2
#define username3 mccPSDsample_username3
#define DEFS mccPSDsample_DEFS
#define Vars mccPSDsample_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccPSDsample_xwidth;
MCNUM yheight = mccPSDsample_yheight;
MCNUM zthick = mccPSDsample_zthick;
MCNUM xmin = mccPSDsample_xmin;
MCNUM xmax = mccPSDsample_xmax;
MCNUM ymin = mccPSDsample_ymin;
MCNUM ymax = mccPSDsample_ymax;
MCNUM zmin = mccPSDsample_zmin;
MCNUM zmax = mccPSDsample_zmax;
MCNUM bins = mccPSDsample_bins;
MCNUM min = mccPSDsample_min;
MCNUM max = mccPSDsample_max;
MCNUM restore_neutron = mccPSDsample_restore_neutron;
#line 384 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  /* save results, but do not free pointers */
  Monitor_nD_Save(&DEFS, &Vars);
}
#line 20601 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* User SAVE code for component 'Sample_liq'. */
  SIG_MESSAGE("Sample_liq (Save)");
#define mccompcurname  Sample_liq
#define mccompcurtype  Isotropic_Sqw
#define mccompcurindex 11
#define Sqw_coh mccSample_liq_Sqw_coh
#define Sqw_inc mccSample_liq_Sqw_inc
#define powder_format mccSample_liq_powder_format
#define geometry mccSample_liq_geometry
#define VarSqw mccSample_liq_VarSqw
#define columns mccSample_liq_columns
#define offdata mccSample_liq_offdata
{   /* Declarations of SETTING parameters. */
MCNUM radius = mccSample_liq_radius;
MCNUM thickness = mccSample_liq_thickness;
MCNUM xwidth = mccSample_liq_xwidth;
MCNUM yheight = mccSample_liq_yheight;
MCNUM zdepth = mccSample_liq_zdepth;
MCNUM qmin = mccSample_liq_qmin;
MCNUM qmax = mccSample_liq_qmax;
MCNUM wmin = mccSample_liq_wmin;
MCNUM wmax = mccSample_liq_wmax;
MCNUM auto_qw = mccSample_liq_auto_qw;
MCNUM threshold = mccSample_liq_threshold;
int order = mccSample_liq_order;
MCNUM T = mccSample_liq_T;
MCNUM verbose = mccSample_liq_verbose;
MCNUM d_phi = mccSample_liq_d_phi;
int concentric = mccSample_liq_concentric;
MCNUM V_rho = mccSample_liq_V_rho;
MCNUM sigma_abs = mccSample_liq_sigma_abs;
MCNUM sigma_coh = mccSample_liq_sigma_coh;
MCNUM sigma_inc = mccSample_liq_sigma_inc;
MCNUM save_sqw = mccSample_liq_save_sqw;
MCNUM powder_Dd = mccSample_liq_powder_Dd;
MCNUM powder_DW = mccSample_liq_powder_DW;
MCNUM powder_Vc = mccSample_liq_powder_Vc;
MCNUM density = mccSample_liq_density;
MCNUM weight = mccSample_liq_weight;
MCNUM p_interact = mccSample_liq_p_interact;
MCNUM auto_norm = mccSample_liq_auto_norm;
MCNUM powder_barns = mccSample_liq_powder_barns;
#line 1944 "/usr/local/lib/mcstas/samples/Isotropic_Sqw.comp"
{
  int  k;

  if (VarSqw.s_coh > 0 || VarSqw.s_inc > 0)
  for (k=0; k < 2; k++) {
    struct Sqw_Data_struct Data_sqw;
    char tmp_str[1024];
    char type_ci[64];
    char ext[20];
    char filename[256];
    char xvar[64];

    strcpy(type_ci, (k == 0 ? "coherent" : "incoherent"));
    strcpy(ext, (k == 0 ? "coh" : "inc"));
    Data_sqw =  (k == 0 ? VarSqw.Data_coh : VarSqw.Data_inc);

    if (save_sqw && Data_sqw.intensity) {
      double SW[Data_sqw.nb_w];
      double SQW[Data_sqw.nb_q][Data_sqw.nb_w];
      long   i,j;

      MPI_MASTER(
        if (VarSqw.verbose_output >= 1)
          printf("Isotropic_Sqw: %s: Writting %s S(q), SW and S(q,w) files as monitors.\n", NAME_CURRENT_COMP, type_ci);
      )

      for (j=0; j < (Data_sqw.nb_w) ; j++) {
        SW[j] = Data_sqw.SW[j].value;
        for (i=0; i < (Data_sqw.nb_q) ; i++)
          SQW[i][j] = Data_sqw.SQW[j][i].value;
      }
      sprintf(tmp_str, "S(q) from %s (%s)", Data_sqw.filename, type_ci);
      sprintf(filename, "%s_%s.sq", NAME_CURRENT_COMP, ext);
      sprintf(xvar, "S_%s(q)", ext);
      if (Data_sqw.nb_q_data > 1)
        DETECTOR_OUT_1D(tmp_str,"Wavevector [Angs-1]",xvar,"q",
        Data_sqw.q_min, Data_sqw.q_max,
        Data_sqw.nb_q_data,NULL,Data_sqw.Sq,NULL,
        filename);
      sprintf(tmp_str, "Energy Density from %s (%s)", Data_sqw.filename, type_ci);
      sprintf(filename, "%s_%s.sw", NAME_CURRENT_COMP, ext);
      sprintf(xvar, "S_%s(w)", ext);
      if (Data_sqw.nb_w > 1)
        DETECTOR_OUT_1D(tmp_str,"Energy [meV]",xvar,"w",
        Data_sqw.w_min, Data_sqw.w_max,
        Data_sqw.nb_w,NULL,SW,NULL,
        filename);
      sprintf(tmp_str, "S(q,w) from %s (%s), Norm=%g",
        Data_sqw.filename, type_ci, Data_sqw.intensity);
      sprintf(filename, "%s_%s.sqw", NAME_CURRENT_COMP, ext);
      sprintf(xvar, "Wavevector [Angs-1] %s", ext);
      if (Data_sqw.nb_q > 1 && Data_sqw.nb_w > 1)
        DETECTOR_OUT_2D(tmp_str,xvar,"Energy [meV]",
        Data_sqw.q_min, Data_sqw.q_max, Data_sqw.w_min, Data_sqw.w_max,
        Data_sqw.nb_q,Data_sqw.nb_w,NULL,&SQW[0][0],NULL,
        filename);
    }

  } /* end for */

/* end SAVE */
}
#line 20722 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef offdata
#undef columns
#undef VarSqw
#undef geometry
#undef powder_format
#undef Sqw_inc
#undef Sqw_coh
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* User SAVE code for component 'BananaTheta'. */
  SIG_MESSAGE("BananaTheta (Save)");
#define mccompcurname  BananaTheta
#define mccompcurtype  Monitor_nD
#define mccompcurindex 16
#define options mccBananaTheta_options
#define filename mccBananaTheta_filename
#define user1 mccBananaTheta_user1
#define user2 mccBananaTheta_user2
#define user3 mccBananaTheta_user3
#define username1 mccBananaTheta_username1
#define username2 mccBananaTheta_username2
#define username3 mccBananaTheta_username3
#define DEFS mccBananaTheta_DEFS
#define Vars mccBananaTheta_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccBananaTheta_xwidth;
MCNUM yheight = mccBananaTheta_yheight;
MCNUM zthick = mccBananaTheta_zthick;
MCNUM xmin = mccBananaTheta_xmin;
MCNUM xmax = mccBananaTheta_xmax;
MCNUM ymin = mccBananaTheta_ymin;
MCNUM ymax = mccBananaTheta_ymax;
MCNUM zmin = mccBananaTheta_zmin;
MCNUM zmax = mccBananaTheta_zmax;
MCNUM bins = mccBananaTheta_bins;
MCNUM min = mccBananaTheta_min;
MCNUM max = mccBananaTheta_max;
MCNUM restore_neutron = mccBananaTheta_restore_neutron;
#line 384 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  /* save results, but do not free pointers */
  Monitor_nD_Save(&DEFS, &Vars);
}
#line 20769 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* User SAVE code for component 'BananaPSD'. */
  SIG_MESSAGE("BananaPSD (Save)");
#define mccompcurname  BananaPSD
#define mccompcurtype  Monitor_nD
#define mccompcurindex 17
#define options mccBananaPSD_options
#define filename mccBananaPSD_filename
#define user1 mccBananaPSD_user1
#define user2 mccBananaPSD_user2
#define user3 mccBananaPSD_user3
#define username1 mccBananaPSD_username1
#define username2 mccBananaPSD_username2
#define username3 mccBananaPSD_username3
#define DEFS mccBananaPSD_DEFS
#define Vars mccBananaPSD_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccBananaPSD_xwidth;
MCNUM yheight = mccBananaPSD_yheight;
MCNUM zthick = mccBananaPSD_zthick;
MCNUM xmin = mccBananaPSD_xmin;
MCNUM xmax = mccBananaPSD_xmax;
MCNUM ymin = mccBananaPSD_ymin;
MCNUM ymax = mccBananaPSD_ymax;
MCNUM zmin = mccBananaPSD_zmin;
MCNUM zmax = mccBananaPSD_zmax;
MCNUM bins = mccBananaPSD_bins;
MCNUM min = mccBananaPSD_min;
MCNUM max = mccBananaPSD_max;
MCNUM restore_neutron = mccBananaPSD_restore_neutron;
#line 384 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  /* save results, but do not free pointers */
  Monitor_nD_Save(&DEFS, &Vars);
}
#line 20819 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#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 20868 "D1A.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] Source\n");
    if (mcAbsorbProp[2]) fprintf(stderr, "Warning: %g events were removed in Component[2] Source\n""         (negative time, rounding errors).\n", mcAbsorbProp[2]);
    if (!mcNCounter[3]) fprintf(stderr, "Warning: No neutron could reach Component[3] mono_cradle\n");
    if (mcAbsorbProp[3]) fprintf(stderr, "Warning: %g events were removed in Component[3] mono_cradle\n""         (negative time, rounding errors).\n", mcAbsorbProp[3]);
  /* User FINALLY code for component 'Monok'. */
  SIG_MESSAGE("Monok (Finally)");
#define mccompcurname  Monok
#define mccompcurtype  Monochromator_curved
#define mccompcurindex 4
#define reflect mccMonok_reflect
#define transmit mccMonok_transmit
#define mos_rms_y mccMonok_mos_rms_y
#define mos_rms_z mccMonok_mos_rms_z
#define mos_rms_max mccMonok_mos_rms_max
#define mono_Q mccMonok_mono_Q
#define SlabWidth mccMonok_SlabWidth
#define SlabHeight mccMonok_SlabHeight
#define rTable mccMonok_rTable
#define tTable mccMonok_tTable
#define row mccMonok_row
#define col mccMonok_col
{   /* Declarations of SETTING parameters. */
MCNUM zwidth = mccMonok_zwidth;
MCNUM yheight = mccMonok_yheight;
MCNUM gap = mccMonok_gap;
MCNUM NH = mccMonok_NH;
MCNUM NV = mccMonok_NV;
MCNUM mosaich = mccMonok_mosaich;
MCNUM mosaicv = mccMonok_mosaicv;
MCNUM r0 = mccMonok_r0;
MCNUM t0 = mccMonok_t0;
MCNUM Q = mccMonok_Q;
MCNUM RV = mccMonok_RV;
MCNUM RH = mccMonok_RH;
MCNUM DM = mccMonok_DM;
MCNUM mosaic = mccMonok_mosaic;
MCNUM width = mccMonok_width;
MCNUM height = mccMonok_height;
MCNUM verbose = mccMonok_verbose;
#line 426 "/usr/local/lib/mcstas/optics/Monochromator_curved.comp"
{
  Table_Free(&rTable);
  Table_Free(&tTable);
}
#line 20924 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef col
#undef row
#undef tTable
#undef rTable
#undef SlabHeight
#undef SlabWidth
#undef mono_Q
#undef mos_rms_max
#undef mos_rms_z
#undef mos_rms_y
#undef transmit
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

    if (!mcNCounter[4]) fprintf(stderr, "Warning: No neutron could reach Component[4] Monok\n");
    if (mcNCounter[4] < 1000*(10)) fprintf(stderr, 
"Warning: Number of events reaching SPLIT position Component[4] Monok\n"
"         is probably too low. Increase Ncount.\n");

    if (mcAbsorbProp[4]) fprintf(stderr, "Warning: %g events were removed in Component[4] Monok\n""         (negative time, rounding errors).\n", mcAbsorbProp[4]);
    if (!mcNCounter[5]) fprintf(stderr, "Warning: No neutron could reach Component[5] mono_out\n");
    if (mcAbsorbProp[5]) fprintf(stderr, "Warning: %g events were removed in Component[5] mono_out\n""         (negative time, rounding errors).\n", mcAbsorbProp[5]);
  /* User FINALLY code for component 'Lmon'. */
  SIG_MESSAGE("Lmon (Finally)");
#define mccompcurname  Lmon
#define mccompcurtype  Monitor_nD
#define mccompcurindex 6
#define options mccLmon_options
#define filename mccLmon_filename
#define user1 mccLmon_user1
#define user2 mccLmon_user2
#define user3 mccLmon_user3
#define username1 mccLmon_username1
#define username2 mccLmon_username2
#define username3 mccLmon_username3
#define DEFS mccLmon_DEFS
#define Vars mccLmon_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccLmon_xwidth;
MCNUM yheight = mccLmon_yheight;
MCNUM zthick = mccLmon_zthick;
MCNUM xmin = mccLmon_xmin;
MCNUM xmax = mccLmon_xmax;
MCNUM ymin = mccLmon_ymin;
MCNUM ymax = mccLmon_ymax;
MCNUM zmin = mccLmon_zmin;
MCNUM zmax = mccLmon_zmax;
MCNUM bins = mccLmon_bins;
MCNUM min = mccLmon_min;
MCNUM max = mccLmon_max;
MCNUM restore_neutron = mccLmon_restore_neutron;
#line 390 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  /* free pointers */
  Monitor_nD_Finally(&DEFS, &Vars);
}
#line 20981 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

    if (!mcNCounter[6]) fprintf(stderr, "Warning: No neutron could reach Component[6] Lmon\n");
    if (mcAbsorbProp[6]) fprintf(stderr, "Warning: %g events were removed in Component[6] Lmon\n""         (negative time, rounding errors).\n", mcAbsorbProp[6]);
  /* User FINALLY code for component 'PSDsample'. */
  SIG_MESSAGE("PSDsample (Finally)");
#define mccompcurname  PSDsample
#define mccompcurtype  Monitor_nD
#define mccompcurindex 7
#define options mccPSDsample_options
#define filename mccPSDsample_filename
#define user1 mccPSDsample_user1
#define user2 mccPSDsample_user2
#define user3 mccPSDsample_user3
#define username1 mccPSDsample_username1
#define username2 mccPSDsample_username2
#define username3 mccPSDsample_username3
#define DEFS mccPSDsample_DEFS
#define Vars mccPSDsample_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccPSDsample_xwidth;
MCNUM yheight = mccPSDsample_yheight;
MCNUM zthick = mccPSDsample_zthick;
MCNUM xmin = mccPSDsample_xmin;
MCNUM xmax = mccPSDsample_xmax;
MCNUM ymin = mccPSDsample_ymin;
MCNUM ymax = mccPSDsample_ymax;
MCNUM zmin = mccPSDsample_zmin;
MCNUM zmax = mccPSDsample_zmax;
MCNUM bins = mccPSDsample_bins;
MCNUM min = mccPSDsample_min;
MCNUM max = mccPSDsample_max;
MCNUM restore_neutron = mccPSDsample_restore_neutron;
#line 390 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  /* free pointers */
  Monitor_nD_Finally(&DEFS, &Vars);
}
#line 21033 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

    if (!mcNCounter[7]) fprintf(stderr, "Warning: No neutron could reach Component[7] PSDsample\n");
    if (mcAbsorbProp[7]) fprintf(stderr, "Warning: %g events were removed in Component[7] PSDsample\n""         (negative time, rounding errors).\n", mcAbsorbProp[7]);
    if (!mcNCounter[8]) fprintf(stderr, "Warning: No neutron could reach Component[8] SamplePos\n");
    if (mcNCounter[8] < 1000*(10)) fprintf(stderr, 
"Warning: Number of events reaching SPLIT position Component[8] SamplePos\n"
"         is probably too low. Increase Ncount.\n");

    if (mcAbsorbProp[8]) fprintf(stderr, "Warning: %g events were removed in Component[8] SamplePos\n""         (negative time, rounding errors).\n", mcAbsorbProp[8]);
    if (!mcNCounter[9]) fprintf(stderr, "Warning: No neutron could reach Component[9] Environment_in\n");
    if (mcAbsorbProp[9]) fprintf(stderr, "Warning: %g events were removed in Component[9] Environment_in\n""         (negative time, rounding errors).\n", mcAbsorbProp[9]);
    if (!mcNCounter[10]) fprintf(stderr, "Warning: No neutron could reach Component[10] Container_in\n");
    if (mcAbsorbProp[10]) fprintf(stderr, "Warning: %g events were removed in Component[10] Container_in\n""         (negative time, rounding errors).\n", mcAbsorbProp[10]);
  /* User FINALLY code for component 'Sample_liq'. */
  SIG_MESSAGE("Sample_liq (Finally)");
#define mccompcurname  Sample_liq
#define mccompcurtype  Isotropic_Sqw
#define mccompcurindex 11
#define Sqw_coh mccSample_liq_Sqw_coh
#define Sqw_inc mccSample_liq_Sqw_inc
#define powder_format mccSample_liq_powder_format
#define geometry mccSample_liq_geometry
#define VarSqw mccSample_liq_VarSqw
#define columns mccSample_liq_columns
#define offdata mccSample_liq_offdata
{   /* Declarations of SETTING parameters. */
MCNUM radius = mccSample_liq_radius;
MCNUM thickness = mccSample_liq_thickness;
MCNUM xwidth = mccSample_liq_xwidth;
MCNUM yheight = mccSample_liq_yheight;
MCNUM zdepth = mccSample_liq_zdepth;
MCNUM qmin = mccSample_liq_qmin;
MCNUM qmax = mccSample_liq_qmax;
MCNUM wmin = mccSample_liq_wmin;
MCNUM wmax = mccSample_liq_wmax;
MCNUM auto_qw = mccSample_liq_auto_qw;
MCNUM threshold = mccSample_liq_threshold;
int order = mccSample_liq_order;
MCNUM T = mccSample_liq_T;
MCNUM verbose = mccSample_liq_verbose;
MCNUM d_phi = mccSample_liq_d_phi;
int concentric = mccSample_liq_concentric;
MCNUM V_rho = mccSample_liq_V_rho;
MCNUM sigma_abs = mccSample_liq_sigma_abs;
MCNUM sigma_coh = mccSample_liq_sigma_coh;
MCNUM sigma_inc = mccSample_liq_sigma_inc;
MCNUM save_sqw = mccSample_liq_save_sqw;
MCNUM powder_Dd = mccSample_liq_powder_Dd;
MCNUM powder_DW = mccSample_liq_powder_DW;
MCNUM powder_Vc = mccSample_liq_powder_Vc;
MCNUM density = mccSample_liq_density;
MCNUM weight = mccSample_liq_weight;
MCNUM p_interact = mccSample_liq_p_interact;
MCNUM auto_norm = mccSample_liq_auto_norm;
MCNUM powder_barns = mccSample_liq_powder_barns;
#line 2008 "/usr/local/lib/mcstas/samples/Isotropic_Sqw.comp"
{
  int  k;

  if (VarSqw.s_coh > 0 || VarSqw.s_inc > 0)
  for (k=0; k < 2; k++) {
    struct Sqw_Data_struct Data_sqw;
    char type_ci[64];

    strcpy(type_ci, (k == 0 ? "coherent" : "incoherent"));
    Data_sqw =  (k == 0 ? VarSqw.Data_coh : VarSqw.Data_inc);

    Table_Free(&(Data_sqw.Sqw));
    /* test if Sqw data is larger than used [q,w] range */
    if (VarSqw.neutron_removed && Data_sqw.nb_q*Data_sqw.nb_w > 1)
    if ((VarSqw.w_max*2 < Data_sqw.w_max) || (VarSqw.q_max*2 < Data_sqw.q_max))
          printf("Isotropic_Sqw: %s: Data from %s file %s in the range\n"
                 "                  q=[%g:%g] w=[%g:%g]\n"
                 "                  is larger than accessible beam range.\n"
                 "               This may result in neutron events removed.\n"
                 "WARNING        Set qmax=%g, wmax=%g\n"
                 "               to Focus simulation optimally, or set 'auto_qw=1'.\n",
            NAME_CURRENT_COMP, type_ci, Data_sqw.filename,
            Data_sqw.q_min, Data_sqw.q_max, Data_sqw.w_min, Data_sqw.w_max,
            VarSqw.q_max,   VarSqw.w_max);

    if (Data_sqw.SW)           free(Data_sqw.SW);
    if (Data_sqw.SQW)          free(Data_sqw.SQW);
    if (Data_sqw.SW_lookup)    free(Data_sqw.SW_lookup);
    if (Data_sqw.QW_lookup)    free(Data_sqw.QW_lookup);
    if (Data_sqw.Sq)           free(Data_sqw.Sq);
  } /* end for */

  if (VarSqw.neutron_removed)
    printf("Isotropic_Sqw: %s: %li neutron events (out of %li) that should have\n"
           "               scattered were transmitted because scattering conditions\n"
           "WARNING        could not be satisfied after %i tries.\n",
          NAME_CURRENT_COMP, VarSqw.neutron_removed, VarSqw.neutron_exit, VarSqw.maxloop);
  if (VarSqw.neutron_pmult)
    printf("Isotropic_Sqw: %s: %li neutron events (out of %li) reached\n"
           "WARNING        unrealistic weight. The S(q,w) norm might be too high\n",
          NAME_CURRENT_COMP, VarSqw.neutron_pmult, VarSqw.neutron_exit);

  if (VarSqw.verbose_output >= 1 && VarSqw.psum_scatt > 0) {
    printf("Isotropic_Sqw: %s: Scattering fraction=%g of incoming intensity\n"
           "               Absorption fraction           =%g\n",
           NAME_CURRENT_COMP,
           VarSqw.mean_scatt/VarSqw.psum_scatt, VarSqw.mean_abs/VarSqw.psum_scatt);
    printf("               Single   scattering intensity =%g\n"
           "               Multiple scattering intensity =%g\n",
           VarSqw.single, VarSqw.multi);
  }

/* end FINALLY */
}
#line 21155 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef offdata
#undef columns
#undef VarSqw
#undef geometry
#undef powder_format
#undef Sqw_inc
#undef Sqw_coh
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

    if (!mcNCounter[11]) fprintf(stderr, "Warning: No neutron could reach Component[11] Sample_liq\n");
    if (mcAbsorbProp[11]) fprintf(stderr, "Warning: %g events were removed in Component[11] Sample_liq\n""         (negative time, rounding errors).\n", mcAbsorbProp[11]);
    if (!mcNCounter[12]) fprintf(stderr, "Warning: No neutron could reach Component[12] Sample\n");
    if (mcAbsorbProp[12]) fprintf(stderr, "Warning: %g events were removed in Component[12] Sample\n""         (negative time, rounding errors).\n", mcAbsorbProp[12]);
    if (!mcNCounter[13]) fprintf(stderr, "Warning: No neutron could reach Component[13] Container_out\n");
    if (mcAbsorbProp[13]) fprintf(stderr, "Warning: %g events were removed in Component[13] Container_out\n""         (negative time, rounding errors).\n", mcAbsorbProp[13]);
    if (!mcNCounter[14]) fprintf(stderr, "Warning: No neutron could reach Component[14] Environment_out\n");
    if (mcAbsorbProp[14]) fprintf(stderr, "Warning: %g events were removed in Component[14] Environment_out\n""         (negative time, rounding errors).\n", mcAbsorbProp[14]);
    if (!mcNCounter[15]) fprintf(stderr, "Warning: No neutron could reach Component[15] Collimator\n");
    if (mcAbsorbProp[15]) fprintf(stderr, "Warning: %g events were removed in Component[15] Collimator\n""         (negative time, rounding errors).\n", mcAbsorbProp[15]);
  /* User FINALLY code for component 'BananaTheta'. */
  SIG_MESSAGE("BananaTheta (Finally)");
#define mccompcurname  BananaTheta
#define mccompcurtype  Monitor_nD
#define mccompcurindex 16
#define options mccBananaTheta_options
#define filename mccBananaTheta_filename
#define user1 mccBananaTheta_user1
#define user2 mccBananaTheta_user2
#define user3 mccBananaTheta_user3
#define username1 mccBananaTheta_username1
#define username2 mccBananaTheta_username2
#define username3 mccBananaTheta_username3
#define DEFS mccBananaTheta_DEFS
#define Vars mccBananaTheta_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccBananaTheta_xwidth;
MCNUM yheight = mccBananaTheta_yheight;
MCNUM zthick = mccBananaTheta_zthick;
MCNUM xmin = mccBananaTheta_xmin;
MCNUM xmax = mccBananaTheta_xmax;
MCNUM ymin = mccBananaTheta_ymin;
MCNUM ymax = mccBananaTheta_ymax;
MCNUM zmin = mccBananaTheta_zmin;
MCNUM zmax = mccBananaTheta_zmax;
MCNUM bins = mccBananaTheta_bins;
MCNUM min = mccBananaTheta_min;
MCNUM max = mccBananaTheta_max;
MCNUM restore_neutron = mccBananaTheta_restore_neutron;
#line 390 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  /* free pointers */
  Monitor_nD_Finally(&DEFS, &Vars);
}
#line 21212 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

    if (!mcNCounter[16]) fprintf(stderr, "Warning: No neutron could reach Component[16] BananaTheta\n");
    if (mcAbsorbProp[16]) fprintf(stderr, "Warning: %g events were removed in Component[16] BananaTheta\n""         (negative time, rounding errors).\n", mcAbsorbProp[16]);
  /* User FINALLY code for component 'BananaPSD'. */
  SIG_MESSAGE("BananaPSD (Finally)");
#define mccompcurname  BananaPSD
#define mccompcurtype  Monitor_nD
#define mccompcurindex 17
#define options mccBananaPSD_options
#define filename mccBananaPSD_filename
#define user1 mccBananaPSD_user1
#define user2 mccBananaPSD_user2
#define user3 mccBananaPSD_user3
#define username1 mccBananaPSD_username1
#define username2 mccBananaPSD_username2
#define username3 mccBananaPSD_username3
#define DEFS mccBananaPSD_DEFS
#define Vars mccBananaPSD_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccBananaPSD_xwidth;
MCNUM yheight = mccBananaPSD_yheight;
MCNUM zthick = mccBananaPSD_zthick;
MCNUM xmin = mccBananaPSD_xmin;
MCNUM xmax = mccBananaPSD_xmax;
MCNUM ymin = mccBananaPSD_ymin;
MCNUM ymax = mccBananaPSD_ymax;
MCNUM zmin = mccBananaPSD_zmin;
MCNUM zmax = mccBananaPSD_zmax;
MCNUM bins = mccBananaPSD_bins;
MCNUM min = mccBananaPSD_min;
MCNUM max = mccBananaPSD_max;
MCNUM restore_neutron = mccBananaPSD_restore_neutron;
#line 390 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  /* free pointers */
  Monitor_nD_Finally(&DEFS, &Vars);
}
#line 21264 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

    if (!mcNCounter[17]) fprintf(stderr, "Warning: No neutron could reach Component[17] BananaPSD\n");
    if (mcAbsorbProp[17]) fprintf(stderr, "Warning: %g events were removed in Component[17] BananaPSD\n""         (negative time, rounding errors).\n", mcAbsorbProp[17]);
  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 'Source'. */
  SIG_MESSAGE("Source (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Source");
#define mccompcurname  Source
#define mccompcurtype  Source_simple
#define mccompcurindex 2
#define pmul mccSource_pmul
{   /* Declarations of SETTING parameters. */
MCNUM radius = mccSource_radius;
MCNUM height = mccSource_height;
MCNUM width = mccSource_width;
MCNUM dist = mccSource_dist;
MCNUM xw = mccSource_xw;
MCNUM yh = mccSource_yh;
MCNUM E0 = mccSource_E0;
MCNUM dE = mccSource_dE;
MCNUM Lambda0 = mccSource_Lambda0;
MCNUM dLambda = mccSource_dLambda;
MCNUM flux = mccSource_flux;
MCNUM gauss = mccSource_gauss;
MCNUM compat = mccSource_compat;
#line 151 "/usr/local/lib/mcstas/sources/Source_simple.comp"
{
  if (square == 1) {
    magnify("xy");
    rectangle("xy",0,0,0,width,height);
  } else {
    magnify("xy");
    circle("xy",0,0,0,radius);
  }
}
#line 21326 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef pmul
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'mono_cradle'. */
  SIG_MESSAGE("mono_cradle (McDisplay)");
  printf("MCDISPLAY: component %s\n", "mono_cradle");
#define mccompcurname  mono_cradle
#define mccompcurtype  Arm
#define mccompcurindex 3
#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 21347 "D1A.c"
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Monok'. */
  SIG_MESSAGE("Monok (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Monok");
#define mccompcurname  Monok
#define mccompcurtype  Monochromator_curved
#define mccompcurindex 4
#define reflect mccMonok_reflect
#define transmit mccMonok_transmit
#define mos_rms_y mccMonok_mos_rms_y
#define mos_rms_z mccMonok_mos_rms_z
#define mos_rms_max mccMonok_mos_rms_max
#define mono_Q mccMonok_mono_Q
#define SlabWidth mccMonok_SlabWidth
#define SlabHeight mccMonok_SlabHeight
#define rTable mccMonok_rTable
#define tTable mccMonok_tTable
#define row mccMonok_row
#define col mccMonok_col
{   /* Declarations of SETTING parameters. */
MCNUM zwidth = mccMonok_zwidth;
MCNUM yheight = mccMonok_yheight;
MCNUM gap = mccMonok_gap;
MCNUM NH = mccMonok_NH;
MCNUM NV = mccMonok_NV;
MCNUM mosaich = mccMonok_mosaich;
MCNUM mosaicv = mccMonok_mosaicv;
MCNUM r0 = mccMonok_r0;
MCNUM t0 = mccMonok_t0;
MCNUM Q = mccMonok_Q;
MCNUM RV = mccMonok_RV;
MCNUM RH = mccMonok_RH;
MCNUM DM = mccMonok_DM;
MCNUM mosaic = mccMonok_mosaic;
MCNUM width = mccMonok_width;
MCNUM height = mccMonok_height;
MCNUM verbose = mccMonok_verbose;
#line 432 "/usr/local/lib/mcstas/optics/Monochromator_curved.comp"
{
  int ih;

  magnify("xy");
  for(ih = 0; ih < NH; ih++)
  {
    int iv;
    for(iv = 0; iv < NV; iv++)
    {
      double zmin,zmax,ymin,ymax;
      double xt, xt1, yt, yt1;

      zmin = (SlabWidth+gap)*(ih-NH/2.0)+gap/2;
      zmax = zmin+SlabWidth;
      ymin = (SlabHeight+gap)*(iv-NV/2.0)+gap/2;
      ymax = ymin+SlabHeight;

      if (RH) xt = -(zmax*zmax - zmin*zmin)/RH/2;
      else    xt = 0;

      if (RV) yt = -(ymax*ymax - ymin*ymin)/RV/2;
      else    yt = 0;
      multiline(5, xt+yt, (double)ymin, (double)zmin,
                   xt-yt, (double)ymax, (double)zmin,
                  -xt-yt, (double)ymax, (double)zmax,
                  -xt+yt, (double)ymin, (double)zmax,
                   xt+yt, (double)ymin, (double)zmin);
     }
   }
}
#line 21419 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef col
#undef row
#undef tTable
#undef rTable
#undef SlabHeight
#undef SlabWidth
#undef mono_Q
#undef mos_rms_max
#undef mos_rms_z
#undef mos_rms_y
#undef transmit
#undef reflect
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'mono_out'. */
  SIG_MESSAGE("mono_out (McDisplay)");
  printf("MCDISPLAY: component %s\n", "mono_out");
#define mccompcurname  mono_out
#define mccompcurtype  Arm
#define mccompcurindex 5
#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 21451 "D1A.c"
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Lmon'. */
  SIG_MESSAGE("Lmon (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Lmon");
#define mccompcurname  Lmon
#define mccompcurtype  Monitor_nD
#define mccompcurindex 6
#define options mccLmon_options
#define filename mccLmon_filename
#define user1 mccLmon_user1
#define user2 mccLmon_user2
#define user3 mccLmon_user3
#define username1 mccLmon_username1
#define username2 mccLmon_username2
#define username3 mccLmon_username3
#define DEFS mccLmon_DEFS
#define Vars mccLmon_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccLmon_xwidth;
MCNUM yheight = mccLmon_yheight;
MCNUM zthick = mccLmon_zthick;
MCNUM xmin = mccLmon_xmin;
MCNUM xmax = mccLmon_xmax;
MCNUM ymin = mccLmon_ymin;
MCNUM ymax = mccLmon_ymax;
MCNUM zmin = mccLmon_zmin;
MCNUM zmax = mccLmon_zmax;
MCNUM bins = mccLmon_bins;
MCNUM min = mccLmon_min;
MCNUM max = mccLmon_max;
MCNUM restore_neutron = mccLmon_restore_neutron;
#line 396 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  Monitor_nD_McDisplay(&DEFS, &Vars);
}
#line 21490 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'PSDsample'. */
  SIG_MESSAGE("PSDsample (McDisplay)");
  printf("MCDISPLAY: component %s\n", "PSDsample");
#define mccompcurname  PSDsample
#define mccompcurtype  Monitor_nD
#define mccompcurindex 7
#define options mccPSDsample_options
#define filename mccPSDsample_filename
#define user1 mccPSDsample_user1
#define user2 mccPSDsample_user2
#define user3 mccPSDsample_user3
#define username1 mccPSDsample_username1
#define username2 mccPSDsample_username2
#define username3 mccPSDsample_username3
#define DEFS mccPSDsample_DEFS
#define Vars mccPSDsample_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccPSDsample_xwidth;
MCNUM yheight = mccPSDsample_yheight;
MCNUM zthick = mccPSDsample_zthick;
MCNUM xmin = mccPSDsample_xmin;
MCNUM xmax = mccPSDsample_xmax;
MCNUM ymin = mccPSDsample_ymin;
MCNUM ymax = mccPSDsample_ymax;
MCNUM zmin = mccPSDsample_zmin;
MCNUM zmax = mccPSDsample_zmax;
MCNUM bins = mccPSDsample_bins;
MCNUM min = mccPSDsample_min;
MCNUM max = mccPSDsample_max;
MCNUM restore_neutron = mccPSDsample_restore_neutron;
#line 396 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  Monitor_nD_McDisplay(&DEFS, &Vars);
}
#line 21540 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'SamplePos'. */
  SIG_MESSAGE("SamplePos (McDisplay)");
  printf("MCDISPLAY: component %s\n", "SamplePos");
#define mccompcurname  SamplePos
#define mccompcurtype  Arm
#define mccompcurindex 8
#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 21570 "D1A.c"
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Environment_in'. */
  SIG_MESSAGE("Environment_in (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Environment_in");
#define mccompcurname  Environment_in
#define mccompcurtype  PowderN
#define mccompcurindex 9
#define reflections mccEnvironment_in_reflections
#define format mccEnvironment_in_format
#define line_info mccEnvironment_in_line_info
#define Nq mccEnvironment_in_Nq
#define my_s_v2 mccEnvironment_in_my_s_v2
#define my_s_v2_sum mccEnvironment_in_my_s_v2_sum
#define my_a_v mccEnvironment_in_my_a_v
#define my_inc mccEnvironment_in_my_inc
#define q_v mccEnvironment_in_q_v
#define w_v mccEnvironment_in_w_v
#define isrect mccEnvironment_in_isrect
#define columns mccEnvironment_in_columns
{   /* Declarations of SETTING parameters. */
MCNUM d_phi = mccEnvironment_in_d_phi;
MCNUM radius = mccEnvironment_in_radius;
MCNUM radius_i = mccEnvironment_in_radius_i;
MCNUM yheight = mccEnvironment_in_yheight;
MCNUM pack = mccEnvironment_in_pack;
MCNUM Vc = mccEnvironment_in_Vc;
MCNUM sigma_abs = mccEnvironment_in_sigma_abs;
MCNUM sigma_inc = mccEnvironment_in_sigma_inc;
MCNUM Delta_d = mccEnvironment_in_Delta_d;
MCNUM frac = mccEnvironment_in_frac;
MCNUM tfrac = mccEnvironment_in_tfrac;
MCNUM xwidth = mccEnvironment_in_xwidth;
MCNUM zthick = mccEnvironment_in_zthick;
MCNUM xwidth_i = mccEnvironment_in_xwidth_i;
MCNUM yheight_i = mccEnvironment_in_yheight_i;
MCNUM zthick_i = mccEnvironment_in_zthick_i;
MCNUM h = mccEnvironment_in_h;
MCNUM DW = mccEnvironment_in_DW;
MCNUM nb_atoms = mccEnvironment_in_nb_atoms;
MCNUM concentric = mccEnvironment_in_concentric;
MCNUM density = mccEnvironment_in_density;
MCNUM weight = mccEnvironment_in_weight;
MCNUM barns = mccEnvironment_in_barns;
#line 744 "/usr/local/lib/mcstas/samples/PowderN.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);
    if (radius_i) {
      h=yheight_i;
      circle("xz", 0,  h/2.0, 0, radius_i);
      circle("xz", 0, -h/2.0, 0, radius_i);
      line(-radius_i, -h/2.0, 0, -radius_i, +h/2.0, 0);
      line(+radius_i, -h/2.0, 0, +radius_i, +h/2.0, 0);
      line(0, -h/2.0, -radius_i, 0, +h/2.0, -radius_i);
      line(0, -h/2.0, +radius_i, 0, +h/2.0, +radius_i);
    }
  } 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);
    if (zthick_i) {
      xmin = -0.5*xwidth_i;
      xmax =  0.5*xwidth_i;
      ymin = -0.5*yheight_i;
      ymax =  0.5*yheight_i;
      zmin = -0.5*zthick_i;
      zmax =  0.5*zthick_i;
      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 21683 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Container_in'. */
  SIG_MESSAGE("Container_in (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Container_in");
#define mccompcurname  Container_in
#define mccompcurtype  PowderN
#define mccompcurindex 10
#define reflections mccContainer_in_reflections
#define format mccContainer_in_format
#define line_info mccContainer_in_line_info
#define Nq mccContainer_in_Nq
#define my_s_v2 mccContainer_in_my_s_v2
#define my_s_v2_sum mccContainer_in_my_s_v2_sum
#define my_a_v mccContainer_in_my_a_v
#define my_inc mccContainer_in_my_inc
#define q_v mccContainer_in_q_v
#define w_v mccContainer_in_w_v
#define isrect mccContainer_in_isrect
#define columns mccContainer_in_columns
{   /* Declarations of SETTING parameters. */
MCNUM d_phi = mccContainer_in_d_phi;
MCNUM radius = mccContainer_in_radius;
MCNUM radius_i = mccContainer_in_radius_i;
MCNUM yheight = mccContainer_in_yheight;
MCNUM pack = mccContainer_in_pack;
MCNUM Vc = mccContainer_in_Vc;
MCNUM sigma_abs = mccContainer_in_sigma_abs;
MCNUM sigma_inc = mccContainer_in_sigma_inc;
MCNUM Delta_d = mccContainer_in_Delta_d;
MCNUM frac = mccContainer_in_frac;
MCNUM tfrac = mccContainer_in_tfrac;
MCNUM xwidth = mccContainer_in_xwidth;
MCNUM zthick = mccContainer_in_zthick;
MCNUM xwidth_i = mccContainer_in_xwidth_i;
MCNUM yheight_i = mccContainer_in_yheight_i;
MCNUM zthick_i = mccContainer_in_zthick_i;
MCNUM h = mccContainer_in_h;
MCNUM DW = mccContainer_in_DW;
MCNUM nb_atoms = mccContainer_in_nb_atoms;
MCNUM concentric = mccContainer_in_concentric;
MCNUM density = mccContainer_in_density;
MCNUM weight = mccContainer_in_weight;
MCNUM barns = mccContainer_in_barns;
#line 744 "/usr/local/lib/mcstas/samples/PowderN.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);
    if (radius_i) {
      h=yheight_i;
      circle("xz", 0,  h/2.0, 0, radius_i);
      circle("xz", 0, -h/2.0, 0, radius_i);
      line(-radius_i, -h/2.0, 0, -radius_i, +h/2.0, 0);
      line(+radius_i, -h/2.0, 0, +radius_i, +h/2.0, 0);
      line(0, -h/2.0, -radius_i, 0, +h/2.0, -radius_i);
      line(0, -h/2.0, +radius_i, 0, +h/2.0, +radius_i);
    }
  } 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);
    if (zthick_i) {
      xmin = -0.5*xwidth_i;
      xmax =  0.5*xwidth_i;
      ymin = -0.5*yheight_i;
      ymax =  0.5*yheight_i;
      zmin = -0.5*zthick_i;
      zmax =  0.5*zthick_i;
      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 21809 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Sample_liq'. */
  SIG_MESSAGE("Sample_liq (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Sample_liq");
#define mccompcurname  Sample_liq
#define mccompcurtype  Isotropic_Sqw
#define mccompcurindex 11
#define Sqw_coh mccSample_liq_Sqw_coh
#define Sqw_inc mccSample_liq_Sqw_inc
#define powder_format mccSample_liq_powder_format
#define geometry mccSample_liq_geometry
#define VarSqw mccSample_liq_VarSqw
#define columns mccSample_liq_columns
#define offdata mccSample_liq_offdata
{   /* Declarations of SETTING parameters. */
MCNUM radius = mccSample_liq_radius;
MCNUM thickness = mccSample_liq_thickness;
MCNUM xwidth = mccSample_liq_xwidth;
MCNUM yheight = mccSample_liq_yheight;
MCNUM zdepth = mccSample_liq_zdepth;
MCNUM qmin = mccSample_liq_qmin;
MCNUM qmax = mccSample_liq_qmax;
MCNUM wmin = mccSample_liq_wmin;
MCNUM wmax = mccSample_liq_wmax;
MCNUM auto_qw = mccSample_liq_auto_qw;
MCNUM threshold = mccSample_liq_threshold;
int order = mccSample_liq_order;
MCNUM T = mccSample_liq_T;
MCNUM verbose = mccSample_liq_verbose;
MCNUM d_phi = mccSample_liq_d_phi;
int concentric = mccSample_liq_concentric;
MCNUM V_rho = mccSample_liq_V_rho;
MCNUM sigma_abs = mccSample_liq_sigma_abs;
MCNUM sigma_coh = mccSample_liq_sigma_coh;
MCNUM sigma_inc = mccSample_liq_sigma_inc;
MCNUM save_sqw = mccSample_liq_save_sqw;
MCNUM powder_Dd = mccSample_liq_powder_Dd;
MCNUM powder_DW = mccSample_liq_powder_DW;
MCNUM powder_Vc = mccSample_liq_powder_Vc;
MCNUM density = mccSample_liq_density;
MCNUM weight = mccSample_liq_weight;
MCNUM p_interact = mccSample_liq_p_interact;
MCNUM auto_norm = mccSample_liq_auto_norm;
MCNUM powder_barns = mccSample_liq_powder_barns;
#line 2066 "/usr/local/lib/mcstas/samples/Isotropic_Sqw.comp"
{
  if (VarSqw.s_coh > 0 || VarSqw.s_inc > 0) {
    magnify("xyz");
    if(VarSqw.shape==1)
    {
      double xmin = -0.5*xwidth;
      double xmax =  0.5*xwidth;
      double ymin = -0.5*yheight;
      double ymax =  0.5*yheight;
      double zmin = -0.5*zdepth;
      double zmax =  0.5*zdepth;
      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);

      if (thickness>0) {
        xmin = -0.5*xwidth+thickness;
        xmax = -xmin;
        ymin = -0.5*yheight+thickness;
        ymax = -ymin;
        zmin = -0.5*zdepth+thickness;
        zmax = -zmin;
        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);
      }
    }
    else if(VarSqw.shape==0)
    {
      circle("xz", 0,  yheight/2.0, 0, radius);
      circle("xz", 0, -yheight/2.0, 0, radius);
      line(-radius, -yheight/2.0, 0, -radius, +yheight/2.0, 0);
      line(+radius, -yheight/2.0, 0, +radius, +yheight/2.0, 0);
      line(0, -yheight/2.0, -radius, 0, +yheight/2.0, -radius);
      line(0, -yheight/2.0, +radius, 0, +yheight/2.0, +radius);
      if (thickness) {
        double radius_i=radius-thickness;
        circle("xz", 0,  yheight/2.0, 0, radius_i);
        circle("xz", 0, -yheight/2.0, 0, radius_i);
        line(-radius_i, -yheight/2.0, 0, -radius_i, +yheight/2.0, 0);
        line(+radius_i, -yheight/2.0, 0, +radius_i, +yheight/2.0, 0);
        line(0, -yheight/2.0, -radius_i, 0, +yheight/2.0, -radius_i);
        line(0, -yheight/2.0, +radius_i, 0, +yheight/2.0, +radius_i);
      }
    } else if(VarSqw.shape==2) {
      if (thickness) {
        double radius_i=radius-thickness;
        circle("xy",0,0,0,radius_i);
        circle("xz",0,0,0,radius_i);
        circle("yz",0,0,0,radius_i);
      }
      circle("xy",0,0,0,radius);
      circle("xz",0,0,0,radius);
      circle("yz",0,0,0,radius);
    } else if (VarSqw.shape == 3) {	/* OFF file */
      off_display(offdata);
    }
  }
/* end MCDISPLAY */
}
#line 21953 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef offdata
#undef columns
#undef VarSqw
#undef geometry
#undef powder_format
#undef Sqw_inc
#undef Sqw_coh
#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  PowderN
#define mccompcurindex 12
#define reflections mccSample_reflections
#define format mccSample_format
#define line_info mccSample_line_info
#define Nq mccSample_Nq
#define my_s_v2 mccSample_my_s_v2
#define my_s_v2_sum mccSample_my_s_v2_sum
#define my_a_v mccSample_my_a_v
#define my_inc mccSample_my_inc
#define q_v mccSample_q_v
#define w_v mccSample_w_v
#define isrect mccSample_isrect
#define columns mccSample_columns
{   /* Declarations of SETTING parameters. */
MCNUM d_phi = mccSample_d_phi;
MCNUM radius = mccSample_radius;
MCNUM radius_i = mccSample_radius_i;
MCNUM yheight = mccSample_yheight;
MCNUM pack = mccSample_pack;
MCNUM Vc = mccSample_Vc;
MCNUM sigma_abs = mccSample_sigma_abs;
MCNUM sigma_inc = mccSample_sigma_inc;
MCNUM Delta_d = mccSample_Delta_d;
MCNUM frac = mccSample_frac;
MCNUM tfrac = mccSample_tfrac;
MCNUM xwidth = mccSample_xwidth;
MCNUM zthick = mccSample_zthick;
MCNUM xwidth_i = mccSample_xwidth_i;
MCNUM yheight_i = mccSample_yheight_i;
MCNUM zthick_i = mccSample_zthick_i;
MCNUM h = mccSample_h;
MCNUM DW = mccSample_DW;
MCNUM nb_atoms = mccSample_nb_atoms;
MCNUM concentric = mccSample_concentric;
MCNUM density = mccSample_density;
MCNUM weight = mccSample_weight;
MCNUM barns = mccSample_barns;
#line 744 "/usr/local/lib/mcstas/samples/PowderN.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);
    if (radius_i) {
      h=yheight_i;
      circle("xz", 0,  h/2.0, 0, radius_i);
      circle("xz", 0, -h/2.0, 0, radius_i);
      line(-radius_i, -h/2.0, 0, -radius_i, +h/2.0, 0);
      line(+radius_i, -h/2.0, 0, +radius_i, +h/2.0, 0);
      line(0, -h/2.0, -radius_i, 0, +h/2.0, -radius_i);
      line(0, -h/2.0, +radius_i, 0, +h/2.0, +radius_i);
    }
  } 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);
    if (zthick_i) {
      xmin = -0.5*xwidth_i;
      xmax =  0.5*xwidth_i;
      ymin = -0.5*yheight_i;
      ymax =  0.5*yheight_i;
      zmin = -0.5*zthick_i;
      zmax =  0.5*zthick_i;
      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 22074 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Container_out'. */
  SIG_MESSAGE("Container_out (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Container_out");
#define mccompcurname  Container_out
#define mccompcurtype  PowderN
#define mccompcurindex 13
#define reflections mccContainer_out_reflections
#define format mccContainer_out_format
#define line_info mccContainer_out_line_info
#define Nq mccContainer_out_Nq
#define my_s_v2 mccContainer_out_my_s_v2
#define my_s_v2_sum mccContainer_out_my_s_v2_sum
#define my_a_v mccContainer_out_my_a_v
#define my_inc mccContainer_out_my_inc
#define q_v mccContainer_out_q_v
#define w_v mccContainer_out_w_v
#define isrect mccContainer_out_isrect
#define columns mccContainer_out_columns
{   /* Declarations of SETTING parameters. */
MCNUM d_phi = mccContainer_out_d_phi;
MCNUM radius = mccContainer_out_radius;
MCNUM radius_i = mccContainer_out_radius_i;
MCNUM yheight = mccContainer_out_yheight;
MCNUM pack = mccContainer_out_pack;
MCNUM Vc = mccContainer_out_Vc;
MCNUM sigma_abs = mccContainer_out_sigma_abs;
MCNUM sigma_inc = mccContainer_out_sigma_inc;
MCNUM Delta_d = mccContainer_out_Delta_d;
MCNUM frac = mccContainer_out_frac;
MCNUM tfrac = mccContainer_out_tfrac;
MCNUM xwidth = mccContainer_out_xwidth;
MCNUM zthick = mccContainer_out_zthick;
MCNUM xwidth_i = mccContainer_out_xwidth_i;
MCNUM yheight_i = mccContainer_out_yheight_i;
MCNUM zthick_i = mccContainer_out_zthick_i;
MCNUM h = mccContainer_out_h;
MCNUM DW = mccContainer_out_DW;
MCNUM nb_atoms = mccContainer_out_nb_atoms;
MCNUM concentric = mccContainer_out_concentric;
MCNUM density = mccContainer_out_density;
MCNUM weight = mccContainer_out_weight;
MCNUM barns = mccContainer_out_barns;
#line 744 "/usr/local/lib/mcstas/samples/PowderN.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);
    if (radius_i) {
      h=yheight_i;
      circle("xz", 0,  h/2.0, 0, radius_i);
      circle("xz", 0, -h/2.0, 0, radius_i);
      line(-radius_i, -h/2.0, 0, -radius_i, +h/2.0, 0);
      line(+radius_i, -h/2.0, 0, +radius_i, +h/2.0, 0);
      line(0, -h/2.0, -radius_i, 0, +h/2.0, -radius_i);
      line(0, -h/2.0, +radius_i, 0, +h/2.0, +radius_i);
    }
  } 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);
    if (zthick_i) {
      xmin = -0.5*xwidth_i;
      xmax =  0.5*xwidth_i;
      ymin = -0.5*yheight_i;
      ymax =  0.5*yheight_i;
      zmin = -0.5*zthick_i;
      zmax =  0.5*zthick_i;
      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 22200 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Environment_out'. */
  SIG_MESSAGE("Environment_out (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Environment_out");
#define mccompcurname  Environment_out
#define mccompcurtype  PowderN
#define mccompcurindex 14
#define reflections mccEnvironment_out_reflections
#define format mccEnvironment_out_format
#define line_info mccEnvironment_out_line_info
#define Nq mccEnvironment_out_Nq
#define my_s_v2 mccEnvironment_out_my_s_v2
#define my_s_v2_sum mccEnvironment_out_my_s_v2_sum
#define my_a_v mccEnvironment_out_my_a_v
#define my_inc mccEnvironment_out_my_inc
#define q_v mccEnvironment_out_q_v
#define w_v mccEnvironment_out_w_v
#define isrect mccEnvironment_out_isrect
#define columns mccEnvironment_out_columns
{   /* Declarations of SETTING parameters. */
MCNUM d_phi = mccEnvironment_out_d_phi;
MCNUM radius = mccEnvironment_out_radius;
MCNUM radius_i = mccEnvironment_out_radius_i;
MCNUM yheight = mccEnvironment_out_yheight;
MCNUM pack = mccEnvironment_out_pack;
MCNUM Vc = mccEnvironment_out_Vc;
MCNUM sigma_abs = mccEnvironment_out_sigma_abs;
MCNUM sigma_inc = mccEnvironment_out_sigma_inc;
MCNUM Delta_d = mccEnvironment_out_Delta_d;
MCNUM frac = mccEnvironment_out_frac;
MCNUM tfrac = mccEnvironment_out_tfrac;
MCNUM xwidth = mccEnvironment_out_xwidth;
MCNUM zthick = mccEnvironment_out_zthick;
MCNUM xwidth_i = mccEnvironment_out_xwidth_i;
MCNUM yheight_i = mccEnvironment_out_yheight_i;
MCNUM zthick_i = mccEnvironment_out_zthick_i;
MCNUM h = mccEnvironment_out_h;
MCNUM DW = mccEnvironment_out_DW;
MCNUM nb_atoms = mccEnvironment_out_nb_atoms;
MCNUM concentric = mccEnvironment_out_concentric;
MCNUM density = mccEnvironment_out_density;
MCNUM weight = mccEnvironment_out_weight;
MCNUM barns = mccEnvironment_out_barns;
#line 744 "/usr/local/lib/mcstas/samples/PowderN.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);
    if (radius_i) {
      h=yheight_i;
      circle("xz", 0,  h/2.0, 0, radius_i);
      circle("xz", 0, -h/2.0, 0, radius_i);
      line(-radius_i, -h/2.0, 0, -radius_i, +h/2.0, 0);
      line(+radius_i, -h/2.0, 0, +radius_i, +h/2.0, 0);
      line(0, -h/2.0, -radius_i, 0, +h/2.0, -radius_i);
      line(0, -h/2.0, +radius_i, 0, +h/2.0, +radius_i);
    }
  } 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);
    if (zthick_i) {
      xmin = -0.5*xwidth_i;
      xmax =  0.5*xwidth_i;
      ymin = -0.5*yheight_i;
      ymax =  0.5*yheight_i;
      zmin = -0.5*zthick_i;
      zmax =  0.5*zthick_i;
      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 22326 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef columns
#undef isrect
#undef w_v
#undef q_v
#undef my_inc
#undef my_a_v
#undef my_s_v2_sum
#undef my_s_v2
#undef Nq
#undef line_info
#undef format
#undef reflections
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'Collimator'. */
  SIG_MESSAGE("Collimator (McDisplay)");
  printf("MCDISPLAY: component %s\n", "Collimator");
#define mccompcurname  Collimator
#define mccompcurtype  Collimator_radial
#define mccompcurindex 15
#define soller_theta1 mccCollimator_soller_theta1
#define soller_theta2 mccCollimator_soller_theta2
#define window_theta mccCollimator_window_theta
#define use_approx mccCollimator_use_approx
#define ideal mccCollimator_ideal
{   /* Declarations of SETTING parameters. */
MCNUM w1 = mccCollimator_w1;
MCNUM h1 = mccCollimator_h1;
MCNUM w2 = mccCollimator_w2;
MCNUM h2 = mccCollimator_h2;
MCNUM len = mccCollimator_len;
MCNUM divergence = mccCollimator_divergence;
MCNUM transmission = mccCollimator_transmission;
MCNUM theta_min = mccCollimator_theta_min;
MCNUM theta_max = mccCollimator_theta_max;
MCNUM nchan = mccCollimator_nchan;
MCNUM radius = mccCollimator_radius;
MCNUM nblades = mccCollimator_nblades;
MCNUM roc = mccCollimator_roc;
MCNUM verbose = mccCollimator_verbose;
#line 226 "/usr/local/lib/mcstas/optics/Collimator_radial.comp"
{
  int i;
  double theta1, theta2;
  double x_in_l,  z_in_l,  x_in_r,  z_in_r;
  double x_out_l, z_out_l, x_out_r, z_out_r;
  double y1, y2;

  magnify("xy");
  y1 = h1/2;
  y2 = h2/2;
  for (i = 0; i < nchan; i++) {
    theta1 = i*window_theta+theta_min;
    theta2 = theta1+window_theta;

    z_in_l = radius*cos(theta1);
    x_in_l = radius*sin(theta1);
    z_in_r = radius*cos(theta2);
    x_in_r = radius*sin(theta2);

    z_out_l = (radius+len)*cos(theta1);
    x_out_l = (radius+len)*sin(theta1);
    z_out_r = (radius+len)*cos(theta2);
    x_out_r = (radius+len)*sin(theta2);
    /* left side */
    multiline(6,
      x_in_l, -y1, z_in_l,
      x_in_l,  y1, z_in_l,
      x_out_l, y2, z_out_l,
      x_out_l,-y2, z_out_l,
      x_in_l, -y1, z_in_l,
      x_in_r, -y1, z_in_r);
   /* left -> right lines */
   line(x_in_l,   y1, z_in_l,  x_in_r,  y1, z_in_r);
   line(x_out_l,  y2, z_out_l, x_out_r, y2, z_out_r);
   line(x_out_l, -y2, z_out_l, x_out_r,-y2, z_out_r);
  }
  /* remaining bits */
  theta1 = nchan*window_theta+theta_min;
  z_in_l = radius*cos(theta1);
  x_in_l = radius*sin(theta1);
  z_out_l = (radius+len)*cos(theta1);
  x_out_l = (radius+len)*sin(theta1);
  multiline(5,
      x_in_l, -y1, z_in_l,
      x_in_l,  y1, z_in_l,
      x_out_l, y2, z_out_l,
      x_out_l,-y2, z_out_l,
      x_in_l, -y1, z_in_l);
}
#line 22420 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef ideal
#undef use_approx
#undef window_theta
#undef soller_theta2
#undef soller_theta1
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'BananaTheta'. */
  SIG_MESSAGE("BananaTheta (McDisplay)");
  printf("MCDISPLAY: component %s\n", "BananaTheta");
#define mccompcurname  BananaTheta
#define mccompcurtype  Monitor_nD
#define mccompcurindex 16
#define options mccBananaTheta_options
#define filename mccBananaTheta_filename
#define user1 mccBananaTheta_user1
#define user2 mccBananaTheta_user2
#define user3 mccBananaTheta_user3
#define username1 mccBananaTheta_username1
#define username2 mccBananaTheta_username2
#define username3 mccBananaTheta_username3
#define DEFS mccBananaTheta_DEFS
#define Vars mccBananaTheta_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccBananaTheta_xwidth;
MCNUM yheight = mccBananaTheta_yheight;
MCNUM zthick = mccBananaTheta_zthick;
MCNUM xmin = mccBananaTheta_xmin;
MCNUM xmax = mccBananaTheta_xmax;
MCNUM ymin = mccBananaTheta_ymin;
MCNUM ymax = mccBananaTheta_ymax;
MCNUM zmin = mccBananaTheta_zmin;
MCNUM zmax = mccBananaTheta_zmax;
MCNUM bins = mccBananaTheta_bins;
MCNUM min = mccBananaTheta_min;
MCNUM max = mccBananaTheta_max;
MCNUM restore_neutron = mccBananaTheta_restore_neutron;
#line 396 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  Monitor_nD_McDisplay(&DEFS, &Vars);
}
#line 22465 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#undef mccompcurname
#undef mccompcurtype
#undef mccompcurindex

  /* MCDISPLAY code for component 'BananaPSD'. */
  SIG_MESSAGE("BananaPSD (McDisplay)");
  printf("MCDISPLAY: component %s\n", "BananaPSD");
#define mccompcurname  BananaPSD
#define mccompcurtype  Monitor_nD
#define mccompcurindex 17
#define options mccBananaPSD_options
#define filename mccBananaPSD_filename
#define user1 mccBananaPSD_user1
#define user2 mccBananaPSD_user2
#define user3 mccBananaPSD_user3
#define username1 mccBananaPSD_username1
#define username2 mccBananaPSD_username2
#define username3 mccBananaPSD_username3
#define DEFS mccBananaPSD_DEFS
#define Vars mccBananaPSD_Vars
{   /* Declarations of SETTING parameters. */
MCNUM xwidth = mccBananaPSD_xwidth;
MCNUM yheight = mccBananaPSD_yheight;
MCNUM zthick = mccBananaPSD_zthick;
MCNUM xmin = mccBananaPSD_xmin;
MCNUM xmax = mccBananaPSD_xmax;
MCNUM ymin = mccBananaPSD_ymin;
MCNUM ymax = mccBananaPSD_ymax;
MCNUM zmin = mccBananaPSD_zmin;
MCNUM zmax = mccBananaPSD_zmax;
MCNUM bins = mccBananaPSD_bins;
MCNUM min = mccBananaPSD_min;
MCNUM max = mccBananaPSD_max;
MCNUM restore_neutron = mccBananaPSD_restore_neutron;
#line 396 "/usr/local/lib/mcstas/monitors/Monitor_nD.comp"
{
  Monitor_nD_McDisplay(&DEFS, &Vars);
}
#line 22515 "D1A.c"
}   /* End of SETTING parameter declarations. */
#undef Vars
#undef DEFS
#undef username3
#undef username2
#undef username1
#undef user3
#undef user2
#undef user1
#undef filename
#undef options
#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
