Skip to content

Remove need for Union_init and Union_stop - #2655

Merged
willend merged 21 commits into
mccode-dev:mainfrom
mads-bertelsen-agentic:Avoid_union_init_and_stop
Sep 26, 2026
Merged

willend merged 21 commits into
mccode-dev:mainfrom
mads-bertelsen-agentic:Avoid_union_init_and_stop

Conversation

@mads-bertelsen-agentic

@mads-bertelsen-agentic mads-bertelsen-agentic commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Free-form text area

Please describe what your PR is adding in terms of features or bugfixes:

This is a suggestion on how to avoid the need for the Union_init and Union_stop components. Today they serve
two functions:

  • Add the .c code files at start and end so the preprocessor can limit what code is actually compiled
  • Provide "global" variables in the init, other Union components communicated through GETPAR things

This branch simply does these things in the cogen by checking if a Union_master or Union_master_GPU is in the instrument. This is to avoid more invasive things like tagging all the Union components, but other suggestions for detecting when to trigger including union globals and libraries.

Instruments with Union_init and Union_stop will continue to work, just show deprecation warnings. Instruments that use the init parameter on Union components explicitly will break as that parameter is not available anymore (mcstas-pygen generated instruments might be extra susceptible to this, as all parameters are always specified).


Declaration of use of AI-tools

  • Please add a checkmark here if you used AI-tools during the work for this contribution
  • Furter, please describe how / where and for what the tools were used:

Development OS / boundary conditions

Please describe what OS you developed and tested your additions on, and if any special dependencies are required:


PR Checklist for contributing to McStas/McXtrace

