Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4JTPolynomialSolver Class Reference

#include <G4JTPolynomialSolver.hh>

Public Member Functions

 G4JTPolynomialSolver ()
 
 ~G4JTPolynomialSolver ()
 
G4int FindRoots (G4double *op, G4int degree, G4double *zeror, G4double *zeroi)
 

Detailed Description

Definition at line 70 of file G4JTPolynomialSolver.hh.

Constructor & Destructor Documentation

◆ G4JTPolynomialSolver()

G4JTPolynomialSolver::G4JTPolynomialSolver ( )

Definition at line 47 of file G4JTPolynomialSolver.cc.

48 : sr(0.), si(0.), u(0.),v(0.),
49 a(0.), b(0.), c(0.), d(0.),
50 a1(0.), a2(0.), a3(0.), a6(0.), a7(0.),
51 e(0.), f(0.), g(0.), h(0.),
52 szr(0.), szi(0.), lzr(0.), lzi(0.),
53 n(0), nmi(0)
54{
55}

◆ ~G4JTPolynomialSolver()

G4JTPolynomialSolver::~G4JTPolynomialSolver ( )

Definition at line 57 of file G4JTPolynomialSolver.cc.

58{
59}

Member Function Documentation

◆ FindRoots()

G4int G4JTPolynomialSolver::FindRoots ( G4double op,
G4int  degree,
G4double zeror,
G4double zeroi 
)

Definition at line 61 of file G4JTPolynomialSolver.cc.

