| [658] | 1 | #include <math.h> | 
|---|
|  | 2 | #include "syngen.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 alm2mapgen(const int nsmax,const int nlmax,const int nmmax, | 
|---|
|  | 12 | const vector< vector< complex<double> > >&alm, | 
|---|
|  | 13 | SphericalMap<double>& map, | 
|---|
|  | 14 | vector< complex<long double> > b_north, | 
|---|
|  | 15 | vector< complex<long double> > b_south, | 
|---|
|  | 16 | vector< complex<long double> > bw, | 
|---|
|  | 17 | vector< complex<long double> > data, | 
|---|
|  | 18 | vector< complex<long double> > work){ | 
|---|
|  | 19 | /*======================================================================= | 
|---|
|  | 20 | computes a map form its alm for the HEALPIX pixelisation | 
|---|
|  | 21 | map(theta,phi) = sum_l_m a_lm Y_lm(theta,phi) | 
|---|
|  | 22 | = sum_m {e^(i*m*phi) sum_l a_lm*lambda_lm(theta)} | 
|---|
|  | 23 |  | 
|---|
|  | 24 | where Y_lm(theta,phi) = lambda(theta) * e^(i*m*phi) | 
|---|
|  | 25 |  | 
|---|
|  | 26 | * the recurrence of Ylm is the standard one (cf Num Rec) | 
|---|
|  | 27 | * the sum over m is done by FFT | 
|---|
|  | 28 |  | 
|---|
|  | 29 | =======================================================================*/ | 
|---|
|  | 30 |  | 
|---|
|  | 31 | //  map.resize(12*nsmax*nsmax); | 
|---|
|  | 32 | b_north.resize(2*nmmax+1); //index m corresponds to nmmax+m | 
|---|
|  | 33 | b_south.resize(2*nmmax+1); | 
|---|
|  | 34 | bw.resize(4*nsmax); | 
|---|
|  | 35 | data.resize(4*nsmax); | 
|---|
|  | 36 | work.resize(4*nsmax); | 
|---|
|  | 37 |  | 
|---|
|  | 38 |  | 
|---|
|  | 39 | /*      INTEGER l, indl */ | 
|---|
|  | 40 |  | 
|---|
|  | 41 | for (int ith = 0; ith <= (map.NbThetaSlices()+1)/2-1;ith++){ | 
|---|
|  | 42 | int nph; | 
|---|
|  | 43 | double phi0; | 
|---|
|  | 44 | double theta,thetas; | 
|---|
|  | 45 | Vector phin, datan,datas; | 
|---|
|  | 46 | TVector<double> phis; | 
|---|
|  | 47 | map.GetThetaSlice(map.NbThetaSlices()-ith-1,thetas,phis,datas); | 
|---|
|  | 48 | map.GetThetaSlice(ith,theta,phin,datan); | 
|---|
|  | 49 | nph = phin.NElts(); | 
|---|
|  | 50 | phi0 = phin(0); | 
|---|
|  | 51 | double cth = cos(theta); | 
|---|
|  | 52 |  | 
|---|
|  | 53 | /*        ----------------------------------------------------- | 
|---|
|  | 54 | for each theta, and each m, computes | 
|---|
|  | 55 | b(m,theta) = sum_over_l>m (lambda_l_m(theta) * a_l_m) | 
|---|
|  | 56 | ------------------------------------------------------ | 
|---|
|  | 57 | lambda_mm tends to go down when m increases (risk of underflow) | 
|---|
|  | 58 | lambda_lm tends to go up   when l increases (risk of overflow)*/ | 
|---|
|  | 59 | // lambda_0_0 * big number --> to avoid underflow | 
|---|
|  | 60 | LambdaBuilder lb(acos(cth),nlmax,nmmax); | 
|---|
|  | 61 | for (int m = 0; m <= nmmax; m++){ | 
|---|
|  | 62 | complex<double> b_n = lb.lamlm(m,m) * alm[m][m]; | 
|---|
|  | 63 | complex<double>  b_s = lb.lamlm(m,m) * alm[m][m]; //m,m even | 
|---|
|  | 64 | for (int l = m+1; l<= nlmax; l++){ | 
|---|
|  | 65 | b_n += lb.lamlm(l,m)*alm[l][m]; | 
|---|
|  | 66 | b_s += lb.lamlm(l,m,-1)*alm[l][m]; | 
|---|
|  | 67 | } | 
|---|
|  | 68 | b_north[m+nmmax] = b_n; | 
|---|
|  | 69 | b_south[m+nmmax] = b_s; | 
|---|
|  | 70 | } | 
|---|
|  | 71 |  | 
|---|
|  | 72 | //        obtains the negative m of b(m,theta) (= complex conjugate) | 
|---|
|  | 73 |  | 
|---|
|  | 74 | for (int m=-nmmax;m<=-1;m++){ | 
|---|
|  | 75 | //compiler doesn't have conj() | 
|---|
|  | 76 | complex<long double> | 
|---|
|  | 77 | shit(b_north[-m+nmmax].real(),-b_north[-m+nmmax].imag()); | 
|---|
|  | 78 | complex<long double> | 
|---|
|  | 79 | shit2(b_south[-m+nmmax].real(),-b_south[-m+nmmax].imag()); | 
|---|
|  | 80 | b_north[m+nmmax] = shit; | 
|---|
|  | 81 | b_south[m+nmmax] = shit2; | 
|---|
|  | 82 | } | 
|---|
|  | 83 | /*        --------------------------------------------------------------- | 
|---|
|  | 84 | sum_m  b(m,theta)*exp(i*m*phi)   -> f(phi,theta) | 
|---|
|  | 85 | ---------------------------------------------------------------*/ | 
|---|
|  | 86 | /*cout <<"gen "; | 
|---|
|  | 87 | for (int i=0;i<2*nmmax+1;i++){ | 
|---|
|  | 88 | cout << b_north[i]<<" ";} | 
|---|
|  | 89 | cout<<endl;*/ | 
|---|
|  | 90 |  | 
|---|
|  | 91 | syn_phasgen(nsmax,nlmax,nmmax,b_north,nph,datan,phi0,bw); // north hemisph. + equator | 
|---|
|  | 92 | if (ith != map.NbThetaSlices()/2){ | 
|---|
|  | 93 | syn_phasgen(nsmax,nlmax,nmmax,b_south,nph,datas,phi0,bw); // south hemisph. w/o equat | 
|---|
|  | 94 | for (int i=0;i< nph;i++){ | 
|---|
|  | 95 | map.PixVal(map.PixIndexSph(thetas,phis(i)))=datas(2*i); | 
|---|
|  | 96 | } | 
|---|
|  | 97 | } | 
|---|
|  | 98 | //cout <<"gen "<<datan<<endl; | 
|---|
|  | 99 | for (int i=0;i< nph;i++){ | 
|---|
|  | 100 | map.PixVal(map.PixIndexSph(theta,phin(i)))=datan(2*i); | 
|---|
|  | 101 | } | 
|---|
|  | 102 | } | 
|---|
|  | 103 | } | 
|---|
|  | 104 |  | 
|---|
|  | 105 | void syn_phasgen(const int nsmax,const int nlmax,const int nmmax, | 
|---|
|  | 106 | const vector< complex<long double> >& datain, | 
|---|
|  | 107 | int nph, Vector& dataout, double phi0, | 
|---|
|  | 108 | vector< complex<long double> >& bw){ | 
|---|
|  | 109 |  | 
|---|
|  | 110 | /*======================================================================= | 
|---|
|  | 111 | dataout(j) = sum_m datain(m) * exp(i*m*phi(j)) | 
|---|
|  | 112 | with phi(j) = j*2pi/nph + kphi0*pi/nph and kphi0 =0 or 1 | 
|---|
|  | 113 |  | 
|---|
|  | 114 | as the set of frequencies {m} is larger than nph, | 
|---|
|  | 115 | we wrap frequencies within {0..nph-1} | 
|---|
|  | 116 | ie  m = k*nph + m' with m' in {0..nph-1} | 
|---|
|  | 117 | then | 
|---|
|  | 118 | noting bw(m') = exp(i*m'*phi0) | 
|---|
|  | 119 | * sum_k (datain(k*nph+m') exp(i*k*pi*kphi0)) | 
|---|
|  | 120 | with bw(nph-m') = CONJ(bw(m')) (if datain(-m) = CONJ(datain(m))) | 
|---|
|  | 121 | dataout(j) = sum_m' [ bw(m') exp (i*j*m'*2pi/nph) ] | 
|---|
|  | 122 | = Fourier Transform of bw | 
|---|
|  | 123 | is real | 
|---|
|  | 124 |  | 
|---|
|  | 125 | NB nph is not necessarily a power of 2 | 
|---|
|  | 126 |  | 
|---|
|  | 127 | =======================================================================*/ | 
|---|
|  | 128 |  | 
|---|
|  | 129 | int ksign =  1; | 
|---|
|  | 130 | //long double * data = new long double[nph*2]; | 
|---|
|  | 131 | complex<double>* data = new complex<double>[nph]; | 
|---|
|  | 132 | long double * work = new long double[nph*2]; | 
|---|
|  | 133 |  | 
|---|
|  | 134 | int iw; | 
|---|
|  | 135 | for (iw=0;iw<nph;iw++){bw[iw]=0;} | 
|---|
|  | 136 |  | 
|---|
|  | 137 | long double shit=phi0*nph; | 
|---|
|  | 138 | //try complex<long double> since generally this will not be an int | 
|---|
|  | 139 | //int kshift = (int) pow(-1,shit); | 
|---|
|  | 140 | //cout<<shit<<" "<<phi0*nph/M_PI<<" "<<kshift<<endl; | 
|---|
|  | 141 | //  int kshift = (int) pow(-1,kphi0);//  ! either 1 or -1 | 
|---|
|  | 142 | //     all frequencies [-m,m] are wrapped in [0,nph-1] | 
|---|
|  | 143 | for (int i=1;i<=2*nmmax+1;i++){ | 
|---|
|  | 144 | int m=i-nmmax-1; //in -nmmax, nmmax | 
|---|
|  | 145 | iw=((m % nph) +nph) % nph; //between 0 and nph = m' | 
|---|
|  | 146 | int k=(m-iw)/nph; //number of 'turns' | 
|---|
|  | 147 | //  cout <<(complex<long double>)pow(kshift,k)<<" "; | 
|---|
|  | 148 | //    bw[iw]+=datain[i-1]* (complex<long double>)(pow(kshift,k));//complex number | 
|---|
|  | 149 | bw[iw]+=datain[i-1]* complex<long double>(cos(shit*k),sin(shit*k));//complex number | 
|---|
|  | 150 | } | 
|---|
|  | 151 |  | 
|---|
|  | 152 |  | 
|---|
|  | 153 | //     applies the shift in position <-> phase factor in Fourier space | 
|---|
|  | 154 | for (int iw=1;iw<=nph;iw++){ | 
|---|
|  | 155 | int m=ksign*(iw-1); | 
|---|
|  | 156 | complex<long double> shit(cos(m*phi0),sin(m*phi0)); | 
|---|
|  | 157 | data[iw-1]=bw[iw-1]*shit; | 
|---|
|  | 158 | //    data[2*(iw-1)]=(bw[iw-1]*shit).real(); | 
|---|
|  | 159 | //data[2*(iw-1)+1]=(bw[iw-1]*shit).imag(); | 
|---|
|  | 160 | } | 
|---|
|  | 161 |  | 
|---|
|  | 162 | //FFTVector inv((double*) data,nph,true); | 
|---|
|  | 163 | //FFTVector outv=FFTServer::solve(inv,1); | 
|---|
|  | 164 | //outv.Vreal(dataout); | 
|---|
|  | 165 |  | 
|---|
|  | 166 | FFTServer fft; | 
|---|
|  | 167 | fft.fftf(nph, data); | 
|---|
|  | 168 | dataout.Realloc(2*nph); | 
|---|
|  | 169 | for (int i=0;i<nph;i++) { | 
|---|
|  | 170 | dataout(2*i)=data[i].real();dataout(2*i+1)=data[i].imag(); | 
|---|
|  | 171 | } | 
|---|
|  | 172 | delete[] data; | 
|---|
|  | 173 | delete[] work; | 
|---|
|  | 174 |  | 
|---|
|  | 175 | /* | 
|---|
|  | 176 | int dum0=1; | 
|---|
|  | 177 | int dum1=1; | 
|---|
|  | 178 |  | 
|---|
|  | 179 | fft_gpd_(data,nph,dum0,ksign,dum1,work); // complex to complex | 
|---|
|  | 180 |  | 
|---|
|  | 181 | for (int iw=0;iw<nph;iw++){dataout(iw) = data[2*iw];}*/ | 
|---|
|  | 182 | } | 
|---|
|  | 183 |  | 
|---|
|  | 184 | void create_almgen(const int nsmax,const int nlmax,const int nmmax, | 
|---|
|  | 185 | vector< vector< complex<double> > >& alm, | 
|---|
|  | 186 | vector<float>& cls_tt,int& iseed,const float fwhm, | 
|---|
|  | 187 | vector<float> lread){ | 
|---|
|  | 188 |  | 
|---|
|  | 189 |  | 
|---|
|  | 190 | /*======================================================================= | 
|---|
|  | 191 | creates the a_lm from the power spectrum, | 
|---|
|  | 192 | assuming they are gaussian  and complex | 
|---|
|  | 193 | with a variance given by C(l) | 
|---|
|  | 194 |  | 
|---|
|  | 195 | the input file should contain : l and C(l) with *consecutive* l's | 
|---|
|  | 196 | (missing C(l) are put to 0.) | 
|---|
|  | 197 |  | 
|---|
|  | 198 | because the map is real we have : a_l-m = (-)^m conjug(a_lm) | 
|---|
|  | 199 | so we actually compute them only for m >= 0 | 
|---|
|  | 200 |  | 
|---|
|  | 201 | modifie G. Le Meur (13/01/98) : | 
|---|
|  | 202 | on ne lit plus les C(l) sur un fichier. Le tableau est entre en argument | 
|---|
|  | 203 | (cls_tt). Ce tableau doit contenir les valeur de C(l) par ordre | 
|---|
|  | 204 | SEQUENTIEL de l (de l=0 a l=nlmax) | 
|---|
|  | 205 | =======================================================================*/ | 
|---|
|  | 206 | /*      CHARACTER*128 filename | 
|---|
|  | 207 |  | 
|---|
|  | 208 | integer unit,n_l,j,il,im | 
|---|
|  | 209 | real    fs,quadrupole,xxxtmp,correct | 
|---|
|  | 210 | real    fs_tt | 
|---|
|  | 211 | real    zeta1_r, zeta1_i | 
|---|
|  | 212 | LOGICAL ok | 
|---|
|  | 213 | character*20 string_quad | 
|---|
|  | 214 |  | 
|---|
|  | 215 | real*4    prefact(0:2) | 
|---|
|  | 216 | logical   prefact_bool | 
|---|
|  | 217 |  | 
|---|
|  | 218 | integer lneffct | 
|---|
|  | 219 | real    gasdev2 | 
|---|
|  | 220 | external lneffct, gasdev2 | 
|---|
|  | 221 |  | 
|---|
|  | 222 | c-----------------------------------------------------------------------*/ | 
|---|
|  | 223 | alm.resize(nlmax+1); | 
|---|
|  | 224 | for (int i=0; i< (signed) alm.size();i++){ | 
|---|
|  | 225 | alm[i].resize(nmmax+1); | 
|---|
|  | 226 | } | 
|---|
|  | 227 | //cout << "cing createalm"<<endl; | 
|---|
|  | 228 | iseed = -abs(iseed); | 
|---|
|  | 229 | if (iseed == 0){iseed=-1;} | 
|---|
|  | 230 | int idum = iseed; | 
|---|
|  | 231 |  | 
|---|
|  | 232 | float sig_smooth = fwhm/sqrt(8.*log(2.))/(60.*180.)* M_PI; | 
|---|
|  | 233 |  | 
|---|
|  | 234 | for (int i=0;i<nlmax+1;i++){lread[i]=0;} | 
|---|
|  | 235 |  | 
|---|
|  | 236 | for (int i=0;i <= nlmax;i++){lread[i]  = i;} | 
|---|
|  | 237 |  | 
|---|
|  | 238 | int n_l = nlmax+1; | 
|---|
|  | 239 |  | 
|---|
|  | 240 | cout<<lread[0]<<" <= l <= "<<lread[n_l-1]<<endl; | 
|---|
|  | 241 |  | 
|---|
|  | 242 | //    --- smoothes the initial power spectrum --- | 
|---|
|  | 243 |  | 
|---|
|  | 244 | for (int i=0;i<n_l;i++){ | 
|---|
|  | 245 | int l= (int) lread[i]; | 
|---|
|  | 246 | float gauss=exp(-l*(l+1.)*sig_smooth*sig_smooth); | 
|---|
|  | 247 | cls_tt[i]*=gauss; | 
|---|
|  | 248 | } | 
|---|
|  | 249 |  | 
|---|
|  | 250 |  | 
|---|
|  | 251 | //     --- generates randomly the alm according to their power spectrum --- | 
|---|
|  | 252 | float hsqrt2 = 1.0 / sqrt(2.0); | 
|---|
|  | 253 |  | 
|---|
|  | 254 | for (int i=0;i<n_l;i++){ | 
|---|
|  | 255 | int l=(int) lread[i]; | 
|---|
|  | 256 | float rms_tt=sqrt(cls_tt[i]); | 
|---|
|  | 257 | //        ------ m = 0 ------ | 
|---|
|  | 258 | complex<float> zeta1(gasdev2_(idum)); | 
|---|
|  | 259 | //cout << "c2 "<<idum << " "<<zeta1 <<endl; | 
|---|
|  | 260 | alm[l][0]   = zeta1 * rms_tt; | 
|---|
|  | 261 |  | 
|---|
|  | 262 | //------ m > 0 ------ | 
|---|
|  | 263 | for (int m=1;m<=l;m++){ | 
|---|
|  | 264 | complex<float> shit1(hsqrt2); | 
|---|
|  | 265 | //    cout << "c "<<idum << endl; | 
|---|
|  | 266 | complex<float> shit2(gasdev2_(idum),gasdev2_(idum)); | 
|---|
|  | 267 | zeta1=shit1*shit2; | 
|---|
|  | 268 | alm[l][m]=rms_tt*zeta1; | 
|---|
|  | 269 | } | 
|---|
|  | 270 | } | 
|---|
|  | 271 | } | 
|---|