Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4AnalyticalPolSolver.cc
Go to the documentation of this file.
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$
28//
29
30#include "globals.hh"
31#include <complex>
32
34
35//////////////////////////////////////////////////////////////////////////////
36
38
39//////////////////////////////////////////////////////////////////////////////
40
42
43//////////////////////////////////////////////////////////////////////////////
44//
45// Array r[3][5] p[5]
46// Roots of poly p[0] x^2 + p[1] x+p[2]=0
47//
48// x = r[1][k] + i r[2][k]; k = 1, 2
49
51{
52 G4double b, c, d2, d;
53
54 b = -p[1]/p[0]/2.;
55 c = p[2]/p[0];
56 d2 = b*b - c;
57
58 if( d2 >= 0. )
59 {
60 d = std::sqrt(d2);
61 r[1][1] = b - d;
62 r[1][2] = b + d;
63 r[2][1] = 0.;
64 r[2][2] = 0.;
65 }
66 else
67 {
68 d = std::sqrt(-d2);
69 r[2][1] = d;
70 r[2][2] = -d;
71 r[1][1] = b;
72 r[1][2] = b;
73 }
74
75 return 2;
76}
77
78//////////////////////////////////////////////////////////////////////////////
79//
80// Array r[3][5] p[5]
81// Roots of poly p[0] x^3 + p[1] x^2...+p[3]=0
82// x=r[1][k] + i r[2][k] k=1,...,3
83// Assumes 0<arctan(x)<pi/2 for x>0
84
86{
87 G4double x,t,b,c,d;
88 G4int k;
89
90 if( p[0] != 1. )
91 {
92 for(k = 1; k < 4; k++ ) { p[k] = p[k]/p[0]; }
93 p[0] = 1.;
94 }
95 x = p[1]/3.0;
96 t = x*p[1];
97 b = 0.5*( x*( t/1.5 - p[2] ) + p[3] );
98 t = ( t - p[2] )/3.0;
99 c = t*t*t;
100 d = b*b - c;
101
102 if( d >= 0. )
103 {
104 d = std::pow( (std::sqrt(d) + std::fabs(b) ), 1.0/3.0 );
105
106 if( d != 0. )
107 {
108 if( b > 0. ) { b = -d; }
109 else { b = d; }
110 c = t/b;
111 }
112 d = std::sqrt(0.75)*(b - c);
113 r[2][2] = d;
114 b = b + c;
115 c = -0.5*b-x;
116 r[1][2] = c;
117
118 if( ( b > 0. && x <= 0. ) || ( b < 0. && x > 0. ) )
119 {
120 r[1][1] = c;
121 r[2][1] = -d;
122 r[1][3] = b - x;
123 r[2][3] = 0;
124 }
125 else
126 {
127 r[1][1] = b - x;
128 r[2][1] = 0.;
129 r[1][3] = c;
130 r[2][3] = -d;
131 }
132 } // end of 2 equal or complex roots
133 else
134 {
135 if( b == 0. ) { d = std::atan(1.0)/1.5; }
136 else { d = std::atan( std::sqrt(-d)/std::fabs(b) )/3.0; }
137
138 if( b < 0. ) { b = std::sqrt(t)*2.0; }
139 else { b = -2.0*std::sqrt(t); }
140
141 c = std::cos(d)*b;
142 t = -std::sqrt(0.75)*std::sin(d)*b - 0.5*c;
143 d = -t - c - x;
144 c = c - x;
145 t = t - x;
146
147 if( std::fabs(c) > std::fabs(t) ) { r[1][3] = c; }
148 else
149 {
150 r[1][3] = t;
151 t = c;
152 }
153 if( std::fabs(d) > std::fabs(t) ) { r[1][2] = d; }
154 else
155 {
156 r[1][2] = t;
157 t = d;
158 }
159 r[1][1] = t;
160
161 for(k = 1; k < 4; k++ ) { r[2][k] = 0.; }
162 }
163 return 0;
164}
165
166//////////////////////////////////////////////////////////////////////////////
167//
168// Array r[3][5] p[5]
169// Roots of poly p[0] x^4 + p[1] x^3...+p[4]=0
170// x=r[1][k] + i r[2][k] k=1,...,4
171
173{
174 G4double a, b, c, d, e;
175 G4int i, k, j;
176
177 if(p[0] != 1.0)
178 {
179 for( k = 1; k < 5; k++) { p[k] = p[k]/p[0]; }
180 p[0] = 1.;
181 }
182 e = 0.25*p[1];
183 b = 2*e;
184 c = b*b;
185 d = 0.75*c;
186 b = p[3] + b*( c - p[2] );
187 a = p[2] - d;
188 c = p[4] + e*( e*a - p[3] );
189 a = a - d;
190
191 p[1] = 0.5*a;
192 p[2] = (p[1]*p[1]-c)*0.25;
193 p[3] = b*b/(-64.0);
194
195 if( p[3] < 0. )
196 {
197 CubicRoots(p,r);
198
199 for( k = 1; k < 4; k++ )
200 {
201 if( r[2][k] == 0. && r[1][k] > 0 )
202 {
203 d = r[1][k]*4;
204 a = a + d;
205
206 if ( a >= 0. && b >= 0.) { p[1] = std::sqrt(d); }
207 else if( a <= 0. && b <= 0.) { p[1] = std::sqrt(d); }
208 else { p[1] = -std::sqrt(d); }
209
210 b = 0.5*( a + b/p[1] );
211
212 p[2] = c/b;
213 QuadRoots(p,r);
214
215 for( i = 1; i < 3; i++ )
216 {
217 for( j = 1; j < 3; j++ ) { r[j][i+2] = r[j][i]; }
218 }
219 p[1] = -p[1];
220 p[2] = b;
221 QuadRoots(p,r);
222
223 for( i = 1; i < 5; i++ ) { r[1][i] = r[1][i] - e; }
224
225 return 4;
226 }
227 }
228 }
229 if( p[2] < 0. )
230 {
231 b = std::sqrt(c);
232 d = b + b - a;
233 p[1] = 0.;
234
235 if( d > 0. ) { p[1] = std::sqrt(d); }
236 }
237 else
238 {
239 if( p[1] > 0.) { b = std::sqrt(p[2])*2.0 + p[1]; }
240 else { b = -std::sqrt(p[2])*2.0 + p[1]; }
241
242 if( b != 0.) { p[1] = 0; }
243 else
244 {
245 for(k = 1; k < 5; k++ )
246 {
247 r[1][k] = -e;
248 r[2][k] = 0;
249 }
250 return 0;
251 }
252 }
253
254 p[2] = c/b;
255 QuadRoots(p,r);
256
257 for( k = 1; k < 3; k++ )
258 {
259 for( j = 1; j < 3; j++ ) { r[j][k+2] = r[j][k]; }
260 }
261 p[1] = -p[1];
262 p[2] = b;
263 QuadRoots(p,r);
264
265 for( k = 1; k < 5; k++ ) { r[1][k] = r[1][k] - e; }
266
267 return 4;
268}
269
270//////////////////////////////////////////////////////////////////////////////
271
273{
274 G4double a0, a1, a2, a3, y1;
275 G4double R2, D2, E2, D, E, R = 0.;
276 G4double a, b, c, d, ds;
277
278 G4double reRoot[4];
279 G4int k, noReRoots = 0;
280
281 for( k = 0; k < 4; k++ ) { reRoot[k] = DBL_MAX; }
282
283 if( p[0] != 1.0 )
284 {
285 for( k = 1; k < 5; k++) { p[k] = p[k]/p[0]; }
286 p[0] = 1.;
287 }
288 a3 = p[1];
289 a2 = p[2];
290 a1 = p[3];
291 a0 = p[4];
292
293 // resolvent cubic equation cofs:
294
295 p[1] = -a2;
296 p[2] = a1*a3 - 4*a0;
297 p[3] = 4*a2*a0 - a1*a1 - a3*a3*a0;
298
299 CubicRoots(p,r);
300
301 for( k = 1; k < 4; k++ )
302 {
303 if( r[2][k] == 0. ) // find a real root
304 {
305 noReRoots++;
306 reRoot[k] = r[1][k];
307 }
308 else reRoot[k] = DBL_MAX; // kInfinity;
309 }
310 y1 = DBL_MAX; // kInfinity;
311 for( k = 1; k < 4; k++ )
312 {
313 if ( reRoot[k] < y1 ) { y1 = reRoot[k]; }
314 }
315
316 R2 = 0.25*a3*a3 - a2 + y1;
317 b = 0.25*(4*a3*a2 - 8*a1 - a3*a3*a3);
318 c = 0.75*a3*a3 - 2*a2;
319 a = c - R2;
320 d = 4*y1*y1 - 16*a0;
321
322 if( R2 > 0.)
323 {
324 R = std::sqrt(R2);
325 D2 = a + b/R;
326 E2 = a - b/R;
327
328 if( D2 >= 0. )
329 {
330 D = std::sqrt(D2);
331 r[1][1] = -0.25*a3 + 0.5*R + 0.5*D;
332 r[1][2] = -0.25*a3 + 0.5*R - 0.5*D;
333 r[2][1] = 0.;
334 r[2][2] = 0.;
335 }
336 else
337 {
338 D = std::sqrt(-D2);
339 r[1][1] = -0.25*a3 + 0.5*R;
340 r[1][2] = -0.25*a3 + 0.5*R;
341 r[2][1] = 0.5*D;
342 r[2][2] = -0.5*D;
343 }
344 if( E2 >= 0. )
345 {
346 E = std::sqrt(E2);
347 r[1][3] = -0.25*a3 - 0.5*R + 0.5*E;
348 r[1][4] = -0.25*a3 - 0.5*R - 0.5*E;
349 r[2][3] = 0.;
350 r[2][4] = 0.;
351 }
352 else
353 {
354 E = std::sqrt(-E2);
355 r[1][3] = -0.25*a3 - 0.5*R;
356 r[1][4] = -0.25*a3 - 0.5*R;
357 r[2][3] = 0.5*E;
358 r[2][4] = -0.5*E;
359 }
360 }
361 else if( R2 < 0.)
362 {
363 R = std::sqrt(-R2);
364 G4complex CD2(a,-b/R);
365 G4complex CD = std::sqrt(CD2);
366
367 r[1][1] = -0.25*a3 + 0.5*real(CD);
368 r[1][2] = -0.25*a3 - 0.5*real(CD);
369 r[2][1] = 0.5*R + 0.5*imag(CD);
370 r[2][2] = 0.5*R - 0.5*imag(CD);
371 G4complex CE2(a,b/R);
372 G4complex CE = std::sqrt(CE2);
373
374 r[1][3] = -0.25*a3 + 0.5*real(CE);
375 r[1][4] = -0.25*a3 - 0.5*real(CE);
376 r[2][3] = -0.5*R + 0.5*imag(CE);
377 r[2][4] = -0.5*R - 0.5*imag(CE);
378 }
379 else // R2=0 case
380 {
381 if(d >= 0.)
382 {
383 D2 = c + std::sqrt(d);
384 E2 = c - std::sqrt(d);
385
386 if( D2 >= 0. )
387 {
388 D = std::sqrt(D2);
389 r[1][1] = -0.25*a3 + 0.5*R + 0.5*D;
390 r[1][2] = -0.25*a3 + 0.5*R - 0.5*D;
391 r[2][1] = 0.;
392 r[2][2] = 0.;
393 }
394 else
395 {
396 D = std::sqrt(-D2);
397 r[1][1] = -0.25*a3 + 0.5*R;
398 r[1][2] = -0.25*a3 + 0.5*R;
399 r[2][1] = 0.5*D;
400 r[2][2] = -0.5*D;
401 }
402 if( E2 >= 0. )
403 {
404 E = std::sqrt(E2);
405 r[1][3] = -0.25*a3 - 0.5*R + 0.5*E;
406 r[1][4] = -0.25*a3 - 0.5*R - 0.5*E;
407 r[2][3] = 0.;
408 r[2][4] = 0.;
409 }
410 else
411 {
412 E = std::sqrt(-E2);
413 r[1][3] = -0.25*a3 - 0.5*R;
414 r[1][4] = -0.25*a3 - 0.5*R;
415 r[2][3] = 0.5*E;
416 r[2][4] = -0.5*E;
417 }
418 }
419 else
420 {
421 ds = std::sqrt(-d);
422 G4complex CD2(c,ds);
423 G4complex CD = std::sqrt(CD2);
424
425 r[1][1] = -0.25*a3 + 0.5*real(CD);
426 r[1][2] = -0.25*a3 - 0.5*real(CD);
427 r[2][1] = 0.5*R + 0.5*imag(CD);
428 r[2][2] = 0.5*R - 0.5*imag(CD);
429
430 G4complex CE2(c,-ds);
431 G4complex CE = std::sqrt(CE2);
432
433 r[1][3] = -0.25*a3 + 0.5*real(CE);
434 r[1][4] = -0.25*a3 - 0.5*real(CE);
435 r[2][3] = -0.5*R + 0.5*imag(CE);
436 r[2][4] = -0.5*R - 0.5*imag(CE);
437 }
438 }
439 return 4;
440}
441
442//
443//
444//////////////////////////////////////////////////////////////////////////////
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
std::complex< G4double > G4complex
Definition: G4Types.hh:69
G4int CubicRoots(G4double p[5], G4double r[3][5])
G4int QuarticRoots(G4double p[5], G4double r[3][5])
G4int QuadRoots(G4double p[5], G4double r[3][5])
G4int BiquadRoots(G4double p[5], G4double r[3][5])
#define DBL_MAX
Definition: templates.hh:83