Geant4-11
Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes
G4JTPolynomialSolver Class Reference

#include <G4JTPolynomialSolver.hh>

Public Member Functions

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

Private Member Functions

void ComputeFixedShiftPolynomial (G4int l2, G4int *nz)
 
void ComputeNewEstimate (G4int type, G4double *uu, G4double *vv)
 
void ComputeNextPolynomial (G4int *type)
 
void ComputeScalarFactors (G4int *type)
 
void Quadratic (G4double a, G4double b1, G4double c, G4double *sr, G4double *si, G4double *lr, G4double *li)
 
void QuadraticPolynomialIteration (G4double *uu, G4double *vv, G4int *nz)
 
void QuadraticSyntheticDivision (G4int n, G4double *u, G4double *v, std::vector< G4double > &p, std::vector< G4double > &q, G4double *a, G4double *b)
 
void RealPolynomialIteration (G4double *sss, G4int *nz, G4int *iflag)
 

Private Attributes

G4double a = 0.0
 
G4double a1 = 0.0
 
G4double a3 = 0.0
 
G4double a7 = 0.0
 
G4double b = 0.0
 
G4double c = 0.0
 
G4double d = 0.0
 
G4double e = 0.0
 
G4double f = 0.0
 
G4double g = 0.0
 
G4double h = 0.0
 
std::vector< G4doublek
 
G4double lzi = 0.0
 
G4double lzr = 0.0
 
G4int n = 0
 
std::vector< G4doublep
 
std::vector< G4doubleqk
 
std::vector< G4doubleqp
 
G4double si = 0.0
 
G4double sr = 0.0
 
std::vector< G4doublesvk
 
G4double szi = 0.0
 
G4double szr = 0.0
 
G4double u = 0.0
 
G4double v = 0.0
 

Static Private Attributes

static const G4double are = DBL_EPSILON
 
static const G4double base = 2
 
static const G4double eta = DBL_EPSILON
 
static const G4double infin = DBL_MAX
 
static const G4double lo = DBL_MIN / DBL_EPSILON
 
static const G4double mre = DBL_EPSILON
 
static const G4double smalno = DBL_MIN
 

Detailed Description

Definition at line 66 of file G4JTPolynomialSolver.hh.

Constructor & Destructor Documentation

◆ G4JTPolynomialSolver()

G4JTPolynomialSolver::G4JTPolynomialSolver ( )

Definition at line 44 of file G4JTPolynomialSolver.cc.

44{}

◆ ~G4JTPolynomialSolver()

G4JTPolynomialSolver::~G4JTPolynomialSolver ( )

Definition at line 46 of file G4JTPolynomialSolver.cc.

46{}

Member Function Documentation

◆ ComputeFixedShiftPolynomial()

void G4JTPolynomialSolver::ComputeFixedShiftPolynomial ( G4int  l2,
G4int nz 
)
private

Definition at line 326 of file G4JTPolynomialSolver.cc.

