-
Notifications
You must be signed in to change notification settings - Fork 44
Support decay in stepping loop #1991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
This reverts commit 757e9a1541c1efa4a118f62eca7cc22f8305781c.
- Rename Process to InteractionProcess and add DecayProcess - Add DecayChannel abstract base class - Add MuDecayChannel and executor - Add decay tables and channel - to - action mapping to physics data - Add DecayTableInserter helper class to build decay tables in physics data - Add decay to particle - processes in physics if present - Add decay_length method to ParticleTrackView - Add decay limiter in calc_physics_step_limit - Store decay process xs and sample from among other interaction processes - Sample decay channel using branching ratios if decay process is chosen - Cache sampled channel for accessing decay daughters in interactor - Refactor muon decay data and interactor to use generic decay data
Test summary 4 576 files 7 305 suites 14m 23s ⏱️ Results for commit 08a2f1f. ♻️ This comment has been updated with latest results. |
sethrj
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still working through the PR. It looks like currently we have one step action per decay channel per particle type? I think we'd be better off treating the decay physics input like a collection of models starting with those we support (as we do with the new optical surface physics), rather than the old ImportX style of making everything generic with an enum to tie it together. Each model would provide a set of particles it applies to.
So for muon decay, we might have optional<MuDecayChannel> in the DecayPhysics. We wouldn't need daughters since each decay channel knows what it can decay and how the particle decays. (If we really wanted to allow more granularity, we could have the MuDecayChannel input take a set of parent particles, which normally would be {mu-,mu+} or empty.) A more complex/general decay channel such as a three-body decay (subset of G4PhaseSpaceDecayChannel functionality) would have a different set of data underneath it: a vector of {particle -> daughters} etc. User-specified decay channel input would be a generic function that returns a vector of decay channels (or something).
As for branching ratios, it might make sense to give them as an unnormalized value or as a decay constant (1/time), which would get normalized among all the decay channels for a particular particle type. For the current capabilities, we only have one decay channel so the ratio doesn't even matter yet.
The DecayProcess would then construct the different decay channels, categorize them by particle ID, and determine branching ratios by relative decay constants/values. The decay channel itself would change (I think?) so that it might contain data from multiple particle types rather than a single one. For the typical case of particle/antiparticle (muon, tau) this is sensible because the only difference in the physics is the daughter particle IDs (I think?).
I'm going to keep reviewing, and I know that this suggestion (assuming I'm not missing something important) is a major change, so we don't have to implement it as part of this PR. But if we do want to go in that direction, we could at least delete aspects that aren't yet needed and will be deleted in the future (I'm thinking specifically the decay channel enum).
| CELER_EXPECT(this->mass() > zero_quantity()); | ||
| CELER_EXPECT(this->decay_constant() != constants::stable_decay_constant); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since momentum is always nonzero, I think we just get a (correct) value of infinity if either or both of these is zero.
| // Exclude the neutrino daughters for muon decay | ||
| //! \todo Remove once neutrinos are included in \c MuDecayInteractor | ||
| size_type num_daughters = channel.type == DecayChannelType::muon | ||
| ? 1 | ||
| : g4_channel->GetNumberOfDaughters(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we warn about missing neutrinos? (And is there another process in which we're neglecting neutrinos as well, or am I thinking of the muon decay that Stefano already put in?) Also, are we sure the neutrino is always listed last? Maybe it'd be better test the PDG inside the loop and warn+skip if neutrino.
I think it's the right thing to omit them on the "input" side rather than pull them in and ignore them at the process level, but maybe it'd be a nice feature to be able to store a more complete physics as input have have the PhysicsParams class trim out deactivated/unsupported features, e.g. removing hadronic physics if hadron particles are disabled?
|
|
||
| //---------------------------------------------------------------------------// | ||
| /*! | ||
| * Decay channels for a particle type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a note that these are stored by the PhysicsParamsData and used in the ProcessGroup (processes that apply to a particular particle type).
| */ | ||
| struct DecayPhysics | ||
| { | ||
| using DecayTable = std::vector<DecayChannel>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think VecDecayChannel since it's not really a table: there's no [row, column] access, and each vector of particle decay channels has additional data.
Does the order of this vector matter, or should it be a set<DecayChannel>?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I see where @amandalund is coming from with this name, since the PDG book has decay tables where the 1st column is the decay channel (so daughters here) and the 2nd column is the branching ratio. But Vec is definitely better in the code.
About the vector ordering: sorting channels by BR may be more efficient when selecting them. Specially in cases like pi0 -> 2gamma, where the BR is ~99%.
|
|
||
| //---------------------------------------------------------------------------// | ||
| /*! | ||
| * Process for decay. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A little more documentation here would be good: this single class manages all possible particle decay channels, each of which is analogous to a model for the action process.
| DecayChannelType type{DecayChannelType::size_}; | ||
| double branching_ratio{}; | ||
| std::vector<PDGNumber> daughters; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% sure I understand the input here. For muon decay, don't we know what the daughter types are? (Is this like specifying the secondary particle types for compton scattering?) Will other decay types need more data than just the branching ratios?
| case G4ProcessType::fOptical: | ||
| return (which & DataSelection::optical); | ||
| case G4ProcessType::fDecay: | ||
| return (which & (DataSelection::em | DataSelection::hadron)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a test to the GeantImporter to see what decay models it pulls out?
| { | ||
| case DecayChannelType::muon: | ||
| result.push_back(std::make_shared<MuDecayChannel>( | ||
| *start_id++, input_)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that for muons we'd create two separate step actions, one for each particle type?
|
@amandalund I am mostly off this week, but I can catch up on this MR later if a second review is needed. |
|
Thanks @sethrj for the comments! I'll look over the rest soon, but just to clarify it's one step action per channel, not per channel per particle type (I don't think we'd want that!) @whokion no worries, enjoy the time off! If you have a chance when you're back I'd definitely appreciate your review to make sure I've got the physics right. |
whokion
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, this looks reasonable to me, although the current implementation is somewhat over-engineered if we’re only supporting muon decay for now - of course, there is nothing wrong with being general from the start. Separately from this MR (perhaps by @stognini), we should add all daughters of the muon decay if we claim full support for it (in the context of the neutrino physics).
| // Calculate the macroscopic cross section as the inverse of the | ||
| // particle's decay length | ||
| process_xs = 1 / particle.decay_length(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this is a technical tweak treating decay as part of a macroscopic interaction. In reality, decay is independent of particle–matter interactions and is an intrinsic process governed solely by the particle’s proper time. A better approach would be to let the interaction process and the decay process compete independently, with the final proposed step length whichever occurs first. I understood this was part of the motivation for introducing InteractionProcess and DecayProcess separately (along with other variations). Mixing these two intrinsically different processes through a material-dependent macroscopic cross section is somewhat physically unnatural, since the proper time is independent of the material.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From a computational perspective I think it's better to combine the probabilities of a change in particle state into a single random number sample. But you do bring up a very good point about length versus time: is there any way this representation will interfere with assumptions about changing speed over the step length? Does Geant4's decay process factor in an average speed, or does it assume the speed is constant with the starting speed? Can we improve up on that? (Or must we avoid improvements to better agree with existing results?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Geant4, the particle velocity is assumed to remain constant during decay-in-flight. This approximation is generally valid, particularly for the muon weak decay, since the mean decay length of a high-energy muon is relatively long (on the order of
In principle, your point remains valid in situations where particle decay competes with material interactions on comparable length scales. However, such cases are not typical for common unstable particles in HEP detector simulations and, when they do arise, of course, should be handled with additional care even though I have not seen any good example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The application for muon decay being funded is muon catalyzed fusion which uses cold muons. So this may be an important effect we can model more accurately than geant4?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure—probably @stognini can clarify. My assumption is that it would be undesirable for muons to produce Michel electrons during the catalyzed fusion process.
| * correspondence between the channel ID and the action ID. Multiple channel | ||
| * IDs can map to a single channel action. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you clarify how multiple channel IDs map to a single channel action? Does this imply that the action is only depending on the multiplicity of daughters?
| { | ||
| CELER_LOG(warning) | ||
| << "branching ratios for decay channels should sum to 1 " | ||
| "but instead sum tp " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "but instead sum tp " | |
| "but instead sum to " |
This adds initial support for decay in the stepping loop. Muon decay is currently the only decay channel supported, but adding additional channels should be straightforward now.
To easily support the different decay channel types (which may not have fixed daughter particle types, or may have an arbitrary number of daughters), this moves from using channel-specific data (e.g.
MuDecayData) to the genericDecayChannelDataandDecayTableData. Daughter particle IDs are passed to the interactor and are expected to be in a specific order (this should be validated in theDecayChannelconstructor).Changes include:
ProcesstoInteractionProcessand add a newDecayProcess(used for all particle types that decay)DecayChannelwhich extends fromCoreStepActionInterface, responsible for validating decay table input and launching kernels for interactorsMuDecayChannelderived classMuDecayInteractorto use generic decay dataselect_discrete_interactionI haven't added any tests yet (only checked that running celer-g4 on a simple problem with muon decay imports the data and interacts by decay without any failures), but otherwise this should be ready for a first look.
See #1375