/******************************************************************************* * * McStas, the neutron ray-tracing package: Source_file.comp * Copyright 1997-2001 Risoe National Laboratory, Roskilde, Denmark * * Component: Source_file * * %I * Written by: E. Farhi * Date: Sep 28th, 2001 * Version: 0.1 * Origin: McStas 1.5//ILL * Modified by: EF, 2004. Upgraded into Virtual_input * * Source that generates neutron events from an ascii/binary 'source' file. * * %D * This component reads neutron events store in a file, and send them into * the instrument. It thus replaces a Source component, using a previously * computed neutron set. * The input file may be * 1-text column formatted with lines containing at least 11 values in the order: * x y z vx vy vz t sx sy sz p * or * x y z vx vy vz t sx sy sz p p2 * Such files may be generated for instance by Monitor_nD with * Monitor_nD(options="list=10000 source") * 2-Vitess files (binary files of Neutron structure records of 'double') * 3-float binary files (with the 12 values 'x y z vx vy vz t sx sy sz p p2') * It is specially 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 'source' file. Further simulations are much faster if they start from * this low flux position with the 'source' file. * OBSOLETE: rather use sources/Virtual_input * * EXAMPLE: * To create a 'source' file collecting all neutron states, use: * COMPONENT MySourceCreator = Monitor_nD( * filename = "MySource.list", options="list all source") * at the position where will be the Source_file. * The output file is text formatted with:[x y z vx vy vz t sx sy sz p p2] lines * and is about 90 bytes per neutron. A binary float format (half size) is * obtained with Monitor_nD(options="list all source binary"). * A Vitess file may be obtained from the 'Vitess_output' component or from a * Vitess simulation. * Then unactivate the component MySourceCreator (add 'unactivate' in options), * as well as your real source, and put the new instrument source: * COMPONENT Source = Source_file( * input="MySource.list") * at the relevant position * * %P * INPUT PARAMETERS * input: (str) * * Optional input parameters: * repeat_count: (1) Number of times the source must be generated. * 0 unactivates the component * * OUTPUT PARAMETERS * * %E * *******************************************************************************/ DEFINE COMPONENT Source_file DEFINITION PARAMETERS (input=0) SETTING PARAMETERS (repeat_count = 1) OUTPUT PARAMETERS (file, source, rep, pos, FileType) STATE PARAMETERS (x,y,z,vx,vy,vz,t,s1,s2,p) POLARISATION PARAMETERS (sx, sy, sz) SHARE %{ #ifndef VITESS_LIB_H #define VITESS_LIB_H /* The Neutron structure, taken from VITESS source code "general.h" */ typedef double VectorType[3]; typedef struct { double Time; double Wavelength; double Probability; VectorType Position; VectorType Vector; VectorType Spin; } Neutron; /* Convert McStas state parameters to VITESS Neutron structure. In VITESS, the neutron velocity is represented by a wavelength in AAngstroem and a unit direction vector, time is in msec and positions are in cm.*/ Neutron mcstas2vitess(double x, double y, double z, double vx, double vy, double vz, double t, double sx, double sy, double sz, double p) { double v,s; /* Neutron speed */ Neutron neu; /* Vitess Neutron structure */ neu.Position[0] = x*100; /* Convert position from m to cm */ neu.Position[1] = y*100; neu.Position[2] = z*100; v = sqrt(vx*vx + vy*vy + vz*vz); if(v == 0.0) { fprintf(stderr, "mcstas2vitess: Error: zero velocity!\n"); exit(1); } neu.Wavelength = 3956.0346/v; /* Convert speed to wavelength */ neu.Vector[0] = vx/v; /* Convert velocity to unit direction vector */ neu.Vector[1] = vy/v; neu.Vector[2] = vz/v; s = sqrt(sx*sx+sy*sy+sz*sz); if(s != 0.0) { neu.Spin[0] = sx/s; neu.Spin[1] = sy/s; neu.Spin[2] = sz/s; } neu.Time = t*1000; /* Convert time from sec to msec */ neu.Probability = p; /* Neutron weight */ return neu; } /* Convert VITESS neutron structure to McStas state parameters. In VITESS, the neutron velocity is represented by a wavelength in AAngstroem and a unit direction vector, time is in msec and positions are in cm. */ void vitess2mcstas(Neutron neu, double *x, double *y, double *z, double *vx, double *vy, double *vz, double *t, double *sx, double *sy, double *sz, double *p) { double v; /* Neutron speed */ *x = 0.01*neu.Position[0]; /* Convert position from cm to m */ *y = 0.01*neu.Position[1]; *z = 0.01*neu.Position[2]; if(neu.Wavelength == 0.0) { fprintf(stderr, "mcstas2vitess: Error: zero wavelength!\n"); exit(1); } v = 3956.0346/neu.Wavelength; /* Convert wavelength to speed */ *vx = v*neu.Vector[0]; /* Convert unit direction vector to velocity */ *vy = v*neu.Vector[1]; *vz = v*neu.Vector[2]; *sx = neu.Spin[0]; *sy = neu.Spin[1]; *sz = neu.Spin[2]; *t = 0.001*neu.Time; /* Convert msec to sec */ *p = neu.Probability; /* Neutron weight */ } #endif %} DECLARE %{ #include double* read_s_file(char *file, double *size) { FILE *f; double i=0; int s_block=0; int block_size=100000; double *s; *size=0; f = fopen(file, "r"); if(!f) { fprintf(stderr, "Source_file: Error: file '%s' cannot be opened/found.\n", file); exit(1); } s = (double*)malloc((block_size)*11*sizeof(double)); while(!feof(f)) { double fx, fy, fz, fvx, fvy, fvz, ft, fsx, fsy, fsz, fp; double dummy; int ret; char Buffer[1024]; ret = fscanf(f, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", &fx, &fy, &fz, &fvx, &fvy, &fvz, &ft, &fsx, &fsy, &fsz, &fp, &dummy); if(ret == EOF) break; if(ret < 11) { fgets(Buffer, 1024, f); continue; } else { long j; j = (long)i; if (s_block>=block_size) { s_block = 0; s = (double*)realloc(s, (long)(i+block_size)*11*sizeof(double)); if(!s) { fprintf(stderr, "Source_file: Error: Out of memory!\n"); exit(1); } } s[11*j+0] = fx; s[11*j+1] = fy; s[11*j+2] = fz; s[11*j+3] = fvx; s[11*j+4] = fvy; s[11*j+5] = fvz; s[11*j+6] = ft; s[11*j+7] = fsx; s[11*j+8] = fsy; s[11*j+9] = fsz; s[11*j+10] = fp; i++; s_block++; } } /* end while */ fclose(f); *size=i; if (i == 0) return(NULL); s = (double*)realloc(s, (long)(i+1)*11*sizeof(double) ); if(!s) { fprintf(stderr, "Source_file: Error: Out of memory!\n"); exit(1); } return (s); } double *source; double length, pos; int rep; char FileType[32]; %} INITIALIZE %{ struct stat stfile; long filesize, i, nelements; FILE *f; length=0; rep =0; source=NULL; strcpy(FileType,""); if (repeat_count != 0) { /* Open neutron input text file. */ if(input) source = read_s_file(input, &length); if(length == 0 || source == NULL) { stat(input,&stfile); filesize = stfile.st_size; f = fopen(input, "r"); /* must exist else exit(-1) in read_s_file */ /* try to read Vitess files */ if (fmod(filesize, sizeof(Neutron)) == 0) { strcpy(FileType, "Vitess"); nelements = (long)(filesize/sizeof(Neutron)); source = (double*)malloc(filesize); if (source==NULL || !fread(source, sizeof(Neutron), nelements, f)) { fprintf(stderr,"Source_file: error reading %i elements in Vitess file '%s'\n", nelements, input); exit(-1); } length = (double)nelements; } else { /* try to read float bin files */ if (fmod(filesize, sizeof(float)) ==0) { strcpy(FileType, "float"); nelements = (long)(filesize/sizeof(float)); source = (double*)malloc(filesize); if (source==NULL || !fread(source, sizeof(float), nelements, f)) { fprintf(stderr,"Source_file: error reading %i elements in float file '%s'\n", nelements, input); exit(-1); } length = (double)nelements/12; } } fclose(f); } else strcpy(FileType, "text"); if (length == 0) { fprintf(stderr,"Source_file: Can not read neutron events from %s file '%s'\n", FileType, (long)length, input); exit(-1); } printf("Source_file: Read %i neutron events from %s file '%s'\n", (long)length, FileType, input); pos = 0; mcset_ncount(length*repeat_count); } %} TRACE %{ if (repeat_count) { if (pos >= length) { rep++; pos = 0; } if (rep > repeat_count) ABSORB; else { long i; i = (long)pos; if (!strcmp(FileType, "Vitess")) { Neutron neu; Neutron *s; double v; s=(Neutron*)source; vitess2mcstas(s[i], &x, &y, &z, &vx, &vy, &vz, &t, &sx, &sy, &sz, &p); } else { if (!strcmp(FileType, "text")) { /* &x, &y, &z, &vx, &vy, &vz, &t, &sx, &sy, &sz, &p */ double *s; s = (double*)source; x = s[11*i+0] ; y = s[11*i+1] ; z = s[11*i+2]; vx = s[11*i+3] ; vy = s[11*i+4] ; vz = s[11*i+5]; t = s[11*i+6] ; sx = s[11*i+7] ; sy = s[11*i+8] ; sz = s[11*i+9]; p = s[11*i+10] ; } else { /* &x, &y, &z, &vx, &vy, &vz, &t, &sx, &sy, &sz, &p, &p2 */ float *s; s = (float*)source; x = s[12*i+0] ; y = s[12*i+1] ; z = s[12*i+2]; vx = s[12*i+3] ; vy = s[12*i+4] ; vz = s[12*i+5]; t = s[12*i+6] ; sx = s[12*i+7] ; sy = s[12*i+8] ; sz = s[12*i+9]; p = s[12*i+10] ; } } pos++; } SCATTER; } %} FINALLY %{ if(source) free(source); %} MCDISPLAY %{ /* 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); %} END