327{
328 // Computes up to L2 fixed shift k-polynomials, testing for convergence
329 // in the linear or quadratic case. Initiates one of the variable shift
330 // iterations and returns with the number of zeros found.
331
332 G4double svu = 0.0, svv = 0.0, ui = 0.0, vi = 0.0, xs = 0.0;
333 G4double betas = 0.25, betav = 0.25, oss = sr, ovv = v, ss = 0.0, vv = 0.0,
334 ts = 1.0, tv = 1.0;
335 G4double ots = 0.0, otv = 0.0;
336 G4double tvv = 1.0, tss = 1.0;
337 G4int type = 0, i = 0, j = 0, iflag = 0, vpass = 0, spass = 0, vtry = 0,
338 stry = 0;
339
340 *nz = 0;
341
342 // Evaluate polynomial by synthetic division.
343 //
344 QuadraticSyntheticDivision(n, &u, &v, p, qp, &a, &b);
346 for(j = 0; j < l2; ++j)
347 {
348 // Calculate next k polynomial and estimate v.
349 //
352 ComputeNewEstimate(type, &ui, &vi);
353 vv = vi;
354
355 // Estimate xs.
356 //
357 ss = 0.0;
358 if(k[n - 1] != 0.0)
359 {
360 ss = -p[n] / k[n - 1];
361 }
362 tv = 1.0;
363 ts = 1.0;
364 if(j == 0 || type == 3)
365 {
366 ovv = vv;
367 oss = ss;
368 otv = tv;
369 ots = ts;
370 continue;
371 }
372
373 // Compute relative measures of convergence of xs and v sequences.
374 //
375 if(vv != 0.0)
376 {
377 tv = std::fabs((vv - ovv) / vv);
378 }
379 if(ss != 0.0)
380 {
381 ts = std::fabs((ss - oss) / ss);
382 }
383
384 // If decreasing, multiply two most recent convergence measures.
385 tvv = 1.0;
386 if(tv < otv)
387 {
388 tvv = tv * otv;
389 }
390 tss = 1.0;
391 if(ts < ots)
392 {
393 tss = ts * ots;
394 }
395
396 // Compare with convergence criteria.
397 vpass = (tvv < betav);
398 spass = (tss < betas);
399 if(!(spass || vpass))
400 {
401 ovv = vv;
402 oss = ss;
403 otv = tv;
404 ots = ts;
405 continue;
406 }
407
408 // At least one sequence has passed the convergence test.
409 // Store variables before iterating.
410 //
411 svu = u;
412 svv = v;
413 for(i = 0; i < n; ++i)
414 {
415 svk[i] = k[i];
416 }
417 xs = ss;
418
419 // Choose iteration according to the fastest converging sequence.
420 //
421 vtry = 0;
422 stry = 0;
423 if((spass && (!vpass)) || (tss < tvv))
424 {
425 RealPolynomialIteration(&xs, nz, &iflag);
426 if(*nz > 0)
427 {
428 return;
429 }
430
431 // Linear iteration has failed. Flag that it has been
432 // tried and decrease the convergence criterion.
433 //
434 stry = 1;
435 betas *= 0.25;
436 if(iflag == 0)
437 {
438 goto _restore_variables;
439 }
440
441 // If linear iteration signals an almost double real
442 // zero attempt quadratic iteration.
443 //
444 ui = -(xs + xs);
445 vi = xs * xs;
446 }
447
448 _quadratic_iteration:
449
450 do
451 {
452 QuadraticPolynomialIteration(&ui, &vi, nz);
453 if(*nz > 0)
454 {
455 return;
456 }
457
458 // Quadratic iteration has failed. Flag that it has
459 // been tried and decrease the convergence criterion.
460 //
461 vtry = 1;
462 betav *= 0.25;
463
464 // Try linear iteration if it has not been tried and
465 // the S sequence is converging.
466 //
467 if(stry || !spass)
468 {
469 break;
470 }
471 for(i = 0; i < n; ++i)
472 {
473 k[i] = svk[i];
474 }
475 RealPolynomialIteration(&xs, nz, &iflag);
476 if(*nz > 0)
477 {
478 return;
479 }
480
481 // Linear iteration has failed. Flag that it has been
482 // tried and decrease the convergence criterion.
483 //
484 stry = 1;
485 betas *= 0.25;
486 if(iflag == 0)
487 {
488 break;
489 }
490
491 // If linear iteration signals an almost double real
492 // zero attempt quadratic iteration.
493 //
494 ui = -(xs + xs);
495 vi = xs * xs;
496 } while(iflag != 0);
497
498 // Restore variables.
499
500 _restore_variables:
501
502 u = svu;
503 v = svv;
504 for(i = 0; i < n; ++i)
505 {
506 k[i] = svk[i];
507 }
508
509 // Try quadratic iteration if it has not been tried
510 // and the V sequence is converging.
511 //
512 if(vpass && !vtry)
513 {
514 goto _quadratic_iteration;
515 }
516
517 // Recompute QP and scalar values to continue the
518 // second stage.
519 //
520 QuadraticSyntheticDivision(n, &u, &v, p, qp, &a, &b);
522
523 ovv = vv;
524 oss = ss;
525 otv = tv;
526 ots = ts;
527 }
528}
double G4double
Definition: G4Types.hh:83
int G4int
Definition: G4Types.hh:85
std::vector< G4double > p
std::vector< G4double > qp
void ComputeScalarFactors(G4int *type)
std::vector< G4double > svk
std::vector< G4double > k
void ComputeNewEstimate(G4int type, G4double *uu, G4double *vv)
void QuadraticPolynomialIteration(G4double *uu, G4double *vv, G4int *nz)
void ComputeNextPolynomial(G4int *type)
void QuadraticSyntheticDivision(G4int n, G4double *u, G4double *v, std::vector< G4double > &p, std::vector< G4double > &q, G4double *a, G4double *b)
void RealPolynomialIteration(G4double *sss, G4int *nz, G4int *iflag)

