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