9#include "FemtoYlmMath.h"
19 FemtoYlmMath::FemtoYlmMath() { InitializeYlms(); }
21 FemtoYlmMath::~FemtoYlmMath() {}
23 FemtoYlmMath::FemtoYlmMath(
const FemtoYlmMath& aYlm) : TObject(aYlm) { InitializeYlms(); }
25 FemtoYlmMath& FemtoYlmMath::operator=(
const FemtoYlmMath& aYlm) {
26 if (
this == &aYlm)
return *
this;
33 std::complex<double> FemtoYlmMath::Ceiphi(
double phi)
const {
return std::complex<double>(cos(phi), sin(phi)); }
35 double FemtoYlmMath::Legendre(
int ell,
int em,
double ctheta)
const {
39 FemtoYlmMath::LegendreUpToYlm(ell, ctheta, lbuf);
41 return lbuf[fPlmshift[ell] - abs(em)];
43 double FemtoYlmMath::DeltaJ(
double aJot1,
double aJot2,
double aJot)
const {
44 if ((aJot1 + aJot2 - aJot) < 0) {
return 0; }
45 if ((aJot1 - aJot2 + aJot) < 0) {
return 0; }
46 if ((-aJot1 + aJot2 + aJot) < 0) {
return 0; }
47 if ((aJot1 + aJot2 + aJot + 1) < 0) {
return 0; }
48 double res = TMath::Sqrt(1.0 * fFactorials[lrint(aJot1 + aJot2 - aJot)] * fFactorials[lrint(aJot1 - aJot2 + aJot)]
49 * fFactorials[lrint(-aJot1 + aJot2 + aJot)] / fFactorials[lrint(aJot1 + aJot2 + aJot + 1)]);
53 double FemtoYlmMath::ClebschGordan(
double aJot1,
double aEm1,
double aJot2,
double aEm2,
double aJot,
double aEm)
const {
59 maxt = lrint(aJot1 + aJot2 - aJot);
61 if (lrint(aJot1 - aEm1) < maxt) maxt = lrint(aJot1 - aEm1);
62 if (lrint(aJot2 + aEm2) < maxt) maxt = lrint(aJot2 + aEm2);
63 if (lrint(-(aJot - aJot2 + aEm1)) > mint) mint = lrint(-(aJot - aJot2 + aEm1));
64 if (lrint(-(aJot - aJot1 - aEm2)) > mint) mint = lrint(-(aJot - aJot1 - aEm2));
66 for (titer = mint; titer <= maxt; titer++) {
67 coef = TMath::Power(-1, titer);
68 coef *= TMath::Sqrt((2 * aJot + 1) * fFactorials[lrint(aJot1 + aEm1)] * fFactorials[lrint(aJot1 - aEm1)]
69 * fFactorials[lrint(aJot2 + aEm2)] * fFactorials[lrint(aJot2 - aEm2)] * fFactorials[lrint(aJot + aEm)]
70 * fFactorials[lrint(aJot - aEm)]);
71 coef /= (fFactorials[titer] * fFactorials[lrint(aJot1 + aJot2 - aJot - titer)] * fFactorials[lrint(aJot1 - aEm1 - titer)]
72 * fFactorials[lrint(aJot2 + aEm2 - titer)] * fFactorials[lrint(aJot - aJot2 + aEm1 + titer)]
73 * fFactorials[lrint(aJot - aJot1 - aEm2 + titer)]);
78 cgc *= DeltaJ(aJot1, aJot2, aJot);
83 double FemtoYlmMath::WignerSymbol(
double aJot1,
double aEm1,
double aJot2,
double aEm2,
double aJot,
double aEm)
const {
84 if (lrint(aEm1 + aEm2 + aEm) != 0.0)
return 0.0;
85 double cge = ClebschGordan(aJot1, aEm1, aJot2, aEm2, aJot, -aEm);
86 if (lrint(abs(aJot1 - aJot2 - aEm)) % 2) cge *= -1.0;
87 cge /= sqrt(2 * aJot + 1);
89 if (cge == -0.0) cge = 0.0;
94 std::complex<double> FemtoYlmMath::Ylm(
int ell,
int m,
double theta,
double phi)
const {
97 std::complex<double> answer;
98 std::complex<double> ci(0.0, 1.0);
100 answer = (fPrefactors[fPrefshift[ell] + m] * Legendre(ell, m, ctheta)) * Ceiphi(m * phi);
105 std::complex<double> FemtoYlmMath::Ylm(
int ell,
int m,
double x,
double y,
double z)
const {
107 std::complex<double> answer;
109 double r = sqrt(x * x + y * y + z * z);
110 if (r < 1e-10 || fabs(z) < 1e-10)
115 answer = (fPrefactors[fPrefshift[ell] + m] * Legendre(ell, m, ctheta)) * Ceiphi(m * phi);
120 double FemtoYlmMath::ReYlm(
int ell,
int m,
double theta,
double phi)
const {
121 return real(FemtoYlmMath::Ylm(ell, m, theta, phi));
124 double FemtoYlmMath::ImYlm(
int ell,
int m,
double theta,
double phi)
const {
125 return imag(FemtoYlmMath::Ylm(ell, m, theta, phi));
128 double FemtoYlmMath::ReYlm(
int ell,
int m,
double x,
double y,
double z)
const {
129 return real(FemtoYlmMath::Ylm(ell, m, x, y, z));
132 double FemtoYlmMath::ImYlm(
int ell,
int m,
double x,
double y,
double z)
const {
133 return imag(FemtoYlmMath::Ylm(ell, m, x, y, z));
136 void FemtoYlmMath::InitializeYlms() {
139 double oneoversqrtpi = 1.0 / TMath::Sqrt(TMath::Pi());
143 fPrefactors[0] = 0.5 * oneoversqrtpi;
146 fPrefactors[1] = 0.5 * sqrt(3.0 / 2.0) * oneoversqrtpi;
147 fPrefactors[2] = 0.5 * sqrt(3.0) * oneoversqrtpi;
148 fPrefactors[3] = -fPrefactors[1];
151 fPrefactors[4] = 0.25 * sqrt(15.0 / 2.0) * oneoversqrtpi;
152 fPrefactors[5] = 0.5 * sqrt(15.0 / 2.0) * oneoversqrtpi;
153 fPrefactors[6] = 0.25 * sqrt(5.0) * oneoversqrtpi;
154 fPrefactors[7] = -fPrefactors[5];
155 fPrefactors[8] = fPrefactors[4];
158 fPrefactors[9] = 0.125 * sqrt(35.0) * oneoversqrtpi;
159 fPrefactors[10] = 0.25 * sqrt(105.0 / 2.0) * oneoversqrtpi;
160 fPrefactors[11] = 0.125 * sqrt(21.0) * oneoversqrtpi;
161 fPrefactors[12] = 0.25 * sqrt(7.0) * oneoversqrtpi;
162 fPrefactors[13] = -fPrefactors[11];
163 fPrefactors[14] = fPrefactors[10];
164 fPrefactors[15] = -fPrefactors[9];
167 fPrefactors[16] = 3.0 / 16.0 * sqrt(35.0 / 2.0) * oneoversqrtpi;
168 fPrefactors[17] = 3.0 / 8.0 * sqrt(35.0) * oneoversqrtpi;
169 fPrefactors[18] = 3.0 / 8.0 * sqrt(5.0 / 2.0) * oneoversqrtpi;
170 fPrefactors[19] = 3.0 / 8.0 * sqrt(5.0) * oneoversqrtpi;
171 fPrefactors[20] = 3.0 / 16.0 * oneoversqrtpi;
172 fPrefactors[21] = -fPrefactors[19];
173 fPrefactors[22] = fPrefactors[18];
174 fPrefactors[23] = -fPrefactors[17];
175 fPrefactors[24] = fPrefactors[16];
178 fPrefactors[25] = 3.0 / 32.0 * sqrt(77.0) * oneoversqrtpi;
179 fPrefactors[26] = 3.0 / 16.0 * sqrt(385.0 / 2.0) * oneoversqrtpi;
180 fPrefactors[27] = 1.0 / 32.0 * sqrt(385.0) * oneoversqrtpi;
181 fPrefactors[28] = 1.0 / 8.0 * sqrt(1155.0 / 2.0) * oneoversqrtpi;
182 fPrefactors[29] = 1.0 / 16.0 * sqrt(165.0 / 2.0) * oneoversqrtpi;
183 fPrefactors[30] = 1.0 / 16.0 * sqrt(11.0) * oneoversqrtpi;
184 fPrefactors[31] = -fPrefactors[29];
185 fPrefactors[32] = fPrefactors[28];
186 fPrefactors[33] = -fPrefactors[27];
187 fPrefactors[34] = fPrefactors[26];
188 fPrefactors[35] = -fPrefactors[25];
203 fYlms =
new std::complex<double>[36];
207 for (
int iter = 1; iter < 24; iter++) {
209 fFactorials[iter] = fac;
213 void FemtoYlmMath::LegendreUpToYlm(
int lmax,
double ctheta,
double* lbuf)
const {
220 sins[1] = sqrt(1 - ctheta * ctheta);
222 for (
int iter = 2; iter < 6; iter++) {
223 sins[iter] = sins[iter - 1] * sins[1];
224 coss[iter] = coss[iter - 1] * coss[1];
239 lbuf[4] = sins[1] * coss[1];
240 lbuf[5] = 3 * coss[2] - 1;
246 lbuf[7] = sins[2] * coss[1];
247 lbuf[8] = (5 * coss[2] - 1) * sins[1];
248 lbuf[9] = 5 * coss[3] - 3 * coss[1];
254 lbuf[11] = sins[3] * coss[1];
255 lbuf[12] = (7 * coss[2] - 1) * sins[2];
256 lbuf[13] = (7 * coss[3] - 3 * coss[1]) * sins[1];
257 lbuf[14] = 35 * coss[4] - 30 * coss[2] + 3;
263 lbuf[16] = sins[4] * coss[1];
264 lbuf[17] = (9 * coss[2] - 1) * sins[3];
265 lbuf[18] = (3 * coss[3] - 1 * coss[1]) * sins[2];
266 lbuf[19] = (21 * coss[4] - 14 * coss[2] + 1) * sins[1];
267 lbuf[20] = 63 * coss[5] - 70 * coss[3] + 15 * coss[1];
271 std::complex<double>* FemtoYlmMath::YlmUpToL(
int lmax,
double x,
double y,
double z) {
276 double r = sqrt(x * x + y * y + z * z);
277 if (r < 1e-10 || fabs(z) < 1e-10)
283 return YlmUpToL(lmax, ctheta, phi);
286 std::complex<double>* FemtoYlmMath::YlmUpToL(
int lmax,
double ctheta,
double phi) {
296 LegendreUpToYlm(lmax, ctheta, lbuf);
298 for (
int iter = 1; iter <= lmax; iter++) {
299 coss[iter - 1] = cos(iter * phi);
300 sins[iter - 1] = sin(iter * phi);
302 fYlms[lcur++] = fPrefactors[0] * lbuf[0] * std::complex<double>(1, 0);
304 for (
int il = 1; il <= lmax; il++) {
306 fYlms[lcur + il] = fPrefactors[fPrefshift[il]] * lbuf[fPlmshift[il]] * std::complex<double>(1.0, 0.0);
308 for (
int im = 1; im <= il; im++) {
309 lpol = lbuf[fPlmshift[il] - im];
310 fYlms[lcur + il - im] = fPrefactors[fPrefshift[il] - im] * lpol * std::complex<double>(coss[im - 1], -sins[im - 1]);
311 fYlms[lcur + il + im] = fPrefactors[fPrefshift[il] + im] * lpol * std::complex<double>(coss[im - 1], sins[im - 1]);