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