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" << 31 #include "G4BiasingProcessInterface.hh" 27 #include "G4BiasingProcessInterface.hh" 32 #include "G4PhysicsModelCatalog.hh" << 33 28 34 #include "G4BOptnForceCommonTruncatedExp.hh" 29 #include "G4BOptnForceCommonTruncatedExp.hh" 35 #include "G4ILawCommonTruncatedExp.hh" 30 #include "G4ILawCommonTruncatedExp.hh" 36 #include "G4BOptnForceFreeFlight.hh" 31 #include "G4BOptnForceFreeFlight.hh" 37 #include "G4BOptnCloning.hh" 32 #include "G4BOptnCloning.hh" 38 33 39 #include "G4Step.hh" 34 #include "G4Step.hh" 40 #include "G4StepPoint.hh" 35 #include "G4StepPoint.hh" 41 #include "G4VProcess.hh" 36 #include "G4VProcess.hh" 42 37 43 #include "G4ParticleDefinition.hh" 38 #include "G4ParticleDefinition.hh" 44 #include "G4ParticleTable.hh" 39 #include "G4ParticleTable.hh" 45 40 46 #include "G4SystemOfUnits.hh" 41 #include "G4SystemOfUnits.hh" 47 42 48 // -- Consider calling other constructor, than << 43 G4BOptrForceCollision::G4BOptrForceCollision(G4String particleName, G4String name) 49 G4BOptrForceCollision:: << 50 G4BOptrForceCollision(const G4String& particle << 51 const G4String& name) << 52 : G4VBiasingOperator(name), 44 : G4VBiasingOperator(name), 53 fForceCollisionModelID(G4PhysicsModelCatal << 45 fFirstProcess(0), fLastProcess(0), >> 46 fSetup(true) 54 { 47 { 55 fSharedForceInteractionOperation = new G4BOp 48 fSharedForceInteractionOperation = new G4BOptnForceCommonTruncatedExp("SharedForceInteraction"); 56 fCloningOperation = new G4BOptnCloning("Clon << 49 fCloningOperation = new G4BOptnCloning("Cloning"); 57 fParticleToBias = G4ParticleTable::GetPartic << 50 fParticle = G4ParticleTable::GetParticleTable()->FindParticle(particleName); 58 51 59 if ( fParticleToBias == nullptr ) << 52 if ( fParticle == 0 ) 60 { << 53 { 61 G4ExceptionDescription ed; << 54 G4ExceptionDescription ed; 62 ed << " Particle `" << particleName << "' << 55 ed << " Particle `" << particleName << "' not found !" << G4endl; 63 G4Exception(" G4BOptrForceCollision::G4BOp << 56 G4Exception(" G4BOptrForceCollision::G4BOptrForceCollision(...)", 64 "BIAS.GEN.07", JustWarning, ed << 57 "BIAS.GEN.07", 65 } << 58 JustWarning, >> 59 ed); >> 60 } 66 } 61 } 67 62 68 G4BOptrForceCollision:: << 63 G4BOptrForceCollision::G4BOptrForceCollision(const G4ParticleDefinition* particle, G4String name) 69 G4BOptrForceCollision(const G4ParticleDefiniti << 70 const G4String& name) << 71 : G4VBiasingOperator(name), 64 : G4VBiasingOperator(name), 72 fForceCollisionModelID(G4PhysicsModelCatal << 65 fFirstProcess(0), fLastProcess(0), >> 66 fSetup(true) 73 { 67 { 74 fSharedForceInteractionOperation = new G4BOp 68 fSharedForceInteractionOperation = new G4BOptnForceCommonTruncatedExp("SharedForceInteraction"); 75 fCloningOperation = new G4BOptnCloning("Clon << 69 fCloningOperation = new G4BOptnCloning("Cloning"); 76 fParticleToBias = particle; << 70 fParticle = particle; 77 } 71 } 78 72 79 G4BOptrForceCollision::~G4BOptrForceCollision( 73 G4BOptrForceCollision::~G4BOptrForceCollision() 80 { 74 { 81 for ( auto it = fFreeFlightOperations.cbegin << 75 for ( std::map< const G4BiasingProcessInterface*, G4BOptnForceFreeFlight* >::iterator it = fFreeFlightOperations.begin() ; 82 it != fFreeFlightOperations.cend( << 76 it != fFreeFlightOperations.end() ; 83 { << 77 it++ ) delete (*it).second; 84 delete (*it).second; << 85 } << 86 delete fSharedForceInteractionOperation; 78 delete fSharedForceInteractionOperation; 87 delete fCloningOperation; 79 delete fCloningOperation; 88 } 80 } 89 81 90 void G4BOptrForceCollision::Configure() << 91 { << 92 // -- build free flight operations: << 93 ConfigureForWorker(); << 94 } << 95 << 96 void G4BOptrForceCollision::ConfigureForWorker << 97 { << 98 // -- start by remembering processes under b << 99 // and create needed biasing operations: << 100 if ( fSetup ) << 101 { << 102 const G4ProcessManager* processManager = f << 103 const G4BiasingProcessSharedData* interfac << 104 if ( interfaceProcessSharedData ) // -- sh << 105 // -- to a vol << 106 { << 107 for ( std::size_t i = 0 ; i < (interface << 108 { << 109 const G4BiasingProcessInterface* wrapp << 110 (interfaceProcessSharedData->GetPhys << 111 const G4String& operationName = "FreeF << 112 fFreeFlightOperations[wrapperProcess] << 113 } << 114 } << 115 fSetup = false; << 116 } << 117 } << 118 << 119 void G4BOptrForceCollision::StartRun() << 120 { << 121 } << 122 82 123 G4VBiasingOperation* << 83 G4VBiasingOperation* G4BOptrForceCollision::ProposeOccurenceBiasingOperation(const G4Track* track, const G4BiasingProcessInterface* callingProcess) 124 G4BOptrForceCollision::ProposeOccurenceBiasing << 125 const G4Biasing << 126 { 84 { 127 // -- does nothing if particle is not of req << 85 if ( track->GetDefinition() != fParticle ) return 0; 128 if ( track->GetDefinition() != fParticleToBi << 129 86 130 // -- trying to get auxiliary track data... << 87 // -- start by remembering processes under biasing, and create needed biasing operations: 131 if ( fCurrentTrackData == nullptr ) << 88 // -- ( Might consider moving this in a less called method. ) 132 { << 89 if ( fSetup ) 133 // ... and if the track has no aux. track << 134 fCurrentTrackData = (G4BOptrForceCollision << 135 if ( fCurrentTrackData == nullptr ) return << 136 } << 137 << 138 // -- Send force free flight to the callingP << 139 // ----------------------------------------- << 140 // -- The track has been cloned in the previ << 141 // -- forced for a free flight. << 142 // -- This track will fly with 0.0 weight du << 143 // -- it is to forbid the double counting wi << 144 // -- Its weight is restored at the end of i << 145 // -- being its initial weight * the weight << 146 // -- this last one being per process. The i << 147 // -- arbitrary asked to the first operation << 148 if ( fCurrentTrackData->fForceCollisionState << 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 { 90 { 159 return nullptr; << 91 if ( ( fFirstProcess == 0 ) && ( callingProcess->GetIsFirstPostStepGPILInterface() ) ) fFirstProcess = callingProcess; >> 92 if ( fLastProcess == 0 ) >> 93 { >> 94 fProcesses.push_back(callingProcess); >> 95 G4String operationName = "FreeFlight-"+callingProcess->GetWrappedProcess()->GetProcessName(); >> 96 fFreeFlightOperations[callingProcess] = new G4BOptnForceFreeFlight(operationName); >> 97 if ( callingProcess->GetIsLastPostStepGPILInterface() ) >> 98 { >> 99 fLastProcess = callingProcess; >> 100 fSetup = false; >> 101 } >> 102 } 160 } 103 } 161 } << 104 162 << 105 163 // -- Send force interaction operation to th 106 // -- Send force interaction operation to the callingProcess: 164 // ----------------------------------------- 107 // ---------------------------------------------------------- 165 // -- at this level, a copy of the track ent 108 // -- at this level, a copy of the track entering the volume was 166 // -- generated (borned) earlier. This copy 109 // -- generated (borned) earlier. This copy will make the forced 167 // -- interaction in the volume. 110 // -- interaction in the volume. 168 if ( fCurrentTrackData->fForceCollisionState << 111 if ( GetBirthOperation( track ) == fCloningOperation ) 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 { 112 { 177 // -- first step of cloned track, initia << 113 // -- forced interaction already occured, abort. 178 if ( track->GetCurrentStepNumber() == 1 << 114 // -- [Note that if ones would redo a forced interaction, it 179 { << 115 // -- would require an other cloning before, if one wants to conserve 180 fSharedForceInteractionOperation->Init << 116 // -- the weight.] 181 } << 117 if ( fSharedForceInteractionOperation->GetInteractionOccured() ) return 0; 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 118 202 // -- [*all processes*] Sanity check : it << 119 if ( callingProcess == fFirstProcess ) 203 // -- out is zero, weight would be infinit << 120 { 204 // -- and abandon biasing. << 121 // -- first step of cloned track, initialize the forced interaction operation: 205 if ( fSharedForceInteractionOperation->Get << 122 if ( track->GetCurrentStepNumber() == 1 ) fSharedForceInteractionOperation->Initialize( track ); 206 { << 123 else 207 fCurrentTrackData->Reset(); << 124 { 208 return nullptr; << 125 if ( fSharedForceInteractionOperation->GetInitialMomentum() != track->GetMomentum() ) 209 } << 126 { >> 127 // -- means that some other physics process, not under control of the forced interaction operation, >> 128 // -- has occured, need to re-initialize the operation as distance to boundary has changed. >> 129 // -- [ Note the re-initialization is only possible for a Markovian law. ] >> 130 fSharedForceInteractionOperation->Initialize( track ); >> 131 } >> 132 else >> 133 { >> 134 // -- means that some other non-physics process (biasing or not, like step limit), has occured, >> 135 // -- but track conserves its momentum direction, only need to reduced the maximum distance for >> 136 // -- forced interaction. >> 137 // -- [ Note the update is only possible for a Markovian law. ] >> 138 fSharedForceInteractionOperation->UpdateForStep( track->GetStep() ); >> 139 } >> 140 } >> 141 } 210 142 211 // -- [* first process*] collect cross-sec << 143 // -- Sanity check : it may happen in limit cases that distance to out is zero, 212 // -- and winning process: << 144 // -- weight would be infinite in this case. Abort forced interaction. 213 if ( isFirstPhysGPIL ) << 145 if ( fSharedForceInteractionOperation->GetMaximumDistance() < DBL_MIN ) return 0; 214 { << 215 // -- collect cross-sections: << 216 // -- ( Remember that the first of the G << 217 // -- of these cross-sections ) << 218 const G4BiasingProcessSharedData* shared << 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 146 233 // -- [*all processes*] Send operation for << 147 // -- conditions to apply forced interaction are met, set up physics: 234 G4VBiasingOperation* operationToReturn = n << 148 // -- Collects well-defined cross-sections... 235 if ( callingProcess->GetWrappedProcess()-> << 149 G4double currentInteractionLength = callingProcess->GetWrappedProcess()->GetCurrentInteractionLength(); 236 operationToReturn = fSharedForceInteract << 150 G4VBiasingOperation* operationToReturn = 0; 237 return operationToReturn; << 151 if ( currentInteractionLength < DBL_MAX/10. ) 238 << 152 { 239 } // -- end of "if ( fCurrentTrackData->fFor << 153 fSharedForceInteractionOperation->AddCrossSection( callingProcess->GetWrappedProcess(), 1.0/currentInteractionLength ); >> 154 operationToReturn = fSharedForceInteractionOperation; >> 155 } >> 156 // -- ... if current process is the last one, cross-section collection is finished. >> 157 // -- Operation is ready to sample the force interaction law and to randomly select >> 158 // -- the process to be applied. >> 159 if ( ( callingProcess == fLastProcess ) && >> 160 ( fSharedForceInteractionOperation->GetCommonTruncatedExpLaw()->GetNumberOfSharing() > 0 ) ) >> 161 fSharedForceInteractionOperation->Sample(); >> 162 >> 163 // -- back to current process (last one or not), if meaningful cross section, bias it returning the force operation: >> 164 return operationToReturn; 240 165 >> 166 } // -- end of " if ( GetBirthOperation( track ) == fCloningOperation ) " >> 167 >> 168 >> 169 >> 170 // -- Send force free flight to the callingProcess: >> 171 // ------------------------------------------------ >> 172 // -- At this point a track cloning happened in the previous step, >> 173 // -- we request the continuing/current track to be forced flight. >> 174 // -- Note this track will fly with 0.0 weight during its forced flight: >> 175 // -- it is to forbid the double counting with the force interaction track. >> 176 // -- Its weight is restored at the end of its free flight, this weight >> 177 // -- being its initial weight * the weight for the free flight travel, >> 178 // -- this last one being per process. The initial weight is common, and is >> 179 // -- arbitrary asked to the first operation to take care of it. >> 180 if ( fPreviousOperationApplied == fCloningOperation ) >> 181 { >> 182 G4BOptnForceFreeFlight* operation = fFreeFlightOperations[callingProcess]; >> 183 if ( callingProcess->GetWrappedProcess()->GetCurrentInteractionLength() < DBL_MAX/10. ) >> 184 { >> 185 // -- the initial track weight will be restored only by the first DoIt free flight: >> 186 operation->ResetInitialTrackWeight(fInitialTrackWeight); >> 187 return operation; >> 188 } >> 189 } >> 190 // -- If forced flight was already requested for the calling process, this flight >> 191 // -- may have been interupted by some other non-physics process : request >> 192 // -- process to continue with same forced flight: >> 193 // -- ** ?? ** Incorrect here in case of flight interrupted by a *physics process*. Ie case >> 194 // -- ** ?? ** of a subset of physics processes forced is not treated correctly here ** ?? ** >> 195 else if ( callingProcess->GetPreviousOccurenceBiasingOperation() == fFreeFlightOperations[callingProcess] ) >> 196 return fFreeFlightOperations[callingProcess]; 241 197 242 // -- other cases here: particle appearing i 198 // -- other cases here: particle appearing in the volume by some 243 // -- previous interaction : we decide to no 199 // -- previous interaction : we decide to not bias these. 244 return nullptr; << 200 return 0; >> 201 245 } 202 } 246 203 247 G4VBiasingOperation* G4BOptrForceCollision:: << 204 248 ProposeNonPhysicsBiasingOperation(const G4Trac << 205 G4VBiasingOperation* G4BOptrForceCollision::ProposeNonPhysicsBiasingOperation(const G4Track* track, 249 const G4Bias << 206 const G4BiasingProcessInterface*) 250 { 207 { 251 if ( track->GetDefinition() != fParticleToBi << 208 if ( track->GetDefinition() != fParticle ) return 0; 252 209 253 // -- Apply biasing scheme only to tracks en << 210 // -- bias only tracks entering the volume. 254 // -- A "cloning" is done: 211 // -- A "cloning" is done: 255 // -- - the primary will be forced flight u 212 // -- - the primary will be forced flight under a zero weight up to volume exit, 256 // -- where the weight will be restored w 213 // -- where the weight will be restored with proper weight for free flight 257 // -- - the clone will be forced to interac 214 // -- - the clone will be forced to interact in the volume. 258 if ( track->GetStep()->GetPreStepPoint()->Ge << 215 if ( track->GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary ) 259 { << 260 // -- check that track is free of undergoi << 261 // -- Get possible track data: << 262 fCurrentTrackData = (G4BOptrForceCollision << 263 if ( fCurrentTrackData != nullptr ) << 264 { 216 { 265 if ( fCurrentTrackData->IsFreeFromBiasin << 217 fSharedForceInteractionOperation->SetInteractionOccured( false ); 266 { << 218 fInitialTrackWeight = track->GetWeight(); 267 // -- takes "ownership" (some track da << 219 fCloningOperation->SetCloneWeights(0.0, fInitialTrackWeight); 268 fCurrentTrackData->fForceCollisionOper << 220 return fCloningOperation; 269 } << 270 else << 271 { << 272 // Would something be really wrong in << 273 // Could this be that a process made a << 274 } << 275 } 221 } 276 else << 277 { << 278 fCurrentTrackData = new G4BOptrForceColl << 279 track->SetAuxiliaryTrackInformation(fFor << 280 } << 281 fCurrentTrackData->fForceCollisionState = << 282 fInitialTrackWeight = track->GetWeight(); << 283 fCloningOperation->SetCloneWeights(0.0, fI << 284 222 285 return fCloningOperation; << 223 // -- for all other cases: does nothing 286 } << 224 return 0; 287 << 288 return nullptr; << 289 } 225 } 290 226 291 G4VBiasingOperation* G4BOptrForceCollision:: << 292 ProposeFinalStateBiasingOperation(const G4Trac << 293 const G4Bias << 294 { << 295 // -- Propose at final state generation the << 296 // -- (which is either the force free flight << 297 // -- count on the process interface to coll << 298 return callingProcess->GetCurrentOccurenceBi << 299 } << 300 227 301 void G4BOptrForceCollision::StartTracking( con << 228 void G4BOptrForceCollision::StartTracking( const G4Track* ) 302 { 229 { 303 fCurrentTrack = track; << 230 fPreviousOperationApplied = 0; 304 fCurrentTrackData = nullptr; << 305 } 231 } 306 232 307 void G4BOptrForceCollision::EndTracking() << 308 { << 309 // -- check for consistency, operator should << 310 if ( fCurrentTrackData != nullptr ) << 311 { << 312 if ( !fCurrentTrackData->IsFreeFromBiasing << 313 { << 314 if ( (fCurrentTrack->GetTrackStatus() == << 315 || (fCurrentTrack->GetTrackStatus() == << 316 { << 317 G4ExceptionDescription ed; << 318 ed << "Current track deleted while under bia << 319 << GetName() << ". Will result in i << 320 G4Exception(" G4BOptrForceCollision::E << 321 "BIAS.GEN.18", JustWarning << 322 } << 323 } << 324 } << 325 } << 326 233 327 void G4BOptrForceCollision:: << 234 void G4BOptrForceCollision::ExitBiasing( const G4Track* track, const G4BiasingProcessInterface* ) 328 OperationApplied( const G4BiasingProcessInterf << 329 G4BiasingAppliedCase B << 330 G4VBiasingOperation* o << 331 const G4VParticleChange* ) << 332 { 235 { 333 if ( fCurrentTrackData == nullptr ) << 236 fPreviousOperationApplied = 0; 334 { << 237 // -- clean-up track for what happens with this operator: 335 if ( BAC != BAC_None ) << 238 ForgetTrack ( track ); 336 { << 337 G4ExceptionDescription ed; << 338 ed << " Internal inconsistency : please << 339 G4Exception(" G4BOptrForceCollision::Ope << 340 "BIAS.GEN.20.1", JustWarning << 341 } << 342 return; << 343 } << 344 << 345 if ( fCurrentTrackData->fForceCollisionState << 346 { << 347 fCurrentTrackData->fForceCollisionState = << 348 auto cloneData = new G4BOptrForceCollision << 349 cloneData->fForceCollisionState = ForceCol << 350 fCloningOperation->GetCloneTrack()->SetAux << 351 } << 352 else if ( fCurrentTrackData->fForceCollision << 353 { << 354 if ( fFreeFlightOperations[callingProcess] << 355 fCurrentTrackData->Reset(); // -- off bi << 356 } << 357 else if ( fCurrentTrackData->fForceCollision << 358 { << 359 if ( operationApplied != fSharedForceInter << 360 { << 361 G4ExceptionDescription ed; << 362 ed << " Internal inconsistency : please << 363 G4Exception(" G4BOptrForceCollision::Ope << 364 "BIAS.GEN.20.2", JustWarning << 365 } << 366 if ( fSharedForceInteractionOperation->Get << 367 { << 368 if ( operationApplied != fSharedForceInt << 369 { << 370 G4ExceptionDescription ed; << 371 ed << " Internal inconsistency : pleas << 372 G4Exception(" G4BOptrForceCollision::O << 373 "BIAS.GEN.20.3", JustWarni << 374 } << 375 } << 376 } << 377 else << 378 { << 379 if ( fCurrentTrackData->fForceCollisionSta << 380 { << 381 G4ExceptionDescription ed; << 382 ed << " Internal inconsistency : please << 383 G4Exception(" G4BOptrForceCollision::Ope << 384 "BIAS.GEN.20.4", JustWarning << 385 } << 386 } << 387 } 239 } 388 240 389 void G4BOptrForceCollision:: << 241 390 OperationApplied( const G4BiasingProcessInterf << 242 void G4BOptrForceCollision::OperationApplied( const G4BiasingProcessInterface* callingProcess, G4BiasingAppliedCase, 391 G4BiasingAppliedCase / << 243 G4VBiasingOperation* operationApplied, const G4VParticleChange* particleChangeProduced ) 392 G4VBiasingOperation* / << 393 G4double / << 394 G4VBiasingOperation* f << 395 const G4VParticleChange* / << 396 { 244 { 397 if ( fCurrentTrackData->fForceCollisionState << 245 fPreviousOperationApplied = operationApplied; 398 { << 246 if ( operationApplied == fCloningOperation ) 399 if ( finalStateOperationApplied != fShared << 247 RememberSecondaries( callingProcess, operationApplied, particleChangeProduced ); 400 { << 401 G4ExceptionDescription ed; << 402 ed << " Internal inconsistency : please << 403 G4Exception(" G4BOptrForceCollision::Ope << 404 "BIAS.GEN.20.5", JustWarning << 405 } << 406 if ( fSharedForceInteractionOperation->Get << 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 } 248 } 417 249