User and Programmers’ Guide to the X Ray-Tracing Package McXtrace, version 3.8.6

6.4  Writing instrument definitions - complex arrangements and syntax

In this section, we describe some additional ways to build instruments using groups, code extension, conditions, loops and duplication of components.

As a summary, the nearly complete grammar definition for component instances within the instrument TRACE section is:

{SPLIT} COMPONENT name = comp(parameters) {WHEN condition}
  AT (...) [RELATIVE [reference|PREVIOUS] | ABSOLUTE]
  {ROTATED {RELATIVE [reference|PREVIOUS] | ABSOLUTE} }
  {GROUP group_name}
  {EXTEND C_code}
  {JUMP [reference|PREVIOUS|MYSELF|NEXT] [ITERATE number_of_times | WHEN condition] }

6.4.1  Embedding instruments in instruments TRACE

The %include insertion mechanism may be used within the TRACE section, in order to concatenate instruments. This way, each DECLARE, INITIALIZE, SAVE, and FINALLY C blocks, as well as instrument parameters from each part are catenated. The TRACE section is made of inserted COMPONENTS from each part. In principle, it then possible to write an instrument as:

DEFINE catenated()
TRACE

%include "part1.instr"
%include "part2.instr"

END

where each inserted instrument is a valid full instrument. In order to avoid some components to be duplicated - e.g. Sources from each part - a special syntax in the TRACE section

INSTRUMENT COMPONENT a=...

marks the component a as removable when inserted. In principle, inserted instruments may themselves use %include.

6.4.2  Component extensions - EXTEND

It is sometimes desirable to slightly modify an existing component of the McXtrace library. One would usually make a copy of the component, and extend the code of its TRACE section. McXtrace provides an easy way to change the behaviour of existing components in an instrument definition without duplicating files, using the EXTEND modifier

EXTEND
%{
…C code executed after the component TRACE section …
%}

The embedded C code is appended to the component TRACE section, and all its internal variables (as well as all the DECLARE instrument variables, except instrument parameters) may be used. To use instrument parameters, you should copy them into global variables in the DECLARE instrument section, and refer to these latter. This component declaration modifier is of course optional. You will find usage examples in the Component manual[BK+12].

6.4.3  Mutually exclusive components in parallell - GROUP

In some configurations it is necessary to position one or more groups of components, nested, in parallel, or overlapping. One example is a multiple crystal monochromator. One would then like the x-ray to interact with one of the components of the group and then continue.

In order to handle such arrangements without removing x-rays, groups are defined by the GROUP modifier (after the AT-ROTATED positioning):

GROUP name

to all involved component declarations. All components of the same named group are tested one after the other, until one of them interacts (uses the SCATTER macro). The selected component acts on the x-ray, and the rest of the group is skipped. Such groups are thus exclusive (only one of the elements is active).

Within a GROUP, all EXTEND sections of the group are executed. In order to discriminate components that are active from those that are skipped, one may use the SCATTERED flag, which is set to zero when entering each component or group, and incremented when the x-ray is SCATTERed, as in the following example

COMPONENT \(\textit {name0} = \textit {comp}(p_1 = e_1, p_2 = e_2, \ldots )\)
AT \((0,0,0)\) ABSOLUTE
COMPONENT \(\textit {name1} = \textit {comp}(\ldots )\) AT \((...)\) ROTATED \((...)\)
GROUP GroupName EXTEND
%{
if (SCATTERED) printf("I scatter");
else printf("I do not scatter");
%}
COMPONENT \(\textit {name2} = \textit {comp}(\ldots )\) AT \((...)\) ROTATED \((...)\)
GROUP GroupName

Components name1 and name2 are at the same position. If the first one intercepts the x-ray (and has a SCATTER within its TRACE section), the SCATTERED variable becomes true, the code extension will result in printing ”I scatter”, and the second component will be skipped. Thus, we recommend to make use of the SCATTER keyword each time a component ’uses’ the x-ray (scatters, detects, …) within component definitions (see section 6.5). Also, the components to be grouped should be consecutive in the TRACE section of the instrument, and the GROUPed section should not contain components which are not part of the group.

