Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // G4BOptrForceCollision << 27 // ------------------------------------------- << 28 << 29 #include "G4BOptrForceCollision.hh" 26 #include "G4BOptrForceCollision.hh" 30 #include "G4BOptrForceCollisionTrackData.hh" 27 #include "G4BOptrForceCollisionTrackData.hh" 31 #include "G4BiasingProcessInterface.hh" 28 #include "G4BiasingProcessInterface.hh" 32 #include "G4PhysicsModelCatalog.hh" 29 #include "G4PhysicsModelCatalog.hh" 33 30 34 #include "G4BOptnForceCommonTruncatedExp.hh" 31 #include "G4BOptnForceCommonTruncatedExp.hh" 35 #include "G4ILawCommonTruncatedExp.hh" 32 #include "G4ILawCommonTruncatedExp.hh" 36 #include "G4BOptnForceFreeFlight.hh" 33 #include "G4BOptnForceFreeFlight.hh" 37 #include "G4BOptnCloning.hh" 34 #include "G4BOptnCloning.hh" 38 35 39 #include "G4Step.hh" 36 #include "G4Step.hh" 40 #include "G4StepPoint.hh" 37 #include "G4StepPoint.hh" 41 #include "G4VProcess.hh" 38 #include "G4VProcess.hh" 42 39 43 #include "G4ParticleDefinition.hh" 40 #include "G4ParticleDefinition.hh" 44 #include "G4ParticleTable.hh" 41 #include "G4ParticleTable.hh" 45 42 46 #include "G4SystemOfUnits.hh" 43 #include "G4SystemOfUnits.hh" 47 44 48 // -- Consider calling other constructor, than << 45 // -- §§ consider calling other constructor, thanks to C++11 49 G4BOptrForceCollision:: << 46 G4BOptrForceCollision::G4BOptrForceCollision(G4String particleName, G4String name) 50 G4BOptrForceCollision(const G4String& particle << 51 const G4String& name) << 52 : G4VBiasingOperator(name), 47 : G4VBiasingOperator(name), 53 fForceCollisionModelID(G4PhysicsModelCatal << 48 fForceCollisionModelID(-1), >> 49 fCurrentTrack(nullptr), >> 50 fCurrentTrackData(nullptr), >> 51 fInitialTrackWeight(-1.0), >> 52 fSetup(true) 54 { 53 { 55 fSharedForceInteractionOperation = new G4BOp 54 fSharedForceInteractionOperation = new G4BOptnForceCommonTruncatedExp("SharedForceInteraction"); 56 fCloningOperation = new G4BOptnCloning("Clon << 55 fCloningOperation = new G4BOptnCloning("Cloning"); 57 fParticleToBias = G4ParticleTable::GetPartic 56 fParticleToBias = G4ParticleTable::GetParticleTable()->FindParticle(particleName); 58 57 59 if ( fParticleToBias == nullptr ) << 58 if ( fParticleToBias == 0 ) 60 { << 59 { 61 G4ExceptionDescription ed; << 60 G4ExceptionDescription ed; 62 ed << " Particle `" << particleName << "' << 61 ed << " Particle `" << particleName << "' not found !" << G4endl; 63 G4Exception(" G4BOptrForceCollision::G4BOp << 62 G4Exception(" G4BOptrForceCollision::G4BOptrForceCollision(...)", 64 "BIAS.GEN.07", JustWarning, ed << 63 "BIAS.GEN.07", 65 } << 64 JustWarning, >> 65 ed); >> 66 } 66 } 67 } 67 68 68 G4BOptrForceCollision:: << 69 69 G4BOptrForceCollision(const G4ParticleDefiniti << 70 G4BOptrForceCollision::G4BOptrForceCollision(const G4ParticleDefinition* particle, G4String name) 70 const G4String& name) << 71 : G4VBiasingOperator(name), 71 : G4VBiasingOperator(name), 72 fForceCollisionModelID(G4PhysicsModelCatal << 72 fForceCollisionModelID(-1), >> 73 fCurrentTrack(nullptr), >> 74 fCurrentTrackData(nullptr), >> 75 fInitialTrackWeight(-1.0), >> 76 fSetup(true) 73 { 77 { 74 fSharedForceInteractionOperation = new G4BOp 78 fSharedForceInteractionOperation = new G4BOptnForceCommonTruncatedExp("SharedForceInteraction"); 75 fCloningOperation = new G4BOptnCloning("Clon << 79 fCloningOperation = new G4BOptnCloning("Cloning"); 76 fParticleToBias = particle; << 80 fParticleToBias = particle; 77 } 81 } 78 82 >> 83 79 G4BOptrForceCollision::~G4BOptrForceCollision( 84 G4BOptrForceCollision::~G4BOptrForceCollision() 80 { 85 { 81 for ( auto it = fFreeFlightOperations.cbegin << 86 for ( std::map< const G4BiasingProcessInterface*, G4BOptnForceFreeFlight* >::iterator it = fFreeFlightOperations.begin() ; 82 it != fFreeFlightOperations.cend( << 87 it != fFreeFlightOperations.end() ; 83 { << 88 it++ ) delete (*it).second; 84 delete (*it).second; << 85 } << 86 delete fSharedForceInteractionOperation; 89 delete fSharedForceInteractionOperation; 87 delete fCloningOperation; 90 delete fCloningOperation; 88 } 91 } 89 92 >> 93 90 void G4BOptrForceCollision::Configure() 94 void G4BOptrForceCollision::Configure() 91 { 95 { >> 96 // -- Create ID for force collision: >> 97 fForceCollisionModelID = G4PhysicsModelCatalog::Register("GenBiasForceCollision"); >> 98 92 // -- build free flight operations: 99 // -- build free flight operations: 93 ConfigureForWorker(); 100 ConfigureForWorker(); 94 } 101 } 95 102 >> 103 96 void G4BOptrForceCollision::ConfigureForWorker 104 void G4BOptrForceCollision::ConfigureForWorker() 97 { 105 { 98 // -- start by remembering processes under b << 106 // -- start by remembering processes under biasing, and create needed biasing operations: 99 // and create needed biasing operations: << 100 if ( fSetup ) 107 if ( fSetup ) 101 { << 108 { 102 const G4ProcessManager* processManager = f << 109 // -- get back ID created in master thread in case of MT (or reget just created ID in sequential mode): 103 const G4BiasingProcessSharedData* interfac << 110 fForceCollisionModelID = G4PhysicsModelCatalog::Register("GenBiasForceCollision"); 104 if ( interfaceProcessSharedData ) // -- sh << 111 105 // -- to a vol << 112 const G4ProcessManager* processManager = fParticleToBias->GetProcessManager(); 106 { << 113 const G4BiasingProcessSharedData* interfaceProcessSharedData = G4BiasingProcessInterface::GetSharedData( processManager ); 107 for ( std::size_t i = 0 ; i < (interface << 114 if ( interfaceProcessSharedData ) // -- sharedData tested, as is can happen a user attaches an operator 108 { << 115 // -- to a volume but without defining BiasingProcessInterface processes. 109 const G4BiasingProcessInterface* wrapp << 116 { 110 (interfaceProcessSharedData->GetPhys << 117 for ( size_t i = 0 ; i < (interfaceProcessSharedData->GetPhysicsBiasingProcessInterfaces()).size(); i++ ) 111 const G4String& operationName = "FreeF << 118 { 112 fFreeFlightOperations[wrapperProcess] << 119 const G4BiasingProcessInterface* wrapperProcess = 113 } << 120 (interfaceProcessSharedData->GetPhysicsBiasingProcessInterfaces())[i]; >> 121 G4String operationName = "FreeFlight-"+wrapperProcess->GetWrappedProcess()->GetProcessName(); >> 122 fFreeFlightOperations[wrapperProcess] = new G4BOptnForceFreeFlight(operationName); >> 123 } >> 124 } >> 125 fSetup = false; 114 } 126 } 115 fSetup = false; << 116 } << 117 } 127 } 118 128 >> 129 119 void G4BOptrForceCollision::StartRun() 130 void G4BOptrForceCollision::StartRun() 120 { 131 { 121 } 132 } 122 133 123 G4VBiasingOperation* << 134 124 G4BOptrForceCollision::ProposeOccurenceBiasing << 135 G4VBiasingOperation* G4BOptrForceCollision::ProposeOccurenceBiasingOperation(const G4Track* track, const G4BiasingProcessInterface* callingProcess) 125 const G4Biasing << 126 { 136 { 127 // -- does nothing if particle is not of req 137 // -- does nothing if particle is not of requested type: 128 if ( track->GetDefinition() != fParticleToBi << 138 if ( track->GetDefinition() != fParticleToBias ) return 0; 129 139 130 // -- trying to get auxiliary track data... 140 // -- trying to get auxiliary track data... 131 if ( fCurrentTrackData == nullptr ) 141 if ( fCurrentTrackData == nullptr ) 132 { << 142 { 133 // ... and if the track has no aux. track << 143 // ... and if the track has no aux. track data, it means its biasing is not started yet (note that cloning is to happen first): 134 fCurrentTrackData = (G4BOptrForceCollision << 144 fCurrentTrackData = (G4BOptrForceCollisionTrackData*)(track->GetAuxiliaryTrackInformation(fForceCollisionModelID)); 135 if ( fCurrentTrackData == nullptr ) return << 145 if ( fCurrentTrackData == nullptr ) return nullptr; 136 } << 146 } 137 147 >> 148 138 // -- Send force free flight to the callingP 149 // -- Send force free flight to the callingProcess: 139 // ----------------------------------------- 150 // ------------------------------------------------ 140 // -- The track has been cloned in the previ 151 // -- The track has been cloned in the previous step, it has now to be 141 // -- forced for a free flight. 152 // -- forced for a free flight. 142 // -- This track will fly with 0.0 weight du 153 // -- This track will fly with 0.0 weight during its forced flight: 143 // -- it is to forbid the double counting wi 154 // -- it is to forbid the double counting with the force interaction track. 144 // -- Its weight is restored at the end of i 155 // -- Its weight is restored at the end of its free flight, this weight 145 // -- being its initial weight * the weight 156 // -- being its initial weight * the weight for the free flight travel, 146 // -- this last one being per process. The i 157 // -- this last one being per process. The initial weight is common, and is 147 // -- arbitrary asked to the first operation 158 // -- arbitrary asked to the first operation to take care of it. 148 if ( fCurrentTrackData->fForceCollisionState 159 if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeFreeFlight ) 149 { << 150 G4BOptnForceFreeFlight* operation = fFreeF << 151 if ( callingProcess->GetWrappedProcess()-> << 152 { << 153 // -- the initial track weight will be r << 154 operation->ResetInitialTrackWeight(fInit << 155 return operation; << 156 } << 157 else << 158 { 160 { 159 return nullptr; << 161 G4BOptnForceFreeFlight* operation = fFreeFlightOperations[callingProcess]; >> 162 if ( callingProcess->GetWrappedProcess()->GetCurrentInteractionLength() < DBL_MAX/10. ) >> 163 { >> 164 // -- the initial track weight will be restored only by the first DoIt free flight: >> 165 operation->ResetInitialTrackWeight(fInitialTrackWeight); >> 166 return operation; >> 167 } >> 168 else >> 169 { >> 170 return nullptr; >> 171 } 160 } 172 } 161 } << 173 162 174 163 // -- Send force interaction operation to th 175 // -- Send force interaction operation to the callingProcess: 164 // ----------------------------------------- 176 // ---------------------------------------------------------- 165 // -- at this level, a copy of the track ent 177 // -- at this level, a copy of the track entering the volume was 166 // -- generated (borned) earlier. This copy 178 // -- generated (borned) earlier. This copy will make the forced 167 // -- interaction in the volume. 179 // -- interaction in the volume. 168 if ( fCurrentTrackData->fForceCollisionState 180 if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeForced ) 169 { << 170 // -- Remember if this calling process is << 171 // -- the PostStepGPIL loop (using default << 172 G4bool isFirstPhysGPIL = callingProcess-> << 173 << 174 // -- [*first process*] Initialize or upda << 175 if ( isFirstPhysGPIL ) << 176 { 181 { 177 // -- first step of cloned track, initia << 182 // -- Remember if this calling process is the first of the physics wrapper in 178 if ( track->GetCurrentStepNumber() == 1 << 183 // -- the PostStepGPIL loop (using default argument of method below): 179 { << 184 G4bool isFirstPhysGPIL = callingProcess-> GetIsFirstPostStepGPILInterface(); 180 fSharedForceInteractionOperation->Init << 181 } << 182 else << 183 { << 184 if ( fSharedForceInteractionOperation- << 185 { << 186 // -- means that some other physics << 187 // -- has occured, need to re-initia << 188 // -- [ Note the re-initialization i << 189 fSharedForceInteractionOperation->In << 190 } << 191 else << 192 { << 193 // -- means that some other non-phys << 194 // -- but track conserves its moment << 195 // -- forced interaction. << 196 // -- [ Note the update is only poss << 197 fSharedForceInteractionOperation->Up << 198 } << 199 } << 200 } << 201 185 202 // -- [*all processes*] Sanity check : it << 186 // -- [*first process*] Initialize or update force interaction operation: 203 // -- out is zero, weight would be infinit << 187 if ( isFirstPhysGPIL ) 204 // -- and abandon biasing. << 188 { 205 if ( fSharedForceInteractionOperation->Get << 189 // -- first step of cloned track, initialize the forced interaction operation: 206 { << 190 if ( track->GetCurrentStepNumber() == 1 ) fSharedForceInteractionOperation->Initialize( track ); 207 fCurrentTrackData->Reset(); << 191 else 208 return nullptr; << 192 { 209 } << 193 if ( fSharedForceInteractionOperation->GetInitialMomentum() != track->GetMomentum() ) >> 194 { >> 195 // -- means that some other physics process, not under control of the forced interaction operation, >> 196 // -- has occured, need to re-initialize the operation as distance to boundary has changed. >> 197 // -- [ Note the re-initialization is only possible for a Markovian law. ] >> 198 fSharedForceInteractionOperation->Initialize( track ); >> 199 } >> 200 else >> 201 { >> 202 // -- means that some other non-physics process (biasing or not, like step limit), has occured, >> 203 // -- but track conserves its momentum direction, only need to reduced the maximum distance for >> 204 // -- forced interaction. >> 205 // -- [ Note the update is only possible for a Markovian law. ] >> 206 fSharedForceInteractionOperation->UpdateForStep( track->GetStep() ); >> 207 } >> 208 } >> 209 } 210 210 211 // -- [* first process*] collect cross-sec << 211 // -- [*all processes*] Sanity check : it may happen in limit cases that distance to 212 // -- and winning process: << 212 // -- out is zero, weight would be infinite in this case: abort forced interaction 213 if ( isFirstPhysGPIL ) << 213 // -- and abandon biasing. 214 { << 214 if ( fSharedForceInteractionOperation->GetMaximumDistance() < DBL_MIN ) 215 // -- collect cross-sections: << 215 { 216 // -- ( Remember that the first of the G << 216 fCurrentTrackData->Reset(); 217 // -- of these cross-sections ) << 217 return 0; 218 const G4BiasingProcessSharedData* shared << 218 } 219 for ( std::size_t i = 0 ; i < (sharedDat << 220 { << 221 const G4BiasingProcessInterface* wrapp << 222 G4double interactionLength = wrapperPr << 223 // -- keep only well defined cross-sec << 224 // -- but cases where a threhold effec << 225 if ( interactionLength < DBL_MAX/10. ) << 226 fSharedForceInteractionOperation->Ad << 227 } << 228 // -- sample the shared law (interaction << 229 if ( fSharedForceInteractionOperation->G << 230 fSharedForceInteractionOperation->Samp << 231 } << 232 219 233 // -- [*all processes*] Send operation for << 220 // -- [* first process*] collect cross-sections and sample force law to determine interaction length 234 G4VBiasingOperation* operationToReturn = n << 221 // -- and winning process: 235 if ( callingProcess->GetWrappedProcess()-> << 222 if ( isFirstPhysGPIL ) 236 operationToReturn = fSharedForceInteract << 223 { 237 return operationToReturn; << 224 // -- collect cross-sections: >> 225 // -- ( Remember that the first of the G4BiasingProcessInterface triggers the update >> 226 // -- of these cross-sections ) >> 227 const G4BiasingProcessSharedData* sharedData = callingProcess->GetSharedData(); >> 228 for ( size_t i = 0 ; i < (sharedData->GetPhysicsBiasingProcessInterfaces()).size() ; i++ ) >> 229 { >> 230 const G4BiasingProcessInterface* wrapperProcess = ( sharedData->GetPhysicsBiasingProcessInterfaces() )[i]; >> 231 G4double interactionLength = wrapperProcess->GetWrappedProcess()->GetCurrentInteractionLength(); >> 232 // -- keep only well defined cross-sections, other processes are ignored. These are not pathological cases >> 233 // -- but cases where a threhold effect par example (eg pair creation) may be at play. (**!**) >> 234 if ( interactionLength < DBL_MAX/10. ) >> 235 fSharedForceInteractionOperation->AddCrossSection( wrapperProcess->GetWrappedProcess(), 1.0/interactionLength ); >> 236 } >> 237 // -- sample the shared law (interaction length, and winning process): >> 238 if ( fSharedForceInteractionOperation->GetNumberOfSharing() > 0 ) fSharedForceInteractionOperation->Sample(); >> 239 } >> 240 >> 241 // -- [*all processes*] Send operation for processes with well defined XS (see "**!**" above): >> 242 G4VBiasingOperation* operationToReturn = nullptr; >> 243 if ( callingProcess->GetWrappedProcess()->GetCurrentInteractionLength() < DBL_MAX/10. ) operationToReturn = fSharedForceInteractionOperation; >> 244 return operationToReturn; >> 245 238 246 239 } // -- end of "if ( fCurrentTrackData->fFor << 247 } // -- end of "if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeForced )" 240 248 241 249 242 // -- other cases here: particle appearing i 250 // -- other cases here: particle appearing in the volume by some 243 // -- previous interaction : we decide to no 251 // -- previous interaction : we decide to not bias these. 244 return nullptr; << 252 return 0; >> 253 245 } 254 } 246 255 247 G4VBiasingOperation* G4BOptrForceCollision:: << 256 248 ProposeNonPhysicsBiasingOperation(const G4Trac << 257 G4VBiasingOperation* G4BOptrForceCollision::ProposeNonPhysicsBiasingOperation(const G4Track* track, 249 const G4Bias << 258 const G4BiasingProcessInterface* /* callingProcess */) 250 { 259 { 251 if ( track->GetDefinition() != fParticleToBi 260 if ( track->GetDefinition() != fParticleToBias ) return nullptr; 252 261 253 // -- Apply biasing scheme only to tracks en 262 // -- Apply biasing scheme only to tracks entering the volume. 254 // -- A "cloning" is done: 263 // -- A "cloning" is done: 255 // -- - the primary will be forced flight u 264 // -- - the primary will be forced flight under a zero weight up to volume exit, 256 // -- where the weight will be restored w 265 // -- where the weight will be restored with proper weight for free flight 257 // -- - the clone will be forced to interac 266 // -- - the clone will be forced to interact in the volume. 258 if ( track->GetStep()->GetPreStepPoint()->Ge 267 if ( track->GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary ) // -- §§§ extent to case of a track shoot on the boundary ? 259 { << 268 { 260 // -- check that track is free of undergoi << 269 // -- check that track is free of undergoing biasing scheme ( no biasing data, or no active active ) 261 // -- Get possible track data: << 270 // -- Get possible track data: 262 fCurrentTrackData = (G4BOptrForceCollision << 271 fCurrentTrackData = (G4BOptrForceCollisionTrackData*)(track->GetAuxiliaryTrackInformation(fForceCollisionModelID)); 263 if ( fCurrentTrackData != nullptr ) << 272 if ( fCurrentTrackData != nullptr ) 264 { << 273 { 265 if ( fCurrentTrackData->IsFreeFromBiasin << 274 if ( fCurrentTrackData->IsFreeFromBiasing() ) 266 { << 275 { 267 // -- takes "ownership" (some track da << 276 // -- takes "ownership" (some track data created before, left free, reuse it): 268 fCurrentTrackData->fForceCollisionOper << 277 fCurrentTrackData->fForceCollisionOperator = this ; 269 } << 278 } >> 279 else >> 280 { >> 281 // §§§ Would something be really wrong in this case ? Could this be that a process made a zero step ? >> 282 } >> 283 } 270 else 284 else 271 { << 285 { 272 // Would something be really wrong in << 286 fCurrentTrackData = new G4BOptrForceCollisionTrackData( this ); 273 // Could this be that a process made a << 287 track->SetAuxiliaryTrackInformation(fForceCollisionModelID, fCurrentTrackData); 274 } << 288 } 275 } << 289 fCurrentTrackData->fForceCollisionState = ForceCollisionState::toBeCloned; 276 else << 290 fInitialTrackWeight = track->GetWeight(); 277 { << 291 fCloningOperation->SetCloneWeights(0.0, fInitialTrackWeight); 278 fCurrentTrackData = new G4BOptrForceColl << 292 return fCloningOperation; 279 track->SetAuxiliaryTrackInformation(fFor << 293 } 280 } << 281 fCurrentTrackData->fForceCollisionState = << 282 fInitialTrackWeight = track->GetWeight(); << 283 fCloningOperation->SetCloneWeights(0.0, fI << 284 << 285 return fCloningOperation; << 286 } << 287 294 >> 295 // -- 288 return nullptr; 296 return nullptr; 289 } 297 } 290 298 291 G4VBiasingOperation* G4BOptrForceCollision:: << 299 292 ProposeFinalStateBiasingOperation(const G4Trac << 300 G4VBiasingOperation* G4BOptrForceCollision::ProposeFinalStateBiasingOperation(const G4Track*, const G4BiasingProcessInterface* callingProcess) 293 const G4Bias << 294 { 301 { 295 // -- Propose at final state generation the 302 // -- Propose at final state generation the same operation which was proposed at GPIL level, 296 // -- (which is either the force free flight 303 // -- (which is either the force free flight or the force interaction operation). 297 // -- count on the process interface to coll 304 // -- count on the process interface to collect this operation: 298 return callingProcess->GetCurrentOccurenceBi 305 return callingProcess->GetCurrentOccurenceBiasingOperation(); 299 } 306 } 300 307 >> 308 301 void G4BOptrForceCollision::StartTracking( con 309 void G4BOptrForceCollision::StartTracking( const G4Track* track ) 302 { 310 { 303 fCurrentTrack = track; 311 fCurrentTrack = track; 304 fCurrentTrackData = nullptr; 312 fCurrentTrackData = nullptr; 305 } 313 } 306 314 >> 315 307 void G4BOptrForceCollision::EndTracking() 316 void G4BOptrForceCollision::EndTracking() 308 { 317 { 309 // -- check for consistency, operator should 318 // -- check for consistency, operator should have cleaned the track: 310 if ( fCurrentTrackData != nullptr ) 319 if ( fCurrentTrackData != nullptr ) 311 { << 312 if ( !fCurrentTrackData->IsFreeFromBiasing << 313 { 320 { 314 if ( (fCurrentTrack->GetTrackStatus() == << 321 if ( !fCurrentTrackData->IsFreeFromBiasing() ) 315 || (fCurrentTrack->GetTrackStatus() == << 322 { 316 { << 323 if ( (fCurrentTrack->GetTrackStatus() == fStopAndKill) || (fCurrentTrack->GetTrackStatus() == fKillTrackAndSecondaries) ) 317 G4ExceptionDescription ed; << 324 { 318 ed << "Current track deleted while under bia << 325 G4ExceptionDescription ed; 319 << GetName() << ". Will result in i << 326 ed << "Current track deleted while under biasing by " << GetName() << ". Will result in inconsistencies."; 320 G4Exception(" G4BOptrForceCollision::E << 327 G4Exception(" G4BOptrForceCollision::EndTracking()", 321 "BIAS.GEN.18", JustWarning << 328 "BIAS.GEN.18", 322 } << 329 JustWarning, 323 } << 330 ed); 324 } << 331 } 325 } << 332 } 326 << 333 } 327 void G4BOptrForceCollision:: << 334 } 328 OperationApplied( const G4BiasingProcessInterf << 335 329 G4BiasingAppliedCase B << 336 330 G4VBiasingOperation* o << 337 void G4BOptrForceCollision::OperationApplied( const G4BiasingProcessInterface* callingProcess, 331 const G4VParticleChange* ) << 338 G4BiasingAppliedCase BAC, >> 339 G4VBiasingOperation* operationApplied, >> 340 const G4VParticleChange* ) 332 { 341 { >> 342 333 if ( fCurrentTrackData == nullptr ) 343 if ( fCurrentTrackData == nullptr ) 334 { << 335 if ( BAC != BAC_None ) << 336 { 344 { 337 G4ExceptionDescription ed; << 345 if ( BAC != BAC_None ) 338 ed << " Internal inconsistency : please << 346 { 339 G4Exception(" G4BOptrForceCollision::Ope << 347 G4ExceptionDescription ed; 340 "BIAS.GEN.20.1", JustWarning << 348 ed << " Internal inconsistency : please submit bug report. " << G4endl; >> 349 G4Exception(" G4BOptrForceCollision::OperationApplied(...)", >> 350 "BIAS.GEN.20.1", >> 351 JustWarning, >> 352 ed); >> 353 } >> 354 return; 341 } 355 } 342 return; << 343 } << 344 356 345 if ( fCurrentTrackData->fForceCollisionState << 357 if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeCloned ) 346 { << 358 { 347 fCurrentTrackData->fForceCollisionState = << 359 fCurrentTrackData->fForceCollisionState = ForceCollisionState::toBeFreeFlight; 348 auto cloneData = new G4BOptrForceCollision << 360 auto cloneData = new G4BOptrForceCollisionTrackData( this ); 349 cloneData->fForceCollisionState = ForceCol << 361 cloneData->fForceCollisionState = ForceCollisionState::toBeForced; 350 fCloningOperation->GetCloneTrack()->SetAux << 362 fCloningOperation->GetCloneTrack()->SetAuxiliaryTrackInformation(fForceCollisionModelID, cloneData); 351 } << 363 } 352 else if ( fCurrentTrackData->fForceCollision 364 else if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeFreeFlight ) 353 { << 354 if ( fFreeFlightOperations[callingProcess] << 355 fCurrentTrackData->Reset(); // -- off bi << 356 } << 357 else if ( fCurrentTrackData->fForceCollision << 358 { << 359 if ( operationApplied != fSharedForceInter << 360 { 365 { 361 G4ExceptionDescription ed; << 366 if ( fFreeFlightOperations[callingProcess]->OperationComplete() ) fCurrentTrackData->Reset(); // -- off biasing for this track 362 ed << " Internal inconsistency : please << 367 } 363 G4Exception(" G4BOptrForceCollision::Ope << 368 else if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeForced ) 364 "BIAS.GEN.20.2", JustWarning << 365 } << 366 if ( fSharedForceInteractionOperation->Get << 367 { 369 { 368 if ( operationApplied != fSharedForceInt 370 if ( operationApplied != fSharedForceInteractionOperation ) 369 { << 371 { 370 G4ExceptionDescription ed; << 372 G4ExceptionDescription ed; 371 ed << " Internal inconsistency : pleas << 373 ed << " Internal inconsistency : please submit bug report. " << G4endl; 372 G4Exception(" G4BOptrForceCollision::O << 374 G4Exception(" G4BOptrForceCollision::OperationApplied(...)", 373 "BIAS.GEN.20.3", JustWarni << 375 "BIAS.GEN.20.2", 374 } << 376 JustWarning, >> 377 ed); >> 378 } >> 379 if ( fSharedForceInteractionOperation->GetInteractionOccured() ) >> 380 { >> 381 if ( operationApplied != fSharedForceInteractionOperation ) >> 382 { >> 383 G4ExceptionDescription ed; >> 384 ed << " Internal inconsistency : please submit bug report. " << G4endl; >> 385 G4Exception(" G4BOptrForceCollision::OperationApplied(...)", >> 386 "BIAS.GEN.20.3", >> 387 JustWarning, >> 388 ed); >> 389 } >> 390 } 375 } 391 } 376 } << 377 else 392 else 378 { << 379 if ( fCurrentTrackData->fForceCollisionSta << 380 { 393 { 381 G4ExceptionDescription ed; << 394 if ( fCurrentTrackData->fForceCollisionState != ForceCollisionState::free ) 382 ed << " Internal inconsistency : please << 395 { 383 G4Exception(" G4BOptrForceCollision::Ope << 396 G4ExceptionDescription ed; 384 "BIAS.GEN.20.4", JustWarning << 397 ed << " Internal inconsistency : please submit bug report. " << G4endl; >> 398 G4Exception(" G4BOptrForceCollision::OperationApplied(...)", >> 399 "BIAS.GEN.20.4", >> 400 JustWarning, >> 401 ed); >> 402 } 385 } 403 } 386 } << 387 } 404 } 388 405 389 void G4BOptrForceCollision:: << 406 390 OperationApplied( const G4BiasingProcessInterf << 407 void G4BOptrForceCollision::OperationApplied( const G4BiasingProcessInterface* /*callingProcess*/, G4BiasingAppliedCase /*biasingCase*/, 391 G4BiasingAppliedCase / << 408 G4VBiasingOperation* /*occurenceOperationApplied*/, G4double /*weightForOccurenceInteraction*/, 392 G4VBiasingOperation* / << 409 G4VBiasingOperation* finalStateOperationApplied, const G4VParticleChange* /*particleChangeProduced*/ ) 393 G4double / << 394 G4VBiasingOperation* f << 395 const G4VParticleChange* / << 396 { 410 { >> 411 397 if ( fCurrentTrackData->fForceCollisionState 412 if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeForced ) 398 { << 413 { 399 if ( finalStateOperationApplied != fShared << 414 if ( finalStateOperationApplied != fSharedForceInteractionOperation ) >> 415 { >> 416 G4ExceptionDescription ed; >> 417 ed << " Internal inconsistency : please submit bug report. " << G4endl; >> 418 G4Exception(" G4BOptrForceCollision::OperationApplied(...)", >> 419 "BIAS.GEN.20.5", >> 420 JustWarning, >> 421 ed); >> 422 } >> 423 if ( fSharedForceInteractionOperation->GetInteractionOccured() ) fCurrentTrackData->Reset(); // -- off biasing for this track >> 424 } >> 425 else 400 { 426 { 401 G4ExceptionDescription ed; 427 G4ExceptionDescription ed; 402 ed << " Internal inconsistency : please 428 ed << " Internal inconsistency : please submit bug report. " << G4endl; 403 G4Exception(" G4BOptrForceCollision::Ope 429 G4Exception(" G4BOptrForceCollision::OperationApplied(...)", 404 "BIAS.GEN.20.5", JustWarning << 430 "BIAS.GEN.20.6", >> 431 JustWarning, >> 432 ed); 405 } 433 } 406 if ( fSharedForceInteractionOperation->Get << 434 407 fCurrentTrackData->Reset(); // -- off bi << 408 } << 409 else << 410 { << 411 G4ExceptionDescription ed; << 412 ed << " Internal inconsistency : please su << 413 G4Exception(" G4BOptrForceCollision::Opera << 414 "BIAS.GEN.20.6", JustWarning, << 415 } << 416 } 435 } >> 436 417 437