For a coherent and useful contribution to McStas/McXtrace, please fill in relevant parts of the checklist:

  • My contribution includes patches to an existing component file

    • I have used the mcdoc utility and rendered a reasonable documentation page for the component (please attach as screenshot in comments!)
    • I have ensured that basic use of the component is OK (e.g. an instrument using it compiles?)
    • I have used the mctest utility to test one or more instruments making use of the component (please attach mcviewtest report as screenshot in comments)
    • I have used the mccode-clangformat tool to apply the standard McCode component indentation scheme
    • I have used the mcrun --c-lint "linter" and followed advice to remove most / all warnings that are raised
  • My work touches the code-generator in mccode/src

    • I have added reasoning and documentation for the change through an ADR record in our GRAMMAR section
    • I am attaching test output in the comments
  • My work touches / adds to the runtime lib code (.c,.h etc in multiple locations

    • I am have added reasoning and documentation for the change below
    • I am attaching test output in the comments

mads-bertelsen-agentic and others added 15 commits September 9, 2026 06:40
Union instruments previously required a Union_init component placed first
and a Union_stop component placed last. Union_init inlined the shared
union-lib.c header (types) and union-init.c (the global list state,
accessed through COMP_GETPAR3(Union_init, init, ...)); Union_stop inlined
union-suffix.c (the dispatch switch) exactly once, after every
PROCESS_*_DETECTOR macro had already been defined. This made the required
first/last ordering fragile.

cogen now injects that shared front/back automatically, so Union_init and
Union_stop are no longer required. The change is applied to both mcstas and
mcxtrace in lockstep.

Detection
cogen_instr_uses_union() returns true when the instrument contains a
Union_master or Union_master_GPU component (the master is mandatory when any
Union component is used). The shared code is injected only in that case, so
non-union instruments are byte-for-byte unchanged.

Injection (mccode/src/cogen.c.in)
- Front, at the top of cogen_decls (before the SHARE loop): emit
  "#define Union 1", then embed_file("union-lib.c") and
  embed_file("union-init.c").
- Back, after the SHARE loop: embed_file("union-suffix.c").
- embed_file() is include-once (via the symtab) and searches the system
  directory before the component path, so each shared file is emitted
  exactly once even when many union components are present.

Shared state (union-init.c, both compilers)
The file-scope globals are renamed to a g_ prefix so they cannot collide
with the component-local pointers of the same name, e.g.
global_process_list -> g_process_list. Each component keeps its local
pointer but sets it to &g_FOO, so all ->, . and * usages (and the
..._master LHS names) are left untouched.
- mcstas: 13 globals (incl. g_surface_list, g_mantid_min_pixel_id)
- mcxtrace: 11 globals (no surface / mantid_min_pixel_id)

Components (mcstas-comps/union, mcxtrace-comps/union)
- Every union .comp now uses &g_FOO instead of
  COMP_GETPAR3(Union_init, init, global_FOO); the
  "if (_getcomp_index(init) < 0) {...}" guard blocks are removed.
- mcxtrace components no longer %include union-init.c (cogen injects it);
  Template_process.comp's bare &global_process_list becomes &g_process_list.
- Int special case: Union_abs_logger_1D_space_event.comp now reads
  g_mantid_min_pixel_id directly (no &, cast dropped).
- Function parameters named global_* in SHARE signatures are untouched.
- Union_init.comp / Union_stop.comp are converted to inert no-ops (empty
  SHARE/DECLARE/INITIALIZE), so existing .instr files that still place them
  compile and run unchanged. The deprecated string init="init" parameter is
  kept so old instruments still parse.

Include guards
union-lib.c, union-init.c and union-suffix.c each gained a guard
(UNION_LIB_C / UNION_INIT_C / UNION_SUFFIX_C) in both mcstas and mcxtrace.

Verification
- mcstas mctest passes: old-style instruments (with init/stop) unchanged;
  new-style (no init/stop) reproduce the exact detector value (4.55997e-10);
  non-union instruments show no injection markers; the dispatch switch is
  emitted once with the PROCESS_*_DETECTOR macros defined before it.
- mcxtrace: Geometry_test compiles with the injection and runs to completion
  (Union_master initialized, trace saved; no .nxs counts because all
  DETECTORs are commented out in that example). Its meshfile mcrun prompt is
  pre-existing (the example requires an external torus.STL it does not ship)
  and reproduces identically on the unmodified baseline.
Every Union component (except the no-op Union_init/Union_stop) now
emits a clear #error when the shared Union library was not injected,
which happens when the instrument contains no Union_master /
Union_master_GPU. Previously mcstas carried a stale message pointing at
the now-optional Union_init component, and mcxtrace silently defined
Union so a masterless instrument failed only with cryptic
'incomplete type' errors.

Also drop the dead, never-referenced length_to_boundery_fp
declaration in Union_master (mcxtrace, missing semicolon) and
Union_master_GPU (mcstas).
@mads-bertelsen-agentic
mads-bertelsen-agentic marked this pull request as draft September 11, 2026 15:21
@mads-bertelsen-agentic
mads-bertelsen-agentic marked this pull request as ready for review September 24, 2026 19:37
@willend

willend commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

@mads-bertelsen the collision / merge conflict above is caused by incoming doc changes from the work on the manuals. Likely trivial to resolve (I will have a look now)

@willend

willend commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

Ran a local test before merging - all good

mctest --instr=Union --mpi=auto
loading system configuration
Output of test will be placed in: .
ncount is: 1e6
mpi count is: auto
Testing: 3.99.99

Finding instruments in: /some/path/micromamba/envs/mccode-dev/share/mcstas/resources/examples
Copying instruments to: ./mcstas-3.99.99_mpi_x_auto_Union_1e6_Darwin_20260926_1931_31

Compiling instruments [seconds]...
Union_NCrystal_example     :   5.00
Union_NCrystal_mix_example :   4.48
Bispectral                 :   4.38
Demonstration              :   5.48
External_component         :   5.16
Laue_camera                :   4.75
Manual_example             :   4.78
Sample_picture_replica     :   4.19
Tagging_demo               :   4.78
Time_of_flight             :   5.38
SE_usage_example           :   5.08
cryostat_example           :   4.93
Incoherent_validation      :   4.97
Mirror_validation          :   3.86
Powder_validation          :   5.06
Single_crystal_validation  :   5.39

Running tests / getting status...
Union_NCrystal_example      :   Display OK (4s)
Union_NCrystal_example      :   1.80    [val: 1.52489e-10 / 1.55e-10 = 98 %]
 - Test 1 plots generated OK
Union_NCrystal_mix_example  :   Display OK (2s)
Union_NCrystal_mix_example  :   1.77    [val: 1.51033e-10 / 1.53e-10 = 99 %]
 - Test 1 plots generated OK
Bispectral                  :   Display OK (2s)
Bispectral                  :   2.38    [val: 512882000000.0 / 510776000000.0 = 100 %]
 - Test 1 plots generated OK
Demonstration               :   Display OK (2s)
Demonstration               :   1.73    [val: 21831.6 / 21849.9 = 100 %]
 - Test 1 plots generated OK
Demonstration_2             :   1.72    [val: 100.482 / 101.8 = 99 %]
 - Test 2 plots generated OK
External_component          :   Display OK (2s)
External_component          :   NO TEST
Laue_camera                 :   Display OK (1s)
Laue_camera                 :   1.67    [val: 20755900.0 / 20826200.0 = 100 %]
 - Test 1 plots generated OK
Laue_camera_2               :   1.58    [val: 1030340.0 / 1034600.0 = 100 %]
 - Test 2 plots generated OK
Laue_camera_3               :   1.59    [val: 230350000.0 / 230318000.0 = 100 %]
 - Test 3 plots generated OK
Manual_example              :   Display OK (1s)
Manual_example              :   NO TEST
Sample_picture_replica      :   Display OK (1s)
Sample_picture_replica      :   1.53    [val: 1977.62 / 1977.65 = 100 %]
 - Test 1 plots generated OK
Tagging_demo                :   Display OK (1s)
Tagging_demo                :   NO TEST
Time_of_flight              :   Display OK (2s)
Time_of_flight              :   NO TEST
SE_usage_example            :   Display OK (1s)
SE_usage_example            :   NO TEST
cryostat_example            :   Display OK (2s)
cryostat_example            :   1.80    [val: 729.25 / 730.0 = 100 %]
 - Test 1 plots generated OK
Incoherent_validation       :   Display OK (1s)
Incoherent_validation       :   1.49    [val: 19093.6 / 19084.8 = 100 %]
 - Test 1 plots generated OK
Incoherent_validation_2     :   1.50    [val: 1.20537 / 1.10444 = 109 %]
 - Test 2 plots generated OK
Incoherent_validation_3     :   1.51    [val: 1.48592 / 1.54102 = 96 %]
 - Test 3 plots generated OK
Mirror_validation           :   Display OK (1s)
Mirror_validation           :   1.67    [val: 0.0178094 / 0.0178 = 100 %]
 - Test 1 plots generated OK
Mirror_validation_2         :   1.60    [val: 0.0178094 / 0.0178 = 100 %]
 - Test 2 plots generated OK
Powder_validation           :   Display OK (1s)
Powder_validation           :   1.50    [val: 67646.3 / 67635.2 = 100 %]
 - Test 1 plots generated OK
Powder_validation_2         :   1.53    [val: 67742.3 / 67635.2 = 100 %]
 - Test 2 plots generated OK
Powder_validation_3         :   1.56    [val: 5.51209 / 5.79875 = 95 %]
 - Test 3 plots generated OK
Powder_validation_4         :   1.52    [val: 5.70231 / 5.79875 = 98 %]
 - Test 4 plots generated OK
Powder_validation_5         :   1.51    [val: 4.75784 / 5.0 = 95 %]
 - Test 5 plots generated OK
Powder_validation_6         :   1.50    [val: 5.17982 / 5.0 = 104 %]
 - Test 6 plots generated OK
Powder_validation_7         :   1.57    [val: 3800.39 / 3750.0 = 101 %]
 - Test 7 plots generated OK
Powder_validation_8         :   1.52    [val: 3741.79 / 3750.0 = 100 %]
 - Test 8 plots generated OK
Powder_validation_9         :   1.60    [val: 12.5119 / 12.5 = 100 %]
 - Test 9 plots generated OK
Powder_validation_10        :   1.52    [val: 13.0362 / 12.5 = 104 %]
 - Test 10 plots generated OK
Single_crystal_validation   :   Display OK (1s)
Single_crystal_validation   :   1.64    [val: 984258.0 / 950000.0 = 104 %]
 - Test 1 plots generated OK
Single_crystal_validation_2 :   1.63    [val: 780474.0 / 793256.0 = 98 %]
 - Test 2 plots generated OK
Single_crystal_validation_3 :   1.61    [val: 779513.0 / 795548.0 = 98 %]
 - Test 3 plots generated OK
======================================
Overall test result:
SUCCESS

@willend
willend merged commit d631dec into mccode-dev:main Sep 26, 2026
13 checks passed
@willend willend mentioned this pull request Oct 2, 2026
2 of 31 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants