Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4ConvergenceTester.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// G4ConvergenceTester class implementation
27//
28// Author: Koi, Tatsumi (SLAC/SCCS)
29// --------------------------------------------------------------------
30
32#include <iomanip>
33
35 : name(theName)
36{
37 nonzero_histories.clear();
38 largest_scores.clear();
39 largest_scores.push_back(0.0);
40
41 history_grid.resize(noBinOfHistory, 0);
42 mean_history.resize(noBinOfHistory, 0.0);
43 var_history.resize(noBinOfHistory, 0.0);
44 sd_history.resize(noBinOfHistory, 0.0);
45 r_history.resize(noBinOfHistory, 0.0);
46 vov_history.resize(noBinOfHistory, 0.0);
47 fom_history.resize(noBinOfHistory, 0.0);
48 shift_history.resize(noBinOfHistory, 0.0);
49 e_history.resize(noBinOfHistory, 0.0);
50 r2eff_history.resize(noBinOfHistory, 0.0);
51 r2int_history.resize(noBinOfHistory, 0.0);
52
53 timer = new G4Timer();
54 timer->Start();
55 cpu_time.clear();
56 cpu_time.push_back(0.0);
57}
58
60
62{
63 // G4cout << x << G4endl;
64
65 timer->Stop();
66 cpu_time.push_back(timer->GetSystemElapsed() + timer->GetUserElapsed());
67
68 if(x < 0.0)
69 {
70 G4cout << "Warning: G4convergenceTester expects zero or positive number as "
71 "inputs, but received a negative number."
72 << G4endl;
73 }
74
75 if(x == 0.0)
76 {
77 }
78 else
79 {
80 nonzero_histories.insert(std::pair<G4int, G4double>(n, x));
81 if(x > largest_scores.back())
82 {
83 // Following serch should become faster if begin from bottom.
84 std::vector<G4double>::iterator it;
85 for(it = largest_scores.begin(); it != largest_scores.end(); it++)
86 {
87 if(x > *it)
88 {
89 largest_scores.insert(it, x);
90 break;
91 }
92 }
93
94 if(largest_scores.size() > 201)
95 {
96 largest_scores.pop_back();
97 }
98 }
99 sum += x;
100 }
101
102 // Data has been added so statistics have not been updated to new values
103 statsAreUpdated = false;
104 n++;
105 return;
106}
107
108void G4ConvergenceTester::calStat()
109{
110 efficiency = double(nonzero_histories.size()) / n;
111
112 mean = sum / n;
113
114 G4double sum_x2 = 0.0;
115 var = 0.0;
116 shift = 0.0;
117 vov = 0.0;
118
119 G4double xi;
120 for(auto it = nonzero_histories.cbegin(); it != nonzero_histories.cend();
121 ++it)
122 {
123 xi = it->second;
124 sum_x2 += xi * xi;
125 var += (xi - mean) * (xi - mean);
126 shift += (xi - mean) * (xi - mean) * (xi - mean);
127 vov += (xi - mean) * (xi - mean) * (xi - mean) * (xi - mean);
128 }
129
130 var += (n - nonzero_histories.size()) * mean * mean;
131 shift += (n - nonzero_histories.size()) * mean * mean * mean * (-1);
132 vov += (n - nonzero_histories.size()) * mean * mean * mean * mean;
133
134 if(var != 0.0)
135 {
136 vov = vov / (var * var) - 1.0 / n;
137
138 var = var / (n - 1);
139
140 sd = std::sqrt(var);
141
142 r = sd / mean / std::sqrt(G4double(n));
143
144 r2eff = (1 - efficiency) / (efficiency * n);
145 r2int = sum_x2 / (sum * sum) - 1 / (efficiency * n);
146
147 shift = shift / (2 * var * n);
148
149 fom = 1 / (r * r) / cpu_time.back();
150 }
151
152 // Find Largest History
153 // G4double largest = 0.0;
154 largest = 0.0;
155 largest_score_happened = 0;
156 G4double spend_time_of_largest = 0.0;
157 for(auto it = nonzero_histories.cbegin(); it != nonzero_histories.cend();
158 ++it)
159 {
160 if(std::abs(it->second) > largest)
161 {
162 largest = it->second;
163 largest_score_happened = it->first;
164 spend_time_of_largest = cpu_time[it->first + 1] - cpu_time[it->first];
165 }
166 }
167
168 mean_1 = 0.0;
169 var_1 = 0.0;
170 shift_1 = 0.0;
171 vov_1 = 0.0;
172 sd_1 = 0.0;
173 r_1 = 0.0;
174 vov_1 = 0.0;
175
176 // G4cout << "The largest history = " << largest << G4endl;
177
178 mean_1 = (sum + largest) / (n + 1);
179
180 for(auto it = nonzero_histories.cbegin(); it != nonzero_histories.cend();
181 ++it)
182 {
183 xi = it->second;
184 var_1 += (xi - mean_1) * (xi - mean_1);
185 shift_1 += (xi - mean_1) * (xi - mean_1) * (xi - mean_1);
186 vov_1 += (xi - mean_1) * (xi - mean_1) * (xi - mean_1) * (xi - mean_1);
187 }
188 xi = largest;
189 var_1 += (xi - mean_1) * (xi - mean_1);
190 shift_1 += (xi - mean_1) * (xi - mean_1) * (xi - mean_1);
191 vov_1 += (xi - mean_1) * (xi - mean_1) * (xi - mean_1) * (xi - mean_1);
192
193 var_1 += (n - nonzero_histories.size()) * mean_1 * mean_1;
194
195 if(var_1 != 0.0)
196 {
197 shift_1 += (n - nonzero_histories.size()) * mean_1 * mean_1 * mean_1 * (-1);
198 vov_1 += (n - nonzero_histories.size()) * mean_1 * mean_1 * mean_1 * mean_1;
199
200 vov_1 = vov_1 / (var_1 * var_1) - 1.0 / (n + 1);
201
202 var_1 = var_1 / n;
203
204 sd_1 = std::sqrt(var_1);
205
206 r_1 = sd_1 / mean_1 / std::sqrt(G4double(n + 1));
207
208 shift_1 = shift_1 / (2 * var_1 * (n + 1));
209
210 fom_1 = 1 / (r * r) / (cpu_time.back() + spend_time_of_largest);
211 }
212
213 if(nonzero_histories.size() < 500)
214 {
215 calcSLOPE = false;
216 }
217 else
218 {
219 G4int i = G4int(nonzero_histories.size());
220
221 // 5% criterion
222 G4int j = G4int(i * 0.05);
223 while(G4int(largest_scores.size()) > j)
224 {
225 largest_scores.pop_back();
226 }
227 calc_slope_fit(largest_scores);
228 }
229
230 calc_grid_point_of_history();
231 calc_stat_history();
232
233 // statistics have been calculated and this function does not need
234 // to be called again until data has been added
235 statsAreUpdated = true;
236}
237
238void G4ConvergenceTester::calc_grid_point_of_history()
239{
240 // histroy_grid [ 0,,,15 ]
241 // history_grid [0] 1/16 ,,, history_grid [15] 16/16
242 // if number of event is x then history_grid [15] become x-1.
243 // 16 -> noBinOfHisotry
244
245 for(G4int i = 1; i <= noBinOfHistory; ++i)
246 {
247 history_grid[i - 1] = G4int(n / (G4double(noBinOfHistory)) * i - 0.1);
248 // G4cout << "history_grid " << i-1 << " " << history_grid [ i-1 ] <<
249 // G4endl;
250 }
251}
252
253void G4ConvergenceTester::calc_stat_history()
254{
255 // G4cout << "i/16 till_ith mean var sd r vov fom shift e r2eff
256 // r2int" << G4endl;
257
258 if(history_grid[0] == 0)
259 {
260 showHistory = false;
261 return;
262 }
263
264 for(G4int i = 0; i < noBinOfHistory; ++i)
265 {
266 G4int ith = history_grid[i];
267
268 G4int nonzero_till_ith = 0;
269 G4double xi;
270 G4double mean_till_ith = 0.0;
271
272 for(const auto& itr : nonzero_histories)
273 {
274 if(itr.first <= ith)
275 {
276 xi = itr.second;
277 mean_till_ith += xi;
278 ++nonzero_till_ith;
279 }
280 }
281
282 if(nonzero_till_ith == 0)
283 continue;
284
285 mean_till_ith = mean_till_ith / (ith + 1);
286 mean_history[i] = mean_till_ith;
287
288 G4double sum_x2_till_ith = 0.0;
289 G4double var_till_ith = 0.0;
290 G4double vov_till_ith = 0.0;
291 G4double shift_till_ith = 0.0;
292
293 for(const auto& itr : nonzero_histories)
294 {
295 if(itr.first <= ith)
296 {
297 xi = itr.second;
298 sum_x2_till_ith += std::pow(xi, 2.0);
299 var_till_ith += std::pow(xi - mean_till_ith, 2.0);
300 shift_till_ith += std::pow(xi - mean_till_ith, 3.0);
301 vov_till_ith += std::pow(xi - mean_till_ith, 4.0);
302 }
303 }
304
305 var_till_ith +=
306 ((ith + 1) - nonzero_till_ith) * std::pow(mean_till_ith, 2.0);
307 vov_till_ith +=
308 ((ith + 1) - nonzero_till_ith) * std::pow(mean_till_ith, 4.0);
309
310 G4double sum_till_ith = mean_till_ith * (ith + 1);
311
312 if(!(std::fabs(var_till_ith) > 0.0))
313 continue;
314 if(!(std::fabs(mean_till_ith) > 0.0))
315 continue;
316 if(!(std::fabs(sum_till_ith) > 0.0))
317 continue;
318
319 vov_till_ith = vov_till_ith / std::pow(var_till_ith, 2.0) - 1.0 / (ith + 1);
320 vov_history[i] = vov_till_ith;
321
322 var_till_ith = var_till_ith / (ith + 1 - 1);
323 var_history[i] = var_till_ith;
324 sd_history[i] = std::sqrt(var_till_ith);
325 r_history[i] =
326 std::sqrt(var_till_ith) / mean_till_ith / std::sqrt(1.0 * (ith + 1));
327
328 if(std::fabs(cpu_time[ith]) > 0.0 && std::fabs(r_history[i]) > 0.0)
329 {
330 fom_history[i] = 1.0 / std::pow(r_history[i], 2.0) / cpu_time[ith];
331 }
332 else
333 {
334 fom_history[i] = 0.0;
335 }
336
337 shift_till_ith +=
338 ((ith + 1) - nonzero_till_ith) * std::pow(mean_till_ith, 3.0) * (-1.0);
339 shift_till_ith = shift_till_ith / (2 * var_till_ith * (ith + 1));
340 shift_history[i] = shift_till_ith;
341
342 e_history[i] = 1.0 * nonzero_till_ith / (ith + 1);
343 if(std::fabs(e_history[i]) > 0.0)
344 {
345 r2eff_history[i] = (1 - e_history[i]) / (e_history[i] * (ith + 1));
346
347 r2int_history[i] = (sum_x2_till_ith) / std::pow(sum_till_ith, 2.0) -
348 1 / (e_history[i] * (ith + 1));
349 }
350 }
351}
352
353void G4ConvergenceTester::ShowResult(std::ostream& out)
354{
355 // if data has been added since the last computation of the statistical values
356 // (not statsAreUpdated) call calStat to recompute the statistical values
357 if(!statsAreUpdated)
358 {
359 calStat();
360 }
361
362 out << std::setprecision(6);
363
364 out << G4endl;
365 out << "G4ConvergenceTester Output Result of " << name << G4endl;
366 out << std::setw(20) << "EFFICIENCY = " << std::setw(13) << efficiency
367 << G4endl;
368 out << std::setw(20) << "MEAN = " << std::setw(13) << mean << G4endl;
369 out << std::setw(20) << "VAR = " << std::setw(13) << var << G4endl;
370 out << std::setw(20) << "SD = " << std::setw(13) << sd << G4endl;
371 out << std::setw(20) << "R = " << std::setw(13) << r << G4endl;
372 out << std::setw(20) << "SHIFT = " << std::setw(13) << shift << G4endl;
373 out << std::setw(20) << "VOV = " << std::setw(13) << vov << G4endl;
374 out << std::setw(20) << "FOM = " << std::setw(13) << fom << G4endl;
375
376 out << std::setw(20) << "THE LARGEST SCORE = " << std::setw(13) << largest
377 << " and it happened at " << largest_score_happened << "th event"
378 << G4endl;
379 if(mean != 0)
380 {
381 out << std::setw(20) << "Affected Mean = " << std::setw(13) << mean_1
382 << " and its ratio to original is " << mean_1 / mean << G4endl;
383 }
384 else
385 {
386 out << std::setw(20) << "Affected Mean = " << std::setw(13) << mean_1
387 << G4endl;
388 }
389 if(var != 0)
390 {
391 out << std::setw(20) << "Affected VAR = " << std::setw(13) << var_1
392 << " and its ratio to original is " << var_1 / var << G4endl;
393 }
394 else
395 {
396 out << std::setw(20) << "Affected VAR = " << std::setw(13) << var_1
397 << G4endl;
398 }
399 if(r != 0)
400 {
401 out << std::setw(20) << "Affected R = " << std::setw(13) << r_1
402 << " and its ratio to original is " << r_1 / r << G4endl;
403 }
404 else
405 {
406 out << std::setw(20) << "Affected R = " << std::setw(13) << r_1 << G4endl;
407 }
408 if(shift != 0)
409 {
410 out << std::setw(20) << "Affected SHIFT = " << std::setw(13) << shift_1
411 << " and its ratio to original is " << shift_1 / shift << G4endl;
412 }
413 else
414 {
415 out << std::setw(20) << "Affected SHIFT = " << std::setw(13) << shift_1
416 << G4endl;
417 }
418 if(fom != 0)
419 {
420 out << std::setw(20) << "Affected FOM = " << std::setw(13) << fom_1
421 << " and its ratio to original is " << fom_1 / fom << G4endl;
422 }
423 else
424 {
425 out << std::setw(20) << "Affected FOM = " << std::setw(13) << fom_1
426 << G4endl;
427 }
428
429 if(!showHistory)
430 {
431 out << "Number of events of this run is too small to do convergence tests."
432 << G4endl;
433 return;
434 }
435
436 check_stat_history(out);
437
438 // check SLOPE and output result
439 if(calcSLOPE)
440 {
441 if(slope >= 3)
442 {
443 noPass++;
444 out << "SLOPE is large enough" << G4endl;
445 }
446 else
447 {
448 out << "SLOPE is not large enough" << G4endl;
449 }
450 }
451 else
452 {
453 out << "Number of non zero history too small to calculate SLOPE" << G4endl;
454 }
455
456 out << "This result passes " << noPass << " / " << noTotal
457 << " Convergence Test." << G4endl;
458 out << G4endl;
459}
460
461void G4ConvergenceTester::ShowHistory(std::ostream& out)
462{
463 if(!showHistory)
464 {
465 out << "Number of events of this run is too small to show history."
466 << G4endl;
467 return;
468 }
469
470 out << std::setprecision(6);
471
472 out << G4endl;
473 out << "G4ConvergenceTester Output History of " << name << G4endl;
474 out << "i/" << noBinOfHistory << " till_ith mean" << std::setw(13)
475 << "var" << std::setw(13) << "sd" << std::setw(13) << "r" << std::setw(13)
476 << "vov" << std::setw(13) << "fom" << std::setw(13) << "shift"
477 << std::setw(13) << "e" << std::setw(13) << "r2eff" << std::setw(13)
478 << "r2int" << G4endl;
479 for(G4int i = 1; i <= noBinOfHistory; i++)
480 {
481 out << std::setw(4) << i << " " << std::setw(5) << history_grid[i - 1]
482 << std::setw(13) << mean_history[i - 1] << std::setw(13)
483 << var_history[i - 1] << std::setw(13) << sd_history[i - 1]
484 << std::setw(13) << r_history[i - 1] << std::setw(13)
485 << vov_history[i - 1] << std::setw(13) << fom_history[i - 1]
486 << std::setw(13) << shift_history[i - 1] << std::setw(13)
487 << e_history[i - 1] << std::setw(13) << r2eff_history[i - 1]
488 << std::setw(13) << r2int_history[i - 1] << G4endl;
489 }
490}
491
492void G4ConvergenceTester::check_stat_history(std::ostream& out)
493{
494 // 1 sigma rejection for null hypothesis
495
496 std::vector<G4double> first_ally;
497 std::vector<G4double> second_ally;
498
499 // use 2nd half of hisories
500 G4int N = mean_history.size() / 2;
501 G4int i;
502
503 G4double pearson_r;
504 G4double t;
505
506 first_ally.resize(N);
507 second_ally.resize(N);
508
509 //
510 G4double sum_of_var =
511 std::accumulate(var_history.begin(), var_history.end(), 0.0);
512 if(sum_of_var == 0.0)
513 {
514 out << "Variances in all historical grids are zero." << G4endl;
515 out << "Terminating checking behavior of statistics numbers." << G4endl;
516 return;
517 }
518
519 // Mean
520
521 for(i = 0; i < N; ++i)
522 {
523 first_ally[i] = history_grid[N + i];
524 second_ally[i] = mean_history[N + i];
525 }
526
527 pearson_r = calc_Pearson_r(N, first_ally, second_ally);
528 t = pearson_r * std::sqrt((N - 2) / (1 - pearson_r * pearson_r));
529
530 if(t < 0.429318) // Student t of (Degree of freedom = N-2 )
531 {
532 out << "MEAN distribution is RANDOM" << G4endl;
533 noPass++;
534 }
535 else
536 {
537 out << "MEAN distribution is not RANDOM" << G4endl;
538 }
539
540 // R
541
542 for(i = 0; i < N; ++i)
543 {
544 first_ally[i] = 1.0 / std::sqrt(G4double(history_grid[N + i]));
545 second_ally[i] = r_history[N + i];
546 }
547
548 pearson_r = calc_Pearson_r(N, first_ally, second_ally);
549 t = pearson_r * std::sqrt((N - 2) / (1 - pearson_r * pearson_r));
550
551 if(t > 1.090546)
552 {
553 out << "r follows 1/std::sqrt(N)" << G4endl;
554 noPass++;
555 }
556 else
557 {
558 out << "r does not follow 1/std::sqrt(N)" << G4endl;
559 }
560
561 if(is_monotonically_decrease(second_ally) == true)
562 {
563 out << "r is monotonically decrease " << G4endl;
564 }
565 else
566 {
567 out << "r is NOT monotonically decrease " << G4endl;
568 }
569
570 if(r_history.back() < 0.1)
571 {
572 out << "r is less than 0.1. r = " << r_history.back() << G4endl;
573 noPass++;
574 }
575 else
576 {
577 out << "r is NOT less than 0.1. r = " << r_history.back() << G4endl;
578 }
579
580 // VOV
581 for(i = 0; i < N; ++i)
582 {
583 first_ally[i] = 1.0 / history_grid[N + i];
584 second_ally[i] = vov_history[N + i];
585 }
586
587 pearson_r = calc_Pearson_r(N, first_ally, second_ally);
588 t = pearson_r * std::sqrt((N - 2) / (1 - pearson_r * pearson_r));
589
590 if(t > 1.090546)
591 {
592 out << "VOV follows 1/std::sqrt(N)" << G4endl;
593 noPass++;
594 }
595 else
596 {
597 out << "VOV does not follow 1/std::sqrt(N)" << G4endl;
598 }
599
600 if(is_monotonically_decrease(second_ally) == true)
601 {
602 out << "VOV is monotonically decrease " << G4endl;
603 }
604 else
605 {
606 out << "VOV is NOT monotonically decrease " << G4endl;
607 }
608
609 // FOM
610
611 for(i = 0; i < N; ++i)
612 {
613 first_ally[i] = history_grid[N + i];
614 second_ally[i] = fom_history[N + i];
615 }
616
617 pearson_r = calc_Pearson_r(N, first_ally, second_ally);
618 t = pearson_r * std::sqrt((N - 2) / (1 - pearson_r * pearson_r));
619
620 if(t < 0.429318)
621 {
622 out << "FOM distribution is RANDOM" << G4endl;
623 noPass++;
624 }
625 else
626 {
627 out << "FOM distribution is not RANDOM" << G4endl;
628 }
629}
630
631G4double G4ConvergenceTester::calc_Pearson_r(G4int N,
632 std::vector<G4double> first_ally,
633 std::vector<G4double> second_ally)
634{
635 G4double first_mean = 0.0;
636 G4double second_mean = 0.0;
637
638 G4int i;
639 for(i = 0; i < N; i++)
640 {
641 first_mean += first_ally[i];
642 second_mean += second_ally[i];
643 }
644 first_mean = first_mean / N;
645 second_mean = second_mean / N;
646
647 G4double a = 0.0;
648 for(i = 0; i < N; ++i)
649 {
650 a += (first_ally[i] - first_mean) * (second_ally[i] - second_mean);
651 }
652
653 G4double b1 = 0.0;
654 G4double b2 = 0.0;
655 for(i = 0; i < N; ++i)
656 {
657 b1 += (first_ally[i] - first_mean) * (first_ally[i] - first_mean);
658 b2 += (second_ally[i] - second_mean) * (second_ally[i] - second_mean);
659 }
660
661 G4double rds = a / std::sqrt(b1 * b2);
662
663 return rds;
664}
665
666G4bool G4ConvergenceTester::is_monotonically_decrease(
667 std::vector<G4double> ally)
668{
669 for(auto it = ally.cbegin(); it != ally.cend() - 1; ++it)
670 {
671 if(*it < *(it + 1))
672 return FALSE;
673 }
674
675 ++noPass;
676 return TRUE;
677}
678
679// void G4ConvergenceTester::calc_slope_fit ( std::vector<G4double>
680// largest_socres )
681void G4ConvergenceTester::calc_slope_fit(std::vector<G4double>)
682{
683 // create PDF bins
684 G4double max = largest_scores.front();
685 G4int last = G4int(largest_scores.size());
686 G4double min = 0.0;
687 if(largest_scores.back() != 0)
688 {
689 min = largest_scores.back();
690 }
691 else
692 {
693 min = largest_scores[last - 1];
694 last = last - 1;
695 }
696
697 // G4cout << "largest " << max << G4endl;
698 // G4cout << "last " << min << G4endl;
699
700 if(max * 0.99 < min)
701 {
702 // upper limit is assumed to have been reached
703 slope = 10.0;
704 return;
705 }
706
707 std::vector<G4double> pdf_grid;
708
709 pdf_grid.resize(noBinOfPDF + 1); // no grid = no bins + 1
710 pdf_grid[0] = max;
711 pdf_grid[noBinOfPDF] = min;
712 G4double log10_max = std::log10(max);
713 G4double log10_min = std::log10(min);
714 G4double log10_delta = log10_max - log10_min;
715 for(G4int i = 1; i < noBinOfPDF; ++i)
716 {
717 pdf_grid[i] = std::pow(10.0, log10_max - log10_delta / 10.0 * (i));
718 // G4cout << "pdf i " << i << " " << pdf_grid[i] << G4endl;
719 }
720
721 std::vector<G4double> pdf;
722 pdf.resize(noBinOfPDF);
723
724 for(G4int j = 0; j < last; ++j)
725 {
726 for(G4int i = 0; i < 11; ++i)
727 {
728 if(largest_scores[j] >= pdf_grid[i + 1])
729 {
730 pdf[i] += 1.0 / (pdf_grid[i] - pdf_grid[i + 1]) / n;
731 // G4cout << "pdf " << j << " " << i << " " << largest_scores[j] << "
732 // "
733 // << G4endl;
734 break;
735 }
736 }
737 }
738
739 f_xi.resize(noBinOfPDF);
740 f_yi.resize(noBinOfPDF);
741 for(G4int i = 0; i < noBinOfPDF; ++i)
742 {
743 // G4cout << "pdf i " << i << " " << (pdf_grid[i]+pdf_grid[i+1])/2 << " "
744 // << pdf[i] << G4endl;
745 f_xi[i] = (pdf_grid[i] + pdf_grid[i + 1]) / 2;
746 f_yi[i] = pdf[i];
747 }
748
749 // number of variables ( a and k )
750 minimizer = new G4SimplexDownhill<G4ConvergenceTester>(this, 2);
751 // G4double minimum = minimizer->GetMinimum();
752 std::vector<G4double> mp = minimizer->GetMinimumPoint();
753 G4double k = mp[1];
754
755 // G4cout << "SLOPE " << 1/mp[1]+1 << G4endl;
756 // G4cout << "SLOPE a " << mp[0] << G4endl;
757 // G4cout << "SLOPE k " << mp[1] << G4endl;
758 // G4cout << "SLOPE minimum " << minimizer->GetMinimum() << G4endl;
759
760 slope = 1 / mp[1] + 1;
761 if(k < 1.0 / 9) // Please look Pareto distribution with "sigma=a" and "k"
762 {
763 slope = 10;
764 }
765 if(slope > 10)
766 {
767 slope = 10;
768 }
769}
770
771G4double G4ConvergenceTester::slope_fitting_function(std::vector<G4double> x)
772{
773 G4double a = x[0];
774 G4double k = x[1];
775
776 if(a <= 0)
777 {
778 return 3.402823466e+38; // FLOAT_MAX
779 }
780 if(k == 0)
781 {
782 return 3.402823466e+38; // FLOAT_MAX
783 }
784
785 // f_xi and f_yi is filled at "calc_slope_fit"
786
787 G4double y = 0.0;
788 for(G4int i = 0; i < G4int(f_yi.size()); ++i)
789 {
790 // if ( 1/a * ( 1 + k * f_xi [ i ] / a ) < 0 )
791 if((1 + k * f_xi[i] / a) < 0)
792 {
793 y += 3.402823466e+38; // FLOAT_MAX
794 }
795 else
796 {
797 y += (f_yi[i] - 1 / a * std::pow(1 + k * f_xi[i] / a, -1 / k - 1)) *
798 (f_yi[i] - 1 / a * std::pow(1 + k * f_xi[i] / a, -1 / k - 1));
799 }
800 }
801 // G4cout << "y = " << y << G4endl;
802
803 return y;
804}
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define TRUE
Definition: Globals.hh:27
#define FALSE
Definition: Globals.hh:23
G4ConvergenceTester(G4String theName="NONAME")
void ShowResult(std::ostream &out=G4cout)
void ShowHistory(std::ostream &out=G4cout)
std::vector< G4double > GetMinimumPoint()
void Stop()
G4double GetSystemElapsed() const
Definition: G4Timer.cc:132
G4double GetUserElapsed() const
Definition: G4Timer.cc:143
void Start()
T max(const T t1, const T t2)
brief Return the largest of the two arguments
T min(const T t1, const T t2)
brief Return the smallest of the two arguments