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 // 26 // 27 // 080721 Create adjust_final_state method by << 27 //080721 Create adjust_final_state method by T. Koi 28 // 080801 Residual reconstruction with theNDLD << 28 //080801 Residual reconstruction with theNDLDataA,Z (A, Z, and momentum are adjusted) by T. Koi 29 // 101110 Set lower limit for gamma energy(1ke << 29 //101110 Set lower limit for gamma energy(1keV) by T. Koi 30 // P. Arce, June-2014 Conversion neutron_hp to 30 // P. Arce, June-2014 Conversion neutron_hp to particle_hp 31 // 31 // 32 32 33 #include "G4ParticleHPFinalState.hh" 33 #include "G4ParticleHPFinalState.hh" 34 34 35 #include "G4Alpha.hh" << 35 #include "G4PhysicalConstants.hh" 36 #include "G4Deuteron.hh" << 36 #include "G4SystemOfUnits.hh" 37 #include "G4Gamma.hh" << 38 #include "G4He3.hh" << 39 #include "G4IonTable.hh" 37 #include "G4IonTable.hh" >> 38 #include "G4Gamma.hh" 40 #include "G4Neutron.hh" 39 #include "G4Neutron.hh" 41 #include "G4PhysicalConstants.hh" << 42 #include "G4Proton.hh" 40 #include "G4Proton.hh" 43 #include "G4RandomDirection.hh" << 41 #include "G4Deuteron.hh" 44 #include "G4SystemOfUnits.hh" << 45 #include "G4Triton.hh" 42 #include "G4Triton.hh" >> 43 #include "G4He3.hh" >> 44 #include "G4Alpha.hh" 46 45 47 G4ParticleHPFinalState::G4ParticleHPFinalState << 46 G4bool G4ParticleHPFinalState::DoNotAdjustFinalState() 48 { 47 { 49 theProjectile = G4Neutron::Neutron(); << 48 return !G4ParticleHPManager::GetInstance()->GetDoNotAdjustFinalState(); 50 theResult.Put(nullptr); << 51 fManager = G4ParticleHPManager::GetInstance( << 52 ionTable = G4IonTable::GetIonTable(); << 53 } 49 } 54 50 55 G4ParticleHPFinalState::~G4ParticleHPFinalStat << 51 void G4ParticleHPFinalState::adjust_final_state ( G4LorentzVector init_4p_lab ) 56 { 52 { 57 delete theResult.Get(); << 58 } << 59 53 60 void G4ParticleHPFinalState::adjust_final_stat << 54 G4double minimum_energy = 1*keV; 61 { << 62 G4double minimum_energy = 1 * keV; << 63 55 64 if (fManager->GetDoNotAdjustFinalState()) re << 56 if ( G4ParticleHPManager::GetInstance()->GetDoNotAdjustFinalState() ) return; 65 57 66 auto nSecondaries = (G4int)theResult.Get()-> << 58 G4int nSecondaries = theResult.Get()->GetNumberOfSecondaries(); 67 59 68 G4int sum_Z = 0; << 60 G4int sum_Z = 0; 69 G4int sum_A = 0; << 61 G4int sum_A = 0; 70 G4int max_SecZ = 0; << 62 G4int max_SecZ = 0; 71 G4int max_SecA = 0; << 63 G4int max_SecA = 0; 72 G4int imaxA = -1; << 64 G4int imaxA = -1; 73 for (G4int i = 0; i < nSecondaries; ++i) { << 65 for ( int i = 0 ; i < nSecondaries ; i++ ) 74 auto ptr = theResult.Get()->GetSecondary(i << 66 { 75 sum_Z += ptr->GetAtomicNumber(); << 67 //G4cout << "G4ParticleHPFinalState::adjust_final_state theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetParticleName() = " << theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetParticleName() << G4endl; 76 max_SecZ = std::max(max_SecZ, ptr->GetAtom << 68 sum_Z += theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetAtomicNumber(); 77 sum_A += ptr->GetAtomicMass(); << 69 max_SecZ = std::max ( max_SecZ , theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetAtomicNumber() ); 78 max_SecA = std::max(max_SecA, ptr->GetAtom << 70 sum_A += theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetAtomicMass(); 79 if (ptr->GetAtomicMass() == max_SecA) << 71 max_SecA = std::max ( max_SecA , theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetAtomicMass() ); 80 imaxA = i; << 72 if ( theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetAtomicMass() == max_SecA ) imaxA = i; 81 #ifdef G4PHPDEBUG 73 #ifdef G4PHPDEBUG 82 if (fManager->GetDEBUG()) << 74 if( std::getenv("G4ParticleHPDebug")) G4cout << "G4ParticleHPFinalState::adjust_final_stat SECO " << i << " " <<theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetParticleName() << G4endl; 83 G4cout << "G4ParticleHPFinalState::adjus << 84 << ptr->GetParticleName() << G4en << 85 #endif 75 #endif 86 } << 87 76 88 G4ParticleDefinition* resi_pd = nullptr; << 77 } >> 78 >> 79 G4ParticleDefinition* resi_pd = 0; 89 80 90 G4int baseZNew = theBaseZ; << 81 G4double baseZNew = theBaseZ; 91 G4int baseANew = theBaseA; << 82 G4double baseANew = theBaseA; 92 if (theProjectile == G4Neutron::Neutron()) { << 83 if( theProjectile == G4Neutron::Neutron() ) { 93 baseANew++; << 84 baseANew ++; 94 } << 85 } else if( theProjectile == G4Proton::Proton() ) { 95 else if (theProjectile == G4Proton::Proton() << 86 baseZNew ++; 96 baseZNew++; << 87 baseANew ++; 97 baseANew++; << 88 } else if( theProjectile == G4Deuteron::Deuteron() ) { 98 } << 89 baseZNew ++; 99 else if (theProjectile == G4Deuteron::Deuter << 90 baseANew += 2; 100 baseZNew++; << 91 } else if( theProjectile == G4Triton::Triton() ) { 101 baseANew += 2; << 92 baseZNew ++; 102 } << 93 baseANew += 3; 103 else if (theProjectile == G4Triton::Triton() << 94 } else if( theProjectile == G4He3::He3() ) { 104 baseZNew++; << 95 baseZNew += 2; 105 baseANew += 3; << 96 baseANew += 3; 106 } << 97 } else if( theProjectile == G4Alpha::Alpha() ) { 107 else if (theProjectile == G4He3::He3()) { << 98 baseZNew += 2; 108 baseZNew += 2; << 99 baseANew += 4; 109 baseANew += 3; << 100 } 110 } << 111 else if (theProjectile == G4Alpha::Alpha()) << 112 baseZNew += 2; << 113 baseANew += 4; << 114 } << 115 101 116 #ifdef G4PHPDEBUG 102 #ifdef G4PHPDEBUG 117 if (fManager->GetDEBUG()) << 103 if( std::getenv("G4ParticleHPDebug")) G4cout << "G4ParticleHPFinalState::adjust_final_stat BaseZ " << baseZNew << " BaseA " << baseANew << " sum_Z " << sum_Z << " sum_A " << sum_A << G4endl; 118 G4cout << "G4ParticleHPFinalState::adjust_ << 119 << baseANew << " sum_Z " << sum_Z < << 120 #endif 104 #endif 121 105 122 G4bool needOneMoreSec = false; << 106 G4bool needOneMoreSec = false; 123 G4ParticleDefinition* oneMoreSec_pd = nullpt << 107 G4ParticleDefinition* oneMoreSec_pd = 0; 124 if (baseZNew == sum_Z && baseANew == sum_A) << 108 if ( (int)(baseZNew - sum_Z) == 0 && (int)(baseANew - sum_A) == 0 ) 125 // All secondaries are already created; << 109 { 126 resi_pd = theResult.Get()->GetSecondary(im << 110 //All secondaries are already created; 127 } << 111 resi_pd = theResult.Get()->GetSecondary( imaxA )->GetParticle()->GetDefinition(); 128 else { << 112 } 129 if (max_SecA >= baseANew - sum_A) { << 113 else 130 // Most heavy secondary is interpreted a << 114 { 131 resi_pd = theResult.Get()->GetSecondary( << 115 if ( max_SecA >= int(baseANew - sum_A) ) 132 needOneMoreSec = true; << 116 { 133 } << 117 //Most heavy secondary is interpreted as residual 134 else { << 118 resi_pd = theResult.Get()->GetSecondary( imaxA )->GetParticle()->GetDefinition(); 135 // creation of residual is required << 119 needOneMoreSec = true; 136 resi_pd = ionTable->GetIon(baseZNew - su << 120 } 137 } << 121 else 138 << 122 { 139 if (needOneMoreSec) { << 123 //creation of residual is requierd 140 if (baseZNew == sum_Z && baseANew == sum << 124 resi_pd = G4IonTable::GetIonTable()->GetIon ( int(baseZNew - sum_Z) , (int)(baseANew - sum_A) , 0.0 ); 141 // In this case, one neutron is added << 125 } 142 if (baseANew - sum_A > 1) << 126 143 G4cout << "More than one neutron is << 127 if ( needOneMoreSec ) 144 << G4endl; << 128 { 145 oneMoreSec_pd = G4Neutron::Neutron(); << 129 if ( int(baseZNew - sum_Z) == 0 && (int)(baseANew - sum_A) > 0 ) 146 } << 130 { 147 else { << 131 //In this case, one neutron is added to secondaries >> 132 if ( int(baseANew - sum_A) > 1 ) G4cout << "More than one neutron is required for the balance of baryon number!" << G4endl; >> 133 oneMoreSec_pd = G4Neutron::Neutron(); >> 134 } >> 135 else >> 136 { 148 #ifdef G4PHPDEBUG 137 #ifdef G4PHPDEBUG 149 if (fManager->GetDEBUG()) << 138 if( std::getenv("G4ParticleHPDebug")) G4cout << this << "G4ParticleHPFinalState oneMoreSec_pd Z " << baseZNew << " - " << sum_Z << " A " << baseANew << " - " << sum_A << " projectile " << theProjectile->GetParticleName() << G4endl; 150 G4cout << this << "G4ParticleHPFinal << 151 << baseZNew << " - " << sum_Z << 152 << " A " << baseANew << " - " << 153 << theProjectile->GetParticle << 154 #endif 139 #endif 155 oneMoreSec_pd = << 140 oneMoreSec_pd = G4IonTable::GetIonTable()->GetIon ( int(baseZNew - sum_Z) , (int)(baseANew - sum_A) , 0.0 ); 156 G4IonTable::GetIonTable()->GetIon(ba << 141 if( !oneMoreSec_pd ) { 157 if (oneMoreSec_pd == nullptr) { << 142 G4cerr << this << "G4ParticleHPFinalState oneMoreSec_pd Z " << baseZNew << " - " << sum_Z << " A " << baseANew << " - " << sum_A << " projectile " << theProjectile->GetParticleName() << G4endl; 158 G4ExceptionDescription ed; << 143 G4Exception("G4ParticleHPFinalState:adjust_final_state", 159 ed << "G4ParticleHPFinalState oneMor << 144 "Warning", 160 << " A=" << baseANew << " - " << 145 JustWarning, 161 << theProjectile->GetParticle << 146 "No adjustment will be done!"); 162 G4Exception("G4ParticleHPFinalState: << 147 return; 163 ed, "No adjustment will << 148 } 164 return; << 149 } >> 150 } >> 151 >> 152 if ( resi_pd == 0 ) >> 153 { >> 154 // theNDLDataZ,A has the Z and A of used NDL file >> 155 G4double ndlZNew = theNDLDataZ; >> 156 G4double ndlANew = theNDLDataA; >> 157 if( theProjectile == G4Neutron::Neutron() ) { >> 158 ndlANew ++; >> 159 } else if( theProjectile == G4Proton::Proton() ) { >> 160 ndlZNew ++; >> 161 ndlANew ++; >> 162 } else if( theProjectile == G4Deuteron::Deuteron() ) { >> 163 ndlZNew ++; >> 164 ndlANew += 2; >> 165 } else if( theProjectile == G4Triton::Triton() ) { >> 166 ndlZNew ++; >> 167 ndlANew += 3; >> 168 } else if( theProjectile == G4He3::He3() ) { >> 169 ndlZNew += 2; >> 170 ndlANew += 3; >> 171 } else if( theProjectile == G4Alpha::Alpha() ) { >> 172 ndlZNew += 2; >> 173 ndlANew += 4; >> 174 } >> 175 // theNDLDataZ,A has the Z and A of used NDL file >> 176 if ( (int)(ndlZNew - sum_Z) == 0 && (int)(ndlANew - sum_A) == 0 ) >> 177 { >> 178 G4int dif_Z = ( int ) ( theNDLDataZ - theBaseZ ); >> 179 G4int dif_A = ( int ) ( theNDLDataA - theBaseA ); >> 180 resi_pd = G4IonTable::GetIonTable()->GetIon ( max_SecZ - dif_Z , max_SecA - dif_A , 0.0 ); >> 181 if( !resi_pd ) { >> 182 G4cerr << "G4ParticleHPFinalState resi_pd Z " << max_SecZ << " - " << dif_Z << " A " << max_SecA << " - " << dif_A << " projectile " << theProjectile->GetParticleName() << G4endl; >> 183 G4Exception("G4ParticleHPFinalState:adjust_final_state", >> 184 "Warning", >> 185 JustWarning, >> 186 "No adjustment will be done!"); >> 187 return; >> 188 } >> 189 >> 190 for ( int i = 0 ; i < nSecondaries ; i++ ) >> 191 { >> 192 if ( theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetAtomicNumber() == max_SecZ >> 193 && theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition()->GetAtomicMass() == max_SecA ) >> 194 { >> 195 G4ThreeVector p = theResult.Get()->GetSecondary( i )->GetParticle()->GetMomentum(); >> 196 p = p * resi_pd->GetPDGMass()/ G4IonTable::GetIonTable()->GetIon ( max_SecZ , max_SecA , 0.0 )->GetPDGMass(); >> 197 theResult.Get()->GetSecondary( i )->GetParticle()->SetDefinition( resi_pd ); >> 198 theResult.Get()->GetSecondary( i )->GetParticle()->SetMomentum( p ); >> 199 } >> 200 } 165 } 201 } 166 } 202 } 167 } << 203 } 168 204 169 if (resi_pd == nullptr) { << 170 // theNDLDataZ,A has the Z and A of used << 171 G4int ndlZNew = theNDLDataZ; << 172 G4int ndlANew = theNDLDataA; << 173 if (theProjectile == G4Neutron::Neutron( << 174 ndlANew++; << 175 } << 176 else if (theProjectile == G4Proton::Prot << 177 ndlZNew++; << 178 ndlANew++; << 179 } << 180 else if (theProjectile == G4Deuteron::De << 181 ndlZNew++; << 182 ndlANew += 2; << 183 } << 184 else if (theProjectile == G4Triton::Trit << 185 ndlZNew++; << 186 ndlANew += 3; << 187 } << 188 else if (theProjectile == G4He3::He3()) << 189 ndlZNew += 2; << 190 ndlANew += 3; << 191 } << 192 else if (theProjectile == G4Alpha::Alpha << 193 ndlZNew += 2; << 194 ndlANew += 4; << 195 } << 196 // theNDLDataZ,A has the Z and A of used << 197 if (ndlZNew == sum_Z && ndlANew == sum_A << 198 G4int dif_Z = theNDLDataZ - theBaseZ; << 199 G4int dif_A = theNDLDataA - theBaseA; << 200 resi_pd = ionTable->GetIon(max_SecZ - << 201 if (resi_pd == nullptr) { << 202 G4ExceptionDescription ed; << 203 ed << "resi_pd Z=" << max_SecZ << " << 204 << max_SecA << " - " << dif_A << 205 << theProjectile->GetParticle << 206 G4Exception("G4ParticleHPFinalState: << 207 ed, "No adjustment will << 208 return; << 209 } << 210 205 211 for (G4int i = 0; i < nSecondaries; ++ << 206 G4LorentzVector secs_4p_lab( 0.0 ); 212 auto ptr = theResult.Get()->GetSecon << 207 213 if (ptr->GetDefinition()->GetAtomicN << 208 G4int n_sec = theResult.Get()->GetNumberOfSecondaries(); 214 ptr->GetDefinition()->GetAtomicM << 209 G4double fast = 0; 215 { << 210 G4double slow = 1; 216 G4ThreeVector p = ptr->GetMomentum << 211 G4int ifast = 0; 217 / ionTable->GetIon(max_SecZ, m << 212 G4int islow = 0; 218 ptr->SetDefinition(resi_pd); << 213 G4int ires = -1; 219 ptr->SetMomentum(p); << 214 220 } << 215 for ( G4int i = 0 ; i < n_sec ; i++ ) 221 } << 216 { >> 217 >> 218 //G4cout << "HP_DB " << i >> 219 // << " " << theResult.GetSecondary( i )->GetParticle()->GetDefinition()->GetParticleName() >> 220 // << " 4p " << theResult.GetSecondary( i )->GetParticle()->Get4Momentum() >> 221 // << " ke " << theResult.GetSecondary( i )->GetParticle()->Get4Momentum().e() - theResult.GetSecondary( i )->GetParticle()->GetDefinition()->GetPDGMass() >> 222 // << G4endl; >> 223 >> 224 secs_4p_lab += theResult.Get()->GetSecondary( i )->GetParticle()->Get4Momentum(); >> 225 >> 226 G4double beta = 0; >> 227 if ( theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition() != G4Gamma::Gamma() ) >> 228 { >> 229 beta = theResult.Get()->GetSecondary( i )->GetParticle()->Get4Momentum().beta(); >> 230 } >> 231 else >> 232 { >> 233 beta = 1; >> 234 } >> 235 >> 236 if ( theResult.Get()->GetSecondary( i )->GetParticle()->GetDefinition() == resi_pd ) ires = i; >> 237 >> 238 if ( slow > beta && beta != 0 ) >> 239 { >> 240 slow = beta; >> 241 islow = i; >> 242 } >> 243 >> 244 if ( fast <= beta ) >> 245 { >> 246 if ( fast != 1 ) >> 247 { >> 248 fast = beta; >> 249 ifast = i; >> 250 } >> 251 else >> 252 { >> 253 // fast is already photon then check E >> 254 G4double e = theResult.Get()->GetSecondary( i )->GetParticle()->Get4Momentum().e(); >> 255 if ( e > theResult.Get()->GetSecondary( ifast )->GetParticle()->Get4Momentum().e() ) >> 256 { >> 257 // among photons, the highest E becomes the fastest >> 258 ifast = i; >> 259 } >> 260 } >> 261 } >> 262 } >> 263 >> 264 >> 265 G4LorentzVector dif_4p = init_4p_lab - secs_4p_lab; >> 266 >> 267 //G4cout << "HP_DB dif_4p " << init_4p_lab - secs_4p_lab << G4endl; >> 268 //G4cout << "HP_DB dif_3p mag " << ( dif_4p.v() ).mag() << G4endl; >> 269 //G4cout << "HP_DB dif_e " << dif_4p.e() - ( dif_4p.v() ).mag()<< G4endl; >> 270 >> 271 G4LorentzVector p4(0); >> 272 if ( ires == -1 ) >> 273 { >> 274 // Create and Add Residual Nucleus >> 275 ires = nSecondaries; >> 276 nSecondaries += 1; >> 277 >> 278 G4DynamicParticle* res = new G4DynamicParticle ( resi_pd , dif_4p.v() ); >> 279 theResult.Get()->AddSecondary ( res ); >> 280 >> 281 p4 = res->Get4Momentum(); >> 282 if ( slow > p4.beta() ) >> 283 { >> 284 slow = p4.beta(); >> 285 islow = ires; >> 286 } >> 287 dif_4p = init_4p_lab - ( secs_4p_lab + p4 ); >> 288 } >> 289 >> 290 if ( needOneMoreSec && oneMoreSec_pd) >> 291 // >> 292 // fca: this is not a fix, this is a crash avoidance... >> 293 // fca: the baryon number is still wrong, most probably because it >> 294 // fca: should have been decreased, but since we could not create a particle >> 295 // fca: we just do not add it >> 296 // >> 297 { >> 298 nSecondaries += 1; >> 299 G4DynamicParticle* one = new G4DynamicParticle ( oneMoreSec_pd , dif_4p.v() ); >> 300 theResult.Get()->AddSecondary ( one ); >> 301 p4 = one->Get4Momentum(); >> 302 if ( slow > p4.beta() ) >> 303 { >> 304 slow = p4.beta(); >> 305 islow = nSecondaries-1; //Because the first is 0th, so the last becomes "nSecondaries-1" 222 } 306 } 223 } << 307 dif_4p = init_4p_lab - ( secs_4p_lab + p4 ); 224 } << 308 } 225 309 226 G4LorentzVector secs_4p_lab(0.0); << 310 //Which is bigger dif_p or dif_e >> 311 >> 312 if ( dif_4p.v().mag() < std::abs( dif_4p.e() ) ) >> 313 { >> 314 >> 315 // Adjust p >> 316 //if ( dif_4p.v().mag() < 1*MeV ) >> 317 if ( minimum_energy < dif_4p.v().mag() && dif_4p.v().mag() < 1*MeV ) >> 318 { >> 319 >> 320 nSecondaries += 1; >> 321 theResult.Get()->AddSecondary ( new G4DynamicParticle ( G4Gamma::Gamma() , dif_4p.v() ) ); 227 322 228 auto n_sec = (G4int)theResult.Get()->GetNumb << 229 G4double fast = 0; << 230 G4double slow = 1; << 231 G4int ifast = 0; << 232 G4int islow = 0; << 233 G4int ires = -1; << 234 << 235 for (G4int i = 0; i < n_sec; ++i) { << 236 auto ptr = theResult.Get()->GetSecondary(i << 237 secs_4p_lab += ptr->Get4Momentum(); << 238 << 239 G4double beta = 0; << 240 if (ptr->GetDefinition() != G4Gamma::Gamma << 241 beta = ptr->Get4Momentum().beta(); << 242 } << 243 else { << 244 beta = 1.0; << 245 } << 246 << 247 if (ptr->GetDefinition() == resi_pd) ires << 248 << 249 if (slow > beta && beta != 0) { << 250 slow = beta; << 251 islow = i; << 252 } << 253 << 254 if (fast <= beta) { << 255 if (fast != 1) { << 256 fast = beta; << 257 ifast = i; << 258 } << 259 else { << 260 // fast is already photon then check E << 261 G4double e = ptr->Get4Momentum().e(); << 262 if (e > theResult.Get()->GetSecondary( << 263 // among photons, the highest E beco << 264 ifast = i; << 265 } << 266 } 323 } 267 } << 324 else 268 } << 325 { >> 326 //G4cout << "HP_DB Difference in dif_p is too large (>1MeV) or too small(<1keV) to adjust, so that give up tuning" << G4endl; >> 327 } 269 328 270 G4LorentzVector dif_4p = init_4p_lab - secs_ << 329 } >> 330 else >> 331 { >> 332 >> 333 // dif_p > dif_e >> 334 // at first momentum >> 335 // Move residual momentum >> 336 >> 337 p4 = theResult.Get()->GetSecondary( ires )->GetParticle()->Get4Momentum(); >> 338 theResult.Get()->GetSecondary( ires )->GetParticle()->SetMomentum( p4.v() + dif_4p.v() ); >> 339 dif_4p = init_4p_lab - ( secs_4p_lab - p4 + theResult.Get()->GetSecondary( ires )->GetParticle()->Get4Momentum() ); >> 340 >> 341 //G4cout << "HP_DB new residual kinetic energy " << theResult.GetSecondary( ires )->GetParticle()->GetKineticEnergy() << G4endl; >> 342 >> 343 } >> 344 >> 345 G4double dif_e = dif_4p.e() - ( dif_4p.v() ).mag(); >> 346 //G4cout << "HP_DB dif_e " << dif_e << G4endl; >> 347 >> 348 if ( dif_e > 0 ) >> 349 { >> 350 >> 351 // create 2 gamma >> 352 >> 353 nSecondaries += 2; >> 354 G4double e1 = ( dif_4p.e() -dif_4p.v().mag() ) / 2; >> 355 >> 356 if ( minimum_energy < e1 ) >> 357 { >> 358 G4double costh = 2.*G4UniformRand()-1.; >> 359 G4double phi = twopi*G4UniformRand(); >> 360 G4ThreeVector dir( std::sin(std::acos(costh))*std::cos(phi), >> 361 std::sin(std::acos(costh))*std::sin(phi), >> 362 costh); >> 363 theResult.Get()->AddSecondary ( new G4DynamicParticle ( G4Gamma::Gamma() , e1*dir ) ); >> 364 theResult.Get()->AddSecondary ( new G4DynamicParticle ( G4Gamma::Gamma() , -e1*dir ) ); >> 365 } >> 366 else >> 367 { >> 368 //G4cout << "HP_DB Difference is too small(<1keV) to adjust, so that neglect it" << G4endl; >> 369 } >> 370 >> 371 } >> 372 else //dif_e < 0 >> 373 { >> 374 >> 375 // At first reduce KE of the fastest secondary; >> 376 G4double ke0 = theResult.Get()->GetSecondary( ifast )->GetParticle()->GetKineticEnergy(); >> 377 G4ThreeVector p0 = theResult.Get()->GetSecondary( ifast )->GetParticle()->GetMomentum(); >> 378 G4ThreeVector dir = ( theResult.Get()->GetSecondary( ifast )->GetParticle()->GetMomentum() ).unit(); >> 379 >> 380 //G4cout << "HP_DB ifast " << ifast << " ke0 " << ke0 << G4endl; >> 381 >> 382 if ( ke0 + dif_e > 0 ) >> 383 { >> 384 theResult.Get()->GetSecondary( ifast )->GetParticle()->SetKineticEnergy( ke0 + dif_e ); >> 385 G4ThreeVector dp = p0 - theResult.Get()->GetSecondary( ifast )->GetParticle()->GetMomentum(); >> 386 >> 387 G4ThreeVector p = theResult.Get()->GetSecondary( islow )->GetParticle()->GetMomentum(); >> 388 //theResult.GetSecondary( islow )->GetParticle()->SetMomentum( p - dif_e*dir ); >> 389 theResult.Get()->GetSecondary( islow )->GetParticle()->SetMomentum( p + dp ); >> 390 } >> 391 else >> 392 { >> 393 //G4cout << "HP_DB Difference in dif_e too large ( <0MeV ) to adjust, so that give up tuning" << G4endl; >> 394 } >> 395 >> 396 } 271 397 272 G4LorentzVector p4(0); << 273 if (ires == -1) { << 274 // Create and Add Residual Nucleus << 275 ires = nSecondaries; << 276 nSecondaries += 1; << 277 << 278 auto res = new G4DynamicParticle(resi_pd, << 279 theResult.Get()->AddSecondary(res, secID); << 280 << 281 p4 = res->Get4Momentum(); << 282 if (slow > p4.beta()) { << 283 slow = p4.beta(); << 284 islow = ires; << 285 } << 286 dif_4p = init_4p_lab - (secs_4p_lab + p4); << 287 } << 288 << 289 if (needOneMoreSec && oneMoreSec_pd != nullp << 290 // << 291 // fca: this is not a fix, this is a crash a << 292 // fca: the baryon number is still wrong, mo << 293 // fca: should have been decreased, but sinc << 294 // fca: we just do not add it << 295 // << 296 { << 297 nSecondaries += 1; << 298 auto one = new G4DynamicParticle(oneMoreSe << 299 theResult.Get()->AddSecondary(one, secID); << 300 p4 = one->Get4Momentum(); << 301 if (slow > p4.beta()) { << 302 slow = p4.beta(); << 303 islow = nSecondaries - 1; // Because th << 304 } << 305 dif_4p = init_4p_lab - (secs_4p_lab + p4); << 306 } << 307 << 308 // Which is bigger dif_p or dif_e << 309 << 310 if (dif_4p.v().mag() < std::abs(dif_4p.e())) << 311 // Adjust p << 312 if (minimum_energy < dif_4p.v().mag() && d << 313 nSecondaries += 1; << 314 theResult.Get()->AddSecondary(new G4Dyna << 315 } << 316 } << 317 else { << 318 // dif_p > dif_e << 319 // at first momentum << 320 // Move residual momentum << 321 p4 = theResult.Get()->GetSecondary(ires)-> << 322 theResult.Get()->GetSecondary(ires)->GetPa << 323 dif_4p = init_4p_lab - << 324 (secs_4p_lab - p4 + theResult.Get()->Get << 325 } << 326 << 327 G4double dif_e = dif_4p.e() - (dif_4p.v()).m << 328 << 329 if (dif_e > 0) { << 330 // create 2 gamma << 331 << 332 nSecondaries += 2; << 333 G4double e1 = (dif_4p.e() - dif_4p.v().mag << 334 << 335 if (minimum_energy < e1) { << 336 G4ThreeVector dir = G4RandomDirection(); << 337 theResult.Get()->AddSecondary(new G4Dyna << 338 theResult.Get()->AddSecondary(new G4Dyna << 339 } << 340 } << 341 else // dif_e < 0 << 342 { << 343 // At first reduce KE of the fastest secon << 344 auto ptr = theResult.Get()->GetSecondary(i << 345 G4double ke0 = ptr->GetKineticEnergy(); << 346 G4ThreeVector p0 = ptr->GetMomentum(); << 347 G4ThreeVector dir = p0.unit(); << 348 << 349 if (ke0 + dif_e > 0) { << 350 ptr->SetKineticEnergy(ke0 + dif_e); << 351 G4ThreeVector dp = p0 - theResult.Get()- << 352 G4ThreeVector p = theResult.Get()->GetSe << 353 theResult.Get()->GetSecondary(islow)->Ge << 354 } << 355 } << 356 } 398 } >> 399 357 400