Note that a GROUP construct is not applicable to a situation where an x-ray which has interacted (SCATTERed) with one component in the group, may interact with another. In this case a more complex arrangement is needed. See [Wil+11] for a description of how to do this in McStas. This is approach is directly applicable in McXtrace without modification.

Combining EXTEND, GROUP and WHEN can result in unexpected behaviour. Please read the related warning at the end of section 6.4.5.

6.4.4  Duplication of component instances - COPY

Often, one has a set of similar component instances in an instrument. These could be e.g. a set of identical monochromator blades, or a set of detectors. Together with JUMPs (see below), there is a way to copy a component instance, duplicating a parameter set, as well as any EXTEND, GROUP, JUMP and WHEN keyword. Position (AT) and rotation (ROTATED) specification must be explicitely entered in order to avoid component overlap.

The syntax for instance copy is

COMPONENT name = COPY(instance_name)

where instance_name is the name of a preceeding component instance in the instrument. It may be ’PREVIOUS’ as well.

If you would like to change only some of the parameters in the instance copy, you may write, e.g.:

COMPONENT name = COPY(instance_name)(par1=0, par2=1)

which will override the original instance parameter values. In case EXTEND, GROUP, JUMP and WHEN keywords are defined for the copied instance, these will override the settings from the copied instance.

In the case where there are many duplicated components all originating from the same instance, there is a mechanism for automating copied instance names:

COMPONENT COPY(root_name) = COPY(instance_name)

will append a unique number to root_name, to avoid name conflicts. As a side effect, referring to this component instance (for e.g. further positioning) is not straight forward as the name is determined by McXtrace and does not depend completely on the user’s choice, even though the PREVIOUS keyword may still be used. We thus recommend to use this naming mechanism only for components which should not be refered to in the instrument.

This automatic naming may be used anywhere in the TRACE section of the instrument, so that all components which do not need further referral may be labeled as COPY(Origin).

As an example, we show how to have a set of three equivalent pinholes (Slits). Only the first instance of the Slit component is defined explicitly, whereas following instances are copies of that definition. The instance names of Slit components are set automatically.

COMPONENT S_in = Arm() AT (...)

COMPONENT S_1  = Slit(radius=0.1)
  AT (0,0,0) RELATIVE PREVIOUS

COMPONENT COPY(S_1)  = COPY(S_1)
  AT (0,0,d) RELATIVE PREVIOUS

COMPONENT COPY(S_1)  = COPY(S_1)
  AT (0,0,d) RELATIVE PREVIOUS
...
COMPONENT S_Out = Arm() AT (0,0,d) RELATIVE PREVIOUS

6.4.5  Conditional components - WHEN

One of the most useful features of the extended McXtrace syntax is the conditional WHEN modifier. This optional keyword comes before the AT-ROTATED positioning. It basically enables the component only when a given condition is true (non null).

COMPONENT \(\textit {name} = \textit {comp}(p_1 = e_1, p_2 = e_2, \ldots )\) WHEN (condition)

The condition has the same scope as the EXTEND modifier, i.e. may use component internal variables as well as all the DECLARE instrument variables.

Usage examples could be to have specific monitors only sensitive to selected processes, or to have components which are only present under given circumstances (e.g. removable filter or radial collimator), or to select a sample among a set of choices.

In the following example, an EXTEND block sets a condition when a scattering event is encoutered, and the following monitor is then activated.

COMPONENT Sample = V_sample(...) AT ...
  EXTEND
  %{
    if (SCATTERED) flag=1; else flag=0;
  %}

COMPONENT MyMon = Monitor(...) WHEN (flag==1)
  AT ...

The WHEN keyword only applies to the TRACE section and related EXTEND blocks of instruments/components. Other sections (INITIALIZE, SAVE, MCDISPLAY, FINALLY) are executed independently of the condition. As a side effect, the 3D view of the instrument (mxdisplay) will show all components as if all conditions were true.

A usage example of the WHEN keyword can be found in the
X-ray site/ESRF/ESRF_ID11 instrument from the mxgui, where the source model may be chosen by an external parameter.

