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*sqrt((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;
78 return fCoeff*sqrt((twoJ1+1)*(twoJ2+1)*(2*LL+1)*(2*Lprime+1)*(2*K+1)*(2*K1+1)*(2*K2+1));
85 fTwoJ1 = std::abs(twoJ1);
86 fTwoJ2 = std::abs(twoJ2);
91 G4cout <<
"SET G4PolarizationTransition: J1= " << fTwoJ1 <<
" J2= " << fTwoJ2
92 <<
" Lbar= " << fLbar <<
" delta= " << fDelta <<
" Lp= " << fL <<
G4endl;
98 double transFCoeff =
FCoefficient(K, fLbar, fLbar, fTwoJ2, fTwoJ1);
99 if(fDelta == 0)
return transFCoeff;
100 transFCoeff += 2.*fDelta*
FCoefficient(K, fLbar, fL, fTwoJ2, fTwoJ1);
101 transFCoeff += fDelta*fDelta*
FCoefficient(K, fL, fL, fTwoJ2, fTwoJ1);
108 double transF3Coeff =
F3Coefficient(K, K2, K1, fLbar, fLbar, fTwoJ2, fTwoJ1);
109 if(fDelta == 0)
return transF3Coeff;
110 transF3Coeff += 2.*fDelta*
F3Coefficient(K, K2, K1, fLbar, fL, fTwoJ2, fTwoJ1);
111 transF3Coeff += fDelta*fDelta*
F3Coefficient(K, K2, K1, fL, fL, fTwoJ2, fTwoJ1);
117 size_t length = pol.size();
123 vector<G4double> polyPDFCoeffs(length, 0.0);
124 for(
size_t k = 0; k < length; k += 2) {
125 if(std::abs(((pol)[k])[0].imag()) > kEps && fVerbose > 0) {
126 G4cout <<
"G4PolarizationTransition::GenerateGammaCosTheta WARNING: \n"
128 << k <<
"][0] has imag component: = "
129 << ((pol)[k])[0].real() <<
" + "
130 << ((pol)[k])[0].imag() <<
"*i" <<
G4endl;
133 for(
size_t iCoeff=0; iCoeff < fgLegendrePolys.
GetNCoefficients(k); ++iCoeff) {
134 polyPDFCoeffs[iCoeff] += a_k*fgLegendrePolys.
GetCoefficient(iCoeff, k);
144 size_t length = pol.size();
146 G4bool phiIsIsotropic =
true;
147 for(
size_t i=0; i<length; ++i) {
148 if(((pol)[i]).size() > 1) {
149 phiIsIsotropic =
false;
157 std::vector<G4double> amp(length, 0.0);
158 std::vector<G4double> phase(length, 0.0);
159 for(
size_t kappa = 0; kappa < length; ++kappa) {
161 for(
size_t k = kappa + (kappa % 2); k < length; k += 2) {
162 if(kappa >= length || std::abs(((pol)[k])[kappa]) < kEps) {
continue; }
164 if(tmpAmp == 0) {
continue; }
166 if(kappa > 0) tmpAmp *= 2.*
G4Exp(0.5*(LnFactorial(k-kappa) - LnFactorial(k+kappa)));
167 cAmpSum += ((pol)[k])[kappa]*tmpAmp;
169 if(kappa == 0 && std::abs(cAmpSum.imag()) > kEps && fVerbose > 0) {
170 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
171 <<
" Got complex amp for kappa = 0! A = " << cAmpSum.real()
172 <<
" + " << cAmpSum.imag() <<
"*i" <<
G4endl;
174 amp[kappa] = std::abs(cAmpSum);
175 phase[kappa] = arg(cAmpSum);
181 for(
size_t kappa = 0; kappa < amp.size(); ++kappa) { pdfMax += amp[kappa]; }
182 if(pdfMax < kEps && fVerbose > 0) {
183 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING "
184 <<
"got pdfMax = 0 for \n";
186 G4cout <<
"I suspect a non-allowed transition! Returning isotropic phi..."
192 for(
size_t i=0; i<1000; ++i) {
196 for(
size_t kappa = 1; kappa < amp.size(); ++kappa) {
197 pdfSum += amp[kappa]*cos(phi*kappa + phase[kappa]);
199 if(prob < pdfSum)
return phi;
200 if(pdfSum > pdfMax && fVerbose > 0) {
201 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
202 <<
"got pdfSum (" << pdfSum <<
") > pdfMax ("
203 << pdfMax <<
") at phi = " << phi <<
G4endl;
207 G4cout <<
"G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
208 <<
"no phi generated in 1000 throws! Returning isotropic phi..." <<
G4endl;
218 if(nucpol ==
nullptr) {
220 G4cout <<
"G4PolarizationTransition::UpdatePolarizationToFinalState ERROR: "
221 <<
"cannot update NULL nuclear polarization" <<
G4endl;
232 size_t newlength = fTwoJ2+1;
233 POLAR newPol(newlength);
235 for(
size_t k2=0; k2<newlength; ++k2) {
236 (newPol[k2]).assign(k2+1, 0);
237 for(
size_t k1=0; k1<pol.size(); ++k1) {
238 for(
size_t k=0; k<=k1+k2; k+=2) {
244 for(
size_t kappa2=0; kappa2<=k2; ++kappa2) {
245 G4int ll = (pol[k1]).size();
246 for(
G4int kappa1 = 1 - ll; kappa1<ll; ++kappa1) {
247 if(k+k2<k1 || k+k1<k2)
continue;
249 conj((pol[k1])[-kappa1])*(kappa1 % 2 ? -1.: 1.) : (pol[k1])[kappa1];
250 if(std::abs(tmpAmp) < kEps)
continue;
253 if(std::abs(tmpAmp) < kEps)
continue;
258 if(std::abs(tF3) < kEps)
break;
260 if(std::abs(tmpAmp) < kEps)
continue;
261 tmpAmp *= ((kappa1+(
G4int)k1)%2 ? -1. : 1.)
262 * sqrt((2.*k+1.)*(2.*k1+1.)/(2.*k2+1.));
265 tmpAmp *=
G4Exp(0.5*(LnFactorial(((
G4int)k)-kappa)
266 - LnFactorial(((
G4int)k)+kappa)));
267 tmpAmp *= polar(1., phi*kappa);
269 (newPol[k2])[kappa2] += tmpAmp;
271 if(!recalcTF3 && std::abs(tF3) < kEps)
break;
278 if(0.0 == newPol[0][0] && fVerbose > 1) {
279 G4cout <<
"G4PolarizationTransition::UpdatePolarizationToFinalState WARNING:"
280 <<
" P[0][0] is zero!" <<
G4endl;
287 if(std::abs((newPol[0])[0].imag()) > kEps && fVerbose > 1) {
288 G4cout <<
"G4PolarizationTransition::UpdatePolarizationToFinalState WARNING: \n"
289 <<
" P[0][0] has a non-zero imaginary part! Unpolarizing..." <<
G4endl;
295 size_t lastNonEmptyK2 = 0;
296 for(
size_t k2=0; k2<newlength; ++k2) {
297 G4int lastNonZero = -1;
298 for(
size_t kappa2=0; kappa2<(newPol[k2]).size(); ++kappa2) {
299 if(k2 == 0 && kappa2 == 0) {
303 if(std::abs((newPol[k2])[kappa2]) > 0.0) {
304 lastNonZero = kappa2;
305 (newPol[k2])[kappa2] /= (newPol[0])[0];
308 while((newPol[k2]).size() != size_t (lastNonZero+1)) (newPol[k2]).pop_back();
309 if((newPol[k2]).size() > 0) lastNonEmptyK2 = k2;
313 while(newPol.size() != lastNonEmptyK2+1) { newPol.pop_back(); }
314 (newPol[0])[0] = 1.0;
321 G4cout <<
"G4PolarizationTransition: ";
322 (fTwoJ1 % 2) ?
G4cout << fTwoJ1 <<
"/2" :
G4cout << fTwoJ1/2;
323 G4cout <<
" --(" << fLbar;
324 if(fDelta != 0)
G4cout <<
" + " << fDelta <<
"*" << fL;
326 (fTwoJ2 % 2) ?
G4cout << fTwoJ2 <<
"/2" :
G4cout << fTwoJ2/2;
328 for(
size_t k=0; k<pol.size(); ++k) {
329 if(k>0)
G4cout <<
" }, { ";
330 for(
size_t kappa=0; kappa<(pol[k]).size(); ++kappa) {
331 if(kappa > 0)
G4cout <<
", ";
332 G4cout << (pol[k])[kappa].real() <<
" + " << (pol[k])[kappa].imag() <<
"*i";
G4double FCoefficient(G4int K, G4int L, G4int Lprime, G4int twoJ2, G4int twoJ1) const
void SetCoefficients(const std::vector< G4double > &v)
G4double GenerateGammaPhi(G4double cosTheta, const POLAR &)
G4double GammaTransF3Coefficient(G4int K, G4int K2, G4int K1) const
static size_t GetNCoefficients(size_t order)
G4double GenerateGammaCosTheta(const POLAR &)
std::complex< G4double > G4complex
G4GLOB_DLL std::ostream G4cout
std::vector< std::vector< G4complex > > & GetPolarization()
static G4double Wigner9J(G4int twoJ1, G4int twoJ2, G4int twoJ3, G4int twoJ4, G4int twoJ5, G4int twoJ6, G4int twoJ7, G4int twoJ8, G4int twoJ9)
G4double GammaTransFCoefficient(G4int K) const
void SetGammaTransitionData(G4int twoJ1, G4int twoJ2, G4int Lbar, G4double delta=0, G4int Lprime=1)
~G4PolarizationTransition()
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
G4double F3Coefficient(G4int K, G4int K2, G4int K1, G4int L, G4int Lprime, G4int twoJ2, G4int twoJ1) const
static G4double Wigner3J(G4double j1, G4double j2, G4double j3, G4double m1, G4double m2, G4double m3)
G4double EvalAssocLegendrePoly(G4int l, G4int m, G4double x)
void UpdatePolarizationToFinalState(G4double cosTheta, G4double phi, G4Fragment *)
static const G4int LL[nN]
void DumpTransitionData(const POLAR &pol) const
static G4double Wigner6J(G4int twoJ1, G4int twoJ2, G4int twoJ3, G4int twoJ4, G4int twoJ5, G4int twoJ6)
G4PolarizationTransition()
static constexpr double twopi
G4NuclearPolarization * GetNuclearPolarization() const
G4double GetCoefficient(size_t i, size_t order)
void SetPolarization(std::vector< std::vector< G4complex > > &p)