Skip to content

Add KSIntSurfaceScattering to simulate scatterings on a surface#147

Open
richeldichel wants to merge 4 commits into
KATRIN-Experiment:mainfrom
richeldichel:MetalSurfaceScattering
Open

Add KSIntSurfaceScattering to simulate scatterings on a surface#147
richeldichel wants to merge 4 commits into
KATRIN-Experiment:mainfrom
richeldichel:MetalSurfaceScattering

Conversation

@richeldichel

Copy link
Copy Markdown
Contributor

This class adds the possibility to simulate scattering of an electron on a surface with a given probability for backscattering of the electron and a given probability for production of a secondary electron from the surface.

Code originally by V. Hannen

This class adds the possibility to simulate scattering of an electron on a surface with a given probability for backscattering of the electron and a given probability for production of a secondary electron from the surface.
Code originally by V. Hannen

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new surface interaction (KSIntSurfaceScattering) to model electron interactions with surfaces, including probabilistic backscattering and probabilistic secondary-electron emission, and wires it into the build system and XML bindings.

Changes:

  • Added KSIntSurfaceScattering interaction implementation and interface.
  • Added XML binding builder to configure the interaction via ksint_surface_scattering with relevant attributes.
  • Registered new sources/headers in the Interactions and Bindings CMakeLists.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
Kassiopeia/Interactions/Source/KSIntSurfaceScattering.cxx Implements the scattering interaction, including backscattering, absorption, and secondary creation logic.
Kassiopeia/Interactions/Include/KSIntSurfaceScattering.h Declares the interaction API and configuration fields (probabilities, energies, side selection).
Kassiopeia/Interactions/CMakeLists.txt Adds the new interaction source/header to the Interactions library build.
Kassiopeia/Bindings/Interactions/Source/KSIntSurfaceScatteringBuilder.cxx Registers the new XML element and its attributes.
Kassiopeia/Bindings/Interactions/Include/KSIntSurfaceScatteringBuilder.h Implements attribute-to-setter wiring for XML configuration.
Kassiopeia/Bindings/CMakeLists.txt Adds the new builder source/header to the Bindings build.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Kassiopeia/Interactions/Source/KSIntSurfaceScattering.cxx
Comment thread Kassiopeia/Interactions/Source/KSIntSurfaceScattering.cxx
Comment thread Kassiopeia/Interactions/Source/KSIntSurfaceScattering.cxx Outdated
Comment thread Kassiopeia/Interactions/Source/KSIntSurfaceScattering.cxx Outdated
Comment thread Kassiopeia/Interactions/Source/KSIntSurfaceScattering.cxx Outdated
Comment thread Kassiopeia/Interactions/Source/KSIntSurfaceScattering.cxx Outdated
Comment thread Kassiopeia/Interactions/Source/KSIntSurfaceScattering.cxx Outdated
Comment thread Kassiopeia/Interactions/Include/KSIntSurfaceScattering.h
Comment thread Kassiopeia/Interactions/Source/KSIntSurfaceScattering.cxx Outdated
Comment thread Kassiopeia/Interactions/Source/KSIntSurfaceScattering.cxx Outdated
richeldichel and others added 3 commits June 8, 2026 09:55
…eview

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Ran Scripts/gen-bindings-docs.sh to regenerate the documentation. The diff includes some other previous PRs.
@richeldichel

richeldichel commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

I have added the suggestions by Copilot as they were all well-justified. Additionally, I enclosed the debug statements about the particle state in a #ifdef Kassiopeia_ENABLE_DEBUG as it does not make any sense otherwise.

The largest diff now comes from the update of the bindings documentation as I re-ran gen-bindings-docs.sh.

@richeldichel richeldichel marked this pull request as ready for review June 8, 2026 08:14
@richeldichel richeldichel requested a review from 2xB June 8, 2026 08:14

@2xB 2xB left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for the work! That looks like an interesting feature. I have some remarks, the most significant of which is my impression that there seems to be an error in KSIntSurfaceScattering::CreateSecondaryElectron.

