Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/de_excitation/multifragmentation/src/G4StatMF.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 //
 27 //
 28 // Hadronic Process: Nuclear De-excitations
 29 // by V. Lara
 30 
 31 #include "G4StatMF.hh"
 32 #include "G4PhysicalConstants.hh"
 33 #include "G4SystemOfUnits.hh"
 34 #include "G4Pow.hh"
 35 #include "G4PhysicsModelCatalog.hh"
 36 
 37 G4StatMF::G4StatMF()
 38 {
 39   _secID = G4PhysicsModelCatalog::GetModelID("model_G4StatMF");
 40 }
 41 
 42 G4StatMF::~G4StatMF() {}
 43 
 44 G4FragmentVector* G4StatMF::BreakItUp(const G4Fragment &theFragment)
 45 {
 46   if (theFragment.GetExcitationEnergy() <= 0.0) {
 47     return nullptr;
 48   }
 49 
 50   // Maximun average multiplicity: M_0 = 2.6 for A ~ 200 
 51   // and M_0 = 3.3 for A <= 110
 52   G4double MaxAverageMultiplicity = 
 53     G4StatMFParameters::GetMaxAverageMultiplicity(theFragment.GetA_asInt());
 54 
 55   
 56     // We'll use two kinds of ensembles
 57   G4StatMFMicroCanonical * theMicrocanonicalEnsemble = 0;
 58   G4StatMFMacroCanonical * theMacrocanonicalEnsemble = 0;
 59   
 60   //-------------------------------------------------------
 61   // Direct simulation part (Microcanonical ensemble)
 62   //-------------------------------------------------------
 63   
 64   // Microcanonical ensemble initialization 
 65   theMicrocanonicalEnsemble = new G4StatMFMicroCanonical(theFragment);
 66 
 67   G4int Iterations = 0;
 68   G4int IterationsLimit = 100000;
 69   G4double Temperature = 0.0;
 70   
 71   G4bool FirstTime = true;
 72   G4StatMFChannel * theChannel = 0;
 73  
 74   G4bool ChannelOk;
 75   do {  // Try to de-excite as much as IterationLimit permits
 76     do {
 77       
 78       G4double theMeanMult = theMicrocanonicalEnsemble->GetMeanMultiplicity();
 79       if (theMeanMult <= MaxAverageMultiplicity) {
 80   // G4cout << "MICROCANONICAL" << G4endl;
 81   // Choose fragments atomic numbers and charges from direct simulation
 82   theChannel = theMicrocanonicalEnsemble->ChooseAandZ(theFragment);
 83   _theEnsemble = theMicrocanonicalEnsemble;
 84       } else {
 85   //-----------------------------------------------------
 86   // Non direct simulation part (Macrocanonical Ensemble)
 87   //-----------------------------------------------------
 88   if (FirstTime) {
 89     // Macrocanonical ensemble initialization 
 90     theMacrocanonicalEnsemble = new G4StatMFMacroCanonical(theFragment);
 91     _theEnsemble = theMacrocanonicalEnsemble;
 92     FirstTime = false;
 93   }
 94   // G4cout << "MACROCANONICAL" << G4endl;
 95   // Select calculated fragment total multiplicity, 
 96   // fragment atomic numbers and fragment charges.
 97   theChannel = theMacrocanonicalEnsemble->ChooseAandZ(theFragment);
 98       }
 99       
100       ChannelOk = theChannel->CheckFragments();
101       if (!ChannelOk) delete theChannel; 
102       
103       // Loop checking, 05-Aug-2015, Vladimir Ivanchenko
104     } while (!ChannelOk);
105     
106     
107     if (theChannel->GetMultiplicity() <= 1) {
108       G4FragmentVector * theResult = new G4FragmentVector;
109       theResult->push_back(new G4Fragment(theFragment));
110       delete theMicrocanonicalEnsemble;
111       if (theMacrocanonicalEnsemble != 0) delete theMacrocanonicalEnsemble;
112       delete theChannel;
113       return theResult;
114     }
115     
116     //--------------------------------------
117     // Second part of simulation procedure.
118     //--------------------------------------
119     
120     // Find temperature of breaking channel.
121     Temperature = _theEnsemble->GetMeanTemperature(); // Initial guess for Temperature 
122  
123     if (FindTemperatureOfBreakingChannel(theFragment,theChannel,Temperature)) break;
124  
125     // Do not forget to delete this unusable channel, for which we failed to find the temperature,
126     // otherwise for very proton-reach nuclei it would lead to memory leak due to large 
127     // number of iterations. N.B. "theChannel" is created in G4StatMFMacroCanonical::ChooseZ()
128 
129     // G4cout << " Iteration # " << Iterations << " Mean Temperature = " << Temperature << G4endl;    
130 
131     delete theChannel;    
132 
133     // Loop checking, 05-Aug-2015, Vladimir Ivanchenko
134   } while (Iterations++ < IterationsLimit );
135 
136   // If Iterations >= IterationsLimit means that we couldn't solve for temperature
137   if (Iterations >= IterationsLimit) 
138     throw G4HadronicException(__FILE__, __LINE__, "G4StatMF::BreakItUp: Was not possible to solve for temperature of breaking channel");
139 
140   G4FragmentVector * theResult = theChannel->
141     GetFragments(theFragment.GetA_asInt(),theFragment.GetZ_asInt(),Temperature);
142     
143   // ~~~~~~ Energy conservation Patch !!!!!!!!!!!!!!!!!!!!!!
144   // Original nucleus 4-momentum in CM system
145   G4LorentzVector InitialMomentum(theFragment.GetMomentum());
146   InitialMomentum.boost(-InitialMomentum.boostVector());
147   G4double ScaleFactor = 0.0;
148   G4double SavedScaleFactor = 0.0;
149   do {
150     G4double FragmentsEnergy = 0.0;
151     for (auto const & ptr : *theResult) {
152       FragmentsEnergy += ptr->GetMomentum().e();
153     }
154     if (0.0 == FragmentsEnergy) { break; } 
155     SavedScaleFactor = ScaleFactor;
156     ScaleFactor = InitialMomentum.e()/FragmentsEnergy;
157     G4ThreeVector ScaledMomentum(0.0,0.0,0.0);
158     for (auto const & ptr : *theResult) {
159       ScaledMomentum = ScaleFactor * ptr->GetMomentum().vect();
160       G4double Mass = ptr->GetMomentum().mag();
161       G4LorentzVector NewMomentum;
162       NewMomentum.setVect(ScaledMomentum);
163       NewMomentum.setE(std::sqrt(ScaledMomentum.mag2()+Mass*Mass));
164       ptr->SetMomentum(NewMomentum);    
165     }
166     // Loop checking, 05-Aug-2015, Vladimir Ivanchenko
167   } while (ScaleFactor > 1.0+1.e-5 && std::abs(ScaleFactor-SavedScaleFactor)/ScaleFactor > 1.e-10);
168   // ~~~~~~ End of patch !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
169   
170   // Perform Lorentz boost
171   G4FragmentVector::iterator i;
172   for (i = theResult->begin(); i != theResult->end(); i++) {
173     G4LorentzVector FourMom = (*i)->GetMomentum();
174     FourMom.boost(theFragment.GetMomentum().boostVector());
175     (*i)->SetMomentum(FourMom);
176     (*i)->SetCreatorModelID(_secID);
177   }
178   
179   // garbage collection
180   delete theMicrocanonicalEnsemble;
181   if (theMacrocanonicalEnsemble != 0) delete theMacrocanonicalEnsemble;
182   delete theChannel;
183   
184   return theResult;
185 }
186 
187 
188 G4bool G4StatMF::FindTemperatureOfBreakingChannel(const G4Fragment & theFragment,
189               const G4StatMFChannel * aChannel,
190               G4double & Temperature)
191   // This finds temperature of breaking channel.
192 {
193   G4int A = theFragment.GetA_asInt();
194   G4int Z = theFragment.GetZ_asInt();
195   G4double U = theFragment.GetExcitationEnergy();
196   
197   G4double T = std::max(Temperature,0.0012*MeV);  
198   G4double Ta = T;
199   G4double TotalEnergy = CalcEnergy(A,Z,aChannel,T);
200   
201   G4double Da = (U - TotalEnergy)/U;
202   G4double Db = 0.0;
203   
204   // bracketing the solution
205   if (Da == 0.0) {
206     Temperature = T;
207     return true;
208   } else if (Da < 0.0) {
209     do {
210       T *= 0.5;
211       if (T < 0.001*MeV) return false;
212       
213       TotalEnergy = CalcEnergy(A,Z,aChannel,T);
214       
215       Db = (U - TotalEnergy)/U;
216       // Loop checking, 05-Aug-2015, Vladimir Ivanchenko
217     } while (Db < 0.0);
218     
219   } else {
220     do {
221       T *= 1.5;
222       
223       TotalEnergy = CalcEnergy(A,Z,aChannel,T);
224       
225       Db = (U - TotalEnergy)/U;
226       // Loop checking, 05-Aug-2015, Vladimir Ivanchenko
227     } while (Db > 0.0); 
228   }
229   
230   G4double eps = 1.0e-14 * std::abs(T-Ta);
231   //G4double eps = 1.0e-3 ;
232   
233   // Start the bisection method
234   for (G4int j = 0; j < 1000; j++) {
235     G4double Tc =  (Ta+T)*0.5;
236     if (std::abs(Ta-Tc) <= eps) {
237       Temperature = Tc;
238       return true;
239     }
240     
241     T = Tc;    
242     TotalEnergy = CalcEnergy(A,Z,aChannel,T);
243     G4double Dc = (U - TotalEnergy)/U; 
244     
245     if (Dc == 0.0) {
246       Temperature  = Tc;
247       return true;
248     }
249     if (Da*Dc < 0.0) {
250       T  = Tc;
251       Db = Dc;
252     } else {
253       Ta = Tc;
254       Da = Dc;
255     }
256   }
257   
258   Temperature  = (Ta+T)*0.5;
259   return false;
260 }
261 
262 G4double G4StatMF::CalcEnergy(G4int A, G4int Z, const G4StatMFChannel * aChannel,
263             G4double T)
264 {
265   G4double MassExcess0 = G4NucleiProperties::GetMassExcess(A,Z);
266   G4double ChannelEnergy = aChannel->GetFragmentsEnergy(T);
267   return -MassExcess0 + G4StatMFParameters::GetCoulomb() + ChannelEnergy;
268 }
269 
270 
271 
272