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 // $Id$ 27 // 28 // 28 // by V. Lara 29 // by V. Lara 29 // ------------------------------------------- 30 // -------------------------------------------------------------------- 30 // 31 // 31 // Modified: 32 // Modified: 32 // 25.07.08 I.Pshenichnov (in collaboration wi 33 // 25.07.08 I.Pshenichnov (in collaboration with Alexander Botvina and Igor 33 // Mishustin (FIAS, Frankfurt, INR, M 34 // Mishustin (FIAS, Frankfurt, INR, Moscow and Kurchatov Institute, 34 // Moscow, pshenich@fias.uni-frankfur 35 // Moscow, pshenich@fias.uni-frankfurt.de) fixed infinite loop for 35 // a fagment with Z=A; fixed memory l 36 // a fagment with Z=A; fixed memory leak 36 37 37 #include "G4StatMFMacroCanonical.hh" 38 #include "G4StatMFMacroCanonical.hh" 38 #include "G4PhysicalConstants.hh" 39 #include "G4PhysicalConstants.hh" 39 #include "G4SystemOfUnits.hh" 40 #include "G4SystemOfUnits.hh" 40 #include "G4Pow.hh" 41 #include "G4Pow.hh" 41 42 42 // constructor 43 // constructor 43 G4StatMFMacroCanonical::G4StatMFMacroCanonical 44 G4StatMFMacroCanonical::G4StatMFMacroCanonical(const G4Fragment & theFragment) 44 { 45 { 45 46 46 // Get memory for clusters 47 // Get memory for clusters 47 _theClusters.push_back(new G4StatMFMacroNucl 48 _theClusters.push_back(new G4StatMFMacroNucleon); // Size 1 48 _theClusters.push_back(new G4StatMFMacroBiNu 49 _theClusters.push_back(new G4StatMFMacroBiNucleon); // Size 2 49 _theClusters.push_back(new G4StatMFMacroTriN 50 _theClusters.push_back(new G4StatMFMacroTriNucleon); // Size 3 50 _theClusters.push_back(new G4StatMFMacroTetr 51 _theClusters.push_back(new G4StatMFMacroTetraNucleon); // Size 4 51 for (G4int i = 4; i < theFragment.GetA_asInt 52 for (G4int i = 4; i < theFragment.GetA_asInt(); i++) 52 _theClusters.push_back(new G4StatMFMacroMu 53 _theClusters.push_back(new G4StatMFMacroMultiNucleon(i+1)); // Size 5 ... A 53 54 54 // Perform class initialization 55 // Perform class initialization 55 Initialize(theFragment); 56 Initialize(theFragment); 56 57 57 } 58 } 58 59 59 // destructor 60 // destructor 60 G4StatMFMacroCanonical::~G4StatMFMacroCanonica 61 G4StatMFMacroCanonical::~G4StatMFMacroCanonical() 61 { 62 { 62 // garbage collection 63 // garbage collection 63 if (!_theClusters.empty()) 64 if (!_theClusters.empty()) 64 { 65 { 65 std::for_each(_theClusters.begin(),_theC 66 std::for_each(_theClusters.begin(),_theClusters.end(),DeleteFragment()); 66 } 67 } 67 } 68 } 68 69 69 // Initialization method 70 // Initialization method 70 void G4StatMFMacroCanonical::Initialize(const 71 void G4StatMFMacroCanonical::Initialize(const G4Fragment & theFragment) 71 { 72 { 72 73 73 G4int A = theFragment.GetA_asInt(); 74 G4int A = theFragment.GetA_asInt(); 74 G4int Z = theFragment.GetZ_asInt(); 75 G4int Z = theFragment.GetZ_asInt(); 75 G4double x = 1.0 - 2.0*Z/G4double(A); 76 G4double x = 1.0 - 2.0*Z/G4double(A); 76 G4Pow* g4calc = G4Pow::GetInstance(); << 77 G4Pow* g4pow = G4Pow::GetInstance(); 77 78 78 // Free Internal energy at T = 0 79 // Free Internal energy at T = 0 79 __FreeInternalE0 = A*( -G4StatMFParameters:: << 80 __FreeInternalE0 = A*( -G4StatMFParameters::GetE0() + // Volume term (for T = 0) 80 G4StatMFParameters::GetGamma0()*x*x) // << 81 G4StatMFParameters::GetGamma0()*x*x) // Symmetry term 81 + G4StatMFParameters::GetBeta0()*g4calc->Z << 82 + 82 0.6*elm_coupling*Z*Z/(G4StatMFParameters:: << 83 G4StatMFParameters::GetBeta0()*g4pow->Z23(A) + // Surface term (for T = 0) 83 g4calc->Z13(A)); << 84 (3.0/5.0)*elm_coupling*Z*Z/(G4StatMFParameters::Getr0()* // Coulomb term >> 85 g4pow->Z13(A)); 84 86 85 CalculateTemperature(theFragment); 87 CalculateTemperature(theFragment); >> 88 86 return; 89 return; 87 } 90 } 88 91 89 void G4StatMFMacroCanonical::CalculateTemperat 92 void G4StatMFMacroCanonical::CalculateTemperature(const G4Fragment & theFragment) 90 { 93 { 91 // Excitation Energy 94 // Excitation Energy 92 G4double U = theFragment.GetExcitationEnergy 95 G4double U = theFragment.GetExcitationEnergy(); 93 96 94 G4int A = theFragment.GetA_asInt(); 97 G4int A = theFragment.GetA_asInt(); 95 G4int Z = theFragment.GetZ_asInt(); 98 G4int Z = theFragment.GetZ_asInt(); 96 99 97 // Fragment Multiplicity 100 // Fragment Multiplicity 98 G4double FragMult = std::max((1.0+(2.31/MeV) 101 G4double FragMult = std::max((1.0+(2.31/MeV)*(U/A - 3.5*MeV))*A/100.0, 2.0); 99 102 >> 103 100 // Parameter Kappa 104 // Parameter Kappa 101 G4Pow* g4calc = G4Pow::GetInstance(); << 105 _Kappa = (1.0+elm_coupling*(std::pow(FragMult,1./3.)-1)/ 102 _Kappa = (1.0+elm_coupling*(g4calc->A13(Frag << 106 (G4StatMFParameters::Getr0()*G4Pow::GetInstance()->Z13(A))); 103 (G4StatMFParameters::Getr0()*g4calc->Z13 << 104 _Kappa = _Kappa*_Kappa*_Kappa - 1.0; 107 _Kappa = _Kappa*_Kappa*_Kappa - 1.0; >> 108 105 109 106 G4StatMFMacroTemperature * theTemp = new 110 G4StatMFMacroTemperature * theTemp = new 107 G4StatMFMacroTemperature(A,Z,U,__FreeInter 111 G4StatMFMacroTemperature(A,Z,U,__FreeInternalE0,_Kappa,&_theClusters); 108 112 109 __MeanTemperature = theTemp->CalcTemperature 113 __MeanTemperature = theTemp->CalcTemperature(); 110 _ChemPotentialNu = theTemp->GetChemicalPoten 114 _ChemPotentialNu = theTemp->GetChemicalPotentialNu(); 111 _ChemPotentialMu = theTemp->GetChemicalPoten 115 _ChemPotentialMu = theTemp->GetChemicalPotentialMu(); 112 __MeanMultiplicity = theTemp->GetMeanMultipl 116 __MeanMultiplicity = theTemp->GetMeanMultiplicity(); 113 __MeanEntropy = theTemp->GetEntropy(); 117 __MeanEntropy = theTemp->GetEntropy(); 114 118 115 delete theTemp; 119 delete theTemp; 116 120 117 return; 121 return; 118 } 122 } 119 123 >> 124 120 // ------------------------------------------- 125 // -------------------------------------------------------------------------- 121 126 122 G4StatMFChannel * G4StatMFMacroCanonical::Choo 127 G4StatMFChannel * G4StatMFMacroCanonical::ChooseAandZ(const G4Fragment &theFragment) 123 // Calculate total fragments multiplicity, fra << 128 // Calculate total fragments multiplicity, fragment atomic numbers and charges 124 { 129 { 125 G4int A = theFragment.GetA_asInt(); 130 G4int A = theFragment.GetA_asInt(); 126 G4int Z = theFragment.GetZ_asInt(); 131 G4int Z = theFragment.GetZ_asInt(); 127 132 128 std::vector<G4int> ANumbers(A); 133 std::vector<G4int> ANumbers(A); 129 134 130 G4double Multiplicity = ChooseA(A,ANumbers); 135 G4double Multiplicity = ChooseA(A,ANumbers); 131 136 132 std::vector<G4int> FragmentsA; 137 std::vector<G4int> FragmentsA; 133 138 134 G4int i = 0; 139 G4int i = 0; 135 for (i = 0; i < A; i++) << 140 for (i = 0; i < A; i++) 136 { << 141 { 137 for (G4int j = 0; j < ANumbers[i]; j++) << 142 for (G4int j = 0; j < ANumbers[i]; j++) FragmentsA.push_back(i+1); 138 } << 143 } 139 << 144 140 // Sort fragments in decreasing order << 145 // Sort fragments in decreasing order 141 G4int im = 0; << 146 G4int im = 0; 142 for (G4int j = 0; j < Multiplicity; j++) << 147 for (G4int j = 0; j < Multiplicity; j++) 143 { << 148 { 144 G4int FragmentsAMax = 0; << 149 G4int FragmentsAMax = 0; 145 im = j; << 150 im = j; 146 for (i = j; i < Multiplicity; i++) << 151 for (i = j; i < Multiplicity; i++) 147 { << 152 { 148 if (FragmentsA[i] <= FragmentsAMax) { cont << 153 if (FragmentsA[i] <= FragmentsAMax) { continue; } 149 else << 154 else 150 { << 155 { 151 im = i; << 156 im = i; 152 FragmentsAMax = FragmentsA[im]; << 157 FragmentsAMax = FragmentsA[im]; 153 } << 158 } 154 } << 159 } 155 if (im != j) << 160 156 { << 161 if (im != j) 157 FragmentsA[im] = FragmentsA[j]; << 162 { 158 FragmentsA[j] = FragmentsAMax; << 163 FragmentsA[im] = FragmentsA[j]; 159 } << 164 FragmentsA[j] = FragmentsAMax; 160 } << 165 } 161 return ChooseZ(Z,FragmentsA); << 166 } >> 167 >> 168 return ChooseZ(Z,FragmentsA); 162 } 169 } 163 170 >> 171 164 G4double G4StatMFMacroCanonical::ChooseA(G4int 172 G4double G4StatMFMacroCanonical::ChooseA(G4int A, std::vector<G4int> & ANumbers) 165 // Determines fragments multiplicities and c 173 // Determines fragments multiplicities and compute total fragment multiplicity 166 { 174 { 167 G4double multiplicity = 0.0; 175 G4double multiplicity = 0.0; 168 G4int i; 176 G4int i; 169 177 170 std::vector<G4double> AcumMultiplicity; 178 std::vector<G4double> AcumMultiplicity; 171 AcumMultiplicity.reserve(A); 179 AcumMultiplicity.reserve(A); 172 180 173 AcumMultiplicity.push_back((*(_theClusters.b 181 AcumMultiplicity.push_back((*(_theClusters.begin()))->GetMeanMultiplicity()); 174 for (std::vector<G4VStatMFMacroCluster*>::it 182 for (std::vector<G4VStatMFMacroCluster*>::iterator it = _theClusters.begin()+1; 175 it != _theClusters.end(); ++it) 183 it != _theClusters.end(); ++it) 176 { 184 { 177 AcumMultiplicity.push_back((*it)->GetMea 185 AcumMultiplicity.push_back((*it)->GetMeanMultiplicity()+AcumMultiplicity.back()); 178 } 186 } 179 187 180 G4int CheckA; 188 G4int CheckA; 181 do { 189 do { 182 CheckA = -1; 190 CheckA = -1; 183 G4int SumA = 0; 191 G4int SumA = 0; 184 G4int ThisOne = 0; 192 G4int ThisOne = 0; 185 multiplicity = 0.0; 193 multiplicity = 0.0; 186 for (i = 0; i < A; i++) ANumbers[i] = 0; 194 for (i = 0; i < A; i++) ANumbers[i] = 0; 187 do { 195 do { 188 G4double RandNumber = G4UniformRand()*__ 196 G4double RandNumber = G4UniformRand()*__MeanMultiplicity; 189 for (i = 0; i < A; i++) { 197 for (i = 0; i < A; i++) { 190 if (RandNumber < AcumMultiplicity[i]) { 198 if (RandNumber < AcumMultiplicity[i]) { 191 ThisOne = i; 199 ThisOne = i; 192 break; 200 break; 193 } 201 } 194 } 202 } 195 multiplicity++; 203 multiplicity++; 196 ANumbers[ThisOne] = ANumbers[ThisOne]+1; 204 ANumbers[ThisOne] = ANumbers[ThisOne]+1; 197 SumA += ThisOne+1; 205 SumA += ThisOne+1; 198 CheckA = A - SumA; 206 CheckA = A - SumA; 199 207 200 // Loop checking, 05-Aug-2015, Vladimir << 201 } while (CheckA > 0); 208 } while (CheckA > 0); 202 209 203 // Loop checking, 05-Aug-2015, Vladimir Iv << 210 } while (CheckA < 0 || std::abs(__MeanMultiplicity - multiplicity) > std::sqrt(__MeanMultiplicity) + 1./2.); 204 } while (CheckA < 0 || std::abs(__MeanMultip << 205 211 206 return multiplicity; 212 return multiplicity; 207 } 213 } 208 214 >> 215 209 G4StatMFChannel * G4StatMFMacroCanonical::Choo 216 G4StatMFChannel * G4StatMFMacroCanonical::ChooseZ(G4int & Z, 210 std::vector<G4int> & FragmentsA) 217 std::vector<G4int> & FragmentsA) 211 // 218 // 212 { 219 { 213 G4Pow* g4calc = G4Pow::GetInstance(); << 220 G4Pow* g4pow = G4Pow::GetInstance(); 214 std::vector<G4int> FragmentsZ; 221 std::vector<G4int> FragmentsZ; 215 222 216 G4int DeltaZ = 0; 223 G4int DeltaZ = 0; 217 G4double CP = G4StatMFParameters::GetCoulom << 224 G4double CP = (3./5.)*(elm_coupling/G4StatMFParameters::Getr0())* 218 G4int multiplicity = (G4int)FragmentsA.size( << 225 (1.0 - 1.0/std::pow(1.0+G4StatMFParameters::GetKappaCoulomb(),1./3.)); 219 226 220 do { << 227 G4int multiplicity = FragmentsA.size(); 221 FragmentsZ.clear(); << 228 222 G4int SumZ = 0; << 229 do 223 for (G4int i = 0; i < multiplicity; ++i) << 230 { 224 { << 231 FragmentsZ.clear(); 225 G4int A = FragmentsA[i]; << 232 G4int SumZ = 0; 226 if (A <= 1) << 233 for (G4int i = 0; i < multiplicity; i++) 227 { << 234 { 228 G4double RandNumber = G4UniformRand(); << 235 G4int A = FragmentsA[i]; 229 if (RandNumber < (*_theClusters.begin()) << 236 if (A <= 1) 230 { << 237 { 231 FragmentsZ.push_back(1); << 238 G4double RandNumber = G4UniformRand(); 232 SumZ += FragmentsZ[i]; << 239 if (RandNumber < (*_theClusters.begin())->GetZARatio()) 233 } << 240 { 234 else FragmentsZ.push_back(0); << 241 FragmentsZ.push_back(1); 235 } << 242 SumZ += FragmentsZ[i]; 236 else << 243 } 237 { << 244 else FragmentsZ.push_back(0); 238 G4double RandZ; << 245 } 239 G4double CC = 8.0*G4StatMFParameters::Ge << 246 else 240 + 2*CP*g4calc->Z23(FragmentsA[i]); << 247 { 241 G4double ZMean; << 248 G4double RandZ; 242 if (FragmentsA[i] > 1 && FragmentsA[i] < << 249 G4double CC = 8.0*G4StatMFParameters::GetGamma0()+2.0*CP*g4pow->Z23(FragmentsA[i]); 243 else { << 250 G4double ZMean; 244 ZMean = FragmentsA[i]*(4.0*G4StatMFPar << 251 if (FragmentsA[i] > 1 && FragmentsA[i] < 5) { ZMean = 0.5*FragmentsA[i]; } 245 + _ChemPotentialNu)/CC; << 252 else ZMean = FragmentsA[i]*(4.0*G4StatMFParameters::GetGamma0()+_ChemPotentialNu)/CC; >> 253 G4double ZDispersion = std::sqrt(FragmentsA[i]*__MeanTemperature/CC); >> 254 G4int z; >> 255 do >> 256 { >> 257 RandZ = G4RandGauss::shoot(ZMean,ZDispersion); >> 258 z = static_cast<G4int>(RandZ+0.5); >> 259 } while (z < 0 || z > A); >> 260 FragmentsZ.push_back(z); >> 261 SumZ += z; 246 } 262 } 247 G4double ZDispersion = std::sqrt(Fragmen << 263 } 248 G4int z; << 264 DeltaZ = Z - SumZ; 249 do << 265 } 250 { << 266 while (std::abs(DeltaZ) > 1); 251 RandZ = G4RandGauss::shoot(ZMean,ZDispersi << 252 z = G4lrint(RandZ+0.5); << 253 // Loop checking, 05-Aug-2015, Vladimir Iv << 254 } while (z < 0 || z > A); << 255 FragmentsZ.push_back(z); << 256 SumZ += z; << 257 } << 258 } << 259 DeltaZ = Z - SumZ; << 260 // Loop checking, 05-Aug-2015, Vladimir Ivan << 261 } while (std::abs(DeltaZ) > 1); << 262 267 263 // DeltaZ can be 0, 1 or -1 268 // DeltaZ can be 0, 1 or -1 264 G4int idx = 0; 269 G4int idx = 0; 265 if (DeltaZ < 0.0) 270 if (DeltaZ < 0.0) 266 { 271 { 267 while (FragmentsZ[idx] < 1) { ++idx; } 272 while (FragmentsZ[idx] < 1) { ++idx; } 268 } 273 } 269 FragmentsZ[idx] += DeltaZ; 274 FragmentsZ[idx] += DeltaZ; 270 275 271 G4StatMFChannel * theChannel = new G4StatMFC 276 G4StatMFChannel * theChannel = new G4StatMFChannel; 272 for (G4int i = multiplicity-1; i >= 0; --i) << 277 for (G4int i = multiplicity-1; i >= 0; i--) 273 { 278 { 274 theChannel->CreateFragment(FragmentsA[i] 279 theChannel->CreateFragment(FragmentsA[i],FragmentsZ[i]); 275 } 280 } 276 281 277 return theChannel; 282 return theChannel; 278 } 283 } 279 284