CosmoBolognaLib
Free Software C++/Python libraries for cosmological calculations
SphericalHarmonics_Coefficients.cpp
1 /********************************************************************
2  * Copyright (C) 2015 by Federico Marulli and Alfonso Veropalumbo *
3  * federico.marulli3@unibo.it *
4  * *
5  * This program is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU General Public License as *
7  * published by the Free Software Foundation; either version 2 of *
8  * the License, or (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public *
16  * License along with this program; if not, write to the Free *
17  * Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ********************************************************************/
20 
38 
39 using namespace std;
40 
41 using namespace cbl;
42 
43 // ============================================================================================
44 
45 
46 void cbl::glob::SphericalHarmonics_Coefficients::initialize (const int norder, const int nbins)
47 {
48 
49  m_nbins = nbins;
50  m_norder = norder;
51  m_lmax = m_norder-1;
52  m_n_sph = gsl_sf_legendre_array_n(m_lmax);
53 
54  vector<vector<complex<double>>> _alm(m_nbins, vector<complex<double>>(m_n_sph, 0));
55 
56  vector<double> normalization (m_n_sph);
57 
58  vector<double> Plm(m_n_sph, 0);
59  vector<complex<double>> sph(m_n_sph);
60 
61  for (int l=0; l<m_norder; l++)
62  for (int m=0; m<l+1; m++) {
63  int n=l*(l+1)/2+m;
64  normalization[n] = gsl_sf_fact (l - m) / gsl_sf_fact ( l + m);
65  }
66 
67  m_alm = _alm;
68  m_normalization = normalization;
69 
70  m_Plm = Plm;
71  m_sph = sph;
72 }
73 
74 
75 // ============================================================================
76 
77 
79 {
80  for (int b=0; b<m_nbins; b++)
81  for (int k1=0; k1<m_n_sph; k1++)
82  m_alm[b][k1] = 0;
83 }
84 
85 
86 // ============================================================================
87 
88 
89 std::vector<std::complex<double>> cbl::glob::SphericalHarmonics_Coefficients::alm (const double xx, const double yy, const double zz)
90 {
91  double cosTheta = zz;
92 
93  m_sph[0].real(1);
94  m_sph[0].imag(0);
95 
96  m_sph[1].real(cosTheta);
97  m_sph[1].imag(0);
98 
99  double Plm0 = 1.;
100  double Plm1 = cosTheta;
101  double Plm2, Plm3;
102 
103  int q, l, lp1;
104 
105  // P(l, 0)
106  for (int l = 1; l < m_norder-1; l++) {
107  q = l+1;
108  Plm2 = ((2*l+1)*cosTheta*Plm1-l*Plm0)/(l+1);
109  m_sph[q*(q+1)/2].real(Plm2);
110  m_sph[q*(q+1)/2].imag(0.);
111  Plm0 = Plm1;
112  Plm1 = Plm2;
113  }
114 
115  double sinTheta = sqrt(1 - cosTheta*cosTheta);
116  if (sinTheta > 0) {
117  double cosPhi = xx/sinTheta;
118  double sinPhi = yy/sinTheta;
119 
120  double old_cc_real = 1.;
121  double old_cc_imag = 0.;
122  double cc_real = cosPhi;
123  double cc_imag = sinPhi;
124 
125  // P(m, m) -> P(m+1, m) -> P( m+1<l<lMax, m)
126  Plm0 = 1.;
127  for (int m=1; m<m_norder; m++) {
128  l = m;
129  lp1 = m+1;
130  Plm1 = -(2*(m-1)+1)*Plm0*sinTheta;
131  Plm0 = Plm1;
132  m_sph[l*(l+1)/2+m].real(Plm1*cc_real);
133  m_sph[l*(l+1)/2+m].imag(Plm1*cc_imag);
134 
135  Plm2 = cosTheta*(2*l+1)*Plm1;
136  m_sph[lp1*(lp1+1)/2+m].real(Plm2*cc_real);
137  m_sph[lp1*(lp1+1)/2+m].imag(Plm2*cc_imag);
138 
139  for (int lp2=lp1+1; lp2<m_norder; lp2++) {
140  Plm3 = ((2.*lp2-1.)*cosTheta*Plm2-(lp2+m-1)*Plm1)/(lp2-m);
141  Plm1 = Plm2;
142  Plm2 = Plm3;
143 
144  m_sph[lp2*(lp2+1)/2+m].real(Plm3*cc_real);
145  m_sph[lp2*(lp2+1)/2+m].imag(Plm3*cc_imag);
146  }
147 
148  old_cc_real = cc_real;
149  old_cc_imag = cc_imag;
150  cc_real = old_cc_real*cosPhi-old_cc_imag*sinPhi;
151  cc_imag = old_cc_real*sinPhi+old_cc_imag*cosPhi;
152  }
153  }
154  else {
155  for (int m=1; m<m_norder; m++) {
156  l = m;
157  lp1 = m+1;
158 
159  m_sph[l*(l+1)/2+m].real(0.);
160  m_sph[l*(l+1)/2+m].imag(0.);
161 
162  m_sph[lp1*(lp1+1)/2+m].real(0.);
163  m_sph[lp1*(lp1+1)/2+m].imag(0.);
164 
165  for (int lp2=lp1+1; lp2<m_norder; lp2++) {
166  Plm3 = ((2.*lp2-1.)*cosTheta*Plm2-(lp2+m-1)*Plm1)/(lp2-m);
167 
168  m_sph[lp2*(lp2+1)/2+m].real(0.);
169  m_sph[lp2*(lp2+1)/2+m].imag(0.);
170  }
171  }
172  }
173 
174 
175  return m_sph;
176 }
177 
178 
179 // ============================================================================
180 
181 
182 void cbl::glob::SphericalHarmonics_Coefficients::add (const std::vector<std::complex<double>> alm, const double ww, const int bin)
183 {
184  for(int n=0; n<m_n_sph; n++)
185  m_alm[bin][n] += ww*alm[n];
186 }
187 
188 
189 // ============================================================================
190 
191 
192 void cbl::glob::SphericalHarmonics_Coefficients::add (const double xx, const double yy, const double zz, const double ww, const int bin)
193 {
194  vector<complex<double>> alm = this->alm (xx, yy, zz);
195  for(int n=0; n<m_n_sph; n++)
196  m_alm[bin][n] += ww*alm[n];
197 }
198 
199 
200 // ============================================================================
201 
202 
203 double cbl::glob::SphericalHarmonics_Coefficients::power (const int l, const int bin1, const int bin2)
204 {
205  const int min_n = l*(l+1)/2;
206  double power = m_normalization[min_n]*(real(min_n, bin1)*real(min_n, bin2)+imag(min_n, bin1)*imag(min_n, bin2));
207  for (int m=1; m<l+1; m++) {
208  const int pos = min_n+m;
209  power += 2.*m_normalization[pos]*(real(pos, bin1)*real(pos, bin2)+imag(pos, bin1)*imag(pos, bin2));
210  }
211 
212  return power;
213 }
Generic functions that use one or more classes of the CosmoBolognaLib.
double power(const int l, const int bin1, const int bin2)
compute the product of the in two separation bin
std::vector< std::complex< double > > alm(const double xx, const double yy, const double zz)
compute the for the normalized coordinates
void initialize(const int norder, const int nbins=1)
initialize the internal quantities
void add(const std::vector< std::complex< double >> alm, const double ww, const int bin=0)
add the to a specific separation bin with a weight
The global namespace of the CosmoBolognaLib
Definition: CAMB.h:38