User and Programmers Guide to the Neutron Ray-Tracing Package McStas, version 3.8.6

4.3  Writing instrument definitions

The purpose of the instrument definition is to specify a sequence of components, along with their position and parameters, which together make up an instrument. Each component is given its own local coordinate system, the position and orientation of which may be specified by its translation and rotation relative to another component. An example is given in section 4.3.13 and some additional examples of instrument definitions can be found on the McStas web-page [Mcs] and in the example directory.

As a summary, the usual grammar for instrument descriptions is

1DEFINE INSTRUMENT name(parameters) 
2DECLARE C_code 
3INITIALIZE C_code 
4TRACE components 
5{FINALLY C_code} 
6END
 
7

4.3.1  The instrument definition head

1DEFINE INSTRUMENT name (a_1, a_2, ...)
 
2

This marks the beginning of the definition. It also gives the name of the instrument and the list of instrument parameters. Instrument parameters describe the configuration of the instrument, and usually correspond to setting parameters of the components, see section 4.5. A motor position is a typical example of an instrument parameter. The input parameters of the instrument constitute the input that the user (or possibly a front-end program) must supply when the generated simulation is started.

By default, the parameters will be floating point numbers, and will have the C type double (double precision floating point). The type of each parameter may optionally be declared to be int for the C integer type or char * for the C string type. The name string may be used as a synonym for char *, and floating point parameters may be explicitly declared using the name double. The following example illustrates all possibilities:

1DEFINE INSTRUMENT test(d1, double d2, int i, char *s1, string s2)
 
2

Here d1 and d2 will be floating point parameters of C type double, i will be an integer parameter of C type int, and s1 and s2 will be string parameters of C type char *. The parameters of an instrument may be given default values. Parameters with default values are called optional parameters, and need not be given an explicit value when the instrument simulation is executed. When executed without any parameter value in the command line (see section 3.4), the instrument asks for all parameter values, but pressing the Return key selects the default value (if any). When used with at least one parameter value in the command line, all non specified parameters will have their value set to the default one (if any). A parameter is given a default value using the syntax “param= value”. For example

1DEFINE INSTRUMENT test(d1= 1, string s2="hello")
 
2

Here d1 and d2 are optional parameters and if no value are given explicitly, “1” and “hello” will be used.

Optional parameters can greatly increase the convenience for users of instruments for which some parameters are seldom changed or of unclear signification to the user. Also, if all instrument parameters have default values, then the simple command mcdisplay test.instr will show the instrument view without requesting any other input, which is usually a good starting point to study the instrument design.

A numeric instrument parameter may optionally carry a documentation-only unit annotation, using a slash followed by a quoted string:

1DEFINE INSTRUMENT test(double lambda/"AA" = 4.0, double L2/"m")
 
2

The unit string is purely informational (it is not converted or checked at run time); it is picked up by mcdoc and mcgui to annotate the parameter in generated documentation and entry dialogs, so it is good practice to use it for any parameter whose unit is not obvious from its name.

4.3.2  The DEPENDENCY line

1DEPENDENCY "-lLIB1 -lLIB2 .."
 
2

If you make use of external library calls in your instrument, you may indicate the dependency list to be used for the compilation of the instrument, as a single DEPENDENCY keyword and a string argument, all on a single line such as:

1DEPENDENCY "-lgsl -lgslcblas"
 
2

The concatenation of all found dependencies from the instrument, but also from all used components, will be printed to the terminal (stdout) as

1CFLAGS=-lgsl -lgslcblas
 
2

This line is interpreted by mcrun (see section 3.5.2) and passed to the compiler. It must be indicated just before the DECLARE section. This line is optional, and if omitted you may need to manually link the instrument with the libraries and add the proper library names to the MCSTAS_CFLAGS or CFLAGS environment variables.

4.3.3  The SEARCH line

1SEARCH "path/to/extra/components"
 
2

Appends an additional directory to the component/instrument search path (complementing the -I command line switch, see section 3.3.2). This is useful for instrument files that depend on a component library kept outside the standard McStas installation, without requiring users to remember to pass -I manually. Like DEPENDENCY, SEARCH may appear at instrument level (before DECLARE) or inside a component definition.

A second form computes the path (or a newline-separated list of paths) by running an external command:

1SEARCH SHELL "pkg-config --variable=compdir my-neutron-lib"
 
