McStas / McXtrace INSTRUMENT grammar

This is one of two companion cheat sheets: this file covers .instr instrument files; the companion COMPONENT grammar covers .comp component files. Each is written to stand alone — a little material (the reserved-keyword table, the particle-terminology note, the shared-grammar note) is intentionally duplicated in both. Keywords are case-insensitive but conventionally written in UPPERCASE; identifiers are case-sensitive C identifiers. Sources are listed at the end of the document (§18).

On "McStas" vs "McXtrace" vs "particle": the instrument/component grammar itself — every keyword and syntax rule in this document — is identical between the two codes; it's one shared parser. What differs is the physics carried by the traced entity: McStas traces neutrons, McXtrace traces X-ray photons. This cheat sheet uses the neutral term "particle" throughout for the thing being traced through the instrument, and only calls out "neutron" or "photon" specifically where the two codes' behaviour (not grammar) actually differs — chiefly, the fields making up the particle's state:

McStas (neutron) McXtrace (photon)
Position x, y, z [m] x, y, z [m]
Direction/momentum velocity vx, vy, vz [m/s] wavevector kx, ky, kz [Å⁻¹]
Extra kinematic field phase phi [rad]
Polarization spin sx, sy, sz polarization vector Ex, Ey, Ez
Time t [s] t [s]
Weight p p

USERVARS fields (§4 below) are appended to whichever of these two per-particle state structs applies for the code you're using — the grammar for declaring them is identical.


Notation used for grammar skeletons in this document: [ ... ] marks an element (or whole clause) as optional; ( a | b | c ) marks a required choice among alternatives. Both are meta-notation and never appear literally in a .instr/.comp file. Everything else — including bare { } and, especially, %{ ... %} — is literal syntax: %{ %} is the actual embedded-C-code delimiter, and bare { } shows up as-is in real code (e.g. a vector default like axis={0,1,0}). The two never mean "optional" in this document.

Contents

Contents

1. Instrument file skeleton

DEFINE INSTRUMENT name(parameters)

[SHELL "command"]                    // rare, pre-parse shell command(s)
[DEPENDENCY "linker/compiler flags"] // linker-instructions

DECLARE
%{
  // global C declarations
%}

USERVARS
%{
  double my_per_particle_flag;   // fields appended to every particle's state
%}

INITIALIZE
%{
  // C code run once at simulation start
%}

TRACE
  [SEARCH "extra/search/dir"]    // optional, only valid here (see §3)
  COMPONENT ... AT ...
  COMPONENT ... AT ...
  ...

[SAVE
%{
  // C code run whenever data is (re)saved
%}]

[FINALLY
%{
  // C code run once at simulation end
%}]

END

DECLARE, USERVARS, INITIALIZE, SAVE, and FINALLY are all optional. TRACE and the final END are mandatory.

2. DEFINE INSTRUMENT and its parameters

DEFINE INSTRUMENT test(d1, double d2, int i, char *s1, string s2,
                        d3 = 1, string s4 = "hello",
                        double lambda/"AA" = 4.0, double L2/"m")

3. Top-level instrument keywords (before DECLARE)

SHELL "some command run prior to code generation"
DEPENDENCY " -DSOME_DEFINE -lsome -L/some/lib -I/some/include "

c TRACE SEARCH "/add/a/component/search/directory/" SEARCH SHELL "wget https://some/component/file.comp" COMPONENT Origin = Progress_bar() AT (0,0,0) ABSOLUTE ... SEARCH SHELL "cmd" runs cmd and adds each line of its stdout as a search directory (e.g. pkg-config --variable=compdir my-neutron-lib). This mechanism is used mainly by Greg Tucker's mcstas-antlr infrastructure for BIFROST-style external component repos — it does not appear anywhere in the shipped mcstas-comps/mcxtrace-comps examples trees.

4. DECLARE / USERVARS / INITIALIZE

DECLARE
%{
  double some_global_var;
%}

USERVARS
%{
  double myvar;   // "type varname;" ONLY — no initializers, no multi-declarations
%}

INITIALIZE
%{
  myvar = sqrt(PI*input_var)*rand01();
%}

5. TRACE — the full component-instance grammar

[REMOVABLE] [CPU] [SPLIT [n]] COMPONENT name = comp(parameters) [WHEN condition]
  AT (x,y,z) (RELATIVE (reference | PREVIOUS[(n)]) | ABSOLUTE)
  [ROTATED (rx,ry,rz) (RELATIVE (reference | PREVIOUS[(n)]) | ABSOLUTE)]
  [GROUP group_name]
  [EXTEND C_code]
  [JUMP (reference | PREVIOUS[(n)] | MYSELF | NEXT[(n)]) (ITERATE n | WHEN condition)]
  [METADATA type name C_code]

Every clause other than COMPONENT name = comp(...) and AT (...) is optional; a component may carry more than one JUMP clause. Order matters and must follow the layout above. Concrete example:

COMPONENT Mono1 = Monochromator_curved(zwidth=0.025, yheight=0.025, gap=0.0005,
    NH=15, NV=1, mosaich=44, mosaicv=44, r0=1, Q=1.8734)
  AT (0, 0, -LMM) RELATIVE Cradle
  ROTATED (0, A1/2, 0) RELATIVE Cradle
  GROUP IN6Monoks
  EXTEND
  %{
    if (SCATTERED) myvar = 1;
  %}

Placement and references

6. SPLIT — boost statistics past a lossy component

SPLIT COMPONENT mono = NCrystal_sample(...) AT (...) ...
SPLIT 100 COMPONENT Sample = Single_crystal(...) AT (...) ...

7. GROUP — mutually-exclusive component sets ("XOR")

COMPONENT Mono1 = Monochromator_curved(...)
  AT (0,0,-LMM) RELATIVE Cradle  ROTATED (0,A1/2,0) RELATIVE Cradle
  GROUP IN6Monoks

COMPONENT Mono2 = Monochromator_curved(...)
  AT (0,0,0) RELATIVE Cradle  ROTATED (0,A2/2,0) RELATIVE Cradle
  GROUP IN6Monoks

8. WHEN — conditional component activation

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

COMPONENT MyMon = PSD_monitor(...) WHEN (flag==1) AT (0,0,0) RELATIVE Sample

9. EXTEND — appending C code after a component's TRACE

COMPONENT Mono2 = Monochromator_curved(...) AT (...) ROTATED (...) GROUP IN6Monoks
EXTEND
%{
  if (SCATTERED) myvar = 2;
%}

10. JUMP — loops and non-sequential propagation

COMPONENT Jmp = Arm() AT (0,0,0.1) ABSOLUTE
JUMP Return WHEN (doJump)          // conditional jump

COMPONENT CG_2 = Guide_gravity(l=L/n, m=1, ...)
  AT (0,0,0) RELATIVE PREVIOUS  ROTATED (0,(L/n+d)/R*180/PI,0) RELATIVE PREVIOUS
  JUMP CG_2_Position ITERATE n   // repeat a loop body n times

11. COPY — duplicating a component instance

COMPONENT COPY(H25_1) = COPY(H25_1)
  AT (0,0,L_H25_1+gGap) RELATIVE PREVIOUS
  ROTATED (0,Rh_H25_1,0) RELATIVE PREVIOUS

COMPONENT COPY(H25_1) = COPY(H25_1)(W=2*gW)     // override one parameter
  AT (0,0,L_H25_1+gGap) RELATIVE PREVIOUS
  ROTATED (0,Rh_H25_1,0) RELATIVE PREVIOUS

12. METADATA — attaching arbitrary side-data

COMPONENT first_file = File(filename="first.txt", metadatakey="stored", keep=1) AT (0,0,0) ABSOLUTE
METADATA txt stored %{
Store text to write in first.txt
%}

METADATA "mimetype/text" origin_info %{
# Generated file
Here is some data to go into a file.
%}

