Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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