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