Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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(-1),
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(-1),
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 // -- Create ID for force collision:
97 fForceCollisionModelID = G4PhysicsModelCatalog::Register("GenBiasForceCollision");
98
99 // -- build free flight operations:
101}
102
103
105{
106 // -- start by remembering processes under biasing, and create needed biasing operations:
107 if ( fSetup )
108 {
109 // -- get back ID created in master thread in case of MT (or reget just created ID in sequential mode):
110 fForceCollisionModelID = G4PhysicsModelCatalog::Register("GenBiasForceCollision");
111
112 const G4ProcessManager* processManager = fParticleToBias->GetProcessManager();
113 const G4BiasingProcessSharedData* interfaceProcessSharedData = G4BiasingProcessInterface::GetSharedData( processManager );
114 if ( interfaceProcessSharedData ) // -- sharedData tested, as is can happen a user attaches an operator
115 // -- to a volume but without defining BiasingProcessInterface processes.
116 {
117 for ( size_t i = 0 ; i < (interfaceProcessSharedData->GetPhysicsBiasingProcessInterfaces()).size(); i++ )
118 {
119 const G4BiasingProcessInterface* wrapperProcess =
120 (interfaceProcessSharedData->GetPhysicsBiasingProcessInterfaces())[i];
121 G4String operationName = "FreeFlight-"+wrapperProcess->GetWrappedProcess()->GetProcessName();
122 fFreeFlightOperations[wrapperProcess] = new G4BOptnForceFreeFlight(operationName);
123 }
124 }
125 fSetup = false;
126 }
127}
128
129
131{
132}
133
134
135G4VBiasingOperation* G4BOptrForceCollision::ProposeOccurenceBiasingOperation(const G4Track* track, const G4BiasingProcessInterface* callingProcess)
136{
137 // -- does nothing if particle is not of requested type:
138 if ( track->GetDefinition() != fParticleToBias ) return 0;
139
140 // -- trying to get auxiliary track data...
141 if ( fCurrentTrackData == nullptr )
142 {
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):
144 fCurrentTrackData = (G4BOptrForceCollisionTrackData*)(track->GetAuxiliaryTrackInformation(fForceCollisionModelID));
145 if ( fCurrentTrackData == nullptr ) return nullptr;
146 }
147
148
149 // -- Send force free flight to the callingProcess:
150 // ------------------------------------------------
151 // -- The track has been cloned in the previous step, it has now to be
152 // -- forced for a free flight.
153 // -- This track will fly with 0.0 weight during its forced flight:
154 // -- it is to forbid the double counting with the force interaction track.
155 // -- Its weight is restored at the end of its free flight, this weight
156 // -- being its initial weight * the weight for the free flight travel,
157 // -- this last one being per process. The initial weight is common, and is
158 // -- arbitrary asked to the first operation to take care of it.
159 if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeFreeFlight )
160 {
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 }
172 }
173
174
175 // -- Send force interaction operation to the callingProcess:
176 // ----------------------------------------------------------
177 // -- at this level, a copy of the track entering the volume was
178 // -- generated (borned) earlier. This copy will make the forced
179 // -- interaction in the volume.
180 if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeForced )
181 {
182 // -- Remember if this calling process is the first of the physics wrapper in
183 // -- the PostStepGPIL loop (using default argument of method below):
184 G4bool isFirstPhysGPIL = callingProcess-> GetIsFirstPostStepGPILInterface();
185
186 // -- [*first process*] Initialize or update force interaction operation:
187 if ( isFirstPhysGPIL )
188 {
189 // -- first step of cloned track, initialize the forced interaction operation:
190 if ( track->GetCurrentStepNumber() == 1 ) fSharedForceInteractionOperation->Initialize( track );
191 else
192 {
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
211 // -- [*all processes*] Sanity check : it may happen in limit cases that distance to
212 // -- out is zero, weight would be infinite in this case: abort forced interaction
213 // -- and abandon biasing.
214 if ( fSharedForceInteractionOperation->GetMaximumDistance() < DBL_MIN )
215 {
216 fCurrentTrackData->Reset();
217 return 0;
218 }
219
220 // -- [* first process*] collect cross-sections and sample force law to determine interaction length
221 // -- and winning process:
222 if ( isFirstPhysGPIL )
223 {
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
246
247 } // -- end of "if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeForced )"
248
249
250 // -- other cases here: particle appearing in the volume by some
251 // -- previous interaction : we decide to not bias these.
252 return 0;
253
254}
255
256
257G4VBiasingOperation* G4BOptrForceCollision::ProposeNonPhysicsBiasingOperation(const G4Track* track,
258 const G4BiasingProcessInterface* /* callingProcess */)
259{
260 if ( track->GetDefinition() != fParticleToBias ) return nullptr;
261
262 // -- Apply biasing scheme only to tracks entering the volume.
263 // -- A "cloning" is done:
264 // -- - the primary will be forced flight under a zero weight up to volume exit,
265 // -- where the weight will be restored with proper weight for free flight
266 // -- - the clone will be forced to interact in the volume.
267 if ( track->GetStep()->GetPreStepPoint()->GetStepStatus() == fGeomBoundary ) // -- §§§ extent to case of a track shoot on the boundary ?
268 {
269 // -- check that track is free of undergoing biasing scheme ( no biasing data, or no active active )
270 // -- Get possible track data:
271 fCurrentTrackData = (G4BOptrForceCollisionTrackData*)(track->GetAuxiliaryTrackInformation(fForceCollisionModelID));
272 if ( fCurrentTrackData != nullptr )
273 {
274 if ( fCurrentTrackData->IsFreeFromBiasing() )
275 {
276 // -- takes "ownership" (some track data created before, left free, reuse it):
277 fCurrentTrackData->fForceCollisionOperator = this ;
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 }
284 else
285 {
286 fCurrentTrackData = new G4BOptrForceCollisionTrackData( this );
287 track->SetAuxiliaryTrackInformation(fForceCollisionModelID, fCurrentTrackData);
288 }
289 fCurrentTrackData->fForceCollisionState = ForceCollisionState::toBeCloned;
290 fInitialTrackWeight = track->GetWeight();
291 fCloningOperation->SetCloneWeights(0.0, fInitialTrackWeight);
292 return fCloningOperation;
293 }
294
295 // --
296 return nullptr;
297}
298
299
300G4VBiasingOperation* G4BOptrForceCollision::ProposeFinalStateBiasingOperation(const G4Track*, const G4BiasingProcessInterface* callingProcess)
301{
302 // -- Propose at final state generation the same operation which was proposed at GPIL level,
303 // -- (which is either the force free flight or the force interaction operation).
304 // -- count on the process interface to collect this operation:
305 return callingProcess->GetCurrentOccurenceBiasingOperation();
306}
307
308
310{
311 fCurrentTrack = track;
312 fCurrentTrackData = nullptr;
313}
314
315
317{
318 // -- check for consistency, operator should have cleaned the track:
319 if ( fCurrentTrackData != nullptr )
320 {
321 if ( !fCurrentTrackData->IsFreeFromBiasing() )
322 {
323 if ( (fCurrentTrack->GetTrackStatus() == fStopAndKill) || (fCurrentTrack->GetTrackStatus() == fKillTrackAndSecondaries) )
324 {
326 ed << "Current track deleted while under biasing by " << GetName() << ". Will result in inconsistencies.";
327 G4Exception(" G4BOptrForceCollision::EndTracking()",
328 "BIAS.GEN.18",
330 ed);
331 }
332 }
333 }
334}
335
336
339 G4VBiasingOperation* operationApplied,
340 const G4VParticleChange* )
341{
342
343 if ( fCurrentTrackData == nullptr )
344 {
345 if ( BAC != BAC_None )
346 {
348 ed << " Internal inconsistency : please submit bug report. " << G4endl;
349 G4Exception(" G4BOptrForceCollision::OperationApplied(...)",
350 "BIAS.GEN.20.1",
352 ed);
353 }
354 return;
355 }
356
357 if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeCloned )
358 {
359 fCurrentTrackData->fForceCollisionState = ForceCollisionState::toBeFreeFlight;
360 auto cloneData = new G4BOptrForceCollisionTrackData( this );
361 cloneData->fForceCollisionState = ForceCollisionState::toBeForced;
362 fCloningOperation->GetCloneTrack()->SetAuxiliaryTrackInformation(fForceCollisionModelID, cloneData);
363 }
364 else if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeFreeFlight )
365 {
366 if ( fFreeFlightOperations[callingProcess]->OperationComplete() ) fCurrentTrackData->Reset(); // -- off biasing for this track
367 }
368 else if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeForced )
369 {
370 if ( operationApplied != fSharedForceInteractionOperation )
371 {
373 ed << " Internal inconsistency : please submit bug report. " << G4endl;
374 G4Exception(" G4BOptrForceCollision::OperationApplied(...)",
375 "BIAS.GEN.20.2",
377 ed);
378 }
379 if ( fSharedForceInteractionOperation->GetInteractionOccured() )
380 {
381 if ( operationApplied != fSharedForceInteractionOperation )
382 {
384 ed << " Internal inconsistency : please submit bug report. " << G4endl;
385 G4Exception(" G4BOptrForceCollision::OperationApplied(...)",
386 "BIAS.GEN.20.3",
388 ed);
389 }
390 }
391 }
392 else
393 {
394 if ( fCurrentTrackData->fForceCollisionState != ForceCollisionState::free )
395 {
397 ed << " Internal inconsistency : please submit bug report. " << G4endl;
398 G4Exception(" G4BOptrForceCollision::OperationApplied(...)",
399 "BIAS.GEN.20.4",
401 ed);
402 }
403 }
404}
405
406
408 G4VBiasingOperation* /*occurenceOperationApplied*/, G4double /*weightForOccurenceInteraction*/,
409 G4VBiasingOperation* finalStateOperationApplied, const G4VParticleChange* /*particleChangeProduced*/ )
410{
411
412 if ( fCurrentTrackData->fForceCollisionState == ForceCollisionState::toBeForced )
413 {
414 if ( finalStateOperationApplied != fSharedForceInteractionOperation )
415 {
417 ed << " Internal inconsistency : please submit bug report. " << G4endl;
418 G4Exception(" G4BOptrForceCollision::OperationApplied(...)",
419 "BIAS.GEN.20.5",
421 ed);
422 }
423 if ( fSharedForceInteractionOperation->GetInteractionOccured() ) fCurrentTrackData->Reset(); // -- off biasing for this track
424 }
425 else
426 {
428 ed << " Internal inconsistency : please submit bug report. " << G4endl;
429 G4Exception(" G4BOptrForceCollision::OperationApplied(...)",
430 "BIAS.GEN.20.6",
432 ed);
433 }
434
435}
436
G4BiasingAppliedCase
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
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()
static G4int Register(const G4String &)
G4StepStatus GetStepStatus() const
G4StepPoint * GetPreStepPoint() const
G4TrackStatus GetTrackStatus() const
void SetAuxiliaryTrackInformation(G4int idx, G4VAuxiliaryTrackInformation *info) const
Definition: G4Track.cc:198
G4double GetWeight() const
G4int GetCurrentStepNumber() const
G4ThreeVector GetMomentum() const
G4ParticleDefinition * GetDefinition() const
G4VAuxiliaryTrackInformation * GetAuxiliaryTrackInformation(G4int idx) const
Definition: G4Track.cc:218
const G4Step * GetStep() const
const G4String GetName() const
G4double GetCurrentInteractionLength() const
Definition: G4VProcess.hh:443
const G4String & GetProcessName() const
Definition: G4VProcess.hh:382
#define DBL_MIN
Definition: templates.hh:54
#define DBL_MAX
Definition: templates.hh:62