Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/materials/src/G4DensityEffectCalculator.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 /materials/src/G4DensityEffectCalculator.cc (Version 11.3.0) and /materials/src/G4DensityEffectCalculator.cc (Version 10.7.p4)


  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 /*                                                 27 /*
 28  * Implements calculation of the Fermi density     28  * Implements calculation of the Fermi density effect as per the method
 29  * described in:                                   29  * described in:
 30  *                                                 30  *
 31  *   R. M. Sternheimer, M. J. Berger, and S. M     31  *   R. M. Sternheimer, M. J. Berger, and S. M. Seltzer. Density
 32  *   effect for the ionization loss of charged     32  *   effect for the ionization loss of charged particles in various sub-
 33  *   stances. Atom. Data Nucl. Data Tabl., 30:     33  *   stances. Atom. Data Nucl. Data Tabl., 30:261, 1984.
 34  *                                                 34  *
 35  * Which (among other Sternheimer references)      35  * Which (among other Sternheimer references) builds on:
 36  *                                                 36  *
 37  *   R. M. Sternheimer. The density effect for     37  *   R. M. Sternheimer. The density effect for ionization loss in
 38  *   materials. Phys. Rev., 88:851­859, 1952.     38  *   materials. Phys. Rev., 88:851­859, 1952.
 39  *                                                 39  *
 40  * The returned values of delta are directly f     40  * The returned values of delta are directly from the Sternheimer calculation,
 41  * and not Sternheimer's popular three-part ap     41  * and not Sternheimer's popular three-part approximate parameterization
 42  * introduced in the same paper.                   42  * introduced in the same paper.
 43  *                                                 43  *
 44  * Author: Matthew Strait <straitm@umn.edu> 20     44  * Author: Matthew Strait <straitm@umn.edu> 2019
 45  */                                                45  */
 46                                                    46 
 47 #include "G4DensityEffectCalculator.hh"            47 #include "G4DensityEffectCalculator.hh"
 48                                                << 
 49 #include "G4AtomicShells.hh"                       48 #include "G4AtomicShells.hh"
 50 #include "G4NistManager.hh"                        49 #include "G4NistManager.hh"
 51 #include "G4Pow.hh"                                50 #include "G4Pow.hh"
 52                                                    51 
 53 static G4Pow* gpow = G4Pow::GetInstance();     <<  52 static G4Pow * gpow = G4Pow::GetInstance();
 54                                                    53 
 55 const G4int maxWarnings = 20;                      54 const G4int maxWarnings = 20;
 56                                                    55 
 57 G4DensityEffectCalculator::G4DensityEffectCalc     56 G4DensityEffectCalculator::G4DensityEffectCalculator(const G4Material* mat, G4int n)
 58   : fMaterial(mat), nlev(n)                    <<  57   : fMaterial(mat), fVerbose(0), fWarnings(0), nlev(n)
 59 {                                                  58 {
 60   fVerbose = std::max(fVerbose, G4NistManager:     59   fVerbose = std::max(fVerbose, G4NistManager::Instance()->GetVerbose());
 61                                                    60 
 62   sternf = new G4double[nlev];                 <<  61   sternf    = new G4double [nlev];
 63   levE = new G4double[nlev];                   <<  62   levE      = new G4double [nlev];
 64   sternl = new G4double[nlev];                 <<  63   sternl    = new G4double [nlev];
 65   sternEbar = new G4double[nlev];              <<  64   sternEbar = new G4double [nlev];
 66   for (G4int i = 0; i < nlev; ++i) {           <<  65   for(G4int i=0; i<nlev; ++i) {
 67     sternf[i] = 0.0;                           <<  66     sternf[i]    = 0.0;
 68     levE[i] = 0.0;                             <<  67     levE[i]      = 0.0;
 69     sternl[i] = 0.0;                           <<  68     sternl[i]    = 0.0;
 70     sternEbar[i] = 0.0;                            69     sternEbar[i] = 0.0;
 71   }                                                70   }
 72                                                    71 
 73   fConductivity = sternx = 0.0;                    72   fConductivity = sternx = 0.0;
 74   G4bool conductor = (fMaterial->GetFreeElectr     73   G4bool conductor = (fMaterial->GetFreeElectronDensity() > 0.0);
 75                                                    74 
 76   G4int sh = 0;                                    75   G4int sh = 0;
 77   G4double sum = 0.;                               76   G4double sum = 0.;
 78   const G4double tot = fMaterial->GetTotNbOfAt     77   const G4double tot = fMaterial->GetTotNbOfAtomsPerVolume();
 79   for (size_t j = 0; j < fMaterial->GetNumberO <<  78   for(size_t j = 0; j < fMaterial->GetNumberOfElements(); ++j) {
 80     // The last subshell is considered to cont     79     // The last subshell is considered to contain the conduction
 81     // electrons. Sternheimer 1984 says "the l     80     // electrons. Sternheimer 1984 says "the lowest chemical valance of
 82     // the element" is used to set the number      81     // the element" is used to set the number of conduction electrons.
 83     // I'm not sure if that means the highest      82     // I'm not sure if that means the highest subshell or the whole
 84     // shell, but in any case, he also says th     83     // shell, but in any case, he also says that the choice is arbitrary
 85     // and offers a possible alternative. This     84     // and offers a possible alternative. This is one of the sources of
 86     // uncertainty in the model.                   85     // uncertainty in the model.
 87     const G4double frac = fMaterial->GetVecNbO <<  86     const G4double frac = fMaterial->GetVecNbOfAtomsPerVolume()[j]/tot;
 88     const G4int Z = fMaterial->GetElement((G4i <<  87     const G4int Z = fMaterial->GetElement(j)->GetZasInt();
 89     const G4int nshell = G4AtomicShells::GetNu     88     const G4int nshell = G4AtomicShells::GetNumberOfShells(Z);
 90     for (G4int i = 0; i < nshell; ++i) {       <<  89     for(G4int i = 0; i < nshell; ++i) {
 91       // For conductors, put *all* top shell e     90       // For conductors, put *all* top shell electrons into the conduction
 92       // band, regardless of element.              91       // band, regardless of element.
 93       const G4double xx = frac * G4AtomicShell <<  92       const G4double xx = frac*G4AtomicShells::GetNumberOfElectrons(Z, i);
 94       if (i < nshell - 1 || ! conductor) {     <<  93       if(i < nshell-1 || !conductor) {
 95         sternf[sh] += xx;                      <<  94   sternf[sh] += xx;
 96       }                                        <<  95       } else {
 97       else {                                   << 
 98         fConductivity += xx;                       96         fConductivity += xx;
 99       }                                            97       }
100       levE[sh] = G4AtomicShells::GetBindingEne <<  98       levE[sh] = G4AtomicShells::GetBindingEnergy(Z, i)/CLHEP::eV;
101       ++sh;                                        99       ++sh;
102     }                                             100     }
103   }                                               101   }
104   for (G4int i = 0; i < nlev; ++i) {           << 102   for(G4int i=0; i<nlev; ++i) {
105     sum += sternf[i];                             103     sum += sternf[i];
106   }                                               104   }
107   sum += fConductivity;                           105   sum += fConductivity;
108                                                   106 
109   const G4double invsum = (sum > 0.0) ? 1. / s << 107   const G4double invsum = (sum > 0.0) ? 1./sum : 0.0;
110   for (G4int i = 0; i < nlev; ++i) {           << 108   for(G4int i=0; i<nlev; ++i) {
111     sternf[i] *= invsum;                          109     sternf[i] *= invsum;
112   }                                               110   }
113   fConductivity *= invsum;                     << 111   fConductivity *= invsum;  
114   plasmaE = fMaterial->GetIonisation()->GetPla << 112   plasmaE = fMaterial->GetIonisation()->GetPlasmaEnergy()/CLHEP::eV;
115   meanexcite = fMaterial->GetIonisation()->Get << 113   meanexcite = fMaterial->GetIonisation()->GetMeanExcitationEnergy()/CLHEP::eV;
116 }                                                 114 }
117                                                   115 
118 G4DensityEffectCalculator::~G4DensityEffectCal    116 G4DensityEffectCalculator::~G4DensityEffectCalculator()
119 {                                                 117 {
120   delete[] sternf;                             << 118   delete [] sternf;
121   delete[] levE;                               << 119   delete [] levE;
122   delete[] sternl;                             << 120   delete [] sternl;
123   delete[] sternEbar;                          << 121   delete [] sternEbar;
124 }                                                 122 }
125                                                   123 
126 G4double G4DensityEffectCalculator::ComputeDen    124 G4double G4DensityEffectCalculator::ComputeDensityCorrection(G4double x)
127 {                                                 125 {
128   if (fVerbose > 1) {                          << 126   if(fVerbose > 1) {
129     G4cout << "G4DensityEffectCalculator::Comp << 127     G4cout << "G4DensityEffectCalculator::ComputeDensityCorrection for " 
130            << ", x= " << x << G4endl;          << 128            << fMaterial->GetName() << ", x= " << x << G4endl;
131   }                                               129   }
132   const G4double approx = fMaterial->GetIonisa    130   const G4double approx = fMaterial->GetIonisation()->GetDensityCorrection(x);
133   const G4double exact = FermiDeltaCalculation << 131   const G4double exact  = FermiDeltaCalculation(x);
134                                                   132 
135   if (fVerbose > 1) {                          << 133   if(fVerbose > 1) {
136     G4cout << "   Delta: computed= " << exact  << 134     G4cout << "   Delta: computed= " << exact 
                                                   >> 135      << ", parametrized= " << approx << G4endl;
137   }                                               136   }
138   if (approx >= 0. && exact < 0.) {            << 137   if(approx >= 0. && exact < 0.) {
139     if (fVerbose > 0) {                        << 138     if(fVerbose > 0) {
140       ++fWarnings;                                139       ++fWarnings;
141       if (fWarnings < maxWarnings) {           << 140       if(fWarnings < maxWarnings) {
142         G4ExceptionDescription ed;             << 141         G4ExceptionDescription ed; 
143         ed << "Sternheimer fit failed for " << << 142         ed << "Sternheimer fit failed for " << fMaterial->GetName() 
144            << ": Delta exact= " << exact << ", << 143      << ", x = " << x << ": Delta exact= "
145         G4Exception("G4DensityEffectCalculator << 144      << exact << ", approx= " << approx;
                                                   >> 145   G4Exception("G4DensityEffectCalculator::DensityCorrection", "mat008", 
                                                   >> 146                     JustWarning, ed);
146       }                                           147       }
147     }                                             148     }
148     return approx;                                149     return approx;
149   }                                               150   }
150   // Fall back to approx if exact and approx a    151   // Fall back to approx if exact and approx are very different, under the
151   // assumption that this means the exact calc    152   // assumption that this means the exact calculation has gone haywire
152   // somehow, with the exception of the case w    153   // somehow, with the exception of the case where approx is negative.  I
153   // have seen this clearly-wrong result occur    154   // have seen this clearly-wrong result occur for substances with extremely
154   // low density (1e-25 g/cc).                    155   // low density (1e-25 g/cc).
155   if (approx >= 0. && std::abs(exact - approx) << 156   if(approx >= 0. && std::abs(exact - approx) > 1.) {
156     if (fVerbose > 0) {                        << 157     if(fVerbose > 0) {
157       ++fWarnings;                                158       ++fWarnings;
158       if (fWarnings < maxWarnings) {           << 159       if(fWarnings < maxWarnings) {
159         G4ExceptionDescription ed;             << 160         G4ExceptionDescription ed; 
160         ed << "Sternheimer exact= " << exact < << 161         ed << "Sternheimer exact= " << exact << " and approx= "
161            << " are too different for " << fMa << 162            << approx << " are too different for "
162         G4Exception("G4DensityEffectCalculator << 163            << fMaterial->GetName() << ", x = " << x;
                                                   >> 164   G4Exception("G4DensityEffectCalculator::DensityCorrection", "mat008", 
                                                   >> 165                     JustWarning, ed);
163       }                                           166       }
164     }                                             167     }
165     return approx;                                168     return approx;
166   }                                               169   }
167   return exact;                                   170   return exact;
168 }                                                 171 }
169                                                   172 
170 G4double G4DensityEffectCalculator::FermiDelta    173 G4double G4DensityEffectCalculator::FermiDeltaCalculation(G4double x)
171 {                                                 174 {
172   // Above beta*gamma of 10^10, the exact trea    175   // Above beta*gamma of 10^10, the exact treatment is within machine
173   // precision of the limiting case, for ordin    176   // precision of the limiting case, for ordinary solids, at least. The
174   // convergence goes up as the density goes d    177   // convergence goes up as the density goes down, but even in a pretty
175   // hard vacuum it converges by 10^20. Also,     178   // hard vacuum it converges by 10^20. Also, it's hard to imagine how
176   // this energy is relevant (x = 20 -> 10^19     179   // this energy is relevant (x = 20 -> 10^19 GeV for muons). So this
177   // is mostly not here for physical reasons,     180   // is mostly not here for physical reasons, but rather to avoid ugly
178   // discontinuities in the return value.         181   // discontinuities in the return value.
179   if (x > 20.) {                               << 182   if(x > 20.) { return -1.; }
180     return -1.;                                << 
181   }                                            << 
182                                                   183 
183   sternx = x;                                     184   sternx = x;
184   G4double sternrho = Newton(1.5, true);          185   G4double sternrho = Newton(1.5, true);
185                                                   186 
186   // Negative values, and values much larger t    187   // Negative values, and values much larger than unity are non-physical.
187   // Values between zero and one are also susp    188   // Values between zero and one are also suspect, but not as clearly wrong.
188   if (sternrho <= 0. || sternrho > 100.) {     << 189   if(sternrho <= 0. || sternrho > 100.) {
189     if (fVerbose > 0) {                        << 190     if(fVerbose > 0) {
190       ++fWarnings;                                191       ++fWarnings;
191       if (fWarnings < maxWarnings) {           << 192       if(fWarnings < maxWarnings) {
192         G4ExceptionDescription ed;             << 193         G4ExceptionDescription ed; 
193         ed << "Sternheimer computation failed  << 194         ed << "Sternheimer computation failed for " << fMaterial->GetName() 
194            << ":\n"                            << 195      << ", x = " << x << ":\n"
195            << "Could not solve for Sternheimer << 196      << "Could not solve for Sternheimer rho. Probably you have a \n"
196            << "mean ionization energy which is << 197      << "mean ionization energy which is incompatible with your\n"
197            << "distribution of energy levels,  << 198      << "distribution of energy levels, or an unusually dense material.\n"
198            << "Number of levels: " << nlev <<  << 199      << "Number of levels: " << nlev 
199            << " Plasma energy(eV): " << plasma << 200      << " Mean ionization energy(eV): " << meanexcite 
200         for (G4int i = 0; i < nlev; ++i) {     << 201      << " Plasma energy(eV): " << plasmaE << "\n";
201           ed << "Level " << i << ": strength " << 202   for(G4int i = 0; i < nlev; ++i) {
202         }                                      << 203           ed << "Level " << i << ": strength " << sternf[i]
203         G4Exception("G4DensityEffectCalculator << 204              << ": energy(eV)= " << levE[i] << "\n";
                                                   >> 205   }
                                                   >> 206   G4Exception("G4DensityEffectCalculator::SetupFermiDeltaCalc", "mat008", 
                                                   >> 207                     JustWarning, ed);
204       }                                           208       }
205     }                                             209     }
206     return -1.;                                   210     return -1.;
207   }                                               211   }
208                                                   212 
209   // Calculate the Sternheimer adjusted energy    213   // Calculate the Sternheimer adjusted energy levels and parameters l_i given
210   // the Sternheimer parameter rho.               214   // the Sternheimer parameter rho.
211   for (G4int i = 0; i < nlev; ++i) {           << 215   for(G4int i=0; i<nlev; ++i) {
212     sternEbar[i] = levE[i] * (sternrho / plasm << 216     sternEbar[i] = levE[i] * (sternrho/plasmaE);
213     sternl[i] = std::sqrt(gpow->powN(sternEbar << 217     sternl[i] = std::sqrt(gpow->powN(sternEbar[i], 2) + (2./3.)*sternf[i]);
214   }                                               218   }
215   // The derivative of the function we are sol    219   // The derivative of the function we are solving for is strictly
216   // negative for positive (physical) values,     220   // negative for positive (physical) values, so if the value at
217   // zero is less than zero, it has no solutio    221   // zero is less than zero, it has no solution, and there is no
218   // density effect in the Sternheimer "exact"    222   // density effect in the Sternheimer "exact" treatment (which is
219   // still an approximation).                     223   // still an approximation).
220   //                                              224   //
221   // For conductors, this test is not needed,     225   // For conductors, this test is not needed, because Ell(L) contains
222   // the term fConductivity/(L*L), so the valu    226   // the term fConductivity/(L*L), so the value at L=0 is always
223   // positive infinity. In the code we don't r    227   // positive infinity. In the code we don't return inf, though, but
224   // rather set that term to zero, which means    228   // rather set that term to zero, which means that if this test were
225   // used, it would give the wrong result for     229   // used, it would give the wrong result for some materials.
226   if (fConductivity == 0 && Ell(0) <= 0) {     << 230   if(fConductivity == 0 && Ell(0) <= 0) return 0;
227     return 0;                                  << 
228   }                                            << 
229                                                   231 
230   // Attempt to find the root from 40 starting    232   // Attempt to find the root from 40 starting points evenly distributed
231   // in log space.  Trying a single starting p    233   // in log space.  Trying a single starting point is not sufficient for
232   // convergence in most cases.                   234   // convergence in most cases.
233   for (G4int startLi = -10; startLi < 30; ++st << 235   for(G4int startLi = -10; startLi < 30; ++startLi){
234     const G4double sternL = Newton(gpow->powN(    236     const G4double sternL = Newton(gpow->powN(2, startLi), false);
235     if (sternL != -1.) {                       << 237     if(sternL != -1.) {
236       return DeltaOnceSolved(sternL);             238       return DeltaOnceSolved(sternL);
237     }                                             239     }
238   }                                               240   }
239   return -1.;  // Signal the caller to use the << 241   return -1.; // Signal the caller to use the Sternheimer approximation,
240                // because we have been unable  << 242               // because we have been unable to solve the exact form.
241 }                                                 243 }
242                                                   244 
243 /* Newton's method for finding roots.  Adapted    245 /* Newton's method for finding roots.  Adapted from G4PolynominalSolver, but
244  * without the assumption that the input is a     246  * without the assumption that the input is a polynomial.  Also, here we
245  * always expect the roots to be positive, so     247  * always expect the roots to be positive, so return -1 as an error value. */
246 G4double G4DensityEffectCalculator::Newton(G4d    248 G4double G4DensityEffectCalculator::Newton(G4double start, G4bool first)
247 {                                                 249 {
248   const G4int maxIter = 100;                      250   const G4int maxIter = 100;
249   G4int nbad = 0, ngood = 0;                      251   G4int nbad = 0, ngood = 0;
250                                                   252 
251   G4double lambda(start), value(0.), dvalue(0.    253   G4double lambda(start), value(0.), dvalue(0.);
252                                                   254 
253   if (fVerbose > 2) {                          << 255   if(fVerbose > 2) {
254     G4cout << "G4DensityEffectCalculator::Newt << 256     G4cout << "G4DensityEffectCalculator::Newton: strat= " << start 
                                                   >> 257      << " type: " << first << G4endl; 
255   }                                               258   }
256   while (true) {                               << 259   while(true) {
257     if (first) {                               << 260     if(first) {
258       value = FRho(lambda);                       261       value = FRho(lambda);
259       dvalue = DFRho(lambda);                     262       dvalue = DFRho(lambda);
260     }                                          << 263     } else {
261     else {                                     << 
262       value = Ell(lambda);                        264       value = Ell(lambda);
263       dvalue = DEll(lambda);                      265       dvalue = DEll(lambda);
264     }                                             266     }
265     if (dvalue == 0.0) {                       << 267     if(dvalue == 0.0) { break; }
266       break;                                   << 268     const G4double del = value/dvalue;
267     }                                          << 
268     const G4double del = value / dvalue;       << 
269     lambda -= del;                                269     lambda -= del;
270                                                   270 
271     const G4double eps = std::abs(del / lambda << 271     const G4double eps = std::abs(del/lambda);
272     if (eps <= 1.e-12) {                       << 272     if(eps <= 1.e-12) {
273       ++ngood;                                    273       ++ngood;
274       if (ngood == 2) {                        << 274       if(ngood == 2) { 
275         if (fVerbose > 2) {                    << 275   if(fVerbose > 2) {
276           G4cout << "  Converged with result=  << 276     G4cout << "  Converged with result= " << lambda << G4endl; 
277         }                                      << 277   }
278         return lambda;                         << 278   return lambda; 
279       }                                           279       }
280     }                                          << 280     } else {
281     else {                                     << 
282       ++nbad;                                     281       ++nbad;
283     }                                             282     }
284     if (nbad > maxIter || std::isnan(value) || << 283     if(nbad > maxIter || std::isnan(value) || std::isinf(value)) { break; }
285       break;                                   << 
286     }                                          << 
287   }                                               284   }
288   if (fVerbose > 2) {                          << 285   if(fVerbose > 2) {
289     G4cout << "  Failed to converge last value << 286     G4cout << "  Failed to converge last value= " << value 
290            << " lambda= " << lambda << G4endl; << 287      << " dvalue= " << dvalue << " lambda= " << lambda << G4endl; 
291   }                                               288   }
292   return -1.;                                     289   return -1.;
293 }                                                 290 }
294                                                   291 
295 /* Return the derivative of the equation used     292 /* Return the derivative of the equation used
296  * to solve for the Sternheimer parameter rho.    293  * to solve for the Sternheimer parameter rho. */
297 G4double G4DensityEffectCalculator::DFRho(G4do    294 G4double G4DensityEffectCalculator::DFRho(G4double rho)
298 {                                                 295 {
299   G4double ans = 0.0;                             296   G4double ans = 0.0;
300   for (G4int i = 0; i < nlev; ++i) {           << 297   for(G4int i = 0; i < nlev; ++i) {
301     if (sternf[i] > 0.) {                      << 298     if(sternf[i] > 0.) {
302       ans += sternf[i] * gpow->powN(levE[i], 2    299       ans += sternf[i] * gpow->powN(levE[i], 2) * rho /
303              (gpow->powN(levE[i] * rho, 2) + 2 << 300         (gpow->powN(levE[i] * rho, 2)
                                                   >> 301          + 2./3. * sternf[i] * gpow->powN(plasmaE, 2));
304     }                                             302     }
305   }                                               303   }
306   return ans;                                     304   return ans;
307 }                                                 305 }
308                                                   306 
309 /* Return the functional value for the equatio    307 /* Return the functional value for the equation used
310  * to solve for the Sternheimer parameter rho.    308  * to solve for the Sternheimer parameter rho. */
311 G4double G4DensityEffectCalculator::FRho(G4dou    309 G4double G4DensityEffectCalculator::FRho(G4double rho)
312 {                                                 310 {
313   G4double ans = 0.0;                             311   G4double ans = 0.0;
314   for (G4int i = 0; i < nlev; ++i) {           << 312   for(G4int i = 0; i<nlev; ++i) {
315     if (sternf[i] > 0.) {                      << 313     if(sternf[i] > 0.) {
316       ans += sternf[i] *                       << 314       ans += sternf[i] * G4Log(gpow->powN(levE[i]*rho, 2) +
317              G4Log(gpow->powN(levE[i] * rho, 2 << 315         2./3. * sternf[i]*gpow->powN(plasmaE, 2));
318     }                                          << 316     }    
319   }                                               317   }
320   ans *= 0.5;  // pulled out of loop for effic << 318   ans *= 0.5; // pulled out of loop for efficiency
321                                                   319 
322   if (fConductivity > 0.) {                    << 320   if(fConductivity > 0.) {
323     ans += fConductivity * G4Log(plasmaE * std    321     ans += fConductivity * G4Log(plasmaE * std::sqrt(fConductivity));
324   }                                               322   }
325   ans -= G4Log(meanexcite);                       323   ans -= G4Log(meanexcite);
326   return ans;                                     324   return ans;
327 }                                                 325 }
328                                                   326 
329 /* Return the derivative for the equation used    327 /* Return the derivative for the equation used to
330  * solve for the Sternheimer parameter l, call    328  * solve for the Sternheimer parameter l, called 'L' here. */
331 G4double G4DensityEffectCalculator::DEll(G4dou    329 G4double G4DensityEffectCalculator::DEll(G4double L)
332 {                                                 330 {
333   G4double ans = 0.;                              331   G4double ans = 0.;
334   for (G4int i = 0; i < nlev; ++i) {           << 332   for(G4int i=0; i<nlev; ++i) {
335     if (sternf[i] > 0 && (sternEbar[i] > 0. || << 333     if(sternf[i] > 0 && (sternEbar[i] > 0. || L != 0.)) {
336       const G4double y = gpow->powN(sternEbar[    334       const G4double y = gpow->powN(sternEbar[i], 2);
337       ans += sternf[i] / gpow->powN(y + L * L, << 335       ans += sternf[i]/gpow->powN(y + L*L, 2);
338     }                                             336     }
339   }                                               337   }
340   ans += fConductivity / gpow->powN(L * L, 2); << 338   ans += fConductivity/gpow->powN(L*L, 2);
341   ans *= (-2 * L);  // pulled out of the loop  << 339   ans *= (-2*L); // pulled out of the loop for efficiency
342   return ans;                                     340   return ans;
343 }                                                 341 }
344                                                   342 
345 /* Return the functional value for the equatio    343 /* Return the functional value for the equation used to
346  * solve for the Sternheimer parameter l, call    344  * solve for the Sternheimer parameter l, called 'L' here. */
347 G4double G4DensityEffectCalculator::Ell(G4doub    345 G4double G4DensityEffectCalculator::Ell(G4double L)
348 {                                                 346 {
349   G4double ans = 0.;                              347   G4double ans = 0.;
350   for (G4int i = 0; i < nlev; ++i) {           << 348   for(G4int i=0; i<nlev; ++i) {
351     if (sternf[i] > 0. && (sternEbar[i] > 0. | << 349     if(sternf[i] > 0. && (sternEbar[i] > 0. || L != 0.)) {
352       ans += sternf[i] / (gpow->powN(sternEbar << 350       ans += sternf[i]/(gpow->powN(sternEbar[i], 2) + L*L);
353     }                                             351     }
354   }                                               352   }
355   if (fConductivity > 0. && L != 0.) {         << 353   if(fConductivity > 0. && L != 0.) {
356     ans += fConductivity / (L * L);            << 354     ans += fConductivity/(L*L);
357   }                                            << 355   }  
358   ans -= gpow->powZ(10, -2 * sternx);             356   ans -= gpow->powZ(10, -2 * sternx);
359   return ans;                                     357   return ans;
360 }                                                 358 }
361                                                   359 
362 /**                                               360 /**
363  * Given the Sternheimer parameter l (called '    361  * Given the Sternheimer parameter l (called 'sternL' here), and that
364  * the l_i and adjusted energies have been fou    362  * the l_i and adjusted energies have been found with SetupFermiDeltaCalc(),
365  * return the value of delta.  Helper function    363  * return the value of delta.  Helper function for DoFermiDeltaCalc().
366  */                                               364  */
367 G4double G4DensityEffectCalculator::DeltaOnceS    365 G4double G4DensityEffectCalculator::DeltaOnceSolved(G4double sternL)
368 {                                                 366 {
369   G4double ans = 0.;                              367   G4double ans = 0.;
370   for (G4int i = 0; i < nlev; ++i) {           << 368   for(G4int i=0; i<nlev; ++i) {
371     if (sternf[i] > 0.) {                      << 369     if(sternf[i] > 0.) {
372       ans += sternf[i] *                       << 370       ans += sternf[i] * G4Log((gpow->powN(sternl[i], 2)
373              G4Log((gpow->powN(sternl[i], 2) + << 371               + gpow->powN(sternL, 2))/gpow->powN(sternl[i], 2));
374     }                                             372     }
375   }                                               373   }
376   // sternl for the conduction electrons is sq    374   // sternl for the conduction electrons is sqrt(fConductivity), with
377   // no factor of 2./3 as with the other level    375   // no factor of 2./3 as with the other levels.
378   if (fConductivity > 0) {                     << 376   if(fConductivity > 0) {
379     ans += fConductivity * G4Log((fConductivit << 377     ans += fConductivity * G4Log((fConductivity
                                                   >> 378                   + gpow->powN(sternL, 2))/fConductivity);
380   }                                               379   }
381   ans -= gpow->powN(sternL, 2) / (1 + gpow->po << 380   ans -= gpow->powN(sternL, 2)/(1 + gpow->powZ(10, 2 * sternx));
382   return ans;                                     381   return ans;
383 }                                                 382 }
384                                                   383