Skip to content

Powder n and single crystal minorfixes - #2622

Open
Lomholy wants to merge 5 commits into
mainfrom
PowderN_and_SingleCrystal_minorfixes
Open

Powder n and single crystal minorfixes#2622
Lomholy wants to merge 5 commits into
mainfrom
PowderN_and_SingleCrystal_minorfixes

Conversation

@Lomholy

@Lomholy Lomholy commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Free-form text area

Please describe what your PR is adding in terms of features or bugfixes:
This PR fixes two minor bugs on the Single_crystal component, and the PowderN component.

The bug in the Single_Crystal component is, that when the number of scatterings is exceeded due to the order parameter, the ray is weighted with exp(-absl). This is wrong, since it should be the total cross section of events i.e exp(-totl).

The bug in the PowderN component is that the attenuation of the ray due to sampling the position is wrong. Currently when order is not set, then my_s is set to my_inc, and it should always be set to the total cross section.
I (embarrasingly enough) implemented this erroneous parameter myself, due to a misunderstanding of the internal workings of this component. I believed that my_s was set to the total cross section in order to mitigate multiple scattering, when it in fact was only there to correct for sampling uniformly instead of exponentially.


Development OS / boundary conditions

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


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

…e with the total cross section, not only the absorption cross section
…erefore it should be the total scattering cross section of the powder, and not only the incoherent xsect, no matter the order
@Lomholy

Lomholy commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

Screenshot of relevant part of PowderN mcdoc page:

billede

Single Crystals documentation was not changed.

@Lomholy

Lomholy commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