2

Each line printed by the command on its standard output is added as a search directory. See also SHELL below.

4.3.4  The SHELL line

1SHELL "command to execute"
 
2

Executes an arbitrary shell command before code generation (i.e. as mcstas parses the file), printing its output to the terminal. This may be used for instance to auto-generate a data file or a piece of included C code as part of the build process. The compiler aborts if the command returns a non-zero exit status. Use with caution, since this executes arbitrary code on the machine running mcstas– do not %include untrusted instrument files containing SHELL lines.

4.3.5  The DECLARE section

1DECLARE 
2%{ 
3   // C declarations of global variables etc. ... 
4%}
 
5

This gives C declarations that may be referred to in the rest of the instrument definition. A typical use is to declare global variables or small functions that are used elsewhere in the instrument. The %include ’’file’’ keyword may be used to import a specific component definition or a part of an instrument. Variables defined here are global, and may conflict with internal McStas variables, specially symbols like x,y,z,sx,sy,sz,vx,vy,vz,t and generally all names starting with mc should be avoided. If you can not compile the instrument, this may be the reason. The DECLARE section is optional.

4.3.6  The USERVARS section

1USERVARS 
2%{ 
3  double my_per_neutron_flag; 
4%}
 
5

USERVARS declares additional fields that are appended to every neutron ray’s state (alongside the built-in x,y,z,vx,vy,vz,t,sx,sy,sz,p), rather than being ordinary global DECLARE variables. It may appear at instrument level (as here) or inside a component definition, and both Instrument- and Component-level USERVARS end up as fields of the same per-neutron state struct.

This matters for two reasons:

USERVARS fields are referred to directly by name from any TRACE, EXTEND, WHEN, or MCDISPLAY code, exactly like the built-in neutron state fields. The section is optional, and may be used at both instrument and component level in the same simulation.

4.3.7  The INITIALIZE section

1INITIALIZE 
2%{ 
3// C initializations. 
4%}
 
5

This gives code that is executed when the simulation starts. This section is optional. Instrument setting parameters may be modified in this section (e.g. doing tests or automatic settings).

4.3.8  The NEXUS extension

The NeXus format [Nex] requires to link the simulation to additional libraries (HDF and NeXus) which must have been pre-installed. Preferably, McStas should have been installed with the ./configure --with-nexus on Unix/Linux systems. To activate the NeXus output, the compilation of the instrument must be done with flag -DUSE_NEXUS -lNeXus. The resulting executable is no longer portable.

The default NeXus format is HDF5 with compression.

You may choose the name of the output file with the -f filename option from the instrument executable or mcrun (see Sections 3.4, 3.5.2 and Table 3.2).

Then, the output format is chosen as usual with the --format=NeXus option when launching the simulation. All output files are stored in the output filename, as well as the instrument description itself. Other formats are still available. When run on a distributed system (e.g. MPI), detectors are gathered, but list of events (see e.g. component Virtual_output) are stored as one data set per node.

4.3.9  The TRACE section

As a summary, the usual grammar for component instances within the instrument TRACE section is

1COMPONENT name = comp(parameters) 
2  AT (...) [RELATIVE [reference|PREVIOUS] | ABSOLUTE] 
3 {ROTATED  {RELATIVE [reference|PREVIOUS] | ABSOLUTE} }
 
4

The TRACE keyword starts a section giving the list of components that constitute the instrument. Components are declared like this:

1COMPONENT name = comp(p_1 = e_1, p_2 = e_2, ...)
 
2

This declares a component named name that is an instance of the component definition named comp. The parameter list gives the setting and definition parameters for the component. The expressions \(e_1, e_2, \ldots \) define the values of the parameters. For setting parameters arbitrary ISO-C expressions may be used, while for definition parameters only constant numbers, strings, names of instrument parameters, or names of C identifiers are allowed (see section 4.5.1 for details of the difference between definition and setting parameters). To assign the value of a general expression to a definition parameter, it is necessary to declare a variable in the DECLARE section, assign the value to the variable in the INITIALIZE section, and use the variable as the value for the parameter.

The McStas program takes care to rename parameters appropriately in the output so that no conflicts occur between different component definitions or between component and instrument definitions. It is thus possible (and usual) to use a component definition multiple times in an instrument description.

