ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4Clebsch.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4Clebsch.cc
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 #include "G4ios.hh"
27 #include "G4Clebsch.hh"
28 #include "G4Pow.hh"
29 #include "G4Exp.hh"
30 #include "G4Log.hh"
31 #include "Randomize.hh"
32 
33 const G4int G4POWLOGFACTMAX = 512;
34 
35 using namespace std;
36 
38  G4int twoJ2, G4int twoM2,
39  G4int twoJ)
40 {
41  if(twoJ1 < 0 || twoJ2 < 0 || twoJ < 0 ||
42  ((twoJ1-twoM1) % 2) || ((twoJ2-twoM2) % 2)) { return 0; }
43 
44  G4int twoM = twoM1 + twoM2;
45  if(twoM1 > twoJ1 || twoM1 < -twoJ1 ||
46  twoM2 > twoJ2 || twoM2 < -twoJ2 ||
47  twoM > twoJ || twoM < -twoJ) { return 0; }
48 
49  // Checks limits on J1, J2, J3
50  G4double triangle = TriangleCoeff(twoJ1, twoJ2, twoJ);
51  if(triangle == 0) { return 0; }
52 
53  G4Pow* g4pow = G4Pow::GetInstance();
54  G4double factor = g4pow->logfactorial((twoJ1 + twoM1)/2) +
55  g4pow->logfactorial((twoJ1 - twoM1)/2);
56  factor += g4pow->logfactorial((twoJ2 + twoM2)/2) +
57  g4pow->logfactorial((twoJ2 - twoM2)/2);
58  factor += g4pow->logfactorial((twoJ + twoM)/2) +
59  g4pow->logfactorial((twoJ - twoM)/2);
60  factor *= 0.5;
61 
62  G4int kMin = 0;
63  G4int sum1 = (twoJ1 - twoM1)/2;
64  G4int kMax = sum1;
65  G4int sum2 = (twoJ - twoJ2 + twoM1)/2;
66  if(-sum2 > kMin) kMin = -sum2;
67  G4int sum3 = (twoJ2 + twoM2)/2;
68  if(sum3 < kMax) kMax = sum3;
69  G4int sum4 = (twoJ - twoJ1 - twoM2)/2;
70  if(-sum4 > kMin) kMin = -sum4;
71  G4int sum5 = (twoJ1 + twoJ2 - twoJ)/2;
72  if(sum5 < kMax) kMax = sum5;
73 
74  // sanity / boundary checks
75  if(kMin < 0) {
76  G4Exception("G4Clebsch::ClebschGordanCoeff()", "Clebsch001",
77  JustWarning, "kMin < 0");
78  return 0;
79  }
80  if(kMax < kMin) {
81  G4Exception("G4Clebsch::ClebschGordanCoeff()", "Clebsch002",
82  JustWarning, "kMax < kMin");
83  return 0;
84  }
85  if(kMax >= G4POWLOGFACTMAX) {
86  G4Exception("G4Clebsch::ClebschGordanCoeff()", "Clebsch003",
87  JustWarning, "kMax too big for G4Pow");
88  return 0;
89  }
90 
91  // Now do the sum over k
92  G4double kSum = 0.;
93  for(G4int k = kMin; k <= kMax; k++) {
94  G4double sign = (k % 2) ? -1 : 1;
95  kSum += sign * G4Exp(factor - g4pow->logfactorial(sum1-k) -
96  g4pow->logfactorial(sum2+k) -
97  g4pow->logfactorial(sum3-k) -
98  g4pow->logfactorial(sum4+k) -
99  g4pow->logfactorial(k) -
100  g4pow->logfactorial(sum5-k));
101  }
102 
103  return triangle*sqrt(twoJ+1)*kSum;
104 }
105 
107  G4int twoJ2, G4int twoM2,
108  G4int twoJ)
109 {
110  // ClebschGordanCoeff() will do all input checking
111  G4double clebsch = ClebschGordanCoeff(twoJ1, twoM1, twoJ2, twoM2, twoJ);
112  return clebsch*clebsch;
113 }
114 
115 std::vector<G4double>
117  G4int twoJ2, G4int twoM2,
118  G4int twoJOut1, G4int twoJOut2)
119 {
120  std::vector<G4double> temp;
121 
122  // ---- Special cases first ----
123 
124  // Special case, both Jin are zero
125  if (twoJ1 == 0 && twoJ2 == 0) {
126  G4Exception("G4Clebsch::GenerateIso3()", "Clebsch010",
127  JustWarning, "both twoJ are zero");
128  temp.push_back(0.);
129  temp.push_back(0.);
130  return temp;
131  }
132 
133  G4int twoM3 = twoM1 + twoM2;
134 
135  // Special case, either Jout is zero
136  if (twoJOut1 == 0) {
137  temp.push_back(0.);
138  temp.push_back(twoM3);
139  return temp;
140  }
141  if (twoJOut2 == 0) {
142  temp.push_back(twoM3);
143  temp.push_back(0.);
144  return temp;
145  }
146 
147  // Number of possible states, in
148  G4int twoJMinIn = std::max(std::abs(twoJ1 - twoJ2), std::abs(twoM3));
149  G4int twoJMaxIn = twoJ1 + twoJ2;
150 
151  // Number of possible states, out
152  G4int twoJMinOut = 9999;
153  for(G4int i=-1; i<=1; i+=2) {
154  for(G4int j=-1; j<=1; j+=2) {
155  G4int twoJTmp= std::abs(i*twoJOut1 + j*twoJOut2);
156  if(twoJTmp < twoJMinOut) twoJMinOut = twoJTmp;
157  }
158  }
159  twoJMinOut = std::max(twoJMinOut, std::abs(twoM3));
160  G4int twoJMaxOut = twoJOut1 + twoJOut2;
161 
162  // Possible in and out common states
163  G4int twoJMin = std::max(twoJMinIn, twoJMinOut);
164  G4int twoJMax = std::min(twoJMaxIn, twoJMaxOut);
165  if (twoJMin > twoJMax) {
166  G4Exception("G4Clebsch::GenerateIso3()", "Clebsch020",
167  JustWarning, "twoJMin > twoJMax");
168  return temp;
169  }
170 
171  // Number of possible isospins
172  G4int nJ = (twoJMax - twoJMin) / 2 + 1;
173 
174  // A few consistency checks
175 
176  if ( (twoJ1 == 0 || twoJ2 == 0) && twoJMin != twoJMax ) {
177  G4Exception("G4Clebsch::GenerateIso3()", "Clebsch021",
178  JustWarning, "twoJ1 or twoJ2 = 0, but twoJMin != JMax");
179  return temp;
180  }
181 
182  // MGP ---- Shall it be a warning or an exception?
183  if (nJ == 0) {
184  G4Exception("G4Clebsch::GenerateIso3()", "Clebsch022",
185  JustWarning, "nJ is zero, no overlap between in and out");
186  return temp;
187  }
188 
189  // Loop over all possible combinations of twoJ1, twoJ2, twoM11, twoM2, twoJTot
190  // to get the probability of each of the in-channel couplings
191 
192  std::vector<G4double> clebsch;
193  G4double sum = 0.0;
194  for(G4int twoJ=twoJMin; twoJ<=twoJMax; twoJ+=2) {
195  sum += ClebschGordan(twoJ1, twoM1, twoJ2, twoM2, twoJ);
196  clebsch.push_back(sum);
197  }
198 
199  // Consistency check
200  if (static_cast<G4int>(clebsch.size()) != nJ) {
201  G4Exception("G4Clebsch::GenerateIso3()", "Clebsch023",
202  JustWarning, "nJ inconsistency");
203  return temp;
204  }
205 
206  // Consistency check
207  if (sum <= 0.) {
208  G4Exception("G4Clebsch::GenerateIso3()", "Clebsch024",
209  JustWarning, "Sum of Clebsch-Gordan probabilities <=0");
210  return temp;
211  }
212 
213  // Generate a random twoJTot according to the Clebsch-Gordan pdf
214  sum *= G4UniformRand();
215  G4int twoJTot = twoJMin;
216  for (G4int i=0; i<nJ; ++i) {
217  if (sum < clebsch[i]) {
218  twoJTot += 2*i;
219  break;
220  }
221  }
222 
223  // Generate twoM3Out
224 
225  std::vector<G4double> mMin;
226  mMin.push_back(-twoJOut1);
227  mMin.push_back(-twoJOut2);
228 
229  std::vector<G4double> mMax;
230  mMax.push_back(twoJOut1);
231  mMax.push_back(twoJOut2);
232 
233  // Calculate the possible |J_i M_i> combinations and their probability
234 
235  std::vector<G4double> m1Out;
236  std::vector<G4double> m2Out;
237 
238  const G4int size = 20;
239  G4double prbout[size][size];
240 
241  G4int m1pos(0), m2pos(0);
242  G4int j12;
243  G4int m1pr(0), m2pr(0);
244 
245  sum = 0.;
246  for(j12 = std::abs(twoJOut1-twoJOut2); j12<=(twoJOut1+twoJOut2); j12+=2)
247  {
248  m1pos = -1;
249  for (m1pr = static_cast<G4int>(mMin[0]+.00001); m1pr <= mMax[0]; m1pr+=2)
250  {
251  m1pos++;
252  if (m1pos >= size) {
253  G4Exception("G4Clebsch::GenerateIso3()", "Clebsch025",
254  JustWarning, "m1pos > size");
255  return temp;
256  }
257  m1Out.push_back(m1pr);
258  m2pos = -1;
259  for (m2pr = static_cast<G4int>(mMin[1]+.00001); m2pr <= mMax[1]; m2pr+=2)
260  {
261  m2pos++;
262  if (m2pos >= size)
263  {
264  G4Exception("G4Clebsch::GenerateIso3()", "Clebsch026",
265  JustWarning, "m2pos > size");
266  return temp;
267  }
268  m2Out.push_back(m2pr);
269 
270  if(m1pr + m2pr == twoM3)
271  {
272  G4int m12 = m1pr + m2pr;
273  G4double c12 = ClebschGordan(twoJOut1, m1pr, twoJOut2,m2pr, j12);
274  G4double c34 = ClebschGordan(0,0,0,0,0);
275  G4double ctot = ClebschGordan(j12, m12, 0, 0, twoJTot);
276  G4double cleb = c12*c34*ctot;
277  prbout[m1pos][m2pos] = cleb;
278  sum += cleb;
279  }
280  else
281  {
282  prbout[m1pos][m2pos] = 0.;
283  }
284  }
285  }
286  }
287 
288  if (sum <= 0.) {
289  G4Exception("G4Clebsch::GenerateIso3()", "Clebsch027",
290  JustWarning, "sum (out) <=0");
291  return temp;
292  }
293 
294  for (G4int i=0; i<size; i++) {
295  for (G4int j=0; j<size; j++) {
296  prbout[i][j] /= sum;
297  }
298  }
299 
300  G4double rand = G4UniformRand();
301 
302  G4int m1p, m2p;
303 
304  for (m1p=0; m1p<m1pos; m1p++) {
305  for (m2p=0; m2p<m2pos; m2p++) {
306  if (rand < prbout[m1p][m2p]) {
307  temp.push_back(m1Out[m1p]);
308  temp.push_back(m2Out[m2p]);
309  return temp;
310  }
311  else rand -= prbout[m1p][m2p];
312  }
313  }
314 
315  G4Exception("G4Clebsch::GenerateIso3()", "Clebsch028",
316  JustWarning, "Should never get here");
317  return temp;
318 }
319 
321  G4int twoJ2, G4int twoM2,
322  G4int twoJOut1, G4int twoJOut2)
323 {
324  G4double value = 0.;
325 
326  G4int twoM = twoM1 + twoM2;
327 
328  G4int twoJMinIn = std::max(std::abs(twoJ1 - twoJ2), std::abs(twoM));
329  G4int twoJMaxIn = twoJ1 + twoJ2;
330 
331  G4int twoJMinOut = std::max(std::abs(twoJOut1 - twoJOut2), std::abs(twoM));
332  G4int twoJMaxOut = twoJOut1 + twoJOut2;
333 
334  G4int twoJMin = std::max(twoJMinIn,twoJMinOut);
335  G4int twoJMax = std::min(twoJMaxIn,twoJMaxOut);
336 
337  for (G4int twoJ=twoJMin; twoJ<=twoJMax; twoJ+=2) {
338  // ClebschGordan() will do all input checking
339  value += ClebschGordan(twoJ1, twoM1, twoJ2, twoM2, twoJ);
340  }
341 
342  return value;
343 }
344 
347 {
348  // G4Exception("G4Clebsch::Wigner3J()", "Clebsch030", JustWarning,
349  // "G4Clebsch::Wigner3J with double arguments is deprecated. Please use G4int version.");
350  G4int twoJ1 = (G4int) (2.*j1);
351  G4int twoJ2 = (G4int) (2.*j2);
352  G4int twoJ3 = (G4int) (2.*j3);
353  G4int twoM1 = (G4int) (2.*m1);
354  G4int twoM2 = (G4int) (2.*m2);
355  G4int twoM3 = (G4int) (2.*m3);
356  return Wigner3J(twoJ1, twoM1, twoJ2, twoM2, twoJ3, twoM3);
357 }
358 
360  G4int twoJ2, G4int twoM2,
361  G4int twoJ3)
362 {
363  G4double clebsch = ClebschGordanCoeff(twoJ1, twoM1, twoJ2, twoM2, twoJ3);
364  if(clebsch == 0) return clebsch;
365  if( (twoJ1-twoJ2+twoM1+twoM2)/2 % 2) clebsch = -clebsch;
366  return clebsch / sqrt(twoJ3+1);
367 }
368 
370  G4int twoJ2, G4int twoM2,
371  G4int twoJ3, G4int twoM3)
372 {
373  if(twoM1 + twoM2 != -twoM3) return 0;
374  G4double clebsch = ClebschGordanCoeff(twoJ1, twoM1, twoJ2, twoM2, twoJ3);
375  if(clebsch == 0) return clebsch;
376  if( (twoJ1-twoJ2-twoM3)/2 % 2) clebsch = -clebsch;
377  return clebsch / sqrt(twoJ3+1);
378 }
379 
381  G4int twoJ1, G4int twoJ2,
382  G4int twoM1, G4int twoM2)
383 {
384  // Calculate the normalized Clebsch-Gordan coefficient, that is the prob
385  // of isospin decomposition of (J,m) into J1, J2, m1, m2
386 
387  G4double cleb = 0.;
388  if(twoJ1 == 0 || twoJ2 == 0) return cleb;
389 
390  // Loop over all J1,J2,Jtot,m1,m2 combinations
391  G4double sum = 0.0;
392  for(G4int twoM1Current=-twoJ1; twoM1Current<=twoJ1; twoM1Current+=2) {
393  G4int twoM2Current = twoM - twoM1Current;
394  // ClebschGordan() will do all further input checking
395  G4double prob = ClebschGordan(twoJ1, twoM1Current, twoJ2,
396  twoM2Current, twoJ);
397  sum += prob;
398  if (twoM2Current == twoM2 && twoM1Current == twoM1) cleb += prob;
399  }
400 
401  // Normalize probs to 1
402  if (sum > 0.) cleb /= sum;
403 
404  return cleb;
405 }
406 
408 {
409  // TC(ABC) = sqrt[ (A+B-C)! (A-B+C)! (-A+B+C)! / (A+B+C+1)! ]
410  // return 0 if the triad does not satisfy the triangle inequalities
411  G4Pow* g4pow = G4Pow::GetInstance();
412 
413  double val = 0;
414  G4int i = twoA+twoB-twoC;
415  // only have to check that i is even the first time
416  if(i<0 || (i%2)) return 0;
417  else val += g4pow->logfactorial(i/2);
418 
419  i = twoA-twoB+twoC;
420  if(i<0) return 0;
421  else val += g4pow->logfactorial(i/2);
422 
423  i = -twoA+twoB+twoC;
424  if(i<0) return 0;
425  else val += g4pow->logfactorial(i/2);
426 
427  i = twoA+twoB+twoC+2;
428  if(i<0) return 0;
429  return G4Exp(0.5*(val - g4pow->logfactorial(i/2)));
430 }
431 
433  G4int twoJ4, G4int twoJ5, G4int twoJ6)
434 {
435  if(twoJ1 < 0 || twoJ2 < 0 || twoJ3 < 0 ||
436  twoJ4 < 0 || twoJ5 < 0 || twoJ6 < 0) return 0;
437 
438  // There is a fast calculation (no sums or exps) when twoJ6 = 0,
439  // so permute to use it when possible
440  if(twoJ6 == 0) {
441  if(twoJ1 != twoJ5) return 0;
442  if(twoJ2 != twoJ4) return 0;
443  if(twoJ1+twoJ2 < twoJ3) return 0;
444  if((twoJ1 > twoJ2) && (twoJ3 < (twoJ1-twoJ2))) return 0;
445  if((twoJ2 > twoJ1) && (twoJ3 < (twoJ2-twoJ1))) return 0;
446  if((twoJ1+twoJ2+twoJ3) % 2) return 0;
447  return (((twoJ1+twoJ2+twoJ3)/2) % 2 ? -1. : 1.) /sqrt((twoJ1+1)*(twoJ2+1));
448  }
449  if(twoJ1 == 0) return Wigner6J(twoJ6, twoJ2, twoJ4, twoJ3, twoJ5, 0);
450  if(twoJ2 == 0) return Wigner6J(twoJ1, twoJ6, twoJ5, twoJ4, twoJ3, 0);
451  if(twoJ3 == 0) return Wigner6J(twoJ4, twoJ2, twoJ6, twoJ1, twoJ5, 0);
452  if(twoJ4 == 0) return Wigner6J(twoJ3, twoJ2, twoJ1, twoJ6, twoJ5, 0);
453  if(twoJ5 == 0) return Wigner6J(twoJ1, twoJ3, twoJ2, twoJ4, twoJ6, 0);
454 
455  // Check triangle inequalities and calculate triangle coefficients.
456  // Also check evenness of sums
457  G4Pow* g4pow = G4Pow::GetInstance();
458  double triangles = 0;
459  G4int i;
460  i = twoJ1+twoJ2-twoJ3; if(i<0 || i%2) return 0; else triangles += g4pow->logfactorial(i/2);
461  i = twoJ1-twoJ2+twoJ3; if(i<0 || i%2) return 0; else triangles += g4pow->logfactorial(i/2);
462  i = -twoJ1+twoJ2+twoJ3; if(i<0 || i%2) return 0; else triangles += g4pow->logfactorial(i/2);
463  i = twoJ1+twoJ2+twoJ3+2; if(i<0 || i%2) return 0; else triangles -= g4pow->logfactorial(i/2);
464  i = twoJ1+twoJ5-twoJ6; if(i<0 || i%2) return 0; else triangles += g4pow->logfactorial(i/2);
465  i = twoJ1-twoJ5+twoJ6; if(i<0 || i%2) return 0; else triangles += g4pow->logfactorial(i/2);
466  i = -twoJ1+twoJ5+twoJ6; if(i<0 || i%2) return 0; else triangles += g4pow->logfactorial(i/2);
467  i = twoJ1+twoJ5+twoJ6+2; if(i<0 || i%2) return 0; else triangles -= g4pow->logfactorial(i/2);
468  i = twoJ4+twoJ2-twoJ6; if(i<0 || i%2) return 0; else triangles += g4pow->logfactorial(i/2);
469  i = twoJ4-twoJ2+twoJ6; if(i<0 || i%2) return 0; else triangles += g4pow->logfactorial(i/2);
470  i = -twoJ4+twoJ2+twoJ6; if(i<0 || i%2) return 0; else triangles += g4pow->logfactorial(i/2);
471  i = twoJ4+twoJ2+twoJ6+2; if(i<0 || i%2) return 0; else triangles -= g4pow->logfactorial(i/2);
472  i = twoJ4+twoJ5-twoJ3; if(i<0 || i%2) return 0; else triangles += g4pow->logfactorial(i/2);
473  i = twoJ4-twoJ5+twoJ3; if(i<0 || i%2) return 0; else triangles += g4pow->logfactorial(i/2);
474  i = -twoJ4+twoJ5+twoJ3; if(i<0 || i%2) return 0; else triangles += g4pow->logfactorial(i/2);
475  i = twoJ4+twoJ5+twoJ3+2; if(i<0 || i%2) return 0; else triangles -= g4pow->logfactorial(i/2);
476  triangles = G4Exp(0.5*triangles);
477 
478  // Prepare to sum over k. If we have made it this far, all of the following
479  // sums must be non-negative and divisible by two
480 
481  // k must be >= all of the following sums:
482  G4int sum1 = (twoJ1 + twoJ2 + twoJ3)/2;
483  G4int kMin = sum1;
484  G4int sum2 = (twoJ1 + twoJ5 + twoJ6)/2;
485  if(sum2 > kMin) kMin = sum2;
486  G4int sum3 = (twoJ4 + twoJ2 + twoJ6)/2;
487  if(sum3 > kMin) kMin = sum3;
488  G4int sum4 = (twoJ4 + twoJ5 + twoJ3)/2;
489  if(sum4 > kMin) kMin = sum4;
490 
491  // and k must be <= all of the following sums:
492  G4int sum5 = (twoJ1 + twoJ2 + twoJ4 + twoJ5)/2;
493  G4int kMax = sum5;
494  G4int sum6 = (twoJ2 + twoJ3 + twoJ5 + twoJ6)/2;
495  if(sum6 < kMax) kMax = sum6;
496  G4int sum7 = (twoJ1 + twoJ3 + twoJ4 + twoJ6)/2;
497  if(sum7 < kMax) kMax = sum7;
498 
499  // sanity / boundary checks
500  if(kMin < 0) {
501  G4Exception("G4Clebsch::Wigner6J()", "Clebsch040",
502  JustWarning, "kMin < 0");
503  return 0;
504  }
505  if(kMax < kMin) {
506  G4Exception("G4Clebsch::Wigner6J()", "Clebsch041",
507  JustWarning, "kMax < kMin");
508  return 0;
509  }
510  if(kMax >= G4POWLOGFACTMAX) {
511  G4Exception("G4Clebsch::Wigner6J()", "Clebsch041",
512  JustWarning, "kMax too big for G4Pow");
513  return 0;
514  }
515 
516  // Now do the sum over k
517  G4double kSum = 0.;
518  G4double sign = (kMin % 2) ? -1 : 1;
519  for(G4int k = kMin; k <= kMax; k++) {
520  kSum += sign * G4Exp(g4pow->logfactorial(k+1) -
521  g4pow->logfactorial(k-sum1) -
522  g4pow->logfactorial(k-sum2) -
523  g4pow->logfactorial(k-sum3) -
524  g4pow->logfactorial(k-sum4) -
525  g4pow->logfactorial(sum5-k) -
526  g4pow->logfactorial(sum6-k) -
527  g4pow->logfactorial(sum7-k));
528  sign *= -1;
529  }
530  return triangles*kSum;
531 }
532 
534  G4int twoJ4, G4int twoJ5, G4int twoJ6,
535  G4int twoJ7, G4int twoJ8, G4int twoJ9)
536 {
537  if(twoJ1 < 0 || twoJ2 < 0 || twoJ3 < 0 ||
538  twoJ4 < 0 || twoJ5 < 0 || twoJ6 < 0 ||
539  twoJ7 < 0 || twoJ8 < 0 || twoJ9 < 0) return 0;
540 
541  if(twoJ9 == 0) {
542  if(twoJ3 != twoJ6) return 0;
543  if(twoJ7 != twoJ8) return 0;
544  G4double sixJ = Wigner6J(twoJ1, twoJ2, twoJ3, twoJ5, twoJ4, twoJ7);
545  if(sixJ == 0) return 0;
546  if((twoJ2+twoJ3+twoJ4+twoJ7)/2 % 2) sixJ = -sixJ;
547  return sixJ/sqrt((twoJ3+1)*(twoJ7+1));
548  }
549  if(twoJ1 == 0) return Wigner9J(twoJ9, twoJ6, twoJ3, twoJ8, twoJ5, twoJ2, twoJ7, twoJ4, twoJ1);
550  if(twoJ2 == 0) return Wigner9J(twoJ7, twoJ9, twoJ8, twoJ4, twoJ6, twoJ5, twoJ1, twoJ3, twoJ2);
551  if(twoJ4 == 0) return Wigner9J(twoJ3, twoJ2, twoJ1, twoJ9, twoJ8, twoJ7, twoJ6, twoJ5, twoJ4);
552  if(twoJ5 == 0) return Wigner9J(twoJ1, twoJ3, twoJ2, twoJ7, twoJ9, twoJ8, twoJ4, twoJ6, twoJ5);
553  G4int twoS = twoJ1+twoJ2+twoJ3+twoJ4+twoJ5+twoJ6+twoJ7+twoJ8+twoJ9;
554  if(twoS % 2) return 0;
555  G4double sign = (twoS/2 % 2) ? -1 : 1;
556  if(twoJ3 == 0) return sign*Wigner9J(twoJ7, twoJ8, twoJ9, twoJ4, twoJ5, twoJ6, twoJ1, twoJ2, twoJ3);
557  if(twoJ6 == 0) return sign*Wigner9J(twoJ1, twoJ2, twoJ3, twoJ7, twoJ8, twoJ9, twoJ4, twoJ5, twoJ6);
558  if(twoJ7 == 0) return sign*Wigner9J(twoJ3, twoJ2, twoJ1, twoJ6, twoJ5, twoJ4, twoJ9, twoJ8, twoJ7);
559  if(twoJ8 == 0) return sign*Wigner9J(twoJ1, twoJ3, twoJ2, twoJ4, twoJ6, twoJ5, twoJ7, twoJ9, twoJ8);
560 
561  // No element is zero: check triads now for speed
562  G4int i;
563  i = twoJ1+twoJ2-twoJ3; if(i<0 || i%2) return 0;
564  i = twoJ1-twoJ2+twoJ3; if(i<0 || i%2) return 0;
565  i = -twoJ1+twoJ2+twoJ3; if(i<0 || i%2) return 0;
566  i = twoJ4+twoJ5-twoJ6; if(i<0 || i%2) return 0;
567  i = twoJ4-twoJ5+twoJ6; if(i<0 || i%2) return 0;
568  i = -twoJ4+twoJ5+twoJ6; if(i<0 || i%2) return 0;
569  i = twoJ7+twoJ8-twoJ9; if(i<0 || i%2) return 0;
570  i = twoJ7-twoJ8+twoJ9; if(i<0 || i%2) return 0;
571  i = -twoJ7+twoJ8+twoJ9; if(i<0 || i%2) return 0;
572  i = twoJ1+twoJ4-twoJ7; if(i<0 || i%2) return 0;
573  i = twoJ1-twoJ4+twoJ7; if(i<0 || i%2) return 0;
574  i = -twoJ1+twoJ4+twoJ7; if(i<0 || i%2) return 0;
575  i = twoJ2+twoJ5-twoJ8; if(i<0 || i%2) return 0;
576  i = twoJ2-twoJ5+twoJ8; if(i<0 || i%2) return 0;
577  i = -twoJ2+twoJ5+twoJ8; if(i<0 || i%2) return 0;
578  i = twoJ3+twoJ6-twoJ9; if(i<0 || i%2) return 0;
579  i = twoJ3-twoJ6+twoJ9; if(i<0 || i%2) return 0;
580  i = -twoJ3+twoJ6+twoJ9; if(i<0 || i%2) return 0;
581 
582  // Okay, have to do the full sum over 6J's
583  // Find limits for K sum
584  G4int twoKMax = twoJ1+twoJ9;
585  if(twoJ4+twoJ8 < twoKMax) twoKMax = twoJ4+twoJ8;
586  if(twoJ2+twoJ6 < twoKMax) twoKMax = twoJ2+twoJ6;
587  G4int twoKMin = twoJ1-twoJ9;
588  if(twoJ9-twoJ1 > twoKMin) twoKMin = twoJ9-twoJ1;
589  if(twoJ4-twoJ8 > twoKMin) twoKMin = twoJ4-twoJ8;
590  if(twoJ8-twoJ4 > twoKMin) twoKMin = twoJ8-twoJ4;
591  if(twoJ2-twoJ6 > twoKMin) twoKMin = twoJ2-twoJ6;
592  if(twoJ6-twoJ2 > twoKMin) twoKMin = twoJ6-twoJ2;
593  if(twoKMin > twoKMax) return 0;
594 
595  G4double sum = 0;
596  for(G4int twoK = twoKMin; twoK <= twoKMax; twoK += 2) {
597  G4double value = Wigner6J(twoJ1, twoJ4, twoJ7, twoJ8, twoJ9, twoK);
598  if(value == 0) continue;
599  value *= Wigner6J(twoJ2, twoJ5, twoJ8, twoJ4, twoK, twoJ6);
600  if(value == 0) continue;
601  value *= Wigner6J(twoJ3, twoJ6, twoJ9, twoK, twoJ1, twoJ2);
602  if(value == 0) continue;
603  if(twoK % 2) value = -value;
604  sum += value*G4double(twoK+1);
605  }
606  return sum;
607 }
608 
610  G4double cosTheta)
611 {
612  if(twoM < -twoJ || twoM > twoJ || twoN < -twoJ || twoN > twoJ
613  || ((twoM % 2) != (twoJ % 2)) || ((twoN % 2) != (twoJ % 2)))
614  { return 0; }
615 
616  if(cosTheta == 1.0) { return G4double(twoM == twoN); }
617 
618  G4int kMin = 0;
619  if(twoM > twoN) kMin = (twoM-twoN)/2;
620  G4int kMax = (twoJ + twoM)/2;
621  if((twoJ-twoN)/2 < kMax) kMax = (twoJ-twoN)/2;
622 
623  G4double lnCosHalfTheta = G4Log((cosTheta+1.)*0.5) * 0.5;
624  G4double lnSinHalfTheta = G4Log((1.-cosTheta)*0.5) * 0.5;
625 
626  G4Pow* g4pow = G4Pow::GetInstance();
627  G4double d = 0;
628  for(G4int k = kMin; k <= kMax; k++) {
629  G4double logSum = 0.5*(g4pow->logfactorial((twoJ+twoM)/2) +
630  g4pow->logfactorial((twoJ-twoM)/2) +
631  g4pow->logfactorial((twoJ+twoN)/2) +
632  g4pow->logfactorial((twoJ-twoN)/2));
633  logSum += -g4pow->logfactorial((twoJ+twoM)/2 - k) -
634  g4pow->logfactorial((twoJ-twoN)/2 - k) -
635  g4pow->logfactorial(k) -
636  g4pow->logfactorial(k+(twoN-twoM)/2);
637  logSum += (twoJ+(twoM-twoN)/2 - 2*k)*lnCosHalfTheta +
638  (2*k + (twoN-twoM)/2)*lnSinHalfTheta;
639  G4double sign = (k % 2) ? -1 : 1;
640  d += sign * G4Exp(logSum);
641  }
642  return d;
643 }