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 // neutron_hp -- source file 26 // neutron_hp -- source file 27 // J.P. Wellisch, Nov-1996 27 // J.P. Wellisch, Nov-1996 28 // A prototype of the low energy neutron trans 28 // A prototype of the low energy neutron transport model. 29 // 29 // 30 // 25-08-06 New Final State type (refFlag==3 , << 30 // 25-08-06 New Final State type (refFlag==3 , Legendre (Low Energy) + Probability (High Energy) ) 31 // is added by T. KOI 31 // is added by T. KOI 32 // 080904 Add Protection for negative energy r << 32 // 080904 Add Protection for negative energy results in very low energy ( 1E-6 eV ) scattering by T. Koi 33 // Koi << 34 // 33 // 35 // P. Arce, June-2014 Conversion neutron_hp to 34 // P. Arce, June-2014 Conversion neutron_hp to particle_hp 36 // 35 // 37 #include "G4ParticleHPElasticFS.hh" 36 #include "G4ParticleHPElasticFS.hh" >> 37 #include "G4ParticleHPManager.hh" 38 38 39 #include "G4Alpha.hh" << 39 #include "G4PhysicalConstants.hh" >> 40 #include "G4SystemOfUnits.hh" >> 41 #include "G4ReactionProduct.hh" >> 42 #include "G4Nucleus.hh" >> 43 #include "G4Proton.hh" 40 #include "G4Deuteron.hh" 44 #include "G4Deuteron.hh" 41 #include "G4HadronicParameters.hh" << 45 #include "G4Triton.hh" 42 #include "G4IonTable.hh" << 46 #include "G4Alpha.hh" >> 47 #include "G4ThreeVector.hh" 43 #include "G4LorentzVector.hh" 48 #include "G4LorentzVector.hh" 44 #include "G4Nucleus.hh" << 49 #include "G4IonTable.hh" 45 #include "G4ParticleHPDataUsed.hh" 50 #include "G4ParticleHPDataUsed.hh" 46 #include "G4ParticleHPManager.hh" << 47 #include "G4PhysicalConstants.hh" << 48 #include "G4PhysicsModelCatalog.hh" << 49 #include "G4Pow.hh" 51 #include "G4Pow.hh" 50 #include "G4Proton.hh" << 51 #include "G4ReactionProduct.hh" << 52 #include "G4SystemOfUnits.hh" << 53 #include "G4ThreeVector.hh" << 54 #include "G4Triton.hh" << 55 << 56 #include "zlib.h" 52 #include "zlib.h" 57 53 58 G4ParticleHPElasticFS::G4ParticleHPElasticFS() << 59 { << 60 svtEmax = 0.0; << 61 dbrcEmax = 0.0; << 62 dbrcEmin = 0.0; << 63 dbrcAmin = 0.0; << 64 dbrcUse = false; << 65 xsForDBRC = nullptr; << 66 << 67 secID = G4PhysicsModelCatalog::GetModelID("m << 68 << 69 hasXsec = false; << 70 theCoefficients = nullptr; << 71 theProbArray = nullptr; << 72 << 73 repFlag = 0; << 74 tE_of_repFlag3 = 0.0; << 75 targetMass = 0.0; << 76 frameFlag = 0; << 77 } << 78 << 79 void G4ParticleHPElasticFS::Init(G4double A, G 54 void G4ParticleHPElasticFS::Init(G4double A, G4double Z, G4int M, 80 const G4Strin << 55 G4String& dirName, G4String&, 81 G4ParticleDef << 56 G4ParticleDefinition* ) 82 { 57 { 83 G4String tString = "/FS"; 58 G4String tString = "/FS"; 84 G4bool dbool = true; << 59 G4bool dbool; 85 SetA_Z(A, Z, M); << 60 G4ParticleHPDataUsed aFile = 86 const G4ParticleHPDataUsed& aFile = << 61 theNames.GetName(static_cast<G4int>(A), static_cast<G4int>(Z), M, dirName, tString, dbool); 87 theNames.GetName(theBaseA, theBaseZ, M, di << 62 G4String filename = aFile.GetName(); 88 const G4String& filename = aFile.GetName(); << 63 SetAZMs( A, Z, M, aFile ); 89 SetAZMs(aFile); << 64 //theBaseA = aFile.GetA(); >> 65 //theBaseZ = aFile.GetZ(); 90 if (!dbool) { 66 if (!dbool) { 91 hasAnyData = false; 67 hasAnyData = false; 92 hasFSData = false; << 68 hasFSData = false; 93 hasXsec = false; 69 hasXsec = false; 94 return; 70 return; 95 } 71 } 96 72 97 // 130205 For compressed data files << 73 //130205 For compressed data files 98 std::istringstream theData(std::ios::in); 74 std::istringstream theData(std::ios::in); 99 G4ParticleHPManager::GetInstance()->GetDataS << 75 G4ParticleHPManager::GetInstance()->GetDataStream(filename,theData); 100 // 130205 END << 76 //130205 END 101 theData >> repFlag >> targetMass >> frameFla 77 theData >> repFlag >> targetMass >> frameFlag; 102 78 103 if (repFlag == 1) { 79 if (repFlag == 1) { 104 G4int nEnergy; 80 G4int nEnergy; 105 theData >> nEnergy; << 81 theData >> nEnergy; 106 theCoefficients = new G4ParticleHPLegendre 82 theCoefficients = new G4ParticleHPLegendreStore(nEnergy); 107 theCoefficients->InitInterpolation(theData 83 theCoefficients->InitInterpolation(theData); 108 G4double temp, energy; 84 G4double temp, energy; 109 G4int tempdep, nLegendre; 85 G4int tempdep, nLegendre; 110 G4int i, ii; 86 G4int i, ii; 111 for (i = 0; i < nEnergy; i++) { << 87 for (i=0; i < nEnergy; i++) { 112 theData >> temp >> energy >> tempdep >> 88 theData >> temp >> energy >> tempdep >> nLegendre; 113 energy *= eV; << 89 energy *=eV; 114 theCoefficients->Init(i, energy, nLegend 90 theCoefficients->Init(i, energy, nLegendre); 115 theCoefficients->SetTemperature(i, temp) 91 theCoefficients->SetTemperature(i, temp); 116 G4double coeff = 0; 92 G4double coeff = 0; 117 for (ii = 0; ii < nLegendre; ii++) { 93 for (ii = 0; ii < nLegendre; ii++) { 118 // load legendre coefficients. 94 // load legendre coefficients. 119 theData >> coeff; 95 theData >> coeff; 120 theCoefficients->SetCoeff(i, ii + 1, c << 96 theCoefficients->SetCoeff(i, ii+1, coeff); // @@@HPW@@@ 121 } 97 } 122 } 98 } 123 } << 99 124 else if (repFlag == 2) { << 100 } else if (repFlag == 2) { 125 G4int nEnergy; 101 G4int nEnergy; 126 theData >> nEnergy; 102 theData >> nEnergy; 127 theProbArray = new G4ParticleHPPartial(nEn 103 theProbArray = new G4ParticleHPPartial(nEnergy, nEnergy); 128 theProbArray->InitInterpolation(theData); 104 theProbArray->InitInterpolation(theData); 129 G4double temp, energy; 105 G4double temp, energy; 130 G4int tempdep, nPoints; 106 G4int tempdep, nPoints; 131 for (G4int i = 0; i < nEnergy; i++) { 107 for (G4int i = 0; i < nEnergy; i++) { 132 theData >> temp >> energy >> tempdep >> 108 theData >> temp >> energy >> tempdep >> nPoints; 133 energy *= eV; 109 energy *= eV; 134 theProbArray->InitInterpolation(i, theDa 110 theProbArray->InitInterpolation(i, theData); 135 theProbArray->SetT(i, temp); 111 theProbArray->SetT(i, temp); 136 theProbArray->SetX(i, energy); 112 theProbArray->SetX(i, energy); 137 G4double prob, costh; 113 G4double prob, costh; 138 for (G4int ii = 0; ii < nPoints; ii++) { 114 for (G4int ii = 0; ii < nPoints; ii++) { 139 // fill probability arrays. 115 // fill probability arrays. 140 theData >> costh >> prob; 116 theData >> costh >> prob; 141 theProbArray->SetX(i, ii, costh); 117 theProbArray->SetX(i, ii, costh); 142 theProbArray->SetY(i, ii, prob); 118 theProbArray->SetY(i, ii, prob); 143 } 119 } 144 theProbArray->DoneSetXY(i); << 120 theProbArray->DoneSetXY( i ); 145 } 121 } 146 } << 122 147 else if (repFlag == 3) { << 123 } else if (repFlag == 3) { 148 G4int nEnergy_Legendre; 124 G4int nEnergy_Legendre; 149 theData >> nEnergy_Legendre; << 125 theData >> nEnergy_Legendre; 150 if (nEnergy_Legendre <= 0) { << 126 if (nEnergy_Legendre <= 0 ) { 151 std::stringstream iss; 127 std::stringstream iss; 152 iss << "G4ParticleHPElasticFS::Init Data 128 iss << "G4ParticleHPElasticFS::Init Data Error repFlag is 3 but nEnergy_Legendre <= 0"; 153 iss << "Z, A and M of problematic file i << 129 iss << "Z, A and M of problematic file is " << theNDLDataZ << ", " 154 << theNDLDataM << " respectively."; << 130 << theNDLDataA << " and " << theNDLDataM << " respectively."; 155 throw G4HadronicException(__FILE__, __LI << 131 throw G4HadronicException(__FILE__, __LINE__, iss.str() ); 156 } 132 } 157 theCoefficients = new G4ParticleHPLegendre << 133 theCoefficients = new G4ParticleHPLegendreStore( nEnergy_Legendre ); 158 theCoefficients->InitInterpolation(theData << 134 theCoefficients->InitInterpolation( theData ); 159 G4double temp, energy; 135 G4double temp, energy; 160 G4int tempdep, nLegendre; 136 G4int tempdep, nLegendre; 161 137 162 for (G4int i = 0; i < nEnergy_Legendre; i+ 138 for (G4int i = 0; i < nEnergy_Legendre; i++) { 163 theData >> temp >> energy >> tempdep >> 139 theData >> temp >> energy >> tempdep >> nLegendre; 164 energy *= eV; << 140 energy *=eV; 165 theCoefficients->Init(i, energy, nLegend << 141 theCoefficients->Init( i , energy , nLegendre ); 166 theCoefficients->SetTemperature(i, temp) << 142 theCoefficients->SetTemperature( i , temp ); 167 G4double coeff = 0; 143 G4double coeff = 0; 168 for (G4int ii = 0; ii < nLegendre; ii++) 144 for (G4int ii = 0; ii < nLegendre; ii++) { 169 // load legendre coefficients. 145 // load legendre coefficients. 170 theData >> coeff; 146 theData >> coeff; 171 theCoefficients->SetCoeff(i, ii + 1, c << 147 theCoefficients->SetCoeff(i, ii+1, coeff); // @@@HPW@@@ 172 } 148 } 173 } << 149 } 174 150 175 tE_of_repFlag3 = energy; << 151 tE_of_repFlag3 = energy; 176 152 177 G4int nEnergy_Prob; 153 G4int nEnergy_Prob; 178 theData >> nEnergy_Prob; 154 theData >> nEnergy_Prob; 179 theProbArray = new G4ParticleHPPartial(nEn << 155 theProbArray = new G4ParticleHPPartial( nEnergy_Prob , nEnergy_Prob ); 180 theProbArray->InitInterpolation(theData); << 156 theProbArray->InitInterpolation( theData ); 181 G4int nPoints; 157 G4int nPoints; 182 for (G4int i = 0; i < nEnergy_Prob; i++) { 158 for (G4int i = 0; i < nEnergy_Prob; i++) { 183 theData >> temp >> energy >> tempdep >> 159 theData >> temp >> energy >> tempdep >> nPoints; 184 energy *= eV; 160 energy *= eV; 185 161 186 // consistency check 162 // consistency check 187 if (i == 0) 163 if (i == 0) 188 // if ( energy != tE_of_repFlag3 ) //1 << 164 //if ( energy != tE_of_repFlag3 ) //110620TK This is too tight for 32bit machines 189 if (std::abs(energy - tE_of_repFlag3) 165 if (std::abs(energy - tE_of_repFlag3) / tE_of_repFlag3 > 1.0e-15) 190 G4cout << "Warning Transition Energy << 166 G4cout << "Warning Transition Energy of repFlag3 is not consistent." << G4endl; 191 167 192 theProbArray->InitInterpolation(i, theDa << 168 theProbArray->InitInterpolation( i , theData ); 193 theProbArray->SetT(i, temp); << 169 theProbArray->SetT( i , temp ); 194 theProbArray->SetX(i, energy); << 170 theProbArray->SetX( i , energy ); 195 G4double prob, costh; 171 G4double prob, costh; 196 for (G4int ii = 0; ii < nPoints; ii++) { 172 for (G4int ii = 0; ii < nPoints; ii++) { 197 // fill probability arrays. 173 // fill probability arrays. 198 theData >> costh >> prob; 174 theData >> costh >> prob; 199 theProbArray->SetX(i, ii, costh); << 175 theProbArray->SetX( i , ii , costh ); 200 theProbArray->SetY(i, ii, prob); << 176 theProbArray->SetY( i , ii , prob ); 201 } 177 } 202 theProbArray->DoneSetXY(i); << 178 theProbArray->DoneSetXY( i ); 203 } 179 } >> 180 >> 181 } else if (repFlag==0) { >> 182 theData >> frameFlag; >> 183 >> 184 } else { >> 185 G4cout << "unusable number for repFlag: repFlag="<<repFlag<<G4endl; >> 186 throw G4HadronicException(__FILE__, __LINE__, "G4ParticleHPElasticFS::Init -- unusable number for repFlag"); 204 } 187 } 205 else if (repFlag == 0) { << 188 //130205 For compressed data files(theData changed from ifstream to istringstream) 206 theData >> frameFlag; << 189 //theData.close(); 207 } << 208 else { << 209 G4cout << "unusable number for repFlag: re << 210 throw G4HadronicException(__FILE__, __LINE << 211 "G4ParticleHPEla << 212 } << 213 // 130205 For compressed data files(theData << 214 // theData.close(); << 215 } 190 } 216 191 217 G4HadFinalState* G4ParticleHPElasticFS::ApplyY << 192 218 { << 193 G4HadFinalState* 219 if (theResult.Get() == nullptr) theResult.Pu << 194 G4ParticleHPElasticFS::ApplyYourself(const G4HadProjectile& theTrack) >> 195 { >> 196 if (theResult.Get() == NULL) theResult.Put(new G4HadFinalState); 220 theResult.Get()->Clear(); 197 theResult.Get()->Clear(); 221 G4double eKinetic = theTrack.GetKineticEnerg 198 G4double eKinetic = theTrack.GetKineticEnergy(); 222 const G4HadProjectile* incidentParticle = &t << 199 const G4HadProjectile *incidentParticle = &theTrack; 223 G4ReactionProduct theNeutron( << 200 G4ReactionProduct theNeutron(const_cast<G4ParticleDefinition*>(incidentParticle->GetDefinition() )); 224 const_cast<G4ParticleDefinition*>(incident << 201 theNeutron.SetMomentum(incidentParticle->Get4Momentum().vect() ); 225 theNeutron.SetMomentum(incidentParticle->Get << 226 theNeutron.SetKineticEnergy(eKinetic); 202 theNeutron.SetKineticEnergy(eKinetic); 227 203 >> 204 G4ReactionProduct theTarget; >> 205 G4Nucleus aNucleus; 228 G4ThreeVector neuVelo = 206 G4ThreeVector neuVelo = 229 (1. / incidentParticle->GetDefinition()->G << 207 (1./incidentParticle->GetDefinition()->GetPDGMass())*theNeutron.GetMomentum(); 230 G4ReactionProduct theTarget = << 208 theTarget = 231 GetBiasedThermalNucleus(targetMass, neuVel << 209 aNucleus.GetBiasedThermalNucleus(targetMass, neuVelo, theTrack.GetMaterial()->GetTemperature()); 232 210 233 // Neutron and target defined as G4ReactionP 211 // Neutron and target defined as G4ReactionProducts 234 // Prepare Lorentz transformation to lab 212 // Prepare Lorentz transformation to lab 235 213 236 G4ThreeVector the3Neutron = theNeutron.GetMo 214 G4ThreeVector the3Neutron = theNeutron.GetMomentum(); 237 G4double nEnergy = theNeutron.GetTotalEnergy 215 G4double nEnergy = theNeutron.GetTotalEnergy(); 238 G4ThreeVector the3Target = theTarget.GetMome 216 G4ThreeVector the3Target = theTarget.GetMomentum(); 239 G4double tEnergy = theTarget.GetTotalEnergy( 217 G4double tEnergy = theTarget.GetTotalEnergy(); 240 G4ReactionProduct theCMS; 218 G4ReactionProduct theCMS; 241 G4double totE = nEnergy + tEnergy; << 219 G4double totE = nEnergy+tEnergy; 242 G4ThreeVector the3CMS = the3Target + the3Neu << 220 G4ThreeVector the3CMS = the3Target+the3Neutron; 243 theCMS.SetMomentum(the3CMS); 221 theCMS.SetMomentum(the3CMS); 244 G4double cmsMom = std::sqrt(the3CMS * the3CM << 222 G4double cmsMom = std::sqrt(the3CMS*the3CMS); 245 G4double sqrts = std::sqrt((totE - cmsMom) * << 223 G4double sqrts = std::sqrt((totE-cmsMom)*(totE+cmsMom)); 246 theCMS.SetMass(sqrts); 224 theCMS.SetMass(sqrts); 247 theCMS.SetTotalEnergy(totE); 225 theCMS.SetTotalEnergy(totE); 248 << 226 249 // Data come as function of n-energy in nucl 227 // Data come as function of n-energy in nuclear rest frame 250 G4ReactionProduct boosted; 228 G4ReactionProduct boosted; 251 boosted.Lorentz(theNeutron, theTarget); 229 boosted.Lorentz(theNeutron, theTarget); 252 eKinetic = boosted.GetKineticEnergy(); // g << 230 eKinetic = boosted.GetKineticEnergy(); // get kinetic energy for scattering 253 G4double cosTh = -2; 231 G4double cosTh = -2; 254 232 255 if (repFlag == 1) { 233 if (repFlag == 1) { 256 cosTh = theCoefficients->SampleElastic(eKi 234 cosTh = theCoefficients->SampleElastic(eKinetic); 257 } << 235 258 else if (repFlag == 2) { << 236 } else if (repFlag == 2) { 259 cosTh = theProbArray->Sample(eKinetic); 237 cosTh = theProbArray->Sample(eKinetic); 260 } << 238 261 else if (repFlag == 3) { << 239 } else if (repFlag == 3) { 262 if (eKinetic <= tE_of_repFlag3) { 240 if (eKinetic <= tE_of_repFlag3) { 263 cosTh = theCoefficients->SampleElastic(e 241 cosTh = theCoefficients->SampleElastic(eKinetic); 264 } << 242 } else { 265 else { << 266 cosTh = theProbArray->Sample(eKinetic); 243 cosTh = theProbArray->Sample(eKinetic); 267 } 244 } 268 } << 245 269 else if (repFlag == 0) { << 246 } else if (repFlag == 0) { 270 cosTh = 2. * G4UniformRand() - 1.; << 247 cosTh = 2.*G4UniformRand() - 1.; 271 } << 248 272 else { << 249 } else { 273 G4cout << "Unusable number for repFlag: re 250 G4cout << "Unusable number for repFlag: repFlag=" << repFlag << G4endl; 274 throw G4HadronicException(__FILE__, __LINE 251 throw G4HadronicException(__FILE__, __LINE__, 275 "G4ParticleHPEla 252 "G4ParticleHPElasticFS::Init -- unusable number for repFlag"); 276 } 253 } 277 254 278 if (cosTh < -1.1) { << 255 if (cosTh < -1.1) { return 0; } 279 return nullptr; << 280 } << 281 256 282 G4double phi = twopi * G4UniformRand(); << 257 G4double phi = twopi*G4UniformRand(); 283 G4double cosPhi = std::cos(phi); 258 G4double cosPhi = std::cos(phi); 284 G4double sinPhi = std::sin(phi); 259 G4double sinPhi = std::sin(phi); 285 G4double theta = std::acos(cosTh); 260 G4double theta = std::acos(cosTh); 286 G4double sinth = std::sin(theta); 261 G4double sinth = std::sin(theta); 287 262 288 if (frameFlag == 1) { 263 if (frameFlag == 1) { 289 // Projectile scattering values cosTh are << 264 // Projectile scattering values cosTh are in target rest frame 290 // In this frame, do relativistic calculat 265 // In this frame, do relativistic calculation of scattered projectile and 291 // target 4-momenta 266 // target 4-momenta 292 267 293 theNeutron.Lorentz(theNeutron, theTarget); 268 theNeutron.Lorentz(theNeutron, theTarget); 294 G4double mN = theNeutron.GetMass(); 269 G4double mN = theNeutron.GetMass(); 295 G4double Pinit = theNeutron.GetTotalMoment << 270 G4double Pinit = theNeutron.GetTotalMomentum(); // Incident momentum 296 G4double Einit = theNeutron.GetTotalEnergy << 271 G4double Einit = theNeutron.GetTotalEnergy(); // Incident energy 297 G4double mT = theTarget.GetMass(); 272 G4double mT = theTarget.GetMass(); 298 273 299 G4double ratio = mT / mN; << 274 G4double ratio = mT/mN; 300 G4double sqt = std::sqrt(ratio * ratio - 1 << 275 G4double sqt = std::sqrt(ratio*ratio - 1.0 + cosTh*cosTh); 301 G4double beta = Pinit / (mT + Einit); // << 276 G4double beta = Pinit/(mT + Einit); // CMS beta 302 G4double denom = 1. - beta * beta * cosTh << 277 G4double denom = 1. - beta*beta*cosTh*cosTh; 303 G4double term1 = cosTh * (Einit * ratio + << 278 G4double term1 = cosTh*(Einit*ratio + mN)/(mN*ratio + Einit); 304 G4double pN = beta * mN * (term1 + sqt) / << 279 G4double pN = beta*mN*(term1 + sqt)/denom; 305 280 306 // Get the scattered momentum and rotate i 281 // Get the scattered momentum and rotate it in theta and phi 307 G4ThreeVector pDir = theNeutron.GetMomentu << 282 G4ThreeVector pDir = theNeutron.GetMomentum()/Pinit; 308 G4double px = pN * pDir.x(); << 283 G4double px = pN*pDir.x(); 309 G4double py = pN * pDir.y(); << 284 G4double py = pN*pDir.y(); 310 G4double pz = pN * pDir.z(); << 285 G4double pz = pN*pDir.z(); 311 286 312 G4ThreeVector pcmRot; 287 G4ThreeVector pcmRot; 313 pcmRot.setX(px * cosTh * cosPhi - py * sin << 288 pcmRot.setX(px*cosTh*cosPhi - py*sinPhi + pz*sinth*cosPhi); 314 pcmRot.setY(px * cosTh * sinPhi + py * cos << 289 pcmRot.setY(px*cosTh*sinPhi + py*cosPhi + pz*sinth*sinPhi); 315 pcmRot.setZ(-px * sinth + pz * cosTh); << 290 pcmRot.setZ(-px*sinth + pz*cosTh); 316 theNeutron.SetMomentum(pcmRot); 291 theNeutron.SetMomentum(pcmRot); 317 G4double eN = std::sqrt(pN * pN + mN * mN) << 292 G4double eN = std::sqrt(pN*pN + mN*mN); // Scattered neutron energy 318 theNeutron.SetTotalEnergy(eN); 293 theNeutron.SetTotalEnergy(eN); 319 294 320 // Get the scattered target momentum << 295 // Get the scattered target momentum 321 G4ReactionProduct toLab(-1. * theTarget); << 296 G4ReactionProduct toLab(-1.*theTarget); 322 theTarget.SetMomentum(pDir * Pinit - pcmRo << 297 theTarget.SetMomentum(pDir*Pinit - pcmRot); 323 G4double eT = Einit - eN + mT; 298 G4double eT = Einit - eN + mT; 324 theTarget.SetTotalEnergy(eT); 299 theTarget.SetTotalEnergy(eT); 325 300 326 // Now back to lab frame << 301 // Now back to lab frame 327 theNeutron.Lorentz(theNeutron, toLab); 302 theNeutron.Lorentz(theNeutron, toLab); 328 theTarget.Lorentz(theTarget, toLab); 303 theTarget.Lorentz(theTarget, toLab); 329 304 330 // 111005 Protection for not producing 0 k << 305 //111005 Protection for not producing 0 kinetic energy target 331 if (theNeutron.GetKineticEnergy() <= 0) 306 if (theNeutron.GetKineticEnergy() <= 0) 332 theNeutron.SetTotalEnergy(theNeutron.Get << 307 theNeutron.SetTotalEnergy(theNeutron.GetMass()*(1. + G4Pow::GetInstance()->powA(10, -15.65) ) ); 333 * (1. + G4Pow: << 308 if (theTarget.GetKineticEnergy() <= 0) 334 if (theTarget.GetKineticEnergy() <= 0) << 309 theTarget.SetTotalEnergy(theTarget.GetMass()*(1. + G4Pow::GetInstance()->powA(10, -15.65) ) ); 335 theTarget.SetTotalEnergy(theTarget.GetMa << 310 336 } << 311 } else if (frameFlag == 2) { 337 else if (frameFlag == 2) { << 338 // Projectile scattering values cosTh take 312 // Projectile scattering values cosTh taken from center of mass tabulation 339 313 340 G4LorentzVector proj(nEnergy, the3Neutron) 314 G4LorentzVector proj(nEnergy, the3Neutron); 341 G4LorentzVector targ(tEnergy, the3Target); 315 G4LorentzVector targ(tEnergy, the3Target); 342 G4ThreeVector boostToCM = proj.findBoostTo 316 G4ThreeVector boostToCM = proj.findBoostToCM(targ); 343 proj.boost(boostToCM); 317 proj.boost(boostToCM); 344 targ.boost(boostToCM); 318 targ.boost(boostToCM); 345 319 346 // Rotate projectile and target momenta by 320 // Rotate projectile and target momenta by CM scattering angle 347 // Note: at this point collision axis is n << 321 // Note: at this point collision axis is not along z axis, due to 348 // momentum given target nucleus by 322 // momentum given target nucleus by thermal process 349 G4double px = proj.px(); 323 G4double px = proj.px(); 350 G4double py = proj.py(); 324 G4double py = proj.py(); 351 G4double pz = proj.pz(); 325 G4double pz = proj.pz(); 352 326 353 G4ThreeVector pcmRot; 327 G4ThreeVector pcmRot; 354 pcmRot.setX(px * cosTh * cosPhi - py * sin << 328 pcmRot.setX(px*cosTh*cosPhi - py*sinPhi + pz*sinth*cosPhi); 355 pcmRot.setY(px * cosTh * sinPhi + py * cos << 329 pcmRot.setY(px*cosTh*sinPhi + py*cosPhi + pz*sinth*sinPhi); 356 pcmRot.setZ(-px * sinth + pz * cosTh); << 330 pcmRot.setZ(-px*sinth + pz*cosTh); 357 proj.setVect(pcmRot); 331 proj.setVect(pcmRot); 358 targ.setVect(-pcmRot); 332 targ.setVect(-pcmRot); 359 333 360 // Back to lab frame 334 // Back to lab frame 361 proj.boost(-boostToCM); 335 proj.boost(-boostToCM); 362 targ.boost(-boostToCM); 336 targ.boost(-boostToCM); 363 337 364 theNeutron.SetMomentum(proj.vect()); << 338 theNeutron.SetMomentum(proj.vect() ); 365 theNeutron.SetTotalEnergy(proj.e()); << 339 theNeutron.SetTotalEnergy(proj.e() ); 366 340 367 theTarget.SetMomentum(targ.vect()); << 341 theTarget.SetMomentum(targ.vect() ); 368 theTarget.SetTotalEnergy(targ.e()); << 342 theTarget.SetTotalEnergy(targ.e() ); 369 343 370 // 080904 Add Protection for very low ener << 344 //080904 Add Protection for very low energy (1e-6eV) scattering 371 if (theNeutron.GetKineticEnergy() <= 0) { 345 if (theNeutron.GetKineticEnergy() <= 0) { 372 theNeutron.SetTotalEnergy(theNeutron.Get << 346 theNeutron.SetTotalEnergy(theNeutron.GetMass()*(1. + G4Pow::GetInstance()->powA(10, -15.65) ) ); 373 * (1. + G4Pow: << 374 } 347 } 375 348 376 // 080904 Add Protection for very low ener << 349 //080904 Add Protection for very low energy (1e-6eV) scattering 377 if (theTarget.GetKineticEnergy() <= 0) { 350 if (theTarget.GetKineticEnergy() <= 0) { 378 theTarget.SetTotalEnergy(theTarget.GetMa << 351 theTarget.SetTotalEnergy(theTarget.GetMass()*(1. + G4Pow::GetInstance()->powA(10, -15.65) ) ); 379 } 352 } 380 } << 353 381 else { << 354 } else { 382 G4cout << "Value of frameFlag (1=LAB, 2=CM 355 G4cout << "Value of frameFlag (1=LAB, 2=CMS): " << frameFlag; 383 throw G4HadronicException(__FILE__, __LINE 356 throw G4HadronicException(__FILE__, __LINE__, 384 "G4ParticleHPEla << 357 "G4ParticleHPElasticFS::ApplyYourSelf frameflag incorrect"); 385 } 358 } 386 359 387 // Everything is now in the lab frame 360 // Everything is now in the lab frame 388 // Set energy change and momentum change 361 // Set energy change and momentum change 389 theResult.Get()->SetEnergyChange(theNeutron. 362 theResult.Get()->SetEnergyChange(theNeutron.GetKineticEnergy()); 390 theResult.Get()->SetMomentumChange(theNeutro 363 theResult.Get()->SetMomentumChange(theNeutron.GetMomentum().unit()); 391 364 392 // Make recoil a G4DynamicParticle 365 // Make recoil a G4DynamicParticle 393 auto theRecoil = new G4DynamicParticle; << 366 G4DynamicParticle* theRecoil = new G4DynamicParticle; 394 theRecoil->SetDefinition(G4IonTable::GetIonT 367 theRecoil->SetDefinition(G4IonTable::GetIonTable()->GetIon(static_cast<G4int>(theBaseZ), 395 << 368 static_cast<G4int>(theBaseA), 0) ); 396 theRecoil->SetMomentum(theTarget.GetMomentum 369 theRecoil->SetMomentum(theTarget.GetMomentum()); 397 theResult.Get()->AddSecondary(theRecoil, sec << 370 theResult.Get()->AddSecondary(theRecoil); 398 371 399 // Postpone the tracking of the primary neut 372 // Postpone the tracking of the primary neutron 400 theResult.Get()->SetStatusChange(suspend); 373 theResult.Get()->SetStatusChange(suspend); 401 return theResult.Get(); 374 return theResult.Get(); 402 } 375 } 403 376 404 void G4ParticleHPElasticFS::InitializeScatteri << 405 { << 406 // Initialize DBRC variables << 407 svtEmax = G4HadronicParameters::Instance()-> << 408 G4ParticleHPManager* manager = G4ParticleHPM << 409 dbrcUse = manager->GetUseDBRC(); << 410 dbrcEmax = manager->GetMaxEnergyDBRC(); << 411 dbrcEmin = manager->GetMinEnergyDBRC(); << 412 dbrcAmin = manager->GetMinADBRC(); << 413 } << 414 << 415 G4ReactionProduct G4ParticleHPElasticFS::GetBi << 416 << 417 << 418 { << 419 // This new method implements the DBRC (Dopp << 420 // on top of the SVT (Sampling of the Veloci << 421 // The SVT algorithm was written by Loic Thu << 422 // the method G4Nucleus::GetBiasedThermalNuc << 423 // implemented the DBRC algorithm on top of << 424 // While the SVT algorithm is still present << 425 // the DBRC algorithm on top of the SVT one << 426 // order to avoid a cycle dependency between << 427 << 428 InitializeScatteringKernelParameters(); << 429 << 430 // Set threshold for SVT algorithm << 431 G4double E_threshold = svtEmax; << 432 if (svtEmax == -1.) { << 433 // If E_neutron <= 400*kB*T (400 is a comm << 434 // then apply the Sampling ot the Velocity << 435 // else consider the target nucleus being << 436 E_threshold = 400.0 * 8.617333262E-11 * te << 437 } << 438 << 439 // If DBRC is enabled and the nucleus is hea << 440 if (dbrcUse && aMass >= dbrcAmin) { << 441 E_threshold = std::max(svtEmax, dbrcEmax); << 442 } << 443 << 444 G4double E_neutron = 0.5 * aVelocity.mag2() << 445 << 446 G4bool dbrcIsOn = dbrcUse && E_neutron >= db << 447 << 448 G4Nucleus aNucleus; << 449 if (E_neutron > E_threshold || !dbrcIsOn) { << 450 // Apply only the SVT algorithm, not the D << 451 return aNucleus.GetBiasedThermalNucleus(ta << 452 } << 453 << 454 G4ReactionProduct result; << 455 result.SetMass(aMass * G4Neutron::Neutron()- << 456 << 457 // Beta = sqrt(m/2kT) << 458 G4double beta = << 459 std::sqrt(result.GetMass() << 460 / (2. * 8.617333262E-11 * temp)) << 461 << 462 // Neutron speed vn << 463 G4double vN_norm = aVelocity.mag(); << 464 G4double vN_norm2 = vN_norm * vN_norm; << 465 G4double y = beta * vN_norm; << 466 << 467 // Normalize neutron velocity << 468 aVelocity = (1. / vN_norm) * aVelocity; << 469 << 470 // Variables for sampling of target speed an << 471 G4double x2; << 472 G4double randThresholdSVT; << 473 G4double vT_norm, vT_norm2, mu; << 474 G4double acceptThresholdSVT; << 475 G4double vRelativeSpeed; << 476 G4double cdf0 = 2. / (2. + std::sqrt(CLHEP:: << 477 << 478 // DBRC variables << 479 G4double xsRelative = -99.; << 480 G4double randThresholdDBRC = 0.; << 481 // Calculate max cross-section in interval f << 482 G4double eMin = << 483 0.5 * G4Neutron::Neutron()->GetPDGMass() * << 484 G4double eMax = << 485 0.5 * G4Neutron::Neutron()->GetPDGMass() * << 486 G4double xsMax = xsForDBRC->GetMaxY(eMin, eM << 487 << 488 do { << 489 do { << 490 // Sample the target velocity vT in the << 491 if (G4UniformRand() < cdf0) { << 492 // Sample in C45 from https://laws.lan << 493 x2 = -std::log(G4UniformRand() * G4Uni << 494 } << 495 else { << 496 // Sample in C61 from https://laws.lan << 497 G4double ampl = std::cos(CLHEP::pi / 2 << 498 x2 = -std::log(G4UniformRand()) - std: << 499 } << 500 << 501 vT_norm = std::sqrt(x2) / beta; << 502 vT_norm2 = vT_norm * vT_norm; << 503 << 504 // Sample cosine between the incident ne << 505 mu = 2. * G4UniformRand() - 1.; << 506 << 507 // Define acceptance threshold for SVT << 508 vRelativeSpeed = std::sqrt(vN_norm2 + vT << 509 acceptThresholdSVT = vRelativeSpeed / (v << 510 randThresholdSVT = G4UniformRand(); << 511 } while (randThresholdSVT >= acceptThresho << 512 << 513 // Apply DBRC rejection << 514 xsRelative = xsForDBRC->GetXsec(0.5 * G4Ne << 515 * vRelativ << 516 randThresholdDBRC = G4UniformRand(); << 517 << 518 } while (randThresholdDBRC >= xsRelative / x << 519 << 520 aNucleus.DoKinematicsOfThermalNucleus(mu, vT << 521 << 522 return result; << 523 } << 524 377