63{
64 G4double t=0.0, aa=0.0, bb=0.0, cc=0.0, factor=1.0;
65 G4double max=0.0, min=infin, xxx=0.0, x=0.0, sc=0.0, bnd=0.0;
66 G4double xm=0.0, ff=0.0, df=0.0, dx=0.0;
67 G4int cnt=0, nz=0, i=0, j=0, jj=0, l=0, nm1=0, zerok=0;
68
69 // Initialization of constants for shift rotation.
70 //
71 G4double xx = std::sqrt(0.5);
72 G4double yy = -xx,
73 rot = 94.0*deg;
74 G4double cosr = std::cos(rot),
75 sinr = std::sin(rot);
76 n = degr;
77
78 // Algorithm fails if the leading coefficient is zero.
79 //
80 if (!(op[0] != 0.0)) { return -1; }
81
82 // Remove the zeros at the origin, if any.
83 //
84 while (!(op[n] != 0.0))
85 {
86 j = degr - n;
87 zeror[j] = 0.0;
88 zeroi[j] = 0.0;
89 n--;
90 }
91 if (n < 1) { return -1; }
92
93 // Allocate buffers here
94 //
95 std::vector<G4double> temp(degr+1) ;
96 std::vector<G4double> pt(degr+1) ;
97
98 p.assign(degr+1,0) ;
99 qp.assign(degr+1,0) ;
100 k.assign(degr+1,0) ;
101 qk.assign(degr+1,0) ;
102 svk.assign(degr+1,0) ;
103
104 // Make a copy of the coefficients.
105 //
106 for (i=0;i<=n;i++)
107 { p[i] = op[i]; }
108
109 do
110 {
111 if (n == 1) // Start the algorithm for one zero.
112 {
113 zeror[degr-1] = -p[1]/p[0];
114 zeroi[degr-1] = 0.0;
115 n -= 1;
116 return degr - n ;
117 }
118 if (n == 2) // Calculate the final zero or pair of zeros.
119 {
120 Quadratic(p[0],p[1],p[2],&zeror[degr-2],&zeroi[degr-2],
121 &zeror[degr-1],&zeroi[degr-1]);
122 n -= 2;
123 return degr - n ;
124 }
125
126 // Find largest and smallest moduli of coefficients.
127 //
128 max = 0.0;
129 min = infin;
130 for (i=0;i<=n;i++)
131 {
132 x = std::fabs(p[i]);
133 if (x > max) { max = x; }
134 if (x != 0.0 && x < min) { min = x; }
135 }
136
137 // Scale if there are large or very small coefficients.
138 // Computes a scale factor to multiply the coefficients of the
139 // polynomial. The scaling is done to avoid overflow and to
140 // avoid undetected underflow interfering with the convergence
141 // criterion. The factor is a power of the base.
142 //
143 sc = lo/min;
144
145 if ( ((sc <= 1.0) && (max >= 10.0))
146 || ((sc > 1.0) && (infin/sc >= max))
147 || ((infin/sc >= max) && (max >= 10)) )
148 {
149 if (!( sc != 0.0 ))
150 { sc = smalno ; }
151 l = (G4int)(std::log(sc)/std::log(base) + 0.5);
152 factor = std::pow(base*1.0,l);
153 if (factor != 1.0)
154 {
155 for (i=0;i<=n;i++)
156 { p[i] = factor*p[i]; } // Scale polynomial.
157 }
158 }
159
160 // Compute lower bound on moduli of roots.
161 //
162 for (i=0;i<=n;i++)
163 {
164 pt[i] = (std::fabs(p[i]));
165 }
166 pt[n] = - pt[n];
167
168 // Compute upper estimate of bound.
169 //
170 x = std::exp((std::log(-pt[n])-std::log(pt[0])) / (G4double)n);
171
172 // If Newton step at the origin is better, use it.
173 //
174 if (pt[n-1] != 0.0)
175 {
176 xm = -pt[n]/pt[n-1];
177 if (xm < x) { x = xm; }
178 }
179
180 // Chop the interval (0,x) until ff <= 0
181 //
182 while (1)
183 {
184 xm = x*0.1;
185 ff = pt[0];
186 for (i=1;i<=n;i++)
187 { ff = ff*xm + pt[i]; }
188 if (ff <= 0.0) { break; }
189 x = xm;
190 }
191 dx = x;
192
193 // Do Newton interation until x converges to two decimal places.
194 //
195 while (std::fabs(dx/x) > 0.005)
196 {
197 ff = pt[0];
198 df = ff;
199 for (i=1;i<n;i++)
200 {
201 ff = ff*x + pt[i];
202 df = df*x + ff;
203 }
204 ff = ff*x + pt[n];
205 dx = ff/df;
206 x -= dx;
207 }
208 bnd = x;
209
210 // Compute the derivative as the initial k polynomial
211 // and do 5 steps with no shift.
212 //
213 nm1 = n - 1;
214 for (i=1;i<n;i++)
215 { k[i] = (G4double)(n-i)*p[i]/(G4double)n; }
216 k[0] = p[0];
217 aa = p[n];
218 bb = p[n-1];
219 zerok = (k[n-1] == 0);
220 for(jj=0;jj<5;jj++)
221 {
222 cc = k[n-1];
223 if (!zerok) // Use a scaled form of recurrence if k at 0 is nonzero.
224 {
225 // Use a scaled form of recurrence if value of k at 0 is nonzero.
226 //
227 t = -aa/cc;
228 for (i=0;i<nm1;i++)
229 {
230 j = n-i-1;
231 k[j] = t*k[j-1]+p[j];
232 }
233 k[0] = p[0];
234 zerok = (std::fabs(k[n-1]) <= std::fabs(bb)*eta*10.0);
235 }
236 else // Use unscaled form of recurrence.
237 {
238 for (i=0;i<nm1;i++)
239 {
240 j = n-i-1;
241 k[j] = k[j-1];
242 }
243 k[0] = 0.0;
244 zerok = (!(k[n-1] != 0.0));
245 }
246 }
247
248 // Save k for restarts with new shifts.
249 //
250 for (i=0;i<n;i++)
251 { temp[i] = k[i]; }
252
253 // Loop to select the quadratic corresponding to each new shift.
254 //
255 for (cnt = 0;cnt < 20;cnt++)
256 {
257 // Quadratic corresponds to a double shift to a
258 // non-real point and its complex conjugate. The point
259 // has modulus bnd and amplitude rotated by 94 degrees
260 // from the previous shift.
261 //
262 xxx = cosr*xx - sinr*yy;
263 yy = sinr*xx + cosr*yy;
264 xx = xxx;
265 sr = bnd*xx;
266 si = bnd*yy;
267 u = -2.0 * sr;
268 v = bnd;
269 ComputeFixedShiftPolynomial(20*(cnt+1),&nz);
270 if (nz != 0)
271 {
272 // The second stage jumps directly to one of the third
273 // stage iterations and returns here if successful.
274 // Deflate the polynomial, store the zero or zeros and
275 // return to the main algorithm.
276 //
277 j = degr - n;
278 zeror[j] = szr;
279 zeroi[j] = szi;
280 n -= nz;
281 for (i=0;i<=n;i++)
282 { p[i] = qp[i]; }
283 if (nz != 1)
284 {
285 zeror[j+1] = lzr;
286 zeroi[j+1] = lzi;
287 }
288 break;
289 }
290 else
291 {
292 // If the iteration is unsuccessful another quadratic
293 // is chosen after restoring k.
294 //
295 for (i=0;i<n;i++)
296 {
297 k[i] = temp[i];
298 }
299 }
300 }
301 }
302 while (nz != 0); // End of initial DO loop
303
304 // Return with failure if no convergence with 20 shifts.
305 //
306 return degr - n;
307}
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66

Referenced by G4TwistBoxSide::DistanceToSurface(), G4TwistTrapAlphaSide::DistanceToSurface(), and G4TwistTrapParallelSide::DistanceToSurface().


The documentation for this class was generated from the following files: