File indexing completed on 2026-04-10 07:50:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 #ifdef STANDALONE
0069
0070 #include "SLOG.hh"
0071 #include "U4.hh"
0072 #else
0073 #include <boost/python.hpp>
0074 #endif
0075
0076 #include "Local_DsG4Scintillation.hh"
0077 #include "globals.hh"
0078 #include "G4PhysicalConstants.hh"
0079 #include "G4SystemOfUnits.hh"
0080 #include "G4UnitsTable.hh"
0081 #include "G4LossTableManager.hh"
0082 #include "G4MaterialCutsCouple.hh"
0083 #include "G4Gamma.hh"
0084 #include "G4Electron.hh"
0085 #include "globals.hh"
0086
0087 #ifdef WITH_G4OPTICKS
0088 #include "G4Opticks.hh"
0089 #include "CGenstep.hh"
0090 #include "CTrack.hh"
0091 #include "CPhotonInfo.hh"
0092 #include "SLOG.hh"
0093 #endif
0094
0095
0096
0097 #ifdef WITH_G4OPTICKS
0098
0099 const plog::Severity Local_DsG4Scintillation::LEVEL = error ;
0100 #endif
0101
0102
0103 #include "U4Stack.h"
0104 #include "SEvt.hh"
0105
0106 const bool Local_DsG4Scintillation::FLOAT = getenv("Local_DsG4Scintillation_FLOAT") != nullptr ;
0107 const int Local_DsG4Scintillation::PIDX = std::atoi( getenv("PIDX") ? getenv("PIDX") : "-1" );
0108
0109
0110 void Local_DsG4Scintillation::ResetNumberOfInteractionLengthLeft()
0111 {
0112
0113 G4double u = G4UniformRand() ;
0114
0115 #ifndef PRODUCTION
0116 #ifdef DEBUG_TAG
0117 SEvt::AddTag( 1, U4Stack_ScintDiscreteReset, u );
0118 #endif
0119 #endif
0120
0121
0122
0123 if(FLOAT)
0124 {
0125 float f = -1.f*std::log( float(u) ) ;
0126 theNumberOfInteractionLengthLeft = f ;
0127 }
0128 else
0129 {
0130 theNumberOfInteractionLengthLeft = -1.*G4Log(u) ;
0131 }
0132 theInitialNumberOfInteractionLength = theNumberOfInteractionLengthLeft;
0133 }
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146 using namespace std;
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164 Local_DsG4Scintillation::Local_DsG4Scintillation(G4int opticksMode, const G4String& processName,
0165 G4ProcessType type)
0166 : G4VRestDiscreteProcess(processName, type)
0167 , doReemission(true)
0168 , doBothProcess(true)
0169 , doReemissionOnly(false)
0170 , fEnableQuenching(true)
0171 , slowerTimeConstant(0) , slowerRatio(0)
0172 , gammaSlowerTime(0) , gammaSlowerRatio(0)
0173 , neutronSlowerTime(0) , neutronSlowerRatio(0)
0174 , alphaSlowerTime(0) , alphaSlowerRatio(0)
0175 , flagDecayTimeFast(true), flagDecayTimeSlow(true)
0176 , fPhotonWeight(1.0)
0177 , fApplyPreQE(false)
0178 , fPreQE(1.)
0179 , m_noop(false)
0180 , m_opticksMode(opticksMode)
0181 {
0182 SetProcessSubType(fScintillation);
0183 fTrackSecondariesFirst = false;
0184
0185 YieldFactor = 1.0;
0186 ExcitationRatio = 1.0;
0187
0188 theFastIntegralTable = NULL;
0189 theSlowIntegralTable = NULL;
0190 theReemissionIntegralTable = NULL;
0191
0192
0193
0194
0195 #ifdef STANDALONE
0196 {
0197 const char* level_ = getenv("Local_DsG4Scintillation_verboseLevel") ;
0198 const char* fallback = "0" ;
0199 int level = std::atoi(level_ ? level_ : fallback) ;
0200 SetVerboseLevel(level);
0201 std::cout << "Local_DsG4Scintillation::Local_DsG4Scintillation level " << level << " verboseLevel " << verboseLevel << std::endl ;
0202 }
0203 #endif
0204
0205 if (verboseLevel > 0) {
0206 G4cout << GetProcessName() << " is created " << G4endl;
0207 }
0208
0209 BuildThePhysicsTable();
0210
0211
0212
0213 }
0214
0215
0216
0217
0218
0219 Local_DsG4Scintillation::~Local_DsG4Scintillation()
0220 {
0221 if (theFastIntegralTable != NULL) {
0222 theFastIntegralTable->clearAndDestroy();
0223 delete theFastIntegralTable;
0224 }
0225 if (theSlowIntegralTable != NULL) {
0226 theSlowIntegralTable->clearAndDestroy();
0227 delete theSlowIntegralTable;
0228 }
0229 if (theReemissionIntegralTable != NULL) {
0230 theReemissionIntegralTable->clearAndDestroy();
0231 delete theReemissionIntegralTable;
0232 }
0233 }
0234
0235
0236
0237
0238
0239
0240
0241
0242 G4VParticleChange*
0243 Local_DsG4Scintillation::AtRestDoIt(const G4Track& aTrack, const G4Step& aStep)
0244
0245
0246
0247
0248 {
0249 return Local_DsG4Scintillation::PostStepDoIt(aTrack, aStep);
0250 }
0251
0252
0253
0254
0255 G4VParticleChange*
0256 Local_DsG4Scintillation::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep)
0257
0258
0259
0260
0261
0262
0263 {
0264 aParticleChange.Initialize(aTrack);
0265
0266
0267 if (m_noop) {
0268 aParticleChange.SetNumberOfSecondaries(0);
0269 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
0270 }
0271
0272
0273 G4String pname="";
0274 G4ThreeVector vertpos;
0275
0276
0277 G4bool flagReemission= false;
0278
0279 if (aTrack.GetDefinition() == G4OpticalPhoton::OpticalPhoton()) {
0280 G4Track *track=aStep.GetTrack();
0281
0282
0283
0284 const G4VProcess* process = track->GetCreatorProcess();
0285 if(process) pname = process->GetProcessName();
0286
0287 if (verboseLevel > 0) {
0288 G4cout<<"Optical photon. Process name is " << pname<<G4endl;
0289 }
0290 if(doBothProcess) {
0291 flagReemission= doReemission
0292 && aTrack.GetTrackStatus() == fStopAndKill
0293 && aStep.GetPostStepPoint()->GetStepStatus() != fGeomBoundary;
0294 }
0295 else{
0296 flagReemission= doReemission
0297 && aTrack.GetTrackStatus() == fStopAndKill
0298 && aStep.GetPostStepPoint()->GetStepStatus() != fGeomBoundary
0299 && pname=="Cerenkov";
0300 }
0301 if(verboseLevel > 0) {
0302 G4cout<<"flag of Reemission is "<<flagReemission<<"!!"<<G4endl;
0303 }
0304 if (!flagReemission) {
0305 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
0306 }
0307 }
0308
0309 G4double TotalEnergyDeposit = aStep.GetTotalEnergyDeposit();
0310 #ifdef STANDALONE
0311
0312 #endif
0313
0314
0315 if (verboseLevel > 0 ) {
0316 G4cout << " TotalEnergyDeposit " << TotalEnergyDeposit
0317 << " material " << aTrack.GetMaterial()->GetName() << G4endl;
0318 }
0319 if (TotalEnergyDeposit <= 0.0 && !flagReemission) {
0320 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
0321 }
0322
0323 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
0324 const G4String aParticleName = aParticle->GetDefinition()->GetParticleName();
0325 const G4Material* aMaterial = aTrack.GetMaterial();
0326
0327 G4MaterialPropertiesTable* aMaterialPropertiesTable =
0328 aMaterial->GetMaterialPropertiesTable();
0329
0330
0331
0332 if (!aMaterialPropertiesTable)
0333 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
0334
0335
0336
0337
0338
0339
0340
0341 const G4MaterialPropertyVector* Fast_Intensity =
0342 aMaterialPropertiesTable->GetProperty("FASTCOMPONENT");
0343 const G4MaterialPropertyVector* Slow_Intensity =
0344 aMaterialPropertiesTable->GetProperty("SLOWCOMPONENT");
0345 const G4MaterialPropertyVector* Reemission_Prob =
0346 aMaterialPropertiesTable->GetProperty("REEMISSIONPROB");
0347 if (verboseLevel > 0 ) {
0348 G4cout << " MaterialPropertyVectors: Fast_Intensity " << Fast_Intensity
0349 << " Slow_Intensity " << Slow_Intensity << " Reemission_Prob " << Reemission_Prob << G4endl;
0350 }
0351 if (!Fast_Intensity && !Slow_Intensity )
0352 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
0353
0354
0355
0356
0357
0358
0359
0360 G4MaterialPropertyVector* Ratio_timeconstant = 0 ;
0361 if (aParticleName == "opticalphoton") {
0362 Ratio_timeconstant = aMaterialPropertiesTable->GetProperty("OpticalCONSTANT");
0363 }
0364 else if(aParticleName == "gamma" || aParticleName == "e+" || aParticleName == "e-") {
0365 Ratio_timeconstant = aMaterialPropertiesTable->GetProperty("GammaCONSTANT");
0366 }
0367 else if(aParticleName == "alpha") {
0368 Ratio_timeconstant = aMaterialPropertiesTable->GetProperty("AlphaCONSTANT");
0369 }
0370 else {
0371 Ratio_timeconstant = aMaterialPropertiesTable->GetProperty("NeutronCONSTANT");
0372 }
0373
0374
0375
0376 G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
0377 G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
0378
0379 G4ThreeVector x0 = pPreStepPoint->GetPosition();
0380 G4ThreeVector p0 = aStep.GetDeltaPosition().unit();
0381 G4double t0 = pPreStepPoint->GetGlobalTime();
0382
0383
0384
0385 G4int NumTracks=0;
0386 G4double weight=1.0;
0387 if (flagReemission) {
0388 if(verboseLevel > 0){
0389 G4cout<<"the process name is "<<pname<<"!!"<<G4endl;}
0390
0391 if ( Reemission_Prob == 0)
0392 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
0393 G4double p_reemission=
0394 Reemission_Prob->Value(aTrack.GetKineticEnergy());
0395
0396 G4double u_reemission = G4UniformRand() ;
0397
0398 #ifndef PRODUCTION
0399 #ifdef DEBUG_TAG
0400 SEvt::AddTag(1, U4Stack_Reemission, u_reemission);
0401 #endif
0402 #endif
0403
0404 if (u_reemission >= p_reemission)
0405 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
0406 NumTracks= 1;
0407 weight= aTrack.GetWeight();
0408 if (verboseLevel > 0 ) {
0409 G4cout << " flagReemission " << flagReemission << " weight " << weight << G4endl;}
0410 }
0411 else {
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427 G4double ScintillationYield = 0;
0428 {
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438 ScintillationYield = aMaterialPropertiesTable->GetConstProperty("SCINTILLATIONYIELD");
0439
0440 }
0441
0442 G4double ResolutionScale = 1;
0443 {
0444 const G4MaterialPropertyVector* ptable =
0445 aMaterialPropertiesTable->GetProperty("RESOLUTIONSCALE");
0446 if (ptable)
0447 ResolutionScale = ptable->Value(0);
0448 }
0449
0450 G4double dE = TotalEnergyDeposit;
0451 G4double dx = aStep.GetStepLength();
0452 G4double dE_dx = dE/dx;
0453 if(aTrack.GetDefinition() == G4Gamma::Gamma() && dE > 0)
0454 {
0455 G4LossTableManager* manager = G4LossTableManager::Instance();
0456 dE_dx = dE/manager->GetRange(G4Electron::Electron(), dE, aTrack.GetMaterialCutsCouple());
0457
0458 }
0459
0460 G4double delta = dE_dx/aMaterial->GetDensity();
0461
0462 G4double birk1 = birksConstant1;
0463 if(abs(aParticle->GetCharge())>1.5)
0464 birk1 = 0.57*birk1;
0465
0466 G4double birk2 = 0;
0467
0468 birk2 = birksConstant2;
0469
0470 G4double QuenchedTotalEnergyDeposit = TotalEnergyDeposit;
0471
0472 if (fEnableQuenching) {
0473 QuenchedTotalEnergyDeposit
0474 = TotalEnergyDeposit/(1+birk1*delta+birk2*delta*delta);
0475 }
0476
0477
0478 if(FastMu300nsTrick) {
0479
0480 if(aStep.GetTrack()->GetGlobalTime()/ns>300) {
0481 ScintillationYield = YieldFactor * ScintillationYield;
0482 }
0483 else{
0484 ScintillationYield=0.;
0485 }
0486 }
0487 else {
0488 ScintillationYield = YieldFactor * ScintillationYield;
0489 }
0490
0491 G4double MeanNumberOfPhotons= ScintillationYield * QuenchedTotalEnergyDeposit;
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503 G4double MeanNumberOfTracks= MeanNumberOfPhotons/fPhotonWeight;
0504 if ( fApplyPreQE ) {
0505 MeanNumberOfTracks*=fPreQE;
0506 }
0507 if (MeanNumberOfTracks > 10.) {
0508 G4double sigma = ResolutionScale * sqrt(MeanNumberOfTracks);
0509 NumTracks = G4int(G4RandGauss::shoot(MeanNumberOfTracks,sigma)+0.5);
0510 }
0511 else {
0512 NumTracks = G4int(G4Poisson(MeanNumberOfTracks));
0513 }
0514 if ( verboseLevel > 0 ) {
0515 G4cout << " Generated " << NumTracks << " scint photons. mean(scint photons) = " << MeanNumberOfTracks << G4endl;
0516 }
0517 }
0518
0519 weight*=fPhotonWeight;
0520 if ( verboseLevel > 0 ) {
0521 G4cout << " set scint photon weight to " << weight << " after multiplying original weight by fPhotonWeight " << fPhotonWeight
0522 << " NumTracks = " << NumTracks
0523 << G4endl;
0524 }
0525
0526 if (NumTracks <= 0) {
0527
0528 aParticleChange.SetNumberOfSecondaries(0);
0529 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
0530 }
0531
0532
0533
0534 aParticleChange.SetNumberOfSecondaries(NumTracks);
0535
0536 if (fTrackSecondariesFirst) {
0537 if (!flagReemission)
0538 if (aTrack.GetTrackStatus() == fAlive )
0539 aParticleChange.ProposeTrackStatus(fSuspend);
0540 }
0541
0542
0543
0544 G4int materialIndex = aMaterial->GetIndex();
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561 int nscnt = Ratio_timeconstant->GetVectorLength();
0562 std::vector<G4int> NumVec(nscnt);
0563 NumVec.clear();
0564 for(G4int i = 0 ; i < NumTracks ; i++){
0565 G4double p = G4UniformRand();
0566
0567 #ifndef PRODUCTION
0568 #ifdef DEBUG_TAG
0569 SEvt::AddTag(1, U4Stack_Reemission, p );
0570 #endif
0571 #endif
0572
0573 G4double p_count = 0;
0574 for(G4int j = 0 ; j < nscnt; j++)
0575 {
0576 p_count += (*Ratio_timeconstant)[j] ;
0577 if( p < p_count ){
0578 NumVec[j]++ ;
0579 break;
0580 }
0581 }
0582
0583 }
0584
0585
0586
0587 #ifdef WITH_G4OPTICKS
0588
0589 CPho ancestor = CPhotonInfo::Get(&aTrack);
0590 int ancestor_id = ancestor.get_id() ;
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605 #endif
0606
0607 #ifdef STANDALONE
0608 U4::GenPhotonAncestor(&aTrack);
0609 #endif
0610
0611
0612
0613
0614 for(G4int scnt = 0 ; scnt < nscnt ; scnt++){
0615
0616 G4double ScintillationTime = 0.*ns;
0617 G4PhysicsOrderedFreeVector* ScintillationIntegral = NULL;
0618
0619 if ( scnt == 0 ){
0620 ScintillationIntegral =
0621 (G4PhysicsOrderedFreeVector*)((*theFastIntegralTable)(materialIndex));
0622 }
0623 else{
0624 ScintillationIntegral =
0625 (G4PhysicsOrderedFreeVector*)((*theSlowIntegralTable)(materialIndex));
0626 }
0627
0628
0629
0630 ScintillationTime = Ratio_timeconstant->Energy(scnt);
0631 if (!flagDecayTimeFast && scnt == 0){
0632 ScintillationTime = 0.*ns ;
0633 }
0634
0635 if (!flagDecayTimeSlow && scnt != 0){
0636
0637 ScintillationTime = 0.*ns ;
0638 }
0639
0640 G4int NumPhoton = NumVec[scnt] ;
0641
0642
0643 #ifdef WITH_G4OPTICKS
0644 if(flagReemission) assert( NumPhoton == 0 || NumPhoton == 1);
0645 bool is_opticks_genstep = NumPhoton > 0 && !flagReemission ;
0646
0647 CGenstep gs ;
0648 if(is_opticks_genstep && (m_opticksMode & 1))
0649 {
0650 gs = G4Opticks::Get()->collectGenstep_Local_DsG4Scintillation_r4695( &aTrack, &aStep, NumPhoton, scnt, ScintillationTime);
0651 }
0652 #endif
0653
0654 #ifdef STANDALONE
0655 if(flagReemission) assert( NumPhoton == 0 || NumPhoton == 1);
0656 bool is_opticks_genstep = NumPhoton > 0 && !flagReemission ;
0657 if(is_opticks_genstep && (m_opticksMode & 1))
0658 {
0659 NumPhoton = std::min( NumPhoton, 3 );
0660 U4::CollectGenstep_DsG4Scintillation_r4695( &aTrack, &aStep, NumPhoton, scnt, ScintillationTime);
0661 }
0662 #endif
0663
0664 if( m_opticksMode == 0 || (m_opticksMode & 2) )
0665 {
0666
0667 for(G4int i = 0 ; i < NumPhoton ; i++) {
0668 #ifdef WITH_G4OPTICKS
0669 G4Opticks::Get()->setAlignIndex( ancestor_id > -1 ? ancestor_id : gs.offset + i );
0670 #endif
0671 #ifdef STANDALONE
0672 U4::GenPhotonBegin(i);
0673 #endif
0674
0675 G4double sampledEnergy;
0676 if ( !flagReemission ) {
0677
0678
0679 G4double u_sampledEnergy = G4UniformRand() ;
0680
0681 G4double CIIvalue = u_sampledEnergy*
0682 ScintillationIntegral->GetMaxValue();
0683 sampledEnergy=
0684 ScintillationIntegral->GetEnergy(CIIvalue);
0685
0686 if (verboseLevel>1)
0687 {
0688 G4cout << "sampledEnergy = " << sampledEnergy << G4endl;
0689 G4cout << "CIIvalue = " << CIIvalue << G4endl;
0690 }
0691 }
0692 else {
0693
0694
0695 G4double u_sampledEnergy = G4UniformRand() ;
0696 #ifndef PRODUCTION
0697 #ifdef DEBUG_TAG
0698 SEvt::AddTag(1, U4Stack_Reemission, u_sampledEnergy );
0699 #endif
0700 #endif
0701
0702 G4double CIIvalue = u_sampledEnergy*
0703 ScintillationIntegral->GetMaxValue();
0704 if (CIIvalue == 0.0) {
0705
0706 aParticleChange.SetNumberOfSecondaries(0);
0707 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
0708 }
0709 sampledEnergy=
0710 ScintillationIntegral->GetEnergy(CIIvalue);
0711 if (verboseLevel>1) {
0712 G4cout << "oldEnergy = " <<aTrack.GetKineticEnergy() << G4endl;
0713 G4cout << "reemittedSampledEnergy = " << sampledEnergy
0714 << "\nreemittedCIIvalue = " << CIIvalue << G4endl;
0715 }
0716 }
0717
0718
0719
0720 G4double u_cost = G4UniformRand();
0721 #ifndef PRODUCTION
0722 #ifdef DEBUG_TAG
0723 SEvt::AddTag(1, U4Stack_Reemission, u_cost );
0724 #endif
0725 #endif
0726
0727 G4double cost = 1. - 2.*u_cost ;
0728 G4double sint = sqrt((1.-cost)*(1.+cost));
0729
0730 G4double u_phi = G4UniformRand() ;
0731 #ifndef PRODUCTION
0732 #ifdef DEBUG_TAG
0733 SEvt::AddTag(1, U4Stack_Reemission, u_phi );
0734 #endif
0735 #endif
0736
0737 G4double phi = twopi*u_phi ;
0738 G4double sinp = sin(phi);
0739 G4double cosp = cos(phi);
0740
0741 G4double px = sint*cosp;
0742 G4double py = sint*sinp;
0743 G4double pz = cost;
0744
0745
0746 G4ParticleMomentum photonMomentum(px, py, pz);
0747
0748
0749 G4double sx = cost*cosp;
0750 G4double sy = cost*sinp;
0751 G4double sz = -sint;
0752
0753 G4ThreeVector photonPolarization(sx, sy, sz);
0754
0755 G4ThreeVector perp = photonMomentum.cross(photonPolarization);
0756
0757 u_phi = G4UniformRand() ;
0758 #ifndef PRODUCTION
0759 #ifdef DEBUG_TAG
0760 SEvt::AddTag(1, U4Stack_Reemission, u_phi );
0761 #endif
0762 #endif
0763
0764 phi = twopi*u_phi ;
0765 sinp = sin(phi);
0766 cosp = cos(phi);
0767
0768 photonPolarization = cosp * photonPolarization + sinp * perp;
0769
0770 photonPolarization = photonPolarization.unit();
0771
0772
0773
0774 G4DynamicParticle* aScintillationPhoton =
0775 new G4DynamicParticle(G4OpticalPhoton::OpticalPhoton(),
0776 photonMomentum);
0777 aScintillationPhoton->SetPolarization
0778 (photonPolarization.x(),
0779 photonPolarization.y(),
0780 photonPolarization.z());
0781
0782 aScintillationPhoton->SetKineticEnergy(sampledEnergy);
0783
0784
0785 G4double rand=0;
0786 G4ThreeVector aSecondaryPosition;
0787 G4double deltaTime;
0788 if (flagReemission) {
0789
0790
0791 G4double u_deltaTime = G4UniformRand() ;
0792 #ifndef PRODUCTION
0793 #ifdef DEBUG_TAG
0794 SEvt::AddTag(1, U4Stack_Reemission, u_deltaTime );
0795 #endif
0796 #endif
0797
0798 deltaTime= pPostStepPoint->GetGlobalTime() - t0
0799 -ScintillationTime * log( u_deltaTime );
0800 aSecondaryPosition= pPostStepPoint->GetPosition();
0801 vertpos = aTrack.GetVertexPosition();
0802
0803
0804
0805
0806
0807 }
0808 else {
0809 if (aParticle->GetDefinition()->GetPDGCharge() != 0)
0810 {
0811 rand = G4UniformRand();
0812 }
0813 else
0814 {
0815 rand = 1.0;
0816 }
0817
0818 G4double delta = rand * aStep.GetStepLength();
0819 deltaTime = delta /
0820 ((pPreStepPoint->GetVelocity()+
0821 pPostStepPoint->GetVelocity())/2.);
0822
0823 deltaTime = deltaTime -
0824 ScintillationTime * log( G4UniformRand() );
0825
0826 aSecondaryPosition =
0827 x0 + rand * aStep.GetDeltaPosition();
0828 }
0829 G4double aSecondaryTime = t0 + deltaTime;
0830 if ( verboseLevel>1 ){
0831 G4cout << "Generate " << i << "th scintillation photon at relative time(ns) " << deltaTime
0832 << " with ScintillationTime " << ScintillationTime << " flagReemission " << flagReemission << G4endl;
0833 }
0834 G4Track* aSecondaryTrack =
0835 new G4Track(aScintillationPhoton,aSecondaryTime,aSecondaryPosition);
0836
0837 aSecondaryTrack->SetWeight( weight );
0838 aSecondaryTrack->SetTouchableHandle(aStep.GetPreStepPoint()->GetTouchableHandle());
0839 aSecondaryTrack->SetParentID(aTrack.GetTrackID());
0840
0841 aParticleChange.SetSecondaryWeightByProcess( true );
0842 aParticleChange.AddSecondary(aSecondaryTrack);
0843
0844 aSecondaryTrack->SetWeight( weight );
0845 if ( verboseLevel > 0 ) {
0846 G4cout << " aSecondaryTrack->SetWeight( " << weight<< " ) ; aSecondaryTrack->GetWeight() = " << aSecondaryTrack->GetWeight() << G4endl;}
0847
0848 #ifdef WITH_G4OPTICKS
0849 aSecondaryTrack->SetUserInformation(CPhotonInfo::MakeScintillation(gs, i, ancestor ));
0850 G4Opticks::Get()->setAlignIndex(-1);
0851 #endif
0852
0853 #ifdef STANDALONE
0854 U4::GenPhotonEnd(i, aSecondaryTrack);
0855 #endif
0856
0857 }
0858
0859
0860 }
0861
0862
0863 }
0864
0865
0866
0867 G4VParticleChange* change = G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
0868
0869
0870 if (verboseLevel > 0) {
0871 G4cout << "\n Exiting from G4Scintillation::DoIt -- NumberOfSecondaries = "
0872 << aParticleChange.GetNumberOfSecondaries() << G4endl;
0873 }
0874
0875 return change ;
0876 }
0877
0878
0879
0880 #ifdef WITH_G4OPTICKS
0881 G4MaterialPropertyVector* Local_DsG4Scintillation::getMaterialProperty(const char* name, G4int materialIndex)
0882 {
0883 const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
0884 G4int numOfMaterials = G4Material::GetNumberOfMaterials();
0885 assert( materialIndex < numOfMaterials );
0886
0887 G4Material* aMaterial = (*theMaterialTable)[materialIndex];
0888 G4MaterialPropertiesTable* aMaterialPropertiesTable = aMaterial->GetMaterialPropertiesTable();
0889 G4MaterialPropertyVector* prop = aMaterialPropertiesTable ? aMaterialPropertiesTable->GetProperty(name) : nullptr ;
0890 return prop ;
0891 }
0892
0893 G4PhysicsOrderedFreeVector* Local_DsG4Scintillation::getScintillationIntegral(G4int scnt, G4int materialIndex) const
0894 {
0895 G4PhysicsOrderedFreeVector* ScintillationIntegral = NULL;
0896
0897 if ( scnt == 0 ){
0898 ScintillationIntegral =
0899 (G4PhysicsOrderedFreeVector*)((*theFastIntegralTable)(materialIndex));
0900 }
0901 else{
0902 ScintillationIntegral =
0903 (G4PhysicsOrderedFreeVector*)((*theSlowIntegralTable)(materialIndex));
0904 }
0905
0906 return ScintillationIntegral ;
0907 }
0908
0909
0910 G4double Local_DsG4Scintillation::getSampledEnergy(G4int scnt, G4int materialIndex) const
0911 {
0912 G4PhysicsOrderedFreeVector* ScintillationIntegral = getScintillationIntegral(scnt, materialIndex);
0913 G4double CIIvalue = G4UniformRand()*ScintillationIntegral->GetMaxValue();
0914 G4double sampledEnergy = ScintillationIntegral->GetEnergy(CIIvalue);
0915 return sampledEnergy ;
0916 }
0917
0918 G4double Local_DsG4Scintillation::getSampledWavelength(G4int scnt, G4int materialIndex) const
0919 {
0920 G4double sampledEnergy = getSampledEnergy(scnt, materialIndex );
0921 G4double wavelength = h_Planck*c_light/sampledEnergy ;
0922 G4double wavelength_nm = wavelength/nm ;
0923 return wavelength_nm ;
0924 }
0925 #endif
0926
0927
0928
0929
0930
0931
0932 void Local_DsG4Scintillation::BuildThePhysicsTable()
0933 {
0934 if (theFastIntegralTable && theSlowIntegralTable && theReemissionIntegralTable) return;
0935
0936 const G4MaterialTable* theMaterialTable =
0937 G4Material::GetMaterialTable();
0938 G4int numOfMaterials = G4Material::GetNumberOfMaterials();
0939
0940
0941 if (verboseLevel > 0) {
0942 G4cout << " theFastIntegralTable " << theFastIntegralTable
0943 << " theSlowIntegralTable " << theSlowIntegralTable
0944 << " theReemissionIntegralTable " << theReemissionIntegralTable << G4endl;
0945 }
0946 if(!theFastIntegralTable)theFastIntegralTable = new G4PhysicsTable(numOfMaterials);
0947 if(!theSlowIntegralTable)theSlowIntegralTable = new G4PhysicsTable(numOfMaterials);
0948 if(!theReemissionIntegralTable)theReemissionIntegralTable
0949 = new G4PhysicsTable(numOfMaterials);
0950 if (verboseLevel > 0) {
0951 G4cout << " building the physics tables for the scintillation process " << G4endl;
0952 }
0953
0954
0955 for (G4int i=0 ; i < numOfMaterials; i++) {
0956 G4PhysicsOrderedFreeVector* aPhysicsOrderedFreeVector =
0957 new G4PhysicsOrderedFreeVector();
0958 G4PhysicsOrderedFreeVector* bPhysicsOrderedFreeVector =
0959 new G4PhysicsOrderedFreeVector();
0960 G4PhysicsOrderedFreeVector* cPhysicsOrderedFreeVector =
0961 new G4PhysicsOrderedFreeVector();
0962
0963
0964
0965
0966 G4Material* aMaterial = (*theMaterialTable)[i];
0967
0968 G4MaterialPropertiesTable* aMaterialPropertiesTable =
0969 aMaterial->GetMaterialPropertiesTable();
0970
0971 if (aMaterialPropertiesTable) {
0972
0973 G4MaterialPropertyVector* theFastLightVector =
0974 aMaterialPropertiesTable->GetProperty("FASTCOMPONENT");
0975
0976 if (theFastLightVector) {
0977 if (verboseLevel > 0) {
0978 G4cout << " Building the material properties table for FASTCOMPONENT" << G4endl;
0979 }
0980
0981
0982
0983 G4double currentIN = (*theFastLightVector)[0];
0984
0985 if (currentIN >= 0.0) {
0986
0987
0988
0989
0990 G4double currentPM = theFastLightVector->
0991 Energy(0);
0992
0993 G4double currentCII = 0.0;
0994
0995 aPhysicsOrderedFreeVector->
0996 InsertValues(currentPM , currentCII);
0997
0998
0999
1000 G4double prevPM = currentPM;
1001 G4double prevCII = currentCII;
1002 G4double prevIN = currentIN;
1003
1004
1005
1006
1007 for(size_t ii = 1;
1008 ii < theFastLightVector->GetVectorLength();
1009 ++ii)
1010 {
1011 currentPM = theFastLightVector->Energy(ii);
1012
1013 currentIN= (*theFastLightVector)[ii];
1014
1015 currentCII = 0.5 * (prevIN + currentIN);
1016
1017 currentCII = prevCII +
1018 (currentPM - prevPM) * currentCII;
1019
1020 aPhysicsOrderedFreeVector->
1021 InsertValues(currentPM, currentCII);
1022
1023 prevPM = currentPM;
1024 prevCII = currentCII;
1025 prevIN = currentIN;
1026 }
1027
1028 }
1029 }
1030
1031 G4MaterialPropertyVector* theSlowLightVector =
1032 aMaterialPropertiesTable->GetProperty("SLOWCOMPONENT");
1033
1034 if (theSlowLightVector) {
1035 if (verboseLevel > 0) {
1036 G4cout << " Building the material properties table for SLOWCOMPONENT" << G4endl;
1037 }
1038
1039
1040
1041
1042 G4double currentIN = (*theSlowLightVector)[0];
1043
1044 if (currentIN >= 0.0) {
1045
1046
1047
1048
1049 G4double currentPM = theSlowLightVector->Energy(0);
1050
1051 G4double currentCII = 0.0;
1052
1053 bPhysicsOrderedFreeVector->
1054 InsertValues(currentPM , currentCII);
1055
1056
1057
1058 G4double prevPM = currentPM;
1059 G4double prevCII = currentCII;
1060 G4double prevIN = currentIN;
1061
1062
1063
1064
1065 for (size_t ii = 1;
1066 ii < theSlowLightVector->GetVectorLength();
1067 ++ii)
1068 {
1069 currentPM = theSlowLightVector->Energy(ii);
1070
1071 currentIN = (*theSlowLightVector)[ii];
1072
1073 currentCII = 0.5 * (prevIN + currentIN);
1074
1075 currentCII = prevCII +
1076 (currentPM - prevPM) * currentCII;
1077
1078 bPhysicsOrderedFreeVector->
1079 InsertValues(currentPM, currentCII);
1080
1081 prevPM = currentPM;
1082 prevCII = currentCII;
1083 prevIN = currentIN;
1084 }
1085
1086 }
1087 }
1088
1089 G4MaterialPropertyVector* theReemissionVector =
1090 aMaterialPropertiesTable->GetProperty("REEMISSIONPROB");
1091
1092 if (theReemissionVector) {
1093 if (verboseLevel > 0) {
1094 G4cout << " Building the material properties table for REEMISSIONPROB" << G4endl;
1095 }
1096
1097
1098
1099
1100 G4double currentIN = (*theReemissionVector)[0];
1101
1102 if (currentIN >= 0.0) {
1103
1104
1105
1106
1107 G4double currentPM = theReemissionVector->Energy(0);
1108
1109 G4double currentCII = 0.0;
1110
1111 cPhysicsOrderedFreeVector->
1112 InsertValues(currentPM , currentCII);
1113
1114
1115
1116 G4double prevPM = currentPM;
1117 G4double prevCII = currentCII;
1118 G4double prevIN = currentIN;
1119
1120
1121
1122
1123 for (size_t ii = 1;
1124 ii < theReemissionVector->GetVectorLength();
1125 ++ii)
1126 {
1127
1128 currentPM = theReemissionVector->Energy(ii);
1129
1130 currentIN = (*theReemissionVector)[ii];
1131
1132 currentCII = 0.5 * (prevIN + currentIN);
1133
1134 currentCII = prevCII +
1135 (currentPM - prevPM) * currentCII;
1136
1137 cPhysicsOrderedFreeVector->
1138 InsertValues(currentPM, currentCII);
1139
1140 prevPM = currentPM;
1141 prevCII = currentCII;
1142 prevIN = currentIN;
1143 }
1144
1145 }
1146 }
1147
1148 }
1149
1150
1151
1152
1153
1154 theFastIntegralTable->insertAt(i,aPhysicsOrderedFreeVector);
1155 theSlowIntegralTable->insertAt(i,bPhysicsOrderedFreeVector);
1156 theReemissionIntegralTable->insertAt(i,cPhysicsOrderedFreeVector);
1157 }
1158
1159 if (verboseLevel > 0) {
1160 G4cout << " theFastIntegralTable " << theFastIntegralTable
1161 << " theSlowIntegralTable " << theSlowIntegralTable
1162 << " theReemissionIntegralTable " << theReemissionIntegralTable << G4endl;
1163 }
1164
1165
1166 }
1167
1168
1169
1170
1171
1172 G4double Local_DsG4Scintillation::GetMeanFreePath(const G4Track&,
1173 G4double ,
1174 G4ForceCondition* condition)
1175 {
1176 *condition = StronglyForced;
1177
1178 return DBL_MAX;
1179
1180 }
1181
1182
1183
1184
1185
1186 G4double Local_DsG4Scintillation::GetMeanLifeTime(const G4Track&,
1187 G4ForceCondition* condition)
1188 {
1189 *condition = Forced;
1190
1191 return DBL_MAX;
1192
1193 }
1194
1195
1196 G4PhysicsTable* Local_DsG4Scintillation::getSlowIntegralTable() {
1197 return theSlowIntegralTable;
1198 }
1199 G4PhysicsTable* Local_DsG4Scintillation::getFastIntegralTable() {
1200 return theFastIntegralTable;
1201 }
1202 G4PhysicsTable* Local_DsG4Scintillation::getReemissionIntegralTable() {
1203 return theReemissionIntegralTable;
1204 }