source: trunk/source/global/HEPNumerics/src/G4AnalyticalPolSolver.cc@ 1340

Last change on this file since 1340 was 1337, checked in by garnier, 15 years ago

tag geant4.9.4 beta 1 + modifs locales

File size: 10.3 KB
RevLine 
[833]1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27// $Id: G4AnalyticalPolSolver.cc,v 1.7 2007/11/13 17:35:06 gcosmo Exp $
[1337]28// GEANT4 tag $Name: geant4-09-04-beta-01 $
[833]29//
30
31#include "globals.hh"
32#include <complex>
33
34#include "G4AnalyticalPolSolver.hh"
35
36//////////////////////////////////////////////////////////////////////////////
37
38G4AnalyticalPolSolver::G4AnalyticalPolSolver() {;}
39
40//////////////////////////////////////////////////////////////////////////////
41
42G4AnalyticalPolSolver::~G4AnalyticalPolSolver() {;}
43
44//////////////////////////////////////////////////////////////////////////////
45//
46// Array r[3][5] p[5]
47// Roots of poly p[0] x^2 + p[1] x+p[2]=0
48//
49// x = r[1][k] + i r[2][k]; k = 1, 2
50
51G4int G4AnalyticalPolSolver::QuadRoots( G4double p[5], G4double r[3][5] )
52{
53 G4double b, c, d2, d;
54
55 b = -p[1]/p[0]/2.;
56 c = p[2]/p[0];
57 d2 = b*b - c;
58
59 if( d2 >= 0. )
60 {
61 d = std::sqrt(d2);
62 r[1][1] = b - d;
63 r[1][2] = b + d;
64 r[2][1] = 0.;
65 r[2][2] = 0.;
66 }
67 else
68 {
69 d = std::sqrt(-d2);
70 r[2][1] = d;
71 r[2][2] = -d;
72 r[1][1] = b;
73 r[1][2] = b;
74 }
75
76 return 2;
77}
78
79//////////////////////////////////////////////////////////////////////////////
80//
81// Array r[3][5] p[5]
82// Roots of poly p[0] x^3 + p[1] x^2...+p[3]=0
83// x=r[1][k] + i r[2][k] k=1,...,3
84// Assumes 0<arctan(x)<pi/2 for x>0
85
86G4int G4AnalyticalPolSolver::CubicRoots( G4double p[5], G4double r[3][5] )
87{
88 G4double x,t,b,c,d;
89 G4int k;
90
91 if( p[0] != 1. )
92 {
93 for(k = 1; k < 4; k++ ) { p[k] = p[k]/p[0]; }
94 p[0] = 1.;
95 }
96 x = p[1]/3.0;
97 t = x*p[1];
98 b = 0.5*( x*( t/1.5 - p[2] ) + p[3] );
99 t = ( t - p[2] )/3.0;
100 c = t*t*t;
101 d = b*b - c;
102
103 if( d >= 0. )
104 {
105 d = std::pow( (std::sqrt(d) + std::fabs(b) ), 1.0/3.0 );
106
107 if( d != 0. )
108 {
109 if( b > 0. ) { b = -d; }
110 else { b = d; }
111 c = t/b;
112 }
113 d = std::sqrt(0.75)*(b - c);
114 r[2][2] = d;
115 b = b + c;
116 c = -0.5*b-x;
117 r[1][2] = c;
118
119 if( ( b > 0. && x <= 0. ) || ( b < 0. && x > 0. ) )
120 {
121 r[1][1] = c;
122 r[2][1] = -d;
123 r[1][3] = b - x;
124 r[2][3] = 0;
125 }
126 else
127 {
128 r[1][1] = b - x;
129 r[2][1] = 0.;
130 r[1][3] = c;
131 r[2][3] = -d;
132 }
133 } // end of 2 equal or complex roots
134 else
135 {
136 if( b == 0. ) { d = std::atan(1.0)/1.5; }
137 else { d = std::atan( std::sqrt(-d)/std::fabs(b) )/3.0; }
138
139 if( b < 0. ) { b = std::sqrt(t)*2.0; }
140 else { b = -2.0*std::sqrt(t); }
141
142 c = std::cos(d)*b;
143 t = -std::sqrt(0.75)*std::sin(d)*b - 0.5*c;
144 d = -t - c - x;
145 c = c - x;
146 t = t - x;
147
148 if( std::fabs(c) > std::fabs(t) ) { r[1][3] = c; }
149 else
150 {
151 r[1][3] = t;
152 t = c;
153 }
154 if( std::fabs(d) > std::fabs(t) ) { r[1][2] = d; }
155 else
156 {
157 r[1][2] = t;
158 t = d;
159 }
160 r[1][1] = t;
161
162 for(k = 1; k < 4; k++ ) { r[2][k] = 0.; }
163 }
164 return 0;
165}
166
167//////////////////////////////////////////////////////////////////////////////
168//
169// Array r[3][5] p[5]
170// Roots of poly p[0] x^4 + p[1] x^3...+p[4]=0
171// x=r[1][k] + i r[2][k] k=1,...,4
172
173G4int G4AnalyticalPolSolver::BiquadRoots( G4double p[5], G4double r[3][5] )
174{
175 G4double a, b, c, d, e;
176 G4int i, k, j, noRoots;
177
178 if(p[0] != 1.0)
179 {
180 for( k = 1; k < 5; k++) { p[k] = p[k]/p[0]; }
181 p[0] = 1.;
182 }
183 e = 0.25*p[1];
184 b = 2*e;
185 c = b*b;
186 d = 0.75*c;
187 b = p[3] + b*( c - p[2] );
188 a = p[2] - d;
189 c = p[4] + e*( e*a - p[3] );
190 a = a - d;
191
192 p[1] = 0.5*a;
193 p[2] = (p[1]*p[1]-c)*0.25;
194 p[3] = b*b/(-64.0);
195
196 if( p[3] < 0. )
197 {
198 noRoots = CubicRoots(p,r);
199
200 for( k = 1; k < 4; k++ )
201 {
202 if( r[2][k] == 0. && r[1][k] > 0 )
203 {
204 d = r[1][k]*4;
205 a = a + d;
206
207 if ( a >= 0. && b >= 0.) { p[1] = std::sqrt(d); }
208 else if( a <= 0. && b <= 0.) { p[1] = std::sqrt(d); }
209 else { p[1] = -std::sqrt(d); }
210
211 b = 0.5*( a + b/p[1] );
212
213 p[2] = c/b;
214 noRoots = QuadRoots(p,r);
215
216 for( i = 1; i < 3; i++ )
217 {
218 for( j = 1; j < 3; j++ ) { r[j][i+2] = r[j][i]; }
219 }
220 p[1] = -p[1];
221 p[2] = b;
222 noRoots = QuadRoots(p,r);
223
224 for( i = 1; i < 5; i++ ) { r[1][i] = r[1][i] - e; }
225
226 return 4;
227 }
228 }
229 }
230 if( p[2] < 0. )
231 {
232 b = std::sqrt(c);
233 d = b + b - a;
234 p[1] = 0.;
235
236 if( d > 0. ) { p[1] = std::sqrt(d); }
237 }
238 else
239 {
240 if( p[1] > 0.) { b = std::sqrt(p[2])*2.0 + p[1]; }
241 else { b = -std::sqrt(p[2])*2.0 + p[1]; }
242
243 if( b != 0.) { p[1] = 0; }
244 else
245 {
246 for(k = 1; k < 5; k++ )
247 {
248 r[1][k] = -e;
249 r[2][k] = 0;
250 }
251 return 0;
252 }
253 }
254
255 p[2] = c/b;
256 noRoots = QuadRoots(p,r);
257
258 for( k = 1; k < 3; k++ )
259 {
260 for( j = 1; j < 3; j++ ) { r[j][k+2] = r[j][k]; }
261 }
262 p[1] = -p[1];
263 p[2] = b;
264 noRoots = QuadRoots(p,r);
265
266 for( k = 1; k < 5; k++ ) { r[1][k] = r[1][k] - e; }
267
268 return 4;
269}
270
271//////////////////////////////////////////////////////////////////////////////
272
273G4int G4AnalyticalPolSolver::QuarticRoots( G4double p[5], G4double r[3][5])
274{
275 G4double a0, a1, a2, a3, y1;
276 G4double R2, D2, E2, D, E, R = 0.;
277 G4double a, b, c, d, ds;
278
279 G4double reRoot[4];
280 G4int k, noRoots, noReRoots = 0;
281
282 for( k = 0; k < 4; k++ ) { reRoot[k] = DBL_MAX; }
283
284 if( p[0] != 1.0 )
285 {
286 for( k = 1; k < 5; k++) { p[k] = p[k]/p[0]; }
287 p[0] = 1.;
288 }
289 a3 = p[1];
290 a2 = p[2];
291 a1 = p[3];
292 a0 = p[4];
293
294 // resolvent cubic equation cofs:
295
296 p[1] = -a2;
297 p[2] = a1*a3 - 4*a0;
298 p[3] = 4*a2*a0 - a1*a1 - a3*a3*a0;
299
300 noRoots = CubicRoots(p,r);
301
302 for( k = 1; k < 4; k++ )
303 {
304 if( r[2][k] == 0. ) // find a real root
305 {
306 noReRoots++;
307 reRoot[k] = r[1][k];
308 }
309 else reRoot[k] = DBL_MAX; // kInfinity;
310 }
311 y1 = DBL_MAX; // kInfinity;
312 for( k = 1; k < 4; k++ )
313 {
314 if ( reRoot[k] < y1 ) { y1 = reRoot[k]; }
315 }
316
317 R2 = 0.25*a3*a3 - a2 + y1;
318 b = 0.25*(4*a3*a2 - 8*a1 - a3*a3*a3);
319 c = 0.75*a3*a3 - 2*a2;
320 a = c - R2;
321 d = 4*y1*y1 - 16*a0;
322
323 if( R2 > 0.)
324 {
325 R = std::sqrt(R2);
326 D2 = a + b/R;
327 E2 = a - b/R;
328
329 if( D2 >= 0. )
330 {
331 D = std::sqrt(D2);
332 r[1][1] = -0.25*a3 + 0.5*R + 0.5*D;
333 r[1][2] = -0.25*a3 + 0.5*R - 0.5*D;
334 r[2][1] = 0.;
335 r[2][2] = 0.;
336 }
337 else
338 {
339 D = std::sqrt(-D2);
340 r[1][1] = -0.25*a3 + 0.5*R;
341 r[1][2] = -0.25*a3 + 0.5*R;
342 r[2][1] = 0.5*D;
343 r[2][2] = -0.5*D;
344 }
345 if( E2 >= 0. )
346 {
347 E = std::sqrt(E2);
348 r[1][3] = -0.25*a3 - 0.5*R + 0.5*E;
349 r[1][4] = -0.25*a3 - 0.5*R - 0.5*E;
350 r[2][3] = 0.;
351 r[2][4] = 0.;
352 }
353 else
354 {
355 E = std::sqrt(-E2);
356 r[1][3] = -0.25*a3 - 0.5*R;
357 r[1][4] = -0.25*a3 - 0.5*R;
358 r[2][3] = 0.5*E;
359 r[2][4] = -0.5*E;
360 }
361 }
362 else if( R2 < 0.)
363 {
364 R = std::sqrt(-R2);
365 G4complex CD2(a,-b/R);
366 G4complex CD = std::sqrt(CD2);
367
368 r[1][1] = -0.25*a3 + 0.5*real(CD);
369 r[1][2] = -0.25*a3 - 0.5*real(CD);
370 r[2][1] = 0.5*R + 0.5*imag(CD);
371 r[2][2] = 0.5*R - 0.5*imag(CD);
372 G4complex CE2(a,b/R);
373 G4complex CE = std::sqrt(CE2);
374
375 r[1][3] = -0.25*a3 + 0.5*real(CE);
376 r[1][4] = -0.25*a3 - 0.5*real(CE);
377 r[2][3] = -0.5*R + 0.5*imag(CE);
378 r[2][4] = -0.5*R - 0.5*imag(CE);
379 }
380 else // R2=0 case
381 {
382 if(d >= 0.)
383 {
384 D2 = c + std::sqrt(d);
385 E2 = c - std::sqrt(d);
386
387 if( D2 >= 0. )
388 {
389 D = std::sqrt(D2);
390 r[1][1] = -0.25*a3 + 0.5*R + 0.5*D;
391 r[1][2] = -0.25*a3 + 0.5*R - 0.5*D;
392 r[2][1] = 0.;
393 r[2][2] = 0.;
394 }
395 else
396 {
397 D = std::sqrt(-D2);
398 r[1][1] = -0.25*a3 + 0.5*R;
399 r[1][2] = -0.25*a3 + 0.5*R;
400 r[2][1] = 0.5*D;
401 r[2][2] = -0.5*D;
402 }
403 if( E2 >= 0. )
404 {
405 E = std::sqrt(E2);
406 r[1][3] = -0.25*a3 - 0.5*R + 0.5*E;
407 r[1][4] = -0.25*a3 - 0.5*R - 0.5*E;
408 r[2][3] = 0.;
409 r[2][4] = 0.;
410 }
411 else
412 {
413 E = std::sqrt(-E2);
414 r[1][3] = -0.25*a3 - 0.5*R;
415 r[1][4] = -0.25*a3 - 0.5*R;
416 r[2][3] = 0.5*E;
417 r[2][4] = -0.5*E;
418 }
419 }
420 else
421 {
422 ds = std::sqrt(-d);
423 G4complex CD2(c,ds);
424 G4complex CD = std::sqrt(CD2);
425
426 r[1][1] = -0.25*a3 + 0.5*real(CD);
427 r[1][2] = -0.25*a3 - 0.5*real(CD);
428 r[2][1] = 0.5*R + 0.5*imag(CD);
429 r[2][2] = 0.5*R - 0.5*imag(CD);
430
431 G4complex CE2(c,-ds);
432 G4complex CE = std::sqrt(CE2);
433
434 r[1][3] = -0.25*a3 + 0.5*real(CE);
435 r[1][4] = -0.25*a3 - 0.5*real(CE);
436 r[2][3] = -0.5*R + 0.5*imag(CE);
437 r[2][4] = -0.5*R - 0.5*imag(CE);
438 }
439 }
440 return 4;
441}
442
443//
444//
445//////////////////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.