68 : nForcedRegions(0),nSecBiasedRegions(0),eIonisation(nullptr),
69 currentStepLimit(0.0),startTracking(true)
71 fSafetyMin = 1.e-6*mm;
75 fDirectionalSplitting =
false;
76 fDirectionalSplittingRadius = 0.;
78 fDirectionalSplittingWeights.clear();
98 if(0 < nForcedRegions) { idxForcedCouple.resize(numOfCouples, -1); }
99 if(0 < nSecBiasedRegions) { idxSecBiasedCouple.resize(numOfCouples, -1); }
102 for (
size_t j=0; j<numOfCouples; ++j) {
106 if(0 < nForcedRegions) {
107 for(
G4int i=0; i<nForcedRegions; ++i) {
108 if(forcedRegions[i]) {
109 if(pcuts == forcedRegions[i]->GetProductionCuts()) {
110 idxForcedCouple[j] = i;
116 if(0 < nSecBiasedRegions) {
117 for(
G4int i=0; i<nSecBiasedRegions; ++i) {
118 if(secBiasedRegions[i]) {
119 if(pcuts == secBiasedRegions[i]->GetProductionCuts()) {
120 idxSecBiasedCouple[j] = i;
130 if (fDirectionalSplitting) {
135 if (nForcedRegions > 0 && 0 < verbose) {
136 G4cout <<
" Forced Interaction is activated for "
139 <<
" inside G4Regions: " <<
G4endl;
140 for (
G4int i=0; i<nForcedRegions; ++i) {
141 const G4Region* r = forcedRegions[i];
145 if (nSecBiasedRegions > 0 && 0 < verbose) {
146 G4cout <<
" Secondary biasing is activated for "
149 <<
" inside G4Regions: " <<
G4endl;
150 for (
G4int i=0; i<nSecBiasedRegions; ++i) {
151 const G4Region* r = secBiasedRegions[i];
154 <<
" BiasingWeight= " << secBiasedWeight[i] <<
G4endl;
157 if (fDirectionalSplitting) {
158 G4cout <<
" Directional splitting activated, with target position: "
159 << fDirectionalSplittingTarget/cm
161 << fDirectionalSplittingRadius/cm
174 if(name ==
"" || name ==
"world" || name ==
"World") {
175 name =
"DefaultRegionForTheWorld";
179 G4cout <<
"### G4EmBiasingManager::ForcedInteraction WARNING: "
181 << rname <<
"> is unknown" <<
G4endl;
186 if (0 < nForcedRegions) {
187 for (
G4int i=0; i<nForcedRegions; ++i) {
188 if (reg == forcedRegions[i]) {
189 lengthForRegion[i] = val;
195 G4cout <<
"### G4EmBiasingManager::ForcedInteraction WARNING: "
196 << val <<
" < 0.0, so no activation for the G4Region <"
197 << rname <<
">" <<
G4endl;
202 forcedRegions.push_back(reg);
203 lengthForRegion.push_back(val);
219 if(name ==
"" || name ==
"world" || name ==
"World") {
220 name =
"DefaultRegionForTheWorld";
224 G4cout <<
"### G4EmBiasingManager::ActivateBremsstrahlungSplitting "
225 <<
"WARNING: G4Region <"
226 << rname <<
"> is unknown" <<
G4endl;
240 }
else if(0.0 < factor) {
246 if (0 < nSecBiasedRegions) {
247 for (
G4int i=0; i<nSecBiasedRegions; ++i) {
248 if (reg == secBiasedRegions[i]) {
249 secBiasedWeight[i] = w;
250 nBremSplitting[i] = nsplit;
251 secBiasedEnegryLimit[i] = energyLimit;
263 secBiasedRegions.push_back(reg);
264 secBiasedWeight.push_back(w);
265 nBremSplitting.push_back(nsplit);
266 secBiasedEnegryLimit.push_back(energyLimit);
277 startTracking =
false;
278 G4int i = idxForcedCouple[coupleIdx];
282 currentStepLimit = lengthForRegion[i];
283 if(currentStepLimit > 0.0) { currentStepLimit *=
G4UniformRand(); }
286 currentStepLimit -= previousStep;
288 if(currentStepLimit < 0.0) { currentStepLimit = 0.0; }
289 return currentStepLimit;
296 std::vector<G4DynamicParticle*>& vd,
305 G4int index = idxSecBiasedCouple[coupleIdx];
308 size_t n = vd.size();
313 if((0 < n && vd[0]->GetKineticEnergy() < secBiasedEnegryLimit[index])
314 || fDirectionalSplitting) {
316 G4int nsplit = nBremSplitting[index];
320 if(safety > fSafetyMin) { ApplyRangeCut(vd, track, eloss, safety); }
323 }
else if(1 == nsplit) {
324 weight = ApplyRussianRoulette(vd, index);
328 if (fDirectionalSplitting) {
329 weight = ApplyDirectionalSplitting(vd, track, currentModel, index, tcut);
334 weight = ApplySplitting(vd, track, currentModel, index, tcut);
349 std::vector<G4DynamicParticle*>& vd,
358 G4int index = idxSecBiasedCouple[coupleIdx];
361 size_t n = vd.size();
366 if((0 < n && vd[0]->GetKineticEnergy() < secBiasedEnegryLimit[index])
367 || fDirectionalSplitting) {
369 G4int nsplit = nBremSplitting[index];
373 if(safety > fSafetyMin) { ApplyRangeCut(vd, track, eloss, safety); }
376 }
else if(1 == nsplit) {
377 weight = ApplyRussianRoulette(vd, index);
381 if (fDirectionalSplitting) {
382 weight = ApplyDirectionalSplitting(vd, track, currentModel,
383 index, tcut, pPartChange);
388 weight = ApplySplitting(vd, track, currentModel, index, tcut);
405 G4int index = idxSecBiasedCouple[coupleIdx];
408 size_t n = track.size();
413 if(0 < n && track[0]->GetKineticEnergy() < secBiasedEnegryLimit[index]) {
415 G4int nsplit = nBremSplitting[index];
419 weight = secBiasedWeight[index];
420 for(
size_t k=0; k<n; ++k) {
436G4EmBiasingManager::ApplyRangeCut(std::vector<G4DynamicParticle*>& vd,
440 size_t n = vd.size();
446 for(
size_t k=0; k<
n; ++k) {
469 if (dist <= fDirectionalSplittingRadius && angle < halfpi) {
478G4EmBiasingManager::ApplySplitting(std::vector<G4DynamicParticle*>& vd,
487 size_t n = vd.size();
488 G4double w = secBiasedWeight[index];
490 if(1 != n || 1.0 <= w) {
return weight; }
495 G4int nsplit = nBremSplitting[index];
498 if(1 < nsplit && trackWeight>w) {
501 if(nsplit > (
G4int)tmpSecondaries.size()) {
502 tmpSecondaries.reserve(nsplit);
506 for(
G4int k=1; k<nsplit; ++k) {
507 tmpSecondaries.clear();
510 for (
size_t kk=0; kk<tmpSecondaries.size(); ++kk) {
511 vd.push_back(tmpSecondaries[kk]);
521G4EmBiasingManager::ApplyDirectionalSplitting(
522 std::vector<G4DynamicParticle*>& vd,
533 G4double w = secBiasedWeight[index];
535 fDirectionalSplittingWeights.clear();
537 fDirectionalSplittingWeights.push_back(weight);
542 G4int nsplit = nBremSplitting[index];
545 if(1 < nsplit && trackWeight>w) {
550 G4bool foundPrimaryParticle =
false;
553 G4double primaryWeight = trackWeight;
558 for (
G4int k=0; k<nsplit; ++k) {
560 tmpSecondaries.clear();
566 for (
size_t kk=0; kk<tmpSecondaries.size(); ++kk) {
567 if (tmpSecondaries[kk]->GetParticleDefinition() == theGamma) {
568 if (
CheckDirection(pos, tmpSecondaries[kk]->GetMomentumDirection())){
569 vd.push_back(tmpSecondaries[kk]);
570 fDirectionalSplittingWeights.push_back(1.);
572 vd.push_back(tmpSecondaries[kk]);
573 fDirectionalSplittingWeights.push_back(1./weight);
575 delete tmpSecondaries[kk];
576 tmpSecondaries[kk] =
nullptr;
579 vd.push_back(tmpSecondaries[kk]);
580 fDirectionalSplittingWeights.push_back(1./weight);
582 delete tmpSecondaries[kk];
583 tmpSecondaries[kk] =
nullptr;
593 if (!foundPrimaryParticle) {
595 primaryMomdir = momdir;
596 foundPrimaryParticle =
true;
597 primaryWeight = weight;
603 fDirectionalSplittingWeights.push_back(1.);
606 if (!foundPrimaryParticle) {
607 foundPrimaryParticle =
true;
609 primaryMomdir = momdir;
616 fDirectionalSplittingWeights.push_back(1./weight);
626 for (
size_t i = 0; i < vd.size(); ++i) {
627 fDirectionalSplittingWeights.push_back(1.);
640 if (fDirectionalSplittingWeights.size() >= (
unsigned int)(i+1) ) {
641 G4double w = fDirectionalSplittingWeights[i];
642 fDirectionalSplittingWeights[i] = 1.;
650G4EmBiasingManager::ApplyDirectionalSplitting(
651 std::vector<G4DynamicParticle*>& vd,
660 G4double w = secBiasedWeight[index];
662 fDirectionalSplittingWeights.clear();
664 fDirectionalSplittingWeights.push_back(weight);
669 G4int nsplit = nBremSplitting[index];
672 if(1 < nsplit && trackWeight>w) {
680 for (
G4int k=0; k<nsplit; ++k) {
682 tmpSecondaries.clear();
688 for (
size_t kk=0; kk < tmpSecondaries.size(); ++kk) {
689 if (
CheckDirection(pos, tmpSecondaries[kk]->GetMomentumDirection())) {
690 vd.push_back(tmpSecondaries[kk]);
691 fDirectionalSplittingWeights.push_back(1.);
693 vd.push_back(tmpSecondaries[kk]);
694 fDirectionalSplittingWeights.push_back(1./weight);
696 delete tmpSecondaries[kk];
697 tmpSecondaries[kk] =
nullptr;
702 for (
size_t i = 0; i < vd.size(); ++i) {
703 fDirectionalSplittingWeights.push_back(1.0);
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cout
Hep3Vector cross(const Hep3Vector &) const
double angle(const Hep3Vector &) const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
static G4Electron * Electron()
void SetDirectionalSplittingRadius(G4double r)
void SetDirectionalSplitting(G4bool v)
G4double ApplySecondaryBiasing(std::vector< G4DynamicParticle * > &, const G4Track &track, G4VEmModel *currentModel, G4ParticleChangeForGamma *pParticleChange, G4double &eloss, G4int coupleIdx, G4double tcut, G4double safety=0.0)
void ActivateSecondaryBiasing(const G4String ®ion, G4double factor, G4double energyLimit)
void Initialise(const G4ParticleDefinition &part, const G4String &procName, G4int verbose)
G4double GetWeight(G4int i)
G4bool CheckDirection(G4ThreeVector pos, G4ThreeVector momdir) const
void ActivateForcedInteraction(G4double length=0.0, const G4String &r="")
void SetDirectionalSplittingTarget(G4ThreeVector v)
G4double GetStepLimit(G4int coupleIdx, G4double previousStep)
static G4EmParameters * Instance()
G4double GetDirectionalSplittingRadius()
G4bool GetDirectionalSplitting() const
G4ThreeVector GetDirectionalSplittingTarget() const
static G4LossTableManager * Instance()
G4VEnergyLossProcess * GetEnergyLossProcess(const G4ParticleDefinition *)
G4ProductionCuts * GetProductionCuts() const
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
G4double GetProposedKineticEnergy() const
const G4ThreeVector & GetProposedMomentumDirection() const
G4double GetProposedKineticEnergy() const
void SetProposedKineticEnergy(G4double proposedKinEnergy)
const G4ThreeVector & GetProposedMomentumDirection() const
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
const G4String & GetParticleName() const
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
static G4RegionStore * GetInstance()
G4Region * GetRegion(const G4String &name, G4bool verbose=true) const
const G4String & GetName() const
G4double GetWeight() const
const G4ThreeVector & GetPosition() const
const G4DynamicParticle * GetDynamicParticle() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin=0.0, G4double tmax=DBL_MAX)=0
G4double GetRangeForLoss(G4double kineticEnergy, const G4MaterialCutsCouple *)
void ProposeWeight(G4double finalWeight)