50 : fVerbose(0), fTwoJ1(0), fTwoJ2(0), fLbar(1), fL(0), fDelta(0), kEps(1.
e-15),
51 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)));
88 if(
fDelta == 0)
return transFCoeff;
98 if(
fDelta == 0)
return transF3Coeff;
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(std::abs(((pol)[k])[0].imag()) >
kEps &&
fVerbose > 0) {
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) {
128 G4cout <<
"G4PolarizationTransition::GenerateGammaCosTheta: WARNING: \n"
129 <<
" size of pol[" << k <<
"] = " << (pol[k]).size()
130 <<
" returning isotropic " <<
G4endl;
134 if(polyPDFCoeffs[polyPDFCoeffs.size()-1] == 0 &&
fVerbose > 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))
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(kappa == 0 && std::abs(cAmpSum.imag()) >
kEps &&
fVerbose > 0) {
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(pdfMax < kEps && fVerbose > 0) {
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(pdfSum > pdfMax &&
fVerbose > 0) {
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..." <<
G4endl;
236 if(nucpol ==
nullptr) {
238 G4cout <<
"G4PolarizationTransition::SampleGammaTransition ERROR: "
239 <<
"cannot update NULL nuclear polarization" <<
G4endl;
265 G4cout <<
"G4PolarizationTransition::SampleGammaTransition: cosTheta= "
270 G4cout <<
"G4PolarizationTransition::SampleGammaTransition: phi= "
279 size_t newlength =
fTwoJ2+1;
284 map<G4int, map<G4int, G4double> >* cachePtr =
nullptr;
287 for(
size_t k2=0; k2<newlength; ++k2) {
288 std::vector<G4complex> npolar;
289 npolar.resize(k2+1, 0);
291 for(
size_t k1=0; k1<pol.size(); ++k1) {
292 for(
size_t k=0; k<=k1+k2; k+=2) {
298 for(
size_t kappa2=0; kappa2<=k2; ++kappa2) {
299 G4int ll = (pol[k1]).size();
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.));
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(0.0 == newPol[0][0] &&
fVerbose > 1) {
338 G4cout <<
"G4PolarizationTransition::SampleGammaTransition WARNING:"
339 <<
" P[0][0] is zero!" <<
G4endl;
346 if(std::abs((newPol[0])[0].imag()) >
kEps &&
fVerbose > 1) {
347 G4cout <<
"G4PolarizationTransition::SampleGammaTransition WARNING: \n"
348 <<
" P[0][0] has a non-zero imaginary part! Unpolarizing..."
358 size_t lastNonEmptyK2 = 0;
359 for(
size_t k2=0; k2<newlength; ++k2) {
360 G4int lastNonZero = -1;
361 for(
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 = kappa2;
368 (newPol[k2])[kappa2] /= (newPol[0])[0];
371 while((newPol[k2]).size() != 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: ";
394 for(
size_t k=0; k<pol.size(); ++k) {
395 if(k>0)
G4cout <<
" }, { ";
396 for(
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";
~G4PolarizationTransition()
G4double LnFactorial(int k) const
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
static const G4int LL[nN]
void SampleGammaTransition(G4NuclearPolarization *np, G4int twoJ1, G4int twoJ2, G4int L0, G4int Lp, G4double mpRatio, G4double &cosTheta, G4double &phi)
G4double FCoefficient(G4int K, G4int L, G4int Lprime, G4int twoJ2, G4int twoJ1) const
G4double EvalAssocLegendrePoly(G4int l, G4int m, G4double x, std::map< G4int, std::map< G4int, G4double > > *cache=NULL)
static size_t GetNCoefficients(size_t order)
std::vector< std::vector< G4complex > > POLAR
std::complex< G4double > G4complex
G4double GammaTransF3Coefficient(G4int K, G4int K2, G4int K1) const
G4double GenerateGammaCosTheta(const POLAR &)
static constexpr double twopi
G4double GenerateGammaPhi(G4double &cosTheta, const POLAR &)
void SetCoefficients(const std::vector< G4double > &v)
G4double F3Coefficient(G4int K, G4int K2, G4int K1, G4int L, G4int Lprime, G4int twoJ2, G4int twoJ1) const
G4GLOB_DLL std::ostream G4cout
G4LegendrePolynomial fgLegendrePolys
static G4double Wigner9J(G4int twoJ1, G4int twoJ2, G4int twoJ3, G4int twoJ4, G4int twoJ5, G4int twoJ6, G4int twoJ7, G4int twoJ8, G4int twoJ9)
static G4double Wigner3J(G4double j1, G4double j2, G4double j3, G4double m1, G4double m2, G4double m3)
std::vector< std::vector< G4complex > > & GetPolarization()
G4double GammaTransFCoefficient(G4int K) const
void DumpTransitionData(const POLAR &pol) const
void SetPolarization(std::vector< std::vector< G4complex > > &p)
G4double GetCoefficient(size_t i, size_t order)
static G4double Wigner6J(G4int twoJ1, G4int twoJ2, G4int twoJ3, G4int twoJ4, G4int twoJ5, G4int twoJ6)
G4PolarizationTransition()