/*******************************************************************************
*
* McStas, neutron ray-tracing package
* Copyright 1997-2002, All rights reserved
* Risoe National Laboratory, Roskilde, Denmark
* Institut Laue Langevin, Grenoble, France
*
* Component: Virtual_tripoli4_input.comp
* %I
* Written by: Guillaume Campioni
* Date: Sep 28th, 2001
* Version: $Revision: 1.10 $
* Origin: SERMA
* Release: McStas 1.8
* Modified by: E. Farhi: Added automatic orientation+beam info+intensity norm
*
* This component uses a file of recorded neutrons from the reactor monte carlo
* code TRIPOLI4.4 as a source of particles.
*
* %D
* This component generates neutron events from a file created using the
* TRIPOLI4 Monte Carlo code for nuclear reactors (as MCNP). It is used to
* calculate flux exiting from hot or cold neutron sources.
* Neutron position and velocity is set from the file. The neutron time is
* left at zero.
* Storage files from TRIPOLI4.4 contain several batches of particules, all
* of them having the same statictical weight.
*
* Note that axes orientation may be different between TRIPOLI4.4 and McStas.
* The component has the ability to center and orient the neutron beam to the Z-axis.
* It also may change the coordinate system from the Tripoli frame to the McStas one.
* The verbose mode is highly recommanded as it displays lots of useful informations,
* including the absolute intensity normalisation factor. All neutron fluxes in the
* instrument should be multiplied by this factor.
* The source total intensity is 1.054e18 for LLB/Saclay and 4.28e18 for ILL/Grenoble.
*
* Format of TRIPOLI4.4 event files is :
*
* NEUTRON energy position_X position_Y position_Z dir_X dir_Y dir_Z weight
*
* energy is in Mega eV
* positions are in cm and the direction vector is normalized to 1.
*
*
* EXAMPLE:
* To create a 'source' from a Tripoli4 simulation event file for the ILL:
* COMPONENT source = Virtual_tripoli4_input(
* file = "ILL_SFH.dat", intensity=4.28e18,
* repeat_count = 1, verbose = 1, autocenter="translate rotate")
*
* %P
* INPUT PARAMETERS
* file: [str] Name of the Tripoli4.4 neutron input file
* repeat_count: [1] Number of times the source must be generated.
* 0 unactivates the component
* verbose: [0|1] Displays additional informations if set to 1
* intensity: [n/s] Initial total Source integrated intensity
* autocenter: [str] String which may contain following keywords.
* "translate" or "center" to center the beam area AT (0,0,0)
* "rotate" or "orient" to center the beam velocity along Z
* "change axes" to change coordinate system definition
* Other words are ignored.
*
* OUTPUT PARAMETERS
* head: [char] header buffer
* nl: [long] nb of lines in header
* mean_x: [double] \
* mean_y: [double] source center coordinates
* mean_z: [double] /
* angle2z:[double, rad] rotation angle required to orient beam along Z axis
* nbatch: [long] number of read neutron batches
*
* %L
* Tripoli
* %L
* Virtual_tripoli4_output
* %L
* CAMPIONI Guillaume, Etude et Modelisation des Sources Froides de Neutrons, These de Doctorat, CEA Saclay/UJF (2004)
*
* %E
*
*******************************************************************************/
DEFINE COMPONENT Virtual_tripoli4_input
DEFINITION PARAMETERS (file=0, autocenter=0)
SETTING PARAMETERS (repeat_count=1, verbose=0, intensity=1)
OUTPUT PARAMETERS (hfile,head,nl,rep,begin_of_file,begin_batch,do_rotate,do_translate,do_axes,
bx,by,bz,angle2z,nbatch,nsize,mean_x, mean_y, mean_z)
STATE PARAMETERS (x,y,z,vx,vy,vz,t,s1,s2,p)
POLARISATION PARAMETERS (sx, sy, sz)
SHARE
%{
#ifndef TRIPOLI4_INPUT_DEFS
#define TRIPOLI4_INPUT_DEFS
/* define Tripoli File parsing functions */
#define T4_WORDSIZE 256
/* number of neutron events to read for file pre-analysis */
#define T4_ANALYSE 10000
#include
/* functions to identify Tripoli keywords */
int begin_of_batch(const char * word )
{
return strcmp(word,"BEGIN_OF_BATCH")==0?1:0;
}
int end_of_batch(const char * word)
{
return strcmp(word,"END_OF_BATCH")==0?1:0;
}
int is_neutron(const char * word)
{
return strcmp(word,"NEUTRON")==0?1:0;
}
/* tripoli_read_word:
function that reads iteratively words in the file
returns EOF or last character
word[0..l-1]
*/
int tripoli_read_word(FILE *hfile,char *word){
char c;
int i=0;
while((c=fgetc(hfile))!=EOF && isspace(c)){ /* skip spaces */ }
if(c!=EOF){
word[i++]=c;
while((c=fgetc(hfile))!=EOF && i < T4_WORDSIZE) {
if(isspace(c)) break;
word[i++]=c;
}
}
word[i]='\0';
return c;
}
/* tripoli_create_neutron:
function that reads values following the NEUTRON keyword
and assigns neutron parameters.
Warning: Tripoli Coord system (x y z) = (-x z y)
*/
int tripoli_create_neutron(FILE *hfile, double *x,double *y,double *z,
double *vx, double *vy, double *vz,
double *t,
double *sx, double *sy, double *sz,
double *p)
{
double Mev2Joule=1.602e-13;
double speed;
int exit_flag=0, ifield=0;
char word[T4_WORDSIZE];
double field[8];
while(ifield<8){
if(tripoli_read_word(hfile,word)==EOF) { exit_flag=1; break; };
field[ifield++]=strtod(word,NULL);
}
if(field[0] < 0 || exit_flag) { exit_flag=1; }
else {
speed=sqrt(2.* field[0]*Mev2Joule/MNEUTRON);
*x=field[1]/100.0;
*y=field[2]/100.0;
*z=field[3]/100.0;
*vx=field[4]*speed;
*vy=field[5]*speed;
*vz=field[6]*speed;
*p=field[7];
*sx=1.;*sy=*sz=0;
*t=0;
}
return (exit_flag);
}
/* tripoli_get_header:
function that gets header lines until the Tripoli start of a batch
*/
char **tripoli_get_header(FILE *hfile,long *nl){
int i;
char **head;
char word[T4_WORDSIZE];
*nl=0;
fgets(word,T4_WORDSIZE,hfile);
while(strncmp(word,"BEGIN_OF_BATCH",14)!=0){
fgets(word,T4_WORDSIZE,hfile);
(*nl)++;
}
rewind(hfile);
head=(char **)calloc(*nl,sizeof(char *));
for(i=0;i<*nl;++i){
fgets(word,T4_WORDSIZE,hfile);
head[i]=(char *)malloc(T4_WORDSIZE);
strcpy(head[i],word);
}
rewind(hfile);
return head;
}
#endif
%}
DECLARE
%{
int rep=1; /* Neutron repeat count */
FILE *hfile; /* Neutron input file handle */
char **head; /*Tripol4 header*/
long nl; /* Number of lines in header*/
long first_batch=0; /* position in file of first batch */
long begin_batch=0, end_batch=0; /* current batch numbers */
char do_rotate=0, do_translate=0, do_axes=0;
double mean_x =0, mean_y =0, mean_z =0;
double bx,by,bz;
double angle2z;
long nbatch=0;
long nsize =0;
%}
INITIALIZE
%{
char word[T4_WORDSIZE];
char exit_flag=0; /* set to 1 if end of simulation */
int result_read;
double mean_vx=0, mean_vy=0, mean_vz=0;
double mean_dx=0, mean_dy=0, mean_dz=0;
double min_x = FLT_MAX, min_y = FLT_MAX, min_z = FLT_MAX;
double max_x =-FLT_MAX, max_y =-FLT_MAX, max_z =-FLT_MAX;
double min_vx= FLT_MAX, min_vy= FLT_MAX, min_vz= FLT_MAX;
double max_vx=-FLT_MAX, max_vy=-FLT_MAX, max_vz=-FLT_MAX;
double n_neutrons=0;
double n_neutrons_p=0;
long filesize =0;
struct stat stfile;
/* Open neutron input file. */
if (file) {
stat(file,&stfile);
filesize = stfile.st_size;
hfile = fopen(file, "r");
}
if(!hfile)
{
fprintf(stderr, "Tripoli4_input: %s: Error: Cannot open input file.\n", NAME_CURRENT_COMP);
exit(1);
} else if (verbose)
printf("Tripoli4_input: %s: opening Tripoli4 file '%s'\n", NAME_CURRENT_COMP, file);
head = tripoli_get_header(hfile, &nl); /* and reset to file start */
while (tripoli_read_word(hfile,word) != EOF) {
/* store position of first batch in file for repeat */
first_batch=ftell(hfile);
if (begin_of_batch(word)) {
if (tripoli_read_word(hfile,word)!=EOF) {
begin_batch=strtol(word,NULL,0);
break;
}
}
if (!strcmp(word,"SIZE") || !strcmp(word,"TAILLE")) {
if (tripoli_read_word(hfile,word)!=EOF) nsize=strtol(word,NULL,0);
}
}
if (verbose) printf("Analysing Tripoli4 file %s (%d events)\n", file, T4_ANALYSE);
/* analyse Tripoli file: count neutrons, get beam center and mean speed
* do that for the first 1e4 neutrons, and extrapolates to file size */
while (!exit_flag && n_neutrons <= T4_ANALYSE) {
result_read=tripoli_read_word(hfile,word);
if (is_neutron(word)) { /* if key word NEUTRON is found */
double x,y,z,vx,vy,vz,t,p,sx,sy,sz;
if (tripoli_create_neutron(hfile,&x,&y,&z,&vx,&vy,&vz,&t,&sx,&sy,&sz,&p)) {
fprintf(stderr, "Tripoli4_input: %s: Error: Cannot get neutron %d in batch %d.\n",NAME_CURRENT_COMP,n_neutrons,begin_batch);
exit_flag = 1;
} else {
double v;
mean_x += p*x; mean_y += p*y; mean_z += p*z;
mean_vx += p*vx; mean_vy += p*vy; mean_vz += p*vz;
v = sqrt(vx*vx+vy*vy+vz*vz);
if (v) {
mean_dx += p*fabs(vx/v); mean_dy += p*fabs(vy/v); mean_dz += p*fabs(vz/v); }
if (x < min_x) min_x = x;
if (y < min_y) min_y = y;
if (z < min_z) min_z = z;
if (vx < min_vx) min_vx = vx;
if (vy < min_vy) min_vy = vy;
if (vz < min_vz) min_vz = z;
if (x > max_x) max_x = x;
if (y > max_y) max_y = y;
if (z > max_z) max_z = z;
if (vx > max_vx) max_vx = vx;
if (vy > max_vy) max_vy = vy;
if (vz > max_vz) max_vz = z;
n_neutrons++;
n_neutrons_p += p;
}
}
if (begin_of_batch(word)){/* if key word BEGIN_OF_BATCH is found */
if (tripoli_read_word(hfile,word) != EOF) {
begin_batch=strtol(word,NULL,0);
nbatch++;
}
}
if (result_read==EOF) { /* normal end of file */
exit_flag=1;
}
} /* end while */
if (n_neutrons) {
double n_count_extrapolated=0;
double mean_v;
long end_analyse=0;
double cx,cy,cz;
end_analyse = ftell(hfile);
mean_x /= n_neutrons_p;
mean_y /= n_neutrons_p;
mean_z /= n_neutrons_p;
mean_vx /= n_neutrons_p;
mean_vy /= n_neutrons_p;
mean_vz /= n_neutrons_p;
mean_dx /= n_neutrons_p;
mean_dy /= n_neutrons_p;
mean_dz /= n_neutrons_p;
/* now estimates total ncount */
mean_v = sqrt(mean_vx*mean_vx+mean_vy*mean_vy+mean_vz*mean_vz);
n_count_extrapolated = n_neutrons*(filesize-first_batch)/(end_analyse - first_batch);
if (verbose) {
double mean_k, mean_w=0, mean_L=0;
mean_k = V2K*mean_v;
if (mean_k) mean_L = 2*PI/mean_k;
mean_w = VS2E*mean_v*mean_v;
printf("Tripoli4 file %s\nContains about %g neutrons in %d batches\n", file, n_count_extrapolated, nbatch*(filesize-first_batch)/(end_analyse - first_batch));
if (n_count_extrapolated > mcget_ncount())
printf(" (will use only %.3g %% of file)\n", 100*mcget_ncount()/n_count_extrapolated);
else
printf(" (limiting simulation to %g neutrons)\n", n_count_extrapolated*repeat_count);
printf(" Source size (full width in [m]): ");
printf(" dX=%g dY=%g dZ=%g\n", max_x-min_x, max_y-min_y, max_z-min_z);
printf(" Source center (in [m]): ");
printf(" X0=%g Y0=%g Z0=%g\n", mean_x, mean_y, mean_z);
printf(" Beam divergence (full width in [deg]):");
printf(" dVx=%g dVy=%g dVz=%g\n",
atan(mean_dx)*RAD2DEG,
atan(mean_dy)*RAD2DEG,
atan(mean_dz)*RAD2DEG);
printf(" Beam speed (in [m/s]): ");
printf(" Vx=%g Vy=%g Vz=%g\n", mean_vx, mean_vy, mean_vz);
printf(" Beam mean energy:\n");
printf(" speed=%g [m/s] energy=%g [meV]\n wavelength=%g [Angs] wavevector=%g [Angs-1]\n", mean_v, mean_w, mean_L, mean_k);
}
if (autocenter) {
if (strstr(autocenter, "rotate") || strstr(autocenter, "orient"))
do_rotate = 1;
if (strstr(autocenter, "translate") || strstr(autocenter, "center"))
do_translate = 1;
if (strstr(autocenter, "change") &&
(strstr(autocenter, "axis") || strstr(autocenter, "axes")
|| strstr(autocenter, "system") || strstr(autocenter, "coord")) )
do_axes = 1;
}
/* compute the rotation matrix to make mean_v along the Z-axis */
/* first normalize mean velocity (will be Z axis): c=v/|v| */
cx = mean_vx/mean_v; cy = mean_vy/mean_v; cz = mean_vz/mean_v;
/* compute angle to rotate in order to come back to Z axis */
angle2z = acos(cz); /* in RAD */
/* get rotation axis b=c x [0 0 1] */
if (angle2z) {
vec_prod(bx,by,bz, cx,cy,cz, 0,0,1);
} else { /* already well oriented: nothing to do */
do_rotate = 0;
}
if (verbose && (do_rotate || do_translate)) {
printf("* Beam will be ");
if (do_translate) printf("translated (in position) ");
if (do_rotate) printf("rotated (%.3g [deg] to Z-axis) ", angle2z*RAD2DEG);
if (do_axes) printf("axes-swaped Tripoli->McStas");
printf("\n");
}
} else {
fprintf(stderr, "Tripoli4_input: %s: Error: file %s neutrons does not contains any neutron. \n",NAME_CURRENT_COMP, file);
exit(-1);
}
begin_batch = 0; nbatch=0;
/* reposition at start of file (batch start) */
if (fseek(hfile, first_batch,SEEK_SET)) {
fprintf(stderr, "Tripoli4_input: %s: Error: Can not reset Tripoli4 file (fseek error at analyse). \n",NAME_CURRENT_COMP);
exit_flag = 1;
}
%}
TRACE
%{
char exit_flag=0; /* set to 1 if end of simulation */
int result_read;
char word[T4_WORDSIZE];
while(1) {
result_read=tripoli_read_word(hfile,word);
if (is_neutron(word)) { /* if key word NEUTRON is found */
if (tripoli_create_neutron(hfile,&x,&y,&z,&vx,&vy,&vz,&t,&sx,&sy,&sz,&p)) {
fprintf(stderr, "Virtual_tripoli4_input: %s: Error: Cannot create neutron in batch %d.\n",NAME_CURRENT_COMP,begin_batch);
fprintf(stderr," Finishing simulation\n");
exit_flag = 1;
} else {
if (do_translate) { /* translate the beam to origin */
x -= mean_x; y -= mean_y; z -= mean_z;
}
if (do_rotate) { /* rotate the beam so that its main axis is along Z */
double nvx, nvy, nvz;
rotate(nvx,nvy,nvz, vx,vy,vz, angle2z, bx,by,bz);
vx = nvx; vy=nvy; vz=nvz;
rotate(nvx,nvy,nvz, x, y, z, angle2z, bx,by,bz);
x = nvx; y=nvy; z=nvz;
}
if (do_axes) {
/* Tripoli/Vitess (xyz) - > McStas (zxy) */
double tx, ty, tz;
tx=x; ty=y; tz=z; x=ty; y=tz; z=tx;
tx=vx; ty=vy; tz=vz; vx=ty; vy=tz; vz=tx;
}
}
SCATTER;
break;
}
if (end_of_batch(word)) { /* if key word END_OF_BATCH is found */
if (tripoli_read_word(hfile,word) != EOF) {
/* this is the number of finishing batch */
end_batch=strtol(word,NULL,0);
if (end_batch!=begin_batch && begin_batch) {
/* finishing batch does not match the one we were reading ! */
fprintf(stderr, "Tripoli4_input: %s: Warning: inconsistent batch numbers between END(%d) and BEGIN(%d).\n", NAME_CURRENT_COMP, end_batch,begin_batch);
} else nbatch++;
}
else {
fprintf(stderr, "Tripoli4_input: %s: Expect 'END_OF_BATCH', found '%s' (after batch %d).", word, begin_batch);
exit_flag = 1;
}
}
if (begin_of_batch(word)){/* if key word BEGIN_OF_BATCH is found */
if (tripoli_read_word(hfile,word) != EOF) {
begin_batch=strtol(word,NULL,0);
}
else {
fprintf(stderr, "Tripoli4_input: %s: Expect 'BEGIN_OF_BATCH', found '%s' (after batch %d).", word, begin_batch);
exit_flag = 1;
}
}
if (result_read==EOF) { /* normal end of file */
rep++;
if (rep < repeat_count) {
/* reposition at start of file (batch start) */
int ret = fseek(hfile, first_batch,SEEK_SET);
if (ret) {
fprintf(stderr, "Tripoli4_input: %s: Error: Can not repeat Tripoli4 file (fseek error at repeat %d). \n",NAME_CURRENT_COMP, rep);
exit_flag = 1;
}
result_read = tripoli_read_word(hfile,word); /* should be batch start */
begin_batch=strtol(word,NULL,0);
if (verbose) printf("Tripoli4_input: %s: Start Batch Number %d (iteration %d)\n",NAME_CURRENT_COMP,begin_batch, rep);
}
else exit_flag=1;
}
if (exit_flag) { mcset_ncount(mcget_run_num()); ABSORB; }
} /* end while */
%}
FINALLY
%{
if (head) free(head);
if (hfile) fclose(hfile);
if (verbose) {
printf("Tripoli4_input: %s: \n", NAME_CURRENT_COMP);
printf(" %g neutrons generated\n", mcget_ncount());
printf(" %d read batch (B) of intial %d neutrons (N)\n",nbatch, nsize);
if (nbatch && nsize)
printf("* Normalisation factor Intensity/N/B = %g [n/s]\n", intensity/nbatch/nsize);
}
%}
END