Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // G4Integrator inline methods implementation << 27 // 26 // 28 // Author: V.Grichine, 04.09.1999 - First impl << 27 // $Id: G4Integrator.icc 80312 2014-04-10 12:20:24Z gcosmo $ 29 // G4SimpleIntegration class with H.P. << 28 // 30 // E.TCherniaev advises << 29 // Implementation of G4Integrator methods. 31 // ------------------------------------------- << 30 // >> 31 // 32 32 33 ////////////////////////////////////////////// 33 ///////////////////////////////////////////////////////////////////// 34 // 34 // 35 // Sympson integration method 35 // Sympson integration method 36 // 36 // 37 ////////////////////////////////////////////// 37 ///////////////////////////////////////////////////////////////////// 38 // 38 // 39 // Integration of class member functions T::f << 39 // Integration of class member functions T::f by Simpson method. 40 40 41 template <class T, class F> << 41 template <class T, class F> 42 G4double G4Integrator<T, F>::Simpson(T& typeT, << 42 G4double G4Integrator<T,F>::Simpson( T& typeT, 43 G4double << 43 F f, 44 { << 44 G4double xInitial, 45 G4int i; << 45 G4double xFinal, 46 G4double step = (xFinal - xInitial) / itera << 46 G4int iterationNumber ) 47 G4double x = xInitial; << 47 { 48 G4double xPlus = xInitial + 0.5 * step; << 48 G4int i ; 49 G4double mean = ((typeT.*f)(xInitial) + (ty << 49 G4double step = (xFinal - xInitial)/iterationNumber ; 50 G4double sum = (typeT.*f)(xPlus); << 50 G4double x = xInitial ; 51 << 51 G4double xPlus = xInitial + 0.5*step ; 52 for(i = 1; i < iterationNumber; ++i) << 52 G4double mean = ( (typeT.*f)(xInitial) + (typeT.*f)(xFinal) )*0.5 ; 53 { << 53 G4double sum = (typeT.*f)(xPlus) ; 54 x += step; << 54 55 xPlus += step; << 55 for(i=1;i<iterationNumber;i++) 56 mean += (typeT.*f)(x); << 56 { 57 sum += (typeT.*f)(xPlus); << 57 x += step ; 58 } << 58 xPlus += step ; 59 mean += 2.0 * sum; << 59 mean += (typeT.*f)(x) ; >> 60 sum += (typeT.*f)(xPlus) ; >> 61 } >> 62 mean += 2.0*sum ; 60 63 61 return mean * step / 3.0; << 64 return mean*step/3.0 ; 62 } 65 } 63 66 64 ////////////////////////////////////////////// 67 ///////////////////////////////////////////////////////////////////// 65 // 68 // 66 // Integration of class member functions T::f 69 // Integration of class member functions T::f by Simpson method. 67 // Convenient to use with 'this' pointer 70 // Convenient to use with 'this' pointer 68 71 69 template <class T, class F> << 72 template <class T, class F> 70 G4double G4Integrator<T, F>::Simpson(T* ptrT, << 73 G4double G4Integrator<T,F>::Simpson( T* ptrT, 71 G4double << 74 F f, 72 { << 75 G4double xInitial, 73 G4int i; << 76 G4double xFinal, 74 G4double step = (xFinal - xInitial) / itera << 77 G4int iterationNumber ) 75 G4double x = xInitial; << 78 { 76 G4double xPlus = xInitial + 0.5 * step; << 79 G4int i ; 77 G4double mean = ((ptrT->*f)(xInitial) + (pt << 80 G4double step = (xFinal - xInitial)/iterationNumber ; 78 G4double sum = (ptrT->*f)(xPlus); << 81 G4double x = xInitial ; >> 82 G4double xPlus = xInitial + 0.5*step ; >> 83 G4double mean = ( (ptrT->*f)(xInitial) + (ptrT->*f)(xFinal) )*0.5 ; >> 84 G4double sum = (ptrT->*f)(xPlus) ; >> 85 >> 86 for(i=1;i<iterationNumber;i++) >> 87 { >> 88 x += step ; >> 89 xPlus += step ; >> 90 mean += (ptrT->*f)(x) ; >> 91 sum += (ptrT->*f)(xPlus) ; >> 92 } >> 93 mean += 2.0*sum ; 79 94 80 for(i = 1; i < iterationNumber; ++i) << 95 return mean*step/3.0 ; 81 { << 82 x += step; << 83 xPlus += step; << 84 mean += (ptrT->*f)(x); << 85 sum += (ptrT->*f)(xPlus); << 86 } << 87 mean += 2.0 * sum; << 88 << 89 return mean * step / 3.0; << 90 } 96 } 91 97 92 ////////////////////////////////////////////// 98 ///////////////////////////////////////////////////////////////////// 93 // 99 // 94 // Integration of class member functions T::f 100 // Integration of class member functions T::f by Simpson method. 95 // Convenient to use, when function f is defin 101 // Convenient to use, when function f is defined in global scope, i.e. in main() 96 // program 102 // program 97 103 98 template <class T, class F> << 104 template <class T, class F> 99 G4double G4Integrator<T, F>::Simpson(G4double << 105 G4double G4Integrator<T,F>::Simpson( G4double (*f)(G4double), 100 G4double << 106 G4double xInitial, 101 { << 107 G4double xFinal, 102 G4int i; << 108 G4int iterationNumber ) 103 G4double step = (xFinal - xInitial) / itera << 109 { 104 G4double x = xInitial; << 110 G4int i ; 105 G4double xPlus = xInitial + 0.5 * step; << 111 G4double step = (xFinal - xInitial)/iterationNumber ; 106 G4double mean = ((*f)(xInitial) + (*f)(xFin << 112 G4double x = xInitial ; 107 G4double sum = (*f)(xPlus); << 113 G4double xPlus = xInitial + 0.5*step ; 108 << 114 G4double mean = ( (*f)(xInitial) + (*f)(xFinal) )*0.5 ; 109 for(i = 1; i < iterationNumber; ++i) << 115 G4double sum = (*f)(xPlus) ; 110 { << 116 111 x += step; << 117 for(i=1;i<iterationNumber;i++) 112 xPlus += step; << 118 { 113 mean += (*f)(x); << 119 x += step ; 114 sum += (*f)(xPlus); << 120 xPlus += step ; 115 } << 121 mean += (*f)(x) ; 116 mean += 2.0 * sum; << 122 sum += (*f)(xPlus) ; >> 123 } >> 124 mean += 2.0*sum ; 117 125 118 return mean * step / 3.0; << 126 return mean*step/3.0 ; 119 } 127 } 120 128 121 ////////////////////////////////////////////// 129 ////////////////////////////////////////////////////////////////////////// 122 // 130 // 123 // Adaptive Gauss method 131 // Adaptive Gauss method 124 // 132 // 125 ////////////////////////////////////////////// 133 ////////////////////////////////////////////////////////////////////////// 126 // 134 // 127 // 135 // 128 136 129 template <class T, class F> << 137 template <class T, class F> 130 G4double G4Integrator<T, F>::Gauss(T& typeT, F << 138 G4double G4Integrator<T,F>::Gauss( T& typeT, F f, 131 G4double xF << 139 G4double xInitial, G4double xFinal ) 132 { << 140 { 133 static const G4double root = 1.0 / std::sqrt << 141 static const G4double root = 1.0/std::sqrt(3.0) ; 134 << 142 135 G4double xMean = (xInitial + xFinal) / 2.0; << 143 G4double xMean = (xInitial + xFinal)/2.0 ; 136 G4double Step = (xFinal - xInitial) / 2.0; << 144 G4double Step = (xFinal - xInitial)/2.0 ; 137 G4double delta = Step * root; << 145 G4double delta = Step*root ; 138 G4double sum = ((typeT.*f)(xMean + delta) << 146 G4double sum = ((typeT.*f)(xMean + delta) + 139 << 147 (typeT.*f)(xMean - delta)) ; 140 return sum * Step; << 148 >> 149 return sum*Step ; 141 } 150 } 142 151 143 ////////////////////////////////////////////// 152 ////////////////////////////////////////////////////////////////////// 144 // 153 // 145 // 154 // 146 155 147 template <class T, class F> << 156 template <class T, class F> G4double 148 G4double G4Integrator<T, F>::Gauss(T* ptrT, F << 157 G4Integrator<T,F>::Gauss( T* ptrT, F f, G4double a, G4double b ) 149 { 158 { 150 return Gauss(*ptrT, f, a, b); << 159 return Gauss(*ptrT,f,a,b) ; 151 } 160 } 152 161 153 ////////////////////////////////////////////// 162 /////////////////////////////////////////////////////////////////////// 154 // 163 // 155 // 164 // 156 165 157 template <class T, class F> 166 template <class T, class F> 158 G4double G4Integrator<T, F>::Gauss(G4double (* << 167 G4double G4Integrator<T,F>::Gauss( G4double (*f)(G4double), 159 G4double xF << 168 G4double xInitial, G4double xFinal) 160 { 169 { 161 static const G4double root = 1.0 / std::sqrt << 170 static const G4double root = 1.0/std::sqrt(3.0) ; 162 171 163 G4double xMean = (xInitial + xFinal) / 2.0; << 172 G4double xMean = (xInitial + xFinal)/2.0 ; 164 G4double Step = (xFinal - xInitial) / 2.0; << 173 G4double Step = (xFinal - xInitial)/2.0 ; 165 G4double delta = Step * root; << 174 G4double delta = Step*root ; 166 G4double sum = ((*f)(xMean + delta) + (*f) << 175 G4double sum = ( (*f)(xMean + delta) + (*f)(xMean - delta) ) ; 167 << 176 168 return sum * Step; << 177 return sum*Step ; 169 } 178 } 170 179 171 ////////////////////////////////////////////// 180 /////////////////////////////////////////////////////////////////////////// 172 // 181 // 173 // 182 // 174 183 175 template <class T, class F> << 184 template <class T, class F> 176 void G4Integrator<T, F>::AdaptGauss(T& typeT, << 185 void G4Integrator<T,F>::AdaptGauss( T& typeT, F f, G4double xInitial, 177 G4double x << 186 G4double xFinal, G4double fTolerance, 178 G4double& << 187 G4double& sum, >> 188 G4int& depth ) >> 189 { >> 190 if(depth > 100) >> 191 { >> 192 G4cout<<"G4Integrator<T,F>::AdaptGauss: WARNING !!!"<<G4endl ; >> 193 G4cout<<"Function varies too rapidly to get stated accuracy in 100 steps " >> 194 <<G4endl ; >> 195 >> 196 return ; >> 197 } >> 198 G4double xMean = (xInitial + xFinal)/2.0 ; >> 199 G4double leftHalf = Gauss(typeT,f,xInitial,xMean) ; >> 200 G4double rightHalf = Gauss(typeT,f,xMean,xFinal) ; >> 201 G4double full = Gauss(typeT,f,xInitial,xFinal) ; >> 202 if(std::fabs(leftHalf+rightHalf-full) < fTolerance) >> 203 { >> 204 sum += full ; >> 205 } >> 206 else >> 207 { >> 208 depth++ ; >> 209 AdaptGauss(typeT,f,xInitial,xMean,fTolerance,sum,depth) ; >> 210 AdaptGauss(typeT,f,xMean,xFinal,fTolerance,sum,depth) ; >> 211 } >> 212 } >> 213 >> 214 template <class T, class F> >> 215 void G4Integrator<T,F>::AdaptGauss( T* ptrT, F f, G4double xInitial, >> 216 G4double xFinal, G4double fTolerance, >> 217 G4double& sum, >> 218 G4int& depth ) 179 { 219 { 180 if(depth > 100) << 220 AdaptGauss(*ptrT,f,xInitial,xFinal,fTolerance,sum,depth) ; 181 { << 182 G4cout << "G4Integrator<T,F>::AdaptGauss: << 183 G4cout << "Function varies too rapidly to << 184 << G4endl; << 185 << 186 return; << 187 } << 188 G4double xMean = (xInitial + xFinal) / 2 << 189 G4double leftHalf = Gauss(typeT, f, xInitia << 190 G4double rightHalf = Gauss(typeT, f, xMean, << 191 G4double full = Gauss(typeT, f, xInitia << 192 if(std::fabs(leftHalf + rightHalf - full) < << 193 { << 194 sum += full; << 195 } << 196 else << 197 { << 198 ++depth; << 199 AdaptGauss(typeT, f, xInitial, xMean, fTol << 200 AdaptGauss(typeT, f, xMean, xFinal, fToler << 201 } << 202 } << 203 << 204 template <class T, class F> << 205 void G4Integrator<T, F>::AdaptGauss(T* ptrT, F << 206 G4double x << 207 G4double& << 208 { << 209 AdaptGauss(*ptrT, f, xInitial, xFinal, fTole << 210 } 221 } 211 222 212 ////////////////////////////////////////////// 223 ///////////////////////////////////////////////////////////////////////// 213 // 224 // 214 // 225 // 215 template <class T, class F> 226 template <class T, class F> 216 void G4Integrator<T, F>::AdaptGauss(G4double ( << 227 void G4Integrator<T,F>::AdaptGauss( G4double (*f)(G4double), 217 G4double x << 228 G4double xInitial, G4double xFinal, 218 G4double& << 229 G4double fTolerance, G4double& sum, 219 { << 230 G4int& depth ) 220 if(depth > 100) << 231 { 221 { << 232 if(depth > 100) 222 G4cout << "G4SimpleIntegration::AdaptGauss << 233 { 223 G4cout << "Function varies too rapidly to << 234 G4cout<<"G4SimpleIntegration::AdaptGauss: WARNING !!!"<<G4endl ; 224 << G4endl; << 235 G4cout<<"Function varies too rapidly to get stated accuracy in 100 steps " 225 << 236 <<G4endl ; 226 return; << 237 227 } << 238 return ; 228 G4double xMean = (xInitial + xFinal) / 2 << 239 } 229 G4double leftHalf = Gauss(f, xInitial, xMea << 240 G4double xMean = (xInitial + xFinal)/2.0 ; 230 G4double rightHalf = Gauss(f, xMean, xFinal) << 241 G4double leftHalf = Gauss(f,xInitial,xMean) ; 231 G4double full = Gauss(f, xInitial, xFin << 242 G4double rightHalf = Gauss(f,xMean,xFinal) ; 232 if(std::fabs(leftHalf + rightHalf - full) < << 243 G4double full = Gauss(f,xInitial,xFinal) ; 233 { << 244 if(std::fabs(leftHalf+rightHalf-full) < fTolerance) 234 sum += full; << 245 { 235 } << 246 sum += full ; 236 else << 247 } 237 { << 248 else 238 ++depth; << 249 { 239 AdaptGauss(f, xInitial, xMean, fTolerance, << 250 depth++ ; 240 AdaptGauss(f, xMean, xFinal, fTolerance, s << 251 AdaptGauss(f,xInitial,xMean,fTolerance,sum,depth) ; 241 } << 252 AdaptGauss(f,xMean,xFinal,fTolerance,sum,depth) ; >> 253 } 242 } 254 } 243 255 244 ////////////////////////////////////////////// 256 //////////////////////////////////////////////////////////////////////// 245 // 257 // 246 // Adaptive Gauss integration with accuracy 'e 258 // Adaptive Gauss integration with accuracy 'e' 247 // Convenient for using with class object type 259 // Convenient for using with class object typeT 248 << 260 249 template <class T, class F> << 261 template<class T, class F> 250 G4double G4Integrator<T, F>::AdaptiveGauss(T& << 262 G4double G4Integrator<T,F>::AdaptiveGauss( T& typeT, F f, G4double xInitial, 251 G4d << 263 G4double xFinal, G4double e ) 252 { << 264 { 253 G4int depth = 0; << 265 G4int depth = 0 ; 254 G4double sum = 0.0; << 266 G4double sum = 0.0 ; 255 AdaptGauss(typeT, f, xInitial, xFinal, e, su << 267 AdaptGauss(typeT,f,xInitial,xFinal,e,sum,depth) ; 256 return sum; << 268 return sum ; 257 } 269 } 258 270 259 ////////////////////////////////////////////// 271 //////////////////////////////////////////////////////////////////////// 260 // 272 // 261 // Adaptive Gauss integration with accuracy 'e 273 // Adaptive Gauss integration with accuracy 'e' 262 // Convenient for using with 'this' pointer 274 // Convenient for using with 'this' pointer 263 << 275 264 template <class T, class F> << 276 template<class T, class F> 265 G4double G4Integrator<T, F>::AdaptiveGauss(T* << 277 G4double G4Integrator<T,F>::AdaptiveGauss( T* ptrT, F f, G4double xInitial, 266 G4d << 278 G4double xFinal, G4double e ) 267 { 279 { 268 return AdaptiveGauss(*ptrT, f, xInitial, xFi << 280 return AdaptiveGauss(*ptrT,f,xInitial,xFinal,e) ; 269 } 281 } 270 282 271 ////////////////////////////////////////////// 283 //////////////////////////////////////////////////////////////////////// 272 // 284 // 273 // Adaptive Gauss integration with accuracy 'e 285 // Adaptive Gauss integration with accuracy 'e' 274 // Convenient for using with global scope func 286 // Convenient for using with global scope function f 275 << 287 276 template <class T, class F> 288 template <class T, class F> 277 G4double G4Integrator<T, F>::AdaptiveGauss(G4d << 289 G4double G4Integrator<T,F>::AdaptiveGauss( G4double (*f)(G4double), 278 G4d << 290 G4double xInitial, G4double xFinal, G4double e ) 279 G4d << 291 { 280 { << 292 G4int depth = 0 ; 281 G4int depth = 0; << 293 G4double sum = 0.0 ; 282 G4double sum = 0.0; << 294 AdaptGauss(f,xInitial,xFinal,e,sum,depth) ; 283 AdaptGauss(f, xInitial, xFinal, e, sum, dept << 295 return sum ; 284 return sum; << 285 } 296 } 286 297 287 ////////////////////////////////////////////// 298 //////////////////////////////////////////////////////////////////////////// 288 // Gauss integration methods involving ortogon 299 // Gauss integration methods involving ortogonal polynomials 289 ////////////////////////////////////////////// 300 //////////////////////////////////////////////////////////////////////////// 290 // 301 // 291 // Methods involving Legendre polynomials << 302 // Methods involving Legendre polynomials 292 // 303 // 293 ////////////////////////////////////////////// 304 ///////////////////////////////////////////////////////////////////////// 294 // 305 // 295 // The value nLegendre set the accuracy requir 306 // The value nLegendre set the accuracy required, i.e the number of points 296 // where the function pFunction will be evalua 307 // where the function pFunction will be evaluated during integration. 297 // The function creates the arrays for absciss << 308 // The function creates the arrays for abscissas and weights that used 298 // in Gauss-Legendre quadrature method. << 309 // in Gauss-Legendre quadrature method. 299 // The values a and b are the limits of integr 310 // The values a and b are the limits of integration of the function f . 300 // nLegendre MUST BE EVEN !!! 311 // nLegendre MUST BE EVEN !!! 301 // Returns the integral of the function f betw << 312 // Returns the integral of the function f between a and b, by 2*fNumber point 302 // Gauss-Legendre integration: the function is 313 // Gauss-Legendre integration: the function is evaluated exactly 303 // 2*fNumber times at interior points in the r << 314 // 2*fNumber times at interior points in the range of integration. 304 // Since the weights and abscissas are, in thi << 315 // Since the weights and abscissas are, in this case, symmetric around 305 // the midpoint of the range of integration, t << 316 // the midpoint of the range of integration, there are actually only 306 // fNumber distinct values of each. 317 // fNumber distinct values of each. 307 // Convenient for using with some class object 318 // Convenient for using with some class object dataT 308 319 309 template <class T, class F> 320 template <class T, class F> 310 G4double G4Integrator<T, F>::Legendre(T& typeT << 321 G4double G4Integrator<T,F>::Legendre( T& typeT, F f, G4double a, G4double b, 311 G4int nL << 322 G4int nLegendre ) 312 { 323 { 313 G4double nwt, nwt1, temp1, temp2, temp3, tem << 324 G4double nwt, nwt1, temp1, temp2, temp3, temp ; 314 G4double xDiff, xMean, dx, integral; << 325 G4double xDiff, xMean, dx, integral ; 315 << 316 const G4double tolerance = 1.6e-10; << 317 G4int i, j, k = nLegendre; << 318 G4int fNumber = (nLegendre + 1) / 2; << 319 << 320 if(2 * fNumber != k) << 321 { << 322 G4Exception("G4Integrator<T,F>::Legendre(T << 323 FatalException, "Invalid (odd) << 324 } << 325 326 326 G4double* fAbscissa = new G4double[fNumber]; << 327 const G4double tolerance = 1.6e-10 ; 327 G4double* fWeight = new G4double[fNumber]; << 328 G4int i, j, k = nLegendre ; 328 << 329 G4int fNumber = (nLegendre + 1)/2 ; 329 for(i = 1; i <= fNumber; ++i) // Loop over << 330 330 { << 331 if(2*fNumber != k) 331 nwt = std::cos(CLHEP::pi * (i - 0.25) / << 332 { 332 (k + 0.5)); // Initial roo << 333 G4Exception("G4Integrator<T,F>::Legendre(T&,F, ...)", "InvalidCall", 333 << 334 FatalException, "Invalid (odd) nLegendre in constructor."); 334 do // loop of Newton's method << 335 } 335 { << 336 336 temp1 = 1.0; << 337 G4double* fAbscissa = new G4double[fNumber] ; 337 temp2 = 0.0; << 338 G4double* fWeight = new G4double[fNumber] ; 338 for(j = 1; j <= k; ++j) << 339 339 { << 340 for(i=1;i<=fNumber;i++) // Loop over the desired roots 340 temp3 = temp2; << 341 { 341 temp2 = temp1; << 342 nwt = std::cos(CLHEP::pi*(i - 0.25)/(k + 0.5)) ; // Initial root approximation 342 temp1 = ((2.0 * j - 1.0) * nwt * temp2 << 343 343 } << 344 do // loop of Newton's method 344 temp = k * (nwt * temp1 - temp2) / (nwt << 345 { 345 nwt1 = nwt; << 346 temp1 = 1.0 ; 346 nwt = nwt1 - temp1 / temp; // Newton's << 347 temp2 = 0.0 ; 347 } while(std::fabs(nwt - nwt1) > tolerance) << 348 for(j=1;j<=k;j++) 348 << 349 { 349 fAbscissa[fNumber - i] = nwt; << 350 temp3 = temp2 ; 350 fWeight[fNumber - i] = 2.0 / ((1.0 - nwt << 351 temp2 = temp1 ; 351 } << 352 temp1 = ((2.0*j - 1.0)*nwt*temp2 - (j - 1.0)*temp3)/j ; 352 << 353 } 353 // << 354 temp = k*(nwt*temp1 - temp2)/(nwt*nwt - 1.0) ; 354 // Now we ready to get integral << 355 nwt1 = nwt ; 355 // << 356 nwt = nwt1 - temp1/temp ; // Newton's method 356 << 357 } 357 xMean = 0.5 * (a + b); << 358 while(std::fabs(nwt - nwt1) > tolerance) ; 358 xDiff = 0.5 * (b - a); << 359 359 integral = 0.0; << 360 fAbscissa[fNumber-i] = nwt ; 360 for(i = 0; i < fNumber; ++i) << 361 fWeight[fNumber-i] = 2.0/((1.0 - nwt*nwt)*temp*temp) ; 361 { << 362 } 362 dx = xDiff * fAbscissa[i]; << 363 363 integral += fWeight[i] * ((typeT.*f)(xMean << 364 // 364 } << 365 // Now we ready to get integral 365 delete[] fAbscissa; << 366 // 366 delete[] fWeight; << 367 367 return integral *= xDiff; << 368 xMean = 0.5*(a + b) ; 368 } << 369 xDiff = 0.5*(b - a) ; >> 370 integral = 0.0 ; >> 371 for(i=0;i<fNumber;i++) >> 372 { >> 373 dx = xDiff*fAbscissa[i] ; >> 374 integral += fWeight[i]*( (typeT.*f)(xMean + dx) + >> 375 (typeT.*f)(xMean - dx) ) ; >> 376 } >> 377 delete[] fAbscissa; >> 378 delete[] fWeight; >> 379 return integral *= xDiff ; >> 380 } 369 381 370 ////////////////////////////////////////////// 382 /////////////////////////////////////////////////////////////////////// 371 // 383 // 372 // Convenient for using with the pointer 'this 384 // Convenient for using with the pointer 'this' 373 385 374 template <class T, class F> 386 template <class T, class F> 375 G4double G4Integrator<T, F>::Legendre(T* ptrT, << 387 G4double G4Integrator<T,F>::Legendre( T* ptrT, F f, G4double a, 376 G4int nL << 388 G4double b, G4int nLegendre ) 377 { 389 { 378 return Legendre(*ptrT, f, a, b, nLegendre); << 390 return Legendre(*ptrT,f,a,b,nLegendre) ; 379 } 391 } 380 392 381 ////////////////////////////////////////////// 393 /////////////////////////////////////////////////////////////////////// 382 // 394 // 383 // Convenient for using with global scope func 395 // Convenient for using with global scope function f 384 396 385 template <class T, class F> 397 template <class T, class F> 386 G4double G4Integrator<T, F>::Legendre(G4double << 398 G4double G4Integrator<T,F>::Legendre( G4double (*f)(G4double), 387 G4double << 399 G4double a, G4double b, G4int nLegendre) 388 { 400 { 389 G4double nwt, nwt1, temp1, temp2, temp3, tem << 401 G4double nwt, nwt1, temp1, temp2, temp3, temp ; 390 G4double xDiff, xMean, dx, integral; << 402 G4double xDiff, xMean, dx, integral ; 391 << 392 const G4double tolerance = 1.6e-10; << 393 G4int i, j, k = nLegendre; << 394 G4int fNumber = (nLegendre + 1) / 2; << 395 << 396 if(2 * fNumber != k) << 397 { << 398 G4Exception("G4Integrator<T,F>::Legendre(. << 399 FatalException, "Invalid (odd) << 400 } << 401 403 402 G4double* fAbscissa = new G4double[fNumber]; << 404 const G4double tolerance = 1.6e-10 ; 403 G4double* fWeight = new G4double[fNumber]; << 405 G4int i, j, k = nLegendre ; 404 << 406 G4int fNumber = (nLegendre + 1)/2 ; 405 for(i = 1; i <= fNumber; i++) // Loop over << 407 406 { << 408 if(2*fNumber != k) 407 nwt = std::cos(CLHEP::pi * (i - 0.25) / << 409 { 408 (k + 0.5)); // Initial roo << 410 G4Exception("G4Integrator<T,F>::Legendre(...)", "InvalidCall", 409 << 411 FatalException, "Invalid (odd) nLegendre in constructor."); 410 do // loop of Newton's method << 412 } 411 { << 413 412 temp1 = 1.0; << 414 G4double* fAbscissa = new G4double[fNumber] ; 413 temp2 = 0.0; << 415 G4double* fWeight = new G4double[fNumber] ; 414 for(j = 1; j <= k; ++j) << 416 415 { << 417 for(i=1;i<=fNumber;i++) // Loop over the desired roots 416 temp3 = temp2; << 418 { 417 temp2 = temp1; << 419 nwt = std::cos(CLHEP::pi*(i - 0.25)/(k + 0.5)) ; // Initial root approximation 418 temp1 = ((2.0 * j - 1.0) * nwt * temp2 << 420 419 } << 421 do // loop of Newton's method 420 temp = k * (nwt * temp1 - temp2) / (nwt << 422 { 421 nwt1 = nwt; << 423 temp1 = 1.0 ; 422 nwt = nwt1 - temp1 / temp; // Newton's << 424 temp2 = 0.0 ; 423 } while(std::fabs(nwt - nwt1) > tolerance) << 425 for(j=1;j<=k;j++) 424 << 426 { 425 fAbscissa[fNumber - i] = nwt; << 427 temp3 = temp2 ; 426 fWeight[fNumber - i] = 2.0 / ((1.0 - nwt << 428 temp2 = temp1 ; 427 } << 429 temp1 = ((2.0*j - 1.0)*nwt*temp2 - (j - 1.0)*temp3)/j ; 428 << 430 } 429 // << 431 temp = k*(nwt*temp1 - temp2)/(nwt*nwt - 1.0) ; 430 // Now we ready to get integral << 432 nwt1 = nwt ; 431 // << 433 nwt = nwt1 - temp1/temp ; // Newton's method 432 << 434 } 433 xMean = 0.5 * (a + b); << 435 while(std::fabs(nwt - nwt1) > tolerance) ; 434 xDiff = 0.5 * (b - a); << 436 435 integral = 0.0; << 437 fAbscissa[fNumber-i] = nwt ; 436 for(i = 0; i < fNumber; ++i) << 438 fWeight[fNumber-i] = 2.0/((1.0 - nwt*nwt)*temp*temp) ; 437 { << 439 } 438 dx = xDiff * fAbscissa[i]; << 440 439 integral += fWeight[i] * ((*f)(xMean + dx) << 441 // 440 } << 442 // Now we ready to get integral 441 delete[] fAbscissa; << 443 // 442 delete[] fWeight; << 444 >> 445 xMean = 0.5*(a + b) ; >> 446 xDiff = 0.5*(b - a) ; >> 447 integral = 0.0 ; >> 448 for(i=0;i<fNumber;i++) >> 449 { >> 450 dx = xDiff*fAbscissa[i] ; >> 451 integral += fWeight[i]*( (*f)(xMean + dx) + (*f)(xMean - dx) ) ; >> 452 } >> 453 delete[] fAbscissa; >> 454 delete[] fWeight; 443 455 444 return integral *= xDiff; << 456 return integral *= xDiff ; 445 } << 457 } 446 458 447 ////////////////////////////////////////////// 459 //////////////////////////////////////////////////////////////////////////// 448 // 460 // 449 // Returns the integral of the function to be 461 // Returns the integral of the function to be pointed by T::f between a and b, 450 // by ten point Gauss-Legendre integration: th 462 // by ten point Gauss-Legendre integration: the function is evaluated exactly 451 // ten times at interior points in the range o 463 // ten times at interior points in the range of integration. Since the weights 452 // and abscissas are, in this case, symmetric << 464 // and abscissas are, in this case, symmetric around the midpoint of the 453 // range of integration, there are actually on 465 // range of integration, there are actually only five distinct values of each 454 // Convenient for using with class object type 466 // Convenient for using with class object typeT 455 467 456 template <class T, class F> << 468 template <class T, class F> 457 G4double G4Integrator<T, F>::Legendre10(T& typ << 469 G4double G4Integrator<T,F>::Legendre10( T& typeT, F f,G4double a, G4double b) 458 { 470 { 459 G4int i; << 471 G4int i ; 460 G4double xDiff, xMean, dx, integral; << 472 G4double xDiff, xMean, dx, integral ; 461 << 473 462 // From Abramowitz M., Stegan I.A. 1964 , Ha << 474 // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 916 463 << 475 464 static const G4double abscissa[] = { 0.14887 << 476 static const G4double abscissa[] = { 0.148874338981631, 0.433395394129247, 465 0.67940 << 477 0.679409568299024, 0.865063366688985, 466 0.97390 << 478 0.973906528517172 } ; 467 << 479 468 static const G4double weight[] = { 0.2955242 << 480 static const G4double weight[] = { 0.295524224714753, 0.269266719309996, 469 0.2190863 << 481 0.219086362515982, 0.149451349150581, 470 0.0666713 << 482 0.066671344308688 } ; 471 xMean = 0.5 * (a + << 483 xMean = 0.5*(a + b) ; 472 xDiff = 0.5 * (b - << 484 xDiff = 0.5*(b - a) ; 473 integral = 0.0; << 485 integral = 0.0 ; 474 for(i = 0; i < 5; ++i) << 486 for(i=0;i<5;i++) 475 { << 487 { 476 dx = xDiff * abscissa[i]; << 488 dx = xDiff*abscissa[i] ; 477 integral += weight[i] * ((typeT.*f)(xMean << 489 integral += weight[i]*( (typeT.*f)(xMean + dx) + (typeT.*f)(xMean - dx)) ; 478 } << 490 } 479 return integral *= xDiff; << 491 return integral *= xDiff ; 480 } 492 } 481 493 482 ////////////////////////////////////////////// 494 /////////////////////////////////////////////////////////////////////////// 483 // 495 // 484 // Convenient for using with the pointer 'this 496 // Convenient for using with the pointer 'this' 485 497 486 template <class T, class F> << 498 template <class T, class F> 487 G4double G4Integrator<T, F>::Legendre10(T* ptr << 499 G4double G4Integrator<T,F>::Legendre10( T* ptrT, F f,G4double a, G4double b) 488 { 500 { 489 return Legendre10(*ptrT, f, a, b); << 501 return Legendre10(*ptrT,f,a,b) ; 490 } << 502 } 491 503 492 ////////////////////////////////////////////// 504 ////////////////////////////////////////////////////////////////////////// 493 // 505 // 494 // Convenient for using with global scope func 506 // Convenient for using with global scope functions 495 507 496 template <class T, class F> 508 template <class T, class F> 497 G4double G4Integrator<T, F>::Legendre10(G4doub << 509 G4double G4Integrator<T,F>::Legendre10( G4double (*f)(G4double), 498 G4doub << 510 G4double a, G4double b ) 499 { 511 { 500 G4int i; << 512 G4int i ; 501 G4double xDiff, xMean, dx, integral; << 513 G4double xDiff, xMean, dx, integral ; 502 << 514 503 // From Abramowitz M., Stegan I.A. 1964 , Ha << 515 // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 916 504 << 516 505 static const G4double abscissa[] = { 0.14887 << 517 static const G4double abscissa[] = { 0.148874338981631, 0.433395394129247, 506 0.67940 << 518 0.679409568299024, 0.865063366688985, 507 0.97390 << 519 0.973906528517172 } ; 508 << 520 509 static const G4double weight[] = { 0.2955242 << 521 static const G4double weight[] = { 0.295524224714753, 0.269266719309996, 510 0.2190863 << 522 0.219086362515982, 0.149451349150581, 511 0.0666713 << 523 0.066671344308688 } ; 512 xMean = 0.5 * (a + << 524 xMean = 0.5*(a + b) ; 513 xDiff = 0.5 * (b - << 525 xDiff = 0.5*(b - a) ; 514 integral = 0.0; << 526 integral = 0.0 ; 515 for(i = 0; i < 5; ++i) << 527 for(i=0;i<5;i++) 516 { << 528 { 517 dx = xDiff * abscissa[i]; << 529 dx = xDiff*abscissa[i] ; 518 integral += weight[i] * ((*f)(xMean + dx) << 530 integral += weight[i]*( (*f)(xMean + dx) + (*f)(xMean - dx)) ; 519 } << 531 } 520 return integral *= xDiff; << 532 return integral *= xDiff ; 521 } 533 } 522 534 523 ////////////////////////////////////////////// 535 /////////////////////////////////////////////////////////////////////// 524 // 536 // 525 // Returns the integral of the function to be 537 // Returns the integral of the function to be pointed by T::f between a and b, 526 // by 96 point Gauss-Legendre integration: the 538 // by 96 point Gauss-Legendre integration: the function is evaluated exactly 527 // ten Times at interior points in the range o 539 // ten Times at interior points in the range of integration. Since the weights 528 // and abscissas are, in this case, symmetric << 540 // and abscissas are, in this case, symmetric around the midpoint of the 529 // range of integration, there are actually on 541 // range of integration, there are actually only five distinct values of each 530 // Convenient for using with some class object 542 // Convenient for using with some class object typeT 531 543 532 template <class T, class F> << 544 template <class T, class F> 533 G4double G4Integrator<T, F>::Legendre96(T& typ << 545 G4double G4Integrator<T,F>::Legendre96( T& typeT, F f,G4double a, G4double b) 534 { 546 { 535 G4int i; << 547 G4int i ; 536 G4double xDiff, xMean, dx, integral; << 548 G4double xDiff, xMean, dx, integral ; 537 << 549 538 // From Abramowitz M., Stegan I.A. 1964 , Ha << 550 // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 919 539 << 551 540 static const G4double abscissa[] = { << 552 static const G4double 541 0.016276744849602969579, 0.048812985136049 << 553 abscissa[] = { 542 0.081297495464425558994, 0.113695850110665 << 554 0.016276744849602969579, 0.048812985136049731112, 543 0.145973714654896941989, 0.178096882367618 << 555 0.081297495464425558994, 0.113695850110665920911, 544 << 556 0.145973714654896941989, 0.178096882367618602759, // 6 545 0.210031310460567203603, 0.241743156163840 << 557 546 0.273198812591049141487, 0.304364944354496 << 558 0.210031310460567203603, 0.241743156163840012328, 547 0.335208522892625422616, 0.365696861472313 << 559 0.273198812591049141487, 0.304364944354496353024, 548 << 560 0.335208522892625422616, 0.365696861472313635031, // 12 549 0.395797649828908603285, 0.425478988407300 << 561 550 0.454709422167743008636, 0.483457973920596 << 562 0.395797649828908603285, 0.425478988407300545365, 551 0.511694177154667673586, 0.539388108324357 << 563 0.454709422167743008636, 0.483457973920596359768, 552 << 564 0.511694177154667673586, 0.539388108324357436227, // 18 553 0.566510418561397168404, 0.593032364777572 << 565 554 0.618925840125468570386, 0.644163403784967 << 566 0.566510418561397168404, 0.593032364777572080684, 555 0.668718310043916153953, 0.692564536642171 << 567 0.618925840125468570386, 0.644163403784967106798, 556 << 568 0.668718310043916153953, 0.692564536642171561344, // 24 557 0.715676812348967626225, 0.738030643744400 << 569 558 0.759602341176647498703, 0.780369043867433 << 570 0.715676812348967626225, 0.738030643744400132851, 559 0.800308744139140817229, 0.819400310737931 << 571 0.759602341176647498703, 0.780369043867433217604, 560 << 572 0.800308744139140817229, 0.819400310737931675539, // 30 561 0.837623511228187121494, 0.854959033434601 << 573 562 0.871388505909296502874, 0.886894517402420 << 574 0.837623511228187121494, 0.854959033434601455463, 563 0.901460635315852341319, 0.915071423120898 << 575 0.871388505909296502874, 0.886894517402420416057, 564 << 576 0.901460635315852341319, 0.915071423120898074206, // 36 565 0.927712456722308690965, 0.939370339752755 << 577 566 0.950032717784437635756, 0.959688291448742 << 578 0.927712456722308690965, 0.939370339752755216932, 567 0.968326828463264212174, 0.975939174585136 << 579 0.950032717784437635756, 0.959688291448742539300, 568 << 580 0.968326828463264212174, 0.975939174585136466453, // 42 569 0.982517263563014677447, 0.988054126329623 << 581 570 0.992543900323762624572, 0.995981842987209 << 582 0.982517263563014677447, 0.988054126329623799481, 571 0.998364375863181677724, 0.999689503883230 << 583 0.992543900323762624572, 0.995981842987209290650, 572 }; << 584 0.998364375863181677724, 0.999689503883230766828 // 48 573 << 585 } ; 574 static const G4double weight[] = { << 586 575 0.032550614492363166242, 0.032516118713868 << 587 static const G4double 576 0.032447163714064269364, 0.032343822568575 << 588 weight[] = { 577 0.032206204794030250669, 0.032034456231992 << 589 0.032550614492363166242, 0.032516118713868835987, 578 << 590 0.032447163714064269364, 0.032343822568575928429, 579 0.031828758894411006535, 0.031589330770727 << 591 0.032206204794030250669, 0.032034456231992663218, // 6 580 0.031316425596862355813, 0.031010332586313 << 592 581 0.030671376123669149014, 0.030299915420827 << 593 0.031828758894411006535, 0.031589330770727168558, 582 << 594 0.031316425596862355813, 0.031010332586313837423, 583 0.029896344136328385984, 0.029461089958167 << 595 0.030671376123669149014, 0.030299915420827593794, // 12 584 0.028994614150555236543, 0.028497411065085 << 596 585 0.027970007616848334440, 0.027412962726029 << 597 0.029896344136328385984, 0.029461089958167905970, 586 << 598 0.028994614150555236543, 0.028497411065085385646, 587 0.026826866725591762198, 0.026212340735672 << 599 0.027970007616848334440, 0.027412962726029242823, // 18 588 0.025570036005349361499, 0.024900633222483 << 600 589 0.024204841792364691282, 0.023483399085926 << 601 0.026826866725591762198, 0.026212340735672413913, 590 << 602 0.025570036005349361499, 0.024900633222483610288, 591 0.022737069658329374001, 0.021966644438744 << 603 0.024204841792364691282, 0.023483399085926219842, // 24 592 0.021172939892191298988, 0.020356797154333 << 604 593 0.019519081140145022410, 0.018660679627411 << 605 0.022737069658329374001, 0.021966644438744349195, 594 << 606 0.021172939892191298988, 0.020356797154333324595, 595 0.017782502316045260838, 0.016885479864245 << 607 0.019519081140145022410, 0.018660679627411467385, // 30 596 0.015970562902562291381, 0.015038721026994 << 608 597 0.014090941772314860916, 0.013128229566961 << 609 0.017782502316045260838, 0.016885479864245172450, 598 << 610 0.015970562902562291381, 0.015038721026994938006, 599 0.012151604671088319635, 0.011162102099838 << 611 0.014090941772314860916, 0.013128229566961572637, // 36 600 0.010160770535008415758, 0.009148671230783 << 612 601 0.008126876925698759217, 0.007096470791153 << 613 0.012151604671088319635, 0.011162102099838498591, 602 << 614 0.010160770535008415758, 0.009148671230783386633, 603 0.006058545504235961683, 0.005014202742927 << 615 0.008126876925698759217, 0.007096470791153865269, // 42 604 0.003964554338444686674, 0.002910731817934 << 616 605 0.001853960788946921732, 0.000796792065552 << 617 0.006058545504235961683, 0.005014202742927517693, 606 }; << 618 0.003964554338444686674, 0.002910731817934946408, 607 xMean = 0.5 * (a + b); << 619 0.001853960788946921732, 0.000796792065552012429 // 48 608 xDiff = 0.5 * (b - a); << 620 } ; 609 integral = 0.0; << 621 xMean = 0.5*(a + b) ; 610 for(i = 0; i < 48; ++i) << 622 xDiff = 0.5*(b - a) ; 611 { << 623 integral = 0.0 ; 612 dx = xDiff * abscissa[i]; << 624 for(i=0;i<48;i++) 613 integral += weight[i] * ((typeT.*f)(xMean << 625 { 614 } << 626 dx = xDiff*abscissa[i] ; 615 return integral *= xDiff; << 627 integral += weight[i]*((typeT.*f)(xMean + dx) + (typeT.*f)(xMean - dx)) ; >> 628 } >> 629 return integral *= xDiff ; 616 } 630 } 617 631 618 ////////////////////////////////////////////// 632 /////////////////////////////////////////////////////////////////////// 619 // 633 // 620 // Convenient for using with the pointer 'this 634 // Convenient for using with the pointer 'this' 621 635 622 template <class T, class F> << 636 template <class T, class F> 623 G4double G4Integrator<T, F>::Legendre96(T* ptr << 637 G4double G4Integrator<T,F>::Legendre96( T* ptrT, F f,G4double a, G4double b) 624 { 638 { 625 return Legendre96(*ptrT, f, a, b); << 639 return Legendre96(*ptrT,f,a,b) ; 626 } << 640 } 627 641 628 ////////////////////////////////////////////// 642 /////////////////////////////////////////////////////////////////////// 629 // 643 // 630 // Convenient for using with global scope func << 644 // Convenient for using with global scope function f 631 645 632 template <class T, class F> 646 template <class T, class F> 633 G4double G4Integrator<T, F>::Legendre96(G4doub << 647 G4double G4Integrator<T,F>::Legendre96( G4double (*f)(G4double), 634 G4doub << 648 G4double a, G4double b ) 635 { 649 { 636 G4int i; << 650 G4int i ; 637 G4double xDiff, xMean, dx, integral; << 651 G4double xDiff, xMean, dx, integral ; 638 << 652 639 // From Abramowitz M., Stegan I.A. 1964 , Ha << 653 // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 919 640 << 654 641 static const G4double abscissa[] = { << 655 static const G4double 642 0.016276744849602969579, 0.048812985136049 << 656 abscissa[] = { 643 0.081297495464425558994, 0.113695850110665 << 657 0.016276744849602969579, 0.048812985136049731112, 644 0.145973714654896941989, 0.178096882367618 << 658 0.081297495464425558994, 0.113695850110665920911, 645 << 659 0.145973714654896941989, 0.178096882367618602759, // 6 646 0.210031310460567203603, 0.241743156163840 << 660 647 0.273198812591049141487, 0.304364944354496 << 661 0.210031310460567203603, 0.241743156163840012328, 648 0.335208522892625422616, 0.365696861472313 << 662 0.273198812591049141487, 0.304364944354496353024, 649 << 663 0.335208522892625422616, 0.365696861472313635031, // 12 650 0.395797649828908603285, 0.425478988407300 << 664 651 0.454709422167743008636, 0.483457973920596 << 665 0.395797649828908603285, 0.425478988407300545365, 652 0.511694177154667673586, 0.539388108324357 << 666 0.454709422167743008636, 0.483457973920596359768, 653 << 667 0.511694177154667673586, 0.539388108324357436227, // 18 654 0.566510418561397168404, 0.593032364777572 << 668 655 0.618925840125468570386, 0.644163403784967 << 669 0.566510418561397168404, 0.593032364777572080684, 656 0.668718310043916153953, 0.692564536642171 << 670 0.618925840125468570386, 0.644163403784967106798, 657 << 671 0.668718310043916153953, 0.692564536642171561344, // 24 658 0.715676812348967626225, 0.738030643744400 << 672 659 0.759602341176647498703, 0.780369043867433 << 673 0.715676812348967626225, 0.738030643744400132851, 660 0.800308744139140817229, 0.819400310737931 << 674 0.759602341176647498703, 0.780369043867433217604, 661 << 675 0.800308744139140817229, 0.819400310737931675539, // 30 662 0.837623511228187121494, 0.854959033434601 << 676 663 0.871388505909296502874, 0.886894517402420 << 677 0.837623511228187121494, 0.854959033434601455463, 664 0.901460635315852341319, 0.915071423120898 << 678 0.871388505909296502874, 0.886894517402420416057, 665 << 679 0.901460635315852341319, 0.915071423120898074206, // 36 666 0.927712456722308690965, 0.939370339752755 << 680 667 0.950032717784437635756, 0.959688291448742 << 681 0.927712456722308690965, 0.939370339752755216932, 668 0.968326828463264212174, 0.975939174585136 << 682 0.950032717784437635756, 0.959688291448742539300, 669 << 683 0.968326828463264212174, 0.975939174585136466453, // 42 670 0.982517263563014677447, 0.988054126329623 << 684 671 0.992543900323762624572, 0.995981842987209 << 685 0.982517263563014677447, 0.988054126329623799481, 672 0.998364375863181677724, 0.999689503883230 << 686 0.992543900323762624572, 0.995981842987209290650, 673 }; << 687 0.998364375863181677724, 0.999689503883230766828 // 48 674 << 688 } ; 675 static const G4double weight[] = { << 689 676 0.032550614492363166242, 0.032516118713868 << 690 static const G4double 677 0.032447163714064269364, 0.032343822568575 << 691 weight[] = { 678 0.032206204794030250669, 0.032034456231992 << 692 0.032550614492363166242, 0.032516118713868835987, 679 << 693 0.032447163714064269364, 0.032343822568575928429, 680 0.031828758894411006535, 0.031589330770727 << 694 0.032206204794030250669, 0.032034456231992663218, // 6 681 0.031316425596862355813, 0.031010332586313 << 695 682 0.030671376123669149014, 0.030299915420827 << 696 0.031828758894411006535, 0.031589330770727168558, 683 << 697 0.031316425596862355813, 0.031010332586313837423, 684 0.029896344136328385984, 0.029461089958167 << 698 0.030671376123669149014, 0.030299915420827593794, // 12 685 0.028994614150555236543, 0.028497411065085 << 699 686 0.027970007616848334440, 0.027412962726029 << 700 0.029896344136328385984, 0.029461089958167905970, 687 << 701 0.028994614150555236543, 0.028497411065085385646, 688 0.026826866725591762198, 0.026212340735672 << 702 0.027970007616848334440, 0.027412962726029242823, // 18 689 0.025570036005349361499, 0.024900633222483 << 703 690 0.024204841792364691282, 0.023483399085926 << 704 0.026826866725591762198, 0.026212340735672413913, 691 << 705 0.025570036005349361499, 0.024900633222483610288, 692 0.022737069658329374001, 0.021966644438744 << 706 0.024204841792364691282, 0.023483399085926219842, // 24 693 0.021172939892191298988, 0.020356797154333 << 707 694 0.019519081140145022410, 0.018660679627411 << 708 0.022737069658329374001, 0.021966644438744349195, 695 << 709 0.021172939892191298988, 0.020356797154333324595, 696 0.017782502316045260838, 0.016885479864245 << 710 0.019519081140145022410, 0.018660679627411467385, // 30 697 0.015970562902562291381, 0.015038721026994 << 711 698 0.014090941772314860916, 0.013128229566961 << 712 0.017782502316045260838, 0.016885479864245172450, 699 << 713 0.015970562902562291381, 0.015038721026994938006, 700 0.012151604671088319635, 0.011162102099838 << 714 0.014090941772314860916, 0.013128229566961572637, // 36 701 0.010160770535008415758, 0.009148671230783 << 715 702 0.008126876925698759217, 0.007096470791153 << 716 0.012151604671088319635, 0.011162102099838498591, 703 << 717 0.010160770535008415758, 0.009148671230783386633, 704 0.006058545504235961683, 0.005014202742927 << 718 0.008126876925698759217, 0.007096470791153865269, // 42 705 0.003964554338444686674, 0.002910731817934 << 719 706 0.001853960788946921732, 0.000796792065552 << 720 0.006058545504235961683, 0.005014202742927517693, 707 }; << 721 0.003964554338444686674, 0.002910731817934946408, 708 xMean = 0.5 * (a + b); << 722 0.001853960788946921732, 0.000796792065552012429 // 48 709 xDiff = 0.5 * (b - a); << 723 } ; 710 integral = 0.0; << 724 xMean = 0.5*(a + b) ; 711 for(i = 0; i < 48; ++i) << 725 xDiff = 0.5*(b - a) ; 712 { << 726 integral = 0.0 ; 713 dx = xDiff * abscissa[i]; << 727 for(i=0;i<48;i++) 714 integral += weight[i] * ((*f)(xMean + dx) << 728 { 715 } << 729 dx = xDiff*abscissa[i] ; 716 return integral *= xDiff; << 730 integral += weight[i]*((*f)(xMean + dx) + (*f)(xMean - dx)) ; >> 731 } >> 732 return integral *= xDiff ; 717 } 733 } 718 734 719 ////////////////////////////////////////////// 735 ////////////////////////////////////////////////////////////////////////////// 720 // 736 // 721 // Methods involving Chebyshev polynomials << 737 // Methods involving Chebyshev polynomials 722 // 738 // 723 ////////////////////////////////////////////// 739 /////////////////////////////////////////////////////////////////////////// 724 // 740 // 725 // Integrates function pointed by T::f from a << 741 // Integrates function pointed by T::f from a to b by Gauss-Chebyshev 726 // quadrature method. 742 // quadrature method. 727 // Convenient for using with class object type 743 // Convenient for using with class object typeT 728 744 729 template <class T, class F> 745 template <class T, class F> 730 G4double G4Integrator<T, F>::Chebyshev(T& type << 746 G4double G4Integrator<T,F>::Chebyshev( T& typeT, F f, G4double a, 731 G4int n << 747 G4double b, G4int nChebyshev ) 732 { 748 { 733 G4int i; << 749 G4int i ; 734 G4double xDiff, xMean, dx, integral = 0.0; << 750 G4double xDiff, xMean, dx, integral = 0.0 ; 735 << 751 736 G4int fNumber = nChebyshev; // Try to << 752 G4int fNumber = nChebyshev ; // Try to reduce fNumber twice ?? 737 G4double cof = CLHEP::pi / fNumber; << 753 G4double cof = CLHEP::pi/fNumber ; 738 G4double* fAbscissa = new G4double[fNumber]; << 754 G4double* fAbscissa = new G4double[fNumber] ; 739 G4double* fWeight = new G4double[fNumber]; << 755 G4double* fWeight = new G4double[fNumber] ; 740 for(i = 0; i < fNumber; ++i) << 756 for(i=0;i<fNumber;i++) 741 { << 757 { 742 fAbscissa[i] = std::cos(cof * (i + 0.5)); << 758 fAbscissa[i] = std::cos(cof*(i + 0.5)) ; 743 fWeight[i] = cof * std::sqrt(1 - fAbscis << 759 fWeight[i] = cof*std::sqrt(1 - fAbscissa[i]*fAbscissa[i]) ; 744 } << 760 } 745 << 761 746 // << 762 // 747 // Now we ready to estimate the integral << 763 // Now we ready to estimate the integral 748 // << 764 // 749 << 765 750 xMean = 0.5 * (a + b); << 766 xMean = 0.5*(a + b) ; 751 xDiff = 0.5 * (b - a); << 767 xDiff = 0.5*(b - a) ; 752 for(i = 0; i < fNumber; ++i) << 768 for(i=0;i<fNumber;i++) 753 { << 769 { 754 dx = xDiff * fAbscissa[i]; << 770 dx = xDiff*fAbscissa[i] ; 755 integral += fWeight[i] * (typeT.*f)(xMean << 771 integral += fWeight[i]*(typeT.*f)(xMean + dx) ; 756 } << 772 } 757 delete[] fAbscissa; << 773 delete[] fAbscissa; 758 delete[] fWeight; << 774 delete[] fWeight; 759 return integral *= xDiff; << 775 return integral *= xDiff ; 760 } 776 } 761 777 762 ////////////////////////////////////////////// 778 /////////////////////////////////////////////////////////////////////// 763 // 779 // 764 // Convenient for using with 'this' pointer 780 // Convenient for using with 'this' pointer 765 781 766 template <class T, class F> 782 template <class T, class F> 767 G4double G4Integrator<T, F>::Chebyshev(T* ptrT << 783 G4double G4Integrator<T,F>::Chebyshev( T* ptrT, F f, G4double a, 768 G4int n << 784 G4double b, G4int n ) 769 { 785 { 770 return Chebyshev(*ptrT, f, a, b, n); << 786 return Chebyshev(*ptrT,f,a,b,n) ; 771 } << 787 } 772 788 773 ////////////////////////////////////////////// 789 //////////////////////////////////////////////////////////////////////// 774 // 790 // 775 // For use with global scope functions f << 791 // For use with global scope functions f 776 792 777 template <class T, class F> 793 template <class T, class F> 778 G4double G4Integrator<T, F>::Chebyshev(G4doubl << 794 G4double G4Integrator<T,F>::Chebyshev( G4double (*f)(G4double), 779 G4doubl << 795 G4double a, G4double b, G4int nChebyshev ) 780 { 796 { 781 G4int i; << 797 G4int i ; 782 G4double xDiff, xMean, dx, integral = 0.0; << 798 G4double xDiff, xMean, dx, integral = 0.0 ; 783 << 799 784 G4int fNumber = nChebyshev; // Try to << 800 G4int fNumber = nChebyshev ; // Try to reduce fNumber twice ?? 785 G4double cof = CLHEP::pi / fNumber; << 801 G4double cof = CLHEP::pi/fNumber ; 786 G4double* fAbscissa = new G4double[fNumber]; << 802 G4double* fAbscissa = new G4double[fNumber] ; 787 G4double* fWeight = new G4double[fNumber]; << 803 G4double* fWeight = new G4double[fNumber] ; 788 for(i = 0; i < fNumber; ++i) << 804 for(i=0;i<fNumber;i++) 789 { << 805 { 790 fAbscissa[i] = std::cos(cof * (i + 0.5)); << 806 fAbscissa[i] = std::cos(cof*(i + 0.5)) ; 791 fWeight[i] = cof * std::sqrt(1 - fAbscis << 807 fWeight[i] = cof*std::sqrt(1 - fAbscissa[i]*fAbscissa[i]) ; 792 } << 808 } 793 << 809 794 // << 810 // 795 // Now we ready to estimate the integral << 811 // Now we ready to estimate the integral 796 // << 812 // 797 << 813 798 xMean = 0.5 * (a + b); << 814 xMean = 0.5*(a + b) ; 799 xDiff = 0.5 * (b - a); << 815 xDiff = 0.5*(b - a) ; 800 for(i = 0; i < fNumber; ++i) << 816 for(i=0;i<fNumber;i++) 801 { << 817 { 802 dx = xDiff * fAbscissa[i]; << 818 dx = xDiff*fAbscissa[i] ; 803 integral += fWeight[i] * (*f)(xMean + dx); << 819 integral += fWeight[i]*(*f)(xMean + dx) ; 804 } << 820 } 805 delete[] fAbscissa; << 821 delete[] fAbscissa; 806 delete[] fWeight; << 822 delete[] fWeight; 807 return integral *= xDiff; << 823 return integral *= xDiff ; 808 } 824 } 809 825 810 ////////////////////////////////////////////// 826 ////////////////////////////////////////////////////////////////////// 811 // 827 // 812 // Method involving Laguerre polynomials 828 // Method involving Laguerre polynomials 813 // 829 // 814 ////////////////////////////////////////////// 830 ////////////////////////////////////////////////////////////////////// 815 // 831 // 816 // Integral from zero to infinity of std::pow( << 832 // Integral from zero to infinity of std::pow(x,alpha)*std::exp(-x)*f(x). 817 // The value of nLaguerre sets the accuracy. 833 // The value of nLaguerre sets the accuracy. 818 // The function creates arrays fAbscissa[0,.., << 834 // The function creates arrays fAbscissa[0,..,nLaguerre-1] and 819 // fWeight[0,..,nLaguerre-1] . << 835 // fWeight[0,..,nLaguerre-1] . 820 // Convenient for using with class object 'typ 836 // Convenient for using with class object 'typeT' and (typeT.*f) function 821 // (T::f) 837 // (T::f) 822 838 823 template <class T, class F> 839 template <class T, class F> 824 G4double G4Integrator<T, F>::Laguerre(T& typeT << 840 G4double G4Integrator<T,F>::Laguerre( T& typeT, F f, G4double alpha, 825 G4int nL << 841 G4int nLaguerre ) 826 { 842 { 827 const G4double tolerance = 1.0e-10; << 843 const G4double tolerance = 1.0e-10 ; 828 const G4int maxNumber = 12; << 844 const G4int maxNumber = 12 ; 829 G4int i, j, k; << 845 G4int i, j, k ; 830 G4double nwt = 0., nwt1, temp1, temp2, << 846 G4double nwt=0., nwt1, temp1, temp2, temp3, temp, cofi ; 831 G4double integral = 0.0; << 847 G4double integral = 0.0 ; 832 << 848 833 G4int fNumber = nLaguerre; << 849 G4int fNumber = nLaguerre ; 834 G4double* fAbscissa = new G4double[fNumber]; << 850 G4double* fAbscissa = new G4double[fNumber] ; 835 G4double* fWeight = new G4double[fNumber]; << 851 G4double* fWeight = new G4double[fNumber] ; >> 852 >> 853 for(i=1;i<=fNumber;i++) // Loop over the desired roots >> 854 { >> 855 if(i == 1) >> 856 { >> 857 nwt = (1.0 + alpha)*(3.0 + 0.92*alpha) >> 858 / (1.0 + 2.4*fNumber + 1.8*alpha) ; >> 859 } >> 860 else if(i == 2) >> 861 { >> 862 nwt += (15.0 + 6.25*alpha)/(1.0 + 0.9*alpha + 2.5*fNumber) ; >> 863 } >> 864 else >> 865 { >> 866 cofi = i - 2 ; >> 867 nwt += ((1.0+2.55*cofi)/(1.9*cofi) >> 868 + 1.26*cofi*alpha/(1.0+3.5*cofi)) >> 869 * (nwt - fAbscissa[i-3])/(1.0 + 0.3*alpha) ; >> 870 } >> 871 for(k=1;k<=maxNumber;k++) >> 872 { >> 873 temp1 = 1.0 ; >> 874 temp2 = 0.0 ; 836 875 837 for(i = 1; i <= fNumber; ++i) // Loop over << 876 for(j=1;j<=fNumber;j++) 838 { << 877 { 839 if(i == 1) << 878 temp3 = temp2 ; 840 { << 879 temp2 = temp1 ; 841 nwt = (1.0 + alpha) * (3.0 + 0.92 * alph << 880 temp1 = ((2*j - 1 + alpha - nwt)*temp2 - (j - 1 + alpha)*temp3)/j ; 842 (1.0 + 2.4 * fNumber + 1.8 * alpha << 881 } 843 } << 882 temp = (fNumber*temp1 - (fNumber +alpha)*temp2)/nwt ; 844 else if(i == 2) << 883 nwt1 = nwt ; 845 { << 884 nwt = nwt1 - temp1/temp ; 846 nwt += (15.0 + 6.25 * alpha) / (1.0 + 0. << 885 847 } << 886 if(std::fabs(nwt - nwt1) <= tolerance) 848 else << 887 { 849 { << 888 break ; 850 cofi = i - 2; << 889 } 851 nwt += ((1.0 + 2.55 * cofi) / (1.9 * cof << 890 } 852 1.26 * cofi * alpha / (1.0 + 3.5 << 891 if(k > maxNumber) 853 (nwt - fAbscissa[i - 3]) / (1.0 + << 892 { 854 } << 893 G4Exception("G4Integrator<T,F>::Laguerre(T,F, ...)", "Error", 855 for(k = 1; k <= maxNumber; ++k) << 894 FatalException, "Too many (>12) iterations."); 856 { << 895 } 857 temp1 = 1.0; << 896 858 temp2 = 0.0; << 897 fAbscissa[i-1] = nwt ; 859 << 898 fWeight[i-1] = -std::exp(GammaLogarithm(alpha + fNumber) - 860 for(j = 1; j <= fNumber; ++j) << 899 GammaLogarithm((G4double)fNumber))/(temp*fNumber*temp2) ; 861 { << 900 } 862 temp3 = temp2; << 901 863 temp2 = temp1; << 902 // 864 temp1 = << 903 // Integral evaluation 865 ((2 * j - 1 + alpha - nwt) * temp2 - << 904 // 866 } << 905 867 temp = (fNumber * temp1 - (fNumber + alp << 906 for(i=0;i<fNumber;i++) 868 nwt1 = nwt; << 907 { 869 nwt = nwt1 - temp1 / temp; << 908 integral += fWeight[i]*(typeT.*f)(fAbscissa[i]) ; 870 << 909 } 871 if(std::fabs(nwt - nwt1) <= tolerance) << 910 delete[] fAbscissa; 872 { << 911 delete[] fWeight; 873 break; << 912 return integral ; 874 } << 913 } 875 } << 876 if(k > maxNumber) << 877 { << 878 G4Exception("G4Integrator<T,F>::Laguerre << 879 FatalException, "Too many (> << 880 } << 881 << 882 fAbscissa[i - 1] = nwt; << 883 fWeight[i - 1] = -std::exp(GammaLogarith << 884 GammaLogarithm( << 885 (temp * fNumber * temp2); << 886 } << 887 914 888 // << 889 // Integral evaluation << 890 // << 891 915 892 for(i = 0; i < fNumber; ++i) << 893 { << 894 integral += fWeight[i] * (typeT.*f)(fAbsci << 895 } << 896 delete[] fAbscissa; << 897 delete[] fWeight; << 898 return integral; << 899 } << 900 916 901 ////////////////////////////////////////////// 917 ////////////////////////////////////////////////////////////////////// 902 // 918 // 903 // 919 // 904 920 905 template <class T, class F> << 921 template <class T, class F> G4double 906 G4double G4Integrator<T, F>::Laguerre(T* ptrT, << 922 G4Integrator<T,F>::Laguerre( T* ptrT, F f, G4double alpha, G4int nLaguerre ) 907 G4int nL << 908 { 923 { 909 return Laguerre(*ptrT, f, alpha, nLaguerre); << 924 return Laguerre(*ptrT,f,alpha,nLaguerre) ; 910 } 925 } 911 926 912 ////////////////////////////////////////////// 927 //////////////////////////////////////////////////////////////////////// 913 // 928 // 914 // For use with global scope functions f << 929 // For use with global scope functions f 915 << 916 template <class T, class F> << 917 G4double G4Integrator<T, F>::Laguerre(G4double << 918 G4int nL << 919 { << 920 const G4double tolerance = 1.0e-10; << 921 const G4int maxNumber = 12; << 922 G4int i, j, k; << 923 G4double nwt = 0., nwt1, temp1, temp2, << 924 G4double integral = 0.0; << 925 << 926 G4int fNumber = nLaguerre; << 927 G4double* fAbscissa = new G4double[fNumber]; << 928 G4double* fWeight = new G4double[fNumber]; << 929 << 930 for(i = 1; i <= fNumber; ++i) // Loop over << 931 { << 932 if(i == 1) << 933 { << 934 nwt = (1.0 + alpha) * (3.0 + 0.92 * alph << 935 (1.0 + 2.4 * fNumber + 1.8 * alpha << 936 } << 937 else if(i == 2) << 938 { << 939 nwt += (15.0 + 6.25 * alpha) / (1.0 + 0. << 940 } << 941 else << 942 { << 943 cofi = i - 2; << 944 nwt += ((1.0 + 2.55 * cofi) / (1.9 * cof << 945 1.26 * cofi * alpha / (1.0 + 3.5 << 946 (nwt - fAbscissa[i - 3]) / (1.0 + << 947 } << 948 for(k = 1; k <= maxNumber; ++k) << 949 { << 950 temp1 = 1.0; << 951 temp2 = 0.0; << 952 << 953 for(j = 1; j <= fNumber; ++j) << 954 { << 955 temp3 = temp2; << 956 temp2 = temp1; << 957 temp1 = << 958 ((2 * j - 1 + alpha - nwt) * temp2 - << 959 } << 960 temp = (fNumber * temp1 - (fNumber + alp << 961 nwt1 = nwt; << 962 nwt = nwt1 - temp1 / temp; << 963 << 964 if(std::fabs(nwt - nwt1) <= tolerance) << 965 { << 966 break; << 967 } << 968 } << 969 if(k > maxNumber) << 970 { << 971 G4Exception("G4Integrator<T,F>::Laguerre << 972 "Too many (>12) iterations." << 973 } << 974 << 975 fAbscissa[i - 1] = nwt; << 976 fWeight[i - 1] = -std::exp(GammaLogarith << 977 GammaLogarithm( << 978 (temp * fNumber * temp2); << 979 } << 980 930 981 // << 931 template <class T, class F> G4double 982 // Integral evaluation << 932 G4Integrator<T,F>::Laguerre( G4double (*f)(G4double), 983 // << 933 G4double alpha, G4int nLaguerre ) >> 934 { >> 935 const G4double tolerance = 1.0e-10 ; >> 936 const G4int maxNumber = 12 ; >> 937 G4int i, j, k ; >> 938 G4double nwt=0., nwt1, temp1, temp2, temp3, temp, cofi ; >> 939 G4double integral = 0.0 ; >> 940 >> 941 G4int fNumber = nLaguerre ; >> 942 G4double* fAbscissa = new G4double[fNumber] ; >> 943 G4double* fWeight = new G4double[fNumber] ; >> 944 >> 945 for(i=1;i<=fNumber;i++) // Loop over the desired roots >> 946 { >> 947 if(i == 1) >> 948 { >> 949 nwt = (1.0 + alpha)*(3.0 + 0.92*alpha) >> 950 / (1.0 + 2.4*fNumber + 1.8*alpha) ; >> 951 } >> 952 else if(i == 2) >> 953 { >> 954 nwt += (15.0 + 6.25*alpha)/(1.0 + 0.9*alpha + 2.5*fNumber) ; >> 955 } >> 956 else >> 957 { >> 958 cofi = i - 2 ; >> 959 nwt += ((1.0+2.55*cofi)/(1.9*cofi) >> 960 + 1.26*cofi*alpha/(1.0+3.5*cofi)) >> 961 * (nwt - fAbscissa[i-3])/(1.0 + 0.3*alpha) ; >> 962 } >> 963 for(k=1;k<=maxNumber;k++) >> 964 { >> 965 temp1 = 1.0 ; >> 966 temp2 = 0.0 ; 984 967 985 for(i = 0; i < fNumber; i++) << 968 for(j=1;j<=fNumber;j++) 986 { << 969 { 987 integral += fWeight[i] * (*f)(fAbscissa[i] << 970 temp3 = temp2 ; 988 } << 971 temp2 = temp1 ; 989 delete[] fAbscissa; << 972 temp1 = ((2*j - 1 + alpha - nwt)*temp2 - (j - 1 + alpha)*temp3)/j ; 990 delete[] fWeight; << 973 } 991 return integral; << 974 temp = (fNumber*temp1 - (fNumber +alpha)*temp2)/nwt ; >> 975 nwt1 = nwt ; >> 976 nwt = nwt1 - temp1/temp ; >> 977 >> 978 if(std::fabs(nwt - nwt1) <= tolerance) >> 979 { >> 980 break ; >> 981 } >> 982 } >> 983 if(k > maxNumber) >> 984 { >> 985 G4Exception("G4Integrator<T,F>::Laguerre( ...)", "Error", >> 986 FatalException, "Too many (>12) iterations."); >> 987 } >> 988 >> 989 fAbscissa[i-1] = nwt ; >> 990 fWeight[i-1] = -std::exp(GammaLogarithm(alpha + fNumber) - >> 991 GammaLogarithm((G4double)fNumber))/(temp*fNumber*temp2) ; >> 992 } >> 993 >> 994 // >> 995 // Integral evaluation >> 996 // >> 997 >> 998 for(i=0;i<fNumber;i++) >> 999 { >> 1000 integral += fWeight[i]*(*f)(fAbscissa[i]) ; >> 1001 } >> 1002 delete[] fAbscissa; >> 1003 delete[] fWeight; >> 1004 return integral ; 992 } 1005 } 993 1006 994 ////////////////////////////////////////////// 1007 /////////////////////////////////////////////////////////////////////// 995 // 1008 // 996 // Auxiliary function which returns the value 1009 // Auxiliary function which returns the value of std::log(gamma-function(x)) 997 // Returns the value ln(Gamma(xx) for xx > 0. << 1010 // Returns the value ln(Gamma(xx) for xx > 0. Full accuracy is obtained for 998 // xx > 1. For 0 < xx < 1. the reflection form 1011 // xx > 1. For 0 < xx < 1. the reflection formula (6.1.4) can be used first. 999 // (Adapted from Numerical Recipes in C) 1012 // (Adapted from Numerical Recipes in C) 1000 // 1013 // 1001 1014 1002 template <class T, class F> 1015 template <class T, class F> 1003 G4double G4Integrator<T, F>::GammaLogarithm(G << 1016 G4double G4Integrator<T,F>::GammaLogarithm(G4double xx) 1004 { 1017 { 1005 static const G4double cof[6] = { 76.1800917 1018 static const G4double cof[6] = { 76.18009172947146, -86.50532032941677, 1006 24.0140982 << 1019 24.01409824083091, -1.231739572450155, 1007 0.12086509 1020 0.1208650973866179e-2, -0.5395239384953e-5 }; 1008 G4int j; 1021 G4int j; 1009 G4double x = xx - 1.0; << 1022 G4double x = xx - 1.0 ; 1010 G4double tmp = x + 5.5; << 1023 G4double tmp = x + 5.5 ; 1011 tmp -= (x + 0.5) * std::log(tmp); << 1024 tmp -= (x + 0.5) * std::log(tmp) ; 1012 G4double ser = 1.000000000190015; << 1025 G4double ser = 1.000000000190015 ; 1013 1026 1014 for(j = 0; j <= 5; ++j) << 1027 for ( j = 0; j <= 5; j++ ) 1015 { 1028 { 1016 x += 1.0; << 1029 x += 1.0 ; 1017 ser += cof[j] / x; << 1030 ser += cof[j]/x ; 1018 } 1031 } 1019 return -tmp + std::log(2.5066282746310005 * << 1032 return -tmp + std::log(2.5066282746310005*ser) ; 1020 } 1033 } 1021 1034 1022 ///////////////////////////////////////////// 1035 /////////////////////////////////////////////////////////////////////// 1023 // 1036 // 1024 // Method involving Hermite polynomials 1037 // Method involving Hermite polynomials 1025 // 1038 // 1026 ///////////////////////////////////////////// 1039 /////////////////////////////////////////////////////////////////////// 1027 // 1040 // 1028 // 1041 // 1029 // Gauss-Hermite method for integration of st << 1042 // Gauss-Hermite method for integration of std::exp(-x*x)*f(x) 1030 // from minus infinity to plus infinity . << 1043 // from minus infinity to plus infinity . 1031 // 1044 // 1032 1045 1033 template <class T, class F> << 1046 template <class T, class F> 1034 G4double G4Integrator<T, F>::Hermite(T& typeT << 1047 G4double G4Integrator<T,F>::Hermite( T& typeT, F f, G4int nHermite ) 1035 { 1048 { 1036 const G4double tolerance = 1.0e-12; << 1049 const G4double tolerance = 1.0e-12 ; 1037 const G4int maxNumber = 12; << 1050 const G4int maxNumber = 12 ; 1038 << 1051 1039 G4int i, j, k; << 1052 G4int i, j, k ; 1040 G4double integral = 0.0; << 1053 G4double integral = 0.0 ; 1041 G4double nwt = 0., nwt1, temp1, temp2, << 1054 G4double nwt=0., nwt1, temp1, temp2, temp3, temp ; 1042 1055 1043 G4double piInMinusQ = << 1056 G4double piInMinusQ = std::pow(CLHEP::pi,-0.25) ; // 1.0/std::sqrt(std::sqrt(pi)) ?? 1044 std::pow(CLHEP::pi, -0.25); // 1.0/std:: << 1045 1057 1046 G4int fNumber = (nHermite + 1) / 2; << 1058 G4int fNumber = (nHermite +1)/2 ; 1047 G4double* fAbscissa = new G4double[fNumber] << 1059 G4double* fAbscissa = new G4double[fNumber] ; 1048 G4double* fWeight = new G4double[fNumber] << 1060 G4double* fWeight = new G4double[fNumber] ; 1049 1061 1050 for(i = 1; i <= fNumber; ++i) << 1062 for(i=1;i<=fNumber;i++) 1051 { << 1063 { 1052 if(i == 1) << 1064 if(i == 1) 1053 { << 1065 { 1054 nwt = std::sqrt((G4double)(2 * nHermite << 1066 nwt = std::sqrt((G4double)(2*nHermite + 1)) - 1055 1.85575001 * std::pow((G4double)( << 1067 1.85575001*std::pow((G4double)(2*nHermite + 1),-0.16666999) ; 1056 } << 1068 } 1057 else if(i == 2) << 1069 else if(i == 2) 1058 { << 1070 { 1059 nwt -= 1.14001 * std::pow((G4double) nH << 1071 nwt -= 1.14001*std::pow((G4double)nHermite,0.425999)/nwt ; 1060 } << 1072 } 1061 else if(i == 3) << 1073 else if(i == 3) 1062 { << 1074 { 1063 nwt = 1.86002 * nwt - 0.86002 * fAbscis << 1075 nwt = 1.86002*nwt - 0.86002*fAbscissa[0] ; 1064 } << 1076 } 1065 else if(i == 4) << 1077 else if(i == 4) 1066 { << 1078 { 1067 nwt = 1.91001 * nwt - 0.91001 * fAbscis << 1079 nwt = 1.91001*nwt - 0.91001*fAbscissa[1] ; 1068 } << 1080 } 1069 else << 1081 else 1070 { << 1082 { 1071 nwt = 2.0 * nwt - fAbscissa[i - 3]; << 1083 nwt = 2.0*nwt - fAbscissa[i - 3] ; 1072 } << 1084 } 1073 for(k = 1; k <= maxNumber; ++k) << 1085 for(k=1;k<=maxNumber;k++) 1074 { << 1086 { 1075 temp1 = piInMinusQ; << 1087 temp1 = piInMinusQ ; 1076 temp2 = 0.0; << 1088 temp2 = 0.0 ; 1077 << 1078 for(j = 1; j <= nHermite; ++j) << 1079 { << 1080 temp3 = temp2; << 1081 temp2 = temp1; << 1082 temp1 = nwt * std::sqrt(2.0 / j) * te << 1083 std::sqrt(((G4double)(j - 1)) << 1084 } << 1085 temp = std::sqrt((G4double) 2 * nHermit << 1086 nwt1 = nwt; << 1087 nwt = nwt1 - temp1 / temp; << 1088 << 1089 if(std::fabs(nwt - nwt1) <= tolerance) << 1090 { << 1091 break; << 1092 } << 1093 } << 1094 if(k > maxNumber) << 1095 { << 1096 G4Exception("G4Integrator<T,F>::Hermite << 1097 FatalException, "Too many ( << 1098 } << 1099 fAbscissa[i - 1] = nwt; << 1100 fWeight[i - 1] = 2.0 / (temp * temp); << 1101 } << 1102 << 1103 // << 1104 // Integral calculation << 1105 // << 1106 1089 1107 for(i = 0; i < fNumber; ++i) << 1090 for(j=1;j<=nHermite;j++) 1108 { << 1091 { 1109 integral += << 1092 temp3 = temp2 ; 1110 fWeight[i] * ((typeT.*f)(fAbscissa[i]) << 1093 temp2 = temp1 ; 1111 } << 1094 temp1 = nwt*std::sqrt(2.0/j)*temp2 - 1112 delete[] fAbscissa; << 1095 std::sqrt(((G4double)(j - 1))/j)*temp3 ; 1113 delete[] fWeight; << 1096 } 1114 return integral; << 1097 temp = std::sqrt((G4double)2*nHermite)*temp2 ; >> 1098 nwt1 = nwt ; >> 1099 nwt = nwt1 - temp1/temp ; >> 1100 >> 1101 if(std::fabs(nwt - nwt1) <= tolerance) >> 1102 { >> 1103 break ; >> 1104 } >> 1105 } >> 1106 if(k > maxNumber) >> 1107 { >> 1108 G4Exception("G4Integrator<T,F>::Hermite(T,F, ...)", "Error", >> 1109 FatalException, "Too many (>12) iterations."); >> 1110 } >> 1111 fAbscissa[i-1] = nwt ; >> 1112 fWeight[i-1] = 2.0/(temp*temp) ; >> 1113 } >> 1114 >> 1115 // >> 1116 // Integral calculation >> 1117 // >> 1118 >> 1119 for(i=0;i<fNumber;i++) >> 1120 { >> 1121 integral += fWeight[i]*( (typeT.*f)(fAbscissa[i]) + >> 1122 (typeT.*f)(-fAbscissa[i]) ) ; >> 1123 } >> 1124 delete[] fAbscissa; >> 1125 delete[] fWeight; >> 1126 return integral ; 1115 } 1127 } 1116 1128 >> 1129 1117 ///////////////////////////////////////////// 1130 //////////////////////////////////////////////////////////////////////// 1118 // 1131 // 1119 // For use with 'this' pointer 1132 // For use with 'this' pointer 1120 1133 1121 template <class T, class F> << 1134 template <class T, class F> 1122 G4double G4Integrator<T, F>::Hermite(T* ptrT, << 1135 G4double G4Integrator<T,F>::Hermite( T* ptrT, F f, G4int n ) 1123 { 1136 { 1124 return Hermite(*ptrT, f, n); << 1137 return Hermite(*ptrT,f,n) ; 1125 } << 1138 } 1126 1139 1127 ///////////////////////////////////////////// 1140 //////////////////////////////////////////////////////////////////////// 1128 // 1141 // 1129 // For use with global scope f 1142 // For use with global scope f 1130 1143 1131 template <class T, class F> 1144 template <class T, class F> 1132 G4double G4Integrator<T, F>::Hermite(G4double << 1145 G4double G4Integrator<T,F>::Hermite( G4double (*f)(G4double), G4int nHermite) 1133 { 1146 { 1134 const G4double tolerance = 1.0e-12; << 1147 const G4double tolerance = 1.0e-12 ; 1135 const G4int maxNumber = 12; << 1148 const G4int maxNumber = 12 ; 1136 << 1149 1137 G4int i, j, k; << 1150 G4int i, j, k ; 1138 G4double integral = 0.0; << 1151 G4double integral = 0.0 ; 1139 G4double nwt = 0., nwt1, temp1, temp2, << 1152 G4double nwt=0., nwt1, temp1, temp2, temp3, temp ; 1140 << 1153 1141 G4double piInMinusQ = << 1154 G4double piInMinusQ = std::pow(CLHEP::pi,-0.25) ; // 1.0/std::sqrt(std::sqrt(pi)) ?? 1142 std::pow(CLHEP::pi, -0.25); // 1.0/std:: << 1155 1143 << 1156 G4int fNumber = (nHermite +1)/2 ; 1144 G4int fNumber = (nHermite + 1) / 2; << 1157 G4double* fAbscissa = new G4double[fNumber] ; 1145 G4double* fAbscissa = new G4double[fNumber] << 1158 G4double* fWeight = new G4double[fNumber] ; 1146 G4double* fWeight = new G4double[fNumber] << 1159 1147 << 1160 for(i=1;i<=fNumber;i++) 1148 for(i = 1; i <= fNumber; ++i) << 1161 { 1149 { << 1162 if(i == 1) 1150 if(i == 1) << 1163 { 1151 { << 1164 nwt = std::sqrt((G4double)(2*nHermite + 1)) - 1152 nwt = std::sqrt((G4double)(2 * nHermite << 1165 1.85575001*std::pow((G4double)(2*nHermite + 1),-0.16666999) ; 1153 1.85575001 * std::pow((G4double)( << 1166 } 1154 } << 1167 else if(i == 2) 1155 else if(i == 2) << 1168 { 1156 { << 1169 nwt -= 1.14001*std::pow((G4double)nHermite,0.425999)/nwt ; 1157 nwt -= 1.14001 * std::pow((G4double) nH << 1170 } 1158 } << 1171 else if(i == 3) 1159 else if(i == 3) << 1172 { 1160 { << 1173 nwt = 1.86002*nwt - 0.86002*fAbscissa[0] ; 1161 nwt = 1.86002 * nwt - 0.86002 * fAbscis << 1174 } 1162 } << 1175 else if(i == 4) 1163 else if(i == 4) << 1176 { 1164 { << 1177 nwt = 1.91001*nwt - 0.91001*fAbscissa[1] ; 1165 nwt = 1.91001 * nwt - 0.91001 * fAbscis << 1178 } 1166 } << 1179 else 1167 else << 1180 { 1168 { << 1181 nwt = 2.0*nwt - fAbscissa[i - 3] ; 1169 nwt = 2.0 * nwt - fAbscissa[i - 3]; << 1182 } 1170 } << 1183 for(k=1;k<=maxNumber;k++) 1171 for(k = 1; k <= maxNumber; ++k) << 1184 { 1172 { << 1185 temp1 = piInMinusQ ; 1173 temp1 = piInMinusQ; << 1186 temp2 = 0.0 ; 1174 temp2 = 0.0; << 1175 << 1176 for(j = 1; j <= nHermite; ++j) << 1177 { << 1178 temp3 = temp2; << 1179 temp2 = temp1; << 1180 temp1 = nwt * std::sqrt(2.0 / j) * te << 1181 std::sqrt(((G4double)(j - 1)) << 1182 } << 1183 temp = std::sqrt((G4double) 2 * nHermit << 1184 nwt1 = nwt; << 1185 nwt = nwt1 - temp1 / temp; << 1186 << 1187 if(std::fabs(nwt - nwt1) <= tolerance) << 1188 { << 1189 break; << 1190 } << 1191 } << 1192 if(k > maxNumber) << 1193 { << 1194 G4Exception("G4Integrator<T,F>::Hermite << 1195 "Too many (>12) iterations. << 1196 } << 1197 fAbscissa[i - 1] = nwt; << 1198 fWeight[i - 1] = 2.0 / (temp * temp); << 1199 } << 1200 << 1201 // << 1202 // Integral calculation << 1203 // << 1204 1187 1205 for(i = 0; i < fNumber; ++i) << 1188 for(j=1;j<=nHermite;j++) 1206 { << 1189 { 1207 integral += fWeight[i] * ((*f)(fAbscissa[ << 1190 temp3 = temp2 ; 1208 } << 1191 temp2 = temp1 ; 1209 delete[] fAbscissa; << 1192 temp1 = nwt*std::sqrt(2.0/j)*temp2 - 1210 delete[] fWeight; << 1193 std::sqrt(((G4double)(j - 1))/j)*temp3 ; 1211 return integral; << 1194 } >> 1195 temp = std::sqrt((G4double)2*nHermite)*temp2 ; >> 1196 nwt1 = nwt ; >> 1197 nwt = nwt1 - temp1/temp ; >> 1198 >> 1199 if(std::fabs(nwt - nwt1) <= tolerance) >> 1200 { >> 1201 break ; >> 1202 } >> 1203 } >> 1204 if(k > maxNumber) >> 1205 { >> 1206 G4Exception("G4Integrator<T,F>::Hermite(...)", "Error", >> 1207 FatalException, "Too many (>12) iterations."); >> 1208 } >> 1209 fAbscissa[i-1] = nwt ; >> 1210 fWeight[i-1] = 2.0/(temp*temp) ; >> 1211 } >> 1212 >> 1213 // >> 1214 // Integral calculation >> 1215 // >> 1216 >> 1217 for(i=0;i<fNumber;i++) >> 1218 { >> 1219 integral += fWeight[i]*( (*f)(fAbscissa[i]) + (*f)(-fAbscissa[i]) ) ; >> 1220 } >> 1221 delete[] fAbscissa; >> 1222 delete[] fWeight; >> 1223 return integral ; 1212 } 1224 } 1213 1225 1214 ///////////////////////////////////////////// 1226 //////////////////////////////////////////////////////////////////////////// 1215 // 1227 // 1216 // Method involving Jacobi polynomials 1228 // Method involving Jacobi polynomials 1217 // 1229 // 1218 ///////////////////////////////////////////// 1230 //////////////////////////////////////////////////////////////////////////// 1219 // 1231 // 1220 // Gauss-Jacobi method for integration of ((1 1232 // Gauss-Jacobi method for integration of ((1-x)^alpha)*((1+x)^beta)*f(x) 1221 // from minus unit to plus unit . 1233 // from minus unit to plus unit . 1222 // 1234 // 1223 1235 1224 template <class T, class F> << 1236 template <class T, class F> 1225 G4double G4Integrator<T, F>::Jacobi(T& typeT, << 1237 G4double G4Integrator<T,F>::Jacobi( T& typeT, F f, G4double alpha, 1226 G4double << 1238 G4double beta, G4int nJacobi) 1227 { << 1239 { 1228 const G4double tolerance = 1.0e-12; << 1240 const G4double tolerance = 1.0e-12 ; 1229 const G4double maxNumber = 12; << 1241 const G4double maxNumber = 12 ; 1230 G4int i, k, j; << 1242 G4int i, k, j ; 1231 G4double alphaBeta, alphaReduced, betaReduc << 1243 G4double alphaBeta, alphaReduced, betaReduced, root1=0., root2=0., root3=0. ; 1232 << 1244 G4double a, b, c, nwt1, nwt2, nwt3, nwt, temp, root=0., rootTemp ; 1233 G4double a, b, c, nwt1, nwt2, nwt3, nwt, te << 1245 1234 << 1246 G4int fNumber = nJacobi ; 1235 G4int fNumber = nJacobi; << 1247 G4double* fAbscissa = new G4double[fNumber] ; 1236 G4double* fAbscissa = new G4double[fNumber] << 1248 G4double* fWeight = new G4double[fNumber] ; 1237 G4double* fWeight = new G4double[fNumber] << 1249 1238 << 1250 for (i=1;i<=nJacobi;i++) 1239 for(i = 1; i <= nJacobi; ++i) << 1251 { 1240 { << 1252 if (i == 1) 1241 if(i == 1) << 1253 { 1242 { << 1254 alphaReduced = alpha/nJacobi ; 1243 alphaReduced = alpha / nJacobi; << 1255 betaReduced = beta/nJacobi ; 1244 betaReduced = beta / nJacobi; << 1256 root1 = (1.0+alpha)*(2.78002/(4.0+nJacobi*nJacobi)+ 1245 root1 = (1.0 + alpha) * (2.78002 << 1257 0.767999*alphaReduced/nJacobi) ; 1246 0.767999 * alp << 1258 root2 = 1.0+1.48*alphaReduced+0.96002*betaReduced + 1247 root2 = 1.0 + 1.48 * alphaReduce << 1259 0.451998*alphaReduced*alphaReduced + 1248 0.451998 * alphaReduced * alpha << 1260 0.83001*alphaReduced*betaReduced ; 1249 0.83001 * alphaReduced * betaRe << 1261 root = 1.0-root1/root2 ; 1250 root = 1.0 - root1 / root2; << 1262 } 1251 } << 1263 else if (i == 2) 1252 else if(i == 2) << 1264 { 1253 { << 1265 root1=(4.1002+alpha)/((1.0+alpha)*(1.0+0.155998*alpha)) ; 1254 root1 = (4.1002 + alpha) / ((1.0 + alph << 1266 root2=1.0+0.06*(nJacobi-8.0)*(1.0+0.12*alpha)/nJacobi ; 1255 root2 = 1.0 + 0.06 * (nJacobi - 8.0) * << 1267 root3=1.0+0.012002*beta*(1.0+0.24997*std::fabs(alpha))/nJacobi ; 1256 root3 = << 1268 root -= (1.0-root)*root1*root2*root3 ; 1257 1.0 + 0.012002 * beta * (1.0 + 0.2499 << 1269 } 1258 root -= (1.0 - root) * root1 * root2 * << 1270 else if (i == 3) 1259 } << 1271 { 1260 else if(i == 3) << 1272 root1=(1.67001+0.27998*alpha)/(1.0+0.37002*alpha) ; 1261 { << 1273 root2=1.0+0.22*(nJacobi-8.0)/nJacobi ; 1262 root1 = (1.67001 + 0.27998 * alpha) / ( << 1274 root3=1.0+8.0*beta/((6.28001+beta)*nJacobi*nJacobi) ; 1263 root2 = 1.0 + 0.22 * (nJacobi - 8.0) / << 1275 root -= (fAbscissa[0]-root)*root1*root2*root3 ; 1264 root3 = 1.0 + 8.0 * beta / ((6.28001 + << 1276 } 1265 root -= (fAbscissa[0] - root) * root1 * << 1277 else if (i == nJacobi-1) 1266 } << 1278 { 1267 else if(i == nJacobi - 1) << 1279 root1=(1.0+0.235002*beta)/(0.766001+0.118998*beta) ; 1268 { << 1280 root2=1.0/(1.0+0.639002*(nJacobi-4.0)/(1.0+0.71001*(nJacobi-4.0))) ; 1269 root1 = (1.0 + 0.235002 * beta) / (0.76 << 1281 root3=1.0/(1.0+20.0*alpha/((7.5+alpha)*nJacobi*nJacobi)) ; 1270 root2 = 1.0 / (1.0 + 0.639002 * (nJacob << 1282 root += (root-fAbscissa[nJacobi-4])*root1*root2*root3 ; 1271 (1.0 + 0.71001 * << 1283 } 1272 root3 = 1.0 / (1.0 + 20.0 * alpha / ((7 << 1284 else if (i == nJacobi) 1273 root += (root - fAbscissa[nJacobi - 4]) << 1285 { 1274 } << 1286 root1 = (1.0+0.37002*beta)/(1.67001+0.27998*beta) ; 1275 else if(i == nJacobi) << 1287 root2 = 1.0/(1.0+0.22*(nJacobi-8.0)/nJacobi) ; 1276 { << 1288 root3 = 1.0/(1.0+8.0*alpha/((6.28002+alpha)*nJacobi*nJacobi)) ; 1277 root1 = (1.0 + 0.37002 * beta) / (1.670 << 1289 root += (root-fAbscissa[nJacobi-3])*root1*root2*root3 ; 1278 root2 = 1.0 / (1.0 + 0.22 * (nJacobi - << 1290 } 1279 root3 = << 1291 else 1280 1.0 / (1.0 + 8.0 * alpha / ((6.28002 << 1292 { 1281 root += (root - fAbscissa[nJacobi - 3]) << 1293 root = 3.0*fAbscissa[i-2]-3.0*fAbscissa[i-3]+fAbscissa[i-4] ; 1282 } << 1294 } 1283 else << 1295 alphaBeta = alpha + beta ; 1284 { << 1296 for (k=1;k<=maxNumber;k++) 1285 root = 3.0 * fAbscissa[i - 2] - 3.0 * f << 1297 { 1286 } << 1298 temp = 2.0 + alphaBeta ; 1287 alphaBeta = alpha + beta; << 1299 nwt1 = (alpha-beta+temp*root)/2.0 ; 1288 for(k = 1; k <= maxNumber; ++k) << 1300 nwt2 = 1.0 ; 1289 { << 1301 for (j=2;j<=nJacobi;j++) 1290 temp = 2.0 + alphaBeta; << 1302 { 1291 nwt1 = (alpha - beta + temp * root) / 2 << 1303 nwt3 = nwt2 ; 1292 nwt2 = 1.0; << 1304 nwt2 = nwt1 ; 1293 for(j = 2; j <= nJacobi; ++j) << 1305 temp = 2*j+alphaBeta ; 1294 { << 1306 a = 2*j*(j+alphaBeta)*(temp-2.0) ; 1295 nwt3 = nwt2; << 1307 b = (temp-1.0)*(alpha*alpha-beta*beta+temp*(temp-2.0)*root) ; 1296 nwt2 = nwt1; << 1308 c = 2.0*(j-1+alpha)*(j-1+beta)*temp ; 1297 temp = 2 * j + alphaBeta; << 1309 nwt1 = (b*nwt2-c*nwt3)/a ; 1298 a = 2 * j * (j + alphaBeta) * (tem << 1310 } 1299 b = (temp - 1.0) * << 1311 nwt = (nJacobi*(alpha - beta - temp*root)*nwt1 + 1300 (alpha * alpha - beta * beta + te << 1312 2.0*(nJacobi + alpha)*(nJacobi + beta)*nwt2)/ 1301 c = 2.0 * (j - 1 + alpha) * (j - 1 << 1313 (temp*(1.0 - root*root)) ; 1302 nwt1 = (b * nwt2 - c * nwt3) / a; << 1314 rootTemp = root ; 1303 } << 1315 root = rootTemp - nwt1/nwt ; 1304 nwt = (nJacobi * (alpha - beta - temp * << 1316 if (std::fabs(root-rootTemp) <= tolerance) 1305 2.0 * (nJacobi + alpha) * (nJaco << 1317 { 1306 (temp * (1.0 - root * root)); << 1318 break ; 1307 rootTemp = root; << 1319 } 1308 root = rootTemp - nwt1 / nwt; << 1320 } 1309 if(std::fabs(root - rootTemp) <= tolera << 1321 if (k > maxNumber) 1310 { << 1322 { 1311 break; << 1323 G4Exception("G4Integrator<T,F>::Jacobi(T,F, ...)", "Error", 1312 } << 1324 FatalException, "Too many (>12) iterations."); 1313 } << 1325 } 1314 if(k > maxNumber) << 1326 fAbscissa[i-1] = root ; 1315 { << 1327 fWeight[i-1] = std::exp(GammaLogarithm((G4double)(alpha+nJacobi)) + 1316 G4Exception("G4Integrator<T,F>::Jacobi( << 1328 GammaLogarithm((G4double)(beta+nJacobi)) - 1317 FatalException, "Too many ( << 1329 GammaLogarithm((G4double)(nJacobi+1.0)) - 1318 } << 1330 GammaLogarithm((G4double)(nJacobi + alphaBeta + 1.0))) 1319 fAbscissa[i - 1] = root; << 1331 *temp*std::pow(2.0,alphaBeta)/(nwt*nwt2) ; 1320 fWeight[i - 1] = << 1332 } 1321 std::exp(GammaLogarithm((G4double)(alph << 1333 1322 GammaLogarithm((G4double)(beta << 1334 // 1323 GammaLogarithm((G4double)(nJac << 1335 // Calculation of the integral 1324 GammaLogarithm((G4double)(nJac << 1336 // 1325 temp * std::pow(2.0, alphaBeta) / (nwt << 1337 1326 } << 1338 G4double integral = 0.0 ; 1327 << 1339 for(i=0;i<fNumber;i++) 1328 // << 1340 { 1329 // Calculation of the integral << 1341 integral += fWeight[i]*(typeT.*f)(fAbscissa[i]) ; 1330 // << 1342 } 1331 << 1343 delete[] fAbscissa; 1332 G4double integral = 0.0; << 1344 delete[] fWeight; 1333 for(i = 0; i < fNumber; ++i) << 1345 return integral ; 1334 { << 1335 integral += fWeight[i] * (typeT.*f)(fAbsc << 1336 } << 1337 delete[] fAbscissa; << 1338 delete[] fWeight; << 1339 return integral; << 1340 } 1346 } 1341 1347 >> 1348 1342 ///////////////////////////////////////////// 1349 ///////////////////////////////////////////////////////////////////////// 1343 // 1350 // 1344 // For use with 'this' pointer 1351 // For use with 'this' pointer 1345 1352 1346 template <class T, class F> << 1353 template <class T, class F> 1347 G4double G4Integrator<T, F>::Jacobi(T* ptrT, << 1354 G4double G4Integrator<T,F>::Jacobi( T* ptrT, F f, G4double alpha, 1348 G4int n) << 1355 G4double beta, G4int n) 1349 { 1356 { 1350 return Jacobi(*ptrT, f, alpha, beta, n); << 1357 return Jacobi(*ptrT,f,alpha,beta,n) ; 1351 } << 1358 } 1352 1359 1353 ///////////////////////////////////////////// 1360 ///////////////////////////////////////////////////////////////////////// 1354 // 1361 // 1355 // For use with global scope f << 1362 // For use with global scope f 1356 1363 1357 template <class T, class F> 1364 template <class T, class F> 1358 G4double G4Integrator<T, F>::Jacobi(G4double << 1365 G4double G4Integrator<T,F>::Jacobi( G4double (*f)(G4double), G4double alpha, 1359 G4double << 1366 G4double beta, G4int nJacobi) 1360 { 1367 { 1361 const G4double tolerance = 1.0e-12; << 1368 const G4double tolerance = 1.0e-12 ; 1362 const G4double maxNumber = 12; << 1369 const G4double maxNumber = 12 ; 1363 G4int i, k, j; << 1370 G4int i, k, j ; 1364 G4double alphaBeta, alphaReduced, betaReduc << 1371 G4double alphaBeta, alphaReduced, betaReduced, root1=0., root2=0., root3=0. ; 1365 << 1372 G4double a, b, c, nwt1, nwt2, nwt3, nwt, temp, root=0., rootTemp ; 1366 G4double a, b, c, nwt1, nwt2, nwt3, nwt, te << 1373 1367 << 1374 G4int fNumber = nJacobi ; 1368 G4int fNumber = nJacobi; << 1375 G4double* fAbscissa = new G4double[fNumber] ; 1369 G4double* fAbscissa = new G4double[fNumber] << 1376 G4double* fWeight = new G4double[fNumber] ; 1370 G4double* fWeight = new G4double[fNumber] << 1377 1371 << 1378 for (i=1;i<=nJacobi;i++) 1372 for(i = 1; i <= nJacobi; ++i) << 1379 { 1373 { << 1380 if (i == 1) 1374 if(i == 1) << 1381 { 1375 { << 1382 alphaReduced = alpha/nJacobi ; 1376 alphaReduced = alpha / nJacobi; << 1383 betaReduced = beta/nJacobi ; 1377 betaReduced = beta / nJacobi; << 1384 root1 = (1.0+alpha)*(2.78002/(4.0+nJacobi*nJacobi)+ 1378 root1 = (1.0 + alpha) * (2.78002 << 1385 0.767999*alphaReduced/nJacobi) ; 1379 0.767999 * alp << 1386 root2 = 1.0+1.48*alphaReduced+0.96002*betaReduced + 1380 root2 = 1.0 + 1.48 * alphaReduce << 1387 0.451998*alphaReduced*alphaReduced + 1381 0.451998 * alphaReduced * alpha << 1388 0.83001*alphaReduced*betaReduced ; 1382 0.83001 * alphaReduced * betaRe << 1389 root = 1.0-root1/root2 ; 1383 root = 1.0 - root1 / root2; << 1390 } 1384 } << 1391 else if (i == 2) 1385 else if(i == 2) << 1392 { 1386 { << 1393 root1=(4.1002+alpha)/((1.0+alpha)*(1.0+0.155998*alpha)) ; 1387 root1 = (4.1002 + alpha) / ((1.0 + alph << 1394 root2=1.0+0.06*(nJacobi-8.0)*(1.0+0.12*alpha)/nJacobi ; 1388 root2 = 1.0 + 0.06 * (nJacobi - 8.0) * << 1395 root3=1.0+0.012002*beta*(1.0+0.24997*std::fabs(alpha))/nJacobi ; 1389 root3 = << 1396 root -= (1.0-root)*root1*root2*root3 ; 1390 1.0 + 0.012002 * beta * (1.0 + 0.2499 << 1397 } 1391 root -= (1.0 - root) * root1 * root2 * << 1398 else if (i == 3) 1392 } << 1399 { 1393 else if(i == 3) << 1400 root1=(1.67001+0.27998*alpha)/(1.0+0.37002*alpha) ; 1394 { << 1401 root2=1.0+0.22*(nJacobi-8.0)/nJacobi ; 1395 root1 = (1.67001 + 0.27998 * alpha) / ( << 1402 root3=1.0+8.0*beta/((6.28001+beta)*nJacobi*nJacobi) ; 1396 root2 = 1.0 + 0.22 * (nJacobi - 8.0) / << 1403 root -= (fAbscissa[0]-root)*root1*root2*root3 ; 1397 root3 = 1.0 + 8.0 * beta / ((6.28001 + << 1404 } 1398 root -= (fAbscissa[0] - root) * root1 * << 1405 else if (i == nJacobi-1) 1399 } << 1406 { 1400 else if(i == nJacobi - 1) << 1407 root1=(1.0+0.235002*beta)/(0.766001+0.118998*beta) ; 1401 { << 1408 root2=1.0/(1.0+0.639002*(nJacobi-4.0)/(1.0+0.71001*(nJacobi-4.0))) ; 1402 root1 = (1.0 + 0.235002 * beta) / (0.76 << 1409 root3=1.0/(1.0+20.0*alpha/((7.5+alpha)*nJacobi*nJacobi)) ; 1403 root2 = 1.0 / (1.0 + 0.639002 * (nJacob << 1410 root += (root-fAbscissa[nJacobi-4])*root1*root2*root3 ; 1404 (1.0 + 0.71001 * << 1411 } 1405 root3 = 1.0 / (1.0 + 20.0 * alpha / ((7 << 1412 else if (i == nJacobi) 1406 root += (root - fAbscissa[nJacobi - 4]) << 1413 { 1407 } << 1414 root1 = (1.0+0.37002*beta)/(1.67001+0.27998*beta) ; 1408 else if(i == nJacobi) << 1415 root2 = 1.0/(1.0+0.22*(nJacobi-8.0)/nJacobi) ; 1409 { << 1416 root3 = 1.0/(1.0+8.0*alpha/((6.28002+alpha)*nJacobi*nJacobi)) ; 1410 root1 = (1.0 + 0.37002 * beta) / (1.670 << 1417 root += (root-fAbscissa[nJacobi-3])*root1*root2*root3 ; 1411 root2 = 1.0 / (1.0 + 0.22 * (nJacobi - << 1418 } 1412 root3 = << 1419 else 1413 1.0 / (1.0 + 8.0 * alpha / ((6.28002 << 1420 { 1414 root += (root - fAbscissa[nJacobi - 3]) << 1421 root = 3.0*fAbscissa[i-2]-3.0*fAbscissa[i-3]+fAbscissa[i-4] ; 1415 } << 1422 } 1416 else << 1423 alphaBeta = alpha + beta ; 1417 { << 1424 for (k=1;k<=maxNumber;k++) 1418 root = 3.0 * fAbscissa[i - 2] - 3.0 * f << 1425 { 1419 } << 1426 temp = 2.0 + alphaBeta ; 1420 alphaBeta = alpha + beta; << 1427 nwt1 = (alpha-beta+temp*root)/2.0 ; 1421 for(k = 1; k <= maxNumber; ++k) << 1428 nwt2 = 1.0 ; 1422 { << 1429 for (j=2;j<=nJacobi;j++) 1423 temp = 2.0 + alphaBeta; << 1430 { 1424 nwt1 = (alpha - beta + temp * root) / 2 << 1431 nwt3 = nwt2 ; 1425 nwt2 = 1.0; << 1432 nwt2 = nwt1 ; 1426 for(j = 2; j <= nJacobi; ++j) << 1433 temp = 2*j+alphaBeta ; 1427 { << 1434 a = 2*j*(j+alphaBeta)*(temp-2.0) ; 1428 nwt3 = nwt2; << 1435 b = (temp-1.0)*(alpha*alpha-beta*beta+temp*(temp-2.0)*root) ; 1429 nwt2 = nwt1; << 1436 c = 2.0*(j-1+alpha)*(j-1+beta)*temp ; 1430 temp = 2 * j + alphaBeta; << 1437 nwt1 = (b*nwt2-c*nwt3)/a ; 1431 a = 2 * j * (j + alphaBeta) * (tem << 1438 } 1432 b = (temp - 1.0) * << 1439 nwt = (nJacobi*(alpha - beta - temp*root)*nwt1 + 1433 (alpha * alpha - beta * beta + te << 1440 2.0*(nJacobi + alpha)*(nJacobi + beta)*nwt2) / 1434 c = 2.0 * (j - 1 + alpha) * (j - 1 << 1441 (temp*(1.0 - root*root)) ; 1435 nwt1 = (b * nwt2 - c * nwt3) / a; << 1442 rootTemp = root ; 1436 } << 1443 root = rootTemp - nwt1/nwt ; 1437 nwt = (nJacobi * (alpha - beta - temp * << 1444 if (std::fabs(root-rootTemp) <= tolerance) 1438 2.0 * (nJacobi + alpha) * (nJaco << 1445 { 1439 (temp * (1.0 - root * root)); << 1446 break ; 1440 rootTemp = root; << 1447 } 1441 root = rootTemp - nwt1 / nwt; << 1448 } 1442 if(std::fabs(root - rootTemp) <= tolera << 1449 if (k > maxNumber) 1443 { << 1450 { 1444 break; << 1451 G4Exception("G4Integrator<T,F>::Jacobi(...)", "Error", 1445 } << 1452 FatalException, "Too many (>12) iterations."); 1446 } << 1453 } 1447 if(k > maxNumber) << 1454 fAbscissa[i-1] = root ; 1448 { << 1455 fWeight[i-1] = 1449 G4Exception("G4Integrator<T,F>::Jacobi( << 1456 std::exp(GammaLogarithm((G4double)(alpha+nJacobi)) + 1450 "Too many (>12) iterations. << 1457 GammaLogarithm((G4double)(beta+nJacobi)) - 1451 } << 1458 GammaLogarithm((G4double)(nJacobi+1.0)) - 1452 fAbscissa[i - 1] = root; << 1459 GammaLogarithm((G4double)(nJacobi + alphaBeta + 1.0))) 1453 fWeight[i - 1] = << 1460 *temp*std::pow(2.0,alphaBeta)/(nwt*nwt2); 1454 std::exp(GammaLogarithm((G4double)(alph << 1461 } 1455 GammaLogarithm((G4double)(beta << 1462 1456 GammaLogarithm((G4double)(nJac << 1463 // 1457 GammaLogarithm((G4double)(nJac << 1464 // Calculation of the integral 1458 temp * std::pow(2.0, alphaBeta) / (nwt << 1465 // 1459 } << 1466 1460 << 1467 G4double integral = 0.0 ; 1461 // << 1468 for(i=0;i<fNumber;i++) 1462 // Calculation of the integral << 1469 { 1463 // << 1470 integral += fWeight[i]*(*f)(fAbscissa[i]) ; 1464 << 1471 } 1465 G4double integral = 0.0; << 1472 delete[] fAbscissa; 1466 for(i = 0; i < fNumber; ++i) << 1473 delete[] fWeight; 1467 { << 1474 return integral ; 1468 integral += fWeight[i] * (*f)(fAbscissa[i << 1469 } << 1470 delete[] fAbscissa; << 1471 delete[] fWeight; << 1472 return integral; << 1473 } 1475 } 1474 1476 1475 // 1477 // 1476 // 1478 // 1477 ///////////////////////////////////////////// 1479 /////////////////////////////////////////////////////////////////// 1478 1480