Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4VSIntegration.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// G4VSIntegration
27//
28// Created 03.03.2025 V.Ivanchenko
29//
30// --------------------------------------------------------------------
31
32#include "G4VSIntegration.hh"
33#include "Randomize.hh"
34
35void
37 G4double de, G4double dmin, G4double dmax)
38{
39 if (acc > 0.0) { fAcc = acc; }
40 if (f1 > 0.0 && f1 < 1.0) { fFactor1 = f1; }
41 if (f2 > 1.0 && f2 < 5.0) { fFactor2 = f2; }
42 if (de > 0.0) { fDelta = de; }
43 fMinDelta = (dmin <= de && dmin > 0.0) ? dmin : de;
44 fMaxDelta = (dmax > de) ? dmax : de;
45 if (fVerbose > 2) {
46 G4cout << "### G4VSIntegration::InitialiseIntegrator: "
47 << "fAcc=" << fAcc << " fFact1=" << fFactor1
48 << " fFact2=" << fFactor2 << " dE=" << fDelta
49 << " dEmin=" << fMinDelta << " dEmax=" << fMaxDelta << G4endl;
50 }
51}
52
55{
56 G4double res = 0.0;
57 if (emin >= emax) { return res; }
58 fEmin = emin;
59 fEmax = emax;
60
61 // preparing smart binning
62 G4int nbin = G4lrint((emax - emin)/fDelta) + 1;
63 nbin = std::max(nbin, 6);
64 G4double edelta = (emax - emin)/static_cast<G4double>(nbin);
65 nbin += nbin;
66
67 // prepare integration
68 G4double x(emin), y(0.0);
70 G4double problast = fPmax;
71#ifdef G4VERBOSE
72 if (fVerbose > 1) {
73 G4cout << "### G4VSIntegration::ComputeIntegral: "
74 << "Pmax=" << fPmax << " Emin=" << emin
75 << " Emax=" << emax << " dE=" << edelta << " nbin=" << nbin
76 << G4endl;
77 }
78#endif
79
80 fE1 = fE2 = emax;
81 fP1 = fP2 = 0.0;
82 G4bool endpoint = false;
83 x += edelta;
84 for (G4int i=0; i<=nbin; ++i) {
85 // the last point - may be earlier due to dynamic interval
86 if (x >= emax) {
87 edelta += emax - x;
88 x = emax;
89 endpoint = true;
90 }
92#ifdef G4VERBOSE
93 if (fVerbose > 2) {
94 G4cout << " " << i << ". E=" << x << " prob=" << y
95 << " Edel=" << edelta << G4endl;
96 }
97#endif
98 if (y >= fPmax) {
99 fPmax = y;
100 // for the case of 2nd maximum
101 fP1 = fP2 = 0.0;
102 fE1 = fE2 = emax;
103 } else if (!endpoint) {
104 if (0.0 == fP1) {
105 // definition of the 2nd area
106 if (y < fFactor1*fPmax) {
107 fE1 = x;
108 fP1 = y;
109 }
110 // for the case of 2nd maximum in the 2nd area
111 // shifted energy limit between the 1st and 2nd areas
112 } else if (y > fP1) {
113 fP2 = 0.0;
114 fE1 = x;
115 fP1 = y;
116 fE2 = emax;
117 // definition of the 3d area
118 } else if (0.0 == fP2 && y < fFactor1*fP1) {
119 fE2 = x;
120 fP2 = y;
121 // extra maximum inside the 3d area
122 // shifted energy limit between the 2nd and 3d areas
123 } else if (0.0 < fP2 && y > fP2) {
124 if (y > fP1) { fP1 = y; }
125 fE2 = x;
126 fP2 = y;
127 }
128 }
129
130 G4double del = (y + problast)*edelta*0.5;
131 res += del;
132
133 // end of the loop condition
134 if ((del < fAcc*res && 0 < fP2) || endpoint) { break; }
135 problast = y;
136
137 // smart next step definition
138 if (del != res) {
139 if (del > 0.8*res && 0.7*edelta > fMinDelta) {
140 edelta *= 0.7;
141 } else if (del < 0.1*res && 1.5*edelta < fMaxDelta) {
142 edelta *= 1.5;
143 }
144 }
145 x += edelta;
146 }
147#ifdef G4VERBOSE
148 if (fVerbose > 1) {
149 G4cout << "### G4VSIntegration::ComputeIntegral: "
150 << "I=" << res << " E1=" << fE1 << " E2=" << fE2
151 << " Pmax=" << fPmax << " P1=" << fP1 << " P2=" << fP2
152 << G4endl;
153 }
154#endif
155 return res;
156}
157
159{
160 // should never happen
161 if (fEmin >= fEmax) { return fEmin; }
162
163 // if 3d region is considered it is subdivided on 2 parts
164 // so sampling may be performed in 4 energy intervals
165 G4double p3 = 0.0;
166 G4double p4 = 0.0;
167 G4double E3 = fEmax;
168 G4double Q0 = fPmax*fFactor2;
169 G4double Q1 = fP1*fFactor2;
170 G4double Q2 = fP2*fFactor2;
171 G4double Q3 = 0.0;
172
173 // for some distributions it may happens that there is a local maximum
174 // closed to maximal energy
175 G4double Q4 = ProbabilityDensityFunction(fEmax - 0.02*(fEmax - fEmin))*fFactor2;
176 Q0 = std::max(Q0, Q4);
177 if (Q1 > 0.0) { Q1 = std::max(Q1, Q4); }
178
179 // integral under the 1st and the 2nd areas
180 G4double p1 = (fE1 - fEmin)*Q0;
181 G4double p2 = (fE2 - fE1)*Q1;
182
183 // if p2 is very small the 2nd area should not be considered
184 if (p2 < 1.e-8*p1) {
185 p2 = 0.0;
186 p1 = (fE2 - fEmin)*Q0;
187 fE1 = fE2;
188 }
189
190 // 3d area may be considered
191 if (Q2 > 0.0 && fE2 < fEmax) {
192 E3 = fEmax - 0.5*(fEmax - fE2);
193 Q3 = ProbabilityDensityFunction(E3)*fFactor2;
194 Q2 = std::max(Q2, Q3);
195 Q3 = std::max(Q3, Q4);
196 p3 = (E3 - fE2)*Q2;
197 p4 = (fEmax - E3)*Q3;
198 }
199 // sampling in 4 areas, probabilities may be zero except p1
200 G4double sum = p1 + p2 + p3 + p4;
201 G4double del1 = (fE1 - fEmin)/p1;
202 G4double del2 = (p2 > 0.0) ? (fE2 - fE1)/p2 : 0.0;
203 G4double del3 = (p3 > 0.0) ? (E3 - fE2)/p3 : 0.0;
204 G4double del4 = (p4 > 0.0) ? (fEmax - E3)/p4 : 0.0;
205
206 CLHEP::HepRandomEngine* rndm = G4Random::getTheEngine();
207 const G4int nmax = 100000;
208 G4double e, gmax, gg;
209 for (G4int n=0; n < nmax; ++n) {
210 G4double q = rndm->flat();
211 G4double p = sum*q;
212 G4int idx = 0;
213 if (p <= p1) {
214 gmax = Q0;
215 e = del1*p + fEmin;
216 } else if (p <= p1 + p2) {
217 gmax = Q1;
218 e = del2*(p - p1) + fE1;
219 idx = 1;
220 } else if (p <= p1 + p2 + p3) {
221 gmax = Q2;
222 e = del3*(p - p1 - p2) + fE2;
223 idx = 2;
224 } else {
225 gmax = Q3;
226 e = del4*(p - p1 - p2 - p3) + E3;
227 idx = 3;
228 }
230 if ((gg > gmax || n >= nmax) && fVerbose > 0) {
231 ++fnWarn;
232 if (fnWarn < fWarnLimit) {
233 G4cout << "### G4VSIntegration::SampleValue() for " << ModelName()
234 << " in area=" << idx << " n=" << n << " gg/gmax=" << gg/gmax
235 << " prob=" << gg << " gmax=" << gmax << G4endl;
236 G4cout << " E=" << e << " Emin=" << fEmin << " Emax=" << fEmax
237 << " E1=" << fE1 << " E2=" << fE2 << " E3=" << E3
238 << " F0=" << Q0 << " F1=" << Q1 << " F2=" << Q2 << " F3=" << Q3
239 << " F4=" << Q4 << G4endl;
240 }
241 }
242 if (gmax*rndm->flat() <= gg) {
243#ifdef G4VERBOSE
244 if (fVerbose > 1) {
245 G4cout << "### G4VSIntegration::SampleValue for " << ModelName()
246 << " E=" << e << " Ntry=" << n
247 << " Emin=" << fEmin << " Emax=" << fEmax << G4endl;
248 }
249#endif
250 return e;
251 }
252 }
253 // if sampling not converged, then sample uniformaly in the 1st energy region
254 e = fEmin + rndm->flat()*(fE1 - fEmin);
255#ifdef G4VERBOSE
256 if (fVerbose > 1) {
257 G4cout << "### G4VSIntegration::SampleValue for " << ModelName()
258 << " E=" << e << " Ntry=" << nmax
259 << " Emin=" << fEmin << " Emax=" << fEmax << G4endl;
260 }
261#endif
262 return e;
263}
264
266{
267 return dummy;
268}
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
virtual double flat()=0
virtual G4double ProbabilityDensityFunction(G4double)=0
G4double ComputeIntegral(const G4double emin, const G4double emax)
virtual const G4String & ModelName() const
void InitialiseIntegrator(G4double accuracy, G4double fact1, G4double fact2, G4double de, G4double dmin, G4double dmax)
int G4lrint(double ad)
Definition templates.hh:134