|
|
|||
File indexing completed on 2026-05-31 07:53:28
0001 // 0002 // ******************************************************************** 0003 // * License and Disclaimer * 0004 // * * 0005 // * The Geant4 software is copyright of the Copyright Holders of * 0006 // * the Geant4 Collaboration. It is provided under the terms and * 0007 // * conditions of the Geant4 Software License, included in the file * 0008 // * LICENSE and available at http://cern.ch/geant4/license . These * 0009 // * include a list of copyright holders. * 0010 // * * 0011 // * Neither the authors of this software system, nor their employing * 0012 // * institutes,nor the agencies providing financial support for this * 0013 // * work make any representation or warranty, express or implied, * 0014 // * regarding this software system or assume any liability for its * 0015 // * use. Please see the license in the file LICENSE and URL above * 0016 // * for the full disclaimer and the limitation of liability. * 0017 // * * 0018 // * This code implementation is the result of the scientific and * 0019 // * technical work of the GEANT4 collaboration. * 0020 // * By using, copying, modifying or distributing the software (or * 0021 // * any work based on the software) you agree to acknowledge its * 0022 // * use in resulting scientific publications, and indicate your * 0023 // * acceptance of all terms of the Geant4 Software license. * 0024 // ******************************************************************** 0025 // 0026 /// \file GB06BOptnSplitAndKillByImportance.cc 0027 /// \brief Implementation of the GB06BOptnSplitAndKillByImportance class 0028 0029 #include "GB06BOptnSplitAndKillByImportance.hh" 0030 0031 #include "G4BiasingProcessInterface.hh" 0032 #include "G4BiasingProcessSharedData.hh" 0033 #include "G4ParallelGeometriesLimiterProcess.hh" 0034 #include "G4ProcessManager.hh" 0035 #include "Randomize.hh" 0036 0037 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 0038 0039 GB06BOptnSplitAndKillByImportance::GB06BOptnSplitAndKillByImportance(G4String name) 0040 : G4VBiasingOperation(name), 0041 fParallelWorldIndex(-1), 0042 fBiasingSharedData(nullptr), 0043 fParticleChange(), 0044 fDummyParticleChange() 0045 {} 0046 0047 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 0048 0049 GB06BOptnSplitAndKillByImportance::~GB06BOptnSplitAndKillByImportance() = default; 0050 0051 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 0052 0053 G4double GB06BOptnSplitAndKillByImportance::DistanceToApplyOperation(const G4Track*, G4double, 0054 G4ForceCondition* condition) 0055 { 0056 // -- Remember the touchable history (ie geometry state) at the beginning of the step: 0057 // -- Start by getting the process handling the step limitation in parallel 0058 // -- geometries for the generic biasing: 0059 auto biasingLimiterProcess = fBiasingSharedData->GetParallelGeometriesLimiterProcess(); 0060 fPreStepTouchableHistory = 0061 biasingLimiterProcess 0062 ->GetNavigator(fParallelWorldIndex) // -- get the navigator of the geometry... 0063 ->CreateTouchableHistoryHandle(); // -- ...and collect the geometry state. 0064 0065 // -- We request to be "forced" : meaning GenerateBiasingFinalState(...) will be called 0066 // -- anyway at the PostStepDoIt(...) stage (ie, when the track will have been moved to 0067 // -- its end point position) and, there, we will have to handle the decision to 0068 // -- split/kill if we are on a volume boundary, or do nothing, if we're not: 0069 *condition = Forced; 0070 0071 // -- As we're forced, we make this returned length void: 0072 return DBL_MAX; 0073 } 0074 0075 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 0076 0077 G4VParticleChange* 0078 GB06BOptnSplitAndKillByImportance::GenerateBiasingFinalState(const G4Track* track, const G4Step*) 0079 { 0080 // -- Given we used the "Forced" condition, this method is always called. 0081 // -- We check the status of the step in the parallel geometry, and apply 0082 // -- splitting/killing if the step has been limited by the geometry. 0083 0084 // -- We first check if we limit the step in the parallel geometry: 0085 G4bool isLimiting = 0086 fBiasingSharedData->GetParallelGeometriesLimiterProcess()->GetIsLimiting(fParallelWorldIndex); 0087 0088 // -- if not limiting, we leave the track unchanged: 0089 if (!isLimiting) { 0090 fDummyParticleChange.Initialize(*track); 0091 return &fDummyParticleChange; 0092 } 0093 0094 // -- We collect the geometry state at the end point step: 0095 // -- Note this is the same call than in the DistanceToApplyOperation(...) for the 0096 // -- fPreStepTouchableHistory, but the navigator has pushed the track in the next 0097 // -- volume since then (even if the track is still on the boundary), and hence the 0098 // -- geometry state has changed. 0099 auto biasingLimiterProcess = fBiasingSharedData->GetParallelGeometriesLimiterProcess(); 0100 fPostStepTouchableHistory = 0101 biasingLimiterProcess->GetNavigator(fParallelWorldIndex)->CreateTouchableHistoryHandle(); 0102 0103 // -- We verify we are still in the "same" physical volume: 0104 // -- remember : using a replica, we have "one" physical volume 0105 // -- but representing many different placements, distinguished 0106 // -- by replica number. By checking we are in the same physical 0107 // -- volume, we verify the end step point has not reached the 0108 // -- world volume of the parallel geometry: 0109 if (fPreStepTouchableHistory->GetVolume() != fPostStepTouchableHistory->GetVolume()) { 0110 // -- the track is leaving the volumes in which biasing is applied, 0111 // -- we leave this track unchanged: 0112 fDummyParticleChange.Initialize(*track); 0113 return &fDummyParticleChange; 0114 } 0115 0116 // ------------------------------------------------------------------------------------- 0117 // -- At this stage, we know we have a particle crossing a boundary between two slices, 0118 // -- each of this slice has a well defined importance : we apply the biasing. 0119 // -- We will split if the track is entering a volume with higher importance, and 0120 // -- kill (applying Russian roulette) in the other case. 0121 // ------------------------------------------------------------------------------------- 0122 0123 // -- We start by getting the replica numbers: 0124 G4int preReplicaNumber = fPreStepTouchableHistory->GetReplicaNumber(); 0125 G4int postReplicaNumber = fPostStepTouchableHistory->GetReplicaNumber(); 0126 0127 // -- and get the related importance we defined in the importance map: 0128 G4int preImportance = (*fImportanceMap)[preReplicaNumber]; 0129 G4int postImportance = (*fImportanceMap)[postReplicaNumber]; 0130 0131 // -- Get track weight: 0132 G4double initialWeight = track->GetWeight(); 0133 0134 // -- Initialize the "particle change" (it will communicate the new track state to 0135 // -- the tracking): 0136 fParticleChange.Initialize(*track); 0137 0138 if (postImportance > preImportance) { 0139 // -- We split : 0140 G4int splittingFactor = postImportance / preImportance; 0141 0142 // Define the tracks weight: 0143 G4double weightOfTrack = initialWeight / splittingFactor; 0144 0145 // Ask currect track weight to be changed to the new value: 0146 fParticleChange.ProposeParentWeight(weightOfTrack); 0147 // Now we clone this track (this is the actual splitting): 0148 // we will then have the primary and clone of it, hence the 0149 // splitting by a factor 2: 0150 auto clone = new G4Track(*track); 0151 clone->SetWeight(weightOfTrack); 0152 fParticleChange.AddSecondary(clone); 0153 // -- Below's call added for safety & illustration : inform particle change to not 0154 // -- modify the clone (ie : daughter) weight to make it that of the primary. 0155 // -- Here this call is not mandatory as both tracks have same weights. 0156 fParticleChange.SetSecondaryWeightByProcess(true); 0157 } 0158 else { 0159 // -- We apply Russian roulette: 0160 G4double survivingProbability = G4double(postImportance) / G4double(preImportance); 0161 0162 // Shoot a random number (in ]0,1[ segment): 0163 G4double random = G4UniformRand(); 0164 if (random > survivingProbability) { 0165 // We ask for the the track to be killed: 0166 fParticleChange.ProposeTrackStatus(fStopAndKill); 0167 } 0168 else { 0169 // In this case, the track survives. We change its weight 0170 // to conserve weight among killed and survival tracks: 0171 fParticleChange.ProposeParentWeight(initialWeight / survivingProbability); 0172 } 0173 } 0174 0175 return &fParticleChange; 0176 } 0177 0178 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|