Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4FastPathHadronicCrossSection.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//
27#include "G4ios.hh"
28#include "G4DynamicParticle.hh"
29#include "G4Material.hh"
31#include <vector>
32#if defined(WIN32)
33 //Needed for M_LN10
34 #define _USE_MATH_DEFINES // for C++
35 #include <math.h>
36#endif
37#include <cmath>
38#include <array>
39
40#ifdef FPDEBUG
41#define DBG( msg ) G4cout<< msg <<G4endl;
42#define DUMP() G4cout<< <<G4endl;
43#else
44#define DBG(msg)
45#define DUMP()
46#endif
47
48using namespace G4FastPathHadronicCrossSection;
49
50//Utility functions used to perform fast-path calculations.
51//See later for details
52namespace {
53 struct Point_t {
54 double e;
55 double xs;
56 };
57 int simplify_function(G4double tolerance,
58 std::vector<Point_t> & raw_data,
59 std::vector<Point_t> & simplified_data);
60 void RemoveBias( std::vector <Point_t> &,
61 std::vector <Point_t> &,
62 std::vector <Point_t> &);
63}
64
66 particle(part),material(mat),min_cutoff(min),physicsVector(nullptr)
67 {
68 DBG("Initializing a fastPathEntry");
69#ifdef FPDEBUG
70 count = 0;
71 slowpath_sum=0.;
72 max_delta=0.;
73 min_delta=0.;
74 sum_delta=0.;
75 sum_delta_square=0.;
76#endif
77}
78
80{
81 DBG("Deleting fastPathEntry");
82 DBG("Dumping status for: "<<(particle?particle->GetParticleName():"PART_NONE")<<" "\
83 <<(material?material->GetName():"MAT_NONE")<<" min_cutoff:"<<min_cutoff<<" "\
84 <<" count:"<<count<<" slowpath_sum:"<<slowpath_sum<<" max_delta:"<<max_delta\
85 <<" min_delta"<<min_delta<<" sum_delta"<<sum_delta<<" sum_delta_squared:"<<sum_delta_square);
86 delete physicsVector;
87}
88
89//namespace {
90// static inline G4double exp10(G4double x) {
91// return std::exp( M_LN10*x);
92// }
93//}
94
96{
97 //Check this method is called when G4CrossSectionDataStore is in the correct state:
98 // FastPath is enabled and we are indeed initializing
101 using std::log10;
102 std::vector<Point_t> data_in;
103 const fastPathParameters& params = xsds->GetFastPathParameters();
104 G4double xs;
105
106 //G4double max_query = params.queryMax;
107 //G4int count = sampleCount;
108 //G4double tol = dpTol;
109
110 //Shift so max and min are >= 1.
111 //Don't forget to shift back before computing XS
112 G4double min = params.sampleMin;
113 G4double max = params.sampleMax;
114 G4double shift = 0.0;
115 if(min < 1.0){
116 shift = 1.0 - min;
117 }
118 min += shift;
119 max += shift;
120
121 G4double log_max = std::log10(params.sampleMax);
122 G4double log_min = std::log10(params.sampleMin);
123 G4double log_step = (log_max-log_min)/(1.0*params.sampleCount);
124
125 G4double max_xs = 0.0;
126
127 //Utility particle to calculate XS, with 0 kin energy by default
128 static const G4ThreeVector constDirection(0.,0.,1.);
129 G4DynamicParticle* probingParticle = new G4DynamicParticle( particle , constDirection , 0 );
130
131 //add the cutoff energy
132 probingParticle->SetKineticEnergy(min_cutoff);
133 //Sample cross-section
134 xs = xsds->GetCrossSection(probingParticle,material);
135 data_in.push_back({min_cutoff,xs});
136
137 G4double currEnergy = 0.0;
138 //log results
139 auto exp10 = [](G4double x){ return std::exp( M_LN10*x); };
140 for(G4double log_currEnergy = log_min; log_currEnergy < log_max; log_currEnergy += log_step){
141 currEnergy = exp10(log_currEnergy) - shift;
142 if (currEnergy < min_cutoff) continue;
143 probingParticle->SetKineticEnergy(currEnergy);
144 xs=xsds->GetCrossSection(probingParticle,material);
145 //G4cout << "PRUTH: energy value " << currEnergy << ", XS value " << xs << G4endl;
146 if (xs > max_xs) max_xs = xs;
147 data_in.push_back({currEnergy,xs});
148 } // --- end of loop i
149 probingParticle->SetKineticEnergy(max-shift);
150 xs = xsds->GetCrossSection(probingParticle,material);
151 data_in.push_back({max-shift,xs});
152
153 G4double tol = max_xs * 0.01;
154 std::vector<Point_t> decimated_data;
155 simplify_function(tol, data_in, decimated_data);
156 std::vector<Point_t> debiased_data;
157 RemoveBias( data_in, decimated_data, debiased_data);
158 if ( physicsVector != nullptr ) delete physicsVector;
159 physicsVector = new XSParam(decimated_data.size());
160 G4int physicsVectorIndex = 0;
161 for(size_t i = 0; i < decimated_data.size(); i++){
162 physicsVector->PutValue(physicsVectorIndex++, decimated_data[i].e, decimated_data[i].xs);
163 }
164 //xsds->DumpFastPath(particle,material,G4cout);
165}
166
168 particle(pname),material(mat),fastPath(nullptr),
169 energy(-1.),crossSection(-1.)
170{
171 DBG("Initializing cache entry");
172#ifdef FPDEBUG
173 cacheHitCount = 0;
174 initCyclesFastPath=0;
175 invocationCountSlowPath=0;
176 totalCyclesSlowPath=0;
177 invocationCountFastPath=0;
178 totalCyclesFastPath=0;
179 invocationCountTriedOneLineCache=0;
180 invocationCountOneLineCache=0;
181#endif
182}
183
185{
186 DBG("Deleting cache entry");
187 DBG(particle<<" "<<material<<" ("<<(material?material->GetName():"MAT_NONE")<<") "<<" "\
188 <<"fast path pointer:"<<fastPath<<" stored:"<<energy<<" "<<crossSection<<" "\
189 <<cacheHitCount<<" "<<initCyclesFastPath<<" "<<invocationCountSlowPath<<" "\
190 <<totalCyclesSlowPath<<" "<<invocationCountFastPath<<" "<<totalCyclesFastPath<<" "\
191 <<invocationCountTriedOneLineCache<<" "<<invocationCountOneLineCache);
192}
193
194#ifdef FPDEBUG
195namespace {
196 static inline unsigned long long rdtsc() {
197 unsigned hi=0,lo=0;
198#if defined(__GNUC__) &&( defined(__i386__)|| defined(__x86_64__) )
199 __asm__ __volatile__ ("rdtsc":"=a"(lo),"=d"(hi));
200#endif
201 return ((unsigned long long)lo) | ((unsigned long long)hi<<32 );
202 }
203}
205{
206 tm.rdtsc_start=rdtsc();
207}
209{
210 tm.rdtsc_stop=rdtsc();
211}
212#endif
214#ifdef FPDEBUG
215 methodCalled = 0;
216 hitOneLineCache=0;
217 fastPath=0;
218 slowPath=0;
219 sampleZandA = 0;
220#endif
221}
222
223namespace {
224// Rob Fowler's simplify code
225
226// This is a curve simplification routine based on the Douglas-Peucker
227// algorithm.
228// Simplifying assumptions are that the input polyline is a piecewise
229// function with the x values monotonically increasing, that the function
230// reaches an asymptote at the right (high energy) end.
231// Also, the correct error measure is the difference in y between the original
232// curve and the result.
233// In GEANT4 use, the assumption is that the calling program has identified
234// low- and high-energy cutoffs and that the vector passed in is restricted
235// to the region between the cutoffs.
236
237
238// The raw_data vector comes in ordered left to right (small energy to large).
239// The simplified_data vector is initially empty.
240
241//A.Dotti ( 16-July-2015): transform variable size C-array and use of size_t
242// to remove compilation warnings
243
244int simplify_function(G4double tolerance,
245 std::vector<Point_t> & raw_data,
246 std::vector<Point_t> & simplified_data)
247{
248
249 int gap_left, gap_right; // indices of the current region
250
251 G4double tolsq = tolerance*tolerance; // Alternative to working with absolute values.
252
253 std::vector<int> working_stack;
254 //A stack of the points to the right of the current interval that
255 // are known to be selected.
256
257 gap_right = raw_data.size() - 1; // index of the last element.
258
259 gap_left = 0;
260
261 DBG("First and last elements " << gap_left <<" " <<gap_right);
262
263 simplified_data.push_back(raw_data[0]); //copy first element over.
264
265 DBG("first point ( 0 "
266 <<simplified_data[0].e <<", "<<simplified_data[0].xs <<" )");
267
268 working_stack.push_back(gap_right); // 0th element on the stack.
269
270 while ( !working_stack.empty() )
271 { G4double a, slope, delta;
272 G4double deltasq_max= tolsq;
273 int i_max;
274
275 gap_right = working_stack.back(); //get current TOS
276 i_max = gap_right;
277
278
279 if ( (gap_left +1) < gap_right ) // At least three points in the range.
280 {
281 // co-efficients for the left to right affine line segment
282 slope = (raw_data[gap_right].xs - raw_data[gap_left].xs) /
283 (raw_data[gap_right].e - raw_data[gap_left].e);
284 a = raw_data[gap_left].xs - slope * raw_data[gap_left].e;
285
286 for ( int i = gap_left +1; i <gap_right; i++) {
287 delta = raw_data[i].xs - a - slope * raw_data[i].e;
288 if ( delta * delta > deltasq_max){
289 deltasq_max = delta * delta;
290 i_max = i;
291 }
292 }
293 } else {
294 DBG(" Less than 3 point interval at [ "<< gap_left <<", " <<gap_right<< " ]");
295 }
296
297 if(i_max < gap_right) { // Found a new point, push it on the stack
298 working_stack.push_back(i_max);
299 DBG(" pushing point " << i_max);
300 gap_right = i_max;
301 }
302 else { // didn't find a new point betweek gap_left and gap_right.
303 simplified_data.push_back(raw_data[gap_right]);
304 DBG("inserting point ("
305 <<gap_right <<", "<<raw_data[gap_right].e <<", "
306 << raw_data[gap_right].xs <<" )");
307 gap_left = gap_right;
308 working_stack.pop_back();
309 gap_right = working_stack.back();
310 DBG(" new gap_right " << gap_right);
311 }
312
313 }
314 DBG("Simplified curve size "<< simplified_data.size());
315 return (simplified_data.size());
316}
317
318// Rob Fowler's debias code
319
320// This is a de-biasing routine applied after using a curve simplification
321// routine based on the Douglas-Peucker
322// algorithm.
323// Simplifying assumptions are that the input polyline is a piecewise
324// function with the x values monotonically increasing, and
325// The right error measure is the difference in y between the original
326// curve and the result.
327
328
329
330void RemoveBias(std::vector<Point_t> & original, std::vector<Point_t> & simplified,
331 std::vector<Point_t> & result){
332
333
334 const size_t originalSize = original.size();
335 const size_t simplifiedSize = simplified.size();
336
337 //Create index mapping array
338 std::vector<G4int> xindex(simplifiedSize,0);
339 //G4int xindex[simplifiedSize];
340 G4int lastmatch = 0;
341 G4int j = 0;
342
343 DBG(" original and simplified vector sizes " << originalSize <<" "<<simplifiedSize);
344
345 for (size_t k = 0; k <simplifiedSize; k++) {
346 for (size_t i = lastmatch; i < originalSize; i++) {
347 if (original[i].e == simplified[k].e) {
348 xindex[j++] = i;
349 lastmatch = i;
350 }
351 }
352 }
353
354 DBG("Matched " << j << " values of the simplified vector");
355 // Use short names here.
356 G4int m = simplifiedSize;
357
358 std::vector<G4double> GArea(m-1,0);
359 //G4double GArea [m-1];
360 G4double GAreatotal = 0;
361
362 //Area of original simplified curve
363 for(int i = 0; i < m-1; i++){
364 G4double GAreatemp = 0;
365
366 for(j = xindex[i]; j< xindex[i+1]; j++){
367 G4double trap = (original[j+1].xs + original[j].xs) * (original[j+1].e - original[j].e)/2.0;
368 GAreatemp = GAreatemp + trap;
369 }
370 GArea[i] = GAreatemp;
371 GAreatotal = GAreatotal + GAreatemp;
372 }
373
374 DBG(" Area under the original curve " << GAreatotal);
375
376 //aleph Why is this not alpha?
377
378
379 std::vector<G4double> aleph(m-1,0);
380 //G4double aleph [m-1];
381 for(int i = 0; i< m-1; i++){
382 aleph[i] = (simplified[i+1].e - simplified[i].e)/2.0;
383 }
384
385 //solve for f
386 std::vector<G4double> adjustedy(m-1,0);
387 //G4double adjustedy [m];
388 adjustedy[m-1] = simplified[m-1].xs;
389 for(int i = 2; i < m+1; i++) {
390 adjustedy[m-i] = (GArea[m-i]/aleph[m-i]) - adjustedy[m-i+1];
391 if (adjustedy[m-i] <0.0) {
392 adjustedy[m-i] = 0.0;
393 DBG(" Fixing negative cross section at index " << (m-i));
394 }
395 }
396
397 //error and difference tracking
398 std::vector<G4double> difference(m,0.);
399 //G4double difference [m];
400 G4double maxdiff = 0;
401 G4double adjustedarea = 0;
402 G4double simplifiedarea = 0;
403 for(int i = 0; i < m-1; i++){
404 G4double trap;
405 trap = (adjustedy[i+1]+adjustedy[i])*(simplified[i+1].e-simplified[i].e)/2.0;
406 adjustedarea = adjustedarea+trap;
407 trap = (simplified[i+1].xs+simplified[i].xs)*(simplified[i+1].e-simplified[i].e)/2.0;
408 simplifiedarea = simplifiedarea + trap;
409 }
410
411 DBG(" Area: Simplified curve = " <<simplifiedarea);
412 DBG(" Area: Debiased curve = " << adjustedarea);
413
414 for(int i = 0; i <m; i++) {
415 difference[i] = simplified[i].xs-adjustedy[i];
416 }
417 for(int i = 0; i <m; i++){
418 if(std::fabs(difference[i]) > maxdiff) {
419 maxdiff = std::fabs(difference[i]);
420 }
421 }
422 // what is the significance of the loops above ?
423
424 for(size_t i = 0; i < simplifiedSize; i++){
425 result.push_back( {simplified[i].e , adjustedy[i] } );
426 }
427
428}
429
430
431}
#define DBG(msg)
double G4double
Definition: G4Types.hh:83
int G4int
Definition: G4Types.hh:85
const G4FastPathHadronicCrossSection::fastPathParameters & GetFastPathParameters() const
const G4FastPathHadronicCrossSection::controlFlag & GetFastPathControlFlags() const
G4double GetCrossSection(const G4DynamicParticle *, const G4Material *)
void SetKineticEnergy(G4double aEnergy)
const G4String & GetName() const
Definition: G4Material.hh:175
const G4String & GetParticleName() const
void PutValue(std::size_t index, G4double energy, G4double dValue)
cycleCountEntry(const G4String &pname, const G4Material *mat)
fastPathEntry(const G4ParticleDefinition *par, const G4Material *mat, G4double min_cutoff)