Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/util/src/G4Clebsch.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /processes/hadronic/util/src/G4Clebsch.cc (Version 11.3.0) and /processes/hadronic/util/src/G4Clebsch.cc (Version 11.2.2)


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