Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4Scintillation.cc
Go to the documentation of this file.
1// ********************************************************************
2// * License and Disclaimer *
3// * *
4// * The Geant4 software is copyright of the Copyright Holders of *
5// * the Geant4 Collaboration. It is provided under the terms and *
6// * conditions of the Geant4 Software License, included in the file *
7// * LICENSE and available at http://cern.ch/geant4/license . These *
8// * include a list of copyright holders. *
9// * *
10// * Neither the authors of this software system, nor their employing *
11// * institutes,nor the agencies providing financial support for this *
12// * work make any representation or warranty, express or implied, *
13// * regarding this software system or assume any liability for its *
14// * use. Please see the license in the file LICENSE and URL above *
15// * for the full disclaimer and the limitation of liability. *
16// * *
17// * This code implementation is the result of the scientific and *
18// * technical work of the GEANT4 collaboration. *
19// * By using, copying, modifying or distributing the software (or *
20// * any work based on the software) you agree to acknowledge its *
21// * use in resulting scientific publications, and indicate your *
22// * acceptance of all terms of the Geant4 Software license. *
23// ********************************************************************
24//
25////////////////////////////////////////////////////////////////////////
26// Scintillation Light Class Implementation
27////////////////////////////////////////////////////////////////////////
28//
29// File: G4Scintillation.cc
30// Description: RestDiscrete Process - Generation of Scintillation Photons
31// Version: 1.0
32// Created: 1998-11-07
33// Author: Peter Gumplinger
34// Updated: 2010-10-20 Allow the scintillation yield to be a function
35// of energy deposited by particle type
36// Thanks to Zach Hartwig (Department of Nuclear
37// Science and Engineeering - MIT)
38// 2010-09-22 by Peter Gumplinger
39// > scintillation rise time included, thanks to
40// > Martin Goettlich/DESY
41// 2005-08-17 by Peter Gumplinger
42// > change variable name MeanNumPhotons -> MeanNumberOfPhotons
43// 2005-07-28 by Peter Gumplinger
44// > add G4ProcessType to constructor
45// 2004-08-05 by Peter Gumplinger
46// > changed StronglyForced back to Forced in GetMeanLifeTime
47// 2002-11-21 by Peter Gumplinger
48// > change to use G4Poisson for small MeanNumberOfPhotons
49// 2002-11-07 by Peter Gumplinger
50// > now allow for fast and slow scintillation component
51// 2002-11-05 by Peter Gumplinger
52// > now use scintillation constants from G4Material
53// 2002-05-09 by Peter Gumplinger
54// > use only the PostStepPoint location for the origin of
55// scintillation photons when energy is lost to the medium
56// by a neutral particle
57// 2000-09-18 by Peter Gumplinger
58// > change: aSecondaryPosition=x0+rand*aStep.GetDeltaPosition();
59// aSecondaryTrack->SetTouchable(0);
60// 2001-09-17, migration of Materials to pure STL (mma)
61// 2003-06-03, V.Ivanchenko fix compilation warnings
62//
63////////////////////////////////////////////////////////////////////////
64
65#include "G4Scintillation.hh"
66
67#include "globals.hh"
68#include "G4DynamicParticle.hh"
69#include "G4EmProcessSubType.hh"
70#include "G4Material.hh"
74#include "G4ParticleMomentum.hh"
75#include "G4ParticleTypes.hh"
78#include "G4PhysicsTable.hh"
79#include "G4Poisson.hh"
81#include "G4StepPoint.hh"
82#include "G4SystemOfUnits.hh"
83#include "G4ThreeVector.hh"
84#include "Randomize.hh"
86
87//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
89 G4ProcessType type)
90 : G4VRestDiscreteProcess(processName, type)
91 , fIntegralTable1(nullptr)
92 , fIntegralTable2(nullptr)
93 , fIntegralTable3(nullptr)
94 , fEmSaturation(nullptr)
95 , fNumPhotons(0)
96{
97 secID = G4PhysicsModelCatalog::GetModelID("model_Scintillation");
99
100#ifdef G4DEBUG_SCINTILLATION
101 ScintTrackEDep = 0.;
102 ScintTrackYield = 0.;
103#endif
104
105 if(verboseLevel > 0)
106 {
107 G4cout << GetProcessName() << " is created " << G4endl;
108 }
109 Initialise();
110}
111
112//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
114{
115 if(fIntegralTable1 != nullptr)
116 {
117 fIntegralTable1->clearAndDestroy();
118 delete fIntegralTable1;
119 }
120 if(fIntegralTable2 != nullptr)
121 {
122 fIntegralTable2->clearAndDestroy();
123 delete fIntegralTable2;
124 }
125 if(fIntegralTable3 != nullptr)
126 {
127 fIntegralTable3->clearAndDestroy();
128 delete fIntegralTable3;
129 }
130}
131
132//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
133void G4Scintillation::ProcessDescription(std::ostream& out) const
134{
135 out << "Scintillation simulates production of optical photons produced\n"
136 "by a high energy particle traversing matter.\n"
137 "Various material properties need to be defined.\n";
139
141 out << "Track secondaries first: " << params->GetScintTrackSecondariesFirst();
142 out << "Finite rise time: " << params->GetScintFiniteRiseTime();
143 out << "Scintillation by particle type: " << params->GetScintByParticleType();
144 out << "Save track information: " << params->GetScintTrackInfo();
145 out << "Stack photons: " << params->GetScintStackPhotons();
146 out << "Verbose level: " << params->GetScintVerboseLevel();
147}
148
149//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
151{
152 if(aParticleType.GetParticleName() == "opticalphoton")
153 return false;
154 if(aParticleType.IsShortLived())
155 return false;
156 return true;
157}
158
159//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
164
165//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
176
177//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
179{
180 if(fIntegralTable1 != nullptr)
181 {
182 fIntegralTable1->clearAndDestroy();
183 delete fIntegralTable1;
184 fIntegralTable1 = nullptr;
185 }
186 if(fIntegralTable2 != nullptr)
187 {
188 fIntegralTable2->clearAndDestroy();
189 delete fIntegralTable2;
190 fIntegralTable2 = nullptr;
191 }
192 if(fIntegralTable3 != nullptr)
193 {
194 fIntegralTable3->clearAndDestroy();
195 delete fIntegralTable3;
196 fIntegralTable3 = nullptr;
197 }
198
199 const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
200 std::size_t numOfMaterials = G4Material::GetNumberOfMaterials();
201
202 // create new physics table
203 if(!fIntegralTable1)
204 fIntegralTable1 = new G4PhysicsTable(numOfMaterials);
205 if(!fIntegralTable2)
206 fIntegralTable2 = new G4PhysicsTable(numOfMaterials);
207 if(!fIntegralTable3)
208 fIntegralTable3 = new G4PhysicsTable(numOfMaterials);
209
210 for(std::size_t i = 0; i < numOfMaterials; ++i)
211 {
212 auto vector1 = new G4PhysicsFreeVector();
213 auto vector2 = new G4PhysicsFreeVector();
214 auto vector3 = new G4PhysicsFreeVector();
215
216 // Retrieve vector of scintillation wavelength intensity for
217 // the material from the material's optical properties table.
219 ((*materialTable)[i])->GetMaterialPropertiesTable();
220
221 if(MPT)
222 {
225 if(MPV)
226 {
227 // Retrieve the first intensity point in vector
228 // of (photon energy, intensity) pairs
229 G4double currentIN = (*MPV)[0];
230 if(currentIN >= 0.0)
231 {
232 // Create first (photon energy, Scintillation Integral pair
233 G4double currentPM = MPV->Energy(0);
234 G4double currentCII = 0.0;
235 vector1->InsertValues(currentPM, currentCII);
236
237 // Set previous values to current ones prior to loop
238 G4double prevPM = currentPM;
239 G4double prevCII = currentCII;
240 G4double prevIN = currentIN;
241
242 // loop over all (photon energy, intensity)
243 // pairs stored for this material
244 for(std::size_t ii = 1; ii < MPV->GetVectorLength(); ++ii)
245 {
246 currentPM = MPV->Energy(ii);
247 currentIN = (*MPV)[ii];
248 currentCII =
249 prevCII + 0.5 * (currentPM - prevPM) * (prevIN + currentIN);
250
251 vector1->InsertValues(currentPM, currentCII);
252
253 prevPM = currentPM;
254 prevCII = currentCII;
255 prevIN = currentIN;
256 }
257 }
258 }
259
261 if(MPV)
262 {
263 // Retrieve the first intensity point in vector
264 // of (photon energy, intensity) pairs
265 G4double currentIN = (*MPV)[0];
266 if(currentIN >= 0.0)
267 {
268 // Create first (photon energy, Scintillation Integral pair
269 G4double currentPM = MPV->Energy(0);
270 G4double currentCII = 0.0;
271 vector2->InsertValues(currentPM, currentCII);
272
273 // Set previous values to current ones prior to loop
274 G4double prevPM = currentPM;
275 G4double prevCII = currentCII;
276 G4double prevIN = currentIN;
277
278 // loop over all (photon energy, intensity)
279 // pairs stored for this material
280 for(std::size_t ii = 1; ii < MPV->GetVectorLength(); ++ii)
281 {
282 currentPM = MPV->Energy(ii);
283 currentIN = (*MPV)[ii];
284 currentCII =
285 prevCII + 0.5 * (currentPM - prevPM) * (prevIN + currentIN);
286
287 vector2->InsertValues(currentPM, currentCII);
288
289 prevPM = currentPM;
290 prevCII = currentCII;
291 prevIN = currentIN;
292 }
293 }
294 }
296 if(MPV)
297 {
298 // Retrieve the first intensity point in vector
299 // of (photon energy, intensity) pairs
300 G4double currentIN = (*MPV)[0];
301 if(currentIN >= 0.0)
302 {
303 // Create first (photon energy, Scintillation Integral pair
304 G4double currentPM = MPV->Energy(0);
305 G4double currentCII = 0.0;
306 vector3->InsertValues(currentPM, currentCII);
307
308 // Set previous values to current ones prior to loop
309 G4double prevPM = currentPM;
310 G4double prevCII = currentCII;
311 G4double prevIN = currentIN;
312
313 // loop over all (photon energy, intensity)
314 // pairs stored for this material
315 for(std::size_t ii = 1; ii < MPV->GetVectorLength(); ++ii)
316 {
317 currentPM = MPV->Energy(ii);
318 currentIN = (*MPV)[ii];
319 currentCII =
320 prevCII + 0.5 * (currentPM - prevPM) * (prevIN + currentIN);
321
322 vector3->InsertValues(currentPM, currentCII);
323
324 prevPM = currentPM;
325 prevCII = currentCII;
326 prevIN = currentIN;
327 }
328 }
329 }
330 }
331 fIntegralTable1->insertAt(i, vector1);
332 fIntegralTable2->insertAt(i, vector2);
333 fIntegralTable3->insertAt(i, vector3);
334 }
335}
336
337//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
339 const G4Step& aStep)
340// This routine simply calls the equivalent PostStepDoIt since all the
341// necessary information resides in aStep.GetTotalEnergyDeposit()
342{
343 return G4Scintillation::PostStepDoIt(aTrack, aStep);
344}
345
346//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
348 const G4Step& aStep)
349// This routine is called for each tracking step of a charged particle
350// in a scintillator. A Poisson/Gauss-distributed number of photons is
351// generated according to the scintillation yield formula, distributed
352// evenly along the track segment and uniformly into 4pi.
353{
355 fNumPhotons = 0;
356
357 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
358 const G4Material* aMaterial = aTrack.GetMaterial();
359
360 G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
361 G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
362
363 G4ThreeVector x0 = pPreStepPoint->GetPosition();
364 G4ThreeVector p0 = aStep.GetDeltaPosition().unit();
365 G4double t0 = pPreStepPoint->GetGlobalTime();
366
367 G4double TotalEnergyDeposit = aStep.GetTotalEnergyDeposit();
368
370 if(!MPT)
371 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
372
373 G4int N_timeconstants = 1;
374
376 N_timeconstants = 3;
378 N_timeconstants = 2;
379 else if(!(MPT->GetProperty(kSCINTILLATIONCOMPONENT1)))
380 {
381 // no components were specified
382 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
383 }
384
385 G4double ResolutionScale = MPT->GetConstProperty(kRESOLUTIONSCALE);
386 G4double MeanNumberOfPhotons;
387
388 G4double yield1 = 0.;
389 G4double yield2 = 0.;
390 G4double yield3 = 0.;
391 G4double timeconstant1 = 0.;
392 G4double timeconstant2 = 0.;
393 G4double timeconstant3 = 0.;
394 G4double sum_yields = 0.;
395
396 if(fScintillationByParticleType)
397 {
398 MeanNumberOfPhotons = GetScintillationYieldByParticleType(
399 aTrack, aStep, yield1, yield2, yield3, timeconstant1, timeconstant2,
400 timeconstant3);
401 }
402 else
403 {
406 : 1.;
409 : 0.;
412 : 0.;
413 // The default linear scintillation process
414 // Units: [# scintillation photons / MeV]
415 MeanNumberOfPhotons = MPT->GetConstProperty(kSCINTILLATIONYIELD);
416 // Birk's correction via fEmSaturation and specifying scintillation by
417 // by particle type are physically mutually exclusive
418 if(fEmSaturation)
419 MeanNumberOfPhotons *=
420 (fEmSaturation->VisibleEnergyDepositionAtAStep(&aStep));
421 else
422 MeanNumberOfPhotons *= TotalEnergyDeposit;
423 }
424 sum_yields = yield1 + yield2 + yield3;
425
426 if(MeanNumberOfPhotons > 10.)
427 {
428 G4double sigma = ResolutionScale * std::sqrt(MeanNumberOfPhotons);
429 fNumPhotons = G4int(G4RandGauss::shoot(MeanNumberOfPhotons, sigma) + 0.5);
430 }
431 else
432 {
433 fNumPhotons = G4int(G4Poisson(MeanNumberOfPhotons));
434 }
435
436 if(fNumPhotons <= 0 || !fStackingFlag)
437 {
438 // return unchanged particle and no secondaries
440 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
441 }
442
444
445 if(fTrackSecondariesFirst)
446 {
447 if(aTrack.GetTrackStatus() == fAlive)
449 }
450
451 G4int materialIndex = (G4int)aMaterial->GetIndex();
452
453 // Retrieve the Scintillation Integral for this material
454 // new G4PhysicsFreeVector allocated to hold CII's
455 std::size_t numPhot = fNumPhotons;
456 G4double scintTime = 0.;
457 G4double riseTime = 0.;
458 G4PhysicsFreeVector* scintIntegral = nullptr;
459 G4ScintillationType scintType = Slow;
460
461 for(G4int scnt = 0; scnt < N_timeconstants; ++scnt)
462 {
463 // if there is 1 time constant it is #1, etc.
464 if(scnt == 0)
465 {
466 if(N_timeconstants == 1)
467 {
468 numPhot = fNumPhotons;
469 }
470 else
471 {
472 numPhot = yield1 / sum_yields * fNumPhotons;
473 }
474 if(fScintillationByParticleType)
475 {
476 scintTime = timeconstant1;
477 }
478 else
479 {
481 }
482 if(fFiniteRiseTime)
483 {
485 }
486 scintType = Fast;
487 scintIntegral =
488 (G4PhysicsFreeVector*) ((*fIntegralTable1)(materialIndex));
489 }
490 else if(scnt == 1)
491 {
492 // to be consistent with old version (due to double->int conversion)
493 if(N_timeconstants == 2)
494 {
495 numPhot = fNumPhotons - numPhot;
496 }
497 else
498 {
499 numPhot = yield2 / sum_yields * fNumPhotons;
500 }
501 if(fScintillationByParticleType)
502 {
503 scintTime = timeconstant2;
504 }
505 else
506 {
508 }
509 if(fFiniteRiseTime)
510 {
512 }
513 scintType = Medium;
514 scintIntegral =
515 (G4PhysicsFreeVector*) ((*fIntegralTable2)(materialIndex));
516 }
517 else if(scnt == 2)
518 {
519 numPhot = yield3 / sum_yields * fNumPhotons;
520 if(fScintillationByParticleType)
521 {
522 scintTime = timeconstant3;
523 }
524 else
525 {
527 }
528 if(fFiniteRiseTime)
529 {
531 }
532 scintType = Slow;
533 scintIntegral =
534 (G4PhysicsFreeVector*) ((*fIntegralTable3)(materialIndex));
535 }
536
537 if(!scintIntegral)
538 continue;
539
540 G4double CIImax = scintIntegral->GetMaxValue();
541 for(std::size_t i = 0; i < numPhot; ++i)
542 {
543 // Determine photon energy
544 G4double CIIvalue = G4UniformRand() * CIImax;
545 G4double sampledEnergy = scintIntegral->GetEnergy(CIIvalue);
546
547 if(verboseLevel > 1)
548 {
549 G4cout << "sampledEnergy = " << sampledEnergy << G4endl;
550 G4cout << "CIIvalue = " << CIIvalue << G4endl;
551 }
552
553 // Generate random photon direction
554 G4double cost = 1. - 2. * G4UniformRand();
555 G4double sint = std::sqrt((1. - cost) * (1. + cost));
556 G4double phi = twopi * G4UniformRand();
557 G4double sinp = std::sin(phi);
558 G4double cosp = std::cos(phi);
559 G4ParticleMomentum photonMomentum(sint * cosp, sint * sinp, cost);
560
561 // Determine polarization of new photon
562 G4ThreeVector photonPolarization(cost * cosp, cost * sinp, -sint);
563 G4ThreeVector perp = photonMomentum.cross(photonPolarization);
564 phi = twopi * G4UniformRand();
565 sinp = std::sin(phi);
566 cosp = std::cos(phi);
567 photonPolarization = (cosp * photonPolarization + sinp * perp).unit();
568
569 // Generate a new photon:
570 auto scintPhoton = new G4DynamicParticle(opticalphoton, photonMomentum);
571 scintPhoton->SetPolarization(photonPolarization);
572 scintPhoton->SetKineticEnergy(sampledEnergy);
573
574 // Generate new G4Track object:
575 G4double rand = G4UniformRand();
576 if(aParticle->GetDefinition()->GetPDGCharge() == 0)
577 {
578 rand = 1.0;
579 }
580
581 // emission time distribution
582 G4double delta = rand * aStep.GetStepLength();
583 G4double deltaTime =
584 delta /
585 (pPreStepPoint->GetVelocity() +
586 rand * (pPostStepPoint->GetVelocity() - pPreStepPoint->GetVelocity()) /
587 2.);
588 if(riseTime == 0.0)
589 {
590 deltaTime -= scintTime * std::log(G4UniformRand());
591 }
592 else
593 {
594 deltaTime += sample_time(riseTime, scintTime);
595 }
596
597 G4double secTime = t0 + deltaTime;
598 G4ThreeVector secPosition = x0 + rand * aStep.GetDeltaPosition();
599
600 G4Track* secTrack = new G4Track(scintPhoton, secTime, secPosition);
601 secTrack->SetTouchableHandle(
603 secTrack->SetParentID(aTrack.GetTrackID());
604 secTrack->SetCreatorModelID(secID);
605 if(fScintillationTrackInfo)
606 secTrack->SetUserInformation(
607 new G4ScintillationTrackInformation(scintType));
609 }
610 }
611
612 if(verboseLevel > 1)
613 {
614 G4cout << "\n Exiting from G4Scintillation::DoIt -- NumberOfSecondaries = "
616 }
617
618 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
619}
620
621//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
628
629//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
636
637//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
638G4double G4Scintillation::sample_time(G4double tau1, G4double tau2)
639{
640 // tau1: rise time and tau2: decay time
641 // Loop checking, 07-Aug-2015, Vladimir Ivanchenko
642 G4double t;
643
644 do
645 {
646 // The exponential distribution as an envelope function: very efficient
647 t = -1.0 * tau2 * G4Log(1.0 - G4UniformRand());
648 }
649 while (G4UniformRand() > (1.0 - G4Exp(-t/tau1)));
650
651 return t;
652}
653
654//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
656 const G4Track& aTrack, const G4Step& aStep, G4double& yield1,
657 G4double& yield2, G4double& yield3, G4double& timeconstant1,
658 G4double& timeconstant2, G4double& timeconstant3)
659{
660 // new in 10.7, allow multiple time constants with ScintByParticleType
661 // Get the G4MaterialPropertyVector containing the scintillation
662 // yield as a function of the energy deposited and particle type
663 // In 11.2, allow different time constants for different particles
664
666 G4MaterialPropertyVector* yieldVector = nullptr;
669
670 // Protons
671 if(pDef == G4Proton::ProtonDefinition())
672 {
673 yieldVector = MPT->GetProperty(kPROTONSCINTILLATIONYIELD);
676 : 1.;
679 : 0.;
682 : 0.;
686 if(yield2 > 0.)
687 {
691 }
692 if(yield3 > 0.)
693 {
697 }
698 }
699
700 // Deuterons
701 else if(pDef == G4Deuteron::DeuteronDefinition())
702 {
703 yieldVector = MPT->GetProperty(kDEUTERONSCINTILLATIONYIELD);
706 : 1.;
709 : 0.;
712 : 0.;
716 if(yield2 > 0.)
717 {
721 }
722 if(yield3 > 0.)
723 {
727 }
728 }
729
730 // Tritons
731 else if(pDef == G4Triton::TritonDefinition())
732 {
733 yieldVector = MPT->GetProperty(kTRITONSCINTILLATIONYIELD);
736 : 1.;
739 : 0.;
742 : 0.;
746 if(yield2 > 0.)
747 {
751 }
752 if(yield3 > 0.)
753 {
757 }
758 }
759
760 // Alphas
761 else if(pDef == G4Alpha::AlphaDefinition())
762 {
763 yieldVector = MPT->GetProperty(kALPHASCINTILLATIONYIELD);
766 : 1.;
769 : 0.;
772 : 0.;
776 if(yield2 > 0.)
777 {
781 }
782 if(yield3 > 0.)
783 {
787 }
788 }
789
790 // Ions (particles derived from G4VIon and G4Ions) and recoil ions
791 // below the production cut from neutrons after hElastic
792 else if(pDef->GetParticleType() == "nucleus" ||
794 {
795 yieldVector = MPT->GetProperty(kIONSCINTILLATIONYIELD);
798 : 1.;
801 : 0.;
804 : 0.;
808 if(yield2 > 0.)
809 {
813 }
814 if(yield3 > 0.)
815 {
819 }
820 }
821
822 // Electrons (must also account for shell-binding energy
823 // attributed to gamma from standard photoelectric effect)
824 // and, default for particles not enumerated/listed above
825 else
826 {
827 yieldVector = MPT->GetProperty(kELECTRONSCINTILLATIONYIELD);
830 : 1.;
833 : 0.;
836 : 0.;
840 if(yield2 > 0.)
841 {
845 }
846 if(yield3 > 0.)
847 {
851 }
852 }
853
854 // Throw an exception if no scintillation yield vector is found
855 if(yieldVector == nullptr)
856 {
858 ed << "\nG4Scintillation::PostStepDoIt(): "
859 << "Request for scintillation yield for energy deposit and particle\n"
860 << "type without correct entry in MaterialPropertiesTable. A material\n"
861 << "property (vector) with name like PARTICLESCINTILLATIONYIELD is\n"
862 << "needed (hint: PARTICLE might not be the primary particle."
863 << G4endl;
864 G4String comments = "Missing MaterialPropertiesTable entry - No correct "
865 "entry in MaterialPropertiesTable";
866 G4Exception("G4Scintillation::PostStepDoIt", "Scint01", FatalException, ed,
867 comments);
868 return 0.; // NOLINT: required to help Coverity recognise this as exit point
869 }
870
871 ///////////////////////////////////////
872 // Calculate the scintillation light //
873 ///////////////////////////////////////
874 // To account for potential nonlinearity and scintillation photon
875 // density along the track, light (L) is produced according to:
876 // L_currentStep = L(PreStepKE) - L(PreStepKE - EDep)
877
878 G4double ScintillationYield = 0.;
879 G4double StepEnergyDeposit = aStep.GetTotalEnergyDeposit();
880 G4double PreStepKineticEnergy = aStep.GetPreStepPoint()->GetKineticEnergy();
881
882 if(PreStepKineticEnergy <= yieldVector->GetMaxEnergy())
883 {
884 // G4double Yield1 = yieldVector->Value(PreStepKineticEnergy);
885 // G4double Yield2 = yieldVector->Value(PreStepKineticEnergy -
886 // StepEnergyDeposit); ScintillationYield = Yield1 - Yield2;
887 ScintillationYield =
888 yieldVector->Value(PreStepKineticEnergy) -
889 yieldVector->Value(PreStepKineticEnergy - StepEnergyDeposit);
890 }
891 else
892 {
893 ++fNumEnergyWarnings;
894 if(verboseLevel > 0 && fNumEnergyWarnings <= 10)
895 {
897 ed << "\nG4Scintillation::GetScintillationYieldByParticleType(): Request\n"
898 << "for scintillation light yield above the available energy range\n"
899 << "specified in G4MaterialPropertiesTable. A linear interpolation\n"
900 << "will be performed to compute the scintillation light yield using\n"
901 << "(L_max / E_max) as the photon yield per unit energy." << G4endl;
902 G4String cmt = "\nScintillation yield may be unphysical!\n";
903
904 if(fNumEnergyWarnings == 10)
905 {
906 ed << G4endl << "*** Scintillation energy warnings stopped.";
907 }
908 G4Exception("G4Scintillation::GetScintillationYieldByParticleType()",
909 "Scint03", JustWarning, ed, cmt);
910 }
911
912 // Units: [# scintillation photons]
913 ScintillationYield = yieldVector->GetMaxValue() /
914 yieldVector->GetMaxEnergy() * StepEnergyDeposit;
915 }
916
917#ifdef G4DEBUG_SCINTILLATION
918 // Increment track aggregators
919 ScintTrackYield += ScintillationYield;
920 ScintTrackEDep += StepEnergyDeposit;
921
922 G4cout << "\n--- G4Scintillation::GetScintillationYieldByParticleType() ---\n"
923 << "--\n"
924 << "-- Name = "
925 << aTrack.GetParticleDefinition()->GetParticleName() << "\n"
926 << "-- TrackID = " << aTrack.GetTrackID() << "\n"
927 << "-- ParentID = " << aTrack.GetParentID() << "\n"
928 << "-- Current KE = " << aTrack.GetKineticEnergy() / MeV
929 << " MeV\n"
930 << "-- Step EDep = " << aStep.GetTotalEnergyDeposit() / MeV
931 << " MeV\n"
932 << "-- Track EDep = " << ScintTrackEDep / MeV << " MeV\n"
933 << "-- Vertex KE = " << aTrack.GetVertexKineticEnergy() / MeV
934 << " MeV\n"
935 << "-- Step yield = " << ScintillationYield << " photons\n"
936 << "-- Track yield = " << ScintTrackYield << " photons\n"
937 << G4endl;
938
939 // The track has terminated within or has left the scintillator volume
940 if((aTrack.GetTrackStatus() == fStopButAlive) or
942 {
943 // Reset aggregators for the next track
944 ScintTrackEDep = 0.;
945 ScintTrackYield = 0.;
946 }
947#endif
948
949 return ScintillationYield;
950}
951
952//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
954{
955 if(fIntegralTable1)
956 {
957 for(std::size_t i = 0; i < fIntegralTable1->entries(); ++i)
958 {
959 ((G4PhysicsFreeVector*) (*fIntegralTable1)[i])->DumpValues();
960 }
961 }
962 if(fIntegralTable2)
963 {
964 for(std::size_t i = 0; i < fIntegralTable2->entries(); ++i)
965 {
966 ((G4PhysicsFreeVector*) (*fIntegralTable2)[i])->DumpValues();
967 }
968 }
969 if(fIntegralTable3)
970 {
971 for(std::size_t i = 0; i < fIntegralTable3->entries(); ++i)
972 {
973 ((G4PhysicsFreeVector*) (*fIntegralTable3)[i])->DumpValues();
974 }
975 }
976}
977
978//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
980{
981 fTrackSecondariesFirst = state;
983 fTrackSecondariesFirst);
984}
985
986//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
988{
989 fFiniteRiseTime = state;
991}
992
993//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
995{
996 if(fEmSaturation && scintType)
997 {
998 G4Exception("G4Scintillation::SetScintillationByParticleType", "Scint02",
1000 "Redefinition: Birks Saturation is replaced by "
1001 "ScintillationByParticleType!");
1003 }
1004 fScintillationByParticleType = scintType;
1006 fScintillationByParticleType);
1007}
1008
1009//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
1011{
1012 fScintillationTrackInfo = trackType;
1013 G4OpticalParameters::Instance()->SetScintTrackInfo(fScintillationTrackInfo);
1014}
1015
1016//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
1018{
1019 fStackingFlag = stackingFlag;
1021}
1022
1023//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@ fScintillation
G4double condition(const G4ErrorSymMatrix &m)
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition G4Exp.hh:180
G4ForceCondition
@ StronglyForced
@ Forced
G4double G4Log(G4double x)
Definition G4Log.hh:227
@ kSCINTILLATIONCOMPONENT1
@ kSCINTILLATIONCOMPONENT2
@ kSCINTILLATIONCOMPONENT3
@ kELECTRONSCINTILLATIONYIELD
@ kALPHASCINTILLATIONYIELD
@ kPROTONSCINTILLATIONYIELD
@ kDEUTERONSCINTILLATIONYIELD
@ kTRITONSCINTILLATIONYIELD
@ kSCINTILLATIONTIMECONSTANT1
@ kTRITONSCINTILLATIONYIELD1
@ kDEUTERONSCINTILLATIONYIELD3
@ kPROTONSCINTILLATIONTIMECONSTANT2
@ kALPHASCINTILLATIONTIMECONSTANT1
@ kELECTRONSCINTILLATIONTIMECONSTANT2
@ kDEUTERONSCINTILLATIONYIELD2
@ kELECTRONSCINTILLATIONTIMECONSTANT3
@ kDEUTERONSCINTILLATIONTIMECONSTANT1
@ kTRITONSCINTILLATIONTIMECONSTANT2
@ kTRITONSCINTILLATIONYIELD2
@ kALPHASCINTILLATIONYIELD2
@ kELECTRONSCINTILLATIONYIELD3
@ kTRITONSCINTILLATIONTIMECONSTANT1
@ kALPHASCINTILLATIONYIELD1
@ kALPHASCINTILLATIONTIMECONSTANT2
@ kPROTONSCINTILLATIONTIMECONSTANT3
@ kDEUTERONSCINTILLATIONTIMECONSTANT3
@ kELECTRONSCINTILLATIONYIELD2
@ kPROTONSCINTILLATIONYIELD2
@ kDEUTERONSCINTILLATIONYIELD1
@ kTRITONSCINTILLATIONTIMECONSTANT3
@ kTRITONSCINTILLATIONYIELD3
@ kSCINTILLATIONTIMECONSTANT3
@ kIONSCINTILLATIONTIMECONSTANT1
@ kIONSCINTILLATIONTIMECONSTANT3
@ kPROTONSCINTILLATIONYIELD3
@ kIONSCINTILLATIONTIMECONSTANT2
@ kALPHASCINTILLATIONTIMECONSTANT3
@ kELECTRONSCINTILLATIONYIELD1
@ kALPHASCINTILLATIONYIELD3
@ kSCINTILLATIONTIMECONSTANT2
@ kPROTONSCINTILLATIONYIELD1
@ kDEUTERONSCINTILLATIONTIMECONSTANT2
@ kPROTONSCINTILLATIONTIMECONSTANT1
@ kELECTRONSCINTILLATIONTIMECONSTANT1
std::vector< G4Material * > G4MaterialTable
G4long G4Poisson(G4double mean)
Definition G4Poisson.hh:50
G4ProcessType
@ fGeomBoundary
@ fSuspend
@ fAlive
@ fStopButAlive
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition Randomize.hh:52
Hep3Vector unit() const
Hep3Vector cross(const Hep3Vector &) const
static G4Alpha * AlphaDefinition()
Definition G4Alpha.cc:78
static G4Deuteron * DeuteronDefinition()
Definition G4Deuteron.cc:85
G4ParticleDefinition * GetDefinition() const
G4double VisibleEnergyDepositionAtAStep(const G4Step *) const
G4bool ConstPropertyExists(const G4String &key) const
G4double GetConstProperty(const G4String &key) const
G4MaterialPropertyVector * GetProperty(const char *key) const
G4MaterialPropertiesTable * GetMaterialPropertiesTable() const
static std::size_t GetNumberOfMaterials()
std::size_t GetIndex() const
static G4MaterialTable * GetMaterialTable()
static G4Neutron * NeutronDefinition()
Definition G4Neutron.cc:96
void SetScintByParticleType(G4bool)
void SetScintTrackSecondariesFirst(G4bool)
G4int GetScintVerboseLevel() const
G4bool GetScintStackPhotons() const
static G4OpticalParameters * Instance()
void SetScintFiniteRiseTime(G4bool)
G4bool GetScintByParticleType() const
G4bool GetScintFiniteRiseTime() const
G4bool GetScintTrackInfo() const
G4bool GetScintTrackSecondariesFirst() const
void AddSecondary(G4Track *aSecondary)
void Initialize(const G4Track &) override
const G4String & GetParticleType() const
const G4String & GetParticleName() const
static G4int GetModelID(const G4int modelIndex)
void clearAndDestroy()
std::size_t entries() const
void insertAt(std::size_t, G4PhysicsVector *)
G4double GetEnergy(const G4double value) const
G4double GetMaxEnergy() const
G4double GetMaxValue() const
G4double Energy(const std::size_t index) const
G4double Value(const G4double energy, std::size_t &lastidx) const
std::size_t GetVectorLength() const
static G4Proton * ProtonDefinition()
Definition G4Proton.cc:85
G4VParticleChange * AtRestDoIt(const G4Track &aTrack, const G4Step &aStep) override
void SetTrackSecondariesFirst(const G4bool state)
void SetStackPhotons(const G4bool)
G4double GetMeanFreePath(const G4Track &aTrack, G4double, G4ForceCondition *) override
void BuildPhysicsTable(const G4ParticleDefinition &aParticleType) override
void SetVerboseLevel(G4int)
void SetScintillationTrackInfo(const G4bool trackType)
G4double GetMeanLifeTime(const G4Track &aTrack, G4ForceCondition *) override
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep) override
G4bool IsApplicable(const G4ParticleDefinition &aParticleType) override
G4double GetScintillationYieldByParticleType(const G4Track &aTrack, const G4Step &aStep, G4double &yield1, G4double &yield2, G4double &yield3, G4double &timeconstant1, G4double &timeconstant2, G4double &timeconstant3)
void DumpPhysicsTable() const
void SetFiniteRiseTime(const G4bool state)
G4Scintillation(const G4String &processName="Scintillation", G4ProcessType type=fElectromagnetic)
void PreparePhysicsTable(const G4ParticleDefinition &part) override
void SetScintillationByParticleType(const G4bool)
void ProcessDescription(std::ostream &) const override
G4StepStatus GetStepStatus() const
G4double GetVelocity() const
G4double GetGlobalTime() const
const G4ThreeVector & GetPosition() const
const G4TouchableHandle & GetTouchableHandle() const
G4double GetKineticEnergy() const
G4ThreeVector GetDeltaPosition() const
G4StepPoint * GetPreStepPoint() const
G4double GetStepLength() const
G4double GetTotalEnergyDeposit() const
G4StepPoint * GetPostStepPoint() const
G4TrackStatus GetTrackStatus() const
G4double GetVertexKineticEnergy() const
G4int GetTrackID() const
const G4ParticleDefinition * GetParticleDefinition() const
void SetTouchableHandle(const G4TouchableHandle &apValue)
G4Material * GetMaterial() const
const G4DynamicParticle * GetDynamicParticle() const
G4double GetKineticEnergy() const
void SetUserInformation(G4VUserTrackInformation *aValue) const
void SetCreatorModelID(const G4int id)
G4int GetParentID() const
void SetParentID(const G4int aValue)
static G4Triton * TritonDefinition()
Definition G4Triton.cc:85
void ProposeTrackStatus(G4TrackStatus status)
G4int GetNumberOfSecondaries() const
void SetNumberOfSecondaries(G4int totSecondaries)
G4ParticleChange aParticleChange
G4int verboseLevel
void SetProcessSubType(G4int)
virtual void DumpInfo() const
const G4String & GetProcessName() const
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
#define DBL_MAX
Definition templates.hh:62