/*******************************************************************************
*
* McStas, neutron ray-tracing package
* Copyright 1997-2002, All rights reserved
* Risoe National Laboratory, Roskilde, Denmark
* Institut Laue Langevin, Grenoble, France
* Component: Virtual_output
*
* %I
* Written by: E. Farhi
* Date: Dec 17th, 2002
* Version: $Revision: 1.13 $
* Origin: ILL
* Release: McStas 1.6
* Modified by: E. Farhi, Dec 17th, 2002: based on Vitess_output and Monitor_nD lib.
*
* Detector-like component that writes neutron state parameters into a 'virtual
* source' neutron file.
*
* %D
* Detector-like component writing neutron state parameters to a
* virtual source neutron file. The component geometry is the full
* plane, and saves the neutron state as it exits from the previous
* component.
*
* It is particularly useful to generate a virtual source at a point that few
* neutron reach. A long simulation will then only be performed once, to create
* the upstream 'source' file. Further simulations are much faster if they start
* from this low flux position with the 'source' file.
*
* Possible file formats are:
* 1-text column formatted with lines containing 11 values in the order:
* p x y z vx vy vz t sx sy sz stored into about 83 bytes/n.
* 2-float/double binary files (with the 11 values 'p x y z vx vy vz t sx sy sz')
* stored into 44 and 88 bytes/n respectively for float/double.
*
* Beware the size of generated files ! When saving all events (bufsize=0) the
* required memory has been optimized and remains very small. On the other hand
* using large bufsize values (not recommanded) requires huge storage memory.
* Moreover, using the 'bufsize' parameter will often lead to wrong intentities.
* Both methods will generate huge files.
*
* A Vitess file may be obtained from the 'Vitess_output' component or from a
* Vitess simulation (104 bytes per neutron) and read with Vitess_input.
*
* Example: Virtual_output(file="MySource.dat")
* will generate a 9 Mo text file for 1e5 events stored.
*
* %BUGS
* Using bufsize non-zero generates a virtual source with wrong intensity
*
* %P
* INPUT PARAMETERS
*
* file: [str] Filename of neutron file to write. Default is standard
* output [string]. If not given, a unique name will be used.
* bufsize:[1] Size of neutron output buffer
* default is 0, i.e. save all - recommanded.
* type: [str] Type of output file 'text','float','double'
* default is text
*
* %E
*******************************************************************************/
DEFINE COMPONENT Virtual_output
DEFINITION PARAMETERS (file=0, type=0)
SETTING PARAMETERS (bufsize=0)
OUTPUT PARAMETERS (DEFS, Vars, mcformat_sim, mcformat_vo, mcformat_override)
STATE PARAMETERS (x,y,z,vx,vy,vz,t,s1,s2,p)
POLARISATION PARAMETERS (sx,sy,sz)
SHARE
%{
%include "monitor_nd-lib"
%}
DECLARE
%{
MonitornD_Defines_type DEFS;
MonitornD_Variables_type Vars;
struct mcformats_struct mcformat_sim;
struct mcformats_struct mcformat_vo;
char mcformat_override;
%}
INITIALIZE
%{
long element_size;
strcpy(Vars.compcurname, NAME_CURRENT_COMP);
if (bufsize > 0) sprintf(Vars.option, "list=%g", bufsize);
else strcpy(Vars.option, "list all");
if (type)
{
if (strstr(type, "Vitess"))
{ fprintf(stderr, "Virtual_output: %s: Vitess files may be generated using the Vitess_output component\n", NAME_CURRENT_COMP); exit(-1); }
if (strstr(type, "binary") || strstr(type, "float")) {
strcat(Vars.option, ", binary float");
element_size = sizeof(float);
} else if (strstr(type, "double")) {
strcat(Vars.option, ", binary double");
element_size = sizeof(double);
} else element_size = 85;
}
strcat(Vars.option,", x y z vx vy vz t sx sy sz");
Monitor_nD_Init(&DEFS, &Vars, 0.1, 0.1, 0, 0,0,0,0,0,0); /* dims for mcdisplay */
if (file != NULL)
strncpy(Vars.Mon_File, file, 128);
mcformat_override = !strstr(Vars.option, "binary");
mcformat_sim = mcformat;
mcformat_vo = mcuse_format("McStas");
if (bufsize > 0) {
printf("Warning: Virtual_output: %s: buffer size=%g not recommanded\n"
" Beware virtual output generated file size (about %g Mo)\n"
" Memory required is about %g Mo\n",
NAME_CURRENT_COMP, bufsize, bufsize*element_size/1e6,
bufsize*sizeof(double)/1e6);
}
%}
TRACE
%{
double pp;
PROP_Z0;
/* transfert current neutron to Monitor_nD vars */
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 (mcformat_override) mcformat = mcformat_vo;
pp = Monitor_nD_Trace(&DEFS, &Vars);
if (mcformat_override) mcformat = mcformat_sim;
Vars.Nsum++;
Vars.psum += pp;
Vars.p2sum += pp*pp;
SCATTER;
%}
SAVE
%{
if (mcformat_override) mcformat = mcformat_vo;
Monitor_nD_Save(&DEFS, &Vars);
if (mcformat_override) mcformat = mcformat_sim;
%}
FINALLY
%{
/* free pointers */
Monitor_nD_Finally(&DEFS, &Vars);
if (bufsize) {
printf("Virtual_output: %s: Saved %li events in file %s\n"
"WARNING When using this source, intensities must be divided\n"
" by a factor %g\n",
NAME_CURRENT_COMP, Vars.Buffer_Block, Vars.Mon_File, Vars.Nsum/bufsize);
} else printf("Virtual_output: %s: Saved %15f events (all) in file %s\n", NAME_CURRENT_COMP, Vars.Nsum, Vars.Mon_File);
%}
MCDISPLAY
%{
Monitor_nD_McDisplay(&DEFS, &Vars);
%}
END