Geant4 11.1.1
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 "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