References a, b, ComputeNewEstimate(), ComputeNextPolynomial(), ComputeScalarFactors(), k, n, p, qp, QuadraticPolynomialIteration(), QuadraticSyntheticDivision(), RealPolynomialIteration(), sr, svk, geant4_check_module_cycles::ts, u, and v.

Referenced by FindRoots().

◆ ComputeNewEstimate()

void G4JTPolynomialSolver::ComputeNewEstimate ( G4int  type,
G4double uu,
G4double vv 
)
private

Definition at line 849 of file G4JTPolynomialSolver.cc.

851{
852 // Compute new estimates of the quadratic coefficients
853 // using the scalars computed in calcsc.
854
855 G4double a4 = 0.0, a5 = 0.0, b1 = 0.0, b2 = 0.0, c1 = 0.0, c2 = 0.0, c3 = 0.0,
856 c4 = 0.0, temp = 0.0;
857
858 // Use formulas appropriate to setting of type.
859 //
860 if(type == 3) // If type=3 the quadratic is zeroed.
861 {
862 *uu = 0.0;
863 *vv = 0.0;
864 return;
865 }
866 if(type == 2)
867 {
868 a4 = (a + g) * f + h;
869 a5 = (f + u) * c + v * d;
870 }
871 else
872 {
873 a4 = a + u * b + h * f;
874 a5 = c + (u + v * f) * d;
875 }
876
877 // Evaluate new quadratic coefficients.
878 //
879 b1 = -k[n - 1] / p[n];
880 b2 = -(k[n - 2] + b1 * p[n - 1]) / p[n];
881 c1 = v * b2 * a1;
882 c2 = b1 * a7;
883 c3 = b1 * b1 * a3;
884 c4 = c1 - c2 - c3;
885 temp = a5 + b1 * a4 - c4;
886 if(!(temp != 0.0))
887 {
888 *uu = 0.0;
889 *vv = 0.0;
890 return;
891 }
892 *uu = u - (u * (c3 + c2) + v * (b1 * a1 + b2 * a7)) / temp;
893 *vv = v * (1.0 + c4 / temp);
894 return;
895}

References a, a1, a3, a7, b, c, d, f, g, h, k, n, p, u, and v.

Referenced by ComputeFixedShiftPolynomial(), and QuadraticPolynomialIteration().

◆ ComputeNextPolynomial()

void G4JTPolynomialSolver::ComputeNextPolynomial ( G4int type)
private

Definition at line 802 of file G4JTPolynomialSolver.cc.

