Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer << 3 // * DISCLAIMER * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th << 5 // * The following disclaimer summarizes all the specific disclaimers * 6 // * the Geant4 Collaboration. It is provided << 6 // * of contributors to this software. The specific disclaimers,which * 7 // * conditions of the Geant4 Software License << 7 // * govern, are listed with their locations in: * 8 // * LICENSE and available at http://cern.ch/ << 8 // * http://cern.ch/geant4/license * 9 // * include a list of copyright holders. << 10 // * 9 // * * 11 // * Neither the authors of this software syst 10 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 11 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 12 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 13 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file << 14 // * use. * 16 // * for the full disclaimer and the limitatio << 17 // * 15 // * * 18 // * This code implementation is the result << 16 // * This code implementation is the intellectual property of the * 19 // * technical work of the GEANT4 collaboratio << 17 // * GEANT4 collaboration. * 20 // * By using, copying, modifying or distri << 18 // * By copying, distributing or modifying the Program (or any work * 21 // * any work based on the software) you ag << 19 // * based on the Program) you indicate your acceptance of this * 22 // * use in resulting scientific publicati << 20 // * statement, and all its terms. * 23 // * acceptance of all terms of the Geant4 Sof << 24 // ******************************************* 21 // ******************************************************************** 25 // 22 // >> 23 // $Id: G4LossTableManager.cc,v 1.44 2004/05/12 12:25:26 vnivanch Exp $ >> 24 // GEANT4 tag $Name: geant4-06-02 $ >> 25 // 26 // ------------------------------------------- 26 // ------------------------------------------------------------------- 27 // 27 // 28 // GEANT4 Class file 28 // GEANT4 Class file 29 // 29 // 30 // 30 // 31 // File name: G4LossTableManager 31 // File name: G4LossTableManager 32 // 32 // 33 // Author: Vladimir Ivanchenko 33 // Author: Vladimir Ivanchenko 34 // 34 // 35 // Creation date: 03.01.2002 35 // Creation date: 03.01.2002 36 // 36 // 37 // Modifications: by V.Ivanchenko << 37 // Modifications: 38 // 38 // >> 39 // 20-01-03 Migrade to cut per region (V.Ivanchenko) >> 40 // 15-02-03 Lambda table can be scaled (V.Ivanchenko) >> 41 // 17-02-03 Fix problem of store/restore tables (V.Ivanchenko) >> 42 // 10-03-03 Add Ion registration (V.Ivanchenko) >> 43 // 25-03-03 Add deregistration (V.Ivanchenko) >> 44 // 02-04-03 Change messenger (V.Ivanchenko) >> 45 // 26-04-03 Fix retrieve tables (V.Ivanchenko) >> 46 // 13-05-03 Add calculation of precise range (V.Ivanchenko) >> 47 // 23-07-03 Add exchange with G4EnergyLossTables (V.Ivanchenko) >> 48 // 05-10-03 Add G4VEmProcesses registration and Verbose command (V.Ivanchenko) >> 49 // 17-10-03 Add SetParameters method (V.Ivanchenko) >> 50 // 23-10-03 Add control on inactive processes (V.Ivanchenko) >> 51 // 04-11-03 Add checks in RetrievePhysicsTable (V.Ivanchenko) >> 52 // 12-11-03 G4EnergyLossSTD -> G4EnergyLossProcess (V.Ivanchenko) >> 53 // 14-01-04 Activate precise range calculation (V.Ivanchenko) >> 54 // 10-03-04 Fix a problem of Precise Range table (V.Ivanchenko) 39 // 55 // 40 // Class Description: 56 // Class Description: 41 // 57 // 42 // ------------------------------------------- 58 // ------------------------------------------------------------------- 43 // 59 // 44 //....oooOO0OOooo........oooOO0OOooo........oo 60 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 45 //....oooOO0OOooo........oooOO0OOooo........oo 61 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 46 62 47 #include "G4LossTableManager.hh" 63 #include "G4LossTableManager.hh" 48 #include "G4SystemOfUnits.hh" << 64 #include "G4EnergyLossMessenger.hh" 49 << 50 #include "G4VMultipleScattering.hh" << 51 #include "G4VEmProcess.hh" << 52 << 53 #include "G4EmParameters.hh" << 54 #include "G4EmSaturation.hh" << 55 #include "G4EmConfigurator.hh" << 56 #include "G4ElectronIonPair.hh" << 57 #include "G4NIELCalculator.hh" << 58 #include "G4EmCorrections.hh" << 59 #include "G4LossTableBuilder.hh" << 60 #include "G4VAtomDeexcitation.hh" << 61 #include "G4VSubCutProducer.hh" << 62 << 63 #include "G4PhysicsTable.hh" 65 #include "G4PhysicsTable.hh" 64 #include "G4ParticleDefinition.hh" 66 #include "G4ParticleDefinition.hh" 65 #include "G4MaterialCutsCouple.hh" 67 #include "G4MaterialCutsCouple.hh" 66 #include "G4ProcessManager.hh" 68 #include "G4ProcessManager.hh" 67 #include "G4Electron.hh" 69 #include "G4Electron.hh" 68 #include "G4Proton.hh" 70 #include "G4Proton.hh" >> 71 #include "G4VMultipleScattering.hh" >> 72 #include "G4VEmProcess.hh" 69 #include "G4ProductionCutsTable.hh" 73 #include "G4ProductionCutsTable.hh" 70 #include "G4PhysicsTableHelper.hh" << 71 #include "G4EmTableType.hh" << 72 #include "G4Region.hh" << 73 #include "G4PhysicalConstants.hh" << 74 << 75 #include "G4Gamma.hh" << 76 #include "G4Positron.hh" << 77 #include "G4OpticalPhoton.hh" << 78 #include "G4Neutron.hh" << 79 #include "G4MuonPlus.hh" << 80 #include "G4MuonMinus.hh" << 81 #include "G4GenericIon.hh" << 82 74 83 //....oooOO0OOooo........oooOO0OOooo........oo << 75 G4LossTableManager* G4LossTableManager::theInstance = 0; 84 76 85 static std::once_flag applyOnce; << 77 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 86 G4ThreadLocal G4LossTableManager* G4LossTableM << 87 78 88 G4LossTableManager* G4LossTableManager::Instan 79 G4LossTableManager* G4LossTableManager::Instance() 89 { 80 { 90 if(nullptr == instance) { << 81 if(0 == theInstance) { 91 static G4ThreadLocalSingleton<G4LossTableM << 82 static G4LossTableManager manager; 92 instance = inst.Instance(); << 83 theInstance = &manager; 93 } 84 } 94 return instance; << 85 return theInstance; 95 } 86 } 96 87 97 //....oooOO0OOooo........oooOO0OOooo........oo 88 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 98 89 99 G4LossTableManager::~G4LossTableManager() 90 G4LossTableManager::~G4LossTableManager() 100 { 91 { 101 for (auto const & p : loss_vector) { delete << 92 for (G4int i=0; i<n_loss; i++) { 102 for (auto const & p : msc_vector) { delete p << 93 if( loss_vector[i] ) delete loss_vector[i]; 103 for (auto const & p : emp_vector) { delete p << 94 } 104 for (auto const & p : p_vector) { delete p; << 95 size_t msc = msc_vector.size(); 105 << 96 for (size_t j=0; j<msc; j++) { 106 std::size_t mod = mod_vector.size(); << 97 if(msc_vector[j] ) delete msc_vector[j]; 107 std::size_t fmod = fmod_vector.size(); << 98 } 108 for (std::size_t a=0; a<mod; ++a) { << 99 size_t emp = emp_vector.size(); 109 if( nullptr != mod_vector[a] ) { << 100 for (size_t k=0; k<emp; k++) { 110 for (std::size_t b=0; b<fmod; ++b) { << 101 if(emp_vector[k] ) delete emp_vector[k]; 111 if((G4VEmModel*)(fmod_vector[b]) == mo << 112 fmod_vector[b] = nullptr; << 113 } << 114 } << 115 delete mod_vector[a]; << 116 mod_vector[a] = nullptr; << 117 } << 118 } 102 } 119 for (auto const & p : fmod_vector) { delete << 120 << 121 Clear(); 103 Clear(); >> 104 delete theMessenger; 122 delete tableBuilder; 105 delete tableBuilder; 123 delete emCorrections; << 124 delete emConfigurator; << 125 delete emElectronIonPair; << 126 delete nielCalculator; << 127 delete atomDeexcitation; << 128 delete subcutProducer; << 129 } 106 } 130 107 131 //....oooOO0OOooo........oooOO0OOooo........oo 108 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 132 109 133 G4LossTableManager::G4LossTableManager() 110 G4LossTableManager::G4LossTableManager() 134 { 111 { 135 theParameters = G4EmParameters::Instance(); << 112 n_loss = 0; 136 theElectron = G4Electron::Electron(); << 113 first_entry = true; 137 << 114 all_tables_are_built = false; 138 // only one thread is the master << 115 all_tables_are_stored = false; 139 std::call_once(applyOnce, [this]() { isMaste << 116 electron_table_are_built = false; 140 verbose = isMaster ? theParameters->Verbose( << 117 currentLoss = 0; 141 << 118 currentParticle = 0; 142 tableBuilder = new G4LossTableBuilder(isMast << 119 lossFluctuationFlag = true; 143 emCorrections = new G4EmCorrections(verbose) << 120 subCutoffFlag = false; 144 << 121 rndmStepFlag = false; 145 std::size_t n = 70; << 122 minSubRange = 0.0; 146 loss_vector.reserve(n); << 123 maxRangeVariation = 1.0; 147 part_vector.reserve(n); << 124 maxFinalStep = 0.0; 148 base_part_vector.reserve(n); << 125 eIonisation = 0; 149 dedx_vector.reserve(n); << 126 minKinEnergy = 0.1*keV; 150 range_vector.reserve(n); << 127 maxKinEnergy = 100.0*TeV; 151 inv_range_vector.reserve(n); << 128 maxKinEnergyForMuons = 100.*TeV; 152 tables_are_built.reserve(n); << 129 theMessenger = new G4EnergyLossMessenger(); 153 isActive.reserve(n); << 130 theElectron = G4Electron::Electron(); 154 msc_vector.reserve(10); << 131 tableBuilder = new G4LossTableBuilder(); 155 emp_vector.reserve(16); << 132 integral = true; 156 mod_vector.reserve(150); << 133 integralActive = false; 157 fmod_vector.reserve(60); << 134 buildPreciseRange = false; >> 135 minEnergyActive = false; >> 136 maxEnergyActive = false; >> 137 maxEnergyForMuonsActive = false; >> 138 stepFunctionActive = false; >> 139 verbose = 0; 158 } 140 } 159 141 160 //....oooOO0OOooo........oooOO0OOooo........oo 142 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 161 143 162 void G4LossTableManager::Clear() 144 void G4LossTableManager::Clear() 163 { 145 { 164 all_tables_are_built = false; 146 all_tables_are_built = false; 165 currentLoss = nullptr; << 147 electron_table_are_built = false; 166 currentParticle = nullptr; << 148 eIonisation = 0; 167 if(n_loss) { << 149 currentLoss = 0; 168 dedx_vector.clear(); << 150 currentParticle = 0; 169 range_vector.clear(); << 151 if(n_loss) 170 inv_range_vector.clear(); << 152 { 171 loss_map.clear(); << 153 dedx_vector.clear(); 172 loss_vector.clear(); << 154 range_vector.clear(); 173 part_vector.clear(); << 155 inv_range_vector.clear(); 174 base_part_vector.clear(); << 156 loss_map.clear(); 175 tables_are_built.clear(); << 157 loss_vector.clear(); 176 isActive.clear(); << 158 part_vector.clear(); 177 n_loss = 0; << 159 base_part_vector.clear(); 178 } << 160 tables_are_built.clear(); >> 161 n_loss = 0; >> 162 } 179 } 163 } 180 164 181 //....oooOO0OOooo........oooOO0OOooo........oo 165 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 182 166 183 void G4LossTableManager::Register(G4VEnergyLos 167 void G4LossTableManager::Register(G4VEnergyLossProcess* p) 184 { 168 { 185 if (nullptr == p) { return; } << 169 n_loss++; 186 for (G4int i=0; i<n_loss; ++i) { << 187 if(loss_vector[i] == p) { return; } << 188 } << 189 if(verbose > 1) { << 190 G4cout << "G4LossTableManager::Register G4 << 191 << p->GetProcessName() << " idx= " << 192 } << 193 ++n_loss; << 194 loss_vector.push_back(p); 170 loss_vector.push_back(p); 195 part_vector.push_back(nullptr); << 171 part_vector.push_back(0); 196 base_part_vector.push_back(nullptr); << 172 base_part_vector.push_back(0); 197 dedx_vector.push_back(nullptr); << 173 dedx_vector.push_back(0); 198 range_vector.push_back(nullptr); << 174 range_vector.push_back(0); 199 inv_range_vector.push_back(nullptr); << 175 inv_range_vector.push_back(0); 200 tables_are_built.push_back(false); 176 tables_are_built.push_back(false); 201 isActive.push_back(true); << 202 all_tables_are_built = false; 177 all_tables_are_built = false; 203 } << 178 if(!lossFluctuationFlag) p->SetLossFluctuations(false); 204 << 179 if(subCutoffFlag) p->SetSubCutoff(true); 205 //....oooOO0OOooo........oooOO0OOooo........oo << 180 if(rndmStepFlag) p->SetRandomStep(true); 206 << 181 if(stepFunctionActive) p->SetStepFunction(maxRangeVariation, maxFinalStep); 207 void G4LossTableManager::ResetParameters() << 182 if(integralActive) p->SetIntegral(integral); 208 { << 183 if(minEnergyActive) p->SetMinKinEnergy(minKinEnergy); 209 // initialisation once per run << 184 if(maxEnergyActive) p->SetMaxKinEnergy(maxKinEnergy); 210 if (!resetParam) { return; } << 211 resetParam = false; << 212 startInitialisation = true; << 213 verbose = theParameters->Verbose(); << 214 if(!isMaster) { << 215 verbose = theParameters->WorkerVerbose(); << 216 } else { << 217 if(verbose > 0) { theParameters->Dump(); } << 218 } << 219 << 220 tableBuilder->InitialiseBaseMaterials(); << 221 if (nullptr != nielCalculator) { nielCalcula << 222 << 223 emCorrections->SetVerbose(verbose); << 224 if(nullptr != emConfigurator) { emConfigurat << 225 if(nullptr != emElectronIonPair) { emElectro << 226 if(nullptr != atomDeexcitation) { << 227 atomDeexcitation->SetVerboseLevel(verbose) << 228 atomDeexcitation->InitialiseAtomicDeexcita << 229 } << 230 if (1 < verbose) { << 231 G4cout << "====== G4LossTableManager::Rese << 232 << " Nloss=" << loss_vector.size() << 233 << " run=" << run << " master=" << isMast << 234 << G4endl; << 235 } << 236 } 185 } 237 186 238 //....oooOO0OOooo........oooOO0OOooo........oo 187 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 239 188 240 void G4LossTableManager::DeRegister(G4VEnergyL 189 void G4LossTableManager::DeRegister(G4VEnergyLossProcess* p) 241 { 190 { 242 if (nullptr == p) { return; } << 191 for (G4int i=0; i<n_loss; i++) { 243 for (G4int i=0; i<n_loss; ++i) { << 192 if(loss_vector[i] == p) loss_vector[i] = 0; 244 if(loss_vector[i] == p) { << 245 loss_vector[i] = nullptr; << 246 break; << 247 } << 248 } 193 } 249 } 194 } 250 195 251 //....oooOO0OOooo........oooOO0OOooo........oo 196 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 252 197 253 void G4LossTableManager::Register(G4VMultipleS 198 void G4LossTableManager::Register(G4VMultipleScattering* p) 254 { 199 { 255 if (nullptr == p) { return; } << 256 std::size_t n = msc_vector.size(); << 257 for (std::size_t i=0; i<n; ++i) { << 258 if(msc_vector[i] == p) { return; } << 259 } << 260 if(verbose > 1) { << 261 G4cout << "G4LossTableManager::Register G4 << 262 << p->GetProcessName() << " idx= " << 263 } << 264 msc_vector.push_back(p); 200 msc_vector.push_back(p); 265 } 201 } 266 202 267 //....oooOO0OOooo........oooOO0OOooo........oo 203 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 268 204 269 void G4LossTableManager::DeRegister(G4VMultipl 205 void G4LossTableManager::DeRegister(G4VMultipleScattering* p) 270 { 206 { 271 if (nullptr == p) { return; } << 207 size_t msc = msc_vector.size(); 272 std::size_t msc = msc_vector.size(); << 208 for (size_t i=0; i<msc; i++) { 273 for (std::size_t i=0; i<msc; ++i) { << 209 if(msc_vector[i] == p) msc_vector[i] = 0; 274 if(msc_vector[i] == p) { << 275 msc_vector[i] = nullptr; << 276 break; << 277 } << 278 } 210 } 279 } 211 } 280 212 281 //....oooOO0OOooo........oooOO0OOooo........oo 213 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 282 214 283 void G4LossTableManager::Register(G4VEmProcess 215 void G4LossTableManager::Register(G4VEmProcess* p) 284 { 216 { 285 if (nullptr == p) { return; } << 286 std::size_t n = emp_vector.size(); << 287 for (std::size_t i=0; i<n; ++i) { << 288 if(emp_vector[i] == p) { return; } << 289 } << 290 if(verbose > 1) { << 291 G4cout << "G4LossTableManager::Register G4 << 292 << p->GetProcessName() << " idx= " << 293 } << 294 emp_vector.push_back(p); 217 emp_vector.push_back(p); 295 } 218 } 296 219 297 //....oooOO0OOooo........oooOO0OOooo........oo 220 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 298 221 299 void G4LossTableManager::DeRegister(G4VEmProce 222 void G4LossTableManager::DeRegister(G4VEmProcess* p) 300 { 223 { 301 if (nullptr == p) { return; } << 224 size_t emp = emp_vector.size(); 302 std::size_t emp = emp_vector.size(); << 225 for (size_t i=0; i<emp; i++) { 303 for (std::size_t i=0; i<emp; ++i) { << 226 if(emp_vector[i] == p) emp_vector[i] = 0; 304 if(emp_vector[i] == p) { << 305 emp_vector[i] = nullptr; << 306 break; << 307 } << 308 } 227 } 309 } 228 } 310 229 311 //....oooOO0OOooo........oooOO0OOooo........oo 230 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 312 231 313 void G4LossTableManager::Register(G4VProcess* << 232 void G4LossTableManager::RegisterIon(const G4ParticleDefinition* ion, G4VEnergyLossProcess* p) 314 { 233 { 315 if (nullptr == p) { return; } << 234 loss_map[ion] = p; 316 std::size_t n = p_vector.size(); << 317 for (std::size_t i=0; i<n; ++i) { << 318 if(p_vector[i] == p) { return; } << 319 } << 320 if(verbose > 1) { << 321 G4cout << "G4LossTableManager::Register G4 << 322 << p->GetProcessName() << " idx= " << 323 } << 324 p_vector.push_back(p); << 325 } 235 } 326 236 327 //....oooOO0OOooo........oooOO0OOooo........oo 237 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 328 238 329 void G4LossTableManager::DeRegister(G4VProcess << 239 G4EnergyLossMessenger* G4LossTableManager::GetMessenger() 330 { 240 { 331 if (nullptr == p) { return; } << 241 return theMessenger; 332 std::size_t emp = p_vector.size(); << 333 for (std::size_t i=0; i<emp; ++i) { << 334 if(p_vector[i] == p) { << 335 p_vector[i] = nullptr; << 336 break; << 337 } << 338 } << 339 } 242 } 340 243 341 //....oooOO0OOooo........oooOO0OOooo........oo 244 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 342 245 343 void G4LossTableManager::Register(G4VEmModel* << 246 void G4LossTableManager::ParticleHaveNoLoss(const G4ParticleDefinition* aParticle) 344 { 247 { 345 mod_vector.push_back(p); << 248 G4String s = "G4LossTableManager:: dE/dx table not found for " 346 if(verbose > 1) { << 249 + aParticle->GetParticleName() + "!"; 347 G4cout << "G4LossTableManager::Register G4 << 250 G4Exception(s); 348 << p->GetName() << " " << p << " << 251 exit(1); 349 } << 350 } 252 } 351 253 352 //....oooOO0OOooo........oooOO0OOooo........oo 254 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... 353 255 354 void G4LossTableManager::DeRegister(G4VEmModel << 256 G4bool G4LossTableManager::IsRecalcNeeded(const G4ParticleDefinition* aParticle) 355 { 257 { 356 //G4cout << "G4LossTableManager::DeRegister << 258 G4bool isNeeded = !all_tables_are_built; 357 std::size_t n = mod_vector.size(); << 259 if (first_entry || (aParticle == firstParticle && all_tables_are_built) ) { 358 for (std::size_t i=0; i<n; ++i) { << 260 isNeeded = true; 359 if(mod_vector[i] == p) { << 261 all_tables_are_built = false; 360 mod_vector[i] = nullptr; << 262 electron_table_are_built = false; 361 break; << 263 loss_map.clear(); >> 264 for (G4int i=0; i<n_loss; i++) { >> 265 if(loss_vector[i]) { >> 266 const G4ProcessManager* pm = loss_vector[i]->GetProcessManager(); >> 267 if (pm->GetProcessActivation(loss_vector[i])) tables_are_built[i] = false; >> 268 else tables_are_built[i] = true; >> 269 } else { >> 270 tables_are_built[i] = true; >> 271 part_vector[i] = 0; >> 272 } 362 } 273 } >> 274 Initialise(); 363 } 275 } 364 } << 365 << 366 //....oooOO0OOooo........oooOO0OOooo........oo << 367 276 368 void G4LossTableManager::Register(G4VEmFluctua << 277 if (first_entry) { 369 { << 278 first_entry = false; 370 fmod_vector.push_back(p); << 279 firstParticle = aParticle; 371 if(verbose > 1) { << 372 G4cout << "G4LossTableManager::Register G4 << 373 << p->GetName() << " " << fmod_vec << 374 } 280 } 375 } << 376 << 377 //....oooOO0OOooo........oooOO0OOooo........oo << 378 281 379 void G4LossTableManager::DeRegister(G4VEmFluct << 282 return isNeeded; 380 { << 381 std::size_t n = fmod_vector.size(); << 382 for (std::size_t i=0; i<n; ++i) { << 383 if(fmod_vector[i] == p) { fmod_vector[i] = << 384 } << 385 } << 386 << 387 //....oooOO0OOooo........oooOO0OOooo........oo << 388 << 389 void G4LossTableManager::RegisterExtraParticle << 390 const G4ParticleDefinition* part, << 391 G4VEnergyLossProcess* p) << 392 { << 393 if (nullptr == p || nullptr == part) { retur << 394 for (G4int i=0; i<n_loss; ++i) { << 395 if(loss_vector[i] == p) { return; } << 396 } << 397 if(verbose > 1) { << 398 G4cout << "G4LossTableManager::RegisterExt << 399 << part->GetParticleName() << " G4 << 400 << p->GetProcessName() << " idx= " << 401 } << 402 ++n_loss; << 403 loss_vector.push_back(p); << 404 part_vector.push_back(part); << 405 base_part_vector.push_back(p->BaseParticle() << 406 dedx_vector.push_back(nullptr); << 407 range_vector.push_back(nullptr); << 408 inv_range_vector.push_back(nullptr); << 409 tables_are_built.push_back(false); << 410 all_tables_are_built = false; << 411 } 283 } 412 284 413 //....oooOO0OOooo........oooOO0OOooo........oo 285 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 414 286 415 G4VEnergyLossProcess* << 287 void G4LossTableManager::Initialise() 416 G4LossTableManager::GetEnergyLossProcess(const << 417 { 288 { 418 if(aParticle != currentParticle) { << 419 currentParticle = aParticle; << 420 std::map<PD,G4VEnergyLossProcess*,std::les << 421 if ((pos = loss_map.find(aParticle)) != lo << 422 currentLoss = (*pos).second; << 423 } else { << 424 currentLoss = nullptr; << 425 if(0.0 != aParticle->GetPDGCharge() && << 426 (pos = loss_map.find(theGenericIon)) != los << 427 currentLoss = (*pos).second; << 428 } << 429 } << 430 } << 431 return currentLoss; << 432 } << 433 289 434 //....oooOO0OOooo........oooOO0OOooo........oo << 290 for(G4int j=0; j<n_loss; j++) { 435 291 436 void << 292 if (loss_vector[j]) { 437 G4LossTableManager::PreparePhysicsTable(const << 293 const G4ParticleDefinition* pd = loss_vector[j]->Particle(); 438 G4VEne << 294 if (!pd) { 439 { << 295 pd = loss_vector[j]->GetProcessManager()->GetParticleType(); 440 if (1 < verbose) { << 296 loss_vector[j]->SetParticle(pd); 441 G4cout << "G4LossTableManager::PreparePhys << 297 } 442 << particle->GetParticleName() << 298 if(maxEnergyForMuonsActive) { 443 << " and " << p->GetProcessName() < << 299 G4double dm = abs(pd->GetPDGMass() - 105.7*MeV); 444 << " loss_vector " << loss_vector << 300 if(dm < 5.*MeV) loss_vector[j]->SetMaxKinEnergy(maxKinEnergyForMuons); 445 << " run=" << run << " master=" << isMast << 301 } 446 << G4endl; << 302 if(!tables_are_built[j]) all_tables_are_built = false; 447 } << 303 if(pd != part_vector[j]) { 448 << 304 part_vector[j] = pd; 449 // start initialisation for the first run << 305 base_part_vector[j] = loss_vector[j]->BaseParticle(); 450 if( -1 == run ) { << 306 } 451 if (nullptr != emConfigurator) { emConfigu << 307 if(0 < verbose) { 452 << 308 G4String nm = "unknown"; 453 // initialise particles for given process << 309 if(pd) nm = pd->GetParticleName(); 454 for (G4int j=0; j<n_loss; ++j) { << 310 G4cout << "For " << loss_vector[j]->GetProcessName() 455 if (p == loss_vector[j] && nullptr == pa << 311 << " for " << nm 456 part_vector[j] = particle; << 312 << " tables_are_built= " << tables_are_built[j] 457 if (particle->GetParticleName() == "Ge << 313 << " procFlag= " << loss_vector[j]->TablesAreBuilt() 458 theGenericIon = particle; << 314 << " all_tables_are_built= " << all_tables_are_built 459 } << 315 << G4endl; 460 } 316 } 461 } 317 } 462 } 318 } 463 ResetParameters(); << 464 } << 465 << 466 //....oooOO0OOooo........oooOO0OOooo........oo << 467 << 468 void << 469 G4LossTableManager::PreparePhysicsTable(const << 470 G4VEmP << 471 { << 472 if (1 < verbose) { << 473 G4cout << "G4LossTableManager::PreparePhys << 474 << particle->GetParticleName() << 475 << " and " << p->GetProcessName() << 476 << " run=" << run << " master=" << isMast << 477 << G4endl; << 478 } << 479 319 480 // start initialisation for the first run << 320 if(0 < verbose) { 481 if( -1 == run ) { << 321 G4cout << "G4LossTableManager::Initialise:" 482 if (nullptr != emConfigurator) { emConfigu << 322 << " electron_table_are_built= " << electron_table_are_built 483 } << 323 << " all_tables_are_built= " << all_tables_are_built 484 << 324 << G4endl; 485 ResetParameters(); << 486 } << 487 << 488 //....oooOO0OOooo........oooOO0OOooo........oo << 489 << 490 void << 491 G4LossTableManager::PreparePhysicsTable(const << 492 G4VMul << 493 { << 494 if (1 < verbose) { << 495 G4cout << "G4LossTableManager::PreparePhys << 496 << particle->GetParticleName() << 497 << " and " << p->GetProcessName() << 498 << " run=" << run << " master=" << isMast << 499 << G4endl; << 500 } 325 } 501 326 502 // start initialisation for the first run << 503 if ( -1 == run ) { << 504 if (nullptr != emConfigurator) { emConfigu << 505 } << 506 << 507 ResetParameters(); << 508 } 327 } 509 328 510 //....oooOO0OOooo........oooOO0OOooo........oo << 329 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 511 330 512 void << 331 void G4LossTableManager::BuildPhysicsTable(const G4ParticleDefinition* aParticle) 513 G4LossTableManager::BuildPhysicsTable(const G4 << 514 { 332 { 515 if(-1 == run && startInitialisation) { << 516 if (nullptr != emConfigurator) { emConfigu << 517 } << 518 if (startInitialisation) { resetParam = true << 519 } << 520 << 521 //....oooOO0OOooo........oooOO0OOooo........oo << 522 333 523 void G4LossTableManager::LocalPhysicsTables( << 334 if(0 < verbose) { 524 const G4ParticleDefinition* aParticle, << 335 G4cout << "### G4LossTableManager::BuildDEDXTable() is requested for " 525 G4VEnergyLossProcess* p) << 526 { << 527 if (1 < verbose) { << 528 G4cout << "### G4LossTableManager::LocalPh << 529 << aParticle->GetParticleName() 336 << aParticle->GetParticleName() 530 << " and process " << p->GetProcess << 531 << G4endl; 337 << G4endl; 532 } 338 } 533 339 534 if(-1 == run && startInitialisation) { << 340 if(aParticle == theElectron) { 535 if (nullptr != emConfigurator) { emConfigu << 341 if(!electron_table_are_built) { 536 firstParticle = aParticle; << 342 eIonisation = BuildTables(theElectron); 537 } << 343 electron_table_are_built = true; 538 << 344 for(G4int i=0; i<n_loss; i++) { 539 if (startInitialisation) { << 345 G4VEnergyLossProcess* em = loss_vector[i]; 540 ++run; << 346 if(aParticle == part_vector[i]) SetParameters(loss_vector[i]); 541 if (1 < verbose) { << 347 if (tables_are_built[i] && em->SecondaryParticle() == theElectron && eIonisation ) { 542 G4cout << "===== G4LossTableManager::Loc << 348 em->SetSecondaryRangeTable(eIonisation->RangeTableForLoss()); 543 << run << " =====" << G4endl; << 349 } 544 } << 545 currentParticle = nullptr; << 546 startInitialisation = false; << 547 resetParam = true; << 548 for (G4int i=0; i<n_loss; ++i) { << 549 if (nullptr != loss_vector[i]) { << 550 tables_are_built[i] = false; << 551 } else { << 552 tables_are_built[i] = true; << 553 part_vector[i] = nullptr; << 554 } 350 } 555 } 351 } 556 } << 557 352 558 all_tables_are_built= true; << 353 } else { 559 for (G4int i=0; i<n_loss; ++i) { << 354 for(G4int i=0; i<n_loss; i++) { 560 if(p == loss_vector[i]) { << 561 tables_are_built[i] = true; << 562 isActive[i] = true; << 563 part_vector[i] = p->Particle(); << 564 base_part_vector[i] = p->BaseParticle(); << 565 dedx_vector[i] = p->DEDXTable(); << 566 range_vector[i] = p->RangeTableForLoss() << 567 inv_range_vector[i] = p->InverseRangeTab << 568 if(0 == run && p->IsIonisationProcess()) << 569 loss_map[part_vector[i]] = p; << 570 } << 571 355 572 if(1 < verbose) { << 356 if(aParticle == part_vector[i] && !tables_are_built[i]) { 573 G4cout << i <<". "<< p->GetProcessNa << 357 SetParameters(loss_vector[i]); 574 if(part_vector[i]) { << 358 // if(tables_are_built[i]) break; 575 G4cout << " for " << part_vector[i << 359 if(!base_part_vector[i]) { >> 360 G4VEnergyLossProcess* hIonisation = BuildTables(aParticle); >> 361 for(G4int j=0; j<n_loss; j++) { >> 362 if (aParticle == base_part_vector[j]) { >> 363 tables_are_built[j] = true; >> 364 G4VEnergyLossProcess* em = loss_vector[j]; >> 365 em->Initialise(); >> 366 em->SetDEDXTable(hIonisation->DEDXTable()); >> 367 em->SetPreciseRangeTable(hIonisation->PreciseRangeTable()); >> 368 em->SetRangeTableForLoss(hIonisation->RangeTableForLoss()); >> 369 em->SetInverseRangeTable(hIonisation->InverseRangeTable()); >> 370 em->SetLambdaTable(hIonisation->LambdaTable()); >> 371 em->SetSubLambdaTable(hIonisation->SubLambdaTable()); >> 372 loss_map[part_vector[j]] = em; >> 373 if (em->SecondaryParticle() == theElectron && eIonisation) { >> 374 em->SetSecondaryRangeTable(eIonisation->RangeTableForLoss()); >> 375 } >> 376 if (0 < verbose) { >> 377 G4cout << "For " << loss_vector[j]->GetProcessName() >> 378 << " for " << part_vector[j]->GetParticleName() >> 379 << " base_part= " << base_part_vector[j]->GetParticleName() >> 380 << " tables are assigned " >> 381 << G4endl; >> 382 } >> 383 } >> 384 } >> 385 } else { >> 386 G4VEnergyLossProcess* em = loss_vector[i]; >> 387 for(G4int j=0; j<n_loss; j++) { >> 388 if (tables_are_built[j] && part_vector[j] == base_part_vector[i]) { >> 389 G4VEnergyLossProcess* hIonisation = loss_vector[j]; >> 390 tables_are_built[i] = true; >> 391 em->Initialise(); >> 392 em->SetDEDXTable(hIonisation->DEDXTable()); >> 393 em->SetPreciseRangeTable(hIonisation->PreciseRangeTable()); >> 394 em->SetRangeTableForLoss(hIonisation->RangeTableForLoss()); >> 395 em->SetInverseRangeTable(hIonisation->InverseRangeTable()); >> 396 em->SetLambdaTable(hIonisation->LambdaTable()); >> 397 em->SetSubLambdaTable(hIonisation->SubLambdaTable()); >> 398 loss_map[part_vector[i]] = em; >> 399 if (em->SecondaryParticle() == theElectron && eIonisation) >> 400 em->SetSecondaryRangeTable(eIonisation->RangeTableForLoss()); >> 401 if (0 < verbose) { >> 402 G4cout << "For " << em->GetProcessName() >> 403 << " for " << part_vector[i]->GetParticleName() >> 404 << " base_part= " << base_part_vector[i]->GetParticleName() >> 405 << " tables are assigned= " << G4endl; >> 406 } >> 407 break; >> 408 } >> 409 } 576 } 410 } 577 G4cout << " active= " << isActive[i] << 411 break; 578 << " table= " << tables_are_bu << 579 << " isIonisation= " << p->IsI << 580 << G4endl; << 581 } 412 } 582 break; << 413 } 583 } else if(!tables_are_built[i]) { << 414 } >> 415 >> 416 if(all_tables_are_built) return; >> 417 all_tables_are_built = true; >> 418 for (G4int ii=0; ii<n_loss; ii++) { >> 419 if ( !tables_are_built[ii] ) { 584 all_tables_are_built = false; 420 all_tables_are_built = false; >> 421 break; 585 } 422 } 586 } 423 } 587 424 588 if(1 < verbose) { << 425 if(0 < verbose) { 589 G4cout << "### G4LossTableManager::LocalPh << 426 G4cout << "### G4LossTableManager::BuildDEDXTable end: " >> 427 << "all_tables_are_built= " << all_tables_are_built 590 << G4endl; 428 << G4endl; 591 } 429 } 592 if(all_tables_are_built) { << 430 if(all_tables_are_built) { 593 if(1 < verbose) { << 431 G4cout << "### All dEdx and Range tables are built #####" << G4endl; 594 G4cout << "%%%%% All dEdx and Range tabl << 595 << run << " %%%%%" << G4endl; << 596 } << 597 } 432 } 598 } 433 } 599 434 600 //....oooOO0OOooo........oooOO0OOooo........oo << 435 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 601 436 602 void G4LossTableManager::BuildPhysicsTable( << 437 void G4LossTableManager::RetrievePhysicsTables(const G4ParticleDefinition* aParticle, 603 const G4ParticleDefinition* aParticle, << 438 G4VEnergyLossProcess* theLoss) 604 G4VEnergyLossProcess* p) << 605 { 439 { 606 if(1 < verbose) { << 440 if(0 < verbose) { 607 G4cout << "### G4LossTableManager::BuildPh << 441 G4cout << "G4LossTableManager::RetrievePhysicsTable() for " 608 << aParticle->GetParticleName() 442 << aParticle->GetParticleName() 609 << " and process " << p->GetProcess << 443 << "; all_tables_are_built= " << all_tables_are_built >> 444 << G4endl; 610 } 445 } 611 // clear configurator << 446 if(all_tables_are_built) return; 612 if(-1 == run && startInitialisation) { << 613 if( nullptr != emConfigurator) { emConfigu << 614 firstParticle = aParticle; << 615 } << 616 if(startInitialisation) { << 617 ++run; << 618 resetParam = true; << 619 startInitialisation = false; << 620 if(1 < verbose) { << 621 G4cout << "===== G4LossTableManager::Bui << 622 << run << " ===== " << atomDeexci << 623 } << 624 currentParticle = nullptr; << 625 all_tables_are_built = false; << 626 << 627 for (G4int i=0; i<n_loss; ++i) { << 628 G4VEnergyLossProcess* el = loss_vector[i << 629 447 630 if(nullptr != el) { << 448 G4bool hasRange = false; 631 isActive[i] = true; << 449 G4bool isLast = false; 632 part_vector[i] = el->Particle(); << 450 G4int i; 633 base_part_vector[i] = el->BaseParticle << 451 for (i=0; i<n_loss; i++) { 634 tables_are_built[i] = false; << 452 if ( theLoss == loss_vector[i] ) { 635 if(1 < verbose) { << 453 if((n_loss-1 == i && part_vector[n_loss-1] != G4Proton::Proton()) || 636 G4cout << i <<". "<< el->GetProces << 454 (n_loss-2 == i && part_vector[n_loss-1] == G4Proton::Proton())) isLast = true; 637 if(el->Particle()) { << 455 tables_are_built[i] = true; 638 G4cout << " for " << el->Particl << 456 if (theLoss->RangeTableForLoss()) { 639 } << 457 if (part_vector[i] == theElectron) { 640 G4cout << " active= " << isActive[i << 458 eIonisation = theLoss; 641 << " table= " << tables_are_ << 459 electron_table_are_built = true; 642 << " isIonisation= " << el-> << 460 } 643 if(base_part_vector[i]) { << 461 loss_map[part_vector[i]] = theLoss; 644 G4cout << " base particle " << 462 hasRange = true; 645 << base_part_vector[i]->Get << 463 if (0 < verbose) { 646 } << 464 G4cout << "dEdx and Range tables are defined for " 647 G4cout << G4endl; << 465 << aParticle->GetParticleName() >> 466 << G4endl; 648 } 467 } 649 } else { << 650 tables_are_built[i] = true; << 651 part_vector[i] = nullptr; << 652 isActive[i] = false; << 653 } 468 } >> 469 if (electron_table_are_built && theLoss->SecondaryParticle() == theElectron) >> 470 theLoss->SetSecondaryRangeTable(eIonisation->RangeTableForLoss()); >> 471 break; 654 } 472 } 655 } 473 } 656 474 657 if (all_tables_are_built) { << 475 if ( hasRange ) { 658 theParameters->SetIsPrintedFlag(true); << 476 for (G4int j=0; j<n_loss; j++) { 659 return; << 477 if ( base_part_vector[j] == aParticle && !tables_are_built[j] ) { 660 } << 478 G4VEnergyLossProcess* em = loss_vector[j]; 661 << 479 tables_are_built[j] = true; 662 // Build tables for given particle << 480 em->Initialise(); 663 all_tables_are_built = true; << 481 em->SetDEDXTable(theLoss->DEDXTable()); 664 << 482 em->SetPreciseRangeTable(theLoss->PreciseRangeTable()); 665 for(G4int i=0; i<n_loss; ++i) { << 483 em->SetRangeTableForLoss(theLoss->RangeTableForLoss()); 666 if(p == loss_vector[i] && !tables_are_buil << 484 em->SetInverseRangeTable(theLoss->InverseRangeTable()); 667 const G4ParticleDefinition* curr_part = << 485 em->SetLambdaTable(theLoss->LambdaTable()); 668 if(1 < verbose) { << 486 em->SetSubLambdaTable(theLoss->SubLambdaTable()); 669 G4cout << "### Build Table for " << p- << 487 if (electron_table_are_built && em->SecondaryParticle() == theElectron) 670 << " and " << curr_part->GetPar << 488 em->SetSecondaryRangeTable(eIonisation->RangeTableForLoss()); 671 << " " << tables_are_built[i] << 489 loss_map[part_vector[j]] = em; 672 << G4endl; << 490 if (1 < verbose) { 673 } << 491 G4String nm = "0"; 674 G4VEnergyLossProcess* curr_proc = BuildT << 492 G4String nm1= "0"; 675 if(curr_proc) { << 493 G4String nm2= "0"; 676 CopyTables(curr_part, curr_proc); << 494 const G4ParticleDefinition* pd = part_vector[j]; 677 if(p == curr_proc && 0 == run && p->Is << 495 const G4ParticleDefinition* bpd = base_part_vector[j]; 678 loss_map[aParticle] = p; << 496 if (pd) nm = pd->GetParticleName(); 679 //G4cout << "G4LossTableManager::Bui << 497 if (bpd) nm2 = bpd->GetParticleName(); 680 // << aParticle->GetParticleName << 498 if (part_vector[j]) nm1 = part_vector[j]->GetParticleName(); 681 // << " added to map " << p << 499 G4cout << "For " << loss_vector[j]->GetProcessName() >> 500 << " for " << nm >> 501 << " (" << nm1 << ") " >> 502 << " base_part= " << nm2 >> 503 << " tables_are_built= " << tables_are_built[j] >> 504 << G4endl; 682 } 505 } 683 } 506 } 684 } 507 } 685 if ( !tables_are_built[i] ) { all_tables_a << 686 } 508 } 687 if(1 < verbose) { << 688 G4cout << "### G4LossTableManager::BuildPh << 689 << "all_tables_are_built= " << all_ << 690 << aParticle->GetParticleName() << << 691 } << 692 } << 693 509 694 //....oooOO0OOooo........oooOO0OOooo........oo << 510 all_tables_are_built = true; 695 << 511 for (G4int ii=0; ii<n_loss; ii++) { 696 void G4LossTableManager::CopyTables(const G4Pa << 512 if ( !tables_are_built[ii] ) { 697 G4VEnergyL << 513 all_tables_are_built = false; 698 { << 514 break; 699 for (G4int j=0; j<n_loss; ++j) { << 700 << 701 G4VEnergyLossProcess* proc = loss_vector[j << 702 << 703 if (!tables_are_built[j] && part == base_p << 704 tables_are_built[j] = true; << 705 // for base particle approach only ionis << 706 proc->SetDEDXTable(base_proc->Ionisation << 707 proc->SetDEDXTable(base_proc->DEDXunRest << 708 proc->SetCSDARangeTable(base_proc->CSDAR << 709 proc->SetRangeTableForLoss(base_proc->Ra << 710 proc->SetInverseRangeTable(base_proc->In << 711 proc->SetLambdaTable(base_proc->LambdaTa << 712 if(proc->IsIonisationProcess()) { << 713 range_vector[j] = base_proc->RangeTabl << 714 inv_range_vector[j] = base_proc->Inver << 715 loss_map[part_vector[j]] = proc; << 716 //G4cout << "G4LossTableManager::CopyT << 717 // << part_vector[j]->GetParticl << 718 // << " added to map " << proc < << 719 } << 720 if (1 < verbose) { << 721 G4cout << " CopyTables for " << pro << 722 << " for " << part_vector[j]-> << 723 << " base_part= " << part->Get << 724 << " tables are assigned" << 725 << G4endl; << 726 } << 727 } 515 } 728 } 516 } >> 517 >> 518 if(0 < verbose) { >> 519 G4cout << "G4LossTableManager::RetrievePhysicsTable end: " >> 520 << "all_tables_are_built= " << all_tables_are_built >> 521 << " i= " << i << " n_loss= " << n_loss >> 522 << G4endl; >> 523 } >> 524 if(all_tables_are_built) { >> 525 G4cout << "##### All dEdx and Range tables are retrieved #####" << G4endl; >> 526 } else if(isLast) { >> 527 G4Exception("G4LossTableManager ERROR: not all dEdx and Range tables are retrieved"); >> 528 } 729 } 529 } 730 530 731 //....oooOO0OOooo........oooOO0OOooo........oo << 531 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 732 532 733 G4VEnergyLossProcess* G4LossTableManager::Buil << 533 G4VEnergyLossProcess* G4LossTableManager::BuildTables(const G4ParticleDefinition* aParticle) 734 const G4ParticleDefiniti << 735 { 534 { 736 if(1 < verbose) { << 535 if(0 < verbose) { 737 G4cout << " G4LossTableManager::BuildTab << 536 G4cout << "G4LossTableManager::BuildTables() for " 738 << aParticle->GetParticleName() << 537 << aParticle->GetParticleName() << G4endl; 739 } 538 } 740 539 741 std::vector<G4PhysicsTable*> t_list; << 540 // Check is it new particle or all tables have to be rebuilt >> 541 std::vector<G4PhysicsTable*> list; >> 542 list.clear(); 742 std::vector<G4VEnergyLossProcess*> loss_list 543 std::vector<G4VEnergyLossProcess*> loss_list; 743 std::vector<G4bool> build_flags; << 544 loss_list.clear(); 744 G4VEnergyLossProcess* em = nullptr; << 545 G4VEnergyLossProcess* em = 0; 745 G4VEnergyLossProcess* p = nullptr; << 746 G4int iem = 0; 546 G4int iem = 0; 747 G4PhysicsTable* dedx = nullptr; << 547 G4bool no_el = true; 748 G4int i; << 749 548 750 G4ProcessVector* pvec = << 549 for (G4int i=0; i<n_loss; i++) { 751 aParticle->GetProcessManager()->GetProcess << 550 if (aParticle == part_vector[i] && !tables_are_built[i]) { 752 G4int nvec = (G4int)pvec->size(); << 551 loss_vector[i]->Initialise(); 753 << 552 if(no_el && loss_vector[i]->SecondaryParticle() == theElectron) { 754 for (i=0; i<n_loss; ++i) { << 553 em = loss_vector[i]; 755 p = loss_vector[i]; << 554 iem= i; 756 if (nullptr != p) { << 555 no_el = false; 757 G4bool yes = (aParticle == part_vector[i << 556 } 758 << 557 if(!em) { 759 // possible case of process sharing betw << 558 em = loss_vector[i]; 760 if(!yes) { << 559 iem= i; 761 auto ptr = static_cast<G4VProcess*>(p) << 762 for(G4int j=0; j<nvec; ++j) { << 763 //G4cout << "j= " << j << " " << (*p << 764 if(ptr == (*pvec)[j]) { << 765 yes = true; << 766 break; << 767 } << 768 } << 769 } << 770 // process belong to this particle << 771 if(yes && isActive[i]) { << 772 if (p->IsIonisationProcess() || !em) { << 773 em = p; << 774 iem= i; << 775 } << 776 // tables may be shared between partic << 777 G4bool val = false; << 778 if (!tables_are_built[i]) { << 779 val = true; << 780 dedx = p->BuildDEDXTable(fRestricted << 781 //G4cout << "===Build DEDX table for << 782 // << " idx= " << i << " dedx:" << d << 783 p->SetDEDXTable(dedx,fRestricted); << 784 tables_are_built[i] = true; << 785 } else { << 786 dedx = p->DEDXTable(); << 787 } << 788 t_list.push_back(dedx); << 789 loss_list.push_back(p); << 790 build_flags.push_back(val); << 791 } 560 } >> 561 tables_are_built[i] = true; >> 562 list.push_back(loss_vector[i]->BuildDEDXTable()); >> 563 loss_list.push_back(loss_vector[i]); 792 } 564 } 793 } 565 } 794 566 795 G4int n_dedx = (G4int)t_list.size(); << 567 G4int n_dedx = list.size(); 796 if (0 == n_dedx || !em) { << 568 if (!n_dedx) return 0; 797 G4cout << "G4LossTableManager WARNING: no << 569 798 << aParticle->GetParticleName() << << 570 if (aParticle == theElectron) eIonisation = em; 799 return nullptr; << 800 } << 801 G4int nSubRegions = em->NumberOfSubCutoffReg << 802 571 803 if (1 < verbose) { 572 if (1 < verbose) { 804 G4cout << " Start to build the sum of << 573 G4cout << "G4LossTableManager::BuildTables() start to build range tables" 805 << " iem= " << iem << " em= " << em << 574 << " and the sum of " << n_dedx << " processes" 806 << " buildCSDARange= " << theParame << 575 << G4endl; 807 << " nSubRegions= " << nSubRegions; << 808 if(subcutProducer) { << 809 G4cout << " SubCutProducer " << subcutPr << 810 } << 811 G4cout << G4endl; << 812 } 576 } 813 // do not build tables if producer class is << 814 if(subcutProducer) { nSubRegions = 0; } << 815 << 816 dedx = em->DEDXTable(); << 817 em->SetDEDXTable(dedx, fIsIonisation); << 818 577 >> 578 G4PhysicsTable* dedx = list[0]; 819 if (1 < n_dedx) { 579 if (1 < n_dedx) { 820 dedx = nullptr; << 580 dedx = tableBuilder->BuildDEDXTable(list); 821 dedx = G4PhysicsTableHelper::PreparePhysic << 581 for(G4int i=0; i<n_dedx; i++) { 822 tableBuilder->BuildDEDXTable(dedx, t_list) << 582 list[i]->clearAndDestroy(); 823 em->SetDEDXTable(dedx, fRestricted); << 583 } 824 } 584 } 825 << 585 em->SetDEDXTable(dedx); 826 dedx_vector[iem] = dedx; 586 dedx_vector[iem] = dedx; 827 << 587 G4PhysicsTable* range = tableBuilder->BuildRangeTable(dedx); 828 G4PhysicsTable* range = em->RangeTableForLos << 588 G4PhysicsTable* invrange = tableBuilder->BuildInverseRangeTable(dedx, range); 829 if(!range) range = G4PhysicsTableHelper::Pr << 830 range_vector[iem] = range; << 831 << 832 G4PhysicsTable* invrange = em->InverseRangeT << 833 if(!invrange) invrange = G4PhysicsTableHelpe << 834 inv_range_vector[iem] = invrange; << 835 << 836 tableBuilder->BuildRangeTable(dedx, range); << 837 tableBuilder->BuildInverseRangeTable(range, << 838 << 839 em->SetRangeTableForLoss(range); << 840 em->SetInverseRangeTable(invrange); 589 em->SetInverseRangeTable(invrange); >> 590 inv_range_vector[iem] = invrange; >> 591 em->SetRangeTableForLoss(range); >> 592 range_vector[iem] = range; 841 593 842 std::vector<G4PhysicsTable*> listCSDA; << 594 if(buildPreciseRange) { 843 << 595 std::vector<G4PhysicsTable*> newlist; 844 for (i=0; i<n_dedx; ++i) { << 596 newlist.clear(); 845 p = loss_list[i]; << 597 for (G4int i=0; i<n_dedx; i++) { 846 if(build_flags[i]) { << 598 newlist.push_back(loss_list[i]->BuildDEDXTableForPreciseRange()); 847 p->SetLambdaTable(p->BuildLambdaTable(fR << 848 } 599 } 849 if(theParameters->BuildCSDARange()) { << 600 G4PhysicsTable* dedxForRange = newlist[0]; 850 dedx = p->BuildDEDXTable(fTotal); << 851 p->SetDEDXTable(dedx,fTotal); << 852 listCSDA.push_back(dedx); << 853 } << 854 } << 855 << 856 if(theParameters->BuildCSDARange()) { << 857 G4PhysicsTable* dedxCSDA = em->DEDXunRestr << 858 if (1 < n_dedx) { 601 if (1 < n_dedx) { 859 dedxCSDA = G4PhysicsTableHelper::Prepare << 602 dedxForRange = tableBuilder->BuildDEDXTable(newlist); 860 tableBuilder->BuildDEDXTable(dedxCSDA, l << 603 for(G4int j=0; j<n_dedx; j++) { 861 em->SetDEDXTable(dedxCSDA,fTotal); << 604 newlist[j]->clearAndDestroy(); >> 605 } 862 } 606 } 863 G4PhysicsTable* rCSDA = em->CSDARangeTable << 607 newlist.clear(); 864 if(!rCSDA) { rCSDA = G4PhysicsTableHelper: << 608 range = tableBuilder->BuildRangeTable(dedxForRange); 865 tableBuilder->BuildRangeTable(dedxCSDA, rC << 609 em->SetPreciseRangeTable(range); 866 em->SetCSDARangeTable(rCSDA); << 610 delete dedxForRange; 867 } 611 } 868 612 869 if (1 < verbose) { << 613 >> 614 loss_map[aParticle] = em; >> 615 for (G4int j=0; j<n_dedx; j++) { >> 616 if(loss_list[j]->SecondaryParticle() == theElectron && eIonisation) >> 617 loss_list[j]->SetSecondaryRangeTable(eIonisation->RangeTableForLoss()); >> 618 >> 619 G4PhysicsTable* lambdaTable = loss_list[j]->BuildLambdaTable(); >> 620 loss_list[j]->SetLambdaTable(lambdaTable); >> 621 if (0 < loss_list[j]->NumberOfSubCutoffRegions()) { >> 622 lambdaTable = loss_list[j]->BuildLambdaSubTable(); >> 623 loss_list[j]->SetSubLambdaTable(lambdaTable); >> 624 } >> 625 } >> 626 if (0 < verbose) { 870 G4cout << "G4LossTableManager::BuildTables 627 G4cout << "G4LossTableManager::BuildTables: Tables are built for " 871 << aParticle->GetParticleName() 628 << aParticle->GetParticleName() 872 << "; ionisation process: " << em-> << 629 << "; ionisation process: " << em->GetProcessName() 873 << " " << em << 874 << G4endl; 630 << G4endl; 875 } 631 } >> 632 list.clear(); >> 633 loss_list.clear(); 876 return em; 634 return em; 877 } 635 } 878 636 879 //....oooOO0OOooo........oooOO0OOooo........oo << 637 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 880 638 881 void G4LossTableManager::ParticleHaveNoLoss( << 639 void G4LossTableManager::SetLossFluctuations(G4bool val) 882 const G4ParticleDefinition* aParticle) << 883 { 640 { 884 G4ExceptionDescription ed; << 641 lossFluctuationFlag = val; 885 ed << "Energy loss process not found for " < << 642 for(G4int i=0; i<n_loss; i++) { 886 << " !"; << 643 if(loss_vector[i]) loss_vector[i]->SetLossFluctuations(val); 887 G4Exception("G4LossTableManager::ParticleHav << 644 } 888 FatalException, ed); << 889 } 645 } 890 646 891 //....oooOO0OOooo........oooOO0OOooo........oo << 647 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 892 648 893 void G4LossTableManager::SetVerbose(G4int val) << 649 void G4LossTableManager::SetSubCutoff(G4bool val) 894 { 650 { 895 verbose = val; << 651 subCutoffFlag = val; >> 652 for(G4int i=0; i<n_loss; i++) { >> 653 if(loss_vector[i]) loss_vector[i]->SetSubCutoff(val); >> 654 } 896 } 655 } 897 656 898 //....oooOO0OOooo........oooOO0OOooo........oo << 657 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 899 658 900 const std::vector<G4VEnergyLossProcess*>& << 659 void G4LossTableManager::SetIntegral(G4bool val) 901 G4LossTableManager::GetEnergyLossProcessVector << 902 { 660 { 903 return loss_vector; << 661 integral = val; >> 662 integralActive = true; >> 663 for(G4int i=0; i<n_loss; i++) { >> 664 if(loss_vector[i]) loss_vector[i]->SetIntegral(val); >> 665 } 904 } 666 } 905 667 906 //....oooOO0OOooo........oooOO0OOooo........oo << 668 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 907 669 908 const std::vector<G4VEmProcess*>& G4LossTableM << 670 void G4LossTableManager::SetMinSubRange(G4double val) 909 { 671 { 910 return emp_vector; << 672 minSubRange = val; >> 673 for(G4int i=0; i<n_loss; i++) { >> 674 if(loss_vector[i]) loss_vector[i]->SetMinSubRange(val); >> 675 } 911 } 676 } 912 677 913 //....oooOO0OOooo........oooOO0OOooo........oo << 678 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 914 679 915 const std::vector<G4VMultipleScattering*>& << 680 void G4LossTableManager::SetRandomStep(G4bool val) 916 G4LossTableManager::GetMultipleScatteringVecto << 917 { 681 { 918 return msc_vector; << 682 rndmStepFlag = val; >> 683 for(G4int i=0; i<n_loss; i++) { >> 684 if(loss_vector[i]) loss_vector[i]->SetRandomStep(val); >> 685 } 919 } 686 } 920 687 921 //....oooOO0OOooo........oooOO0OOooo........oo 688 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 922 689 923 G4EmSaturation* G4LossTableManager::EmSaturati << 690 void G4LossTableManager::SetMinEnergy(G4double val) 924 { 691 { 925 return theParameters->GetEmSaturation(); << 692 minEnergyActive = true; >> 693 minKinEnergy = val; >> 694 for(G4int i=0; i<n_loss; i++) { >> 695 if(loss_vector[i]) loss_vector[i]->SetMinKinEnergy(val); >> 696 } >> 697 size_t msc = msc_vector.size(); >> 698 for (size_t j=0; j<msc; j++) { >> 699 if(msc_vector[j]) msc_vector[j]->SetMinKinEnergy(val); >> 700 } >> 701 size_t emp = emp_vector.size(); >> 702 for (size_t k=0; k<emp; k++) { >> 703 if(emp_vector[k]) emp_vector[k]->SetMinKinEnergy(val); >> 704 } 926 } 705 } 927 706 928 //....oooOO0OOooo........oooOO0OOooo........oo 707 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 929 708 930 G4EmConfigurator* G4LossTableManager::EmConfig << 709 void G4LossTableManager::SetMaxEnergy(G4double val) 931 { 710 { 932 if(!emConfigurator) { << 711 maxEnergyActive = true; 933 emConfigurator = new G4EmConfigurator(verb << 712 maxKinEnergy = val; >> 713 for(G4int i=0; i<n_loss; i++) { >> 714 if(loss_vector[i]) loss_vector[i]->SetMaxKinEnergy(val); >> 715 } >> 716 size_t msc = msc_vector.size(); >> 717 for (size_t j=0; j<msc; j++) { >> 718 if(msc_vector[j]) msc_vector[j]->SetMaxKinEnergy(val); >> 719 } >> 720 size_t emp = emp_vector.size(); >> 721 for (size_t k=0; k<emp; k++) { >> 722 if(emp_vector[k]) emp_vector[k]->SetMaxKinEnergy(val); 934 } 723 } 935 return emConfigurator; << 936 } 724 } 937 725 938 //....oooOO0OOooo........oooOO0OOooo........oo 726 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 939 727 940 G4ElectronIonPair* G4LossTableManager::Electro << 728 void G4LossTableManager::SetMaxEnergyForPreciseRange(G4double val) 941 { 729 { 942 if(!emElectronIonPair) { << 730 for(G4int i=0; i<n_loss; i++) { 943 emElectronIonPair = new G4ElectronIonPair( << 731 if(loss_vector[i]) loss_vector[i]->SetMaxKinEnergyForPreciseRange(val); 944 } 732 } 945 return emElectronIonPair; << 946 } 733 } 947 734 948 //....oooOO0OOooo........oooOO0OOooo........oo 735 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 949 736 950 void G4LossTableManager::SetNIELCalculator(G4N << 737 void G4LossTableManager::SetMaxEnergyForMuons(G4double val) >> 738 { >> 739 maxEnergyForMuonsActive = true; >> 740 maxKinEnergyForMuons = val; >> 741 } >> 742 >> 743 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... >> 744 >> 745 void G4LossTableManager::SetDEDXBinning(G4int val) 951 { 746 { 952 if(nullptr != ptr && ptr != nielCalculator) << 747 for(G4int i=0; i<n_loss; i++) { 953 delete nielCalculator; << 748 if(loss_vector[i]) loss_vector[i]->SetDEDXBinning(val); 954 nielCalculator = ptr; << 955 } 749 } 956 } 750 } 957 751 >> 752 958 //....oooOO0OOooo........oooOO0OOooo........oo 753 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 959 754 960 G4NIELCalculator* G4LossTableManager::NIELCalc << 755 void G4LossTableManager::SetDEDXBinningForPreciseRange(G4int val) 961 { 756 { 962 if(!nielCalculator) { << 757 for(G4int i=0; i<n_loss; i++) { 963 nielCalculator = new G4NIELCalculator(null << 758 if(loss_vector[i]) loss_vector[i]->SetDEDXBinningForPreciseRange(val); 964 } 759 } 965 return nielCalculator; << 966 } 760 } 967 761 968 //....oooOO0OOooo........oooOO0OOooo........oo << 762 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 969 << 763 970 void G4LossTableManager::SetAtomDeexcitation(G << 764 void G4LossTableManager::SetLambdaBinning(G4int val) 971 { 765 { 972 if(atomDeexcitation != p) { << 766 for(G4int i=0; i<n_loss; i++) { 973 delete atomDeexcitation; << 767 if(loss_vector[i]) loss_vector[i]->SetLambdaBinning(val); 974 atomDeexcitation = p; << 768 } >> 769 size_t msc = msc_vector.size(); >> 770 for (size_t j=0; j<msc; j++) { >> 771 if(msc_vector[j]) msc_vector[j]->SetBinning(val); >> 772 } >> 773 size_t emp = emp_vector.size(); >> 774 for (size_t k=0; k<emp; k++) { >> 775 if(emp_vector[k]) emp_vector[k]->SetLambdaBinning(val); 975 } 776 } 976 } 777 } 977 778 978 //....oooOO0OOooo........oooOO0OOooo........oo << 779 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 979 780 980 void G4LossTableManager::SetSubCutProducer(G4V << 781 void G4LossTableManager::SetVerbose(G4int val) 981 { 782 { 982 if(subcutProducer != p) { << 783 verbose = val; 983 delete subcutProducer; << 784 for(G4int i=0; i<n_loss; i++) { 984 subcutProducer = p; << 785 if(loss_vector[i]) loss_vector[i]->SetVerboseLevel(val); >> 786 } >> 787 size_t msc = msc_vector.size(); >> 788 for (size_t j=0; j<msc; j++) { >> 789 if(msc_vector[j]) msc_vector[j]->SetVerboseLevel(val); >> 790 } >> 791 size_t emp = emp_vector.size(); >> 792 for (size_t k=0; k<emp; k++) { >> 793 if(emp_vector[k]) emp_vector[k]->SetVerboseLevel(val); 985 } 794 } 986 } 795 } 987 796 988 //....oooOO0OOooo........oooOO0OOooo........oo << 797 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 989 798 990 void G4LossTableManager::PrintEWarning(G4Strin << 799 void G4LossTableManager::SetStepLimits(G4double v1, G4double v2) 991 { 800 { 992 G4String ss = "G4LossTableManager::" + tit; << 801 stepFunctionActive = true; 993 G4ExceptionDescription ed; << 802 maxRangeVariation = v1; 994 /* << 803 maxFinalStep = v2; 995 ed << "Parameter is out of range: " << val << 804 for(G4int i=0; i<n_loss; i++) { 996 << " it will have no effect!\n" << " ## " << 805 if(loss_vector[i]) loss_vector[i]->SetStepFunction(v1, v2); 997 << " nbins= " << nbinsLambda << 806 } 998 << " nbinsPerDecade= " << nbinsPerDecade << 999 << " Emin(keV)= " << minKinEnergy/keV << 1000 << " Emax(GeV)= " << maxKinEnergy/GeV; << 1001 */ << 1002 G4Exception(ss, "em0044", JustWarning, ed); << 1003 } 807 } 1004 808 1005 //....oooOO0OOooo........oooOO0OOooo........o << 809 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 1006 810 1007 void G4LossTableManager::DumpHtml() << 811 void G4LossTableManager::SetBuildPreciseRange(G4bool val) 1008 { 812 { 1009 // Automatic generation of html documentati << 813 buildPreciseRange = val; 1010 // List processes and models for the most i << 814 } 1011 // particles in descending order of importa << 1012 // NB. for model names with length > 18 cha << 1013 // to be edited by hand. Or modify G4EmMod << 1014 << 1015 char* dirName = std::getenv("G4PhysListDocD << 1016 char* physList = std::getenv("G4PhysListNam << 1017 if (dirName && physList) { << 1018 G4String physListName = G4String(physList << 1019 G4String pathName = G4String(dirName) + " << 1020 << 1021 std::ofstream outFile; << 1022 outFile.open(pathName); << 1023 << 1024 outFile << physListName << G4endl; << 1025 outFile << std::string(physListName.lengt << 1026 << 1027 std::vector<G4ParticleDefinition*> partic << 1028 G4Gamma::Gamma(), << 1029 G4Electron::Electron(), << 1030 G4Positron::Positron(), << 1031 G4Proton::ProtonDefinition(), << 1032 G4MuonPlus::MuonPlusDefinition(), << 1033 G4MuonMinus::MuonMinusDefinition(), << 1034 }; << 1035 << 1036 std::vector<G4VEmProcess*> emproc_vector << 1037 std::vector<G4VEnergyLossProcess*> enloss << 1038 GetEnergyLossProcessVector(); << 1039 std::vector<G4VMultipleScattering*> mscat << 1040 GetMultipleScatteringVector(); << 1041 << 1042 for (auto theParticle : particles) { << 1043 outFile << G4endl << "**" << theParticl << 1044 << "**" << G4endl << G4endl << << 1045 << 1046 G4ProcessManager* pm = theParticle->Get << 1047 G4ProcessVector* pv = pm->GetProcessLi << 1048 G4int plen = pm->GetProcessListLength() << 1049 << 1050 for (auto emproc : emproc_vector) { << 1051 for (G4int i = 0; i < plen; ++i) { << 1052 G4VProcess* proc = (*pv)[i]; << 1053 if (proc == emproc) { << 1054 outFile << G4endl; << 1055 proc->ProcessDescription(outFile) << 1056 break; << 1057 } << 1058 } << 1059 } << 1060 815 1061 for (auto mscproc : mscat_vector) { << 816 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 1062 for (G4int i = 0; i < plen; ++i) { << 1063 G4VProcess* proc = (*pv)[i]; << 1064 if (proc == mscproc) { << 1065 outFile << G4endl; << 1066 proc->ProcessDescription(outFile) << 1067 break; << 1068 } << 1069 } << 1070 } << 1071 817 1072 for (auto enlossproc : enloss_vector) { << 818 void G4LossTableManager::SetParameters(G4VEnergyLossProcess* p) 1073 for (G4int i = 0; i < plen; ++i) { << 819 { 1074 G4VProcess* proc = (*pv)[i]; << 820 if(stepFunctionActive) p->SetStepFunction(maxRangeVariation, maxFinalStep); 1075 if (proc == enlossproc) { << 821 if(integralActive) p->SetIntegral(integral); 1076 outFile << G4endl; << 822 if(minEnergyActive) p->SetMinKinEnergy(minKinEnergy); 1077 proc->ProcessDescription(outFile) << 823 if(maxEnergyActive) p->SetMaxKinEnergy(maxKinEnergy); 1078 break; << 1079 } << 1080 } << 1081 } << 1082 } << 1083 outFile.close(); << 1084 } << 1085 } 824 } 1086 825 1087 //....oooOO0OOooo........oooOO0OOooo........o << 826 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 1088 827 >> 828 const std::vector<G4VEnergyLossProcess*>& G4LossTableManager::GetEnergyLossProcessVector() >> 829 { >> 830 return loss_vector; >> 831 } >> 832 >> 833 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... >> 834 >> 835 const std::vector<G4VEmProcess*>& G4LossTableManager::GetEmProcessVector() >> 836 { >> 837 return emp_vector; >> 838 } >> 839 >> 840 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... >> 841 >> 842 const std::vector<G4VMultipleScattering*>& G4LossTableManager::GetMultipleScatteringVector() >> 843 { >> 844 return msc_vector; >> 845 } >> 846 >> 847 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 1089 848