Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/de_excitation/multifragmentation/src/G4StatMFChannel.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 ]

Diff markup

Differences between /processes/hadronic/models/de_excitation/multifragmentation/src/G4StatMFChannel.cc (Version 11.3.0) and /processes/hadronic/models/de_excitation/multifragmentation/src/G4StatMFChannel.cc (Version 10.0.p3)


  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: G4StatMFChannel.cc 67983 2013-03-13 10:42:03Z gcosmo $
 27 //                                                 28 //
 28 // Hadronic Process: Nuclear De-excitations        29 // Hadronic Process: Nuclear De-excitations
 29 // by V. Lara                                      30 // by V. Lara
 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 semi-infinite loop 
 35                                                    36 
 36 #include <numeric>                                 37 #include <numeric>
 37                                                    38 
 38 #include "G4StatMFChannel.hh"                      39 #include "G4StatMFChannel.hh"
 39 #include "G4PhysicalConstants.hh"                  40 #include "G4PhysicalConstants.hh"
 40 #include "G4HadronicException.hh"                  41 #include "G4HadronicException.hh"
 41 #include "Randomize.hh"                        << 
 42 #include "G4Pow.hh"                                42 #include "G4Pow.hh"
 43 #include "G4Exp.hh"                            <<  43 
 44 #include "G4RandomDirection.hh"                <<  44 class SumCoulombEnergy : public std::binary_function<G4double,G4double,G4double>
                                                   >>  45 {
                                                   >>  46 public:
                                                   >>  47   SumCoulombEnergy() : total(0.0) {}
                                                   >>  48   G4double operator() (G4double& , G4StatMFFragment*& frag)
                                                   >>  49   { 
                                                   >>  50       total += frag->GetCoulombEnergy();
                                                   >>  51       return total;
                                                   >>  52   }
                                                   >>  53     
                                                   >>  54   G4double GetTotal() { return total; }
                                                   >>  55 public:
                                                   >>  56   G4double total;  
                                                   >>  57 };
 45                                                    58 
 46 G4StatMFChannel::G4StatMFChannel() :               59 G4StatMFChannel::G4StatMFChannel() : 
 47   _NumOfNeutralFragments(0),                       60   _NumOfNeutralFragments(0), 
 48   _NumOfChargedFragments(0)                        61   _NumOfChargedFragments(0)
 49 {                                              <<  62 {}
 50   Pos.resize(8);                               << 
 51   Vel.resize(8);                               << 
 52   Accel.resize(8);                             << 
 53 }                                              << 
 54                                                    63 
 55 G4StatMFChannel::~G4StatMFChannel()                64 G4StatMFChannel::~G4StatMFChannel() 
 56 {                                                  65 { 
 57   if (!_theFragments.empty()) {                    66   if (!_theFragments.empty()) {
 58     std::for_each(_theFragments.begin(),_theFr     67     std::for_each(_theFragments.begin(),_theFragments.end(),
 59       DeleteFragment());                           68       DeleteFragment());
 60   }                                                69   }
 61 }                                                  70 }
 62                                                    71 
 63 G4bool G4StatMFChannel::CheckFragments(void)       72 G4bool G4StatMFChannel::CheckFragments(void)
 64 {                                                  73 {
 65   std::deque<G4StatMFFragment*>::iterator i;   <<  74     std::deque<G4StatMFFragment*>::iterator i;
 66   for (i = _theFragments.begin();              <<  75     for (i = _theFragments.begin(); 
 67        i != _theFragments.end(); ++i)          <<  76    i != _theFragments.end(); ++i) 
 68     {                                          <<  77       {
 69       G4int A = (*i)->GetA();                  <<  78   G4int A = (*i)->GetA();
 70       G4int Z = (*i)->GetZ();                  <<  79   G4int Z = (*i)->GetZ();
 71       if ( (A > 1 && (Z > A || Z <= 0)) || (A= <<  80         if ( (A > 1 && (Z > A || Z <= 0)) || (A==1 && Z > A) || A <= 0 ) return false;
 72     }                                              81     }
 73     return true;                                   82     return true;
 74 }                                                  83 }
 75                                                    84 
 76 void G4StatMFChannel::CreateFragment(G4int A,      85 void G4StatMFChannel::CreateFragment(G4int A, G4int Z)
 77 // Create a new fragment.                      <<  86     // Create a new fragment.
 78 // Fragments are automatically sorted: first c <<  87     // Fragments are automatically sorted: first charged fragments, 
 79 // then neutral ones.                          <<  88     // then neutral ones.
 80 {                                              <<  89 {
 81   if (Z <= 0.5) {                              <<  90     if (Z <= 0.5) {
 82     _theFragments.push_back(new G4StatMFFragme <<  91   _theFragments.push_back(new G4StatMFFragment(A,Z));
 83     _NumOfNeutralFragments++;                  <<  92   _NumOfNeutralFragments++;
 84   } else {                                     <<  93     } else {
 85     _theFragments.push_front(new G4StatMFFragm <<  94   _theFragments.push_front(new G4StatMFFragment(A,Z));
 86     _NumOfChargedFragments++;                  <<  95   _NumOfChargedFragments++;
 87   }                                            <<  96     }
 88                                                    97   
 89   return;                                      <<  98     return;
 90 }                                                  99 }
 91                                                   100 
 92 G4double G4StatMFChannel::GetFragmentsCoulombE    101 G4double G4StatMFChannel::GetFragmentsCoulombEnergy(void)
 93 {                                                 102 {
 94   G4double Coulomb =                           << 103     G4double Coulomb = std::accumulate(_theFragments.begin(),_theFragments.end(),
 95     std::accumulate(_theFragments.begin(),_the << 104            0.0,SumCoulombEnergy());
 96                     0.0,                       << 105 //      G4double Coulomb = 0.0;
 97                     [](const G4double& running << 106 //      for (unsigned int i = 0;i < _theFragments.size(); i++)
 98                        G4StatMFFragment*& frag << 107 //    Coulomb += _theFragments[i]->GetCoulombEnergy();
 99                     {                          << 108     return Coulomb;
100                       return running_total + f << 
101                     } );                       << 
102   //      G4double Coulomb = 0.0;              << 
103   //      for (unsigned int i = 0;i < _theFrag << 
104   //    Coulomb += _theFragments[i]->GetCoulom << 
105   return Coulomb;                              << 
106 }                                                 109 }
107                                                   110 
                                                   >> 111 
                                                   >> 112 
108 G4double G4StatMFChannel::GetFragmentsEnergy(G    113 G4double G4StatMFChannel::GetFragmentsEnergy(G4double T) const
109 {                                                 114 {
110   G4double Energy = 0.0;                       << 115     G4double Energy = 0.0;
111                                                   116   
112   G4double TranslationalEnergy = 1.5*T*_theFra << 117     G4double TranslationalEnergy = (3./2.)*T*static_cast<G4double>(_theFragments.size());
113                                                   118 
114   std::deque<G4StatMFFragment*>::const_iterato << 119     std::deque<G4StatMFFragment*>::const_iterator i;
115   for (i = _theFragments.begin(); i != _theFra << 120     for (i = _theFragments.begin(); i != _theFragments.end(); ++i)
116     {                                          << 121       {
117       Energy += (*i)->GetEnergy(T);            << 122   Energy += (*i)->GetEnergy(T);
118     }                                          << 123       }
119   return Energy + TranslationalEnergy;         << 124     return Energy + TranslationalEnergy;  
120 }                                                 125 }
121                                                   126 
122 G4FragmentVector * G4StatMFChannel::GetFragmen    127 G4FragmentVector * G4StatMFChannel::GetFragments(G4int anA, 
123              G4int anZ,                           128              G4int anZ,
124              G4double T)                          129              G4double T)
                                                   >> 130     //
125 {                                                 131 {
126   // calculate momenta of charged fragments    << 132     // calculate momenta of charged fragments  
127   CoulombImpulse(anA,anZ,T);                   << 133     CoulombImpulse(anA,anZ,T);
128                                                   134   
129   // calculate momenta of neutral fragments    << 135     // calculate momenta of neutral fragments
130   FragmentsMomenta(_NumOfNeutralFragments, _Nu << 136     FragmentsMomenta(_NumOfNeutralFragments, _NumOfChargedFragments, T);
131                                                   137 
132   G4FragmentVector * theResult = new G4Fragmen << 138     G4FragmentVector * theResult = new G4FragmentVector;
133   std::deque<G4StatMFFragment*>::iterator i;   << 139     std::deque<G4StatMFFragment*>::iterator i;
134   for (i = _theFragments.begin(); i != _theFra << 140     for (i = _theFragments.begin(); i != _theFragments.end(); ++i)
135     theResult->push_back((*i)->GetFragment(T)) << 141   theResult->push_back((*i)->GetFragment(T));
136                                                   142 
137   return theResult;                            << 143     return theResult;
138 }                                                 144 }
139                                                   145 
140 void G4StatMFChannel::CoulombImpulse(G4int anA    146 void G4StatMFChannel::CoulombImpulse(G4int anA, G4int anZ, G4double T)
141 // Aafter breakup, fragments fly away under Co << 147     // Aafter breakup, fragments fly away under Coulomb field.
142 // This method calculates asymptotic fragments << 148     // This method calculates asymptotic fragments momenta.
143 {                                                 149 {
144   // First, we have to place the fragments ins << 150     // First, we have to place the fragments inside of the original nucleus volume
145   PlaceFragments(anA);                         << 151     PlaceFragments(anA);
146                                                   152   
147   // Second, we sample initial charged fragmen << 153   // Second, we sample initial charged fragments momenta. There are
148   // _NumOfChargedFragments charged fragments  << 154   // _NumOfChargedFragments charged fragments and they start at the begining
149   // of the vector _theFragments (i.e. 0)      << 155   // of the vector _theFragments (i.e. 0) 
150   FragmentsMomenta(_NumOfChargedFragments, 0,  << 156     FragmentsMomenta(_NumOfChargedFragments, 0, T);
151                                                << 157 
152   // Third, we have to figure out the asymptot << 158     // Third, we have to figure out the asymptotic momenta of charged fragments 
153   // For taht we have to solve equations of mo << 159     // For taht we have to solve equations of motion for fragments
154   SolveEqOfMotion(anA,anZ,T);                  << 160     SolveEqOfMotion(anA,anZ,T);
155                                                   161 
156   return;                                      << 162     return;
157 }                                                 163 }
158                                                   164 
159 void G4StatMFChannel::PlaceFragments(G4int anA    165 void G4StatMFChannel::PlaceFragments(G4int anA)
160 // This gives the position of fragments at the << 166     // This gives the position of fragments at the breakup instant. 
161 // Fragments positions are sampled inside prol << 167     // Fragments positions are sampled inside prolongated ellipsoid.
162 {                                                 168 {
163   G4Pow* g4calc = G4Pow::GetInstance();        << 169     G4Pow* g4pow = G4Pow::GetInstance();
164   const G4double R0 = G4StatMFParameters::Getr << 170     const G4double R0 = G4StatMFParameters::Getr0();
165   G4double Rsys = 2.0*R0*g4calc->Z13(anA);     << 171     const G4double Rsys = 2.0*R0*g4pow->Z13(anA);
166                                                   172 
167   G4bool TooMuchIterations;                    << 173     G4bool TooMuchIterations;
168   do                                           << 174     do 
169     {                                          << 175       {
170       TooMuchIterations = false;               << 176   TooMuchIterations = false;
171                                                   177   
172       // Sample the position of the first frag << 178   // Sample the position of the first fragment
173       G4double R = (Rsys - R0*g4calc->Z13(_the << 179   G4double R = (Rsys - R0*g4pow->Z13(_theFragments[0]->GetA()))*
174   g4calc->A13(G4UniformRand());                << 180     std::pow(G4UniformRand(),1./3.);
175       _theFragments[0]->SetPosition(R*G4Random << 181   _theFragments[0]->SetPosition(IsotropicVector(R));
176                                                   182   
177                                                   183   
178       // Sample the position of the remaining  << 184   // Sample the position of the remaining fragments
179       G4bool ThereAreOverlaps = false;         << 185   G4bool ThereAreOverlaps = false;
180       std::deque<G4StatMFFragment*>::iterator  << 186   std::deque<G4StatMFFragment*>::iterator i;
181       for (i = _theFragments.begin()+1; i != _ << 187   for (i = _theFragments.begin()+1; i != _theFragments.end(); ++i) 
182   {                                            << 188     {
183     G4int counter = 0;                         << 189       G4int counter = 0;
184     do                                         << 190       do 
185       {                                        << 191         {
186         R = (Rsys - R0*g4calc->Z13((*i)->GetA( << 192     R = (Rsys - R0*g4pow->Z13((*i)->GetA()))*std::pow(G4UniformRand(),1./3.);
187         (*i)->SetPosition(R*G4RandomDirection( << 193     (*i)->SetPosition(IsotropicVector(R));
188                                                   194     
189         // Check that there are not overlappin << 195     // Check that there are not overlapping fragments
190         std::deque<G4StatMFFragment*>::iterato << 196     std::deque<G4StatMFFragment*>::iterator j;
191         for (j = _theFragments.begin(); j != i << 197     for (j = _theFragments.begin(); j != i; ++j) 
192     {                                          << 198       {
193       G4ThreeVector FragToFragVector =         << 199         G4ThreeVector FragToFragVector = (*i)->GetPosition() - (*j)->GetPosition();
194         (*i)->GetPosition() - (*j)->GetPositio << 200         G4double Rmin = R0*(g4pow->Z13((*i)->GetA()) +
195       G4double Rmin = R0*(g4calc->Z13((*i)->Ge << 201           g4pow->Z13((*j)->GetA()));
196               g4calc->Z13((*j)->GetA()));      << 202         if ( (ThereAreOverlaps = (FragToFragVector.mag2() < Rmin*Rmin)) ) break;
197       if ( (ThereAreOverlaps = (FragToFragVect << 203       }
198         { break; }                             << 204     counter++;
199     }                                          << 205         } while (ThereAreOverlaps && counter < 1000);
200         counter++;                             << 
201         // Loop checking, 05-Aug-2015, Vladimi << 
202       } while (ThereAreOverlaps && counter < 1 << 
203                                                   206       
204     if (counter >= 1000)                       << 207       if (counter >= 1000) 
205       {                                        << 208         {
206         TooMuchIterations = true;              << 209     TooMuchIterations = true;
207         break;                                 << 210     break;
208       }                                        << 211         } 
209   }                                            << 212     }
210       // Loop checking, 05-Aug-2015, Vladimir  << 
211     } while (TooMuchIterations);                  213     } while (TooMuchIterations);
                                                   >> 214     
212     return;                                       215     return;
213 }                                                 216 }
214                                                   217 
215 void G4StatMFChannel::FragmentsMomenta(G4int N    218 void G4StatMFChannel::FragmentsMomenta(G4int NF, G4int idx,
216                G4double T)                        219                G4double T)
217 // Calculate fragments momenta at the breakup  << 220     // Calculate fragments momenta at the breakup instant
218 // Fragment kinetic energies are calculated ac << 221     // Fragment kinetic energies are calculated according to the 
219 // Boltzmann distribution at given temperature << 222     // Boltzmann distribution at given temperature.
220 // NF is number of fragments                   << 223     // NF is number of fragments
221 // idx is index of first fragment              << 224     // idx is index of first fragment
222 {                                                 225 {
223   G4double KinE = 1.5*T*NF;                    << 226     G4double KinE = (3./2.)*T*static_cast<G4double>(NF);
224   G4ThreeVector p(0.,0.,0.);                   << 
225                                                   227   
226   if (NF <= 0) return;                         << 228     G4ThreeVector p;
227   else if (NF == 1)                            << 229   
228     {                                          << 230     if (NF <= 0) return;
229       // We have only one fragment to deal wit << 231     else if (NF == 1) 
230       p = std::sqrt(2.0*_theFragments[idx]->Ge << 232       {
231   *G4RandomDirection();                        << 233   // We have only one fragment to deal with
232       _theFragments[idx]->SetMomentum(p);      << 234   p = IsotropicVector(std::sqrt(2.0*_theFragments[idx]->GetNuclearMass()*KinE));
233     }                                          << 235   _theFragments[idx]->SetMomentum(p);
234   else if (NF == 2)                            << 236       } 
235     {                                          << 237     else if (NF == 2) 
236       // We have only two fragment to deal wit << 238       {
237       G4double M1 = _theFragments[idx]->GetNuc << 239   // We have only two fragment to deal with
238       G4double M2 = _theFragments[idx+1]->GetN << 240   G4double M1 = _theFragments[idx]->GetNuclearMass();
239       p = std::sqrt(2.0*KinE*(M1*M2)/(M1+M2))* << 241   G4double M2 = _theFragments[idx+1]->GetNuclearMass();
240       _theFragments[idx]->SetMomentum(p);      << 242   p = IsotropicVector(std::sqrt(2.0*KinE*(M1*M2)/(M1+M2)));   
241       _theFragments[idx+1]->SetMomentum(-p);   << 243   _theFragments[idx]->SetMomentum(p);
242     }                                          << 244   _theFragments[idx+1]->SetMomentum(-p);
243   else                                         << 245       } 
244     {                                          << 246     else 
245       // We have more than two fragments       << 247       {
246       G4double AvailableE;                     << 248   // We have more than two fragments
247       G4int i1,i2;                             << 249   G4double AvailableE;
248       G4double SummedE;                        << 250   G4int i1,i2;
249       G4ThreeVector SummedP(0.,0.,0.);         << 251   G4double SummedE;
250       do                                       << 252   G4ThreeVector SummedP;
251   {                                            << 
252     // Fisrt sample momenta of NF-2 fragments  << 
253     // according to Boltzmann distribution     << 
254     AvailableE = 0.0;                          << 
255     SummedE = 0.0;                             << 
256     SummedP.setX(0.0);SummedP.setY(0.0);Summed << 
257     for (G4int i = idx; i < idx+NF-2; ++i)     << 
258       {                                        << 
259         G4double E;                            << 
260         G4double RandE;                        << 
261         do                                     << 
262     {                                          << 
263       E = 9.0*G4UniformRand();                 << 
264       RandE = std::sqrt(0.5/E)*G4Exp(E-0.5)*G4 << 
265     }                                          << 
266         // Loop checking, 05-Aug-2015, Vladimi << 
267         while (RandE > 1.0);                   << 
268         E *= T;                                << 
269         p = std::sqrt(2.0*E*_theFragments[i]-> << 
270     *G4RandomDirection();                      << 
271         _theFragments[i]->SetMomentum(p);      << 
272         SummedE += E;                          << 
273         SummedP += p;                          << 
274       }                                        << 
275     // Calculate momenta of last two fragments << 
276     // that constraints are satisfied          << 
277     i1 = idx+NF-2;  // before last fragment in << 
278     i2 = idx+NF-1;  // last fragment index     << 
279     p = -SummedP;                              << 
280     AvailableE = KinE - SummedE;               << 
281     // Available Kinetic Energy should be shar << 
282   }                                            << 
283       // Loop checking, 05-Aug-2015, Vladimir  << 
284       while (AvailableE <= p.mag2()/(2.0*(_the << 
285             _theFragments[i2]->GetNuclearMass( << 
286       G4double H = 1.0 + _theFragments[i2]->Ge << 
287   /_theFragments[i1]->GetNuclearMass();        << 
288       G4double CTM12 = H*(1.0 - 2.0*_theFragme << 
289         *AvailableE/p.mag2());                 << 
290       G4double CosTheta1;                      << 
291       G4double Sign;                           << 
292                                                << 
293       if (CTM12 > 1.) {CosTheta1 = 1.;}        << 
294       else {                                   << 
295   do                                              253   do 
296     {                                             254     {
297       do                                       << 255       // Fisrt sample momenta of NF-2 fragments 
                                                   >> 256       // according to Boltzmann distribution
                                                   >> 257       AvailableE = 0.0;
                                                   >> 258       SummedE = 0.0;
                                                   >> 259       SummedP.setX(0.0);SummedP.setY(0.0);SummedP.setZ(0.0);
                                                   >> 260       for (G4int i = idx; i < idx+NF-2; i++) 
298         {                                         261         {
299     CosTheta1 = 1.0 - 2.0*G4UniformRand();     << 262     G4double E;
300         }                                      << 263     G4double RandE;
301       // Loop checking, 05-Aug-2015, Vladimir  << 264     G4double Boltzmann;
302       while (CosTheta1*CosTheta1 < CTM12);     << 265     do 
303     }                                          << 266       {
304   // Loop checking, 05-Aug-2015, Vladimir Ivan << 267         E = 9.0*T*G4UniformRand();
305   while (CTM12 >= 0.0 && CosTheta1 < 0.0);     << 268         Boltzmann = std::sqrt(E)*std::exp(-E/T);
306       }                                        << 269         RandE = std::sqrt(T/2.)*std::exp(-0.5)*G4UniformRand();
                                                   >> 270       } 
                                                   >> 271     while (RandE > Boltzmann);
                                                   >> 272     p = IsotropicVector(std::sqrt(2.0*E*_theFragments[i]->GetNuclearMass()));
                                                   >> 273     _theFragments[i]->SetMomentum(p);
                                                   >> 274     SummedE += E;
                                                   >> 275     SummedP += p;
                                                   >> 276         } 
                                                   >> 277       // Calculate momenta of last two fragments in such a way
                                                   >> 278       // that constraints are satisfied
                                                   >> 279       i1 = idx+NF-2;  // before last fragment index
                                                   >> 280       i2 = idx+NF-1;  // last fragment index
                                                   >> 281       p = -SummedP;
                                                   >> 282       AvailableE = KinE - SummedE;
                                                   >> 283       // Available Kinetic Energy should be shared between two last fragments
                                                   >> 284     } 
                                                   >> 285   while (AvailableE <= p.mag2()/(2.0*(_theFragments[i1]->GetNuclearMass()+
                                                   >> 286               _theFragments[i2]->GetNuclearMass())));   
                                                   >> 287     
                                                   >> 288   G4double H = 1.0 + _theFragments[i2]->GetNuclearMass()/_theFragments[i1]->GetNuclearMass();
                                                   >> 289   G4double CTM12 = H*(1.0 - 2.0*_theFragments[i2]->GetNuclearMass()*AvailableE/p.mag2());
                                                   >> 290   G4double CosTheta1;
                                                   >> 291   G4double Sign;
                                                   >> 292 
                                                   >> 293         if (CTM12 > 0.9999) {CosTheta1 = 1.;} 
                                                   >> 294         else {
                                                   >> 295    do 
                                                   >> 296      {
                                                   >> 297        do 
                                                   >> 298          {
                                                   >> 299      CosTheta1 = 1.0 - 2.0*G4UniformRand();
                                                   >> 300          } 
                                                   >> 301        while (CosTheta1*CosTheta1 < CTM12);
                                                   >> 302      }
                                                   >> 303           while (CTM12 >= 0.0 && CosTheta1 < 0.0);
                                                   >> 304   }
307                                                   305 
308       if (CTM12 < 0.0) Sign = 1.0;             << 306   if (CTM12 < 0.0) Sign = 1.0;
309       else if (G4UniformRand() <= 0.5) Sign =  << 307   else if (G4UniformRand() <= 0.5) Sign = -1.0;
310       else Sign = 1.0;                         << 308   else Sign = 1.0;
311                                                   309     
312       G4double P1 = (p.mag()*CosTheta1+Sign*st << 
313                   *(CosTheta1*CosTheta1-CTM12) << 
314       G4double P2 = std::sqrt(P1*P1+p.mag2() - << 
315       G4double Phi = twopi*G4UniformRand();    << 
316       G4double SinTheta1 = std::sqrt(1.0 - Cos << 
317       G4double CosPhi1 = std::cos(Phi);        << 
318       G4double SinPhi1 = std::sin(Phi);        << 
319       G4double CosPhi2 = -CosPhi1;             << 
320       G4double SinPhi2 = -SinPhi1;             << 
321       G4double CosTheta2 = (p.mag2() + P2*P2 - << 
322       G4double SinTheta2 = 0.0;                << 
323       if (CosTheta2 > -1.0 && CosTheta2 < 1.0) << 
324   SinTheta2 = std::sqrt(1.0 - CosTheta2*CosThe << 
325       }                                        << 
326       G4ThreeVector p1(P1*SinTheta1*CosPhi1,P1 << 
327       G4ThreeVector p2(P2*SinTheta2*CosPhi2,P2 << 
328       G4ThreeVector b(1.0,0.0,0.0);            << 
329                                                << 
330       p1 = RotateMomentum(p,b,p1);             << 
331       p2 = RotateMomentum(p,b,p2);             << 
332                                                << 
333       SummedP += p1 + p2;                      << 
334       SummedE += p1.mag2()/(2.0*_theFragments[ << 
335   p2.mag2()/(2.0*_theFragments[i2]->GetNuclear << 
336                                                   310     
337       _theFragments[i1]->SetMomentum(p1);      << 311   G4double P1 = (p.mag()*CosTheta1+Sign*std::sqrt(p.mag2()*(CosTheta1*CosTheta1-CTM12)))/H;
338       _theFragments[i2]->SetMomentum(p2);      << 312   G4double P2 = std::sqrt(P1*P1+p.mag2() - 2.0*P1*p.mag()*CosTheta1);
                                                   >> 313   G4double Phi = twopi*G4UniformRand();
                                                   >> 314   G4double SinTheta1 = std::sqrt(1.0 - CosTheta1*CosTheta1);
                                                   >> 315   G4double CosPhi1 = std::cos(Phi);
                                                   >> 316   G4double SinPhi1 = std::sin(Phi);
                                                   >> 317   G4double CosPhi2 = -CosPhi1;
                                                   >> 318   G4double SinPhi2 = -SinPhi1;
                                                   >> 319   G4double CosTheta2 = (p.mag2() + P2*P2 - P1*P1)/(2.0*p.mag()*P2);
                                                   >> 320   G4double SinTheta2 = 0.0;
                                                   >> 321   if (CosTheta2 > -1.0 && CosTheta2 < 1.0) SinTheta2 = std::sqrt(1.0 - CosTheta2*CosTheta2);
                                                   >> 322   
                                                   >> 323   G4ThreeVector p1(P1*SinTheta1*CosPhi1,P1*SinTheta1*SinPhi1,P1*CosTheta1);
                                                   >> 324   G4ThreeVector p2(P2*SinTheta2*CosPhi2,P2*SinTheta2*SinPhi2,P2*CosTheta2);
                                                   >> 325   G4ThreeVector b(1.0,0.0,0.0);
                                                   >> 326   
                                                   >> 327   p1 = RotateMomentum(p,b,p1);
                                                   >> 328   p2 = RotateMomentum(p,b,p2);
                                                   >> 329   
                                                   >> 330   SummedP += p1 + p2;
                                                   >> 331   SummedE += p1.mag2()/(2.0*_theFragments[i1]->GetNuclearMass()) + 
                                                   >> 332       p2.mag2()/(2.0*_theFragments[i2]->GetNuclearMass());    
339                                                   333     
340     }                                          << 334   _theFragments[i1]->SetMomentum(p1);
341   return;                                      << 335   _theFragments[i2]->SetMomentum(p2);
                                                   >> 336     
                                                   >> 337       }
                                                   >> 338 
                                                   >> 339     return;
342 }                                                 340 }
343                                                   341 
                                                   >> 342 
344 void G4StatMFChannel::SolveEqOfMotion(G4int an    343 void G4StatMFChannel::SolveEqOfMotion(G4int anA, G4int anZ, G4double T)
345 // This method will find a solution of Newton' << 344     // This method will find a solution of Newton's equation of motion
346 // for fragments in the self-consistent time-d << 345     // for fragments in the self-consistent time-dependent Coulomb field
347 {                                                 346 {
348   G4Pow* g4calc = G4Pow::GetInstance();        << 347   G4double CoulombEnergy = (3./5.)*(elm_coupling*anZ*anZ)*
349   G4double CoulombEnergy = 0.6*CLHEP::elm_coup << 348     std::pow(1.0+G4StatMFParameters::GetKappaCoulomb(),1./3.)/
350     g4calc->A13(1.0+G4StatMFParameters::GetKap << 349     (G4StatMFParameters::Getr0()*G4Pow::GetInstance()->Z13(anA))
351     (G4StatMFParameters::Getr0()*g4calc->Z13(a << 350     - GetFragmentsCoulombEnergy();
352   if (CoulombEnergy <= 0.0) return;               351   if (CoulombEnergy <= 0.0) return;
353                                                   352   
354   G4int Iterations = 0;                           353   G4int Iterations = 0;
355   G4double TimeN = 0.0;                           354   G4double TimeN = 0.0;
356   G4double TimeS = 0.0;                           355   G4double TimeS = 0.0;
357   G4double DeltaTime = 10.0;                      356   G4double DeltaTime = 10.0;
358   if (_NumOfChargedFragments > (G4int)Pos.size << 357   
359     Pos.resize(_NumOfChargedFragments);        << 358   G4ThreeVector * Pos = new G4ThreeVector[_NumOfChargedFragments];
360     Vel.resize(_NumOfChargedFragments);        << 359   G4ThreeVector * Vel = new G4ThreeVector[_NumOfChargedFragments];
361     Accel.resize(_NumOfChargedFragments);      << 360   G4ThreeVector * Accel = new G4ThreeVector[_NumOfChargedFragments];
362   }                                            << 
363                                                   361   
364   G4int i;                                        362   G4int i;
365   for (i = 0; i < _NumOfChargedFragments; ++i) << 363   for (i = 0; i < _NumOfChargedFragments; i++) 
366     {                                             364     {
367       Vel[i] = (1.0/(_theFragments[i]->GetNucl    365       Vel[i] = (1.0/(_theFragments[i]->GetNuclearMass()))*
368   _theFragments[i]->GetMomentum();                366   _theFragments[i]->GetMomentum();
369       Pos[i] = _theFragments[i]->GetPosition()    367       Pos[i] = _theFragments[i]->GetPosition();
370     }                                             368     }
                                                   >> 369   
                                                   >> 370   do 
                                                   >> 371     {
371                                                   372 
372   G4ThreeVector distance(0.,0.,0.);            << 373       G4ThreeVector distance;
373   G4ThreeVector force(0.,0.,0.);               << 374       G4ThreeVector force;
374   G4ThreeVector SavedVel(0.,0.,0.);            << 375 
375   do {                                         << 376       for (i = 0; i < _NumOfChargedFragments; i++) 
376     for (i = 0; i < _NumOfChargedFragments; ++ << 377   {
377       {                                        << 378     force.setX(0.0); force.setY(0.0); force.setZ(0.0);
378   force.set(0.,0.,0.);                         << 379     for (G4int j = 0; j < _NumOfChargedFragments; j++) 
379   for (G4int j = 0; j < _NumOfChargedFragments << 380       {
380     {                                          << 381         if (i != j) 
381       if (i != j)                              << 382     {
382         {                                      << 383       distance = Pos[i] - Pos[j];
383     distance = Pos[i] - Pos[j];                << 384       force += (elm_coupling*_theFragments[i]->GetZ()
384     force += (_theFragments[i]->GetZ()*_theFra << 385             *_theFragments[j]->GetZ()/
385         (distance.mag2()*distance.mag()))*dist << 386           (distance.mag2()*distance.mag()))*distance;
386         }                                      << 387     }
387     }                                          << 388       }
388   Accel[i] = CLHEP::elm_coupling*CLHEP::fermi* << 389     Accel[i] = (1./(_theFragments[i]->GetNuclearMass()))*force;
389       }                                        << 390   }
390                                                   391 
391     TimeN = TimeS + DeltaTime;                 << 392       TimeN = TimeS + DeltaTime;
392                                                   393   
393     for ( i = 0; i < _NumOfChargedFragments; + << 394       G4ThreeVector SavedVel;
394       {                                        << 395       for ( i = 0; i < _NumOfChargedFragments; i++) 
395   SavedVel = Vel[i];                           << 396   {
396   Vel[i] += Accel[i]*(TimeN-TimeS);            << 397     SavedVel = Vel[i];
397   Pos[i] += (SavedVel+Vel[i])*(TimeN-TimeS)*0. << 398     Vel[i] += Accel[i]*(TimeN-TimeS);
398       }                                        << 399     Pos[i] += (SavedVel+Vel[i])*(TimeN-TimeS)*0.5;
399     TimeS = TimeN;                             << 400   }
400                                                << 401       
401     // Loop checking, 05-Aug-2015, Vladimir Iv << 402       //    if (Iterations >= 50 && Iterations < 75) DeltaTime = 4.;
402   } while (Iterations++ < 100);                << 403       //    else if (Iterations >= 75) DeltaTime = 10.;
                                                   >> 404 
                                                   >> 405       TimeS = TimeN;
                                                   >> 406 
                                                   >> 407     } 
                                                   >> 408   while (Iterations++ < 100);
403                                                   409   
404   // Summed fragment kinetic energy               410   // Summed fragment kinetic energy
405   G4double TotalKineticEnergy = 0.0;              411   G4double TotalKineticEnergy = 0.0;
406   for (i = 0; i < _NumOfChargedFragments; ++i) << 412   for (i = 0; i < _NumOfChargedFragments; i++) 
407     {                                             413     {
408       TotalKineticEnergy += _theFragments[i]->    414       TotalKineticEnergy += _theFragments[i]->GetNuclearMass()*
409   0.5*Vel[i].mag2();                              415   0.5*Vel[i].mag2();
410     }                                             416     }
411   // Scaling of fragment velocities               417   // Scaling of fragment velocities
412   G4double KineticEnergy = 1.5*_NumOfChargedFr << 418   G4double KineticEnergy = (3./2.)*_theFragments.size()*T;
413   G4double Eta = std::pow(( CoulombEnergy + Ki << 419   G4double Eta = ( CoulombEnergy + KineticEnergy ) / TotalKineticEnergy;
414                                                << 420   for (i = 0; i < _NumOfChargedFragments; i++) 
                                                   >> 421     {
                                                   >> 422       Vel[i] *= Eta;
                                                   >> 423     }
                                                   >> 424   
415   // Finally calculate fragments momenta          425   // Finally calculate fragments momenta
416   for (i = 0; i < _NumOfChargedFragments; ++i) << 426   for (i = 0; i < _NumOfChargedFragments; i++) 
417     {                                             427     {
418       _theFragments[i]->SetMomentum((_theFragm << 428       _theFragments[i]->SetMomentum(_theFragments[i]->GetNuclearMass()*Vel[i]);
419     }                                             429     }
                                                   >> 430   
                                                   >> 431   // garbage collection
                                                   >> 432   delete [] Pos;
                                                   >> 433   delete [] Vel;
                                                   >> 434   delete [] Accel;
                                                   >> 435   
420   return;                                         436   return;
421 }                                                 437 }
422                                                   438 
                                                   >> 439 
                                                   >> 440 
423 G4ThreeVector G4StatMFChannel::RotateMomentum(    441 G4ThreeVector G4StatMFChannel::RotateMomentum(G4ThreeVector Pa,
424                 G4ThreeVector V, G4ThreeVector    442                 G4ThreeVector V, G4ThreeVector P)
425     // Rotates a 3-vector P to close momentum     443     // Rotates a 3-vector P to close momentum triangle Pa + V + P = 0
426 {                                                 444 {
427   G4ThreeVector U = Pa.unit();                    445   G4ThreeVector U = Pa.unit();
428                                                   446   
429   G4double Alpha1 = U * V;                        447   G4double Alpha1 = U * V;
430                                                   448   
431   G4double Alpha2 = std::sqrt(V.mag2() - Alpha    449   G4double Alpha2 = std::sqrt(V.mag2() - Alpha1*Alpha1);
432                                                   450 
433   G4ThreeVector N = (1./Alpha2)*U.cross(V);       451   G4ThreeVector N = (1./Alpha2)*U.cross(V);
434                                                   452   
435   G4ThreeVector RotatedMomentum(                  453   G4ThreeVector RotatedMomentum(
436         ( (V.x() - Alpha1*U.x())/Alpha2 ) * P.    454         ( (V.x() - Alpha1*U.x())/Alpha2 ) * P.x() + N.x() * P.y() + U.x() * P.z(),
437         ( (V.y() - Alpha1*U.y())/Alpha2 ) * P.    455         ( (V.y() - Alpha1*U.y())/Alpha2 ) * P.x() + N.y() * P.y() + U.y() * P.z(),
438         ( (V.z() - Alpha1*U.z())/Alpha2 ) * P.    456         ( (V.z() - Alpha1*U.z())/Alpha2 ) * P.x() + N.z() * P.y() + U.z() * P.z()
439         );                                        457         );
440   return RotatedMomentum;                         458   return RotatedMomentum;
441 }                                                 459 }
442                                                   460 
                                                   >> 461 
                                                   >> 462 
                                                   >> 463 
                                                   >> 464 
                                                   >> 465 G4ThreeVector G4StatMFChannel::IsotropicVector(const G4double Magnitude)
                                                   >> 466     // Samples a isotropic random vector with a magnitud given by Magnitude.
                                                   >> 467     // By default Magnitude = 1
                                                   >> 468 {
                                                   >> 469     G4double CosTheta = 1.0 - 2.0*G4UniformRand();
                                                   >> 470     G4double SinTheta = std::sqrt(1.0 - CosTheta*CosTheta);
                                                   >> 471     G4double Phi = twopi*G4UniformRand();
                                                   >> 472     G4ThreeVector Vector(Magnitude*std::cos(Phi)*SinTheta,
                                                   >> 473        Magnitude*std::cos(Phi)*CosTheta,
                                                   >> 474        Magnitude*std::sin(Phi));
                                                   >> 475     return Vector;
                                                   >> 476 }
443                                                   477