803{
804 // Computes the next k polynomials using scalars
805 // computed in ComputeScalarFactors.
806
807 G4int i = 2;
808
809 if(*type == 3) // Use unscaled form of the recurrence if type is 3.
810 {
811 k[0] = 0.0;
812 k[1] = 0.0;
813 for(i = 2; i < n; ++i)
814 {
815 k[i] = qk[i - 2];
816 }
817 return;
818 }
819 G4double temp = a;
820 if(*type == 1)
821 {
822 temp = b;
823 }
824 if(std::fabs(a1) <= std::fabs(temp) * eta * 10.0)
825 {
826 // If a1 is nearly zero then use a special form of the recurrence.
827 //
828 k[0] = 0.0;
829 k[1] = -a7 * qp[0];
830 for(i = 2; i < n; ++i)
831 {
832 k[i] = a3 * qk[i - 2] - a7 * qp[i - 1];
833 }
834 return;
835 }
836
837 // Use scaled form of the recurrence.
838 //
839 a7 /= a1;
840 a3 /= a1;
841 k[0] = qp[0];
842 k[1] = qp[1] - a7 * qp[0];
843 for(i = 2; i < n; ++i)
844 {
845 k[i] = a3 * qk[i - 2] - a7 * qp[i - 1] + qp[i];
846 }
847}
std::vector< G4double > qk
static const G4double eta

References a, a1, a3, a7, b, eta, k, n, qk, and qp.

Referenced by ComputeFixedShiftPolynomial(), and QuadraticPolynomialIteration().

◆ ComputeScalarFactors()

void G4JTPolynomialSolver::ComputeScalarFactors ( G4int type)
private

Definition at line 760 of file G4JTPolynomialSolver.cc.

761{
762 // This function calculates scalar quantities used to
763 // compute the next k polynomial and new estimates of
764 // the quadratic coefficients.
765 // type - integer variable set here indicating how the
766 // calculations are normalized to avoid overflow.
767
768 // Synthetic division of k by the quadratic 1,u,v
769 //
770 QuadraticSyntheticDivision(n - 1, &u, &v, k, qk, &c, &d);
771 if(std::fabs(c) <= std::fabs(k[n - 1] * 100.0 * eta))
772 {
773 if(std::fabs(d) <= std::fabs(k[n - 2] * 100.0 * eta))
774 {
775 *type = 3; // Type=3 indicates the quadratic is almost a factor of k.
776 return;
777 }
778 }
779
780 if(std::fabs(d) < std::fabs(c))
781 {
782 *type = 1; // Type=1 indicates that all formulas are divided by c.
783 e = a / c;
784 f = d / c;
785 g = u * e;
786 h = v * b;
787 a3 = a * e + (h / c + g) * b;
788 a1 = b - a * (d / c);
789 a7 = a + g * d + h * f;
790 return;
791 }
792 *type = 2; // Type=2 indicates that all formulas are divided by d.
793 e = a / d;
794 f = c / d;
795 g = u * b;
796 h = v * b;
797 a3 = (a + g) * e + h * (b / d);
798 a1 = b * f - a;
799 a7 = (f + u) * a + h;
800}

References a, a1, a3, a7, b, c, d, e, eta, f, g, h, k, n, qk, QuadraticSyntheticDivision(), u, and v.

Referenced by ComputeFixedShiftPolynomial(), and QuadraticPolynomialIteration().

◆ FindRoots()

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

Definition at line 48 of file G4JTPolynomialSolver.cc.

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

References base, ComputeFixedShiftPolynomial(), deg, eta, G4Exp(), G4Log(), G4Pow::GetInstance(), infin, k, lo, lzi, lzr, G4INCL::Math::max(), G4INCL::Math::min(), n, p, G4Pow::powN(), qk, qp, Quadratic(), si, smalno, sr, svk, szi, szr, u, and v.

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

◆ Quadratic()

void G4JTPolynomialSolver::Quadratic ( G4double  a,
G4double  b1,
G4double  c,
G4double sr,
G4double si,
G4double lr,
G4double li 
)
private

Definition at line 918 of file G4JTPolynomialSolver.cc.

921{
922 // Calculate the zeros of the quadratic aa*z^2 + b1*z + cc.
923 // The quadratic formula, modified to avoid overflow, is used
924 // to find the larger zero if the zeros are real and both
925 // are complex. The smaller real zero is found directly from
926 // the product of the zeros c/a.
927
928 G4double bb = 0.0, dd = 0.0, ee = 0.0;
929
930 if(!(aa != 0.0)) // less than two roots
931 {
932 if(b1 != 0.0)
933 {
934 *ssr = -cc / b1;
935 }
936 else
937 {
938 *ssr = 0.0;
939 }
940 *lr = 0.0;
941 *ssi = 0.0;
942 *li = 0.0;
943 return;
944 }
945 if(!(cc != 0.0)) // one real root, one zero root
946 {
947 *ssr = 0.0;
948 *lr = -b1 / aa;
949 *ssi = 0.0;
950 *li = 0.0;
951 return;
952 }
953
954 // Compute discriminant avoiding overflow.
955 //
956 bb = b1 / 2.0;
957 if(std::fabs(bb) < std::fabs(cc))
958 {
959 if(cc < 0.0)
960 {
961 ee = -aa;
962 }
963 else
964 {
965 ee = aa;
966 }
967 ee = bb * (bb / std::fabs(cc)) - ee;
968 dd = std::sqrt(std::fabs(ee)) * std::sqrt(std::fabs(cc));
969 }
970 else
971 {
972 ee = 1.0 - (aa / bb) * (cc / bb);
973 dd = std::sqrt(std::fabs(ee)) * std::fabs(bb);
974 }
975 if(ee < 0.0) // complex conjugate zeros
976 {
977 *ssr = -bb / aa;
978 *lr = *ssr;
979 *ssi = std::fabs(dd / aa);
980 *li = -(*ssi);
981 }
982 else
983 {
984 if(bb >= 0.0) // real zeros.
985 {
986 dd = -dd;
987 }
988 *lr = (-bb + dd) / aa;
989 *ssr = 0.0;
990 if(*lr != 0.0)
991 {
992 *ssr = (cc / *lr) / aa;
993 }
994 *ssi = 0.0;
995 *li = 0.0;
996 }
997}

Referenced by FindRoots(), and QuadraticPolynomialIteration().

◆ QuadraticPolynomialIteration()

void G4JTPolynomialSolver::QuadraticPolynomialIteration ( G4double uu,
G4double vv,
G4int nz 
)
private

Definition at line 530 of file G4JTPolynomialSolver.cc.

532{
533 // Variable-shift k-polynomial iteration for a
534 // quadratic factor converges only if the zeros are
535 // equimodular or nearly so.
536 // uu, vv - coefficients of starting quadratic.
537 // nz - number of zeros found.
538 //
539 G4double ui = 0.0, vi = 0.0;
540 G4double omp = 0.0;
541 G4double relstp = 0.0;
542 G4double mp = 0.0, ee = 0.0, t = 0.0, zm = 0.0;
543 G4int type = 0, i = 1, j = 0, tried = 0;
544
545 *nz = 0;
546 tried = 0;
547 u = *uu;
548 v = *vv;
549
550 // Main loop.
551
552 while(1)
553 {
554 Quadratic(1.0, u, v, &szr, &szi, &lzr, &lzi);
555
556 // Return if roots of the quadratic are real and not
557 // close to multiple or nearly equal and of opposite
558 // sign.
559 //
560 if(std::fabs(std::fabs(szr) - std::fabs(lzr)) > 0.01 * std::fabs(lzr))
561 {
562 return;
563 }
564
565 // Evaluate polynomial by quadratic synthetic division.
566 //
567 QuadraticSyntheticDivision(n, &u, &v, p, qp, &a, &b);
568 mp = std::fabs(a - szr * b) + std::fabs(szi * b);
569
570 // Compute a rigorous bound on the rounding error in evaluating p.
571 //
572 zm = std::sqrt(std::fabs(v));
573 ee = 2.0 * std::fabs(qp[0]);
574 t = -szr * b;
575 for(i = 1; i < n; ++i)
576 {
577 ee = ee * zm + std::fabs(qp[i]);
578 }
579 ee = ee * zm + std::fabs(a + t);
580 ee *= (5.0 * mre + 4.0 * are);
581 ee = ee - (5.0 * mre + 2.0 * are) * (std::fabs(a + t) + std::fabs(b) * zm) +
582 2.0 * are * std::fabs(t);
583
584 // Iteration has converged sufficiently if the
585 // polynomial value is less than 20 times this bound.
586 //
587 if(mp <= 20.0 * ee)
588 {
589 *nz = 2;
590 return;
591 }
592 j++;
593
594 // Stop iteration after 20 steps.
595 //
596 if(j > 20)
597 {
598 return;
599 }
600 if(j >= 2)
601 {
602 if(!(relstp > 0.01 || mp < omp || tried))
603 {
604 // A cluster appears to be stalling the convergence.
605 // Five fixed shift steps are taken with a u,v close to the cluster.
606 //
607 if(relstp < eta)
608 {
609 relstp = eta;
610 }
611 relstp = std::sqrt(relstp);
612 u = u - u * relstp;
613 v = v + v * relstp;
614 QuadraticSyntheticDivision(n, &u, &v, p, qp, &a, &b);
615 for(i = 0; i < 5; ++i)
616 {
619 }
620 tried = 1;
621 j = 0;
622 }
623 }
624 omp = mp;
625
626 // Calculate next k polynomial and new u and v.
627 //
631 ComputeNewEstimate(type, &ui, &vi);
632
633 // If vi is zero the iteration is not converging.
634 //
635 if(!(vi != 0.0))
636 {
637 return;
638 }
639 relstp = std::fabs((vi - v) / vi);
640 u = ui;
641 v = vi;
642 }
643}
static const G4double are
static const G4double mre

References a, are, b, ComputeNewEstimate(), ComputeNextPolynomial(), ComputeScalarFactors(), eta, lzi, lzr, mre, n, p, qp, Quadratic(), QuadraticSyntheticDivision(), szi, szr, u, and v.

Referenced by ComputeFixedShiftPolynomial().

◆ QuadraticSyntheticDivision()

void G4JTPolynomialSolver::QuadraticSyntheticDivision ( G4int  n,
G4double u,
G4double v,
std::vector< G4double > &  p,
std::vector< G4double > &  q,
G4double a,
G4double b 
)
private

Definition at line 897 of file G4JTPolynomialSolver.cc.

900{
901 // Divides pp by the quadratic 1,uu,vv placing the quotient
902 // in qq and the remainder in aa,bb.
903
904 G4double cc = 0.0;
905 *bb = pp[0];
906 qq[0] = *bb;
907 *aa = pp[1] - (*bb) * (*uu);
908 qq[1] = *aa;
909 for(G4int i = 2; i <= nn; ++i)
910 {
911 cc = pp[i] - (*aa) * (*uu) - (*bb) * (*vv);
912 qq[i] = cc;
913 *bb = *aa;
914 *aa = cc;
915 }
916}

References G4InuclParticleNames::nn, and G4InuclParticleNames::pp.

Referenced by ComputeFixedShiftPolynomial(), ComputeScalarFactors(), and QuadraticPolynomialIteration().

◆ RealPolynomialIteration()

void G4JTPolynomialSolver::RealPolynomialIteration ( G4double sss,
G4int nz,
G4int iflag 
)
private

Definition at line 645 of file G4JTPolynomialSolver.cc.

