Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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