/******************************************************************************* * McStas, neutron ray-tracing package * Copyright 1997-2002, All rights reserved * Risoe National Laboratory, Roskilde, Denmark * Institut Laue Langevin, Grenoble, France * * Component: Res_monitor * * %I * Written by: Kristian Nielsen * Date: 1999 * Version: $Revision: 1.24 $ * Origin: Risoe * Release: McStas 1.6 * Modified by: EF, 16th Apr 2003: imported from Monitor_nD to enable many shapes * * Monitor for resolution calculations * * %D * A single detector/monitor, used together with the Res_sample component to * compute instrument resolution functions. Outputs a list of neutron * scattering events in the sample along with their intensities in the * detector. The output file may be analyzed with the mcresplot front-end. * * Example: Res_monitor(filename="Output.res", res_sample_comp=RSample, * xmin=-0.1, xmax=0.1, ymin=-0.1, ymax=0.1) * * Setting the monitor geometry. * The optional parameter 'options' may be set as a string with the * following keywords. Default is rectangular ('square'): * box Box of size xwidth, yheight, zthick * cylinder To get a cylindrical monitor * (diameter is xwidth, height is yheight). * banana Same as cylinder, without top/bottom, * on restricted angular area * disk Disk flat xy monitor. radius is xwidth. * sphrere To get a spherical monitor (e.g. a 4PI) * (diameter is xwidth). * square Square flat xy monitor (xwidth, yheight) * * %P * INPUT PARAMETERS: * * xmin: Lower x bound of detector opening (m) * xmax: Upper x bound of detector opening (m) * ymin: Lower y bound of detector opening (m) * ymax: Upper y bound of detector opening (m) * zmin: Lower z bound of detector opening (m) * zmax: Upper z bound of detector opening (m) * filename: Name of output file. If unset, use automatic name (string) * res_sample_comp: Name of Res_sample component in the instrument * definition [no quotes] * bufsize: Number of events to store. Use 0 to store all [1] * * OPTIONAL PARAMETERS (derived from Monitor_nD) * * xwidth: (m) Width/diameter of detector (x) * yheight: (m) Height of detector (y) * zthick: (m) Thichness of detector (z) * options: (str) String that specifies the geometry of the monitor
* * OUTPUT PARAMETERS: * * DEFS: structure containing Monitor_nD Defines (struct) * Vars: structure containing Monitor_nD variables (struct) * buffer_index: number of recorded events (long) * * %E *******************************************************************************/ DEFINE COMPONENT Res_monitor DEFINITION PARAMETERS (filename=0, options=0, res_sample_comp) SETTING PARAMETERS (xwidth=.1, yheight=.1, zthick=0, xmin=0, xmax=0, ymin=0, ymax=0, zmin=0, zmax=0, bufsize=10000) /* these are protected C variables */ OUTPUT PARAMETERS (DEFS, Vars, buffer_index) 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; long buffer_index=0; %} INITIALIZE %{ int i; char tmp[1024]; strcpy(Vars.compcurname, NAME_CURRENT_COMP); if (options != NULL) strncpy(tmp, options, 1024); else strcpy(tmp, ""); if (strstr(tmp, "list")) exit(fprintf(stderr, "Res_monitor: %s: Error: Only use geometry keywords (remove list from 'option').\n", NAME_CURRENT_COMP)); if (!bufsize) sprintf(Vars.option, "%s list all, x vx sx y vy sy z vz sz t ", tmp); else sprintf(Vars.option, "%s list=%f, x vx sx y vy sy z vz sz t ", tmp, bufsize); Monitor_nD_Init(&DEFS, &Vars, xwidth, yheight, zthick, xmin,xmax,ymin,ymax,zmin,zmax); if (Vars.Coord_Number != 10) exit(fprintf(stderr,"Res_monitor: %s: Error: Invalid number of variables to monitor (%d).\n", NAME_CURRENT_COMP, Vars.Coord_Number+1)); /* set the labels */ /* we have to record ki_x ki_y ki_z kf_x kf_y kf_z x y z p_i p_f */ strcpy(tmp,"ki_x"); strcpy(Vars.Coord_Label[0],tmp);strcpy(Vars.Coord_Var[0],tmp); strcpy(tmp,"ki_y"); strcpy(Vars.Coord_Label[1],tmp);strcpy(Vars.Coord_Var[1],tmp); strcpy(tmp,"ki_z"); strcpy(Vars.Coord_Label[2],tmp);strcpy(Vars.Coord_Var[2],tmp); strcpy(tmp,"kf_x"); strcpy(Vars.Coord_Label[3],tmp);strcpy(Vars.Coord_Var[3],tmp); strcpy(tmp,"kf_y"); strcpy(Vars.Coord_Label[4],tmp);strcpy(Vars.Coord_Var[4],tmp); strcpy(tmp,"kf_z"); strcpy(Vars.Coord_Label[5],tmp);strcpy(Vars.Coord_Var[5],tmp); strcpy(tmp,"x"); strcpy(Vars.Coord_Label[6],tmp);strcpy(Vars.Coord_Var[6],tmp); strcpy(tmp,"y"); strcpy(Vars.Coord_Label[7],tmp);strcpy(Vars.Coord_Var[7],tmp); strcpy(tmp,"z"); strcpy(Vars.Coord_Label[8],tmp);strcpy(Vars.Coord_Var[8],tmp); strcpy(tmp,"p_i"); strcpy(Vars.Coord_Label[9],tmp);strcpy(Vars.Coord_Var[9],tmp); strcpy(tmp,"p_f"); strcpy(Vars.Coord_Label[10],tmp);strcpy(Vars.Coord_Var[10],tmp); if (filename != NULL) strncpy(Vars.Mon_File, filename, 128); %} TRACE %{ double t0 = 0; double t1 = 0; int intersect = 0; 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)); } 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 */ } /* total intensity received */ Vars.Nsum++; Vars.psum += p; Vars.p2sum += p*p; /* Now fetch data from the Res_sample. */ if(p && (!bufsize || buffer_indexpi != 0) { Vars.cp = s->ki_x; Vars.cx = s->ki_y; Vars.cvx = s->ki_z; Vars.csx = s->kf_x; Vars.cy = s->kf_y; Vars.cvy = s->kf_z; Vars.csy = s->rx; Vars.cz = s->ry; Vars.cvz = s->rz; Vars.csz = s->pi; Vars.ct = p/s->pi; Monitor_nD_Trace(&DEFS, &Vars); } /* if s->pi */ SCATTER; } /* if p */ } /* end if intersection */ %} SAVE %{ /* save results, but do not free pointers */ Monitor_nD_Save(&DEFS, &Vars); %} FINALLY %{ /* free pointers */ Monitor_nD_Finally(&DEFS, &Vars); %} MCDISPLAY %{ Monitor_nD_McDisplay(&DEFS, &Vars); %} END