void SetSide(std::string side_name)
{
//default is both sides of the surface execute the interaction
fSideName = std::string("both");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should really just be an enum. Also, information is duplicated between this, fPerformSideCheck and fSideSignIsNegative. Which is hard to track when it somehow gets de-synced. I would keep it as a single enum and then maybe when it is actually used do something like const performSideCheck = fSideName != SideName::Both.

Comment on lines +6 to +16
#include "KSIntSurfaceScattering.h"

#include "KRandom.h"
#include "KSInteractionsMessage.h"
using katrin::KRandom;

#include "KConst.h"

#include <cmath>

using katrin::KThreeVector;

@2xB 2xB Jun 12, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#include "KSIntSurfaceScattering.h"
#include "KRandom.h"
#include "KSInteractionsMessage.h"
using katrin::KRandom;
#include "KConst.h"
#include <cmath>
using katrin::KThreeVector;
#include "KSIntSurfaceScattering.h"
#include "KConst.h"
#include "KRandom.h"
#include "KSInteractionsMessage.h"
#include "KThreeVector.hh"
#include <cmath>
#include <limits>
using katrin::KRandom;
using katrin::KThreeVector;

Cleaning up the includes here. Also adding #include <limits> for the NaNs suggested below.

Comment on lines +22 to +25
fScatProbability(0.3),
fScatLossFraction(0.0),
fSecElectronProbability(0.25),
fSecElectronMeanEnergy(4.0),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fScatProbability(0.3),
fScatLossFraction(0.0),
fSecElectronProbability(0.25),
fSecElectronMeanEnergy(4.0),
fScatProbability(std::numeric_limits<double>::quiet_NaN()),
fScatLossFraction(std::numeric_limits<double>::quiet_NaN()),
fSecElectronProbability(std::numeric_limits<double>::quiet_NaN()),
fSecElectronMeanEnergy(std::numeric_limits<double>::quiet_NaN()),

There is no point in hidden defaults. Either a user sets it or it should fail. There should also be an error thrown if any of these is NaN during calculation so one knows what one missed.

#endif

// figure out the basis directions for the particle ejection
// eject it with a diffuse 'Lambertian' distribution

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// eject it with a diffuse 'Lambertian' distribution

This comment has nothing to do with this code.


const KThreeVector tInitialMomentum = anInitialParticle.GetMomentum();
const double dot_prod = tInitialMomentum.Dot(tNormal);
bool execute_interaction = true;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if at the end of a function usually feels ugly to me since it adds some avoidable nesting. Like here: I would start with if (!execute_interaction) and early return; from there, that way the interaction code does not have to be in an if block but can just happen if no return happened.
That debug output is not useful in this case anyways since the particle was not really changed.

Comment on lines +168 to +169
tInitialNormalMomentum = -1.0 * tInitialNormalMomentum; //reverse direction for reflection
KThreeVector tInitialTangentMomentum = tInitialMomentum - tInitialNormalMomentum;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the impression at first glance that the next function has essentially the same code but programmed significantly more cleanly - most of my comments here don't apply there. Could it live in a common helper function GetReflectionMomentum(anInitialParticle, tSinTheta, tCosTheta) so it only exists once, preferably in the more clean way?


Other than that, I think there seems to be a bug here since this seems double-negating: tInitialNormalMomentum before the negation to my understanding should be the momentum in direction of the surface. Meaning tInitialMomentum - tInitialNormalMomentum before the negation should be the momentum orthogonal to tInitialNormalMomentum. That tInitialNormalMomentum = -1.0 * tInitialNormalMomentum; in combination with the minus sign in the next line does not make sense to me.

Also in general I think re-defining an existing variable is bad style. That also goes for the next two lines.

Comment on lines +171 to +172
tInitialNormalMomentum = tInitialNormalMomentum.Unit();
tInitialTangentMomentum = tInitialTangentMomentum.Unit();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's really inconsistent when .Unit() is applied and when one tracks variables, one sees that sometimes that is applied twice.

Comment on lines +190 to +193
if (tDirection.Dot(momDirection) > 0) {
tDirection = -1.0 * tDirection;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this a case that should never happen if the calculation was programmed correctly? Then it should better error in that case.

Comment on lines +222 to +227
if (tKineticEnergy < 0.0) {
intmsg(eError) << "surface diffuse interaction named <" << GetName()
<< "> tried to give a particle a negative kinetic energy." << eom;
return;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would that happen? Isn't it better to ensure fScatLossFraction is between 0 and 1?

1.)); // only KRandom::GetInstance().Uniform( 0., 1. ); is wrong: see http://www.sciencedirect.com/science/article/pii/S0042207X02001732
double tCosTheta = std::sqrt((1.0 - tSinTheta) * (1.0 + tSinTheta));

KThreeVector tNormal;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this following code I have essentially already reviewed above - Could it live in a function GetReflectionMomentum(anInitialParticle, tSinTheta, tCosTheta) so it only exists once?

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