Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // Hadronic Process: Nuclear De-excitations 26 // Hadronic Process: Nuclear De-excitations 27 // by V. Lara (Oct 1998) 27 // by V. Lara (Oct 1998) 28 // 28 // 29 // Modifications: 29 // Modifications: 30 // 28.10.2010 V.Ivanchenko defined members in 30 // 28.10.2010 V.Ivanchenko defined members in constructor and cleaned up 31 31 32 #include "G4VEmissionProbability.hh" 32 #include "G4VEmissionProbability.hh" 33 #include "G4NuclearLevelData.hh" 33 #include "G4NuclearLevelData.hh" 34 #include "G4LevelManager.hh" 34 #include "G4LevelManager.hh" 35 #include "G4DeexPrecoParameters.hh" 35 #include "G4DeexPrecoParameters.hh" 36 #include "Randomize.hh" 36 #include "Randomize.hh" 37 #include "G4Pow.hh" 37 #include "G4Pow.hh" 38 #include "G4Log.hh" << 39 #include "G4Exp.hh" << 40 38 41 G4VEmissionProbability::G4VEmissionProbability 39 G4VEmissionProbability::G4VEmissionProbability(G4int Z, G4int A) 42 : pVerbose(1), theZ(Z), theA(A), elimit(CLHE << 40 : OPTxs(3),pVerbose(1),theZ(Z),theA(A),resZ(0),resA(0), >> 41 pMass(0.0),pEvapMass(0.0),pResMass(0.0),fExc(0.0),fExcRes(0.0), >> 42 elimit(CLHEP::MeV),accuracy(0.02),fFD(false) 43 { 43 { 44 pNuclearLevelData = G4NuclearLevelData::GetI 44 pNuclearLevelData = G4NuclearLevelData::GetInstance(); 45 pG4pow = G4Pow::GetInstance(); 45 pG4pow = G4Pow::GetInstance(); 46 if(A > 0) { pEvapMass = G4NucleiProperties:: 46 if(A > 0) { pEvapMass = G4NucleiProperties::GetNuclearMass(theA, theZ); } 47 G4DeexPrecoParameters* param = pNuclearLevel << 47 // G4cout << "G4VEvaporationProbability: Z= " << theZ << " A= " << theA 48 OPTxs = param->GetDeexModelType(); << 48 // << " M(GeV)= " << pEvapMass/1000. << G4endl; >> 49 length = nbin = 0; >> 50 emin = emax = eCoulomb = pProbability = probmax = 0.0; 49 } 51 } 50 52 >> 53 G4VEmissionProbability::~G4VEmissionProbability() >> 54 {} >> 55 51 void G4VEmissionProbability::Initialise() 56 void G4VEmissionProbability::Initialise() 52 { 57 { 53 G4DeexPrecoParameters* param = pNuclearLevel 58 G4DeexPrecoParameters* param = pNuclearLevelData->GetParameters(); >> 59 OPTxs = param->GetDeexModelType(); 54 pVerbose = param->GetVerbose(); 60 pVerbose = param->GetVerbose(); 55 fFD = param->GetDiscreteExcitationFlag(); 61 fFD = param->GetDiscreteExcitationFlag(); 56 pTolerance = param->GetMinExcitation(); << 57 pWidth = param->GetNuclearLevelWidth(); << 58 } 62 } 59 63 60 void G4VEmissionProbability::ResetIntegrator(s << 64 void G4VEmissionProbability::ResetIntegrator(size_t nbins, G4double de, G4double eps) 61 { 65 { >> 66 if(nbins > 0) { length = nbins; } 62 if(de > 0.0) { elimit = de; } 67 if(de > 0.0) { elimit = de; } 63 if(eps > 0.0) { accuracy = eps; } 68 if(eps > 0.0) { accuracy = eps; } 64 } 69 } 65 70 66 G4double G4VEmissionProbability::EmissionProba 71 G4double G4VEmissionProbability::EmissionProbability(const G4Fragment&, G4double) 67 { 72 { 68 return 0.0; 73 return 0.0; 69 } 74 } 70 75 71 G4double G4VEmissionProbability::ComputeProbab 76 G4double G4VEmissionProbability::ComputeProbability(G4double, G4double) 72 { 77 { 73 return 0.0; 78 return 0.0; 74 } 79 } 75 80 76 G4double G4VEmissionProbability::IntegrateProb 81 G4double G4VEmissionProbability::IntegrateProbability(G4double elow, 77 82 G4double ehigh, 78 83 G4double cb) 79 { 84 { 80 pProbability = 0.0; 85 pProbability = 0.0; 81 if(elow >= ehigh) { return pProbability; } 86 if(elow >= ehigh) { return pProbability; } 82 87 83 emin = elow; 88 emin = elow; 84 emax = ehigh; 89 emax = ehigh; 85 eCoulomb = cb; 90 eCoulomb = cb; 86 91 87 const G4double edeltamin = 0.1*CLHEP::MeV; << 92 G4double edelta = elimit; >> 93 nbin = (size_t)((emax - emin)/edelta) + 1; >> 94 const G4double edeltamin = 0.2*CLHEP::MeV; 88 const G4double edeltamax = 2*CLHEP::MeV; 95 const G4double edeltamax = 2*CLHEP::MeV; 89 G4double edelta = std::min(std::min(elimit, << 96 if(nbin < 4) { 90 G4double xbin = (emax - emin)/edelta + 1.0; << 97 nbin = 4; 91 G4int ibin = std::max((G4int)xbin, 4); << 98 edelta = (emax - emin)/(G4double)nbin; 92 << 99 } else if(nbin > length) { 93 // providing smart binning << 100 nbin = length; 94 G4int nbin = ibin*5; << 101 } 95 edelta = (emax - emin)/ibin; << 96 102 97 G4double x(emin), y(0.0); << 103 G4double x(emin), del, y; 98 G4double edelmicro = edelta*0.02; << 104 G4double edelmicro= edelta*0.02; 99 probmax = ComputeProbability(x + edelmicro, 105 probmax = ComputeProbability(x + edelmicro, eCoulomb); 100 G4double problast = probmax; 106 G4double problast = probmax; 101 if(pVerbose > 1) { << 107 if(pVerbose > 2) { 102 G4cout << "### G4VEmissionProbability::Int << 108 G4cout << "### G4VEmissionProbability::IntegrateProbability: " 103 << "probmax=" << probmax << " Emin=" << e << 109 << " Emax= " << emax << " QB= " << cb << " nbin= " << nbin 104 << " Emax=" << emax << " QB=" << cb << " << 105 << G4endl; 110 << G4endl; >> 111 G4cout << " 0. E= " << emin << " prob= " << probmax << G4endl; 106 } 112 } 107 fE1 = fE2 = fP2 = 0.0; << 113 for(size_t i=1; i<=nbin; ++i) { 108 G4double emax0 = emax - edelmicro; << 109 G4bool endpoint = false; << 110 for(G4int i=0; i<nbin; ++i) { << 111 x += edelta; 114 x += edelta; 112 if(x >= emax0) { << 115 if(x > emax) { 113 x = emax0; << 116 edelta += (emax - x); 114 endpoint = true; << 117 x = emax; 115 } << 118 } 116 y = ComputeProbability(x, eCoulomb); << 119 G4bool endpoint = (std::abs(x - emax) < edelmicro) ? true : false; >> 120 G4double xx = endpoint ? x - edelmicro : x; >> 121 y = ComputeProbability(xx, eCoulomb); 117 if(pVerbose > 2) { 122 if(pVerbose > 2) { 118 G4cout << " " << i << ". E= " << x < << 123 G4cout << " " << i << ". E= " << x << " prob= " << y 119 << " Edel= " << edelta << G4endl; 124 << " Edel= " << edelta << G4endl; 120 } 125 } 121 if(y >= probmax) { << 126 probmax = std::max(probmax, y); 122 probmax = y; << 127 del = (y + problast)*edelta*0.5; 123 } else if(0.0 == fE1 && 2*y < probmax) { << 124 fE1 = x; << 125 } << 126 << 127 G4double del = (y + problast)*edelta*0.5; << 128 pProbability += del; 128 pProbability += del; 129 // end of the loop 129 // end of the loop 130 if(del < accuracy*pProbability || endpoint 130 if(del < accuracy*pProbability || endpoint) { break; } 131 problast = y; 131 problast = y; 132 132 133 // smart step definition 133 // smart step definition 134 if(del != pProbability && del > 0.8*pProba 134 if(del != pProbability && del > 0.8*pProbability && 135 0.7*edelta > edeltamin) { 135 0.7*edelta > edeltamin) { 136 edelta *= 0.7; 136 edelta *= 0.7; 137 } else if(del < 0.1*pProbability && 1.5*ed 137 } else if(del < 0.1*pProbability && 1.5*edelta < edeltamax) { 138 edelta *= 1.5; 138 edelta *= 1.5; 139 } 139 } 140 } 140 } 141 if(fE1 > emin && fE1 < emax) { << 142 fE2 = std::max(0.5*(fE1 + emax), emax - ed << 143 fP2 = 2*ComputeProbability(fE2, eCoulomb); << 144 } << 145 141 146 if(pVerbose > 1) { 142 if(pVerbose > 1) { 147 G4cout << " Probability= " << pProbability 143 G4cout << " Probability= " << pProbability << " probmax= " 148 << probmax << " emin=" << emin << " << 144 << probmax << G4endl; 149 << " E1=" << fE1 << " E2=" << fE2 << G4en << 150 } 145 } 151 return pProbability; 146 return pProbability; 152 } 147 } 153 148 154 G4double G4VEmissionProbability::SampleEnergy( 149 G4double G4VEmissionProbability::SampleEnergy() 155 { 150 { 156 static const G4double fact = 1.05; 151 static const G4double fact = 1.05; 157 static const G4double alim = 0.05; << 158 static const G4double blim = 20.; << 159 probmax *= fact; 152 probmax *= fact; 160 153 161 // two regions with flat and exponential maj << 162 G4double del = emax - emin; << 163 G4double p1 = 1.0; << 164 G4double p2 = 0.0; << 165 G4double a0 = 0.0; << 166 G4double a1 = 1.0; << 167 G4double x; << 168 if(fE1 > 0.0 && fP2 > 0.0 && fP2 < 0.5*probm << 169 a0 = G4Log(probmax/fP2)/(fE2 - fE1); << 170 del= fE1 - emin; << 171 p1 = del; << 172 x = a0*(emax - fE1); << 173 if(x < blim) { << 174 a1 = (x > alim) ? 1.0 - G4Exp(-x) : x*(1 << 175 } << 176 p2 = a1/a0; << 177 p1 /= (p1 + p2); << 178 p2 = 1.0 - p1; << 179 } << 180 << 181 if(pVerbose > 1) { 154 if(pVerbose > 1) { 182 G4cout << "### G4VEmissionProbability::Sam 155 G4cout << "### G4VEmissionProbability::SampleEnergy: " 183 << " Emin= " << emin << " Emax= " << emax 156 << " Emin= " << emin << " Emax= " << emax 184 << "/n E1=" << fE1 << " p1=" << << 157 << " probmax= " << probmax << G4endl; 185 << " probmax=" << probmax << " P2=" << fP << 186 } 158 } 187 159 188 CLHEP::HepRandomEngine* rndm = G4Random::get 160 CLHEP::HepRandomEngine* rndm = G4Random::getTheEngine(); 189 const G4int nmax = 1000; << 161 const G4int nmax = 100; 190 G4double ekin, gg, gmax; << 162 G4double del = emax - emin; >> 163 G4double ekin, g; 191 G4int n = 0; 164 G4int n = 0; 192 do { 165 do { >> 166 ekin = del*rndm->flat() + emin; 193 ++n; 167 ++n; 194 G4double q = rndm->flat(); << 168 g = ComputeProbability(ekin, eCoulomb); 195 if (p2 == 0.0) { << 196 gmax = probmax; << 197 ekin = del*q + emin; << 198 } else if (q <= p1) { << 199 gmax = probmax; << 200 ekin = del*q/p1 + emin; << 201 } else { << 202 ekin = fE1 - G4Log(1.0 - (q - p1)*a1/p2) << 203 x = a0*(ekin - fE1); << 204 gmax = fP2; << 205 if(x < blim) { << 206 gmax = probmax*((x > alim) ? G4Exp(-x) : 1.0 << 207 } << 208 } << 209 gg = ComputeProbability(ekin, eCoulomb); << 210 if(pVerbose > 2) { 169 if(pVerbose > 2) { 211 G4cout << " " << n 170 G4cout << " " << n 212 << ". prob= " << gg << " probmax= " << << 171 << ". prob= " << g << " probmax= " << probmax 213 << " Ekin= " << ekin << G4endl; 172 << " Ekin= " << ekin << G4endl; 214 } 173 } 215 if((gg > gmax || n > nmax) && pVerbose > 1 << 174 if((g > probmax || n > nmax) && pVerbose > 1) { 216 G4cout << "### G4VEmissionProbability::S 175 G4cout << "### G4VEmissionProbability::SampleEnergy for Z= " << theZ 217 << " A= " << theA << " Eex(MeV)=" << 176 << " A= " << theA 218 << "\n Warning n= " << n 177 << "\n Warning n= " << n 219 << " prob/gmax=" << gg/gmax << 178 << " prob/probmax= " << g/probmax 220 << " prob=" << gg << " gmax=" << gmax < << 179 << " prob= " << g << " probmax= " << probmax 221 << "\n Ekin= " << ekin << " Emin= " 180 << "\n Ekin= " << ekin << " Emin= " << emin 222 << " Emax= " << emax << G4endl; 181 << " Emax= " << emax << G4endl; 223 } 182 } 224 } while(gmax*rndm->flat() > gg && n < nmax); << 183 } while(probmax*rndm->flat() > g && n < nmax); 225 G4double enew = FindRecoilExcitation(ekin); << 184 return (fFD) ? FindRecoilExcitation(ekin) : ekin; 226 if(pVerbose > 1) { << 227 G4cout << "### SampleEnergy: Efinal= " << 228 << enew << " E=" << ekin << " Eexc=" << << 229 } << 230 return enew; << 231 } 185 } 232 186 233 G4double G4VEmissionProbability::FindRecoilExc << 187 G4double G4VEmissionProbability::FindRecoilExcitation(G4double e) 234 { 188 { >> 189 fExcRes = 0.0; 235 G4double mass = pEvapMass + fExc; 190 G4double mass = pEvapMass + fExc; >> 191 // abnormal case - should never happens >> 192 if(pMass < mass + pResMass) { return 0.0; } 236 193 237 G4double m02 = pMass*pMass; << 194 G4double m02 = pMass*pMass; 238 G4double m12 = mass*mass; << 195 G4double m12 = mass*mass; 239 G4double m22 = pResMass*pResMass; << 196 G4double m22 = pResMass*pResMass; 240 G4double mres = std::sqrt(m02 + m12 - 2.*pMa << 197 G4double mres = std::sqrt(m02 + m12 - 2.*pMass*(mass + e)); 241 198 242 fExcRes = mres - pResMass; 199 fExcRes = mres - pResMass; >> 200 const G4double tolerance = 0.1*CLHEP::keV; 243 201 244 if(pVerbose > 1) { 202 if(pVerbose > 1) { 245 G4cout << "### FindRecoilExcitation for re << 203 G4cout << "### G4VEmissionProbability::FindRecoilExcitation for resZ= " 246 << resZ << " resA= " << resA 204 << resZ << " resA= " << resA 247 << " evaporated Z= " << theZ << " A 205 << " evaporated Z= " << theZ << " A= " << theA 248 << " Ekin= " << e << " Eexc= " << fExcRes 206 << " Ekin= " << e << " Eexc= " << fExcRes << G4endl; 249 } 207 } 250 208 251 // residual nucleus is in the ground state 209 // residual nucleus is in the ground state 252 if(fExcRes < pTolerance) { << 210 if(fExcRes < tolerance) { 253 fExcRes = 0.0; 211 fExcRes = 0.0; 254 return std::max(0.5*(m02 + m12 - m22)/pMas << 212 //G4cout<<"Ground state Ekin= "<< 0.5*(m02 + m12 - m22)/pMass - mass<<G4endl; >> 213 return std::max(0.5*(m02 + m12 - m22)/pMass - mass,0.0); 255 } 214 } 256 if(!fFD) { return e; } << 257 << 258 // select final state excitation 215 // select final state excitation 259 auto lManager = pNuclearLevelData->GetLevelM 216 auto lManager = pNuclearLevelData->GetLevelManager(resZ, resA); 260 if(nullptr == lManager) { return e; } << 217 if(!lManager) { return e; } 261 218 >> 219 //G4cout<<"ExcMax= "<< lManager->MaxLevelEnergy()<<" CB= "<<eCoulomb<<G4endl; 262 // levels are not known 220 // levels are not known 263 if(fExcRes > lManager->MaxLevelEnergy() + pT << 221 if(fExcRes > lManager->MaxLevelEnergy() + tolerance) { return e; } 264 222 265 // find level 223 // find level 266 std::size_t idx = lManager->NearestLevelInde << 224 auto idx = lManager->NearestLevelIndex(fExcRes); 267 auto level = lManager->GetLevel(idx); << 225 //G4cout << "idx= " << idx << " Exc= " << fExcRes 268 << 226 // << " Elevel= " << lManager->LevelEnergy(idx) << G4endl; 269 // unstable level << 227 for(; idx > 0; --idx) { 270 if (level->GetTimeGamma() == 0.0) { return e << 228 fExcRes = lManager->LevelEnergy(idx); 271 << 229 // excited level 272 // is possible to use level energy? << 230 if(pMass > mass + pResMass + fExcRes && lManager->FloatingLevel(idx) == 0) { 273 G4double elevel = lManager->LevelEnergy(idx) << 231 G4double massR = pResMass + fExcRes; 274 if (std::abs(elevel - fExcRes) > pWidth || p << 232 G4double mr2 = massR*massR; 275 return e; << 233 //G4cout << "Result idx= " << idx << " Eexc= " << fExcRes 276 } << 234 // << " Ekin= " << 0.5*(m02 + m12 - mr2)/pMass - mass << G4endl; 277 << 235 return std::max(0.5*(m02 + m12 - mr2)/pMass - mass,0.0); 278 // long-lived level << 236 } 279 G4double massR = pResMass + elevel; << 237 } 280 G4double mr2 = massR*massR; << 238 // ground level 281 fExcRes = elevel; << 239 fExcRes = 0.0; 282 return std::max(0.5*(m02 + m12 - mr2)/pMass << 240 //G4cout << "Ground state Ekin= " << 0.5*(m02 + m12 - m22)/pMass - mass << G4endl; >> 241 return std::max(0.5*(m02 + m12 - m22)/pMass - mass,0.0); 283 } 242 } 284 243