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