33 #include "string_utils.h" 35 #include "planck_rng.h" 38 #include "rotmatrix.h" 39 #include "openmp_support.h" 41 #include "lsconstants.h" 45 (
const PowSpec &powspec,
Alm<xcomplex<T> > &alm, planck_rng &rng)
47 int lmax = alm.Lmax();
48 int mmax = alm.Mmax();
49 const double hsqrt2 = 1/sqrt(2.);
51 for (
int l=0; l<=lmax; ++l)
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)
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));
66 Alm<xcomplex<float> > &alm, planck_rng &rng);
68 Alm<xcomplex<double> > &alm, planck_rng &rng);
73 Alm<xcomplex<T> > &almT,
74 Alm<xcomplex<T> > &almG,
75 Alm<xcomplex<T> > &almC,
78 int lmax = almT.Lmax();
79 int mmax = almT.Mmax();
80 const double hsqrt2 = 1/sqrt(2.);
84 for (
int l=0; l<=lmax; ++l)
86 double rms_tt=0, rms_g1=0, rms_c1=0;
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;
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)
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));
108 for (
int l=0; l<=lmax; ++l)
110 double rms_g2=0, rms_c2=0, rms_c3=0;
113 rms_g2 = ps.
gg(l) - (ps.
tg(l)/ps.
tt(l))*ps.
tg(l);
116 planck_assert (abs(rms_g2) <= 1e-8*abs(ps.
gg(l)),
117 "Inconsistent TT, GG and TG spectra at l="+dataToString(l));
120 double rms_c1 = full ? (ps.
tc(l) / sqrt(ps.
tt(l))) : 0.;
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;
126 rms_c3 = ps.
cc(l) - rms_c1*rms_c1 - rms_c2*rms_c2;
129 planck_assert (abs(rms_c3) <= 1e-8*abs(ps.
cc(l)),
130 "Inconsistent spectra at l="+dataToString(l));
133 rms_c3 = sqrt(rms_c3);
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);
140 for (
int m=1; m<=min(l,mmax); ++m)
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;
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));
156 Alm<xcomplex<float> > &almT,
157 Alm<xcomplex<float> > &almG,
158 Alm<xcomplex<float> > &almC,
162 Alm<xcomplex<double> > &almT,
163 Alm<xcomplex<double> > &almG,
164 Alm<xcomplex<double> > &almC,
169 (
const Alm<xcomplex<T> > &alm1,
170 const Alm<xcomplex<T> > &alm2,
PowSpec &powspec)
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)
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());
187 (
const Alm<xcomplex<float> > &alm1,
188 const Alm<xcomplex<float> > &alm2,
PowSpec &powspec);
190 (
const Alm<xcomplex<double> > &alm1,
191 const Alm<xcomplex<double> > &alm2,
PowSpec &powspec);
199 (
const Alm<xcomplex<float> > &alm,
PowSpec &powspec);
201 (
const Alm<xcomplex<double> > &alm,
PowSpec &powspec);
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,
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");
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)
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)
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());
252 powspec.
Set(tt,gg,cc,tg,tc,gc);
258 (
const Alm<xcomplex<T> > &almT,
259 const Alm<xcomplex<T> > &almG,
260 const Alm<xcomplex<T> > &almC,
265 (
const Alm<xcomplex<float> > &almT,
266 const Alm<xcomplex<float> > &almG,
267 const Alm<xcomplex<float> > &almC,
270 (
const Alm<xcomplex<double> > &almT,
271 const Alm<xcomplex<double> > &almG,
272 const Alm<xcomplex<double> > &almC,
276 template<
typename T>
void smoothWithGauss
277 (
Alm<xcomplex<T> > &alm,
double fwhm)
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);
287 template void smoothWithGauss
288 (
Alm<xcomplex<float> > &alm,
double fwhm);
289 template void smoothWithGauss
290 (
Alm<xcomplex<double> > &alm,
double fwhm);
293 template<
typename T>
void smoothWithGauss
295 Alm<xcomplex<T> > &almG,
296 Alm<xcomplex<T> > &almC,
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);
306 for (
int l=0; l<=almT.Lmax(); ++l)
308 almG.ScaleL(gb); almC.ScaleL(gb);
311 template<
typename T>
void applyCosineWindow
312 (
Alm<xcomplex<T> > &alm,
int lmin,
int lmax)
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)
320 cw[i]=(1+cos(pi*(i-lmin)/
double(lmax-lmin)))/2;
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);
332 template void smoothWithGauss
333 (
Alm<xcomplex<float> > &almT,
334 Alm<xcomplex<float> > &almG,
335 Alm<xcomplex<float> > &almC,
337 template void smoothWithGauss
338 (
Alm<xcomplex<double> > &almT,
339 Alm<xcomplex<double> > &almG,
340 Alm<xcomplex<double> > &almC,
343 template<
typename T>
void rotate_alm (
Alm<xcomplex<T> > &alm,
344 double psi,
double theta,
double phi)
346 planck_assert (alm.Lmax()==alm.Mmax(),
347 "rotate_alm: lmax must be equal to mmax");
349 arr<xcomplex<double> > exppsi(lmax+1), expphi(lmax+1);
350 for (
int m=0; m<=lmax; ++m)
352 exppsi[m] = dcomplex(cos(psi*m),-sin(psi*m));
353 expphi[m] = dcomplex(cos(phi*m),-sin(phi*m));
356 wigner_d_risbo_openmp rec(lmax,theta);
358 arr<xcomplex<double> > almtmp(lmax+1);
360 for (
int l=0; l<=lmax; ++l)
362 const arr2<double> &d(rec.recurse());
364 for (
int m=0; m<=l; ++m)
365 almtmp[m] = xcomplex<double>(alm(l,0))*d[l][l+m];
370 openmp_calc_share(0,l+1,lo,hi);
373 for (
int mm=1; mm<=l; ++mm)
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)
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);
389 for (
int m=0; m<=l; ++m)
390 alm(l,m) = xcomplex<T>(almtmp[m]*expphi[m]);
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);
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)
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)
411 exppsi[m] = dcomplex(cos(psi*m),-sin(psi*m));
412 expphi[m] = dcomplex(cos(phi*m),-sin(phi*m));
415 wigner_d_risbo_openmp rec(lmax,theta);
417 arr<xcomplex<double> > almtmpT(lmax+1), almtmpG(lmax+1), almtmpC(lmax+1);
419 for (
int l=0; l<=lmax; ++l)
421 const arr2<double> &d(rec.recurse());
423 for (
int m=0; m<=l; ++m)
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];
433 openmp_calc_share(0,l+1,lo,hi);
436 for (
int mm=1; mm<=l; ++mm)
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)
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);
456 for (
int m=0; m<=l; ++m)
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]);
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);
473 template<
typename T>
void rotate_alm (
Alm<xcomplex<T> > &alm,
474 const rotmatrix &mat)
477 mat.Extract_CPAC_Euler_Angles (a1, a2, a3);
478 rotate_alm (alm, a3, a2, a1);
481 template void rotate_alm (
Alm<xcomplex<float> > &alm,
const rotmatrix &mat);
482 template void rotate_alm (
Alm<xcomplex<double> > &alm,
const rotmatrix &mat);
484 template<
typename T>
void rotate_alm (
Alm<xcomplex<T> > &almT,
485 Alm<xcomplex<T> > &almG,
Alm<xcomplex<T> > &almC,
486 const rotmatrix &mat)
489 mat.Extract_CPAC_Euler_Angles (a1, a2, a3);
490 rotate_alm (almT, almG, almC, a3, a2, a1);
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)
const arr< double > & gg() const
const arr< double > & tc() const
void create_alm_pol(const PowSpec &ps, Alm< xcomplex< T > > &almT, Alm< xcomplex< T > > &almG, Alm< xcomplex< T > > &almC, planck_rng &rng)
const arr< double > & tt() const
const arr< double > & tg() const
const arr< double > & cc() const
void extract_powspec(const Alm< xcomplex< T > > &alm, PowSpec &powspec)
const arr< double > & gc() const
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)