Healpix C++  3.83
alm_powspec_tools.cc
1 /*
2  * This file is part of Healpix_cxx.
3  *
4  * Healpix_cxx is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * Healpix_cxx is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with Healpix_cxx; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  * For more information about HEALPix, see http://healpix.sourceforge.net
19  */
20 
21 /*
22  * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik
23  * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
24  * (DLR).
25  */
26 
27 /*
28  * Copyright (C) 2003-2015 Max-Planck-Society
29  * Author: Martin Reinecke
30  */
31 
32 #include "alm_powspec_tools.h"
33 #include "string_utils.h"
34 #include "alm.h"
35 #include "planck_rng.h"
36 #include "powspec.h"
37 #include "xcomplex.h"
38 #include "rotmatrix.h"
39 #include "openmp_support.h"
40 #include "wigner.h"
41 #include "lsconstants.h"
42 
43 using namespace std;
44 template<typename T> void create_alm
45  (const PowSpec &powspec, Alm<xcomplex<T> > &alm, planck_rng &rng)
46  {
47  int lmax = alm.Lmax();
48  int mmax = alm.Mmax();
49  const double hsqrt2 = 1/sqrt(2.);
50 
51  for (int l=0; l<=lmax; ++l)
52  {
53  double rms_tt = sqrt(powspec.tt(l));
54  double zeta1_r = rng.rand_gauss();
55  alm(l,0) = T(zeta1_r * rms_tt);
56  for (int m=1; m<=min(l,mmax); ++m)
57  {
58  zeta1_r = rng.rand_gauss()*hsqrt2;
59  double zeta1_i = rng.rand_gauss()*hsqrt2;
60  alm(l,m) = xcomplex<T>(T(zeta1_r*rms_tt), T(zeta1_i*rms_tt));
61  }
62  }
63  }
64 
65 template void create_alm (const PowSpec &powspec,
66  Alm<xcomplex<float> > &alm, planck_rng &rng);
67 template void create_alm (const PowSpec &powspec,
68  Alm<xcomplex<double> > &alm, planck_rng &rng);
69 
70 
71 template<typename T> void create_alm_pol
72  (const PowSpec &ps,
73  Alm<xcomplex<T> > &almT,
74  Alm<xcomplex<T> > &almG,
75  Alm<xcomplex<T> > &almC,
76  planck_rng &rng)
77  {
78  int lmax = almT.Lmax();
79  int mmax = almT.Mmax();
80  const double hsqrt2 = 1/sqrt(2.);
81 
82  bool full = ps.Num_specs()==6;
83 
84  for (int l=0; l<=lmax; ++l)
85  {
86  double rms_tt=0, rms_g1=0, rms_c1=0;
87  if (ps.tt(l) > 0)
88  {
89  rms_tt = sqrt(ps.tt(l));
90  rms_g1 = ps.tg(l)/rms_tt;
91  if (full) rms_c1 = ps.tc(l)/rms_tt;
92  }
93 
94  double zeta1_r = rng.rand_gauss();
95  almT(l,0) = T(zeta1_r * rms_tt);
96  almG(l,0) = T(zeta1_r * rms_g1);
97  almC(l,0) = T(zeta1_r * rms_c1);
98  for (int m=1; m<=min(l,mmax); ++m)
99  {
100  zeta1_r = rng.rand_gauss()*hsqrt2;
101  double zeta1_i = rng.rand_gauss()*hsqrt2;
102  almT(l,m) = xcomplex<T>(T(zeta1_r*rms_tt), T(zeta1_i*rms_tt));
103  almG(l,m) = xcomplex<T>(T(zeta1_r*rms_g1), T(zeta1_i*rms_g1));
104  almC(l,m) = xcomplex<T>(T(zeta1_r*rms_c1), T(zeta1_i*rms_c1));
105  }
106  }
107 
108  for (int l=0; l<=lmax; ++l)
109  {
110  double rms_g2=0, rms_c2=0, rms_c3=0;
111  if (ps.tt(l) > 0)
112  {
113  rms_g2 = ps.gg(l) - (ps.tg(l)/ps.tt(l))*ps.tg(l);
114  if (rms_g2<=0)
115  {
116  planck_assert (abs(rms_g2) <= 1e-8*abs(ps.gg(l)),
117  "Inconsistent TT, GG and TG spectra at l="+dataToString(l));
118  rms_g2 = 0;
119  }
120  double rms_c1 = full ? (ps.tc(l) / sqrt(ps.tt(l))) : 0.;
121  if (rms_g2>0)
122  {
123  rms_g2 = sqrt(rms_g2);
124  if (full) rms_c2 = (ps.gc(l) - ps.tc(l) * (ps.tg(l)/ps.tt(l))) / rms_g2;
125  }
126  rms_c3 = ps.cc(l) - rms_c1*rms_c1 - rms_c2*rms_c2;
127  if (rms_c3<=0)
128  {
129  planck_assert (abs(rms_c3) <= 1e-8*abs(ps.cc(l)),
130  "Inconsistent spectra at l="+dataToString(l));
131  rms_c3 = 0;
132  }
133  rms_c3 = sqrt(rms_c3);
134  }
135  double zeta2_r = rng.rand_gauss();
136  double zeta3_r = rng.rand_gauss();
137  almG(l,0) += T(zeta2_r*rms_g2);
138  almC(l,0) += T(zeta3_r*rms_c3 + zeta2_r*rms_c2);
139 
140  for (int m=1; m<=min(l,mmax); ++m)
141  {
142  zeta2_r = rng.rand_gauss()*hsqrt2;
143  double zeta2_i = rng.rand_gauss()*hsqrt2;
144  zeta3_r = rng.rand_gauss()*hsqrt2;
145  double zeta3_i = rng.rand_gauss()*hsqrt2;
146 
147  almG(l,m) += xcomplex<T> (T(zeta2_r*rms_g2),T(zeta2_i*rms_g2));
148  almC(l,m) += xcomplex<T> (T(zeta3_r*rms_c3),T(zeta3_i*rms_c3))
149  +xcomplex<T> (T(zeta2_r*rms_c2),T(zeta2_i*rms_c2));
150  }
151  }
152  }
153 
154 template void create_alm_pol
155  (const PowSpec &powspec,
156  Alm<xcomplex<float> > &almT,
157  Alm<xcomplex<float> > &almG,
158  Alm<xcomplex<float> > &almC,
159  planck_rng &rng);
160 template void create_alm_pol
161  (const PowSpec &powspec,
162  Alm<xcomplex<double> > &almT,
163  Alm<xcomplex<double> > &almG,
164  Alm<xcomplex<double> > &almC,
165  planck_rng &rng);
166 
167 
168 template<typename T> void extract_crosspowspec
169  (const Alm<xcomplex<T> > &alm1,
170  const Alm<xcomplex<T> > &alm2,PowSpec &powspec)
171  {
172  planck_assert (alm1.conformable(alm2), "a_lm are not conformable");
173  arr<double> tt(alm1.Lmax()+1);
174  for (int l=0; l<=alm1.Lmax(); ++l)
175  {
176  tt[l] = alm1(l,0).real()*alm2(l,0).real();
177  int limit = min(l,alm1.Mmax());
178  for (int m=1; m<=limit; ++m)
179  tt[l] += 2 * (alm1(l,m).real()*alm2(l,m).real()
180  + alm1(l,m).imag()*alm2(l,m).imag());
181  tt[l] /= (2*l+1);
182  }
183  powspec.Set(tt);
184  }
185 
186 template void extract_crosspowspec
187  (const Alm<xcomplex<float> > &alm1,
188  const Alm<xcomplex<float> > &alm2, PowSpec &powspec);
189 template void extract_crosspowspec
190  (const Alm<xcomplex<double> > &alm1,
191  const Alm<xcomplex<double> > &alm2, PowSpec &powspec);
192 
193 
194 template<typename T> void extract_powspec
195  (const Alm<xcomplex<T> > &alm, PowSpec &powspec)
196  { extract_crosspowspec (alm,alm,powspec); }
197 
198 template void extract_powspec
199  (const Alm<xcomplex<float> > &alm, PowSpec &powspec);
200 template void extract_powspec
201  (const Alm<xcomplex<double> > &alm, PowSpec &powspec);
202 
203 namespace {
204 
205 template<typename T> void extract_crosspowspec
206  (const Alm<xcomplex<T> > &almT1,
207  const Alm<xcomplex<T> > &almG1,
208  const Alm<xcomplex<T> > &almC1,
209  const Alm<xcomplex<T> > &almT2,
210  const Alm<xcomplex<T> > &almG2,
211  const Alm<xcomplex<T> > &almC2,
212  PowSpec &powspec)
213  {
214  planck_assert (almT1.conformable(almG1) && almT1.conformable(almC1) &&
215  almT1.conformable(almT2) && almT1.conformable(almG2) &&
216  almT1.conformable(almC2), "a_lm are not conformable");
217 
218  int lmax = almT1.Lmax();
219  arr<double> tt(lmax+1), gg(lmax+1), cc(lmax+1), tg(lmax+1),
220  tc(lmax+1), gc(lmax+1);
221  for (int l=0; l<=lmax; ++l)
222  {
223  tt[l] = almT1(l,0).real()*almT2(l,0).real();
224  gg[l] = almG1(l,0).real()*almG2(l,0).real();
225  cc[l] = almC1(l,0).real()*almC2(l,0).real();
226  tg[l] = almT1(l,0).real()*almG2(l,0).real();
227  tc[l] = almT1(l,0).real()*almC2(l,0).real();
228  gc[l] = almG1(l,0).real()*almC2(l,0).real();
229  int limit = min(l,almT1.Mmax());
230  for (int m=1; m<=limit; ++m)
231  {
232  tt[l] += 2 * (almT1(l,m).real()*almT2(l,m).real()
233  + almT1(l,m).imag()*almT2(l,m).imag());
234  gg[l] += 2 * (almG1(l,m).real()*almG2(l,m).real()
235  + almG1(l,m).imag()*almG2(l,m).imag());
236  cc[l] += 2 * (almC1(l,m).real()*almC2(l,m).real()
237  + almC1(l,m).imag()*almC2(l,m).imag());
238  tg[l] += 2 * (almT1(l,m).real()*almG2(l,m).real()
239  + almT1(l,m).imag()*almG2(l,m).imag());
240  tc[l] += 2 * (almT1(l,m).real()*almC2(l,m).real()
241  + almT1(l,m).imag()*almC2(l,m).imag());
242  gc[l] += 2 * (almG1(l,m).real()*almC2(l,m).real()
243  + almG1(l,m).imag()*almC2(l,m).imag());
244  }
245  tt[l] /= (2*l+1);
246  gg[l] /= (2*l+1);
247  cc[l] /= (2*l+1);
248  tg[l] /= (2*l+1);
249  tc[l] /= (2*l+1);
250  gc[l] /= (2*l+1);
251  }
252  powspec.Set(tt,gg,cc,tg,tc,gc);
253  }
254 
255 } // unnamed namespace
256 
257 template<typename T> void extract_powspec
258  (const Alm<xcomplex<T> > &almT,
259  const Alm<xcomplex<T> > &almG,
260  const Alm<xcomplex<T> > &almC,
261  PowSpec &powspec)
262  { extract_crosspowspec(almT,almG,almC,almT,almG,almC,powspec); }
263 
264 template void extract_powspec
265  (const Alm<xcomplex<float> > &almT,
266  const Alm<xcomplex<float> > &almG,
267  const Alm<xcomplex<float> > &almC,
268  PowSpec &powspec);
269 template void extract_powspec
270  (const Alm<xcomplex<double> > &almT,
271  const Alm<xcomplex<double> > &almG,
272  const Alm<xcomplex<double> > &almC,
273  PowSpec &powspec);
274 
275 
276 template<typename T> void smoothWithGauss
277  (Alm<xcomplex<T> > &alm, double fwhm)
278  {
279  int fct = (fwhm>=0) ? 1 : -1;
280  double sigma = fwhm*fwhm2sigma;
281  arr<double> gb(alm.Lmax()+1);
282  for (int l=0; l<=alm.Lmax(); ++l)
283  gb[l] = exp(-.5*fct*l*(l+1)*sigma*sigma);
284  alm.ScaleL(gb);
285  }
286 
287 template void smoothWithGauss
288  (Alm<xcomplex<float> > &alm, double fwhm);
289 template void smoothWithGauss
290  (Alm<xcomplex<double> > &alm, double fwhm);
291 
292 
293 template<typename T> void smoothWithGauss
294  (Alm<xcomplex<T> > &almT,
295  Alm<xcomplex<T> > &almG,
296  Alm<xcomplex<T> > &almC,
297  double fwhm)
298  {
299  int fct = (fwhm>=0) ? 1 : -1;
300  double sigma = fwhm*fwhm2sigma;
301  double fact_pol = exp(2*fct*sigma*sigma);
302  arr<double> gb(almT.Lmax()+1);
303  for (int l=0; l<=almT.Lmax(); ++l)
304  gb[l] = exp(-.5*fct*l*(l+1)*sigma*sigma);
305  almT.ScaleL(gb);
306  for (int l=0; l<=almT.Lmax(); ++l)
307  gb[l] *= fact_pol;
308  almG.ScaleL(gb); almC.ScaleL(gb);
309  }
310 
311 template<typename T> void applyCosineWindow
312  (Alm<xcomplex<T> > &alm, int lmin, int lmax)
313  {
314  planck_assert((lmin>=0)&&(lmax>lmin),"bad lmin/lmax");
315  arr<double> cw(alm.Lmax()+1);
316  for (int i=0; i<int(cw.size()); ++i)
317  if (i<lmin)
318  cw[i]=1;
319  else if (i<lmax)
320  cw[i]=(1+cos(pi*(i-lmin)/double(lmax-lmin)))/2;
321  else
322  cw[i]=0;
323 
324  alm.ScaleL(cw);
325  }
326 
327 template void applyCosineWindow
328  (Alm<xcomplex<float> > &alm, int lmin, int lmax);
329 template void applyCosineWindow
330  (Alm<xcomplex<double> > &alm, int lmin, int lmax);
331 
332 template void smoothWithGauss
333  (Alm<xcomplex<float> > &almT,
334  Alm<xcomplex<float> > &almG,
335  Alm<xcomplex<float> > &almC,
336  double fwhm);
337 template void smoothWithGauss
338  (Alm<xcomplex<double> > &almT,
339  Alm<xcomplex<double> > &almG,
340  Alm<xcomplex<double> > &almC,
341  double fwhm);
342 
343 template<typename T> void rotate_alm (Alm<xcomplex<T> > &alm,
344  double psi, double theta, double phi)
345  {
346  planck_assert (alm.Lmax()==alm.Mmax(),
347  "rotate_alm: lmax must be equal to mmax");
348  int lmax=alm.Lmax();
349  arr<xcomplex<double> > exppsi(lmax+1), expphi(lmax+1);
350  for (int m=0; m<=lmax; ++m)
351  {
352  exppsi[m] = dcomplex(cos(psi*m),-sin(psi*m));
353  expphi[m] = dcomplex(cos(phi*m),-sin(phi*m));
354  }
355 
356  wigner_d_risbo_openmp rec(lmax,theta);
357 
358  arr<xcomplex<double> > almtmp(lmax+1);
359 
360  for (int l=0; l<=lmax; ++l)
361  {
362  const arr2<double> &d(rec.recurse());
363 
364  for (int m=0; m<=l; ++m)
365  almtmp[m] = xcomplex<double>(alm(l,0))*d[l][l+m];
366 
367 #pragma omp parallel
368 {
369  int64 lo,hi;
370  openmp_calc_share(0,l+1,lo,hi);
371 
372  bool flip = true;
373  for (int mm=1; mm<=l; ++mm)
374  {
375  dcomplex t1 = dcomplex(alm(l,mm))*exppsi[mm];
376  bool flip2 = ((mm+lo)&1) ? true : false;
377  for (int m=lo; m<hi; ++m)
378  {
379  double d1 = flip2 ? -d[l-mm][l-m] : d[l-mm][l-m];
380  double d2 = flip ? -d[l-mm][l+m] : d[l-mm][l+m];
381  double f1 = d1+d2, f2 = d1-d2;
382  almtmp[m]+=dcomplex(t1.real()*f1,t1.imag()*f2);
383  flip2 = !flip2;
384  }
385  flip = !flip;
386  }
387 }
388 
389  for (int m=0; m<=l; ++m)
390  alm(l,m) = xcomplex<T>(almtmp[m]*expphi[m]);
391  }
392  }
393 
394 template void rotate_alm (Alm<xcomplex<float> > &alm,
395  double psi, double theta, double phi);
396 template void rotate_alm (Alm<xcomplex<double> > &alm,
397  double psi, double theta, double phi);
398 
399 template<typename T> void rotate_alm (Alm<xcomplex<T> > &almT,
400  Alm<xcomplex<T> > &almG, Alm<xcomplex<T> > &almC,
401  double psi, double theta, double phi)
402  {
403  planck_assert (almT.Lmax()==almT.Mmax(),
404  "rotate_alm: lmax must be equal to mmax");
405  planck_assert (almG.conformable(almT) && almC.conformable(almT),
406  "rotate_alm: a_lm are not conformable");
407  int lmax=almT.Lmax();
408  arr<xcomplex<double> > exppsi(lmax+1), expphi(lmax+1);
409  for (int m=0; m<=lmax; ++m)
410  {
411  exppsi[m] = dcomplex(cos(psi*m),-sin(psi*m));
412  expphi[m] = dcomplex(cos(phi*m),-sin(phi*m));
413  }
414 
415  wigner_d_risbo_openmp rec(lmax,theta);
416 
417  arr<xcomplex<double> > almtmpT(lmax+1), almtmpG(lmax+1), almtmpC(lmax+1);
418 
419  for (int l=0; l<=lmax; ++l)
420  {
421  const arr2<double> &d(rec.recurse());
422 
423  for (int m=0; m<=l; ++m)
424  {
425  almtmpT[m] = xcomplex<double>(almT(l,0))*d[l][m+l];
426  almtmpG[m] = xcomplex<double>(almG(l,0))*d[l][m+l];
427  almtmpC[m] = xcomplex<double>(almC(l,0))*d[l][m+l];
428  }
429 
430 #pragma omp parallel
431 {
432  int64 lo,hi;
433  openmp_calc_share(0,l+1,lo,hi);
434 
435  bool flip = true;
436  for (int mm=1; mm<=l; ++mm)
437  {
438  dcomplex t1T = dcomplex(almT(l,mm))*exppsi[mm];
439  dcomplex t1G = dcomplex(almG(l,mm))*exppsi[mm];
440  dcomplex t1C = dcomplex(almC(l,mm))*exppsi[mm];
441  bool flip2 = ((mm+lo)&1) ? true : false;
442  for (int m=lo; m<hi; ++m)
443  {
444  double d1 = flip2 ? -d[l-mm][l-m] : d[l-mm][l-m];
445  double d2 = flip ? -d[l-mm][l+m] : d[l-mm][l+m];
446  double f1 = d1+d2, f2 = d1-d2;
447  almtmpT[m]+=dcomplex(t1T.real()*f1,t1T.imag()*f2);
448  almtmpG[m]+=dcomplex(t1G.real()*f1,t1G.imag()*f2);
449  almtmpC[m]+=dcomplex(t1C.real()*f1,t1C.imag()*f2);
450  flip2 = !flip2;
451  }
452  flip = !flip;
453  }
454 }
455 
456  for (int m=0; m<=l; ++m)
457  {
458  almT(l,m) = xcomplex<T>(almtmpT[m]*expphi[m]);
459  almG(l,m) = xcomplex<T>(almtmpG[m]*expphi[m]);
460  almC(l,m) = xcomplex<T>(almtmpC[m]*expphi[m]);
461  }
462  }
463  }
464 
465 template void rotate_alm (Alm<xcomplex<float> > &almT,
466  Alm<xcomplex<float> > &almG, Alm<xcomplex<float> > &almC,
467  double psi, double theta, double phi);
468 template void rotate_alm (Alm<xcomplex<double> > &almT,
469  Alm<xcomplex<double> > &almG, Alm<xcomplex<double> > &almC,
470  double psi, double theta, double phi);
471 
472 
473 template<typename T> void rotate_alm (Alm<xcomplex<T> > &alm,
474  const rotmatrix &mat)
475  {
476  double a1, a2, a3;
477  mat.Extract_CPAC_Euler_Angles (a1, a2, a3);
478  rotate_alm (alm, a3, a2, a1);
479  }
480 
481 template void rotate_alm (Alm<xcomplex<float> > &alm, const rotmatrix &mat);
482 template void rotate_alm (Alm<xcomplex<double> > &alm, const rotmatrix &mat);
483 
484 template<typename T> void rotate_alm (Alm<xcomplex<T> > &almT,
485  Alm<xcomplex<T> > &almG, Alm<xcomplex<T> > &almC,
486  const rotmatrix &mat)
487  {
488  double a1, a2, a3;
489  mat.Extract_CPAC_Euler_Angles (a1, a2, a3);
490  rotate_alm (almT, almG, almC, a3, a2, a1);
491  }
492 
493 template void rotate_alm (Alm<xcomplex<float> > &almT,
494  Alm<xcomplex<float> > &almG, Alm<xcomplex<float> > &almC,
495  const rotmatrix &mat);
496 template void rotate_alm (Alm<xcomplex<double> > &almT,
497  Alm<xcomplex<double> > &almG, Alm<xcomplex<double> > &almC,
498  const rotmatrix &mat);
void Set(int nspec, int lmax)
Definition: powspec.cc:92
const arr< double > & gg() const
Definition: powspec.h:71
const arr< double > & tc() const
Definition: powspec.h:77
void create_alm_pol(const PowSpec &ps, Alm< xcomplex< T > > &almT, Alm< xcomplex< T > > &almG, Alm< xcomplex< T > > &almC, planck_rng &rng)
int Num_specs() const
Definition: powspec.h:65
Definition: alm.h:88
const arr< double > & tt() const
Definition: powspec.h:69
const arr< double > & tg() const
Definition: powspec.h:75
const arr< double > & cc() const
Definition: powspec.h:73
void extract_powspec(const Alm< xcomplex< T > > &alm, PowSpec &powspec)
const arr< double > & gc() const
Definition: powspec.h:79
void extract_crosspowspec(const Alm< xcomplex< T > > &alm1, const Alm< xcomplex< T > > &alm2, PowSpec &powspec)
void create_alm(const PowSpec &powspec, Alm< xcomplex< T > > &alm, planck_rng &rng)

Generated on Wed Nov 13 2024 12:18:30 for Healpix C++