Beware about variable type conversion when setting numerical parameter values, as in p1=12/1000. In this example, the parameter p1 will be set to 0 as the division of the two integers is indeed 0. To avoid that, use explicitly floating type numbers as in p1=12.0/1000.

The compiler mcstas will automatically search for a file containing a definition of the component if it has not been declared previously. The definition is searched for in a file called “name.comp”. See section 3.3.2 for details on which directories are searched. This facility is often used to refer to existing component definitions in standard component libraries. It is also possible to write component definitions in the main file before the instrument definitions, or to explicitly read definitions from other files using %include (not within embedded C blocks).

The physical position of a component is specified using an AT modifier following the component declaration:

1  AT (x,y,z) RELATIVE name
 
2

This places the component at position \((x,y,z)\) in the coordinate system of the previously declared component name. Placement may also be absolute (not relative to any component) by writing

1  AT (x,y,z) RELATIVE ABSOLUTE
 
2

Any C expression may be used for \(x\), \(y\), and \(z\). The AT modifier is required. Rotation is achieved similarly by writing

1  ROTATED (phi_x,phi_y,phi_z) RELATIVE name
 
2

This will result in a coordinate system that is rotated first the angle \(\phi _x\) (in degrees) around the \(x\) axis, then \(\phi _y\) around the \(y\) axis, and finally \(\phi _z\) around the \(z\) axis. Rotation may also be specified using ABSOLUTE rather than RELATIVE. If no rotation is specified, the default is \((0,0,0)\) using the same relative or absolute specification used in the AT modifier. We strongly recommend to apply all rotations of an instrument description on Arm class components only, acting as goniometers, and position the optics on top of these. This usually makes it much easier to orient pieces of the instrument, and avoid positioning errors.

The position of a component is actually the origin of its local coordinate system. Usually, this is used as the input window position (e.g. for guide-like components), or the center position for cylindrical/spherical components.

The PREVIOUS keyword is a generic name to refer to the previous component in the simulation. Moreover, the PREVIOUS(n) keyword will refer to the \(n\)-th previous component, starting from the current component, so that PREVIOUS is equivalent to PREVIOUS(1). This keyword should be used after the RELATIVE keyword, but not for the first component instance of the instrument description.

1AT (x,y,z) RELATIVE PREVIOUS 
2ROTATED (phi_x, phi_y, phi_z) RELATIVE PREVIOUS(2)
 
3

Invalid PREVIOUS references will be assumed to be absolute placement.

The order and position of components in the TRACE section does not allow components to overlap, except for particular cases (see the GROUP keyword below). Indeed, many components of the McStas library start by propagating the neutron event to the beginning of the component itself. Anyway, when the corresponding propagation time is found to be negative (i.e. the neutron ray is already after or aside the component, and has thus passed the ’active’ position), the neutron event is ABSORBed, resulting in a zero intensity and event counts after a given position. The number of such removed neutrons is indicated at the end of the simulation. Getting such warning messages is an indication that either some components overlap, or some neutrons are getting outside of the simulation, for instance this usually happens after a monochromator, as the non-reflected beam is indeed lost. A special warning appears when no neutron ray has reached some part of the simulation. This is usually the sign of either overlapping components or a very low intensity.

For experienced users, we recommend as well the usage of the WHEN and EXTEND keywords, as well as other syntax extensions presented in section 4.4 below.

4.3.10  The SAVE section

1SAVE 
2%{ 
3  // C code to execute each time a temporary save is required... 
4%}
 
5

This gives code that will be executed when the simulation is requested to save data, for instance when receiving a USR2 signal (on Unix systems), or using the Progress_bar component with intermediate savings. It is also executed when the simulation ends. This section is optional.

4.3.11  The FINALLY section

1FINALLY 
2%{ 
3   // C code to execute at end of simulation 
4%}
 
5

This gives code that will be executed when the simulation has ended. When existing, the SAVE section is first executed. The FINALLY section is optional. A simulation may be requested to end before all neutrons have been traced when receiving a TERM or INT signal (on Unix systems), or with Control-C, causing code in FINALLY to be evaluated.

4.3.12  The end of the instrument definition

The end of the instrument definition must be explicitly marked using the keyword

1END

4.3.13  Code for the instrument vanadium_example.instr

A commented instrument definition taken from the examples directory is here shown as an example of the use of McStas.