View | Details | Raw Unified | Return to problem 2330
Collapse All | Expand All

(-)a/source/materials/src/G4DensityEffectCalculator.cc (-11 / +40 lines)
Lines 102-111 G4DensityEffectCalculator::G4DensityEffectCalculator(const G4Material* mat, G4in Link Here
102
  for(G4int i=0; i<nlev; ++i) {
102
  for(G4int i=0; i<nlev; ++i) {
103
    sum += sternf[i];
103
    sum += sternf[i];
104
  }
104
  }
105
  sum = (sum > 0.0) ? 1./sum : 0.0;
105
  sum += fConductivity;
106
107
  const G4double invsum = (sum > 0.0) ? 1./sum : 0.0;
106
  for(G4int i=0; i<nlev; ++i) {
108
  for(G4int i=0; i<nlev; ++i) {
107
    sternf[i] *= sum;
109
    sternf[i] *= invsum;
108
  }
110
  }
111
  fConductivity *= invsum;
112
109
  plasmaE = fMaterial->GetIonisation()->GetPlasmaEnergy()/CLHEP::eV;
113
  plasmaE = fMaterial->GetIonisation()->GetPlasmaEnergy()/CLHEP::eV;
110
  meanexcite = fMaterial->GetIonisation()->GetMeanExcitationEnergy()/CLHEP::eV;
114
  meanexcite = fMaterial->GetIonisation()->GetMeanExcitationEnergy()/CLHEP::eV;
111
}
115
}
Lines 209-224 G4double G4DensityEffectCalculator::FermiDeltaCalculation(G4double x) Link Here
209
213
210
  // Calculate the Sternheimer adjusted energy levels and parameters l_i given
214
  // Calculate the Sternheimer adjusted energy levels and parameters l_i given
211
  // the Sternheimer parameter rho.
215
  // the Sternheimer parameter rho.
212
  sternrho /= plasmaE; 
213
  for(G4int i=0; i<nlev; ++i) {
216
  for(G4int i=0; i<nlev; ++i) {
214
    sternEbar[i] = levE[i] * sternrho;
217
    sternEbar[i] = levE[i] * sternrho/plasmaE;
215
    sternl[i] = std::sqrt(gpow->powN(sternEbar[i], 2) + 2./3.*sternf[i]);
218
    sternl[i] = std::sqrt(gpow->powN(sternEbar[i], 2) + 2./3.*sternf[i]);
216
  }
219
  }
217
220
218
  // Make imphirical initial guess
221
  // The derivative of the function we are solving for is strictly
219
  const G4double sternL = Newton(sternrho, false);
222
  // negative for positive (physical) values, so if the value at
220
  if(sternL > -1.) {
223
  // zero is less than zero, it has no solution, and there is no
221
    return DeltaOnceSolved(sternL);
224
  // density effect in the Sternheimer "exact" treatment (which is
225
  // still an approximation).
226
  if(Ell(0) <= 0) return 0;
227
228
  // Attempt to find the root from 40 starting points evenly distributed
229
  // in log space.  Trying a single starting point is not sufficient for
230
  // convergence in most cases.
231
  for(G4int startLi = -10; startLi < 30; startLi++){
232
    const G4double sternL = Newton(gpow->powN(2, startLi), false);
233
    if(sternL != -1.) {
234
      return DeltaOnceSolved(sternL);
235
    }
222
  }
236
  }
223
237
224
  return -1.; // Signal the caller to use the Sternheimer approximation,
238
  return -1.; // Signal the caller to use the Sternheimer approximation,
Lines 251-257 G4double G4DensityEffectCalculator::Newton(G4double start, G4bool first) Link Here
251
    const G4double del = value/dvalue;
265
    const G4double del = value/dvalue;
252
    lambda -= del;
266
    lambda -= del;
253
267
254
    const G4double eps = std::abs(del);
268
    const G4double eps = std::abs(del/lambda);
255
    if(eps <= 1.e-12) {
269
    if(eps <= 1.e-12) {
256
      ++ngood;
270
      ++ngood;
257
      if(ngood == 2) { 
271
      if(ngood == 2) { 
Lines 263-269 G4double G4DensityEffectCalculator::Newton(G4double start, G4bool first) Link Here
263
    } else {
277
    } else {
264
      ++nbad;
278
      ++nbad;
265
    }
279
    }
266
    if(nbad > maxIter || eps > 1.) { break; }
280
    if(nbad > maxIter || std::isnan(value) || std::isinf(value)) { break; }
267
  }
281
  }
268
  if(fVerbose > 2) {
282
  if(fVerbose > 2) {
269
    G4cout << "  Failed to converge last value= " << value 
283
    G4cout << "  Failed to converge last value= " << value 
Lines 318-323 G4double G4DensityEffectCalculator::DEll(G4double L) Link Here
318
      ans += sternf[i]/gpow->powN(y + L*L, 2);
332
      ans += sternf[i]/gpow->powN(y + L*L, 2);
319
    }
333
    }
320
  }
334
  }
335
336
  ans += fConductivity/gpow->powN(L*L, 2);
337
321
  ans *= (-2*L); // pulled out of the loop for efficiency
338
  ans *= (-2*L); // pulled out of the loop for efficiency
322
  return ans;
339
  return ans;
323
}
340
}
Lines 332-343 G4double G4DensityEffectCalculator::Ell(G4double L) Link Here
332
      ans += sternf[i]/(gpow->powN(sternEbar[i], 2) + L*L);
349
      ans += sternf[i]/(gpow->powN(sternEbar[i], 2) + L*L);
333
    }
350
    }
334
  }
351
  }
352
353
  if(fConductivity > 0. && L != 0.) {
354
    ans += fConductivity/(L*L);
355
  }
356
335
  ans -= gpow->powZ(10, -2 * sternx);
357
  ans -= gpow->powZ(10, -2 * sternx);
336
  return ans;
358
  return ans;
337
}
359
}
338
360
339
/**
361
/**
340
 * Given the Sternheimer parameter l^2 (called 'sternL' here), and that
362
 * Given the Sternheimer parameter l (called 'sternL' here), and that
341
 * the l_i and adjusted energies have been found with SetupFermiDeltaCalc(),
363
 * the l_i and adjusted energies have been found with SetupFermiDeltaCalc(),
342
 * return the value of delta.  Helper function for DoFermiDeltaCalc().
364
 * return the value of delta.  Helper function for DoFermiDeltaCalc().
343
 */
365
 */
Lines 350-355 G4double G4DensityEffectCalculator::DeltaOnceSolved(G4double sternL) Link Here
350
              + gpow->powN(sternL, 2))/gpow->powN(sternl[i], 2));
372
              + gpow->powN(sternL, 2))/gpow->powN(sternl[i], 2));
351
    }
373
    }
352
  }
374
  }
375
376
  // sternl for the conduction electrons is sqrt(fConductivity), with
377
  // no factor of 2./3 as with the other levels.
378
  if(fConductivity > 0)
379
    ans += fConductivity * G4Log((fConductivity
380
                  + gpow->powN(sternL, 2))/fConductivity);
381
353
  ans -= gpow->powN(sternL, 2)/(1 + gpow->powZ(10, 2 * sternx));
382
  ans -= gpow->powN(sternL, 2)/(1 + gpow->powZ(10, 2 * sternx));
354
  return ans;
383
  return ans;
355
}
384
}

Return to problem 2330