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:
27 #
28 ###############################################################################
29 */
30 
31 
37 #include <cmath>
38 
39 #include "egs_interpolator.h"
40 #include "egs_functions.h"
41 
42 EGS_Interpolator::EGS_Interpolator() : n(0), own_data(true) {};
43 
44 EGS_Interpolator::EGS_Interpolator(int nbin, EGS_Float Xmin, EGS_Float Xmax,
45  const EGS_Float *values) : n(0), own_data(true) {
46  initialize(nbin,Xmin,Xmax,values);
47 }
48 
49 EGS_Interpolator::EGS_Interpolator(int nbin, EGS_Float Xmin, EGS_Float Xmax,
50  EGS_InterpolatorFuncion func, void *data) : n(0), own_data(true) {
51  initialize(nbin,Xmax,Xmax,func,data);
52 }
53 
54 EGS_Interpolator::EGS_Interpolator(int nbin, EGS_Float Xmin, EGS_Float Xmax,
55  EGS_Float *a, EGS_Float *b) : n(0), own_data(true) {
56  initialize(nbin,Xmax,Xmax,a,b);
57 }
58 
59 EGS_Interpolator::EGS_Interpolator(EGS_Float Xmin, EGS_Float Xmax,
60  EGS_InterpolatorFuncion func, void *data,
61  int nmax, EGS_Float accu) : n(0), own_data(true) {
62  initialize(Xmin,Xmax,func,data,nmax,accu);
63 }
64 
65 void EGS_Interpolator::clear() {
66  if (n > 0 && own_data) {
67  delete [] a;
68  delete [] b;
69  n = 0;
70  }
71 }
72 
74  clear();
75 }
76 
77 void EGS_Interpolator::check(int nbin, EGS_Float Xmin, EGS_Float Xmax) {
78  if (nbin < 2) egsFatal("EGS_Interpolator::initialize: \n"
79  " attempt to initialize the interpolator with %d bins\n",nbin);
80  if (Xmin >= Xmax) egsFatal("EGS_Interpolator::initialize: \n"
81  " Xmin must be > Xmax, I got Xmin=%g Xmax=%g\n",Xmin,Xmax);
82 }
83 
84 void EGS_Interpolator::initialize(int nbin, EGS_Float Xmin, EGS_Float Xmax,
85  const EGS_Float *values) {
86  check(nbin,Xmin,Xmax);
87  clear();
88  own_data = true;
89  n = nbin - 1;
90  a = new EGS_Float [nbin], b = new EGS_Float [nbin];
91  xmin = Xmin;
92  xmax = Xmax;
93  fmin = values[0];
94  fmax = values[n];
95  EGS_Float dx = (xmax-xmin)/n;
96  bx = 1/dx;
97  ax = -xmin*bx;
98  for (int j=0; j<n; j++) {
99  b[j] = (values[j+1]-values[j])*bx;
100  a[j] = values[j] - b[j]*(xmin + dx*j);
101  }
102  /****************************************************
103  Extra subinterval at top of interval, taking care
104  of round-off errors via extrapolation.
105  Mimics PEGS4 PWLF QFIT approach.
106  *****************************************************/
107  a[n] = a[n-1];
108  b[n] = b[n-1];
109 }
110 
111 void EGS_Interpolator::initialize(int nbin, EGS_Float Xmin, EGS_Float Xmax,
112  EGS_InterpolatorFuncion func,void *data) {
113  EGS_Float *aux = new EGS_Float [nbin];
114  EGS_Float dx = (Xmax - Xmin)/(nbin-1);
115  for (int j=0; j<nbin; j++) {
116  aux[j] = func(Xmin + dx*j, data);
117  }
118  initialize(nbin,Xmin,Xmax,aux);
119  delete [] aux;
120 }
121 
122 void EGS_Interpolator::initialize(int nbin, EGS_Float Xmin, EGS_Float Xmax,
123  EGS_Float *A, EGS_Float *B) {
124  check(nbin,Xmin,Xmax);
125  clear();
126  own_data = false;
127  n = nbin - 1;
128  xmin = Xmin;
129  xmax = Xmax;
130  EGS_Float dx = (xmax-xmin)/n;
131  bx = 1/dx;
132  ax = -xmin*bx;
133  a = A;
134  b = B;
135  fmin = a[0] + b[0]*xmin;
136  fmax = a[n-1]+b[n-1]*xmax;
137 }
138 
139 void EGS_Interpolator::initialize(EGS_Float Xmin, EGS_Float Xmax,
140  EGS_InterpolatorFuncion func, void *data,
141  int nmax, EGS_Float accu) {
142  check(nmax,Xmin,Xmax);
143  clear();
144  if (nmax <= 9) {
145  initialize(nmax,Xmin,Xmax,func,data);
146  return;
147  }
148  int nnow = 9;
149  EGS_Float *tmp = new EGS_Float [nnow];
150  int j;
151  EGS_Float ddx = (Xmax-Xmin)/(nnow-1);
152  for (j=0; j<nnow; j++) {
153  tmp[j] = func(Xmin + ddx*j, data);
154  }
155  for (EGS_I64 loopCount=0; loopCount<=loopMax; ++loopCount) {
156  if (loopCount == loopMax) {
157  egsFatal("EGS_Interpolator::initialize: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
158  return;
159  }
160  EGS_Float *tmp1 = new EGS_Float [nnow-1];
161  for (j=0; j<nnow-1; j++) {
162  tmp1[j] = func(Xmin + ddx*(0.5+j),data);
163  }
164  bool ok = true;
165  for (j=0; j<nnow-1; j++) {
166  EGS_Float fint = 0.5*(tmp[j] + tmp[j+1]);
167  EGS_Float err = fabs(fint/tmp1[j]-1);
168  if (err > accu) {
169  ok = false;
170  break;
171  }
172  }
173  if (ok) {
174  initialize(nnow,Xmin,Xmax,tmp);
175  delete [] tmp;
176  delete [] tmp1;
177  return;
178  }
179  if (2*nnow-1 > nmax) {
180  delete [] tmp;
181  delete [] tmp1;
182  break;
183  }
184  EGS_Float *aux = new EGS_Float [2*nnow-1];
185  aux[0] = tmp[0];
186  int i = 1;
187  for (j=1; j<nnow; j++) {
188  aux[i++] = tmp1[j-1];
189  aux[i++] = tmp[j];
190  }
191  delete [] tmp;
192  delete [] tmp1;
193  tmp = aux;
194  nnow = 2*nnow-1;
195  ddx = (Xmax-Xmin)/(nnow-1);
196  }
197  initialize(nmax,Xmin,Xmax,func,data);
198 }
const EGS_I64 loopMax
The maximum number of iterations for near-infinite loops.
Definition: egs_functions.h:95
Global egspp functions header file.
~EGS_Interpolator()
Destructor.
void initialize(int nbin, EGS_Float Xmin, EGS_Float Xmax, EGS_InterpolatorFuncion func, void *data)
Initialize the interpolator.
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
EGS_Interpolator()
Create an empty (unitialized) interpolator.
void initialize(int nbin, EGS_Float Xmin, EGS_Float Xmax, const EGS_Float *values)
Initialize the interpolator.
EGS_Interpolator class header file.