[483] | 1 | #include <math.h>
|
---|
| 2 | #include "syn2fast.h"
|
---|
| 3 | #include "lambuilder.h"
|
---|
| 4 | #include "fftserver.h"
|
---|
| 5 |
|
---|
| 6 | extern "C" {
|
---|
| 7 | // void fft_gpd_(long double* ,int& ,int& ,int& ,int& ,long double*);
|
---|
| 8 | float gasdev2_(int& idum);
|
---|
| 9 | }
|
---|
| 10 |
|
---|
| 11 | void a2lm2map(const int nsmax,const int nlmax,const int nmmax,
|
---|
| 12 | const vector< vector< complex<double> > >&alme,
|
---|
| 13 | const vector< vector< complex<double> > >&almb,
|
---|
| 14 | vector<float>& mapq,
|
---|
| 15 | vector<float>& mapu,
|
---|
| 16 | vector< complex<long double> > b_northp,
|
---|
| 17 | vector< complex<long double> > b_southp,
|
---|
| 18 | vector< complex<long double> > bwp,
|
---|
| 19 | vector< complex<long double> > b_northm,
|
---|
| 20 | vector< complex<long double> > b_southm,
|
---|
| 21 | vector< complex<long double> > bwm){
|
---|
| 22 | /*=======================================================================
|
---|
| 23 | computes a map form its alm for the HEALPIX pixelisation
|
---|
| 24 | map(theta,phi) = sum_l_m a_lm Y_lm(theta,phi)
|
---|
| 25 | = sum_m {e^(i*m*phi) sum_l a_lm*lambda_lm(theta)}
|
---|
| 26 |
|
---|
| 27 | where Y_lm(theta,phi) = lambda(theta) * e^(i*m*phi)
|
---|
| 28 |
|
---|
| 29 | * the recurrence of Ylm is the standard one (cf Num Rec)
|
---|
| 30 | * the sum over m is done by FFT
|
---|
| 31 |
|
---|
| 32 | =======================================================================*/
|
---|
| 33 | vector< complex<float> > mapp;
|
---|
| 34 | vector< complex<float> > mapm;
|
---|
| 35 |
|
---|
| 36 | //convert the alm from e/b to +/-
|
---|
| 37 | complex<double> im(0,1);
|
---|
| 38 | vector< vector< complex<double> > >almp=alme;
|
---|
| 39 | vector< vector< complex<double> > >almm=almb;
|
---|
| 40 | for (int i=0;i<(signed) almp.size();i++){
|
---|
| 41 | for (int j=0;j<(signed) almp[i].size();j++){
|
---|
| 42 | almp[i][j]=-(alme[i][j]+im*almb[i][j]);
|
---|
| 43 | almm[i][j]=-(alme[i][j]-im*almb[i][j]);
|
---|
| 44 | }
|
---|
| 45 | }
|
---|
| 46 | //for (int i=0;i<(signed) almp.size();i++){cout<<alme[i][0]<<" "<<almb[i][0]<<" "<<almp[i][0]<<" "<<almm[i][0]<<endl;}
|
---|
| 47 | mapp.resize(12*nsmax*nsmax);
|
---|
| 48 | b_northp.resize(2*nmmax+1); //index m corresponds to nmmax+m
|
---|
| 49 | b_southp.resize(2*nmmax+1);
|
---|
| 50 | bwp.resize(4*nsmax);
|
---|
| 51 | mapm.resize(12*nsmax*nsmax);
|
---|
| 52 | b_northm.resize(2*nmmax+1); //index m corresponds to nmmax+m
|
---|
| 53 | b_southm.resize(2*nmmax+1);
|
---|
| 54 | bwm.resize(4*nsmax);
|
---|
| 55 |
|
---|
| 56 |
|
---|
| 57 | /* INTEGER l, indl */
|
---|
| 58 |
|
---|
| 59 | int istart_north = 0;
|
---|
| 60 | int istart_south = 12*nsmax*nsmax;
|
---|
| 61 |
|
---|
| 62 | double dth1 = 1. / (3.*nsmax*nsmax);
|
---|
| 63 | double dth2 = 2. / (3.*nsmax);
|
---|
| 64 | double dst1 = 1. / (sqrt(6.) * nsmax);
|
---|
| 65 |
|
---|
| 66 | for (int ith = 1; ith <= 2*nsmax;ith++){
|
---|
| 67 | int nph, kphi0;
|
---|
| 68 | double cth, sth, sth2;
|
---|
| 69 | if (ith <= nsmax-1){ /* north polar cap */
|
---|
| 70 | nph = 4*ith;
|
---|
| 71 | kphi0 = 1;
|
---|
| 72 | cth = 1. - dth1*ith*ith; /* cos(theta) */
|
---|
| 73 | sth = sin( 2. * asin( ith * dst1 ) ) ; /* sin(theta) */
|
---|
| 74 | sth2 = sth*sth;
|
---|
| 75 | } else { /* tropical band + equat. */
|
---|
| 76 | nph = 4*nsmax;
|
---|
| 77 | kphi0 = (ith+1-nsmax) % 2;
|
---|
| 78 | cth = (2.*nsmax-ith) * dth2;
|
---|
| 79 | sth = sqrt((1.-cth)*(1.+cth)); /* ! sin(theta)*/
|
---|
| 80 | sth2=(1.-cth)*(1.+cth);
|
---|
| 81 | }
|
---|
| 82 |
|
---|
| 83 | /* -----------------------------------------------------
|
---|
| 84 | for each theta, and each m, computes
|
---|
| 85 | b(m,theta) = sum_over_l>m (lambda_l_m(theta) * a_l_m)
|
---|
| 86 | ------------------------------------------------------
|
---|
| 87 | lambda_mm tends to go down when m increases (risk of underflow)
|
---|
| 88 | lambda_lm tends to go up when l increases (risk of overflow)*/
|
---|
| 89 | Lambda2Builder l2b(acos(cth),nlmax,nmmax);
|
---|
| 90 | for (int m = 0; m <= nmmax; m++){
|
---|
| 91 | complex<double> b_np,b_sp,b_nm,b_sm;
|
---|
| 92 | // cout <<l2b.lam2lmp(m,m)<<endl;
|
---|
| 93 | b_np = l2b.lam2lmp(m,m)* almp[m][m];
|
---|
| 94 | b_sp = l2b.lam2lmp(m,m,-1)* almp[m][m];
|
---|
| 95 | b_nm = l2b.lam2lmm(m,m)* almm[m][m];
|
---|
| 96 | b_sm = l2b.lam2lmm(m,m,-1)* almm[m][m];
|
---|
| 97 | for (int l = m+1; l<= nlmax; l++){
|
---|
| 98 | //cout<<l2b.lam2lmp(l,m)<<endl;
|
---|
| 99 | b_np += l2b.lam2lmp(l,m)*almp[l][m];
|
---|
| 100 | b_sp += l2b.lam2lmp(l,m,-1)*almp[l][m];
|
---|
| 101 | b_nm += l2b.lam2lmm(l,m)*almm[l][m];
|
---|
| 102 | b_sm += l2b.lam2lmm(l,m,-1)*almm[l][m];
|
---|
| 103 | }
|
---|
| 104 |
|
---|
| 105 | b_northp[m+nmmax] = b_np;
|
---|
| 106 | b_southp[m+nmmax] = b_sp;
|
---|
| 107 | b_northm[m+nmmax] = b_nm;
|
---|
| 108 | b_southm[m+nmmax] = b_sm;
|
---|
| 109 | }
|
---|
| 110 |
|
---|
| 111 | // obtains the negative m of b(m,theta) (= complex conjugate)
|
---|
| 112 | for (int m=-nmmax;m<=-1;m++){
|
---|
| 113 | int fac = 1;//(int) pow(-1,m);// ! either 1 or -1
|
---|
| 114 | complex<long double>
|
---|
| 115 | shit(b_northp[-m+nmmax].real(),-b_northp[-m+nmmax].imag());
|
---|
| 116 | complex<long double>
|
---|
| 117 | shit2(b_southp[-m+nmmax].real(),-b_southp[-m+nmmax].imag());
|
---|
| 118 | shit*=fac; shit2*=fac;
|
---|
| 119 | b_northm[m+nmmax] = shit;
|
---|
| 120 | b_southm[m+nmmax] = shit2;
|
---|
| 121 | shit=complex<long double>(b_northm[-m+nmmax].real(),-b_northm[-m+nmmax].imag());
|
---|
| 122 | shit2=complex<long double>(b_southm[-m+nmmax].real(),-b_southm[-m+nmmax].imag());
|
---|
| 123 | shit*=fac; shit2*=fac;
|
---|
| 124 | b_northp[m+nmmax] = shit;
|
---|
| 125 | b_southp[m+nmmax] = shit2;
|
---|
| 126 | }
|
---|
| 127 |
|
---|
| 128 | // for (int i=0;i<2*nmmax+1;i++){ cout<< b_northp[i]<<" "<<b_southp[i]<<" "<<b_northm[i]
|
---|
| 129 | // <<" "<<b_southm[i]<<endl;}
|
---|
| 130 | /* ---------------------------------------------------------------
|
---|
| 131 | sum_m b(m,theta)*exp(i*m*phi) -> f(phi,theta)
|
---|
| 132 | ---------------------------------------------------------------*/
|
---|
| 133 | syn2_phas(nsmax,nlmax,nmmax,b_northp,nph,mapp,istart_north,kphi0,bwp); // north hemisph. + equator
|
---|
| 134 | syn2_phas(nsmax,nlmax,nmmax,b_northm,nph,mapm,istart_north,kphi0,bwm);
|
---|
| 135 | istart_north = istart_north + nph;
|
---|
| 136 | if (ith < 2*nsmax){
|
---|
| 137 | istart_south=istart_south-nph;
|
---|
| 138 | syn2_phas(nsmax,nlmax,nmmax,b_southp,nph,mapp,istart_south,kphi0,bwp); // south hemisph. w/o equat
|
---|
| 139 | syn2_phas(nsmax,nlmax,nmmax,b_southm,nph,mapm,istart_south,kphi0,bwm);
|
---|
| 140 | }
|
---|
| 141 | }
|
---|
| 142 | for (int i=0;i< (signed)mapp.size();i++){
|
---|
| 143 | //cout << mapp[i]<<" "<<mapm[i]<<endl;
|
---|
| 144 | mapq[i]=(mapp[i]+mapm[i]).real()/2;
|
---|
| 145 | mapu[i]=(mapp[i]-mapm[i]).imag()/2;
|
---|
| 146 | //cout << mapq[i]<<" "<<mapu[i]<<endl;
|
---|
| 147 | }
|
---|
| 148 | }
|
---|
| 149 |
|
---|
| 150 | void syn2_phas(const int nsmax,const int nlmax,const int nmmax,
|
---|
| 151 | const vector< complex<long double> >& datain,
|
---|
| 152 | int nph,vector< complex<float> >& dataout, const int start,
|
---|
| 153 | int kphi0,
|
---|
| 154 | vector< complex<long double> >& bw){
|
---|
| 155 |
|
---|
| 156 | /*=======================================================================
|
---|
| 157 | dataout(j) = sum_m datain(m) * exp(i*m*phi(j))
|
---|
| 158 | with phi(j) = j*2pi/nph + kphi0*pi/nph and kphi0 =0 or 1
|
---|
| 159 |
|
---|
| 160 | as the set of frequencies {m} is larger than nph,
|
---|
| 161 | we wrap frequencies within {0..nph-1}
|
---|
| 162 | ie m = k*nph + m' with m' in {0..nph-1}
|
---|
| 163 | then
|
---|
| 164 | noting bw(m') = exp(i*m'*phi0)
|
---|
| 165 | * sum_k (datain(k*nph+m') exp(i*k*pi*kphi0))
|
---|
| 166 | with bw(nph-m') = CONJ(bw(m')) (if datain(-m) = CONJ(datain(m)))
|
---|
| 167 | dataout(j) = sum_m' [ bw(m') exp (i*j*m'*2pi/nph) ]
|
---|
| 168 | = Fourier Transform of bw
|
---|
| 169 | is real
|
---|
| 170 |
|
---|
| 171 | NB nph is not necessarily a power of 2
|
---|
| 172 |
|
---|
| 173 | =======================================================================*/
|
---|
| 174 | int ksign = 1;
|
---|
| 175 | complex<double>* data= new complex<double>[4*nsmax];
|
---|
| 176 |
|
---|
| 177 | for (int iw=0;iw<nph;iw++){bw[iw]=0;}
|
---|
| 178 |
|
---|
| 179 | double phi0 = kphi0*M_PI/nph;
|
---|
| 180 | int kshift = (int) pow(-1,kphi0);// ! either 1 or -1
|
---|
| 181 | // all frequencies [-m,m] are wrapped in [0,nph-1]
|
---|
| 182 | for (int i=1;i<=2*nmmax+1;i++){
|
---|
| 183 | int m=i-nmmax-1; //in -nmmax, nmmax
|
---|
| 184 | int iw=((m % nph) +nph) % nph; //between 0 and nph = m'
|
---|
| 185 | int k=(m-iw)/nph; //number of 'turns'
|
---|
| 186 | complex<long double> shit(pow(kshift,k));
|
---|
| 187 | bw[iw]+=datain[i-1]*shit;//complex number
|
---|
| 188 | }
|
---|
| 189 |
|
---|
| 190 | // kshift**k = 1 for even turn numbers
|
---|
| 191 | // = 1 or -1 for odd turn numbers : results from the shift in space
|
---|
| 192 |
|
---|
| 193 | // applies the shift in position <-> phase factor in Fourier space
|
---|
| 194 | for (int iw=1;iw<=nph;iw++){
|
---|
| 195 | int m=ksign*(iw-1);
|
---|
| 196 | complex<long double> shit(cos(m*phi0),sin(m*phi0));
|
---|
| 197 | data[iw-1]=bw[iw-1]*shit;
|
---|
| 198 | }
|
---|
| 199 | for (int i = nph; i< 4*nsmax;i++){
|
---|
| 200 | data[i] = 0;
|
---|
| 201 | }
|
---|
| 202 | //cout<<endl;
|
---|
| 203 | //fft_gpd_(data,nph,dum0,ksign,dum1,work); // complex to complex
|
---|
| 204 | FFTServer fft;
|
---|
| 205 | fft.fftf(nph,data);
|
---|
| 206 |
|
---|
| 207 | for (int iw=0;iw<nph;iw++){
|
---|
| 208 | dataout[iw+start]=data[iw];
|
---|
| 209 | }
|
---|
| 210 | delete[] data;
|
---|
| 211 | }
|
---|
| 212 |
|
---|
| 213 |
|
---|
| 214 | void create_a2lm(const int nsmax,const int nlmax,const int nmmax,
|
---|
| 215 | vector< vector< complex<double> > >& a2lme,
|
---|
| 216 | vector< vector< complex<double> > >& a2lmb,
|
---|
| 217 | vector<float>& cls_e,
|
---|
| 218 | vector<float>& cls_b,
|
---|
| 219 | int& iseed,const float fwhm,
|
---|
| 220 | vector<float> lread){
|
---|
| 221 |
|
---|
| 222 |
|
---|
| 223 | /*=======================================================================
|
---|
| 224 | creates the a_lm from the power spectrum,
|
---|
| 225 | assuming they are gaussian and complex
|
---|
| 226 | with a variance given by C(l)
|
---|
| 227 |
|
---|
| 228 | the input file should contain : l and C(l) with *consecutive* l's
|
---|
| 229 | (missing C(l) are put to 0.)
|
---|
| 230 |
|
---|
| 231 | because the map is real we have : a_l-m = (-)^m conjug(a_lm)
|
---|
| 232 | so we actually compute them only for m >= 0
|
---|
| 233 |
|
---|
| 234 | modifie G. Le Meur (13/01/98) :
|
---|
| 235 | on ne lit plus les C(l) sur un fichier. Le tableau est entre en argument
|
---|
| 236 | (cls_tt). Ce tableau doit contenir les valeur de C(l) par ordre
|
---|
| 237 | SEQUENTIEL de l (de l=0 a l=nlmax)
|
---|
| 238 | =======================================================================*/
|
---|
| 239 | /* CHARACTER*128 filename
|
---|
| 240 |
|
---|
| 241 | integer unit,n_l,j,il,im
|
---|
| 242 | real fs,quadrupole,xxxtmp,correct
|
---|
| 243 | real fs_tt
|
---|
| 244 | real zeta1_r, zeta1_i
|
---|
| 245 | LOGICAL ok
|
---|
| 246 | character*20 string_quad
|
---|
| 247 |
|
---|
| 248 | real*4 prefact(0:2)
|
---|
| 249 | logical prefact_bool
|
---|
| 250 |
|
---|
| 251 | integer lneffct
|
---|
| 252 | real gasdev2
|
---|
| 253 | external lneffct, gasdev2
|
---|
| 254 |
|
---|
| 255 | c-----------------------------------------------------------------------*/
|
---|
| 256 | a2lme.resize(nlmax+1);
|
---|
| 257 | a2lmb.resize(nlmax+1);
|
---|
| 258 | for (int i=0; i< (signed) a2lme.size();i++){
|
---|
| 259 | a2lme[i].resize(nmmax+1);
|
---|
| 260 | a2lmb[i].resize(nmmax+1);
|
---|
| 261 | }
|
---|
| 262 |
|
---|
| 263 |
|
---|
| 264 | iseed = -abs(iseed);
|
---|
| 265 | if (iseed == 0){iseed=-1;}
|
---|
| 266 | int idum = iseed;
|
---|
| 267 |
|
---|
| 268 | float sig_smooth = fwhm/sqrt(8.*log(2.))/(60.*180.)* M_PI;
|
---|
| 269 |
|
---|
| 270 | for (int i=0;i<nlmax+1;i++){lread[i]=0;}
|
---|
| 271 |
|
---|
| 272 | for (int i=0;i <= nlmax;i++){lread[i] = i;}
|
---|
| 273 |
|
---|
| 274 | int n_l = nlmax+1;
|
---|
| 275 |
|
---|
| 276 | cout<<lread[0]<<" <= l <= "<<lread[n_l-1]<<endl;
|
---|
| 277 |
|
---|
| 278 | // --- smoothes the initial power spectrum ---
|
---|
| 279 |
|
---|
| 280 | for (int i=0;i<n_l;i++){
|
---|
| 281 | int l= (int) lread[i];
|
---|
| 282 | float gauss=exp(-l*(l+1.)*sig_smooth*sig_smooth);
|
---|
| 283 | cls_e[i]*=gauss;
|
---|
| 284 | cls_b[i]*=gauss;
|
---|
| 285 | }
|
---|
| 286 |
|
---|
| 287 |
|
---|
| 288 | // --- generates randomly the alm according to their power spectrum ---
|
---|
| 289 | float hsqrt2 = 1.0 / sqrt(2.0);
|
---|
| 290 |
|
---|
| 291 | for (int i=0;i<n_l;i++){
|
---|
| 292 | int l=(int) lread[i];
|
---|
| 293 | float rms_e=sqrt(cls_e[i]);
|
---|
| 294 | float rms_b=sqrt(cls_b[i]);
|
---|
| 295 | // ------ m = 0 ------
|
---|
| 296 | complex<float> zeta1(gasdev2_(idum));
|
---|
| 297 | a2lme[l][0] = zeta1 * rms_e;
|
---|
| 298 | zeta1=complex<float>(gasdev2_(idum));
|
---|
| 299 | a2lmb[l][0] = zeta1 * rms_b;
|
---|
| 300 |
|
---|
| 301 | //------ m > 0 ------
|
---|
| 302 | for (int m=1;m<=l;m++){
|
---|
| 303 | complex<float> shit1(hsqrt2);
|
---|
| 304 | complex<float> shit2(gasdev2_(idum),gasdev2_(idum));
|
---|
| 305 | zeta1=shit1*shit2;
|
---|
| 306 | a2lme[l][m]=rms_e*zeta1;
|
---|
| 307 | shit2= complex<float>(gasdev2_(idum),gasdev2_(idum));
|
---|
| 308 | zeta1=shit1*shit2;
|
---|
| 309 | a2lmb[l][m]=rms_b*zeta1;
|
---|
| 310 | }
|
---|
| 311 | }
|
---|
| 312 | }
|
---|