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 7.1)


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