50 : fVerbose(1), fTwoJ1(0), fTwoJ2(0), fLbar(1), fL(0), fDelta(0),
51 kEps(1.e-15), kPolyPDF(0, nullptr, -1, 1)
61 if(fCoeff == 0)
return 0;
63 if(fCoeff == 0)
return 0;
64 if(((twoJ1+twoJ2)/2 - 1) %2) fCoeff = -fCoeff;
65 return fCoeff*std::sqrt(
G4double((2*K+1)*(twoJ1+1)*(2*LL+1)*(2*Lprime+1)));
73 if(fCoeff == 0)
return 0;
76 if(fCoeff == 0)
return 0;
77 if((Lprime+K2+K1+1) % 2) fCoeff = -fCoeff;
81 return fCoeff*std::sqrt(
G4double((twoJ1+1)*(twoJ2+1)*(2*LL+1))
82 *
G4double((2*Lprime+1)*(2*K+1)*(2*K1+1)*(2*K2+1)));
87 double transFCoeff =
FCoefficient(K, fLbar, fLbar, fTwoJ2, fTwoJ1);
88 if(fDelta == 0)
return transFCoeff;
89 transFCoeff += 2.*fDelta*
FCoefficient(K, fLbar, fL, fTwoJ2, fTwoJ1);
90 transFCoeff += fDelta*fDelta*
FCoefficient(K, fL, fL, fTwoJ2, fTwoJ1);
97 double transF3Coeff =
F3Coefficient(K, K2, K1, fLbar, fLbar, fTwoJ2, fTwoJ1);
98 if(fDelta == 0)
return transF3Coeff;
99 transF3Coeff += 2.*fDelta*
F3Coefficient(K, K2, K1, fLbar, fL, fTwoJ2, fTwoJ1);
100 transF3Coeff += fDelta*fDelta*
F3Coefficient(K, K2, K1, fL, fL, fTwoJ2, fTwoJ1);
104G4double G4PolarizationTransition::GenerateGammaCosTheta(
const POLAR& pol)
106 std::size_t length = pol.size();
112 vector<G4double> polyPDFCoeffs(length, 0.0);
114 if ((pol[k]).size() > 0 ) {
115 if(fVerbose > 1 && std::abs(((pol)[k])[0].imag()) > kEps) {
116 G4cout <<
"G4PolarizationTransition::GenerateGammaCosTheta WARNING: \n"
118 << k <<
"][0] has imag component: = "
119 << ((pol)[k])[0].real() <<
" + "
120 << ((pol)[k])[0].imag() <<
"*i" <<
G4endl;
124 for(std::size_t iCoeff=0; iCoeff < nCoeff; ++iCoeff) {
125 polyPDFCoeffs[iCoeff] += a_k*fgLegendrePolys.
GetCoefficient(iCoeff, k);
128 G4cout <<
"G4PolarizationTransition::GenerateGammaCosTheta: WARNING: \n"
129 <<
" size of pol[" << k <<
"] = " << (pol[k]).size()
130 <<
" returning isotropic " <<
G4endl;
134 if(fVerbose > 1 && polyPDFCoeffs[polyPDFCoeffs.size()-1] == 0) {
135 G4cout <<
"G4PolarizationTransition::GenerateGammaCosTheta: WARNING: "
136 <<
"got zero highest-order coefficient." <<
G4endl;
148 G4bool phiIsIsotropic =
true;
149 for(
G4int i=0; i<length; ++i) {
150 if(((pol)[i]).size() > 1) {
151 phiIsIsotropic =
false;
157 map<G4int, map<G4int, G4double> >* cachePtr =
nullptr;
161 std::vector<G4double> amp(length, 0.0);
162 std::vector<G4double> phase(length, 0.0);
163 for(
G4int kappa = 0; kappa < length; ++kappa) {
165 for(
G4int k = kappa + (kappa % 2); k < length; k += 2) {
168 if(kappa >= kmax || std::abs(((pol)[k])[kappa]) < kEps) {
continue; }
170 if(tmpAmp == 0) {
continue; }
171 tmpAmp *= std::sqrt((
G4double)(2*k+1))
173 if(kappa > 0) tmpAmp *= 2.*
G4Exp(0.5*(LnFactorial(k-kappa) - LnFactorial(k+kappa)));
174 cAmpSum += ((pol)[k])[kappa]*tmpAmp;
177 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
178 <<
" size of pol[" << k <<
"] = " << (pol[k]).size()
179 <<
" returning isotropic " <<
G4endl;
184 if(fVerbose > 1 && kappa == 0 && std::abs(cAmpSum.imag()) > kEps) {
185 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
186 <<
" Got complex amp for kappa = 0! A = " << cAmpSum.real()
187 <<
" + " << cAmpSum.imag() <<
"*i" <<
G4endl;
189 amp[kappa] = std::abs(cAmpSum);
190 phase[kappa] = arg(cAmpSum);
196 for(
G4int kappa = 0; kappa < length; ++kappa) { pdfMax += amp[kappa]; }
197 if(fVerbose > 1 && pdfMax < kEps) {
198 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING "
199 <<
"got pdfMax = 0 for \n";
201 G4cout <<
"I suspect a non-allowed transition! Returning isotropic phi..."
207 for(std::size_t i=0; i<100; ++i) {
211 for(
G4int kappa = 1; kappa < length; ++kappa) {
212 pdfSum += amp[kappa]*std::cos(phi*kappa + phase[kappa]);
214 if(fVerbose > 1 && pdfSum > pdfMax) {
215 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
216 <<
"got pdfSum (" << pdfSum <<
") > pdfMax ("
217 << pdfMax <<
") at phi = " << phi <<
G4endl;
219 if(prob <= pdfSum) {
return phi; }
222 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
223 <<
"no phi generated in 1000 throws! Returning isotropic phi..."
235 if(nucpol ==
nullptr) {
237 G4cout <<
"G4PolarizationTransition::SampleGammaTransition ERROR: "
238 <<
"cannot update NULL nuclear polarization" <<
G4endl;
248 G4cout <<
"G4PolarizationTransition: 2J1= " << fTwoJ1 <<
" 2J2= " << fTwoJ2
249 <<
" Lbar= " << fLbar <<
" delta= " << fDelta <<
" Lp= " << fL
262 cosTheta = GenerateGammaCosTheta(pol);
264 G4cout <<
"G4PolarizationTransition::SampleGammaTransition: cosTheta= "
267 phi = GenerateGammaPhi(cosTheta, pol);
269 G4cout <<
"G4PolarizationTransition::SampleGammaTransition: phi= "
279 std::size_t newlength = fTwoJ2+1;
284 map<G4int, map<G4int, G4double> >* cachePtr =
nullptr;
288 std::vector<G4complex> npolar;
289 npolar.resize(k2+1, 0);
292 for(
G4int k=0; k<=k1+k2; k+=2) {
298 for(
G4int kappa2=0; kappa2<=k2; ++kappa2) {
300 for(
G4int kappa1 = 1 - ll; kappa1<ll; ++kappa1) {
301 if(k+k2<k1 || k+k1<k2)
continue;
303 conj((pol[k1])[-kappa1])*(kappa1 % 2 ? -1.: 1.) : (pol[k1])[kappa1];
304 if(std::abs(tmpAmp) < kEps)
continue;
307 if(std::abs(tmpAmp) < kEps)
continue;
312 if(std::abs(tF3) < kEps)
break;
314 if(std::abs(tmpAmp) < kEps)
continue;
315 tmpAmp *= ((kappa1+(
G4int)k1)%2 ? -1. : 1.)
316 * sqrt((2.*k+1.)*(2.*k1+1.)/(2.*k2+1.));
322 tmpAmp *=
G4Exp(0.5*(LnFactorial(((
G4int)k)-kappa)
323 - LnFactorial(((
G4int)k)+kappa)));
324 tmpAmp *= polar(1., phi*kappa);
327 npolar[kappa2] += tmpAmp;
329 if(!recalcTF3 && std::abs(tF3) < kEps)
break;
333 newPol.push_back(npolar);
337 if(fVerbose > 2 && 0.0 == newPol[0][0]) {
338 G4cout <<
"G4PolarizationTransition::SampleGammaTransition WARNING:"
339 <<
" P[0][0] is zero!" <<
G4endl;
346 if(fVerbose > 2 && std::abs((newPol[0])[0].imag()) > kEps) {
347 G4cout <<
"G4PolarizationTransition::SampleGammaTransition WARNING: \n"
348 <<
" P[0][0] has a non-zero imaginary part! Unpolarizing..."
358 std::size_t lastNonEmptyK2 = 0;
359 for(std::size_t k2=0; k2<newlength; ++k2) {
360 G4int lastNonZero = -1;
361 for(std::size_t kappa2=0; kappa2<(newPol[k2]).size(); ++kappa2) {
362 if(k2 == 0 && kappa2 == 0) {
366 if(std::abs((newPol[k2])[kappa2]) > 0.0) {
367 lastNonZero = (
G4int)kappa2;
368 (newPol[k2])[kappa2] /= (newPol[0])[0];
371 while((newPol[k2]).size() != std::size_t (lastNonZero+1)) (newPol[k2]).pop_back();
372 if((newPol[k2]).size() > 0) lastNonEmptyK2 = k2;
376 while(newPol.size() != lastNonEmptyK2+1) { newPol.pop_back(); }
377 (newPol[0])[0] = 1.0;
381 G4cout <<
"Updated polarization: " << *nucpol <<
G4endl;
387 G4cout <<
"G4PolarizationTransition: ";
388 (fTwoJ1 % 2) ?
G4cout << fTwoJ1 <<
"/2" :
G4cout << fTwoJ1/2;
389 G4cout <<
" --(" << fLbar;
390 if(fDelta != 0)
G4cout <<
" + " << fDelta <<
"*" << fL;
392 (fTwoJ2 % 2) ?
G4cout << fTwoJ2 <<
"/2" :
G4cout << fTwoJ2/2;
394 for(std::size_t k=0; k<pol.size(); ++k) {
395 if(k>0)
G4cout <<
" }, { ";
396 for(std::size_t kappa=0; kappa<(pol[k]).size(); ++kappa) {
397 if(kappa > 0)
G4cout <<
", ";
398 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)
G4double EvalAssocLegendrePoly(G4int l, G4int m, G4double x, std::map< G4int, std::map< G4int, G4double > > *cache=NULL)
G4double GetCoefficient(size_t i, size_t order)
static size_t GetNCoefficients(size_t order)
std::vector< std::vector< G4complex > > & GetPolarization()
void SetPolarization(std::vector< std::vector< G4complex > > &p)
void DumpTransitionData(const POLAR &pol) const
~G4PolarizationTransition()
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
void SetCoefficients(const std::vector< G4double > &v)