Geant4 10.7.0
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//
27////////////////////////////////////////////////////////////////////////
28// Scintillation Light Class Implementation
29////////////////////////////////////////////////////////////////////////
30//
31// File: G4Scintillation.cc
32// Description: RestDiscrete Process - Generation of Scintillation Photons
33// Version: 1.0
34// Created: 1998-11-07
35// Author: Peter Gumplinger
36// Updated: 2010-10-20 Allow the scintillation yield to be a function
37// of energy deposited by particle type
38// Thanks to Zach Hartwig (Department of Nuclear
39// Science and Engineeering - MIT)
40// 2010-09-22 by Peter Gumplinger
41// > scintillation rise time included, thanks to
42// > Martin Goettlich/DESY
43// 2005-08-17 by Peter Gumplinger
44// > change variable name MeanNumPhotons -> MeanNumberOfPhotons
45// 2005-07-28 by Peter Gumplinger
46// > add G4ProcessType to constructor
47// 2004-08-05 by Peter Gumplinger
48// > changed StronglyForced back to Forced in GetMeanLifeTime
49// 2002-11-21 by Peter Gumplinger
50// > change to use G4Poisson for small MeanNumberOfPhotons
51// 2002-11-07 by Peter Gumplinger
52// > now allow for fast and slow scintillation component
53// 2002-11-05 by Peter Gumplinger
54// > now use scintillation constants from G4Material
55// 2002-05-09 by Peter Gumplinger
56// > use only the PostStepPoint location for the origin of
57// scintillation photons when energy is lost to the medium
58// by a neutral particle
59// 2000-09-18 by Peter Gumplinger
60// > change: aSecondaryPosition=x0+rand*aStep.GetDeltaPosition();
61// aSecondaryTrack->SetTouchable(0);
62// 2001-09-17, migration of Materials to pure STL (mma)
63// 2003-06-03, V.Ivanchenko fix compilation warnings
64//
65//
66////////////////////////////////////////////////////////////////////////
67
68#include "G4ios.hh"
69#include "globals.hh"
71#include "G4SystemOfUnits.hh"
72#include "G4ParticleTypes.hh"
73#include "G4EmProcessSubType.hh"
74
77#include "G4Scintillation.hh"
78
79//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
81 G4ProcessType type)
82 : G4VRestDiscreteProcess(processName, type)
83 , fIntegralTable1(nullptr)
84 , fIntegralTable2(nullptr)
85 , fIntegralTable3(nullptr)
86 , fNumPhotons(0)
87 , fEmSaturation(nullptr)
88{
90
91#ifdef G4DEBUG_SCINTILLATION
92 ScintTrackEDep = 0.;
93 ScintTrackYield = 0.;
94#endif
95
96 if(verboseLevel > 0)
97 {
98 G4cout << GetProcessName() << " is created " << G4endl;
99 }
100 Initialise();
101}
102
103//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
105{
106 if(fIntegralTable1 != nullptr)
107 {
109 delete fIntegralTable1;
110 }
111 if(fIntegralTable2 != nullptr)
112 {
114 delete fIntegralTable2;
115 }
116 if(fIntegralTable3 != nullptr)
117 {
119 delete fIntegralTable3;
120 }
121}
122
123//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
125{
126 return (aParticleType.GetPDGCharge() == 0.0 || aParticleType.IsShortLived())
127 ? false
128 : true;
129}
130
131//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
133{
134 Initialise();
135}
136
137//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
139{
150}
151
152//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
154{
155 if(fIntegralTable1 != nullptr)
156 {
158 delete fIntegralTable1;
159 fIntegralTable1 = nullptr;
160 }
161 if(fIntegralTable2 != nullptr)
162 {
164 delete fIntegralTable2;
165 fIntegralTable2 = nullptr;
166 }
167 if(fIntegralTable3 != nullptr)
168 {
170 delete fIntegralTable3;
171 fIntegralTable3 = nullptr;
172 }
173
174 const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
175 size_t numOfMaterials = G4Material::GetNumberOfMaterials();
176
177 // create new physics table
178 if(!fIntegralTable1)
179 fIntegralTable1 = new G4PhysicsTable(numOfMaterials);
180 if(!fIntegralTable2)
181 fIntegralTable2 = new G4PhysicsTable(numOfMaterials);
182 if(!fIntegralTable3)
183 fIntegralTable3 = new G4PhysicsTable(numOfMaterials);
184
185 for(size_t i = 0; i < numOfMaterials; ++i)
186 {
190
191 // Retrieve vector of scintillation wavelength intensity for
192 // the material from the material's optical properties table.
194 ((*materialTable)[i])->GetMaterialPropertiesTable();
195
196 if(MPT)
197 {
198 // integral table 1 is either FASTCOMPONENT or SCINTILLATIONCOMPONENT1
200 if(!MPV)
202 if(MPV)
203 {
204 // Retrieve the first intensity point in vector
205 // of (photon energy, intensity) pairs
206 G4double currentIN = (*MPV)[0];
207 if(currentIN >= 0.0)
208 {
209 // Create first (photon energy, Scintillation Integral pair
210 G4double currentPM = MPV->Energy(0);
211 G4double currentCII = 0.0;
212 vector1->InsertValues(currentPM, currentCII);
213
214 // Set previous values to current ones prior to loop
215 G4double prevPM = currentPM;
216 G4double prevCII = currentCII;
217 G4double prevIN = currentIN;
218
219 // loop over all (photon energy, intensity)
220 // pairs stored for this material
221 for(size_t ii = 1; ii < MPV->GetVectorLength(); ++ii)
222 {
223 currentPM = MPV->Energy(ii);
224 currentIN = (*MPV)[ii];
225 currentCII =
226 prevCII + 0.5 * (currentPM - prevPM) * (prevIN + currentIN);
227
228 vector1->InsertValues(currentPM, currentCII);
229
230 prevPM = currentPM;
231 prevCII = currentCII;
232 prevIN = currentIN;
233 }
234 }
235 }
236
237 // integral table 2 is SCINTILLATIONCOMPONENT2
239 if(MPV)
240 {
241 // Retrieve the first intensity point in vector
242 // of (photon energy, intensity) pairs
243 G4double currentIN = (*MPV)[0];
244 if(currentIN >= 0.0)
245 {
246 // Create first (photon energy, Scintillation Integral pair
247 G4double currentPM = MPV->Energy(0);
248 G4double currentCII = 0.0;
249 vector2->InsertValues(currentPM, currentCII);
250
251 // Set previous values to current ones prior to loop
252 G4double prevPM = currentPM;
253 G4double prevCII = currentCII;
254 G4double prevIN = currentIN;
255
256 // loop over all (photon energy, intensity)
257 // pairs stored for this material
258 for(size_t ii = 1; ii < MPV->GetVectorLength(); ++ii)
259 {
260 currentPM = MPV->Energy(ii);
261 currentIN = (*MPV)[ii];
262 currentCII =
263 prevCII + 0.5 * (currentPM - prevPM) * (prevIN + currentIN);
264
265 vector2->InsertValues(currentPM, currentCII);
266
267 prevPM = currentPM;
268 prevCII = currentCII;
269 prevIN = currentIN;
270 }
271 }
272 }
273 // integral table 3 is either SLOWCOMPONENT or SCINTILLATIONCOMPONENT3
274 MPV = MPT->GetProperty(kSLOWCOMPONENT);
275 if(!MPV)
277 if(MPV)
278 {
279 // Retrieve the first intensity point in vector
280 // of (photon energy, intensity) pairs
281 G4double currentIN = (*MPV)[0];
282 if(currentIN >= 0.0)
283 {
284 // Create first (photon energy, Scintillation Integral pair
285 G4double currentPM = MPV->Energy(0);
286 G4double currentCII = 0.0;
287 vector3->InsertValues(currentPM, currentCII);
288
289 // Set previous values to current ones prior to loop
290 G4double prevPM = currentPM;
291 G4double prevCII = currentCII;
292 G4double prevIN = currentIN;
293
294 // loop over all (photon energy, intensity)
295 // pairs stored for this material
296 for(size_t ii = 1; ii < MPV->GetVectorLength(); ++ii)
297 {
298 currentPM = MPV->Energy(ii);
299 currentIN = (*MPV)[ii];
300 currentCII =
301 prevCII + 0.5 * (currentPM - prevPM) * (prevIN + currentIN);
302
303 vector3->InsertValues(currentPM, currentCII);
304
305 prevPM = currentPM;
306 prevCII = currentCII;
307 prevIN = currentIN;
308 }
309 }
310 }
311 }
312 fIntegralTable1->insertAt(i, vector1);
313 fIntegralTable2->insertAt(i, vector2);
314 fIntegralTable3->insertAt(i, vector3);
315 }
316}
317
318//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
320 const G4Step& aStep)
321// This routine simply calls the equivalent PostStepDoIt since all the
322// necessary information resides in aStep.GetTotalEnergyDeposit()
323{
324 return G4Scintillation::PostStepDoIt(aTrack, aStep);
325}
326
327//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
329 const G4Step& aStep)
330// This routine is called for each tracking step of a charged particle
331// in a scintillator. A Poisson/Gauss-distributed number of photons is
332// generated according to the scintillation yield formula, distributed
333// evenly along the track segment and uniformly into 4pi.
334{
336 fNumPhotons = 0;
337
338 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
339 const G4Material* aMaterial = aTrack.GetMaterial();
340
341 G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
342 G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
343
344 G4ThreeVector x0 = pPreStepPoint->GetPosition();
345 G4ThreeVector p0 = aStep.GetDeltaPosition().unit();
346 G4double t0 = pPreStepPoint->GetGlobalTime();
347
348 G4double TotalEnergyDeposit = aStep.GetTotalEnergyDeposit();
349
351 if(!MPT)
352 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
353
354 G4int N_timeconstants = 1;
355
356 // only needed for old (two time constants) version
357 G4MaterialPropertyVector* Fast_Intensity = nullptr;
358 G4MaterialPropertyVector* Slow_Intensity = nullptr;
359
360 if(fEnhancedTimeConstants)
361 {
363 N_timeconstants = 3;
365 N_timeconstants = 2;
366 else if(!(MPT->GetProperty(kSCINTILLATIONCOMPONENT1)))
367 {
368 // no components were specified
369 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
370 }
371 }
372 else
373 { // OLD METHOD
374 Fast_Intensity = MPT->GetProperty(kFASTCOMPONENT);
375 Slow_Intensity = MPT->GetProperty(kSLOWCOMPONENT);
376 if(!Fast_Intensity && !Slow_Intensity)
377 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
378 if(Fast_Intensity && Slow_Intensity)
379 N_timeconstants = 2;
380 }
381
382 G4double ResolutionScale = MPT->GetConstProperty(kRESOLUTIONSCALE);
383 G4double MeanNumberOfPhotons;
384
385 G4double yield1 = 0.;
386 G4double yield2 = 0.;
387 G4double yield3 = 0.;
388 G4double sum_yields = 0.;
389
390 if(!fEnhancedTimeConstants)
391 {
392 // Scintillation depends on particle type, energy deposited
393 if(fScintillationByParticleType)
394 {
395 MeanNumberOfPhotons = GetScintillationYieldByParticleType(aTrack, aStep);
396 }
397 else
398 {
399 // The default linear scintillation process
400 // Units: [# scintillation photons / MeV]
401 MeanNumberOfPhotons =
402 MPT->GetConstProperty(kSCINTILLATIONYIELD) * fYieldFactor;
403 // Birk's correction via fEmSaturation and specifying scintillation by
404 // by particle type are physically mutually exclusive
405 if(fEmSaturation)
406 MeanNumberOfPhotons *=
407 (fEmSaturation->VisibleEnergyDepositionAtAStep(&aStep));
408 else
409 MeanNumberOfPhotons *= TotalEnergyDeposit;
410 }
411 }
412
413 else
414 {
415 if(fScintillationByParticleType)
416 {
417 MeanNumberOfPhotons = GetScintillationYieldByParticleType(
418 aTrack, aStep, yield1, yield2, yield3);
419 }
420 else
421 {
424 : 1.;
427 : 0.;
430 : 0.;
431 // The default linear scintillation process
432 // Units: [# scintillation photons / MeV]
433 MeanNumberOfPhotons =
434 MPT->GetConstProperty(kSCINTILLATIONYIELD) * fYieldFactor;
435 // Birk's correction via fEmSaturation and specifying scintillation by
436 // by particle type are physically mutually exclusive
437 if(fEmSaturation)
438 MeanNumberOfPhotons *=
439 (fEmSaturation->VisibleEnergyDepositionAtAStep(&aStep));
440 else
441 MeanNumberOfPhotons *= TotalEnergyDeposit;
442 }
443 sum_yields = yield1 + yield2 + yield3;
444 }
445
446 if(MeanNumberOfPhotons > 10.)
447 {
448 G4double sigma = ResolutionScale * std::sqrt(MeanNumberOfPhotons);
449 fNumPhotons = G4int(G4RandGauss::shoot(MeanNumberOfPhotons, sigma) + 0.5);
450 }
451 else
452 {
453 fNumPhotons = G4int(G4Poisson(MeanNumberOfPhotons));
454 }
455
456 if(fNumPhotons <= 0 || !fStackingFlag)
457 {
458 // return unchanged particle and no secondaries
460 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
461 }
462
464
465 if(fTrackSecondariesFirst)
466 {
467 if(aTrack.GetTrackStatus() == fAlive)
469 }
470
471 G4int materialIndex = aMaterial->GetIndex();
472
473 // Retrieve the Scintillation Integral for this material
474 // new G4PhysicsOrderedFreeVector allocated to hold CII's
475 size_t numPhot = fNumPhotons;
476 G4double scintTime = 0.;
477 G4double riseTime = 0.;
478 G4PhysicsOrderedFreeVector* scintIntegral = nullptr;
479 G4ScintillationType scintType = Slow;
480
481 for(G4int scnt = 0; scnt < N_timeconstants; ++scnt)
482 {
483 // Original method with FAST and SLOW
484 if(!fEnhancedTimeConstants)
485 {
486 if(scnt == 0)
487 {
488 if(N_timeconstants == 1)
489 {
490 if(Fast_Intensity)
491 {
492 scintTime = MPT->GetConstProperty(kFASTTIMECONSTANT);
493 if(fFiniteRiseTime)
494 {
496 }
497 scintType = Fast;
498 scintIntegral =
499 (G4PhysicsOrderedFreeVector*) ((*fIntegralTable1)(materialIndex));
500 }
501 if(Slow_Intensity)
502 {
503 scintTime = MPT->GetConstProperty(kSLOWTIMECONSTANT);
504 if(fFiniteRiseTime)
505 {
507 }
508 scintType = Slow;
509 scintIntegral =
510 (G4PhysicsOrderedFreeVector*) ((*fIntegralTable3)(materialIndex));
511 }
512 }
513 else
514 { /// N_timeconstants != 1 and still scnt == 0
515 G4double yieldRatio = MPT->GetConstProperty(kYIELDRATIO);
516 if(fExcitationRatio == 1.0 || fExcitationRatio == 0.0)
517 {
518 numPhot = G4int(std::min(yieldRatio, 1.0) * fNumPhotons);
519 }
520 else
521 {
522 numPhot = G4int(std::min(fExcitationRatio, 1.0) * fNumPhotons);
523 }
524 scintTime = MPT->GetConstProperty(kFASTTIMECONSTANT);
525 if(fFiniteRiseTime)
526 {
528 }
529 scintType = Fast;
530 scintIntegral =
531 (G4PhysicsOrderedFreeVector*) ((*fIntegralTable1)(materialIndex));
532 }
533 }
534 else
535 { // scnt != 0
536 numPhot = fNumPhotons - numPhot;
537 scintTime = MPT->GetConstProperty(kSLOWTIMECONSTANT);
538 if(fFiniteRiseTime)
539 {
541 }
542 scintType = Slow;
543 scintIntegral =
544 (G4PhysicsOrderedFreeVector*) ((*fIntegralTable3)(materialIndex));
545 }
546 }
547 else
548 { // fEnhancedTimeConstants == true
549 // in the new method, if there is 1 time constant it is #1, etc.
550 // Note: fExcitationRatio is not used
551 if(scnt == 0)
552 {
553 if(N_timeconstants == 1)
554 {
555 numPhot = fNumPhotons;
556 }
557 else
558 {
559 numPhot = yield1 / sum_yields * fNumPhotons;
560 }
562 if(fFiniteRiseTime)
563 {
565 }
566 scintType = Fast;
567 scintIntegral =
568 (G4PhysicsOrderedFreeVector*) ((*fIntegralTable1)(materialIndex));
569 }
570 else if(scnt == 1)
571 {
572 // to be consistent with old version (due to double->int conversion)
573 if(N_timeconstants == 2)
574 {
575 numPhot = fNumPhotons - numPhot;
576 }
577 else
578 {
579 numPhot = yield2 / sum_yields * fNumPhotons;
580 }
582 if(fFiniteRiseTime)
583 {
585 }
586 scintType = Medium;
587 scintIntegral =
588 (G4PhysicsOrderedFreeVector*) ((*fIntegralTable2)(materialIndex));
589 }
590 else if(scnt == 2)
591 {
592 numPhot = yield3 / sum_yields * fNumPhotons;
594 if(fFiniteRiseTime)
595 {
597 }
598 scintType = Slow;
599 scintIntegral =
600 (G4PhysicsOrderedFreeVector*) ((*fIntegralTable3)(materialIndex));
601 }
602 }
603
604 if(!scintIntegral)
605 continue;
606
607 G4double CIImax = scintIntegral->GetMaxValue();
608 for(size_t i = 0; i < numPhot; ++i)
609 {
610 // Determine photon energy
611 G4double CIIvalue = G4UniformRand() * CIImax;
612 G4double sampledEnergy = scintIntegral->GetEnergy(CIIvalue);
613
614 if(verboseLevel > 1)
615 {
616 G4cout << "sampledEnergy = " << sampledEnergy << G4endl;
617 G4cout << "CIIvalue = " << CIIvalue << G4endl;
618 }
619
620 // Generate random photon direction
621 G4double cost = 1. - 2. * G4UniformRand();
622 G4double sint = std::sqrt((1. - cost) * (1. + cost));
623 G4double phi = twopi * G4UniformRand();
624 G4double sinp = std::sin(phi);
625 G4double cosp = std::cos(phi);
626 G4ParticleMomentum photonMomentum(sint * cosp, sint * sinp, cost);
627
628 // Determine polarization of new photon
629 G4ThreeVector photonPolarization(cost * cosp, cost * sinp, -sint);
630 G4ThreeVector perp = photonMomentum.cross(photonPolarization);
631 phi = twopi * G4UniformRand();
632 sinp = std::sin(phi);
633 cosp = std::cos(phi);
634 photonPolarization = (cosp * photonPolarization + sinp * perp).unit();
635
636 // Generate a new photon:
637 G4DynamicParticle* scintPhoton =
638 new G4DynamicParticle(opticalphoton, photonMomentum);
639 scintPhoton->SetPolarization(photonPolarization);
640 scintPhoton->SetKineticEnergy(sampledEnergy);
641
642 // Generate new G4Track object:
643 G4double rand = G4UniformRand();
644 if(aParticle->GetDefinition()->GetPDGCharge() == 0)
645 {
646 rand = 1.0;
647 }
648
649 // emission time distribution
650 G4double delta = rand * aStep.GetStepLength();
651 G4double deltaTime =
652 delta /
653 (pPreStepPoint->GetVelocity() +
654 rand * (pPostStepPoint->GetVelocity() - pPreStepPoint->GetVelocity()) /
655 2.);
656 if(riseTime == 0.0)
657 {
658 deltaTime -= scintTime * std::log(G4UniformRand());
659 }
660 else
661 {
662 deltaTime += sample_time(riseTime, scintTime);
663 }
664
665 G4double secTime = t0 + deltaTime;
666 G4ThreeVector secPosition = x0 + rand * aStep.GetDeltaPosition();
667
668 G4Track* secTrack = new G4Track(scintPhoton, secTime, secPosition);
669 secTrack->SetTouchableHandle(
671 secTrack->SetParentID(aTrack.GetTrackID());
672 if(fScintillationTrackInfo)
673 secTrack->SetUserInformation(
674 new G4ScintillationTrackInformation(scintType));
676 }
677 }
678
679 if(verboseLevel > 1)
680 {
681 G4cout << "\n Exiting from G4Scintillation::DoIt -- NumberOfSecondaries = "
683 }
684
685 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
686}
687
688//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
690{
691 if(fEmSaturation && scintType)
692 {
693 G4Exception("G4Scintillation::SetScintillationByParticleType", "Scint02",
695 "Redefinition: Birks Saturation is replaced by "
696 "ScintillationByParticleType!");
698 }
699 fScintillationByParticleType = scintType;
700}
701
702//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
705{
707 return DBL_MAX;
708}
709
710//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
713{
714 *condition = Forced;
715 return DBL_MAX;
716}
717
718//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
719G4double G4Scintillation::sample_time(G4double tau1, G4double tau2)
720{
721 // tau1: rise time and tau2: decay time
722 // Loop checking, 07-Aug-2015, Vladimir Ivanchenko
723 while(true)
724 {
725 G4double ran1 = G4UniformRand();
726 G4double ran2 = G4UniformRand();
727
728 // exponential distribution as envelope function: very efficient
729 G4double d = (tau1 + tau2) / tau2;
730 // make sure the envelope function is
731 // always larger than the bi-exponential
732 G4double t = -1.0 * tau2 * std::log(1. - ran1);
733 G4double gg = d * single_exp(t, tau2);
734 if(ran2 <= bi_exp(t, tau1, tau2) / gg)
735 return t;
736 }
737 return -1.0;
738}
739
740//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
742 const G4Track& aTrack, const G4Step& aStep)
743{
744 // Get the G4MaterialPropertyVector containing the scintillation
745 // yield as a function of the energy deposited and particle type
746
748 G4MaterialPropertyVector* scintVector = nullptr;
751
752 // Protons
753 if(pDef == G4Proton::ProtonDefinition())
754 scintVector = MPT->GetProperty(kPROTONSCINTILLATIONYIELD);
755
756 // Deuterons
757 else if(pDef == G4Deuteron::DeuteronDefinition())
758 scintVector = MPT->GetProperty(kDEUTERONSCINTILLATIONYIELD);
759
760 // Tritons
761 else if(pDef == G4Triton::TritonDefinition())
762 scintVector = MPT->GetProperty(kTRITONSCINTILLATIONYIELD);
763
764 // Alphas
765 else if(pDef == G4Alpha::AlphaDefinition())
766 scintVector = MPT->GetProperty(kALPHASCINTILLATIONYIELD);
767
768 // Ions (particles derived from G4VIon and G4Ions) and recoil ions
769 // below the production cut from neutrons after hElastic
770 else if(pDef->GetParticleType() == "nucleus" ||
772 scintVector = MPT->GetProperty(kIONSCINTILLATIONYIELD);
773
774 // Electrons (must also
775 else if(pDef == G4Electron::ElectronDefinition() ||
776 pDef == G4Gamma::GammaDefinition())
777 scintVector = MPT->GetProperty(kELECTRONSCINTILLATIONYIELD);
778
779 // Default for particles not enumerated/listed above
780 // includes gamma to account for shell-binding energy
781 // attributed to gamma from standard photoelectric effect)
782 else
783 scintVector = MPT->GetProperty(kELECTRONSCINTILLATIONYIELD);
784
785 // Throw an exception if no scintillation yield vector is found
786 if(!scintVector)
787 {
789 ed << "\nG4Scintillation::PostStepDoIt(): "
790 << "Request for scintillation yield for energy deposit and particle\n"
791 << "type without correct entry in MaterialPropertiesTable.\n"
792 << "ScintillationByParticleType requires at minimum that \n"
793 << "ELECTRONSCINTILLATIONYIELD is set by the user\n"
794 << G4endl;
795 G4String comments = "Missing MaterialPropertiesTable entry - No correct "
796 "entry in MaterialPropertiesTable";
797 G4Exception("G4Scintillation::PostStepDoIt", "Scint01", FatalException, ed,
798 comments);
799 }
800
801 ///////////////////////////////////////
802 // Calculate the scintillation light //
803 ///////////////////////////////////////
804 // To account for potential nonlinearity and scintillation photon
805 // density along the track, light (L) is produced according to:
806 // L_currentStep = L(PreStepKE) - L(PreStepKE - EDep)
807
808 G4double ScintillationYield = 0.;
809 G4double StepEnergyDeposit = aStep.GetTotalEnergyDeposit();
810 G4double PreStepKineticEnergy = aStep.GetPreStepPoint()->GetKineticEnergy();
811
812 if(PreStepKineticEnergy <= scintVector->GetMaxEnergy())
813 {
814 G4double Yield1 = scintVector->Value(PreStepKineticEnergy);
815 G4double Yield2 =
816 scintVector->Value(PreStepKineticEnergy - StepEnergyDeposit);
817 ScintillationYield = Yield1 - Yield2;
818 }
819 else
820 {
822 ed << "\nG4Scintillation::GetScintillationYieldByParticleType(): Request\n"
823 << "for scintillation light yield above the available energy range\n"
824 << "specified in G4MaterialPropertiesTable. A linear interpolation\n"
825 << "will be performed to compute the scintillation light yield using\n"
826 << "(L_max / E_max) as the photon yield per unit energy." << G4endl;
827 G4String cmt = "\nScintillation yield may be unphysical!\n";
828 G4Exception("G4Scintillation::GetScintillationYieldByParticleType()",
829 "Scint03", JustWarning, ed, cmt);
830
831 // Units: [# scintillation photons]
832 ScintillationYield = scintVector->GetMaxValue() /
833 scintVector->GetMaxEnergy() * StepEnergyDeposit;
834 }
835
836#ifdef G4DEBUG_SCINTILLATION
837 // Increment track aggregators
838 ScintTrackYield += ScintillationYield;
839 ScintTrackEDep += StepEnergyDeposit;
840
841 G4cout << "\n--- G4Scintillation::GetScintillationYieldByParticleType() ---\n"
842 << "--\n"
843 << "-- Name = "
844 << aTrack.GetParticleDefinition()->GetParticleName() << "\n"
845 << "-- TrackID = " << aTrack.GetTrackID() << "\n"
846 << "-- ParentID = " << aTrack.GetParentID() << "\n"
847 << "-- Current KE = " << aTrack.GetKineticEnergy() / MeV
848 << " MeV\n"
849 << "-- Step EDep = " << aStep.GetTotalEnergyDeposit() / MeV
850 << " MeV\n"
851 << "-- Track EDep = " << ScintTrackEDep / MeV << " MeV\n"
852 << "-- Vertex KE = " << aTrack.GetVertexKineticEnergy() / MeV
853 << " MeV\n"
854 << "-- Step yield = " << ScintillationYield << " photons\n"
855 << "-- Track yield = " << ScintTrackYield << " photons\n"
856 << G4endl;
857
858 // The track has terminated within or has left the scintillator volume
859 if((aTrack.GetTrackStatus() == fStopButAlive) or
861 {
862 // Reset aggregators for the next track
863 ScintTrackEDep = 0.;
864 ScintTrackYield = 0.;
865 }
866#endif
867
868 return ScintillationYield;
869}
870
871//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
873 const G4Track& aTrack, const G4Step& aStep, G4double& yield1,
874 G4double& yield2, G4double& yield3)
875{
876 // new in 10.7, allow multiple time constants with ScintByParticleType
877 // Get the G4MaterialPropertyVector containing the scintillation
878 // yield as a function of the energy deposited and particle type
879
881 G4MaterialPropertyVector* yieldVector = nullptr;
884
885 // Protons
886 if(pDef == G4Proton::ProtonDefinition())
887 {
888 yieldVector = MPT->GetProperty(kPROTONSCINTILLATIONYIELD);
891 : 1.;
894 : 0.;
897 : 0.;
898 }
899
900 // Deuterons
901 else if(pDef == G4Deuteron::DeuteronDefinition())
902 {
903 yieldVector = MPT->GetProperty(kDEUTERONSCINTILLATIONYIELD);
906 : 1.;
909 : 0.;
912 : 0.;
913 }
914
915 // Tritons
916 else if(pDef == G4Triton::TritonDefinition())
917 {
918 yieldVector = MPT->GetProperty(kTRITONSCINTILLATIONYIELD);
921 : 1.;
924 : 0.;
927 : 0.;
928 }
929
930 // Alphas
931 else if(pDef == G4Alpha::AlphaDefinition())
932 {
933 yieldVector = MPT->GetProperty(kALPHASCINTILLATIONYIELD);
936 : 1.;
939 : 0.;
942 : 0.;
943 }
944
945 // Ions (particles derived from G4VIon and G4Ions) and recoil ions
946 // below the production cut from neutrons after hElastic
947 else if(pDef->GetParticleType() == "nucleus" ||
949 {
950 yieldVector = MPT->GetProperty(kIONSCINTILLATIONYIELD);
953 : 1.;
956 : 0.;
959 : 0.;
960 }
961
962 // Electrons (must also account for shell-binding energy
963 // attributed to gamma from standard photoelectric effect)
964 // and, default for particles not enumerated/listed above
965 else
966 {
967 yieldVector = MPT->GetProperty(kELECTRONSCINTILLATIONYIELD);
970 : 1.;
973 : 0.;
976 : 0.;
977 }
978
979 // Throw an exception if no scintillation yield vector is found
980 if(!yieldVector)
981 {
983 ed << "\nG4Scintillation::PostStepDoIt(): "
984 << "Request for scintillation yield for energy deposit and particle\n"
985 << "type without correct entry in MaterialPropertiesTable.\n"
986 << "ScintillationByParticleType requires at minimum that \n"
987 << "ELECTRONSCINTILLATIONYIELD is set by the user\n"
988 << G4endl;
989 G4String comments = "Missing MaterialPropertiesTable entry - No correct "
990 "entry in MaterialPropertiesTable";
991 G4Exception("G4Scintillation::PostStepDoIt", "Scint01", FatalException, ed,
992 comments);
993 }
994
995 ///////////////////////////////////////
996 // Calculate the scintillation light //
997 ///////////////////////////////////////
998 // To account for potential nonlinearity and scintillation photon
999 // density along the track, light (L) is produced according to:
1000 // L_currentStep = L(PreStepKE) - L(PreStepKE - EDep)
1001
1002 G4double ScintillationYield = 0.;
1003 G4double StepEnergyDeposit = aStep.GetTotalEnergyDeposit();
1004 G4double PreStepKineticEnergy = aStep.GetPreStepPoint()->GetKineticEnergy();
1005
1006 if(PreStepKineticEnergy <= yieldVector->GetMaxEnergy())
1007 {
1008 // G4double Yield1 = yieldVector->Value(PreStepKineticEnergy);
1009 // G4double Yield2 = yieldVector->Value(PreStepKineticEnergy -
1010 // StepEnergyDeposit); ScintillationYield = Yield1 - Yield2;
1011 ScintillationYield =
1012 yieldVector->Value(PreStepKineticEnergy) -
1013 yieldVector->Value(PreStepKineticEnergy - StepEnergyDeposit);
1014 }
1015 else
1016 {
1018 ed << "\nG4Scintillation::GetScintillationYieldByParticleType(): Request\n"
1019 << "for scintillation light yield above the available energy range\n"
1020 << "specified in G4MaterialPropertiesTable. A linear interpolation\n"
1021 << "will be performed to compute the scintillation light yield using\n"
1022 << "(L_max / E_max) as the photon yield per unit energy." << G4endl;
1023 G4String cmt = "\nScintillation yield may be unphysical!\n";
1024 G4Exception("G4Scintillation::GetScintillationYieldByParticleType()",
1025 "Scint03", JustWarning, ed, cmt);
1026
1027 // Units: [# scintillation photons]
1028 ScintillationYield = yieldVector->GetMaxValue() /
1029 yieldVector->GetMaxEnergy() * StepEnergyDeposit;
1030 }
1031
1032#ifdef G4DEBUG_SCINTILLATION
1033 // Increment track aggregators
1034 ScintTrackYield += ScintillationYield;
1035 ScintTrackEDep += StepEnergyDeposit;
1036
1037 G4cout << "\n--- G4Scintillation::GetScintillationYieldByParticleType() ---\n"
1038 << "--\n"
1039 << "-- Name = "
1040 << aTrack.GetParticleDefinition()->GetParticleName() << "\n"
1041 << "-- TrackID = " << aTrack.GetTrackID() << "\n"
1042 << "-- ParentID = " << aTrack.GetParentID() << "\n"
1043 << "-- Current KE = " << aTrack.GetKineticEnergy() / MeV
1044 << " MeV\n"
1045 << "-- Step EDep = " << aStep.GetTotalEnergyDeposit() / MeV
1046 << " MeV\n"
1047 << "-- Track EDep = " << ScintTrackEDep / MeV << " MeV\n"
1048 << "-- Vertex KE = " << aTrack.GetVertexKineticEnergy() / MeV
1049 << " MeV\n"
1050 << "-- Step yield = " << ScintillationYield << " photons\n"
1051 << "-- Track yield = " << ScintTrackYield << " photons\n"
1052 << G4endl;
1053
1054 // The track has terminated within or has left the scintillator volume
1055 if((aTrack.GetTrackStatus() == fStopButAlive) or
1057 {
1058 // Reset aggregators for the next track
1059 ScintTrackEDep = 0.;
1060 ScintTrackYield = 0.;
1061 }
1062#endif
1063
1064 return ScintillationYield;
1065}
1066
1067//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
1069{
1071 if(fIntegralTable1)
1072 {
1073 for(size_t i = 0; i < fIntegralTable1->entries(); ++i)
1074 {
1076 v->DumpValues();
1077 }
1078 }
1079 if(fIntegralTable2)
1080 {
1081 for(size_t i = 0; i < fIntegralTable2->entries(); ++i)
1082 {
1084 v->DumpValues();
1085 }
1086 }
1087 if(fIntegralTable3)
1088 {
1089 for(size_t i = 0; i < fIntegralTable3->entries(); ++i)
1090 {
1092 v->DumpValues();
1093 }
1094 }
1095}
@ fScintillation
G4double condition(const G4ErrorSymMatrix &m)
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
G4ForceCondition
@ StronglyForced
@ Forced
@ kSCINTILLATIONCOMPONENT1
@ kSCINTILLATIONCOMPONENT2
@ kSCINTILLATIONCOMPONENT3
@ kELECTRONSCINTILLATIONYIELD
@ kALPHASCINTILLATIONYIELD
@ kPROTONSCINTILLATIONYIELD
@ kDEUTERONSCINTILLATIONYIELD
@ kIONSCINTILLATIONYIELD
@ kTRITONSCINTILLATIONYIELD
@ kSCINTILLATIONTIMECONSTANT1
@ kSCINTILLATIONRISETIME2
@ kTRITONSCINTILLATIONYIELD1
@ kDEUTERONSCINTILLATIONYIELD3
@ kIONSCINTILLATIONYIELD1
@ kSCINTILLATIONRISETIME1
@ kFASTSCINTILLATIONRISETIME
@ kDEUTERONSCINTILLATIONYIELD2
@ kSLOWSCINTILLATIONRISETIME
@ kTRITONSCINTILLATIONYIELD2
@ kALPHASCINTILLATIONYIELD2
@ kELECTRONSCINTILLATIONYIELD3
@ kALPHASCINTILLATIONYIELD1
@ kELECTRONSCINTILLATIONYIELD2
@ kIONSCINTILLATIONYIELD2
@ kIONSCINTILLATIONYIELD3
@ kSCINTILLATIONRISETIME3
@ kPROTONSCINTILLATIONYIELD2
@ kDEUTERONSCINTILLATIONYIELD1
@ kTRITONSCINTILLATIONYIELD3
@ kSCINTILLATIONTIMECONSTANT3
@ kPROTONSCINTILLATIONYIELD3
@ kELECTRONSCINTILLATIONYIELD1
@ kALPHASCINTILLATIONYIELD3
@ kSCINTILLATIONTIMECONSTANT2
@ kPROTONSCINTILLATIONYIELD1
std::vector< G4Material * > G4MaterialTable
G4long G4Poisson(G4double mean)
Definition: G4Poisson.hh:50
G4ProcessType
@ fGeomBoundary
Definition: G4StepStatus.hh:43
@ 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:57
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:83
static G4Deuteron * DeuteronDefinition()
Definition: G4Deuteron.cc:88
void SetPolarization(const G4ThreeVector &)
G4ParticleDefinition * GetDefinition() const
void SetKineticEnergy(G4double aEnergy)
static G4Electron * ElectronDefinition()
Definition: G4Electron.cc:88
G4double VisibleEnergyDepositionAtAStep(const G4Step *) const
static G4Gamma * GammaDefinition()
Definition: G4Gamma.cc:80
G4MaterialPropertyVector * GetProperty(const char *key, G4bool warning=false)
G4bool ConstPropertyExists(const G4String &key) const
G4double GetConstProperty(const G4String &key) const
G4MaterialPropertiesTable * GetMaterialPropertiesTable() const
Definition: G4Material.hh:254
static size_t GetNumberOfMaterials()
Definition: G4Material.cc:644
static G4MaterialTable * GetMaterialTable()
Definition: G4Material.cc:637
size_t GetIndex() const
Definition: G4Material.hh:258
static G4Neutron * NeutronDefinition()
Definition: G4Neutron.cc:98
G4int GetScintVerboseLevel() const
G4bool GetScintStackPhotons() const
static G4OpticalParameters * Instance()
G4double GetScintExcitationRatio() const
G4bool GetScintEnhancedTimeConstants() const
G4bool GetScintByParticleType() const
G4bool GetScintFiniteRiseTime() const
G4double GetScintYieldFactor() const
G4bool GetScintTrackInfo() const
G4bool GetScintTrackSecondariesFirst() const
void AddSecondary(G4Track *aSecondary)
virtual void Initialize(const G4Track &)
const G4String & GetParticleType() const
G4double GetPDGCharge() const
const G4String & GetParticleName() const
void InsertValues(G4double energy, G4double value)
G4double GetEnergy(G4double aValue)
void clearAndDestroy()
std::size_t entries() const
void insertAt(std::size_t, G4PhysicsVector *)
G4double Energy(std::size_t index) const
G4double Value(G4double theEnergy, std::size_t &lastidx) const
G4double GetMaxEnergy() const
std::size_t GetVectorLength() const
void DumpValues(G4double unitE=1.0, G4double unitV=1.0) const
static G4Proton * ProtonDefinition()
Definition: G4Proton.cc:87
G4PhysicsTable * fIntegralTable3
G4VParticleChange * AtRestDoIt(const G4Track &aTrack, const G4Step &aStep) override
void SetScintillationYieldFactor(const G4double yieldfactor)
void SetTrackSecondariesFirst(const G4bool state)
void SetStackPhotons(const G4bool)
G4double GetMeanFreePath(const G4Track &aTrack, G4double, G4ForceCondition *) override
void BuildPhysicsTable(const G4ParticleDefinition &aParticleType) override
G4double GetScintillationYieldByParticleType(const G4Track &aTrack, const G4Step &aStep)
void SetScintillationExcitationRatio(const G4double ratio)
G4PhysicsTable * fIntegralTable1
void SetScintillationTrackInfo(const G4bool trackType)
void SetEnhancedTimeConstants(G4bool)
G4double GetMeanLifeTime(const G4Track &aTrack, G4ForceCondition *) override
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep) override
G4bool IsApplicable(const G4ParticleDefinition &aParticleType) override
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)
G4PhysicsTable * fIntegralTable2
G4StepStatus GetStepStatus() const
G4double GetVelocity() const
G4double GetGlobalTime() const
const G4ThreeVector & GetPosition() const
const G4TouchableHandle & GetTouchableHandle() const
G4double GetKineticEnergy() const
Definition: G4Step.hh:62
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
G4int GetParentID() const
void SetParentID(const G4int aValue)
static G4Triton * TritonDefinition()
Definition: G4Triton.cc:89
void ProposeTrackStatus(G4TrackStatus status)
G4int GetNumberOfSecondaries() const
void SetNumberOfSecondaries(G4int totSecondaries)
void SetVerboseLevel(G4int value)
Definition: G4VProcess.hh:412
G4ParticleChange aParticleChange
Definition: G4VProcess.hh:327
G4int verboseLevel
Definition: G4VProcess.hh:356
void SetProcessSubType(G4int)
Definition: G4VProcess.hh:406
const G4String & GetProcessName() const
Definition: G4VProcess.hh:382
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
#define DBL_MAX
Definition: templates.hh:62