1/*******************************************************************************
2*
3* McCode, neutron/xray ray-tracing package
4*         Copyright (C) 1997-2009, All rights reserved
5*         Risoe National Laboratory, Roskilde, Denmark
6*         Institut Laue Langevin, Grenoble, France
7*
8* Runtime: share/mccode-r.h
9*
10* %Identification
11* Written by: KN
12* Date:    Aug 29, 1997
13* Release: McXtrace 1.2
14* Version: $Revision$
15*
16* Runtime system header for McStas/McXtrace.
17*
18* In order to use this library as an external library, the following variables
19* and macros must be declared (see details in the code)
20*
21*   struct mcinputtable_struct mcinputtable[];
22*   int mcnumipar;
23*   char mcinstrument_name[], mcinstrument_source[];
24*   int mctraceenabled, mcdefaultmain;
25*   extern MCNUM  mccomp_storein[];
26*   extern MCNUM  mcAbsorbProp[];
27*   extern MCNUM  mcScattered;
28*   #define MCCODE_STRING "the McStas/McXtrace version"
29*
30* Usage: Automatically embbeded in the c code.
31*
32* $Id$
33*
34*******************************************************************************/
35
36#ifndef MCCODE_R_H
37#define MCCODE_R_H "$Revision$"
38
39#include <math.h>
40#include <string.h>
41#include <stdlib.h>
42#include <stdio.h>
43#include <stdarg.h>
44#include <limits.h>
45#include <errno.h>
46#include <time.h>
47#include <float.h>
48
49/* If the runtime is embedded in the simulation program, some definitions can
50   be made static. */
51
52#ifdef MC_EMBEDDED_RUNTIME
53#define mcstatic static
54#else
55#define mcstatic
56#endif
57
58#ifdef __dest_os
59#if (__dest_os == __mac_os)
60#define MAC
61#endif
62#endif
63
64#ifdef __FreeBSD__
65#define NEED_STAT_H
66#endif
67
68#if defined(__APPLE__) && defined(__GNUC__)
69#define NEED_STAT_H
70#endif
71
72#ifdef NEED_STAT_H
73#include <sys/stat.h>
74#endif
75
76#ifndef MC_PATHSEP_C
77#ifdef WIN32
78#define MC_PATHSEP_C '\\'
79#define MC_PATHSEP_S "\\"
80#else  /* !WIN32 */
81#define MC_PATHSEP_C '/'
82#define MC_PATHSEP_S "/"
83#endif /* !WIN32 */
84#endif /* MC_PATHSEP_C */
85
86
87
88/* the version string is replaced when building distribution with mkdist */
89#ifndef MCCODE_STRING
90#define MCCODE_STRING "McXtrace 1.2 - Jul. 02, 2015"
91#endif
92
93#ifndef MCCODE_DATE
94#define MCCODE_DATE "Jul. 02, 2015"
95#endif
96
97#ifndef MCCODE_VERSION
98#define MCCODE_VERSION "1.2"
99#endif
100
101#ifndef MCCODE_NAME
102#define MCCODE_NAME "McXtrace"
103#endif
104
105#ifndef MCCODE_PARTICLE
106#define MCCODE_PARTICLE "@MCCODE_PARTICLE@"
107#endif
108
109#ifndef MCCODE_LIBENV
110#define MCCODE_LIBENV "@MCCODE_LIBENV@"
111#endif
112
113#ifndef FLAVOR_UPPER
114#define FLAVOR_UPPER MCCODE_NAME
115#endif
116
117#ifdef MC_PORTABLE
118#ifndef NOSIGNALS
119#define NOSIGNALS 1
120#endif
121#endif
122
123#ifdef MAC
124#ifndef NOSIGNALS
125#define NOSIGNALS 1
126#endif
127#endif
128
129#if (USE_MPI == 0)
130#undef USE_MPI
131#endif
132
133#ifdef USE_MPI  /* default is to disable signals with MPI, as MPICH uses them to communicate */
134#ifndef NOSIGNALS
135#define NOSIGNALS 1
136#endif
137#endif
138
139#if (NOSIGNALS == 0)
140#undef NOSIGNALS
141#endif
142
143/* Note: the enum instr_formal_types definition MUST be kept
144   synchronized with the one in mccode.h and with the
145   instr_formal_type_names array in cogen.c. */
146enum instr_formal_types
147  {
148    instr_type_double, instr_type_int, instr_type_string
149  };
150struct mcinputtable_struct { /* defines instrument parameters */
151  char *name; /* name of parameter */
152  void *par;  /* pointer to instrument parameter (variable) */
153  enum instr_formal_types type;
154  char *val;  /* default value */
155};
156
157typedef double MCNUM;
158typedef struct {MCNUM x, y, z;} Coords;
159typedef MCNUM Rotation[3][3];
160
161/* the following variables are defined in the McStas generated C code
162   but should be defined externally in case of independent library usage */
163#ifndef DANSE
164extern struct mcinputtable_struct mcinputtable[]; /* list of instrument parameters */
165extern int    mcnumipar;                          /* number of instrument parameters */
166extern char   mcinstrument_name[], mcinstrument_source[]; /* instrument name and filename */
167extern char  *mcinstrument_exe;                           /* executable path = argv[0] or NULL */
168extern MCNUM  mccomp_storein[]; /* 11 coords * number of components in instrument */
169extern MCNUM  mcAbsorbProp[];
170extern MCNUM  mcScattered;      /* number of SCATTER calls in current component */
171extern MCNUM  mcRestore;        /* Flag to indicate if neutron needs to be restored */
172#ifndef MC_ANCIENT_COMPATIBILITY
173extern int mctraceenabled, mcdefaultmain;
174#endif
175#endif
176
177
178/* Useful macros ============================================================ */
179
180/* MPI stuff */
181
182#ifdef USE_MPI
183#include "mpi.h"
184
185#ifdef OMPI_MPI_H  /* openmpi does not use signals: we may install our sighandler */
186#undef NOSIGNALS
187#endif
188
189/*
190 * MPI_MASTER(i):
191 * execution of i only on master node
192 */
193#define MPI_MASTER(statement) { \
194  if(mpi_node_rank == mpi_node_root)\
195  { statement; } \
196}
197
198#ifndef MPI_REDUCE_BLOCKSIZE
199#define MPI_REDUCE_BLOCKSIZE 1000
200#endif
201
202int mc_MPI_Sum(double* buf, long count);
203int mc_MPI_Send(void *sbuf, long count, MPI_Datatype dtype, int dest);
204int mc_MPI_Recv(void *rbuf, long count, MPI_Datatype dtype, int source);
205
206/* MPI_Finalize exits gracefully and should be preferred to MPI_Abort */
207#define exit(code) do {                                   \
208    MPI_Finalize();                                       \
209    exit(code);                                           \
210  } while(0)
211
212#else /* !USE_MPI */
213#define MPI_MASTER(instr) instr
214#endif /* USE_MPI */
215
216#ifdef USE_MPI
217static int mpi_node_count;
218#endif
219
220#ifdef USE_THREADS  /* user want threads */
221#error Threading (USE_THREADS) support has been removed for very poor efficiency. Use MPI/SSH grid instead.
222#endif
223
224
225void   mcset_ncount(unsigned long long count);    /* wrapper to get mcncount */
226unsigned long long int mcget_ncount(void);            /* wrapper to set mcncount */
227unsigned long long mcget_run_num(void);           /* wrapper to get mcrun_num=0:mcncount */
228
229
230/* Following part is only embedded when not redundant with mccode.h ========= */
231
232#ifndef MCCODE_H
233
234#ifndef NOSIGNALS
235#include <signal.h>
236#define SIG_MESSAGE(msg) strcpy(mcsig_message, msg);
237#else
238#define SIG_MESSAGE(msg)
239#endif /* !NOSIGNALS */
240
241/* Useful macros and constants ============================================== */
242
243#ifndef FLT_MAX
244#define FLT_MAX         3.40282347E+38F /* max decimal value of a "float" */
245#endif
246
247#ifndef MIN
248#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
249#endif
250#ifndef MAX
251#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
252#endif
253#ifndef SQR
254#define SQR(x) ( (x) * (x) )
255#endif
256#ifndef SIGN
257#define SIGN(x) (((x)>0.0)?(1):(-1))
258#endif
259
260#ifndef PI
261# ifdef M_PI
262#  define PI M_PI
263# else
264#  define PI 3.14159265358979323846
265# endif
266#endif
267
268#define RAD2MIN  ((180*60)/PI)
269#define MIN2RAD  (PI/(180*60))
270#define DEG2RAD  (PI/180)
271#define RAD2DEG  (180/PI)
272#define FWHM2RMS 0.424660900144    /* Convert between full-width-half-max and */
273#define RMS2FWHM 2.35482004503     /* root-mean-square (standard deviation) */
274#define HBAR     1.05457168e-34    /* [Js] h bar Planck constant CODATA 2002 */
275#define MNEUTRON 1.67492728e-27    /* [kg] mass of neutron CODATA 2002 */
276#define GRAVITY  9.81              /* [m/s^2] gravitational acceleration */
277#define NA       6.02214179e23     /* [#atoms/g .mole] Avogadro's number*/
278
279
280/* wrapper to get absolute and relative position of comp */
281/* mccomp_posa and mccomp_posr are defined in McStas generated C code */
282#define POS_A_COMP_INDEX(index) \
283    (mccomp_posa[index])
284#define POS_R_COMP_INDEX(index) \
285    (mccomp_posr[index])
286/* number of SCATTER calls in current comp: mcScattered defined in generated C code */
287#define SCATTERED mcScattered
288/* Flag to indicate if neutron needs to be restored: mcRestore defined in generated C code */
289#define RESTORE mcRestore
290
291
292/* Retrieve component information from the kernel */
293/* Name, position and orientation (both absolute and relative)  */
294/* Any component: For "redundancy", see comment by KN */
295#define tmp_name_comp(comp) #comp
296#define NAME_COMP(comp) tmp_name_comp(comp)
297#define tmp_pos_a_comp(comp) (mcposa ## comp)
298#define POS_A_COMP(comp) tmp_pos_a_comp(comp)
299#define tmp_pos_r_comp(comp) (mcposr ## comp)
300#define POS_R_COMP(comp) tmp_pos_r_comp(comp)
301#define tmp_rot_a_comp(comp) (mcrota ## comp)
302#define ROT_A_COMP(comp) tmp_rot_a_comp(comp)
303#define tmp_rot_r_comp(comp) (mcrotr ## comp)
304#define ROT_R_COMP(comp) tmp_rot_r_comp(comp)
305
306/* Current component name, index, position and orientation */
307#define NAME_CURRENT_COMP  NAME_COMP(mccompcurname)
308#define INDEX_CURRENT_COMP mccompcurindex
309#define POS_A_CURRENT_COMP POS_A_COMP(mccompcurname)
310#define POS_R_CURRENT_COMP POS_R_COMP(mccompcurname)
311#define ROT_A_CURRENT_COMP ROT_A_COMP(mccompcurname)
312#define ROT_R_CURRENT_COMP ROT_R_COMP(mccompcurname)
313
314/* Note: The two-stage approach to MC_GETPAR is NOT redundant; without it,
315* after #define C sample, MC_GETPAR(C,x) would refer to component C, not to
316* component sample. Such are the joys of ANSI C.
317
318* Anyway the usage of MCGETPAR requires that we use sometimes bare names...
319*/
320#define MC_GETPAR2(comp, par) (mcc ## comp ## _ ## par)
321#define MC_GETPAR(comp, par) MC_GETPAR2(comp,par)
322
323/* MCDISPLAY/trace and debugging message sent to stdout */
324#ifdef MC_TRACE_ENABLED
325#define DEBUG
326#endif
327
328#ifdef DEBUG
329#define mcDEBUG_INSTR() if(!mcdotrace); else { printf("INSTRUMENT:\n"); printf("Instrument '%s' (%s)\n", mcinstrument_name, mcinstrument_source); }
330#define mcDEBUG_COMPONENT(name,c,t) if(!mcdotrace); else {\
331  printf("COMPONENT: \"%s\"\n" \
332         "POS: %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g\n", \
333         name, c.x, c.y, c.z, t[0][0], t[0][1], t[0][2], \
334         t[1][0], t[1][1], t[1][2], t[2][0], t[2][1], t[2][2]); \
335  printf("Component %30s AT (%g,%g,%g)\n", name, c.x, c.y, c.z); \
336  }
337#define mcDEBUG_INSTR_END() if(!mcdotrace); else printf("INSTRUMENT END:\n");
338#define mcDEBUG_ENTER() if(!mcdotrace); else printf("ENTER:\n");
339#define mcDEBUG_COMP(c) if(!mcdotrace); else printf("COMP: \"%s\"\n", c);
340#define mcDEBUG_LEAVE() if(!mcdotrace); else printf("LEAVE:\n");
341#define mcDEBUG_ABSORB() if(!mcdotrace); else printf("ABSORB:\n");
342#else
343#define mcDEBUG_INSTR()
344#define mcDEBUG_COMPONENT(name,c,t)
345#define mcDEBUG_INSTR_END()
346#define mcDEBUG_ENTER()
347#define mcDEBUG_COMP(c)
348#define mcDEBUG_LEAVE()
349#define mcDEBUG_ABSORB()
350#endif
351
352// mcDEBUG_STATE and mcDEBUG_SCATTER are defined by mcstas-r.h and mcxtrace-r.h
353
354
355
356#ifdef TEST
357#define test_printf printf
358#else
359#define test_printf while(0) printf
360#endif
361
362/* send MCDISPLAY message to stdout to show gemoetry */
363void mcdis_magnify(char *what);
364void mcdis_line(double x1, double y1, double z1,
365                double x2, double y2, double z2);
366void mcdis_dashed_linemcdis_dashed_line(double x1, double y1, double z1,
367		       double x2, double y2, double z2, int n);
368void mcdis_multiline(int count, ...);
369void mcdis_rectangle(char* plane, double x, double y, double z,
370		     double width, double height);
371void mcdis_box(double x, double y, double z,
372	       double width, double height, double length);
373void mcdis_circle(char *plane, double x, double y, double z, double r);
374
375/* selection of random number generator. default is MT */
376#ifndef MC_RAND_ALG
377#define MC_RAND_ALG 1
378#endif
379
380#if MC_RAND_ALG == 0
381   /* Use system random() (not recommended). */
382#  define MC_RAND_MAX RAND_MAX
383#elif MC_RAND_ALG == 1
384   /* "Mersenne Twister", by Makoto Matsumoto and Takuji Nishimura. */
385#  define MC_RAND_MAX ((unsigned long)0xffffffff)
386#  define random mt_random
387#  define srandom mt_srandom
388#elif MC_RAND_ALG == 2
389   /* Algorithm used in McStas CVS-080208 and earlier (not recommended). */
390#  define MC_RAND_MAX 0x7fffffff
391#  define random mc_random
392#  define srandom mc_srandom
393#else
394#  error "Bad value for random number generator choice."
395#endif
396
397typedef int mc_int32_t;
398mc_int32_t mc_random(void);
399void mc_srandom (unsigned int x);
400unsigned long mt_random(void);
401void mt_srandom (unsigned long x);
402
403double rand01();
404double randpm1();
405double rand0max(double max);
406double randminmax(double min, double max);
407
408double randnorm(void);
409double randtriangle(void);
410
411#ifndef DANSE
412void mcinit(void);
413void mcraytrace(void);
414void mcsave(FILE *);
415void mcfinally(void);
416void mcdisplay(void);
417#endif
418
419/* simple vector algebra ==================================================== */
420#define vec_prod(x, y, z, x1, y1, z1, x2, y2, z2) \
421	vec_prod_func(&x, &y, &z, x1, y1, z1, x2, y2, z2)
422mcstatic inline void vec_prod_func(double *x, double *y, double *z,
423		double x1, double y1, double z1, double x2, double y2, double z2);
424
425mcstatic inline double scalar_prod(
426		double x1, double y1, double z1, double x2, double y2, double z2);
427
428#define NORM(x,y,z) \
429	norm_func(&x, &y, &z)
430mcstatic inline void norm_func(double *x, double *y, double *z) {
431	double temp = (*x * *x) + (*y * *y) + (*z * *z);
432	if (temp != 0) {
433		temp = sqrt(temp);
434		*x /= temp;
435		*y /= temp;
436		*z /= temp;
437	}
438}
439
440void normal_vec(double *nx, double *ny, double *nz,
441    double x, double y, double z);
442
443/**
444 * Rotate the vector vx,vy,vz psi radians around the vector ax,ay,az
445 * and put the result in x,y,z.
446 */
447#define rotate(x, y, z, vx, vy, vz, phi, ax, ay, az) \
448  do { \
449    double mcrt_tmpx = (ax), mcrt_tmpy = (ay), mcrt_tmpz = (az); \
450    double mcrt_vp, mcrt_vpx, mcrt_vpy, mcrt_vpz; \
451    double mcrt_vnx, mcrt_vny, mcrt_vnz, mcrt_vn1x, mcrt_vn1y, mcrt_vn1z; \
452    double mcrt_bx, mcrt_by, mcrt_bz; \
453    double mcrt_cos, mcrt_sin; \
454    NORM(mcrt_tmpx, mcrt_tmpy, mcrt_tmpz); \
455    mcrt_vp = scalar_prod((vx), (vy), (vz), mcrt_tmpx, mcrt_tmpy, mcrt_tmpz); \
456    mcrt_vpx = mcrt_vp*mcrt_tmpx; \
457    mcrt_vpy = mcrt_vp*mcrt_tmpy; \
458    mcrt_vpz = mcrt_vp*mcrt_tmpz; \
459    mcrt_vnx = (vx) - mcrt_vpx; \
460    mcrt_vny = (vy) - mcrt_vpy; \
461    mcrt_vnz = (vz) - mcrt_vpz; \
462    vec_prod(mcrt_bx, mcrt_by, mcrt_bz, \
463             mcrt_tmpx, mcrt_tmpy, mcrt_tmpz, mcrt_vnx, mcrt_vny, mcrt_vnz); \
464    mcrt_cos = cos((phi)); mcrt_sin = sin((phi)); \
465    mcrt_vn1x = mcrt_vnx*mcrt_cos + mcrt_bx*mcrt_sin; \
466    mcrt_vn1y = mcrt_vny*mcrt_cos + mcrt_by*mcrt_sin; \
467    mcrt_vn1z = mcrt_vnz*mcrt_cos + mcrt_bz*mcrt_sin; \
468    (x) = mcrt_vpx + mcrt_vn1x; \
469    (y) = mcrt_vpy + mcrt_vn1y; \
470    (z) = mcrt_vpz + mcrt_vn1z; \
471  } while(0)
472
473/**
474 * Mirror (xyz) in the plane given by the point (rx,ry,rz) and normal (nx,ny,nz)
475 *
476 * TODO: This define is seemingly never used...
477 */
478#define mirror(x,y,z,rx,ry,rz,nx,ny,nz) \
479  do { \
480    double mcrt_tmpx= (nx), mcrt_tmpy = (ny), mcrt_tmpz = (nz); \
481    double mcrt_tmpt; \
482    NORM(mcrt_tmpx, mcrt_tmpy, mcrt_tmpz); \
483    mcrt_tmpt=scalar_prod((rx),(ry),(rz),mcrt_tmpx,mcrt_tmpy,mcrt_tmpz); \
484    (x) = rx -2 * mcrt_tmpt*mcrt_rmpx; \
485    (y) = ry -2 * mcrt_tmpt*mcrt_rmpy; \
486    (z) = rz -2 * mcrt_tmpt*mcrt_rmpz; \
487  } while (0)
488
489Coords coords_set(MCNUM x, MCNUM y, MCNUM z);
490Coords coords_get(Coords a, MCNUM *x, MCNUM *y, MCNUM *z);
491Coords coords_add(Coords a, Coords b);
492Coords coords_sub(Coords a, Coords b);
493Coords coords_neg(Coords a);
494Coords coords_scale(Coords b, double scale);
495double coords_sp(Coords a, Coords b);
496Coords coords_xp(Coords b, Coords c);
497void   coords_print(Coords a);
498mcstatic inline void coords_norm(Coords* c);
499
500void rot_set_rotation(Rotation t, double phx, double phy, double phz);
501int  rot_test_identity(Rotation t);
502void rot_mul(Rotation t1, Rotation t2, Rotation t3);
503void rot_copy(Rotation dest, Rotation src);
504void rot_transpose(Rotation src, Rotation dst);
505Coords rot_apply(Rotation t, Coords a);
506
507void mccoordschange(Coords a, Rotation t, double *x, double *y, double *z,
508    double *vx, double *vy, double *vz, double *sx, double *sy, double *sz);
509void
510mccoordschange_polarisation(Rotation t, double *sx, double *sy, double *sz);
511
512double mcestimate_error(double N, double p1, double p2);
513void mcreadparams(void);
514
515/* this is now in mcstas-r.h and mcxtrace-r.h as the number of state parameters is no longer equal*/
516/* void mcsetstate(double x, double y, double z, double vx, double vy, double vz,
517                double t, double sx, double sy, double sz, double p);
518*/
519void mcgenstate(void);
520
521/* trajectory/shape intersection routines */
522int inside_rectangle(double, double, double, double);
523int box_intersect(double *dt_in, double *dt_out, double x, double y, double z,
524    double vx, double vy, double vz, double dx, double dy, double dz);
525int cylinder_intersect(double *t0, double *t1, double x, double y, double z,
526    double vx, double vy, double vz, double r, double h);
527int sphere_intersect(double *t0, double *t1, double x, double y, double z,
528                 double vx, double vy, double vz, double r);
529/* second order equation roots */
530int solve_2nd_order(double *t1, double *t2,
531    double A,  double B,  double C);
532
533/* random vector generation to shape */
534void randvec_target_circle(double *xo, double *yo, double *zo,
535    double *solid_angle, double xi, double yi, double zi, double radius);
536#define randvec_target_sphere randvec_target_circle
537void randvec_target_rect_angular(double *xo, double *yo, double *zo,
538    double *solid_angle,
539               double xi, double yi, double zi, double height, double width, Rotation A);
540#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)
541void randvec_target_rect_real(double *xo, double *yo, double *zo,
542    double *solid_angle,
543	       double xi, double yi, double zi, double height, double width, Rotation A,
544			 double lx, double ly, double lz, int order);
545
546/* this is the main() */
547int mccode_main(int argc, char *argv[]);
548
549
550#endif /* !MCCODE_H */
551
552#ifndef MCCODE_R_IO_H
553#define MCCODE_R_IO_H "$Revision$"
554
555#if (USE_NEXUS == 0)
556#undef USE_NEXUS
557#endif
558
559#ifndef CHAR_BUF_LENGTH
560#define CHAR_BUF_LENGTH 1024
561#endif
562
563/* I/O section part ========================================================= */
564
565/* ========================================================================== */
566
567/*                               MCCODE_R_IO_C                                */
568
569/* ========================================================================== */
570
571
572/* main DETECTOR structure which stores most information to write to data files */
573struct mcdetector_struct {
574  char   filename[CHAR_BUF_LENGTH];   /* file name of monitor */
575  char   position[CHAR_BUF_LENGTH];   /* position of detector component */
576  char   component[CHAR_BUF_LENGTH];  /* component instance name */
577  char   instrument[CHAR_BUF_LENGTH]; /* instrument name */
578  char   type[CHAR_BUF_LENGTH];       /* data type, e.g. 0d, 1d, 2d, 3d */
579  char   user[CHAR_BUF_LENGTH];       /* user name, e.g. HOME */
580  char   date[CHAR_BUF_LENGTH];       /* date of simulation end/write time */
581  char   title[CHAR_BUF_LENGTH];      /* title of detector */
582  char   xlabel[CHAR_BUF_LENGTH];     /* X axis label */
583  char   ylabel[CHAR_BUF_LENGTH];     /* Y axis label */
584  char   zlabel[CHAR_BUF_LENGTH];     /* Z axis label */
585  char   xvar[CHAR_BUF_LENGTH];       /* X variable name */
586  char   yvar[CHAR_BUF_LENGTH];       /* Y variable name */
587  char   zvar[CHAR_BUF_LENGTH];       /* Z variable name */
588  char   ncount[CHAR_BUF_LENGTH];     /* number of events initially generated */
589  char   limits[CHAR_BUF_LENGTH];     /* X Y Z limits, e.g. [xmin xmax ymin ymax zmin zmax] */
590  char   variables[CHAR_BUF_LENGTH];  /* variables written into data block */
591  char   statistics[CHAR_BUF_LENGTH]; /* center, mean and half width along axis */
592  char   signal[CHAR_BUF_LENGTH];     /* min max and mean of signal (data block) */
593  char   values[CHAR_BUF_LENGTH];     /* integrated values e.g. [I I_err N] */
594  double xmin,xmax;                   /* min max of axes */
595  double ymin,ymax;
596  double zmin,zmax;
597  double intensity;                   /* integrated values for data block */
598  double error;
599  double events;
600  double min;                         /* statistics for data block */
601  double max;
602  double mean;
603  double centerX;                     /* statistics for axes */
604  double halfwidthX;
605  double centerY;
606  double halfwidthY;
607  int    rank;                        /* dimensionaly of monitor, e.g. 0 1 2 3 */
608  char   istransposed;                /* flag to transpose matrix for some formats */
609
610  long   m,n,p;                       /* dimensions of data block and along axes */
611  long   date_l;                      /* same as date, but in sec since 1970 */
612
613  double *p0, *p1, *p2;               /* pointers to saved data, NULL when freed */
614  char   format[CHAR_BUF_LENGTH];    /* format for file generation */
615};
616
617typedef struct mcdetector_struct MCDETECTOR;
618
619static   char *mcdirname             = NULL;      /* name of output directory */
620static   char *mcsiminfo_name        = "mccode";  /* default output sim file name */
621char    *mcformat                    = NULL;      /* NULL (default) or a specific format */
622
623/* file I/O definitions and function prototypes */
624
625#ifndef MC_EMBEDDED_RUNTIME /* the mcstatic variables (from mccode-r.c) */
626extern FILE * mcsiminfo_file;     /* handle to the output siminfo file */
627extern int    mcgravitation;      /* flag to enable gravitation */
628extern int    mcdotrace;          /* flag to print MCDISPLAY messages */
629#else
630mcstatic FILE *mcsiminfo_file        = NULL;
631#endif
632
633/* I/O function prototypes ================================================== */
634
635/* output functions */
636MCDETECTOR mcdetector_out_0D(char *t, double p0, double p1, double p2, char *c, Coords pos);
637MCDETECTOR mcdetector_out_1D(char *t, char *xl, char *yl,
638                  char *xvar, double x1, double x2, long n,
639                  double *p0, double *p1, double *p2, char *f, char *c, Coords pos);
640MCDETECTOR mcdetector_out_2D(char *t, char *xl, char *yl,
641                  double x1, double x2, double y1, double y2, long m,
642                  long n, double *p0, double *p1, double *p2, char *f,
643                  char *c, Coords pos);
644MCDETECTOR mcdetector_out_list(char *t, char *xl, char *yl,
645                  long m, long n,
646                  double *p1, char *f,
647                  char *c, Coords posa);
648
649/* wrappers to output functions, that automatically set NAME and POSITION */
650#define DETECTOR_OUT(p0,p1,p2) mcdetector_out_0D(NAME_CURRENT_COMP,p0,p1,p2,NAME_CURRENT_COMP,POS_A_CURRENT_COMP)
651#define DETECTOR_OUT_0D(t,p0,p1,p2) mcdetector_out_0D(t,p0,p1,p2,NAME_CURRENT_COMP,POS_A_CURRENT_COMP)
652#define DETECTOR_OUT_1D(t,xl,yl,xvar,x1,x2,n,p0,p1,p2,f) \
653     mcdetector_out_1D(t,xl,yl,xvar,x1,x2,n,p0,p1,p2,f,NAME_CURRENT_COMP,POS_A_CURRENT_COMP)
654#define DETECTOR_OUT_2D(t,xl,yl,x1,x2,y1,y2,m,n,p0,p1,p2,f) \
655     mcdetector_out_2D(t,xl,yl,x1,x2,y1,y2,m,n,p0,p1,p2,f,NAME_CURRENT_COMP,POS_A_CURRENT_COMP)
656
657#ifdef USE_NEXUS
658#include "napi.h"
659NXhandle nxhandle;
660#endif
661
662#endif /* ndef MCCODE_R_IO_H */
663
664#endif /* MCCODE_R_H */
665