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