File indexing completed on 2026-09-13 08:28:45
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 #include "RMC01AnalysisManager.hh"
0040 #include "G4AdjointSimManager.hh"
0041 #include "G4SDManager.hh"
0042 #include "RMC01SD.hh"
0043 #include "G4THitsCollection.hh"
0044 #include "G4Electron.hh"
0045 #include "G4Proton.hh"
0046 #include "G4Gamma.hh"
0047 #include "G4Timer.hh"
0048 #include "G4RunManager.hh"
0049 #include "G4MTRunManager.hh"
0050 #include "G4PhysicalConstants.hh"
0051 #include "G4SystemOfUnits.hh"
0052 #include "RMC01AnalysisManagerMessenger.hh"
0053 #include "G4AccumulableManager.hh"
0054 #include "G4Threading.hh"
0055 #include "G4PhysicsOrderedFreeVector.hh"
0056 #include "G4Event.hh"
0057 #include "globals.hh"
0058 #include "G4SPSEneDistribution.hh"
0059 #include "RMC01PrimaryGeneratorAction.hh"
0060
0061 #include "G4AutoLock.hh"
0062
0063 namespace
0064 {
0065 G4Mutex fMergeMutex = G4MUTEX_INITIALIZER;
0066 G4double fGlobalEdep = 0.;
0067 G4double fGlobalEdep2 = 0.;
0068 std::fstream fConvergenceFileOutput;
0069 G4Timer fTimer;
0070 G4double elapsed_time=0.;
0071 G4int nb_global_evt_processed=0;
0072 }
0073
0074 RMC01AnalysisManager *RMC01AnalysisManager::GetInstance()
0075 {
0076 static G4ThreadLocal RMC01AnalysisManager theInstance;
0077 return &theInstance;
0078 }
0079
0080
0081
0082 RMC01AnalysisManager::RMC01AnalysisManager()
0083 :fAccumulated_edep("Accumulated_edep", 0.),
0084 fAccumulated_edep2("Accumulated_edep2", 0.), fMean_edep(0.),
0085 fError_mean_edep(0.), fRelative_error(0.),
0086 fPrecision_to_reach(0.),fStop_run_if_precision_reached(true),
0087 fNb_evt_modulo_for_convergence_test(5000),
0088 fEdep_rmatrix_vs_electron_prim_energy(0),
0089 fElectron_current_rmatrix_vs_electron_prim_energy(0),
0090 fGamma_current_rmatrix_vs_electron_prim_energy(0),
0091 fEdep_rmatrix_vs_gamma_prim_energy(0),
0092 fElectron_current_rmatrix_vs_gamma_prim_energy(0),
0093 fGamma_current_rmatrix_vs_gamma_prim_energy(0),
0094 fEdep_rmatrix_vs_proton_prim_energy(0),
0095 fElectron_current_rmatrix_vs_proton_prim_energy(0),
0096 fProton_current_rmatrix_vs_proton_prim_energy(0),
0097 fGamma_current_rmatrix_vs_proton_prim_energy(0),
0098 fFactoryOn(false),
0099 fPrimSpectrumType(EXPO),
0100 fAlpha_or_E0(.5*MeV),fAmplitude_prim_spectrum (1.),
0101 fEmin_prim_spectrum(1.*keV),fEmax_prim_spectrum (20.*MeV),
0102 fAdjoint_sim_mode(true),fNb_evt_per_adj_evt(2)
0103 {
0104
0105 fMsg = new RMC01AnalysisManagerMessenger(this);
0106
0107
0108
0109
0110
0111
0112
0113
0114 fPrimPDG_ID = G4Electron::Electron()->GetPDGEncoding();
0115
0116 fFileName[0] = "sim";
0117
0118 G4AccumulableManager *accumulableManager = G4AccumulableManager::Instance();
0119 accumulableManager->Register(fAccumulated_edep);
0120 accumulableManager->Register(fAccumulated_edep2);
0121 }
0122
0123
0124
0125 RMC01AnalysisManager::~RMC01AnalysisManager()
0126 {;
0127 }
0128
0129
0130
0131 void RMC01AnalysisManager::BeginOfRun(const G4Run* aRun)
0132 {
0133 fIsEndOfRun =false;
0134 G4AccumulableManager *accumulableManager = G4AccumulableManager::Instance();
0135 accumulableManager->Reset();
0136 fRelative_error=1.;
0137 fMean_edep=0.;
0138 fError_mean_edep=0.;
0139
0140 fAdjoint_sim_mode =G4AdjointSimManager::GetInstance()->GetAdjointSimMode();
0141
0142 if (fAdjoint_sim_mode)
0143 {
0144 fNb_evt_per_adj_evt=aRun->GetNumberOfEventToBeProcessed()/
0145 G4AdjointSimManager::GetInstance()->GetNbEvtOfLastRun();
0146 if (G4Threading::IsMasterThread()
0147 || !G4Threading::IsMultithreadedApplication())
0148 {
0149 fConvergenceFileOutput.open("ConvergenceOfAdjointSimulationResults.txt",
0150 std::ios::out);
0151 fConvergenceFileOutput << "Normalised Edep[MeV]\terror[MeV]"
0152 << "\tcomputing_time[s]\tnb_adjoint_event"
0153 << std::endl;
0154 fConvergenceFileOutput.setf(std::ios::scientific);
0155 fConvergenceFileOutput.precision(6);
0156 }
0157 }
0158 else
0159 {
0160 if (G4Threading::IsMasterThread()
0161 || !G4Threading::IsMultithreadedApplication())
0162 {
0163 fConvergenceFileOutput.open("ConvergenceOfForwardSimulationResults.txt",
0164 std::ios::out);
0165 fConvergenceFileOutput
0166 << "Edep per event [MeV]\terror[MeV]\tcomputing_time[s]\tnb_event"
0167 <<std::endl;
0168 fConvergenceFileOutput.setf(std::ios::scientific);
0169 fConvergenceFileOutput.precision(6);
0170 }
0171 }
0172 Book();
0173 if (G4Threading::IsMasterThread()
0174 || !G4Threading::IsMultithreadedApplication())
0175 {
0176 fGlobalEdep = 0.;
0177 fGlobalEdep2 = 0.;
0178 nb_global_evt_processed=0;
0179 fTimer.Start();
0180 elapsed_time=0.;
0181 }
0182 }
0183
0184
0185 void RMC01AnalysisManager::EndOfRun(const G4Run* aRun)
0186 {
0187 G4int nb_evt=aRun->GetNumberOfEvent();
0188 G4double factor =1./ nb_evt;
0189 G4AccumulableManager *accumulableManager = G4AccumulableManager::Instance();
0190 accumulableManager->Merge();
0191 if (G4Threading::IsMasterThread()
0192 || !G4Threading::IsMultithreadedApplication())
0193 {
0194 fTimer.Stop();
0195 elapsed_time+=fTimer.GetRealElapsed();
0196 }
0197
0198 fIsEndOfRun =true;
0199 ComputeMeanEdepAndError(fMean_edep,fError_mean_edep,nb_evt);
0200
0201 if (!fAdjoint_sim_mode)
0202 {
0203 if (G4Threading::IsMasterThread()
0204 || !G4Threading::IsMultithreadedApplication())
0205 {
0206 G4cout << "Results of forward simulation!" << std::endl;
0207 G4cout << "edep per event [MeV] = " << fMean_edep << std::endl;
0208 G4cout << "precision[MeV] = " << fError_mean_edep << std::endl;
0209 }
0210 }
0211 else
0212 {
0213 if (G4Threading::IsMasterThread())
0214 {
0215 G4cout << "Results of reverse/adjoint simulation!" << std::endl;
0216 G4cout << "normalised edep [MeV] = " << fMean_edep << std::endl;
0217 G4cout << "precision[MeV] = " << fError_mean_edep << std::endl;
0218 }
0219 factor = 1.*G4AdjointSimManager::GetInstance()->GetNbEvtOfLastRun()
0220 * fNb_evt_per_adj_evt/aRun->GetNumberOfEvent();
0221 nb_evt=nb_evt/fNb_evt_per_adj_evt;
0222 }
0223 Save(factor);
0224 if (G4Threading::IsMasterThread()
0225 || !G4Threading::IsMultithreadedApplication())
0226 {
0227 fConvergenceFileOutput << fMean_edep << '\t' << fError_mean_edep
0228 << '\t' << elapsed_time << '\t' << nb_evt
0229 << std::endl;
0230 fConvergenceFileOutput.close();
0231 }
0232 }
0233
0234
0235
0236 void RMC01AnalysisManager::BeginOfEvent(const G4Event* )
0237 {
0238 }
0239
0240
0241
0242 void RMC01AnalysisManager::EndOfEvent(const G4Event* anEvent)
0243 {
0244 if (fAdjoint_sim_mode) EndOfEventForAdjointSimulation(anEvent);
0245 else EndOfEventForForwardSimulation(anEvent);
0246
0247
0248
0249
0250 G4int nb_event = G4RunManager::GetRunManager()
0251 ->GetCurrentRun()->GetNumberOfEvent();
0252 nb_event = anEvent->GetEventID()+1;
0253
0254 if (fAdjoint_sim_mode)
0255 {
0256 G4double n_adj_evt= nb_event/fNb_evt_per_adj_evt;
0257 if (n_adj_evt*fNb_evt_per_adj_evt == nb_event)
0258 {
0259 nb_event =static_cast<G4int>(n_adj_evt);
0260 }
0261 else nb_event=0;
0262 }
0263
0264 if (nb_event>100 && fStop_run_if_precision_reached
0265 && fPrecision_to_reach >fRelative_error)
0266 {
0267 G4cout << fPrecision_to_reach*100. << "% Precision reached!" << std::endl;
0268 G4RunManager::GetRunManager()->AbortRun(true);
0269 }
0270
0271 if (nb_event>0 && nb_event % fNb_evt_modulo_for_convergence_test == 0)
0272 {
0273 G4AutoLock lock(&fMergeMutex);
0274 fTimer.Stop();
0275 elapsed_time+=fTimer.GetRealElapsed();
0276 fTimer.Start();
0277 fConvergenceFileOutput << fMean_edep << '\t' << fError_mean_edep
0278 << '\t' << elapsed_time << '\t' << nb_event
0279 << std::endl;
0280 }
0281 }
0282
0283
0284
0285 void RMC01AnalysisManager::EndOfEventForForwardSimulation(
0286 const G4Event* anEvent)
0287 {
0288
0289 G4SDManager* SDman = G4SDManager::GetSDMpointer();
0290 G4HCofThisEvent* HCE = anEvent->GetHCofThisEvent();
0291 RMC01DoubleWithWeightHitsCollection* edepCollection =
0292 (RMC01DoubleWithWeightHitsCollection*)
0293 (HCE->GetHC(0));
0294
0295 RMC01DoubleWithWeightHitsCollection* electronCurrentCollection =
0296 (RMC01DoubleWithWeightHitsCollection*)
0297 (HCE->GetHC(SDman->GetCollectionID("current_electron")));
0298
0299 RMC01DoubleWithWeightHitsCollection* protonCurrentCollection =
0300 (RMC01DoubleWithWeightHitsCollection*)
0301 (HCE->GetHC(SDman->GetCollectionID("current_proton")));
0302
0303 RMC01DoubleWithWeightHitsCollection* gammaCurrentCollection =
0304 (RMC01DoubleWithWeightHitsCollection*)
0305 (HCE->GetHC(SDman->GetCollectionID("current_gamma")));
0306
0307
0308
0309 G4double totEdep=0;
0310 size_t i;
0311 if(edepCollection)
0312 for (i=0;i<edepCollection->entries();i++)
0313 totEdep+=(*edepCollection)[i]->GetValue()
0314 *(*edepCollection)[i]->GetWeight();
0315 {
0316 G4AutoLock lock(&fMergeMutex);
0317 nb_global_evt_processed +=1;
0318 }
0319 if (totEdep>0.)
0320 {
0321 fAccumulated_edep +=totEdep ;
0322 fAccumulated_edep2 +=totEdep*totEdep ;
0323
0324 G4AutoLock lock(&fMergeMutex);
0325 fGlobalEdep += totEdep ;
0326 fGlobalEdep2 += totEdep*totEdep ;
0327 G4PrimaryParticle* thePrimary= anEvent->GetPrimaryVertex()->GetPrimary();
0328 G4double E0= thePrimary->GetG4code()->GetPDGMass();
0329 G4double P=thePrimary->GetMomentum().mag();
0330 G4double prim_ekin =std::sqrt(E0*E0+P*P)-E0;
0331 fEdep_vs_prim_ekin->fill(prim_ekin,totEdep);
0332 }
0333 ComputeMeanEdepAndError(fMean_edep,fError_mean_edep,nb_global_evt_processed);
0334 if (fError_mean_edep>0) fRelative_error= fError_mean_edep/fMean_edep;
0335
0336
0337
0338
0339 if(electronCurrentCollection)
0340 for (i=0;i<electronCurrentCollection->entries();i++)
0341 {
0342 G4double ekin =(*electronCurrentCollection)[i]->GetValue();
0343 G4double weight=(*electronCurrentCollection)[i]->GetWeight();
0344 fElectron_current->fill(ekin,weight);
0345 }
0346
0347 if(protonCurrentCollection)
0348 for (i=0;i<protonCurrentCollection->entries();i++)
0349 {
0350 G4double ekin =(*protonCurrentCollection)[i]->GetValue();
0351 G4double weight=(*protonCurrentCollection)[i]->GetWeight();
0352 fProton_current->fill(ekin,weight);
0353 }
0354
0355 if(gammaCurrentCollection)
0356 for (i=0;i<gammaCurrentCollection->entries();i++)
0357 {
0358 G4double ekin =(*gammaCurrentCollection)[i]->GetValue();
0359 G4double weight=(*gammaCurrentCollection)[i]->GetWeight();
0360 fGamma_current->fill(ekin,weight);
0361 }
0362 }
0363
0364
0365
0366 void RMC01AnalysisManager::EndOfEventForAdjointSimulation(
0367 const G4Event* anEvent)
0368 {
0369
0370
0371 G4SDManager* SDman = G4SDManager::GetSDMpointer();
0372 G4HCofThisEvent* HCE = anEvent->GetHCofThisEvent();
0373 RMC01DoubleWithWeightHitsCollection* edepCollection =
0374 (RMC01DoubleWithWeightHitsCollection*)(
0375 HCE->GetHC(SDman->GetCollectionID("edep")));
0376
0377 RMC01DoubleWithWeightHitsCollection* electronCurrentCollection =
0378 (RMC01DoubleWithWeightHitsCollection*)(
0379 HCE->GetHC(SDman->GetCollectionID("current_electron")));
0380
0381 RMC01DoubleWithWeightHitsCollection* protonCurrentCollection =
0382 (RMC01DoubleWithWeightHitsCollection*)(
0383 HCE->GetHC(SDman->GetCollectionID("current_proton")));
0384
0385 RMC01DoubleWithWeightHitsCollection* gammaCurrentCollection =
0386 (RMC01DoubleWithWeightHitsCollection*)(
0387 HCE->GetHC(SDman->GetCollectionID("current_gamma")));
0388
0389
0390
0391 G4double totEdep=0;
0392 size_t i;
0393 if(edepCollection)
0394 for (i=0;i<edepCollection->entries();i++)
0395 totEdep+=(*edepCollection)[i]->GetValue()
0396 *(*edepCollection)[i]->GetWeight();
0397
0398
0399
0400
0401 G4AdjointSimManager* theAdjointSimManager =
0402 G4AdjointSimManager::GetInstance();
0403
0404 size_t nb_adj_track =
0405 theAdjointSimManager->GetNbOfAdointTracksReachingTheExternalSurface();
0406 G4double total_normalised_weight = 0.;
0407
0408
0409
0410 for (size_t j=0;j<nb_adj_track;j++)
0411 {
0412 G4int pdg_nb =theAdjointSimManager
0413 ->GetFwdParticlePDGEncodingAtEndOfLastAdjointTrack(j);
0414 G4double prim_ekin=theAdjointSimManager
0415 ->GetEkinAtEndOfLastAdjointTrack(j);
0416 G4double adj_weight=theAdjointSimManager
0417 ->GetWeightAtEndOfLastAdjointTrack(j);
0418
0419
0420
0421 G4double normalised_weight = 0.;
0422 if (pdg_nb== fPrimPDG_ID && prim_ekin>= fEmin_prim_spectrum
0423 && prim_ekin<= fEmax_prim_spectrum)
0424 normalised_weight =
0425 adj_weight*PrimDiffAndDirFluxForAdjointSim(prim_ekin);
0426 total_normalised_weight += normalised_weight;
0427
0428
0429
0430 G4AnaH1* edep_rmatrix =0;
0431 G4AnaH2* electron_current_rmatrix =0;
0432 G4AnaH2* gamma_current_rmatrix =0;
0433 G4AnaH2* proton_current_rmatrix =0;
0434
0435 if (pdg_nb == G4Electron::Electron()->GetPDGEncoding())
0436 {
0437 edep_rmatrix = fEdep_rmatrix_vs_electron_prim_energy;
0438 electron_current_rmatrix =
0439 fElectron_current_rmatrix_vs_electron_prim_energy;
0440 gamma_current_rmatrix = fGamma_current_rmatrix_vs_electron_prim_energy;
0441 }
0442 else if (pdg_nb == G4Gamma::Gamma()->GetPDGEncoding())
0443 {
0444
0445 edep_rmatrix = fEdep_rmatrix_vs_gamma_prim_energy;
0446 electron_current_rmatrix = fElectron_current_rmatrix_vs_gamma_prim_energy;
0447 gamma_current_rmatrix = fGamma_current_rmatrix_vs_gamma_prim_energy;
0448 }
0449 else if (pdg_nb == G4Proton::Proton()->GetPDGEncoding()){
0450
0451 edep_rmatrix = fEdep_rmatrix_vs_proton_prim_energy;
0452 electron_current_rmatrix =
0453 fElectron_current_rmatrix_vs_proton_prim_energy;
0454 gamma_current_rmatrix = fGamma_current_rmatrix_vs_proton_prim_energy;
0455 proton_current_rmatrix = fProton_current_rmatrix_vs_proton_prim_energy;
0456 }
0457
0458
0459 if (normalised_weight>0) fEdep_vs_prim_ekin
0460 ->fill(prim_ekin,totEdep*normalised_weight);
0461
0462
0463 edep_rmatrix->fill(prim_ekin,totEdep*adj_weight/cm2);
0464
0465
0466
0467
0468 if(electronCurrentCollection)
0469 for (i=0;i<electronCurrentCollection->entries();i++)
0470 {
0471 G4double ekin =(*electronCurrentCollection)[i]->GetValue();
0472 G4double weight=(*electronCurrentCollection)[i]->GetWeight();
0473 fElectron_current->fill(ekin,weight*normalised_weight);
0474 if(electron_current_rmatrix)
0475 electron_current_rmatrix->fill(prim_ekin,ekin,weight*adj_weight/cm2);
0476 }
0477 if(protonCurrentCollection)
0478 for (i=0;i<protonCurrentCollection->entries();i++)
0479 {
0480 G4double ekin =(*protonCurrentCollection)[i]->GetValue();
0481 G4double weight=(*protonCurrentCollection)[i]->GetWeight();
0482 fProton_current->fill(ekin,weight*normalised_weight);
0483 if(proton_current_rmatrix)
0484 proton_current_rmatrix->fill(prim_ekin,ekin,weight*adj_weight/cm2);
0485 }
0486 if(gammaCurrentCollection)
0487 for (i=0;i<gammaCurrentCollection->entries();i++)
0488 {
0489 G4double ekin =(*gammaCurrentCollection)[i]->GetValue();
0490 G4double weight=(*gammaCurrentCollection)[i]->GetWeight();
0491 fGamma_current->fill(ekin,weight*normalised_weight);
0492 if(gamma_current_rmatrix)
0493 gamma_current_rmatrix->fill(prim_ekin,ekin,weight*adj_weight/cm2);
0494 }
0495 }
0496
0497
0498
0499 {
0500 G4AutoLock lock(&fMergeMutex);
0501 nb_global_evt_processed +=1;
0502 }
0503 G4bool new_mean_computed=false;
0504 if (totEdep>0.)
0505 {
0506 if (total_normalised_weight>0.)
0507 {
0508 G4double edep=totEdep* total_normalised_weight;
0509
0510
0511
0512 G4double new_mean , new_error;
0513 fAccumulated_edep +=edep;
0514 fAccumulated_edep2 +=edep*edep;
0515
0516
0517 G4AutoLock lock(&fMergeMutex);
0518 fGlobalEdep += edep;
0519 fGlobalEdep2 += edep*edep;
0520
0521 ComputeMeanEdepAndError(new_mean,new_error,nb_global_evt_processed);
0522 G4double new_relative_error = 1.;
0523 if ( new_error >0)
0524 new_relative_error = new_error/ new_mean;
0525 fMean_edep = new_mean;
0526 fError_mean_edep = new_error;
0527 fRelative_error =new_relative_error;
0528 new_mean_computed=true;
0529 }
0530 if (!new_mean_computed)
0531 {
0532 G4AutoLock lock(&fMergeMutex);
0533 ComputeMeanEdepAndError(fMean_edep,fError_mean_edep,
0534 nb_global_evt_processed);
0535 if (fError_mean_edep>0)
0536 fRelative_error= fError_mean_edep/fMean_edep;
0537 }
0538 }
0539 }
0540
0541
0542
0543 G4double RMC01AnalysisManager::
0544 PrimDiffAndDirFluxForAdjointSim(G4double prim_energy)
0545 {
0546 G4double flux=fAmplitude_prim_spectrum;
0547 if (fPrimSpectrumType ==EXPO)
0548 flux*=std::exp(-prim_energy/fAlpha_or_E0);
0549 else
0550 flux*=std::pow(prim_energy, -fAlpha_or_E0);
0551 return flux;
0552 }
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596 void RMC01AnalysisManager::
0597 ComputeMeanEdepAndError(G4double& mean,G4double& error,
0598 G4int nb_of_global_evt_processed)
0599 {
0600 G4double nb_event=G4double(nb_of_global_evt_processed);
0601 G4double factor=1.;
0602 G4double factor1=1.;
0603
0604 if (fAdjoint_sim_mode)
0605 {
0606 nb_event /= fNb_evt_per_adj_evt;
0607 G4double nb_evt_sim = G4double(G4AdjointSimManager::GetInstance()
0608 ->GetNbEvtOfLastRun());
0609 factor = nb_evt_sim;
0610 factor1 = factor*nb_evt_sim;
0611 }
0612
0613
0614
0615
0616
0617
0618
0619 if (nb_event>1.)
0620 {
0621 mean = fGlobalEdep*factor/nb_event;
0622 G4double mean_x2 = fGlobalEdep2*factor1/nb_event;
0623 if (fIsEndOfRun)
0624 {
0625 mean = fAccumulated_edep.GetValue()*factor/nb_event;
0626 mean_x2 = fAccumulated_edep2.GetValue()*factor1/nb_event;
0627 }
0628 G4double n_eff= nb_event;
0629 G4double var_weighted = (mean_x2 - mean*mean)*n_eff/(n_eff-1.);
0630 error = std::sqrt(std::max(var_weighted, 0.)/n_eff);
0631 }
0632 else
0633 {
0634 mean=0;
0635 error=0;
0636 }
0637 }
0638
0639
0640
0641 void RMC01AnalysisManager::SetPrimaryExpSpectrumForAdjointSim(
0642 const G4String& particle_name, G4double omni_fluence,
0643 G4double E0, G4double Emin, G4double Emax)
0644 {
0645 fPrimSpectrumType = EXPO;
0646 if (particle_name == "e-" )
0647 fPrimPDG_ID = G4Electron::Electron()->GetPDGEncoding();
0648 else if (particle_name == "gamma")
0649 fPrimPDG_ID = G4Gamma::Gamma()->GetPDGEncoding();
0650 else if (particle_name == "proton")
0651 fPrimPDG_ID = G4Proton::Proton()->GetPDGEncoding();
0652 else
0653 {
0654 G4cout << "The particle that you did select is not in the candidate "
0655 << "list for primary [e-, gamma, proton]!" << G4endl;
0656 return;
0657 }
0658 fAlpha_or_E0 = E0 ;
0659 fAmplitude_prim_spectrum = omni_fluence/E0
0660 / (std::exp(-Emin/E0)-std::exp(-Emax/E0))/4./pi;
0661 fEmin_prim_spectrum = Emin ;
0662 fEmax_prim_spectrum = Emax;
0663 }
0664
0665
0666
0667 void RMC01AnalysisManager::SetPrimaryPowerLawSpectrumForAdjointSim(
0668 const G4String& particle_name, G4double omni_fluence,
0669 G4double alpha, G4double Emin,G4double Emax)
0670 {
0671 fPrimSpectrumType=POWER;
0672 if (particle_name == "e-" )
0673 fPrimPDG_ID = G4Electron::Electron()->GetPDGEncoding();
0674 else if (particle_name == "gamma")
0675 fPrimPDG_ID = G4Gamma::Gamma()->GetPDGEncoding();
0676 else if (particle_name == "proton")
0677 fPrimPDG_ID = G4Proton::Proton()->GetPDGEncoding();
0678 else
0679 {
0680 G4cout << "The particle that you did select is not in the candidate"
0681 << " list for primary [e-, gamma, proton]!"<<G4endl;
0682 return;
0683 }
0684
0685 if (alpha ==1.)
0686 {
0687 fAmplitude_prim_spectrum = omni_fluence/std::log(Emax/Emin)/4./pi;
0688 }
0689 else
0690 {
0691 G4double p=1.-alpha;
0692 fAmplitude_prim_spectrum = omni_fluence/p
0693 / (std::pow(Emax,p)-std::pow(Emin,p))/4./pi;
0694 }
0695
0696 fAlpha_or_E0 = alpha;
0697 fEmin_prim_spectrum = Emin;
0698 fEmax_prim_spectrum = Emax;
0699 }
0700
0701
0702
0703 void RMC01AnalysisManager::Book()
0704 {
0705
0706
0707
0708
0709
0710
0711 G4double emin=1.*keV;
0712 G4double emax=1.*GeV;
0713
0714
0715 fFileName[0]="forward_sim";
0716 if (fAdjoint_sim_mode) fFileName[0]="adjoint_sim";
0717
0718
0719 G4AnalysisManager* theHistoManager = G4AnalysisManager::Instance();
0720 theHistoManager->SetDefaultFileType("root");
0721 G4String extension = theHistoManager->GetFileType();
0722 fFileName[1] = fFileName[0] + "." + extension;
0723 theHistoManager->SetFirstHistoId(1);
0724
0725 G4bool fileOpen = theHistoManager->OpenFile(fFileName[0]);
0726 if (!fileOpen)
0727 {
0728 G4cout << "\n---> RMC01AnalysisManager::Book(): cannot open "
0729 << fFileName[1]
0730 << G4endl;
0731 return;
0732 }
0733
0734
0735
0736
0737
0738
0739
0740
0741
0742 G4int idHisto =
0743 theHistoManager->CreateH1(G4String("Edep_vs_prim_ekin"),
0744 G4String("edep vs e- primary energy"),60,emin,emax,
0745 "none","none",G4String("log"));
0746 fEdep_vs_prim_ekin = theHistoManager->GetH1(idHisto);
0747
0748 idHisto = theHistoManager->CreateH1(G4String("elecron_current"),
0749 G4String("electron"),60,emin,emax,
0750 "none","none",G4String("log"));
0751
0752 fElectron_current = theHistoManager->GetH1(idHisto);
0753
0754 idHisto= theHistoManager->CreateH1(G4String("proton_current"),
0755 G4String("proton"),60,emin,emax,
0756 "none","none",G4String("log"));
0757 fProton_current=theHistoManager->GetH1(idHisto);
0758
0759 idHisto= theHistoManager->CreateH1(G4String("gamma_current"),
0760 G4String("gamma"),60,emin,emax,
0761 "none","none",G4String("log"));
0762 fGamma_current=theHistoManager->GetH1(idHisto);
0763
0764
0765
0766 if (fAdjoint_sim_mode)
0767 {
0768
0769
0770
0771 idHisto =
0772 theHistoManager->CreateH1(G4String("Edep_rmatrix_vs_electron_prim_energy"),
0773 G4String("electron RM vs e- primary energy"),60,emin,emax,
0774 "none","none",G4String("log"));
0775 fEdep_rmatrix_vs_electron_prim_energy = theHistoManager->GetH1(idHisto);
0776
0777 idHisto =
0778 theHistoManager->
0779 CreateH2(G4String("Electron_current_rmatrix_vs_electron_prim_energy"),
0780 G4String("electron current RM vs e- primary energy"),
0781 60,emin,emax,60,emin,emax,
0782 "none","none","none","none",G4String("log"),G4String("log"));
0783
0784 fElectron_current_rmatrix_vs_electron_prim_energy =
0785 theHistoManager->GetH2(idHisto);
0786
0787 idHisto =
0788 theHistoManager->
0789 CreateH2(G4String("Gamma_current_rmatrix_vs_electron_prim_energy"),
0790 G4String("gamma current RM vs e- primary energy"),
0791 60,emin,emax,60,emin,emax,
0792 "none","none","none","none",G4String("log"),G4String("log"));
0793
0794 fGamma_current_rmatrix_vs_electron_prim_energy =
0795 theHistoManager->GetH2(idHisto);
0796
0797
0798
0799 idHisto =
0800 theHistoManager->CreateH1(G4String("Edep_rmatrix_vs_gamma_prim_energy"),
0801 G4String("electron RM vs gamma primary energy"),60,emin,emax,
0802 "none","none",G4String("log"));
0803 fEdep_rmatrix_vs_gamma_prim_energy = theHistoManager->GetH1(idHisto);
0804
0805 idHisto =
0806 theHistoManager->
0807 CreateH2(G4String("Electron_current_rmatrix_vs_gamma_prim_energy"),
0808 G4String("electron current RM vs gamma primary energy"),
0809 60,emin,emax,60,emin,emax,
0810 "none","none","none","none",G4String("log"),G4String("log"));
0811
0812 fElectron_current_rmatrix_vs_gamma_prim_energy =
0813 theHistoManager->GetH2(idHisto);
0814
0815 idHisto =
0816 theHistoManager->
0817 CreateH2(G4String("Gamma_current_rmatrix_vs_gamma_prim_energy"),
0818 G4String("gamma current RM vs gamma primary energy"),
0819 60,emin,emax,60,emin,emax,
0820 "none","none","none","none",G4String("log"),G4String("log"));
0821
0822 fGamma_current_rmatrix_vs_gamma_prim_energy= theHistoManager->GetH2(idHisto);
0823
0824
0825
0826 idHisto =
0827 theHistoManager->CreateH1(G4String("Edep_rmatrix_vs_proton_prim_energy"),
0828 G4String("electron RM vs proton primary energy"),60,emin,emax,
0829 "none","none",G4String("log"));
0830 fEdep_rmatrix_vs_proton_prim_energy = theHistoManager->GetH1(idHisto);
0831
0832 idHisto =
0833 theHistoManager->
0834 CreateH2(G4String("Electron_current_rmatrix_vs_proton_prim_energy"),
0835 G4String("electron current RM vs proton primary energy"),
0836 60,emin,emax,60,emin,emax,
0837 "none","none","none","none",G4String("log"),G4String("log"));
0838
0839 fElectron_current_rmatrix_vs_proton_prim_energy =
0840 theHistoManager->GetH2(idHisto);
0841
0842 idHisto =
0843 theHistoManager->
0844 CreateH2(G4String("Gamma_current_rmatrix_vs_proton_prim_energy"),
0845 G4String("gamma current RM vs proton primary energy"),
0846 60,emin,emax,60,emin,emax,
0847 "none","none","none","none",G4String("log"),G4String("log"));
0848
0849 fGamma_current_rmatrix_vs_proton_prim_energy =
0850 theHistoManager->GetH2(idHisto);
0851
0852 idHisto =
0853 theHistoManager->
0854 CreateH2(G4String("Proton_current_rmatrix_vs_proton_prim_energy"),
0855 G4String("proton current RM vs proton primary energy"),
0856 60,emin,emax,60,emin,emax,
0857 "none","none","none","none",G4String("log"),G4String("log"));
0858
0859 fProton_current_rmatrix_vs_proton_prim_energy =
0860 theHistoManager->GetH2(idHisto);
0861 }
0862 fFactoryOn = true;
0863 G4cout << "\n----> Histogram Tree is opened in " << fFileName[1] << G4endl;
0864 }
0865
0866
0867
0868 void RMC01AnalysisManager::Save(G4double scaling_factor)
0869 {
0870 if (fFactoryOn)
0871 {
0872 G4AnalysisManager* theHistoManager = G4AnalysisManager::Instance();
0873
0874
0875
0876 for (int ind=1; ind<=theHistoManager->GetNofH1s();ind++)
0877 {
0878 theHistoManager->SetH1Ascii(ind,true);
0879 theHistoManager->ScaleH1(ind,scaling_factor);
0880 }
0881 for (int ind=1; ind<=theHistoManager->GetNofH2s();ind++)
0882 theHistoManager->ScaleH2(ind,scaling_factor);
0883
0884 theHistoManager->Write();
0885 theHistoManager->CloseFile();
0886 G4cout << "\n----> Histogram Tree is saved in " << fFileName[1] << G4endl;
0887
0888 fFactoryOn = false;
0889 }
0890 }
0891
0892
0893
0894 void RMC01AnalysisManager::
0895 SetUserDefinedSpectrumPointForAdjointSim(const G4String& particle_name,
0896 G4double omni_fluence,
0897 G4bool is_arbitrary_point_wise)
0898 {
0899 fPrimSpectrumType = USER;
0900 if (particle_name == "e-" )
0901 fPrimPDG_ID = G4Electron::Electron()->GetPDGEncoding();
0902 else if (particle_name == "gamma")
0903 fPrimPDG_ID = G4Gamma::Gamma()->GetPDGEncoding();
0904 else if (particle_name == "proton")
0905 fPrimPDG_ID = G4Proton::Proton()->GetPDGEncoding();
0906 else
0907 {
0908 G4cout << "The particle that you did select is not in the candidate "
0909 << "list for primary [e-, gamma, proton]!" << G4endl;
0910 return;
0911 }
0912 G4cout << "Define user spectrum" << G4endl;
0913 G4cout << dynamic_cast<const RMC01PrimaryGeneratorAction*>
0914 (G4RunManager::GetRunManager()->GetUserPrimaryGeneratorAction())
0915 << G4endl;
0916
0917 G4cout << G4MTRunManager::GetMasterRunManager()
0918 ->GetUserPrimaryGeneratorAction() << G4endl;
0919 G4SPSEneDistribution* theSPSEneDistribution =
0920 dynamic_cast<const RMC01PrimaryGeneratorAction*>
0921 (G4RunManager::GetRunManager()->GetUserPrimaryGeneratorAction())
0922 ->GetParticleGun()->GetCurrentSource()->GetEneDist();
0923 G4PhysicsOrderedFreeVector* aVec = nullptr;
0924
0925 f_energy_vec.clear();
0926 f_flux_vec.clear();
0927
0928 if (!is_arbitrary_point_wise)
0929 {
0930 aVec = new G4PhysicsOrderedFreeVector(theSPSEneDistribution
0931 ->GetUserDefinedEnergyHisto());
0932 fEmin_prim_spectrum = aVec->GetMinEnergy();
0933 fEmax_prim_spectrum = aVec->GetMaxEnergy();
0934 for (size_t i=0;i<aVec->GetVectorLength();i++)
0935 {
0936 f_energy_vec.push_back(aVec->GetLowEdgeEnergy(i));
0937 f_flux_vec.push_back((*aVec)[i]);
0938 }
0939 f_flux_vec[0]=0.;
0940 }
0941 else
0942 {
0943 G4PhysicsOrderedFreeVector aVec1= theSPSEneDistribution->GetArbEnergyHisto();
0944
0945
0946
0947
0948 size_t n = aVec1.GetVectorLength();
0949 G4double* evec=new G4double[n-1];
0950 G4double* fvec=new G4double[n-1];
0951 for (size_t i=0;i<n-1;i++)
0952 {
0953 evec[i]=aVec1.GetLowEdgeEnergy(i);
0954 fvec[i]=aVec1[i];
0955 }
0956
0957 f_flux_vec.push_back(0);
0958 G4double flux1=aVec1[0];
0959 G4double E1 =aVec1.GetLowEdgeEnergy(0);
0960 f_energy_vec.push_back(E1);
0961 fEmin_prim_spectrum = E1;
0962
0963 for (size_t i=1;i<n-1;i++)
0964 {
0965 G4double flux2=aVec1[i];
0966 G4double E2 = aVec1.GetLowEdgeEnergy(i);
0967 size_t lastidx=0;
0968
0969 if ((E2/E1)>1.05)
0970 {
0971 G4double E =E1*1.05;
0972 G4double flux=0.;
0973 G4double logE1,logE2,logf1,logf2,d;
0974 logE1=std::log(E1);
0975 logE2=std::log(E2);
0976 logf1=std::log(flux1);
0977 logf2=std::log(flux2);
0978 d=(logf2-logf1)/(logE2-logE1);
0979
0980 while(E<E2)
0981 {
0982 flux=aVec1.Value(E,lastidx);
0983 f_energy_vec.push_back(E);
0984 flux=std::exp(logf1+d*(std::log(E)-logE1));
0985 f_flux_vec.push_back((E-E1)*(flux1+flux)/2.);
0986 E1=E;
0987 flux1=flux;
0988 E=E1*1.05;
0989 }
0990 }
0991
0992 f_energy_vec.push_back(E2);
0993 f_flux_vec.push_back((E2-E1)*(flux1+flux2)/2.);
0994 flux1=flux2;
0995 E1=E2;
0996 fEmax_prim_spectrum = E2;
0997 }
0998 }
0999
1000 G4double integral_flux =0.;
1001 for (size_t i=0;i<f_flux_vec.size();i++)
1002 integral_flux += f_flux_vec[i];
1003 for (size_t i=1;i<f_flux_vec.size();i++)
1004 {
1005 G4double dE=f_energy_vec[i]-f_energy_vec[i-1];
1006 f_flux_vec[i] = omni_fluence*f_flux_vec[i]/integral_flux/4/pi/dE;
1007 }
1008 }