The WHEN keyword is compatible with GROUP, and thus may be used to activate/deactivate members in a GROUP just like non-grouped components. Combining WHEN, EXTEND and GROUP can result in unexpected behaviour, please use them with caution! As an example, let a GROUP of components all have the same WHEN condition. If the condition is false, none of the elements SCATTER, meaning that all x-rays will be ABSORBed. As a solution to this problem, we propose to include an EXTENDed Arm component in the GROUP, but with the opposite WHEN condition and a SCATTER keyword in the EXTEND section. This means that when none of the other GROUP elements are present, the Arm will be present and SCATTER.

6.4.6  Component loops and non sequential propagation - JUMP

There are situations in which one would like to repeat a given component many times, or under a given condition. The JUMP modifier is meant for that and should be mentioned after the positioning, GROUP and EXTEND. This breaks the sequential propagation along components in the instrument description. There may be more than one JUMP per component instance.

The jump may depend on a condition:

COMPONENT \(\textit {name} = \textit {comp}(p_1 = e_1, p_2 = e_2, \ldots )\) AT (...) JUMP reference WHEN condition

in which case the instrument TRACE will jump to the reference when condition is true.

The reference may be an instance name, as well as PREVIOUS, PREVIOUS(\(n\)), MYSELF, NEXT, and NEXT(\(n\)), where \(n\) is the index gap to the target either backward (PREVIOUS) or forward (NEXT), so that PREVIOUS(1) is PREVIOUS and NEXT(1) is NEXT. MYSELF means that the component will be iterated as long as the condition is true. This may be a way to handle multiple scattering, if the component has been designed for that.

The jump arrives directly inside the target component, in the local coordinate system (i.e. without applying the AT and ROTATED keywords). In order to better control the target positions, it is required that, except for looping MYSELF, the target component type should be an Arm. Similarly to the WHEN modifier (see section 6.4.5), JUMP only applies within the TRACE section of the instrument definition. Other sections (INITIALIZE, SAVE, MCDISPLAY, FINALLY) are exectuted independently of the jump. As a side effect, the 3D view of the instrument mxdisplay will show components as if there was no jump. This means that in the following example, the very long mirror 3D view only shows a single mirror element.

It is not recommended to use the JUMP inside GROUPs, as the JUMP condition/counter applies to the component instance within its group.

We would like to emphasize the potential errors originating from such jumps. Indeed, imbricating many jumps may lead to situations were it is difficult to understand the flow of the simulation. We thus recommend the usage of JUMPs only for experienced and cautious users.

6.4.7  Enhancing statistics reaching components - SPLIT

The following method applies when the incoming x-ray event distribution is considered to be representative of the real beam, but x-rays are lost in the course of propagation (with low efficiency processes, absorption, etc). Then, one may think that it’s a pity to have so few events reaching the ’interesting’ part of the beamline (usually close to the end of the instrument description). If some components make extensive use of random numbers (MC choices), they shuffle this way the distributions, so that identical incoming events will not produce the same outgoing event. In this case, you may want to use a technique known as stratified sampling (see chapter 4) which in McXtrace is implemented through the SPLIT keyword with the syntax

SPLIT \(r\) COMPONENT \(\textit {name} = \textit {comp}(\ldots )\)

where the optional number \(r\) specifies the number of repetitions for each event. Default is \(r=10\). Each x-ray event reaching component name will be repeated \(r\) times with a weight divided by \(r\), so that in practice the number of events for the remaining part of the simulation (down to the END), will potentially have more statistics. This is only true if following components (and preferably component name) use random numbers. You may use this method as many times as you wish in the same instrument, e.g. at the monochromator and sample position. This keyword can also be used within a GROUP. The efficiency is roughly \(r\) raised to the number of occurences in the instrument, so that enhancing two components with the default \(r=10\) will produce an enhancement effect of \(100\) wrt. the number of events at the end. The execution time will increase but at a slower rate than the statistical quality, provided that the above criteria are met. If the instrument makes use of global variables - e.g. in conjunction with a WHEN or User Variable monitoring (see Monitor_nD) - you should take care that these variables are set properly for each SPLIT loop, which usually means that they must be reset inside the SPLITed section and assigned/used further on.