647{
648 // Variable-shift H polynomial iteration for a real zero.
649 // sss - starting iterate
650 // nz - number of zeros found
651 // iflag - flag to indicate a pair of zeros near real axis.
652
653 G4double t = 0.;
654 G4double omp = 0.;
655 G4double pv = 0.0, kv = 0.0, xs = *sss;
656 G4double mx = 0.0, mp = 0.0, ee = 0.0;
657 G4int i = 1, j = 0;
658
659 *nz = 0;
660 *iflag = 0;
661
662 // Main loop
663 //
664 while(1)
665 {
666 pv = p[0];
667
668 // Evaluate p at xs.
669 //
670 qp[0] = pv;
671 for(i = 1; i <= n; ++i)
672 {
673 pv = pv * xs + p[i];
674 qp[i] = pv;
675 }
676 mp = std::fabs(pv);
677
678 // Compute a rigorous bound on the error in evaluating p.
679 //
680 mx = std::fabs(xs);
681 ee = (mre / (are + mre)) * std::fabs(qp[0]);
682 for(i = 1; i <= n; ++i)
683 {
684 ee = ee * mx + std::fabs(qp[i]);
685 }
686
687 // Iteration has converged sufficiently if the polynomial
688 // value is less than 20 times this bound.
689 //
690 if(mp <= 20.0 * ((are + mre) * ee - mre * mp))
691 {
692 *nz = 1;
693 szr = xs;
694 szi = 0.0;
695 return;
696 }
697 j++;
698
699 // Stop iteration after 10 steps.
700 //
701 if(j > 10)
702 {
703 return;
704 }
705 if(j >= 2)
706 {
707 if(!(std::fabs(t) > 0.001 * std::fabs(xs - t) || mp < omp))
708 {
709 // A cluster of zeros near the real axis has been encountered.
710 // Return with iflag set to initiate a quadratic iteration.
711 //
712 *iflag = 1;
713 *sss = xs;
714 return;
715 } // Return if the polynomial value has increased significantly.
716 }
717
718 omp = mp;
719
720 // Compute t, the next polynomial, and the new iterate.
721 //
722 kv = k[0];
723 qk[0] = kv;
724 for(i = 1; i < n; ++i)
725 {
726 kv = kv * xs + k[i];
727 qk[i] = kv;
728 }
729 if(std::fabs(kv) <= std::fabs(k[n - 1]) * 10.0 * eta) // Use unscaled form.
730 {
731 k[0] = 0.0;
732 for(i = 1; i < n; ++i)
733 {
734 k[i] = qk[i - 1];
735 }
736 }
737 else // Use the scaled form of the recurrence if k at xs is nonzero.
738 {
739 t = -pv / kv;
740 k[0] = qp[0];
741 for(i = 1; i < n; ++i)
742 {
743 k[i] = t * qk[i - 1] + qp[i];
744 }
745 }
746 kv = k[0];
747 for(i = 1; i < n; ++i)
748 {
749 kv = kv * xs + k[i];
750 }
751 t = 0.0;
752 if(std::fabs(kv) > std::fabs(k[n - 1] * 10.0 * eta))
753 {
754 t = -pv / kv;
755 }
756 xs += t;
757 }
758}
static const char sss[MAX_N_PAR+2]
Definition: Evaluator.cc:63

References are, eta, k, mre, n, p, qk, qp, sss, szi, and szr.

Referenced by ComputeFixedShiftPolynomial().

Field Documentation

◆ a

G4double G4JTPolynomialSolver::a = 0.0
private

◆ a1

G4double G4JTPolynomialSolver::a1 = 0.0
private

◆ a3

G4double G4JTPolynomialSolver::a3 = 0.0
private

◆ a7

G4double G4JTPolynomialSolver::a7 = 0.0
private

◆ are

const G4double G4JTPolynomialSolver::are = DBL_EPSILON
staticprivate

◆ b

G4double G4JTPolynomialSolver::b = 0.0
private

◆ base

const G4double G4JTPolynomialSolver::base = 2
staticprivate

Definition at line 107 of file G4JTPolynomialSolver.hh.

Referenced by FindRoots().

