/******************************************************************************* * * McStas, neutron ray-tracing package * Copyright 1997-2002, All rights reserved * Risoe National Laboratory, Roskilde, Denmark * Institut Laue Langevin, Grenoble, France * * Component: Slit * * %I * Written by: Kim Lefmann and Henrik M. Roennow * Date: June 16, 1997 * Origin: Risoe * * Rectangular/circular slit * * %D * A simple rectangular or circular slit. You may either * specify the radius (circular shape), or the rectangular bounds. * No transmission around the slit is allowed. * * Example: Slit(xmin=-0.01, xmax=0.01, ymin=-0.01, ymax=0.01) * Slit(xwidth=0.02, yheight=0.02) * Slit(radius=0.01) * * The Slit will issue a warning if run as "closed" * * %P * INPUT PARAMETERS * * radius: [m] Radius of slit in the z=0 plane, centered at Origin * xmin: [m] Lower x bound * xmax: [m] Upper x bound * ymin: [m] Lower y bound * ymax: [m] Upper y bound * xwidth: [m] Width of slit. Overrides xmin,xmax if they are unset. * yheight: [m] Height of slit. Overrides ymin,ymax if they are unset. * * * * %E *******************************************************************************/ DEFINE COMPONENT Slit DEFINITION PARAMETERS () SETTING PARAMETERS (xmin=UNSET, xmax=UNSET, ymin=UNSET, ymax=UNSET, radius=UNSET, xwidth=UNSET, yheight=UNSET) OUTPUT PARAMETERS () /* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */ SHARE %{ void slit_print_if(int condition, char* level, char* message, char* component){ if (condition) fprintf(stderr, "Slit: %s: %s: %s\n", component, level, message); } void slit_error_if(int condition, char* message, char* component){ slit_print_if(condition, "Error", message, component); if (condition) exit(-1); } void slit_warning_if(int condition, char* message, char* component){ slit_print_if(condition, "Warning", message, component); } %} DECLARE %{ char isradial; %} INITIALIZE %{ if (is_unset(radius)){ isradial=0; if (all_set(3, xwidth, xmin, xmax)){ slit_error_if(xwidth != xmax - xmin, "specifying xwidth, xmin and xmax requires consistent parameters", NAME_CURRENT_COMP); } else { slit_error_if(is_unset(xwidth) && any_unset(2, xmin, xmax), "specify either xwidth or xmin & xmax", NAME_CURRENT_COMP); } if (all_set(3, yheight, ymin, ymax)){ slit_error_if(yheight != ymax - ymin, "specifying yheight, ymin and ymax requires consistent parameters", NAME_CURRENT_COMP); } else { slit_error_if(is_unset(yheight) && any_unset(2, ymin, ymax), "specify either yheight or ymin & ymax", NAME_CURRENT_COMP); } if (is_unset(xmin)) { // xmax also unset but xwidth *is* set xmax = xwidth/2; xmin = -xmax; } if (is_unset(ymin)) { // ymax also unset but yheight *is* set ymax = yheight/2; ymin = -ymax; } slit_warning_if(xmin == xmax || ymin == ymax, "Running with CLOSED rectangular slit - is this intentional?", NAME_CURRENT_COMP); } else { isradial=1; slit_error_if(any_set(6, xwidth, xmin, xmax, yheight, ymin, ymax), "specify radius OR width and height parameters", NAME_CURRENT_COMP); slit_warning_if(radius == 0., "Running with CLOSED radial slit - is this intentional?", NAME_CURRENT_COMP); } %} TRACE %{ PROP_Z0; if (!isradial ? (x < xmin || x > xmax || y < ymin || y > ymax) : (x * x + y * y > radius * radius)) ABSORB; else SCATTER; %} MCDISPLAY %{ if (is_unset(radius)) { double xw, yh; xw = (xmax - xmin)/2.0; yh = (ymax - ymin)/2.0; multiline(3, xmin-xw, (double)ymax, 0.0, (double)xmin, (double)ymax, 0.0, (double)xmin, ymax+yh, 0.0); multiline(3, xmax+xw, (double)ymax, 0.0, (double)xmax, (double)ymax, 0.0, (double)xmax, ymax+yh, 0.0); multiline(3, xmin-xw, (double)ymin, 0.0, (double)xmin, (double)ymin, 0.0, (double)xmin, ymin-yh, 0.0); multiline(3, xmax+xw, (double)ymin, 0.0, (double)xmax, (double)ymin, 0.0, (double)xmax, ymin-yh, 0.0); } else { circle("xy",0,0,0,radius); } %} END