Import Geant4 11.4.0 source tree
This commit is contained in:
@@ -31,7 +31,6 @@
|
||||
|
||||
#include "G4VSIntegration.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4Log.hh"
|
||||
|
||||
void
|
||||
G4VSIntegration::InitialiseIntegrator(G4double acc, G4double f1, G4double f2,
|
||||
@@ -61,7 +60,7 @@ G4VSIntegration::ComputeIntegral(const G4double emin, const G4double emax)
|
||||
|
||||
// preparing smart binning
|
||||
G4int nbin = G4lrint((emax - emin)/fDelta) + 1;
|
||||
nbin = std::max(nbin, 4);
|
||||
nbin = std::max(nbin, 6);
|
||||
G4double edelta = (emax - emin)/static_cast<G4double>(nbin);
|
||||
nbin += nbin;
|
||||
|
||||
@@ -109,8 +108,10 @@ G4VSIntegration::ComputeIntegral(const G4double emin, const G4double emax)
|
||||
fP1 = y;
|
||||
}
|
||||
// for the case of 2nd maximum in the 2nd area
|
||||
// shifted energy limit between the 1st and 2nd areas
|
||||
} else if (y > fP1) {
|
||||
fP2 = 0.0;
|
||||
fE1 = x;
|
||||
fP1 = y;
|
||||
fE2 = emax;
|
||||
// definition of the 3d area
|
||||
@@ -118,22 +119,28 @@ G4VSIntegration::ComputeIntegral(const G4double emin, const G4double emax)
|
||||
fE2 = x;
|
||||
fP2 = y;
|
||||
// extra maximum inside the 3d area
|
||||
// shifted energy limit between the 2nd and 3d areas
|
||||
} else if (0.0 < fP2 && y > fP2) {
|
||||
fP2 = y;
|
||||
if (y > fP1) { fP1 = y; }
|
||||
fE2 = x;
|
||||
fP2 = y;
|
||||
}
|
||||
}
|
||||
|
||||
G4double del = (y + problast)*edelta*0.5;
|
||||
res += del;
|
||||
// end of the loop
|
||||
if (del < fAcc*res || endpoint) { break; }
|
||||
|
||||
// end of the loop condition
|
||||
if ((del < fAcc*res && 0 < fP2) || endpoint) { break; }
|
||||
problast = y;
|
||||
|
||||
// smart next step definition
|
||||
if (del != res && del > 0.8*res && 0.7*edelta > fMinDelta) {
|
||||
edelta *= 0.7;
|
||||
} else if (del < 0.1*res && 1.5*edelta < fMaxDelta) {
|
||||
edelta *= 1.5;
|
||||
if (del != res) {
|
||||
if (del > 0.8*res && 0.7*edelta > fMinDelta) {
|
||||
edelta *= 0.7;
|
||||
} else if (del < 0.1*res && 1.5*edelta < fMaxDelta) {
|
||||
edelta *= 1.5;
|
||||
}
|
||||
}
|
||||
x += edelta;
|
||||
}
|
||||
@@ -153,57 +160,71 @@ G4double G4VSIntegration::SampleValue()
|
||||
// should never happen
|
||||
if (fEmin >= fEmax) { return fEmin; }
|
||||
|
||||
fPmax *= fFactor2;
|
||||
|
||||
// two regions with flat and one with exponential majorant
|
||||
G4double b = 1.0;
|
||||
// if 3d region is considered it is subdivided on 2 parts
|
||||
// so sampling may be performed in 4 energy intervals
|
||||
G4double p3 = 0.0;
|
||||
G4double p4 = 0.0;
|
||||
G4double E3 = fEmax;
|
||||
G4double Q0 = fPmax*fFactor2;
|
||||
G4double Q1 = fP1*fFactor2;
|
||||
G4double Q2 = fP2*fFactor2;
|
||||
G4double Q3 = 0.0;
|
||||
|
||||
// for some distributions it may happens that there is a local maximum
|
||||
// closed to maximal energy
|
||||
G4double Q4 = ProbabilityDensityFunction(fEmax - 0.02*(fEmax - fEmin))*fFactor2;
|
||||
Q0 = std::max(Q0, Q4);
|
||||
if (Q1 > 0.0) { Q1 = std::max(Q1, Q4); }
|
||||
|
||||
// 2d and 3d areas may be considered
|
||||
if (fP2 > 0.0 && fE2 < fEmax) {
|
||||
Q3 = 2*ProbabilityDensityFunction(fEmax - 0.5*(fEmax - fE2));
|
||||
// exclude 3d area from sampling
|
||||
if (4*Q3 > fP2 || Q3 <= 0.0) {
|
||||
fE2 = fEmax;
|
||||
// 3d area is considered
|
||||
} else {
|
||||
b = 2*G4Log(fP2/Q3)/(fEmax - fE2);
|
||||
p3 = (fP2 - Q3)/b;
|
||||
}
|
||||
}
|
||||
G4double p1 = (fE1 - fEmin)*fPmax;
|
||||
G4double p2 = (fE2 - fE1)*fP1;
|
||||
// integral under the 1st and the 2nd areas
|
||||
G4double p1 = (fE1 - fEmin)*Q0;
|
||||
G4double p2 = (fE2 - fE1)*Q1;
|
||||
|
||||
// if p2 is very small the 2nd area should not be considered
|
||||
if (p2 < 1.e-8*p1) {
|
||||
p2 = 0.0;
|
||||
p1 = (fE2 - fEmin)*fPmax;
|
||||
p1 = (fE2 - fEmin)*Q0;
|
||||
fE1 = fE2;
|
||||
}
|
||||
G4double sum = p1 + p2 + p3;
|
||||
|
||||
// 3d area may be considered
|
||||
if (Q2 > 0.0 && fE2 < fEmax) {
|
||||
E3 = fEmax - 0.5*(fEmax - fE2);
|
||||
Q3 = ProbabilityDensityFunction(E3)*fFactor2;
|
||||
Q2 = std::max(Q2, Q3);
|
||||
Q3 = std::max(Q3, Q4);
|
||||
p3 = (E3 - fE2)*Q2;
|
||||
p4 = (fEmax - E3)*Q3;
|
||||
}
|
||||
// sampling in 4 areas, probabilities may be zero except p1
|
||||
G4double sum = p1 + p2 + p3 + p4;
|
||||
G4double del1 = (fE1 - fEmin)/p1;
|
||||
G4double del2 = (p2 > 0.0) ? (fE2 - fE1)/p2 : 0.0;
|
||||
G4double del3 = (p3 > 0.0) ? (E3 - fE2)/p3 : 0.0;
|
||||
G4double del4 = (p4 > 0.0) ? (fEmax - E3)/p4 : 0.0;
|
||||
|
||||
CLHEP::HepRandomEngine* rndm = G4Random::getTheEngine();
|
||||
const G4int nmax = 1000;
|
||||
const G4int nmax = 100000;
|
||||
G4double e, gmax, gg;
|
||||
G4int n = 0;
|
||||
do {
|
||||
++n;
|
||||
for (G4int n=0; n < nmax; ++n) {
|
||||
G4double q = rndm->flat();
|
||||
G4double p = sum*q;
|
||||
G4int idx = 0;
|
||||
if (p <= p1) {
|
||||
gmax = fPmax;
|
||||
gmax = Q0;
|
||||
e = del1*p + fEmin;
|
||||
} else if (p <= p1 + p2) {
|
||||
gmax = fP1;
|
||||
gmax = Q1;
|
||||
e = del2*(p - p1) + fE1;
|
||||
idx = 1;
|
||||
} else {
|
||||
G4double x = 1.0 - rndm->flat()*(1.0 - Q3/fP2);
|
||||
e = fE2 - G4Log(x)/b;
|
||||
gmax = fP2*x;
|
||||
} else if (p <= p1 + p2 + p3) {
|
||||
gmax = Q2;
|
||||
e = del3*(p - p1 - p2) + fE2;
|
||||
idx = 2;
|
||||
} else {
|
||||
gmax = Q3;
|
||||
e = del4*(p - p1 - p2 - p3) + E3;
|
||||
idx = 3;
|
||||
}
|
||||
gg = ProbabilityDensityFunction(e);
|
||||
if ((gg > gmax || n >= nmax) && fVerbose > 0) {
|
||||
@@ -213,15 +234,28 @@ G4double G4VSIntegration::SampleValue()
|
||||
<< " in area=" << idx << " n=" << n << " gg/gmax=" << gg/gmax
|
||||
<< " prob=" << gg << " gmax=" << gmax << G4endl;
|
||||
G4cout << " E=" << e << " Emin=" << fEmin << " Emax=" << fEmax
|
||||
<< " E1=" << fE1 << " E2=" << fE2 << " Fmax=" << fPmax
|
||||
<< " F1=" << fP1 << G4endl;
|
||||
<< " E1=" << fE1 << " E2=" << fE2 << " E3=" << E3
|
||||
<< " F0=" << Q0 << " F1=" << Q1 << " F2=" << Q2 << " F3=" << Q3
|
||||
<< " F4=" << Q4 << G4endl;
|
||||
}
|
||||
}
|
||||
} while(gmax*rndm->flat() > gg && n < nmax);
|
||||
if (gmax*rndm->flat() <= gg) {
|
||||
#ifdef G4VERBOSE
|
||||
if (fVerbose > 1) {
|
||||
G4cout << "### G4VSIntegration::SampleValue for " << ModelName()
|
||||
<< " E=" << e << " Ntry=" << n
|
||||
<< " Emin=" << fEmin << " Emax=" << fEmax << G4endl;
|
||||
}
|
||||
#endif
|
||||
return e;
|
||||
}
|
||||
}
|
||||
// if sampling not converged, then sample uniformaly in the 1st energy region
|
||||
e = fEmin + rndm->flat()*(fE1 - fEmin);
|
||||
#ifdef G4VERBOSE
|
||||
if (fVerbose > 1) {
|
||||
G4cout << "### G4VSIntegration::SampleValue for " << ModelName()
|
||||
<< " E=" << e << " Ntry=" << n
|
||||
<< " E=" << e << " Ntry=" << nmax
|
||||
<< " Emin=" << fEmin << " Emax=" << fEmax << G4endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user