◆ c

G4double G4JTPolynomialSolver::c = 0.0
private

Definition at line 98 of file G4JTPolynomialSolver.hh.

Referenced by ComputeNewEstimate(), and ComputeScalarFactors().

◆ d

G4double G4JTPolynomialSolver::d = 0.0
private

Definition at line 98 of file G4JTPolynomialSolver.hh.

Referenced by ComputeNewEstimate(), and ComputeScalarFactors().

◆ e

G4double G4JTPolynomialSolver::e = 0.0
private

Definition at line 100 of file G4JTPolynomialSolver.hh.

Referenced by ComputeScalarFactors().

◆ eta

const G4double G4JTPolynomialSolver::eta = DBL_EPSILON
staticprivate

◆ f

G4double G4JTPolynomialSolver::f = 0.0
private

Definition at line 100 of file G4JTPolynomialSolver.hh.

Referenced by ComputeNewEstimate(), and ComputeScalarFactors().

◆ g

G4double G4JTPolynomialSolver::g = 0.0
private

Definition at line 100 of file G4JTPolynomialSolver.hh.

Referenced by ComputeNewEstimate(), and ComputeScalarFactors().

◆ h

G4double G4JTPolynomialSolver::h = 0.0
private

Definition at line 100 of file G4JTPolynomialSolver.hh.

Referenced by ComputeNewEstimate(), and ComputeScalarFactors().

◆ infin

const G4double G4JTPolynomialSolver::infin = DBL_MAX
staticprivate

Definition at line 109 of file G4JTPolynomialSolver.hh.

Referenced by FindRoots().

◆ k

std::vector<G4double> G4JTPolynomialSolver::k
private

◆ lo

const G4double G4JTPolynomialSolver::lo = DBL_MIN / DBL_EPSILON
staticprivate

Definition at line 113 of file G4JTPolynomialSolver.hh.

Referenced by FindRoots().

◆ lzi

G4double G4JTPolynomialSolver::lzi = 0.0
private

Definition at line 102 of file G4JTPolynomialSolver.hh.

Referenced by FindRoots(), and QuadraticPolynomialIteration().

◆ lzr

G4double G4JTPolynomialSolver::lzr = 0.0
private

Definition at line 102 of file G4JTPolynomialSolver.hh.

Referenced by FindRoots(), and QuadraticPolynomialIteration().

◆ mre

const G4double G4JTPolynomialSolver::mre = DBL_EPSILON
staticprivate

◆ n

G4int G4JTPolynomialSolver::n = 0
private

◆ p

std::vector<G4double> G4JTPolynomialSolver::p
private

◆ qk

std::vector<G4double> G4JTPolynomialSolver::qk
private

◆ qp

std::vector<G4double> G4JTPolynomialSolver::qp
private

◆ si

G4double G4JTPolynomialSolver::si = 0.0
private

Definition at line 96 of file G4JTPolynomialSolver.hh.

Referenced by FindRoots().

◆ smalno

const G4double G4JTPolynomialSolver::smalno = DBL_MIN
staticprivate

Definition at line 110 of file G4JTPolynomialSolver.hh.

Referenced by FindRoots().

◆ sr

G4double G4JTPolynomialSolver::sr = 0.0
private

Definition at line 95 of file G4JTPolynomialSolver.hh.

Referenced by ComputeFixedShiftPolynomial(), and FindRoots().

◆ svk

std::vector<G4double> G4JTPolynomialSolver::svk
private

Definition at line 93 of file G4JTPolynomialSolver.hh.

Referenced by ComputeFixedShiftPolynomial(), and FindRoots().

◆ szi

G4double G4JTPolynomialSolver::szi = 0.0
private

◆ szr

G4double G4JTPolynomialSolver::szr = 0.0
private

◆ u

G4double G4JTPolynomialSolver::u = 0.0
private

◆ v

G4double G4JTPolynomialSolver::v = 0.0
private

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