50 : fVerbose(1), fTwoJ1(0), fTwoJ2(0), fLbar(1), fL(0), fDelta(0),
51 kEps(1.e-15), kPolyPDF(0, nullptr, -1, 1)
58 if(fCoeff == 0)
return 0;
60 if(fCoeff == 0)
return 0;
61 if(((twoJ1+twoJ2)/2 - 1) %2) fCoeff = -fCoeff;
62 return fCoeff*std::sqrt(
G4double((2*K+1)*(twoJ1+1)*(2*LL+1)*(2*Lprime+1)));
70 if(fCoeff == 0)
return 0;
73 if(fCoeff == 0)
return 0;
74 if((Lprime+K2+K1+1) % 2) fCoeff = -fCoeff;
78 return fCoeff*std::sqrt(
G4double((twoJ1+1)*(twoJ2+1)*(2*LL+1))
79 *
G4double((2*Lprime+1)*(2*K+1)*(2*K1+1)*(2*K2+1)));
84 double transFCoeff =
FCoefficient(K, fLbar, fLbar, fTwoJ2, fTwoJ1);
85 if(fDelta == 0)
return transFCoeff;
86 transFCoeff += 2.*fDelta*
FCoefficient(K, fLbar, fL, fTwoJ2, fTwoJ1);
87 transFCoeff += fDelta*fDelta*
FCoefficient(K, fL, fL, fTwoJ2, fTwoJ1);
94 double transF3Coeff =
F3Coefficient(K, K2, K1, fLbar, fLbar, fTwoJ2, fTwoJ1);
95 if(fDelta == 0)
return transF3Coeff;
96 transF3Coeff += 2.*fDelta*
F3Coefficient(K, K2, K1, fLbar, fL, fTwoJ2, fTwoJ1);
97 transF3Coeff += fDelta*fDelta*
F3Coefficient(K, K2, K1, fL, fL, fTwoJ2, fTwoJ1);
101G4double G4PolarizationTransition::GenerateGammaCosTheta(
const POLAR& pol)
103 std::size_t length = pol.size();
109 std::vector<G4double> polyPDFCoeffs(length, 0.0);
111 if ((pol[k]).size() > 0 ) {
112 if(fVerbose > 1 && std::abs(((pol)[k])[0].imag()) > kEps) {
113 G4cout <<
"G4PolarizationTransition::GenerateGammaCosTheta WARNING: \n"
115 << k <<
"][0] has imag component: = "
116 << ((pol)[k])[0].real() <<
" + "
117 << ((pol)[k])[0].imag() <<
"*i" <<
G4endl;
120 std::size_t nCoeff = fgLegendrePolys.GetNCoefficients(k);
121 for(std::size_t iCoeff=0; iCoeff < nCoeff; ++iCoeff) {
122 polyPDFCoeffs[iCoeff] += a_k*fgLegendrePolys.GetCoefficient(iCoeff, k);
125 G4cout <<
"G4PolarizationTransition::GenerateGammaCosTheta: WARNING: \n"
126 <<
" size of pol[" << k <<
"] = " << (pol[k]).size()
127 <<
" returning isotropic " <<
G4endl;
131 if(fVerbose > 1 && polyPDFCoeffs[polyPDFCoeffs.size()-1] == 0) {
132 G4cout <<
"G4PolarizationTransition::GenerateGammaCosTheta: WARNING: "
133 <<
"got zero highest-order coefficient." <<
G4endl;
136 kPolyPDF.SetCoefficients(polyPDFCoeffs);
137 return kPolyPDF.GetRandomX();
145 G4bool phiIsIsotropic =
true;
146 for(
G4int i=0; i<length; ++i) {
147 if(((pol)[i]).size() > 1) {
148 phiIsIsotropic =
false;
155 std::vector<G4double> amp(length, 0.0);
156 std::vector<G4double> phase(length, 0.0);
157 for(
G4int kappa = 0; kappa < length; ++kappa) {
159 for(
G4int k = kappa + (kappa % 2); k < length; k += 2) {
162 if(kappa >= kmax || std::abs(((pol)[k])[kappa]) < kEps) {
continue; }
164 if(tmpAmp == 0) {
continue; }
165 tmpAmp *= std::sqrt((
G4double)(2*k+1))
166 * fgLegendrePolys.EvalAssocLegendrePoly(k, kappa, cosTheta);
167 if(kappa > 0) tmpAmp *= 2.*
G4Exp(0.5*(LnFactorial(k-kappa) - LnFactorial(k+kappa)));
168 cAmpSum += ((pol)[k])[kappa]*tmpAmp;
171 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
172 <<
" size of pol[" << k <<
"] = " << (pol[k]).size()
173 <<
" returning isotropic " <<
G4endl;
178 if(fVerbose > 1 && kappa == 0 && std::abs(cAmpSum.imag()) > kEps) {
179 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
180 <<
" Got complex amp for kappa = 0! A = " << cAmpSum.real()
181 <<
" + " << cAmpSum.imag() <<
"*i" <<
G4endl;
183 amp[kappa] = std::abs(cAmpSum);
184 phase[kappa] = arg(cAmpSum);
190 for(
G4int kappa = 0; kappa < length; ++kappa) { pdfMax += amp[kappa]; }
191 if(fVerbose > 1 && pdfMax < kEps) {
192 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING "
193 <<
"got pdfMax = 0 for \n";
195 G4cout <<
"I suspect a non-allowed transition! Returning isotropic phi..."
201 for(std::size_t i=0; i<100; ++i) {
205 for(
G4int kappa = 1; kappa < length; ++kappa) {
206 pdfSum += amp[kappa]*std::cos(phi*kappa + phase[kappa]);
208 if(fVerbose > 1 && pdfSum > pdfMax) {
209 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
210 <<
"got pdfSum (" << pdfSum <<
") > pdfMax ("
211 << pdfMax <<
") at phi = " << phi <<
G4endl;
213 if(prob <= pdfSum) {
return phi; }
216 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
217 <<
"no phi generated in 1000 throws! Returning isotropic phi..."
229 if(nucpol ==
nullptr) {
231 G4cout <<
"G4PolarizationTransition::SampleGammaTransition ERROR: "
232 <<
"cannot update NULL nuclear polarization" <<
G4endl;
242 G4cout <<
"G4PolarizationTransition: 2J1= " << fTwoJ1 <<
" 2J2= " << fTwoJ2
243 <<
" Lbar= " << fLbar <<
" delta= " << fDelta <<
" Lp= " << fL
256 cosTheta = GenerateGammaCosTheta(pol);
257 phi = GenerateGammaPhi(cosTheta, pol);
259 G4cout <<
"G4PolarizationTransition::SampleGammaTransition: cosTheta= "
260 << cosTheta <<
" phi= " << phi <<
G4endl;
269 std::size_t newlength = fTwoJ2+1;
274 std::vector<G4complex> npolar;
275 npolar.resize(k2+1, 0);
278 for(
G4int k=0; k<=k1+k2; k+=2) {
284 for(
G4int kappa2=0; kappa2<=k2; ++kappa2) {
286 for(
G4int kappa1 = 1 - ll; kappa1<ll; ++kappa1) {
287 if(k+k2<k1 || k+k1<k2)
continue;
289 conj((pol[k1])[-kappa1])*(kappa1 % 2 ? -1.: 1.) : (pol[k1])[kappa1];
290 if(std::abs(tmpAmp) < kEps)
continue;
293 if(std::abs(tmpAmp) < kEps)
continue;
298 if(std::abs(tF3) < kEps)
break;
300 if(std::abs(tmpAmp) < kEps)
continue;
301 tmpAmp *= ((kappa1+(
G4int)k1)%2 ? -1. : 1.)
302 * sqrt((2.*k+1.)*(2.*k1+1.)/(2.*k2+1.));
306 tmpAmp *= fgLegendrePolys.EvalAssocLegendrePoly(k, kappa, cosTheta);
308 tmpAmp *=
G4Exp(0.5*(LnFactorial(((
G4int)k)-kappa)
309 - LnFactorial(((
G4int)k)+kappa)));
310 tmpAmp *= polar(1., phi*kappa);
312 npolar[kappa2] += tmpAmp;
314 if(!recalcTF3 && std::abs(tF3) < kEps)
break;
318 newPol.push_back(std::move(npolar));
322 if(fVerbose > 2 && 0.0 == newPol[0][0]) {
323 G4cout <<
"G4PolarizationTransition::SampleGammaTransition WARNING:"
324 <<
" P[0][0] is zero!" <<
G4endl;
331 if(fVerbose > 2 && std::abs((newPol[0])[0].imag()) > kEps) {
332 G4cout <<
"G4PolarizationTransition::SampleGammaTransition WARNING: \n"
333 <<
" P[0][0] has a non-zero imaginary part! Unpolarizing..."
343 std::size_t lastNonEmptyK2 = 0;
344 for(std::size_t k2=0; k2<newlength; ++k2) {
345 G4int lastNonZero = -1;
346 for(std::size_t kappa2=0; kappa2<(newPol[k2]).size(); ++kappa2) {
347 if(k2 == 0 && kappa2 == 0) {
351 if(std::abs((newPol[k2])[kappa2]) > 0.0) {
352 lastNonZero = (
G4int)kappa2;
353 (newPol[k2])[kappa2] /= (newPol[0])[0];
356 while((newPol[k2]).size() != std::size_t (lastNonZero+1)) (newPol[k2]).pop_back();
357 if((newPol[k2]).size() > 0) lastNonEmptyK2 = k2;
361 while(newPol.size() != lastNonEmptyK2+1) { newPol.pop_back(); }
362 (newPol[0])[0] = 1.0;
366 G4cout <<
"Updated polarization: " << *nucpol <<
G4endl;
372 G4cout <<
"G4PolarizationTransition: ";
373 (fTwoJ1 % 2) ?
G4cout << fTwoJ1 <<
"/2" :
G4cout << fTwoJ1/2;
374 G4cout <<
" --(" << fLbar;
375 if(fDelta != 0)
G4cout <<
" + " << fDelta <<
"*" << fL;
377 (fTwoJ2 % 2) ?
G4cout << fTwoJ2 <<
"/2" :
G4cout << fTwoJ2/2;
379 for(std::size_t k=0; k<pol.size(); ++k) {
380 if(k>0)
G4cout <<
" }, { ";
381 for(std::size_t kappa=0; kappa<(pol[k]).size(); ++kappa) {
382 if(kappa > 0)
G4cout <<
", ";
383 G4cout << (pol[k])[kappa].real() <<
" + " << (pol[k])[kappa].imag() <<
"*i";
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
std::complex< G4double > G4complex
G4GLOB_DLL std::ostream G4cout
static G4double Wigner3J(G4double j1, G4double j2, G4double j3, G4double m1, G4double m2, G4double m3)
static G4double Wigner6J(G4int twoJ1, G4int twoJ2, G4int twoJ3, G4int twoJ4, G4int twoJ5, G4int twoJ6)
static G4double Wigner9J(G4int twoJ1, G4int twoJ2, G4int twoJ3, G4int twoJ4, G4int twoJ5, G4int twoJ6, G4int twoJ7, G4int twoJ8, G4int twoJ9)
std::vector< std::vector< G4complex > > & GetPolarization()
void SetPolarization(std::vector< std::vector< G4complex > > &p)
void DumpTransitionData(const POLAR &pol) const
void SampleGammaTransition(G4NuclearPolarization *np, G4int twoJ1, G4int twoJ2, G4int L0, G4int Lp, G4double mpRatio, G4double &cosTheta, G4double &phi)
G4double F3Coefficient(G4int K, G4int K2, G4int K1, G4int L, G4int Lprime, G4int twoJ2, G4int twoJ1) const
G4PolarizationTransition()
G4double FCoefficient(G4int K, G4int L, G4int Lprime, G4int twoJ2, G4int twoJ1) const
G4double GammaTransF3Coefficient(G4int K, G4int K2, G4int K1) const
G4double GammaTransFCoefficient(G4int K) const