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 size_t length = pol.size();
112 vector<G4double> polyPDFCoeffs(length, 0.0);
113 for(
size_t k = 0; k < length; k += 2) {
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(
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;
146 size_t length = pol.size();
148 G4bool phiIsIsotropic =
true;
149 for(
size_t i=0; i<length; ++i) {
150 if(((pol)[i]).size() > 1) {
151 phiIsIsotropic =
false;
158 map<G4int, map<G4int, G4double> >* cachePtr =
nullptr;
163 std::vector<G4double> amp(length, 0.0);
164 std::vector<G4double> phase(length, 0.0);
165 for(
size_t kappa = 0; kappa < length; ++kappa) {
167 for(
size_t k = kappa + (kappa % 2); k < length; k += 2) {
168 size_t kmax = (pol[k]).size();
170 if(kappa >= kmax || std::abs(((pol)[k])[kappa]) < kEps) {
continue; }
172 if(tmpAmp == 0) {
continue; }
173 tmpAmp *= std::sqrt((
G4double)(2*k+1))
175 if(kappa > 0) tmpAmp *= 2.*
G4Exp(0.5*(LnFactorial(k-kappa) - LnFactorial(k+kappa)));
176 cAmpSum += ((pol)[k])[kappa]*tmpAmp;
179 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
180 <<
" size of pol[" << k <<
"] = " << (pol[k]).size()
181 <<
" returning isotropic " <<
G4endl;
186 if(fVerbose > 1 && kappa == 0 && std::abs(cAmpSum.imag()) > kEps) {
187 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
188 <<
" Got complex amp for kappa = 0! A = " << cAmpSum.real()
189 <<
" + " << cAmpSum.imag() <<
"*i" <<
G4endl;
191 amp[kappa] = std::abs(cAmpSum);
192 phase[kappa] = arg(cAmpSum);
198 for(
size_t kappa = 0; kappa < length; ++kappa) { pdfMax += amp[kappa]; }
199 if(fVerbose > 1 && pdfMax < kEps) {
200 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING "
201 <<
"got pdfMax = 0 for \n";
203 G4cout <<
"I suspect a non-allowed transition! Returning isotropic phi..."
209 for(
size_t i=0; i<100; ++i) {
213 for(
size_t kappa = 1; kappa < length; ++kappa) {
214 pdfSum += amp[kappa]*std::cos(phi*kappa + phase[kappa]);
216 if(fVerbose > 1 && pdfSum > pdfMax) {
217 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
218 <<
"got pdfSum (" << pdfSum <<
") > pdfMax ("
219 << pdfMax <<
") at phi = " << phi <<
G4endl;
221 if(prob <= pdfSum) {
return phi; }
224 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
225 <<
"no phi generated in 1000 throws! Returning isotropic phi..."
237 if(nucpol ==
nullptr) {
239 G4cout <<
"G4PolarizationTransition::SampleGammaTransition ERROR: "
240 <<
"cannot update NULL nuclear polarization" <<
G4endl;
250 G4cout <<
"G4PolarizationTransition: 2J1= " << fTwoJ1 <<
" 2J2= " << fTwoJ2
251 <<
" Lbar= " << fLbar <<
" delta= " << fDelta <<
" Lp= " << fL
265 cosTheta = GenerateGammaCosTheta(pol);
267 G4cout <<
"G4PolarizationTransition::SampleGammaTransition: cosTheta= "
270 phi = GenerateGammaPhi(cosTheta, pol);
272 G4cout <<
"G4PolarizationTransition::SampleGammaTransition: phi= "
281 size_t newlength = fTwoJ2+1;
286 map<G4int, map<G4int, G4double> >* cachePtr =
nullptr;
289 for(
size_t k2=0; k2<newlength; ++k2) {
290 std::vector<G4complex> npolar;
291 npolar.resize(k2+1, 0);
293 for(
size_t k1=0; k1<pol.size(); ++k1) {
294 for(
size_t k=0; k<=k1+k2; k+=2) {
300 for(
size_t kappa2=0; kappa2<=k2; ++kappa2) {
301 G4int ll = (pol[k1]).size();
302 for(
G4int kappa1 = 1 - ll; kappa1<ll; ++kappa1) {
303 if(k+k2<k1 || k+k1<k2)
continue;
305 conj((pol[k1])[-kappa1])*(kappa1 % 2 ? -1.: 1.) : (pol[k1])[kappa1];
306 if(std::abs(tmpAmp) < kEps)
continue;
309 if(std::abs(tmpAmp) < kEps)
continue;
314 if(std::abs(tF3) < kEps)
break;
316 if(std::abs(tmpAmp) < kEps)
continue;
317 tmpAmp *= ((kappa1+(
G4int)k1)%2 ? -1. : 1.)
318 * sqrt((2.*k+1.)*(2.*k1+1.)/(2.*k2+1.));
324 tmpAmp *=
G4Exp(0.5*(LnFactorial(((
G4int)k)-kappa)
325 - LnFactorial(((
G4int)k)+kappa)));
326 tmpAmp *= polar(1., phi*kappa);
329 npolar[kappa2] += tmpAmp;
331 if(!recalcTF3 && std::abs(tF3) < kEps)
break;
335 newPol.push_back(npolar);
339 if(fVerbose > 2 && 0.0 == newPol[0][0]) {
340 G4cout <<
"G4PolarizationTransition::SampleGammaTransition WARNING:"
341 <<
" P[0][0] is zero!" <<
G4endl;
348 if(fVerbose > 2 && std::abs((newPol[0])[0].imag()) > kEps) {
349 G4cout <<
"G4PolarizationTransition::SampleGammaTransition WARNING: \n"
350 <<
" P[0][0] has a non-zero imaginary part! Unpolarizing..."
360 size_t lastNonEmptyK2 = 0;
361 for(
size_t k2=0; k2<newlength; ++k2) {
362 G4int lastNonZero = -1;
363 for(
size_t kappa2=0; kappa2<(newPol[k2]).size(); ++kappa2) {
364 if(k2 == 0 && kappa2 == 0) {
368 if(std::abs((newPol[k2])[kappa2]) > 0.0) {
369 lastNonZero = kappa2;
370 (newPol[k2])[kappa2] /= (newPol[0])[0];
373 while((newPol[k2]).size() != size_t (lastNonZero+1)) (newPol[k2]).pop_back();
374 if((newPol[k2]).size() > 0) lastNonEmptyK2 = k2;
378 while(newPol.size() != lastNonEmptyK2+1) { newPol.pop_back(); }
379 (newPol[0])[0] = 1.0;
383 G4cout <<
"Updated polarization: " << *nucpol <<
G4endl;
389 G4cout <<
"G4PolarizationTransition: ";
390 (fTwoJ1 % 2) ?
G4cout << fTwoJ1 <<
"/2" :
G4cout << fTwoJ1/2;
391 G4cout <<
" --(" << fLbar;
392 if(fDelta != 0)
G4cout <<
" + " << fDelta <<
"*" << fL;
394 (fTwoJ2 % 2) ?
G4cout << fTwoJ2 <<
"/2" :
G4cout << fTwoJ2/2;
396 for(
size_t k=0; k<pol.size(); ++k) {
397 if(k>0)
G4cout <<
" }, { ";
398 for(
size_t kappa=0; kappa<(pol[k]).size(); ++kappa) {
399 if(kappa > 0)
G4cout <<
", ";
400 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)