alm_powspec_tools.cc

00001 /*
00002  *  This file is part of Healpix_cxx.
00003  *
00004  *  Healpix_cxx is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  Healpix_cxx is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with Healpix_cxx; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017  *
00018  *  For more information about HEALPix, see http://healpix.sourceforge.net
00019  */
00020 
00021 /*
00022  *  Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik
00023  *  and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
00024  *  (DLR).
00025  */
00026 
00027 /*
00028  *  Copyright (C) 2003-2011 Max-Planck-Society
00029  *  Author: Martin Reinecke
00030  */
00031 
00032 #include "alm_powspec_tools.h"
00033 #include "string_utils.h"
00034 #include "alm.h"
00035 #include "planck_rng.h"
00036 #include "powspec.h"
00037 #include "xcomplex.h"
00038 #include "rotmatrix.h"
00039 #include "openmp_support.h"
00040 #include "wigner.h"
00041 #include "lsconstants.h"
00042 
00043 using namespace std;
00044 template<typename T> void create_alm
00045   (const PowSpec &powspec, Alm<xcomplex<T> > &alm, planck_rng &rng)
00046   {
00047   int lmax = alm.Lmax();
00048   int mmax = alm.Mmax();
00049   const double hsqrt2 = 1/sqrt(2.);
00050 
00051   for (int l=0; l<=lmax; ++l)
00052     {
00053     double rms_tt = sqrt(powspec.tt(l));
00054     double zeta1_r = rng.rand_gauss();
00055     alm(l,0) = T(zeta1_r * rms_tt);
00056     for (int m=1; m<=min(l,mmax); ++m)
00057       {
00058       zeta1_r = rng.rand_gauss()*hsqrt2;
00059       double zeta1_i = rng.rand_gauss()*hsqrt2;
00060       alm(l,m).Set (T(zeta1_r*rms_tt), T(zeta1_i*rms_tt));
00061       }
00062     }
00063   }
00064 
00065 template void create_alm (const PowSpec &powspec,
00066   Alm<xcomplex<float> > &alm, planck_rng &rng);
00067 template void create_alm (const PowSpec &powspec,
00068   Alm<xcomplex<double> > &alm, planck_rng &rng);
00069 
00070 
00071 template<typename T> void create_alm_pol
00072   (const PowSpec &powspec,
00073    Alm<xcomplex<T> > &almT,
00074    Alm<xcomplex<T> > &almG,
00075    Alm<xcomplex<T> > &almC,
00076    planck_rng &rng)
00077   {
00078   int lmax = almT.Lmax();
00079   int mmax = almT.Mmax();
00080   const double hsqrt2 = 1/sqrt(2.);
00081 
00082   for (int l=0; l<=lmax; ++l)
00083     {
00084     double rms_tt=0, rms_g1=0;
00085     if (powspec.tt(l) != 0)
00086       {
00087       rms_tt = sqrt(powspec.tt(l));
00088       rms_g1 = powspec.tg(l)/rms_tt;
00089       }
00090 
00091     double zeta1_r = rng.rand_gauss();
00092     almT(l,0) = T(zeta1_r * rms_tt);
00093     almG(l,0) = T(zeta1_r * rms_g1);
00094     for (int m=1; m<=min(l,mmax); ++m)
00095       {
00096       zeta1_r = rng.rand_gauss()*hsqrt2;
00097       double zeta1_i = rng.rand_gauss()*hsqrt2;
00098       almT(l,m).Set (T(zeta1_r*rms_tt), T(zeta1_i*rms_tt));
00099       almG(l,m).Set (T(zeta1_r*rms_g1), T(zeta1_i*rms_g1));
00100       }
00101     }
00102 
00103   for (int l=0; l<=lmax; ++l)
00104     {
00105     double rms_g2 = 0;
00106     double rms_cc = 0;
00107     if (powspec.tt(l) != 0)
00108       {
00109       rms_g2 = powspec.gg(l) - (powspec.tg(l)/powspec.tt(l))*powspec.tg(l);
00110       if (rms_g2 <= 0)
00111         {
00112         planck_assert (abs(rms_g2) <= 1e-8*abs(powspec.gg(l)),
00113           "Inconsistent TT, GG and TG spectra at l="+dataToString(l));
00114         rms_g2 = 0;
00115         }
00116       rms_g2 = sqrt(rms_g2);
00117       rms_cc = sqrt(powspec.cc(l));
00118       }
00119     almG(l,0) += T(rng.rand_gauss()*rms_g2);
00120     almC(l,0)  = T(rng.rand_gauss()*rms_cc);
00121 
00122     for (int m=1; m<=min(l,mmax); ++m)
00123       {
00124       double zeta2_r = rng.rand_gauss()*hsqrt2;
00125       double zeta2_i = rng.rand_gauss()*hsqrt2;
00126       double zeta3_r = rng.rand_gauss()*hsqrt2;
00127       double zeta3_i = rng.rand_gauss()*hsqrt2;
00128 
00129       almG(l,m) += xcomplex<T> (T(zeta2_r*rms_g2),T(zeta2_i*rms_g2));
00130       almC(l,m).Set (T(zeta3_r*rms_cc),T(zeta3_i*rms_cc));
00131       }
00132     }
00133   }
00134 
00135 template void create_alm_pol
00136   (const PowSpec &powspec,
00137    Alm<xcomplex<float> > &almT,
00138    Alm<xcomplex<float> > &almG,
00139    Alm<xcomplex<float> > &almC,
00140    planck_rng &rng);
00141 template void create_alm_pol
00142   (const PowSpec &powspec,
00143    Alm<xcomplex<double> > &almT,
00144    Alm<xcomplex<double> > &almG,
00145    Alm<xcomplex<double> > &almC,
00146    planck_rng &rng);
00147 
00148 
00149 template<typename T> void extract_crosspowspec
00150   (const Alm<xcomplex<T> > &alm1,
00151    const Alm<xcomplex<T> > &alm2,PowSpec &powspec)
00152   {
00153   planck_assert (alm1.conformable(alm2), "a_lm are not conformable");
00154   arr<double> tt(alm1.Lmax()+1);
00155   for (int l=0; l<=alm1.Lmax(); ++l)
00156     {
00157     tt[l] = alm1(l,0).re*alm2(l,0).re;
00158     int limit = min(l,alm1.Mmax());
00159     for (int m=1; m<=limit; ++m)
00160       tt[l] += 2 * (alm1(l,m).re*alm2(l,m).re + alm1(l,m).im*alm2(l,m).im);
00161     tt[l] /= (2*l+1);
00162     }
00163   powspec.Set(tt);
00164   }
00165 
00166 template void extract_crosspowspec
00167   (const Alm<xcomplex<float> > &alm1,
00168    const Alm<xcomplex<float> > &alm2, PowSpec &powspec);
00169 template void extract_crosspowspec
00170   (const Alm<xcomplex<double> > &alm1,
00171    const Alm<xcomplex<double> > &alm2, PowSpec &powspec);
00172 
00173 
00174 template<typename T> void extract_powspec
00175   (const Alm<xcomplex<T> > &alm, PowSpec &powspec)
00176   { extract_crosspowspec (alm,alm,powspec); }
00177 
00178 template void extract_powspec
00179   (const Alm<xcomplex<float> > &alm, PowSpec &powspec);
00180 template void extract_powspec
00181   (const Alm<xcomplex<double> > &alm, PowSpec &powspec);
00182 
00183 namespace {
00184 
00185 template<typename T> void extract_crosspowspec
00186   (const Alm<xcomplex<T> > &almT1,
00187    const Alm<xcomplex<T> > &almG1,
00188    const Alm<xcomplex<T> > &almC1,
00189    const Alm<xcomplex<T> > &almT2,
00190    const Alm<xcomplex<T> > &almG2,
00191    const Alm<xcomplex<T> > &almC2,
00192    PowSpec &powspec)
00193   {
00194   planck_assert (almT1.conformable(almG1) && almT1.conformable(almC1) &&
00195                  almT1.conformable(almT2) && almT1.conformable(almG2) &&
00196                  almT1.conformable(almC2), "a_lm are not conformable");
00197 
00198   int lmax = almT1.Lmax();
00199   arr<double> tt(lmax+1), gg(lmax+1), cc(lmax+1), tg(lmax+1),
00200               tc(lmax+1), gc(lmax+1);
00201   for (int l=0; l<=lmax; ++l)
00202     {
00203     tt[l] = almT1(l,0).re*almT2(l,0).re;
00204     gg[l] = almG1(l,0).re*almG2(l,0).re;
00205     cc[l] = almC1(l,0).re*almC2(l,0).re;
00206     tg[l] = almT1(l,0).re*almG2(l,0).re;
00207     tc[l] = almT1(l,0).re*almC2(l,0).re;
00208     gc[l] = almG1(l,0).re*almC2(l,0).re;
00209     int limit = min(l,almT1.Mmax());
00210     for (int m=1; m<=limit; ++m)
00211       {
00212       tt[l] += 2 * (almT1(l,m).re*almT2(l,m).re + almT1(l,m).im*almT2(l,m).im);
00213       gg[l] += 2 * (almG1(l,m).re*almG2(l,m).re + almG1(l,m).im*almG2(l,m).im);
00214       cc[l] += 2 * (almC1(l,m).re*almC2(l,m).re + almC1(l,m).im*almC2(l,m).im);
00215       tg[l] += 2 * (almT1(l,m).re*almG2(l,m).re + almT1(l,m).im*almG2(l,m).im);
00216       tc[l] += 2 * (almT1(l,m).re*almC2(l,m).re + almT1(l,m).im*almC2(l,m).im);
00217       gc[l] += 2 * (almG1(l,m).re*almC2(l,m).re + almG1(l,m).im*almC2(l,m).im);
00218       }
00219     tt[l] /= (2*l+1);
00220     gg[l] /= (2*l+1);
00221     cc[l] /= (2*l+1);
00222     tg[l] /= (2*l+1);
00223     tc[l] /= (2*l+1);
00224     gc[l] /= (2*l+1);
00225     }
00226   powspec.Set(tt,gg,cc,tg,tc,gc);
00227   }
00228 
00229 } // unnamed namespace
00230 
00231 template<typename T> void extract_powspec
00232   (const Alm<xcomplex<T> > &almT,
00233    const Alm<xcomplex<T> > &almG,
00234    const Alm<xcomplex<T> > &almC,
00235    PowSpec &powspec)
00236   { extract_crosspowspec(almT,almG,almC,almT,almG,almC,powspec); }
00237 
00238 template void extract_powspec
00239   (const Alm<xcomplex<float> > &almT,
00240    const Alm<xcomplex<float> > &almG,
00241    const Alm<xcomplex<float> > &almC,
00242    PowSpec &powspec);
00243 template void extract_powspec
00244   (const Alm<xcomplex<double> > &almT,
00245    const Alm<xcomplex<double> > &almG,
00246    const Alm<xcomplex<double> > &almC,
00247    PowSpec &powspec);
00248 
00249 
00250 template<typename T> void smoothWithGauss
00251   (Alm<xcomplex<T> > &alm, double fwhm)
00252   {
00253   int fct = (fwhm>=0) ? 1 : -1;
00254   double sigma = fwhm*fwhm2sigma;
00255   arr<double> gb(alm.Lmax()+1);
00256   for (int l=0; l<=alm.Lmax(); ++l)
00257     gb[l] = exp(-.5*fct*l*(l+1)*sigma*sigma);
00258   alm.ScaleL(gb);
00259   }
00260 
00261 template void smoothWithGauss
00262   (Alm<xcomplex<float> > &alm, double fwhm);
00263 template void smoothWithGauss
00264   (Alm<xcomplex<double> > &alm, double fwhm);
00265 
00266 
00267 template<typename T> void smoothWithGauss
00268   (Alm<xcomplex<T> > &almT,
00269    Alm<xcomplex<T> > &almG,
00270    Alm<xcomplex<T> > &almC,
00271    double fwhm)
00272   {
00273   int fct = (fwhm>=0) ? 1 : -1;
00274   double sigma = fwhm*fwhm2sigma;
00275   double fact_pol = exp(2*fct*sigma*sigma);
00276   arr<double> gb(almT.Lmax()+1);
00277   for (int l=0; l<=almT.Lmax(); ++l)
00278     gb[l] = exp(-.5*fct*l*(l+1)*sigma*sigma);
00279   almT.ScaleL(gb);
00280   for (int l=0; l<=almT.Lmax(); ++l)
00281     gb[l] *= fact_pol;
00282   almG.ScaleL(gb); almC.ScaleL(gb);
00283   }
00284 
00285 template void smoothWithGauss
00286   (Alm<xcomplex<float> > &almT,
00287    Alm<xcomplex<float> > &almG,
00288    Alm<xcomplex<float> > &almC,
00289    double fwhm);
00290 template void smoothWithGauss
00291   (Alm<xcomplex<double> > &almT,
00292    Alm<xcomplex<double> > &almG,
00293    Alm<xcomplex<double> > &almC,
00294    double fwhm);
00295 
00296 template<typename T> void rotate_alm (Alm<xcomplex<T> > &alm,
00297   double psi, double theta, double phi)
00298   {
00299   planck_assert (alm.Lmax()==alm.Mmax(),
00300     "rotate_alm: lmax must be equal to mmax");
00301   int lmax=alm.Lmax();
00302   arr<xcomplex<double> > exppsi(lmax+1), expphi(lmax+1);
00303   for (int m=0; m<=lmax; ++m)
00304     {
00305     exppsi[m].Set (cos(psi*m),-sin(psi*m));
00306     expphi[m].Set (cos(phi*m),-sin(phi*m));
00307     }
00308 
00309   wigner_d_risbo_openmp rec(lmax,theta);
00310 
00311   arr<xcomplex<double> > almtmp(lmax+1);
00312 
00313   for (int l=0; l<=lmax; ++l)
00314     {
00315     const arr2<double> &d(rec.recurse());
00316 
00317     for (int m=0; m<=l; ++m)
00318       almtmp[m] = xcomplex<double>(alm(l,0))*d[l][l+m];
00319 
00320 #pragma omp parallel
00321 {
00322     int64 lo,hi;
00323     openmp_calc_share(0,l+1,lo,hi);
00324 
00325     bool flip = true;
00326     for (int mm=1; mm<=l; ++mm)
00327       {
00328       xcomplex<double> t1 = xcomplex<double>(alm(l,mm))*exppsi[mm];
00329       bool flip2 = ((mm+lo)&1) ? true : false;
00330       for (int m=lo; m<hi; ++m)
00331         {
00332         double d1 = flip2 ? -d[l-mm][l-m] : d[l-mm][l-m];
00333         double d2 = flip  ? -d[l-mm][l+m] : d[l-mm][l+m];
00334         double f1 = d1+d2, f2 = d1-d2;
00335         almtmp[m].re += t1.re*f1; almtmp[m].im += t1.im*f2;
00336         flip2 = !flip2;
00337         }
00338       flip = !flip;
00339       }
00340 }
00341 
00342     for (int m=0; m<=l; ++m)
00343       alm(l,m) = xcomplex<T>(almtmp[m]*expphi[m]);
00344     }
00345   }
00346 
00347 template void rotate_alm (Alm<xcomplex<float> > &alm,
00348   double psi, double theta, double phi);
00349 template void rotate_alm (Alm<xcomplex<double> > &alm,
00350   double psi, double theta, double phi);
00351 
00352 template<typename T> void rotate_alm (Alm<xcomplex<T> > &almT,
00353   Alm<xcomplex<T> > &almG, Alm<xcomplex<T> > &almC,
00354   double psi, double theta, double phi)
00355   {
00356   planck_assert (almT.Lmax()==almT.Mmax(),
00357     "rotate_alm: lmax must be equal to mmax");
00358   planck_assert (almG.conformable(almT) && almC.conformable(almT),
00359     "rotate_alm: a_lm are not conformable");
00360   int lmax=almT.Lmax();
00361   arr<xcomplex<double> > exppsi(lmax+1), expphi(lmax+1);
00362   for (int m=0; m<=lmax; ++m)
00363     {
00364     exppsi[m].Set (cos(psi*m),-sin(psi*m));
00365     expphi[m].Set (cos(phi*m),-sin(phi*m));
00366     }
00367 
00368   wigner_d_risbo_openmp rec(lmax,theta);
00369 
00370   arr<xcomplex<double> > almtmpT(lmax+1), almtmpG(lmax+1), almtmpC(lmax+1);
00371 
00372   for (int l=0; l<=lmax; ++l)
00373     {
00374     const arr2<double> &d(rec.recurse());
00375 
00376     for (int m=0; m<=l; ++m)
00377       {
00378       almtmpT[m] = xcomplex<double>(almT(l,0))*d[l][m+l];
00379       almtmpG[m] = xcomplex<double>(almG(l,0))*d[l][m+l];
00380       almtmpC[m] = xcomplex<double>(almC(l,0))*d[l][m+l];
00381       }
00382 
00383 #pragma omp parallel
00384 {
00385     int64 lo,hi;
00386     openmp_calc_share(0,l+1,lo,hi);
00387 
00388     bool flip = true;
00389     for (int mm=1; mm<=l; ++mm)
00390       {
00391       xcomplex<double> t1T = xcomplex<double>(almT(l,mm))*exppsi[mm];
00392       xcomplex<double> t1G = xcomplex<double>(almG(l,mm))*exppsi[mm];
00393       xcomplex<double> t1C = xcomplex<double>(almC(l,mm))*exppsi[mm];
00394       bool flip2 = ((mm+lo)&1) ? true : false;
00395       for (int m=lo; m<hi; ++m)
00396         {
00397         double d1 = flip2 ? -d[l-mm][l-m] : d[l-mm][l-m];
00398         double d2 = flip  ? -d[l-mm][l+m] : d[l-mm][l+m];
00399         double f1 = d1+d2, f2 = d1-d2;
00400         almtmpT[m].re += t1T.re*f1; almtmpT[m].im += t1T.im*f2;
00401         almtmpG[m].re += t1G.re*f1; almtmpG[m].im += t1G.im*f2;
00402         almtmpC[m].re += t1C.re*f1; almtmpC[m].im += t1C.im*f2;
00403         flip2 = !flip2;
00404         }
00405       flip = !flip;
00406       }
00407 }
00408 
00409     for (int m=0; m<=l; ++m)
00410       {
00411       almT(l,m) = xcomplex<T>(almtmpT[m]*expphi[m]);
00412       almG(l,m) = xcomplex<T>(almtmpG[m]*expphi[m]);
00413       almC(l,m) = xcomplex<T>(almtmpC[m]*expphi[m]);
00414       }
00415     }
00416   }
00417 
00418 template void rotate_alm (Alm<xcomplex<float> > &almT,
00419   Alm<xcomplex<float> > &almG, Alm<xcomplex<float> > &almC,
00420   double psi, double theta, double phi);
00421 template void rotate_alm (Alm<xcomplex<double> > &almT,
00422   Alm<xcomplex<double> > &almG, Alm<xcomplex<double> > &almC,
00423   double psi, double theta, double phi);
00424 
00425 
00426 template<typename T> void rotate_alm (Alm<xcomplex<T> > &alm,
00427   const rotmatrix &mat)
00428   {
00429   double a1, a2, a3;
00430   mat.Extract_CPAC_Euler_Angles (a1, a2, a3);
00431   rotate_alm (alm, a3, a2, a1);
00432   }
00433 
00434 template void rotate_alm (Alm<xcomplex<float> > &alm, const rotmatrix &mat);
00435 template void rotate_alm (Alm<xcomplex<double> > &alm, const rotmatrix &mat);
00436 
00437 template<typename T> void rotate_alm (Alm<xcomplex<T> > &almT,
00438   Alm<xcomplex<T> > &almG, Alm<xcomplex<T> > &almC,
00439   const rotmatrix &mat)
00440   {
00441   double a1, a2, a3;
00442   mat.Extract_CPAC_Euler_Angles (a1, a2, a3);
00443   rotate_alm (almT, almG, almC, a3, a2, a1);
00444   }
00445 
00446 template void rotate_alm (Alm<xcomplex<float> > &almT,
00447   Alm<xcomplex<float> > &almG, Alm<xcomplex<float> > &almC,
00448   const rotmatrix &mat);
00449 template void rotate_alm (Alm<xcomplex<double> > &almT,
00450   Alm<xcomplex<double> > &almG, Alm<xcomplex<double> > &almC,
00451   const rotmatrix &mat);

Generated on Wed Apr 24 11:31:18 2013 for Healpix C++