Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/global/HEPNumerics/include/G4PolynomialSolver.icc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /global/HEPNumerics/include/G4PolynomialSolver.icc (Version 11.3.0) and /global/HEPNumerics/include/G4PolynomialSolver.icc (Version 8.0.p1)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                    <<   3 // * DISCLAIMER                                                       *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th <<   5 // * The following disclaimer summarizes all the specific disclaimers *
  6 // * the Geant4 Collaboration.  It is provided <<   6 // * of contributors to this software. The specific disclaimers,which *
  7 // * conditions of the Geant4 Software License <<   7 // * govern, are listed with their locations in:                      *
  8 // * LICENSE and available at  http://cern.ch/ <<   8 // *   http://cern.ch/geant4/license                                  *
  9 // * include a list of copyright holders.      << 
 10 // *                                                9 // *                                                                  *
 11 // * Neither the authors of this software syst     10 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     11 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     12 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     13 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  <<  14 // * use.                                                             *
 16 // * for the full disclaimer and the limitatio << 
 17 // *                                               15 // *                                                                  *
 18 // * This  code  implementation is the result  <<  16 // * This  code  implementation is the  intellectual property  of the *
 19 // * technical work of the GEANT4 collaboratio <<  17 // * GEANT4 collaboration.                                            *
 20 // * By using,  copying,  modifying or  distri <<  18 // * By copying,  distributing  or modifying the Program (or any work *
 21 // * any work based  on the software)  you  ag <<  19 // * based  on  the Program)  you indicate  your  acceptance of  this *
 22 // * use  in  resulting  scientific  publicati <<  20 // * statement, and all its terms.                                    *
 23 // * acceptance of all terms of the Geant4 Sof << 
 24 // *******************************************     21 // ********************************************************************
 25 //                                                 22 //
 26 // G4PolynomialSolver inline methods implement << 
 27 //                                                 23 //
 28 // Author: E.Medernach, 19.12.2000 - First imp <<  24 // $Id: G4PolynomialSolver.icc,v 1.7 2004/11/12 17:38:29 gcosmo Exp $
 29 // ------------------------------------------- <<  25 // GEANT4 tag $Name: geant4-08-00-patch-01 $
                                                   >>  26 // 
                                                   >>  27 // class G4PolynomialSolver
                                                   >>  28 //
                                                   >>  29 // 19.12.00 E.Medernach, First implementation
                                                   >>  30 //
 30                                                    31 
 31 #define POLEPSILON 1e-12                       <<  32 #define POLEPSILON   1e-12
 32 #define POLINFINITY 9.0E99                     <<  33 #define POLINFINITY  9.0E99
 33 #define ITERATION 12  // 20 But 8 is really en <<  34 #define ITERATION  12 // 20 But 8 is really enough for Newton with a good guess
 34                                                    35 
 35 template <class T, class F>                        36 template <class T, class F>
 36 G4PolynomialSolver<T, F>::G4PolynomialSolver(T <<  37 G4PolynomialSolver<T,F>::G4PolynomialSolver (T* typeF, F func, F deriv,
 37                                              G     38                                              G4double precision)
 38 {                                                  39 {
 39   Precision     = precision;                   <<  40   Precision = precision ;
 40   FunctionClass = typeF;                       <<  41   FunctionClass = typeF ;
 41   Function      = func;                        <<  42   Function = func ;
 42   Derivative    = deriv;                       <<  43   Derivative = deriv ;  
 43 }                                                  44 }
 44                                                    45 
 45 template <class T, class F>                        46 template <class T, class F>
 46 G4PolynomialSolver<T, F>::~G4PolynomialSolver( <<  47 G4PolynomialSolver<T,F>::~G4PolynomialSolver ()
 47 {}                                             <<  48 {
                                                   >>  49 }
 48                                                    50 
 49 template <class T, class F>                        51 template <class T, class F>
 50 G4double G4PolynomialSolver<T, F>::solve(G4dou <<  52 G4double G4PolynomialSolver<T,F>::solve(G4double IntervalMin,
 51                                          G4dou <<  53           G4double IntervalMax)
 52 {                                                  54 {
 53   return Newton(IntervalMin, IntervalMax);     <<  55   return Newton(IntervalMin,IntervalMax);  
 54 }                                                  56 }
 55                                                    57 
                                                   >>  58 
 56 /* If we want to be general this could work fo     59 /* If we want to be general this could work for any
 57    polynomial of order more that 4 if we find      60    polynomial of order more that 4 if we find the (ORDER + 1)
 58    control points                                  61    control points
 59 */                                                 62 */
 60 #define NBBEZIER 5                                 63 #define NBBEZIER 5
 61                                                    64 
 62 template <class T, class F>                        65 template <class T, class F>
 63 G4int G4PolynomialSolver<T, F>::BezierClipping <<  66 G4int
 64                                                <<  67 G4PolynomialSolver<T,F>::BezierClipping(/*T* typeF,F func,F deriv,*/
 65                                                <<  68           G4double *IntervalMin,
                                                   >>  69           G4double *IntervalMax)
 66 {                                                  70 {
 67   /** BezierClipping is a clipping interval Ne     71   /** BezierClipping is a clipping interval Newton method **/
 68   /** It works by clipping the area where the      72   /** It works by clipping the area where the polynomial is **/
 69                                                    73 
 70   G4double P[NBBEZIER][2], D[2];               <<  74   G4double P[NBBEZIER][2],D[2];
 71   G4double NewMin, NewMax;                     <<  75   G4double NewMin,NewMax;
 72                                                    76 
 73   G4int IntervalIsVoid = 1;                        77   G4int IntervalIsVoid = 1;
 74                                                <<  78   
 75   /*** Calculating Control Points  ***/            79   /*** Calculating Control Points  ***/
 76   /* We see the polynomial as a Bezier curve f     80   /* We see the polynomial as a Bezier curve for some control points to find */
 77                                                    81 
 78   /*                                               82   /*
 79     For 5 control points (polynomial of degree     83     For 5 control points (polynomial of degree 4) this is:
 80                                                <<  84     
 81     0     p0 = F((*IntervalMin))                   85     0     p0 = F((*IntervalMin))
 82     1/4   p1 = F((*IntervalMin)) + ((*Interval     86     1/4   p1 = F((*IntervalMin)) + ((*IntervalMax) - (*IntervalMin))/4
 83                  * F'((*IntervalMin))              87                  * F'((*IntervalMin))
 84     2/4   p2 = 1/6 * (16*F(((*IntervalMax) + (     88     2/4   p2 = 1/6 * (16*F(((*IntervalMax) + (*IntervalMin))/2)
 85                       - (p0 + 4*p1 + 4*p3 + p4 <<  89                       - (p0 + 4*p1 + 4*p3 + p4))  
 86     3/4   p3 = F((*IntervalMax)) - ((*Interval     90     3/4   p3 = F((*IntervalMax)) - ((*IntervalMax) - (*IntervalMin))/4
 87                  * F'((*IntervalMax))              91                  * F'((*IntervalMax))
 88     1     p4 = F((*IntervalMax))                   92     1     p4 = F((*IntervalMax))
 89   */                                           <<  93   */  
 90                                                    94 
 91   /* x,y,z,dx,dy,dz are constant during search     95   /* x,y,z,dx,dy,dz are constant during searching */
 92                                                    96 
 93   D[0] = (FunctionClass->*Derivative)(*Interva     97   D[0] = (FunctionClass->*Derivative)(*IntervalMin);
 94                                                <<  98   
 95   P[0][0] = (*IntervalMin);                        99   P[0][0] = (*IntervalMin);
 96   P[0][1] = (FunctionClass->*Function)(*Interv    100   P[0][1] = (FunctionClass->*Function)(*IntervalMin);
                                                   >> 101   
 97                                                   102 
 98   if(std::fabs(P[0][1]) < Precision)           << 103   if (std::fabs(P[0][1]) < Precision) {
 99   {                                            << 
100     return 1;                                     104     return 1;
101   }                                               105   }
102                                                << 106   
103   if(((*IntervalMax) - (*IntervalMin)) < POLEP << 107   if (((*IntervalMax) - (*IntervalMin)) < POLEPSILON) {
104   {                                            << 
105     return 1;                                     108     return 1;
106   }                                               109   }
107                                                   110 
108   P[1][0] = (*IntervalMin) + ((*IntervalMax) - << 111   P[1][0] = (*IntervalMin) + ((*IntervalMax) - (*IntervalMin))/4;
109   P[1][1] = P[0][1] + (((*IntervalMax) - (*Int << 112   P[1][1] = P[0][1] + (((*IntervalMax) - (*IntervalMin))/4.0) * D[0];
110                                                   113 
111   D[1] = (FunctionClass->*Derivative)(*Interva    114   D[1] = (FunctionClass->*Derivative)(*IntervalMax);
112                                                   115 
113   P[4][0] = (*IntervalMax);                       116   P[4][0] = (*IntervalMax);
114   P[4][1] = (FunctionClass->*Function)(*Interv    117   P[4][1] = (FunctionClass->*Function)(*IntervalMax);
                                                   >> 118   
                                                   >> 119   P[3][0] = (*IntervalMax) - ((*IntervalMax) - (*IntervalMin))/4;
                                                   >> 120   P[3][1] = P[4][1] - ((*IntervalMax) - (*IntervalMin))/4 * D[1];
                                                   >> 121 
                                                   >> 122   P[2][0] = ((*IntervalMax) + (*IntervalMin))/2;
                                                   >> 123   P[2][1] = (16*(FunctionClass->*Function)(((*IntervalMax)+(*IntervalMin))/2)
                                                   >> 124              - (P[0][1] + 4*P[1][1] + 4*P[3][1] + P[4][1]))/6 ;
                                                   >> 125 
                                                   >> 126   {
                                                   >> 127     G4double Intersection ;
                                                   >> 128     G4int i,j;
                                                   >> 129   
                                                   >> 130     NewMin = (*IntervalMax) ;
                                                   >> 131     NewMax = (*IntervalMin) ;    
                                                   >> 132 
                                                   >> 133     for (i=0;i<5;i++)
                                                   >> 134       for (j=i+1;j<5;j++)
                                                   >> 135   {
                                                   >> 136     /* there is an intersection only if each have different signs */
                                                   >> 137     if (((P[j][1] > -Precision) && (P[i][1] < Precision)) ||
                                                   >> 138         ((P[j][1] < Precision) && (P[i][1] > -Precision))) {
                                                   >> 139       IntervalIsVoid  = 0;
                                                   >> 140       Intersection = P[j][0] - P[j][1]*((P[i][0] - P[j][0])/
                                                   >> 141                                         (P[i][1] - P[j][1]));
                                                   >> 142       if (Intersection < NewMin) {
                                                   >> 143         NewMin = Intersection;
                                                   >> 144       }
                                                   >> 145       if (Intersection > NewMax) {
                                                   >> 146         NewMax = Intersection;
                                                   >> 147       }
                                                   >> 148     }
                                                   >> 149   }
115                                                   150 
116   P[3][0] = (*IntervalMax) - ((*IntervalMax) - << 151     
117   P[3][1] = P[4][1] - ((*IntervalMax) - (*Inte << 152     if (IntervalIsVoid != 1) {
118                                                << 
119   P[2][0] = ((*IntervalMax) + (*IntervalMin))  << 
120   P[2][1] =                                    << 
121     (16 * (FunctionClass->*Function)(((*Interv << 
122      (P[0][1] + 4 * P[1][1] + 4 * P[3][1] + P[ << 
123     6;                                         << 
124                                                << 
125   {                                            << 
126     G4double Intersection;                     << 
127     G4int i, j;                                << 
128                                                << 
129     NewMin = (*IntervalMax);                   << 
130     NewMax = (*IntervalMin);                   << 
131                                                << 
132     for(i = 0; i < 5; ++i)                     << 
133       for(j = i + 1; j < 5; ++j)               << 
134       {                                        << 
135         /* there is an intersection only if ea << 
136         if(((P[j][1] > -Precision) && (P[i][1] << 
137            ((P[j][1] < Precision) && (P[i][1]  << 
138         {                                      << 
139           IntervalIsVoid = 0;                  << 
140           Intersection =                       << 
141             P[j][0] - P[j][1] * ((P[i][0] - P[ << 
142           if(Intersection < NewMin)            << 
143           {                                    << 
144             NewMin = Intersection;             << 
145           }                                    << 
146           if(Intersection > NewMax)            << 
147           {                                    << 
148             NewMax = Intersection;             << 
149           }                                    << 
150         }                                      << 
151       }                                        << 
152                                                << 
153     if(IntervalIsVoid != 1)                    << 
154     {                                          << 
155       (*IntervalMax) = NewMax;                    153       (*IntervalMax) = NewMax;
156       (*IntervalMin) = NewMin;                    154       (*IntervalMin) = NewMin;
157     }                                             155     }
158   }                                               156   }
159                                                << 157   
160   if(IntervalIsVoid == 1)                      << 158   if (IntervalIsVoid == 1) {
161   {                                            << 
162     return -1;                                    159     return -1;
163   }                                               160   }
164                                                << 161   
165   return 0;                                       162   return 0;
166 }                                                 163 }
167                                                   164 
168 template <class T, class F>                       165 template <class T, class F>
169 G4double G4PolynomialSolver<T, F>::Newton(G4do << 166 G4double G4PolynomialSolver<T,F>::Newton (G4double IntervalMin,
170                                           G4do    167                                           G4double IntervalMax)
171 {                                                 168 {
172   /* So now we have a good guess and an interv    169   /* So now we have a good guess and an interval where
173      if there are an intersection the root mus    170      if there are an intersection the root must be */
174                                                   171 
175   G4double Value    = 0;                       << 172   G4double Value = 0;
176   G4double Gradient = 0;                          173   G4double Gradient = 0;
177   G4double Lambda;                             << 174   G4double Lambda ;
178                                                << 
179   G4int i = 0;                                 << 
180   G4int j = 0;                                 << 
181                                                   175 
                                                   >> 176   G4int i=0;
                                                   >> 177   G4int j=0;
                                                   >> 178   
                                                   >> 179   
182   /* Reduce interval before applying Newton Me    180   /* Reduce interval before applying Newton Method */
183   {                                               181   {
184     G4int NewtonIsSafe;                        << 182     G4int NewtonIsSafe ;
185                                                   183 
186     while((NewtonIsSafe = BezierClipping(&Inte << 184     while ((NewtonIsSafe = BezierClipping(&IntervalMin,&IntervalMax)) == 0) ;
187       ;                                        << 
188                                                   185 
189     if(NewtonIsSafe == -1)                     << 186     if (NewtonIsSafe == -1) {
190     {                                          << 
191       return POLINFINITY;                         187       return POLINFINITY;
192     }                                             188     }
193   }                                               189   }
194                                                   190 
195   Lambda = IntervalMin;                           191   Lambda = IntervalMin;
196   Value  = (FunctionClass->*Function)(Lambda); << 192   Value = (FunctionClass->*Function)(Lambda);
                                                   >> 193 
197                                                   194 
198   //  while ((std::fabs(Value) > Precision)) {    195   //  while ((std::fabs(Value) > Precision)) {
199   while(j != -1)                               << 196   while (j != -1) {
200   {                                            << 197     
201     Value = (FunctionClass->*Function)(Lambda)    198     Value = (FunctionClass->*Function)(Lambda);
202                                                   199 
203     Gradient = (FunctionClass->*Derivative)(La    200     Gradient = (FunctionClass->*Derivative)(Lambda);
204                                                   201 
205     Lambda = Lambda - Value / Gradient;        << 202     Lambda = Lambda - Value/Gradient ;
206                                                   203 
207     if(std::fabs(Value) <= Precision)          << 204     if (std::fabs(Value) <= Precision) {
208     {                                          << 205       j ++;
209       ++j;                                     << 206       if (j == 2) {
210       if(j == 2)                               << 207   j = -1; 
211       {                                        << 208       }      
212         j = -1;                                << 209     } else {
213       }                                        << 210       i ++;
214     }                                          << 211       
215     else                                       << 212       if (i > ITERATION) 
216     {                                          << 213   return POLINFINITY;
217       ++i;                                     << 214     }    
218                                                << 
219       if(i > ITERATION)                        << 
220         return POLINFINITY;                    << 
221     }                                          << 
222   }                                               215   }
223   return Lambda;                               << 216   return Lambda ;
224 }                                                 217 }
225                                                   218