EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_interpolator.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ interpolator
5 # Copyright (C) 2015 National Research Council Canada
6 #
7 # This file is part of EGSnrc.
8 #
9 # EGSnrc is free software: you can redistribute it and/or modify it under
10 # the terms of the GNU Affero General Public License as published by the
11 # Free Software Foundation, either version 3 of the License, or (at your
12 # option) any later version.
13 #
14 # EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY
15 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
17 # more details.
18 #
19 # You should have received a copy of the GNU Affero General Public License
20 # along with EGSnrc. If not, see <http://www.gnu.org/licenses/>.
21 #
22 ###############################################################################
23 #
24 # Author: Iwan Kawrakow, 2005
25 #
26 # Contributors: Ernesto Mainegra-Hing
27 # Reid Townson
28 #
29 ###############################################################################
30 */
31 
32 
38 #include <cmath>
39 
40 #include "egs_interpolator.h"
41 #include "egs_functions.h"
42 
43 EGS_Interpolator::EGS_Interpolator() : n(0), own_data(true) {};
44 
45 EGS_Interpolator::EGS_Interpolator(int nbin, EGS_Float Xmin, EGS_Float Xmax,
46  const EGS_Float *values) : n(0), own_data(true) {
47  initialize(nbin,Xmin,Xmax,values);
48 }
49 
50 EGS_Interpolator::EGS_Interpolator(int nbin, EGS_Float Xmin, EGS_Float Xmax,
51  EGS_InterpolatorFuncion func, void *data) : n(0), own_data(true) {
52  initialize(nbin,Xmax,Xmax,func,data);
53 }
54 
55 EGS_Interpolator::EGS_Interpolator(int nbin, EGS_Float Xmin, EGS_Float Xmax,
56  EGS_Float *a, EGS_Float *b) : n(0), own_data(true) {
57  initialize(nbin,Xmax,Xmax,a,b);
58 }
59 
60 EGS_Interpolator::EGS_Interpolator(EGS_Float Xmin, EGS_Float Xmax,
61  EGS_InterpolatorFuncion func, void *data,
62  int nmax, EGS_Float accu) : n(0), own_data(true) {
63  initialize(Xmin,Xmax,func,data,nmax,accu);
64 }
65 
66 void EGS_Interpolator::clear() {
67  if (n > 0 && own_data) {
68  delete [] a;
69  delete [] b;
70  n = 0;
71  }
72 }
73 
75  clear();
76 }
77 
78 void EGS_Interpolator::check(int nbin, EGS_Float Xmin, EGS_Float Xmax) {
79  if (nbin < 2) egsFatal("EGS_Interpolator::initialize: \n"
80  " attempt to initialize the interpolator with %d bins\n",nbin);
81  if (Xmin >= Xmax) egsFatal("EGS_Interpolator::initialize: \n"
82  " Xmin must be > Xmax, I got Xmin=%g Xmax=%g\n",Xmin,Xmax);
83 }
84 
85 void EGS_Interpolator::initialize(int nbin, EGS_Float Xmin, EGS_Float Xmax,
86  const EGS_Float *values) {
87  check(nbin,Xmin,Xmax);
88  clear();
89  own_data = true;
90  n = nbin - 1;
91  a = new EGS_Float [nbin], b = new EGS_Float [nbin];
92  xmin = Xmin;
93  xmax = Xmax;
94  fmin = values[0];
95  fmax = values[n];
96  EGS_Float dx = (xmax-xmin)/n;
97  bx = 1/dx;
98  ax = -xmin*bx;
99  for (int j=0; j<n; j++) {
100  b[j] = (values[j+1]-values[j])*bx;
101  a[j] = values[j] - b[j]*(xmin + dx*j);
102  }
103  /****************************************************
104  Extra subinterval at top of interval, taking care
105  of round-off errors via extrapolation.
106  Mimics PEGS4 PWLF QFIT approach.
107  *****************************************************/
108  a[n] = a[n-1];
109  b[n] = b[n-1];
110 }
111 
112 void EGS_Interpolator::initialize(int nbin, EGS_Float Xmin, EGS_Float Xmax,
113  EGS_InterpolatorFuncion func,void *data) {
114  EGS_Float *aux = new EGS_Float [nbin];
115  EGS_Float dx = (Xmax - Xmin)/(nbin-1);
116  for (int j=0; j<nbin; j++) {
117  aux[j] = func(Xmin + dx*j, data);
118  }
119  initialize(nbin,Xmin,Xmax,aux);
120  delete [] aux;
121 }
122 
123 void EGS_Interpolator::initialize(int nbin, EGS_Float Xmin, EGS_Float Xmax,
124  EGS_Float *A, EGS_Float *B) {
125  check(nbin,Xmin,Xmax);
126  clear();
127  own_data = false;
128  n = nbin - 1;
129  xmin = Xmin;
130  xmax = Xmax;
131  EGS_Float dx = (xmax-xmin)/n;
132  bx = 1/dx;
133  ax = -xmin*bx;
134  a = A;
135  b = B;
136  fmin = a[0] + b[0]*xmin;
137  fmax = a[n-1]+b[n-1]*xmax;
138 }
139 
140 void EGS_Interpolator::initialize(EGS_Float Xmin, EGS_Float Xmax,
141  EGS_InterpolatorFuncion func, void *data,
142  int nmax, EGS_Float accu) {
143  check(nmax,Xmin,Xmax);
144  clear();
145  if (nmax <= 9) {
146  initialize(nmax,Xmin,Xmax,func,data);
147  return;
148  }
149  int nnow = 9;
150  EGS_Float *tmp = new EGS_Float [nnow];
151  int j;
152  EGS_Float ddx = (Xmax-Xmin)/(nnow-1);
153  for (j=0; j<nnow; j++) {
154  tmp[j] = func(Xmin + ddx*j, data);
155  }
156  for (EGS_I64 loopCount=0; loopCount<=loopMax; ++loopCount) {
157  if (loopCount == loopMax) {
158  egsFatal("EGS_Interpolator::initialize: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
159  return;
160  }
161  EGS_Float *tmp1 = new EGS_Float [nnow-1];
162  for (j=0; j<nnow-1; j++) {
163  tmp1[j] = func(Xmin + ddx*(0.5+j),data);
164  }
165  bool ok = true;
166  for (j=0; j<nnow-1; j++) {
167  EGS_Float fint = 0.5*(tmp[j] + tmp[j+1]);
168  EGS_Float err = fabs(fint/tmp1[j]-1);
169  if (err > accu) {
170  ok = false;
171  break;
172  }
173  }
174  if (ok) {
175  initialize(nnow,Xmin,Xmax,tmp);
176  delete [] tmp;
177  delete [] tmp1;
178  return;
179  }
180  if (2*nnow-1 > nmax) {
181  delete [] tmp;
182  delete [] tmp1;
183  break;
184  }
185  EGS_Float *aux = new EGS_Float [2*nnow-1];
186  aux[0] = tmp[0];
187  int i = 1;
188  for (j=1; j<nnow; j++) {
189  aux[i++] = tmp1[j-1];
190  aux[i++] = tmp[j];
191  }
192  delete [] tmp;
193  delete [] tmp1;
194  tmp = aux;
195  nnow = 2*nnow-1;
196  ddx = (Xmax-Xmin)/(nnow-1);
197  }
198  initialize(nmax,Xmin,Xmax,func,data);
199 }
void initialize(int nbin, EGS_Float Xmin, EGS_Float Xmax, const EGS_Float *values)
Initialize the interpolator.
EGS_Interpolator()
Create an empty (unitialized) interpolator.
~EGS_Interpolator()
Destructor.
Global egspp functions header file.
EGS_Interpolator class header file.
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
const EGS_I64 loopMax
The maximum number of iterations for near-infinite loops.
Definition: egs_functions.h:96