13. CPU — force one instance to run on CPU

CPU COMPONENT slow_bit = SomeLib(...) AT (...) ...

14. %include and instrument concatenation

%include "monitor_nd-lib"          // C library, from within a %{ %} block
%include "ILL_H16.instr"           // whole instrument or component file

15. SAVE / FINALLY / END (instrument level)

SAVE
%{ // executed whenever a (partial) save is triggered, and at simulation end %}

FINALLY
%{ // executed once, at simulation end, after SAVE %}

END

16. Reserved keyword reference

All tokens below are reserved and case-insensitive; do not reuse them as C identifiers. "Scope": I = valid in instrument definitions, C = valid in component definitions (the companion component-grammar file covers the C-scope keywords in more depth).

Keyword Scope Meaning
ABSOLUTE I Global coordinate frame for AT/ROTATED.
AT I Component position.
COMPONENT I Declares a component instance.
COPY I Duplicate a preceding instance (§11).
CPU I Force one instance to run on CPU only (§13).
DECLARE I, C C global declarations.
DEFINE I, C Starts an INSTRUMENT or COMPONENT definition.
DEFINITION C No longer supported — raises a compile error if used (COMPONENT grammar, §3).
DEPENDENCY I, C Compiler/linker flags (§3).
DISPLAY C Alias for MCDISPLAY.
END I, C Ends the definition.
EXTEND I, C Appends C code after a TRACE, or after an INHERITed section.
FINALLY I, C C code run at simulation end.
GROUP I Exclusive ("XOR") component group (§7).
%include I, C Import a file — component/instrument, or (inside %{ %}) a C library (§14).
INHERIT C Derive a component (whole or per-section) from a parent.
INITIALIZE / INITIALISE I, C C code run once at start-up.
ITERATE I JUMP loop-count clause (§10).
JUMP I Conditional/iterative non-sequential propagation (§10).
MCDISPLAY C C code to draw component geometry (alias DISPLAY).
METADATA I, C Attach a named, typed text block (§12).
MYSELF I Self-reference for COPY/JUMP.
NEXT / NEXT(n) I Forward instance reference, for JUMP.
NOACC C Marks a component class GPU-incompatible.
OUTPUT C Alias for PRIVATE PARAMETERS; parses but no longer has any effect (COMPONENT grammar, §3).
PARAMETERS C Qualifier after SETTING/OUTPUT/PRIVATE (and the rejected DEFINITION).
PREVIOUS / PREVIOUS(n) I, C Backward instance reference.
PRIVATE C Alias for OUTPUT PARAMETERS; parses but no longer has any effect (COMPONENT grammar, §3).
RELATIVE I Relative coordinate frame for AT/ROTATED.
REMOVABLE I Skip this component when the file is %include'd (§14).
ROTATED I Component orientation.
SAVE I, C C code run on (partial) data save.
SEARCH I Extra component/instrument search directory — TRACE-section only (§3).
SETTING C Component parameters compiled as ordinary C variables.
SHARE C C code emitted once, shared across all instances.
SHELL I, C Run a shell command at parse time (§3).
SPLIT I Boost downstream statistics by event repetition (§6).
TRACE I, C The particle-propagation / component-interaction section.
USERVARS I, C Per-particle custom fields (§4).
WHEN I Conditional component activation, or JUMP condition (§8, §10).

Obsolete / rejected keywords

STATE PARAMETERS, POLARISATION PARAMETERS, and DEFINITION PARAMETERS (a component-definition keyword — see the COMPONENT grammar, §3) are all still recognised by the grammar but immediately raise a compile error if used — leftovers from older grammar versions. Separately, OUTPUT PARAMETERS/PRIVATE PARAMETERS are not rejected — they still parse without error — but no longer have any effect; they're inert rather than erroring. All four are usually a sign the file, or the documentation it was written against, predates the current McStas/McXtrace.


17. Source-material for this reference

See also: McStas_McXtrace_COMPONENT_Grammar.md (COMPONENT grammar, .comp grammar).