@willend I am trying to run mctest --testdir tmp --comp PowderN -n 1e6 but this throws the following error (that I don't understand):

File "mcstas-dev/share/mcstas/tools/Python/mctest/mctest.py", line 979, in
main(args)
~~~~^^^^^^
File "mcstas-dev/share/mcstas/tools/Python/mctest/mctest.py", line 946, in main
run_default_test(testdir, mccoderoot, limit, instrfilter, compfilter, suffix)
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "mcstas-dev/share/mcstas/tools/Python/mctest/mctest.py", line 648, in run_default_test
(results, failed, num_compilefail, num_runfail, num_valfail, num_noexample) = mccode_test(mccoderoot, labeldir, limit, instrfilter, compfilter)
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "mcstas-dev/share/mcstas/tools/Python/mctest/mctest.py", line 426, in mccode_test
formatstr = "%-" + "%ds: Display FAILED (%ds)" % (maxnamelen+1, test.displaytime)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TypeError: %d format: a real number is required, not NoneType

Have you seen this error before / know the work around? (The same command works for Single_crystal)

@mads-bertelsen

Copy link
Copy Markdown
Contributor

The PowderN bug makes sense. Why was there an order parameter in PowderN, thought it was only single scattering? Was it done in preparation to adding multiple scattering to the component?

I don't think it's wrong to only apply the absorption cross section for the exit path in Single_crystal when order is reached. After a scattering (which is known to have happened since the order is reached), the new wavevector will match the bragg condition of the crystal plane it already scattered in, and have a very high probability to scatter again, reducing the weight to almost 0 if it was used for the remaining path. What would happen if order was larger is the ray reflecting back and forth on that same reflection (and maybe more if it happens that more can be reached), so it would still have a big probability to continue in the direction order 1 predicted, but it would of course be attenuated by the path length, which is what the current order=1 approximates (the real path length would be slightly longer due to the zig-zag path).

@mads-bertelsen

Copy link
Copy Markdown
Contributor

@willend I am trying to run mctest --testdir tmp --comp PowderN -n 1e6 but this throws the following error (that I don't understand):

File "mcstas-dev/share/mcstas/tools/Python/mctest/mctest.py", line 979, in main(args) ~~~~^^^^^^ File "mcstas-dev/share/mcstas/tools/Python/mctest/mctest.py", line 946, in main run_default_test(testdir, mccoderoot, limit, instrfilter, compfilter, suffix) ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "mcstas-dev/share/mcstas/tools/Python/mctest/mctest.py", line 648, in run_default_test (results, failed, num_compilefail, num_runfail, num_valfail, num_noexample) = mccode_test(mccoderoot, labeldir, limit, instrfilter, compfilter) ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "mcstas-dev/share/mcstas/tools/Python/mctest/mctest.py", line 426, in mccode_test formatstr = "%-" + "%ds: Display FAILED (%ds)" % (maxnamelen+1, test.displaytime) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TypeError: %d format: a real number is required, not NoneType

Have you seen this error before / know the work around? (The same command works for Single_crystal)

I also ran into this while trying to perform tests yesterday and did not figure it out. Will take a look soon.

@Lomholy

Lomholy commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

The PowderN bug makes sense. Why was there an order parameter in PowderN, thought it was only single scattering? Was it done in preparation to adding multiple scattering to the component?

No. It was done, because I had misunderstood that attenuating by the total scattering cross section was a way to account for multiple scattering. (Which it isn't)

I don't think it's wrong to only apply the absorption cross section for the exit path in Single_crystal when order is reached. After a scattering (which is known to have happened since the order is reached), the new wavevector will match the bragg condition of the crystal plane it already scattered in, and have a very high probability to scatter again, reducing the weight to almost 0 if it was used for the remaining path. What would happen if order was larger is the ray reflecting back and forth on that same reflection (and maybe more if it happens that more can be reached), so it would still have a big probability to continue in the direction order 1 predicted, but it would of course be attenuated by the path length, which is what the current order=1 approximates (the real path length would be slightly longer due to the zig-zag path).

Hmmm. I don't quite think I am following you here. The way I see it, when order is reached, we make a monte carlo choice, to set the probability of transmitting to 1. The probability to actually transmit is exp(-total sigma * l), and therefore the factor we should multiply onto the weight is exactly exp(-total sigma * l) and not exp(-abs * l).

With that said, my fix is not good enough, since the total scattering cross section that we access has not yet been modified for the direction of the neutron.

@mads-bertelsen

Copy link
Copy Markdown
Contributor

The PowderN bug makes sense. Why was there an order parameter in PowderN, thought it was only single scattering? Was it done in preparation to adding multiple scattering to the component?

No. It was done, because I had misunderstood that attenuating by the total scattering cross section was a way to account for multiple scattering. (Which it isn't)

Ah okay, so the order parameter that existed in PowderN had a different meaning than Single_crystal order.

I don't think it's wrong to only apply the absorption cross section for the exit path in Single_crystal when order is reached. After a scattering (which is known to have happened since the order is reached), the new wavevector will match the bragg condition of the crystal plane it already scattered in, and have a very high probability to scatter again, reducing the weight to almost 0 if it was used for the remaining path. What would happen if order was larger is the ray reflecting back and forth on that same reflection (and maybe more if it happens that more can be reached), so it would still have a big probability to continue in the direction order 1 predicted, but it would of course be attenuated by the path length, which is what the current order=1 approximates (the real path length would be slightly longer due to the zig-zag path).

Hmmm. I don't quite think I am following you here. The way I see it, when order is reached, we make a monte carlo choice, to set the probability of transmitting to 1. The probability to actually transmit is exp(-total sigma * l), and therefore the factor we should multiply onto the weight is exactly exp(-total sigma * l) and not exp(-abs * l).

With that said, my fix is not good enough, since the total scattering cross section that we access has not yet been modified for the direction of the neutron.

The scattering back and forth on the same reflection is quite common and the current approximation doesn't quite follow it either, as there would only be a 50% chance of the ray leaving with that direction. I think your suggested change would be more accurate (order=1 being a good approximation to order=0) for very small crystals, while for larger crystals I would guess the current approximation would be closer. Could do some tests similar to PR #1767

@willend

willend commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

@Lomholy @mads-bertelsen the mctest issue above seems associated with a bad state of the mctest on your branch...
(probably forked off between me introducing a new feature, finding and fixing a bug...)

The one on main works nicely for me.

I have therefore used the "Update branch" button on this PR to rebase against main.

git pull, ./devel/bin/mccode-build-conda and you should hopefully be in a good place?

Otherwise let me know and I can debug with you via zoom tomorrow.

@willend

willend commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

(as a result a new set of tests just started ...)

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