00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <math.h>
00034 #include "sharp_geomhelpers.h"
00035 #include "c_utils.h"
00036 #include "ls_fft.h"
00037
00038 void sharp_make_weighted_healpix_geom_info (int nside, int stride,
00039 const double *weight, sharp_geom_info **geom_info)
00040 {
00041 const double pi=3.141592653589793238462643383279502884197;
00042 ptrdiff_t npix=(ptrdiff_t)nside*nside*12;
00043 ptrdiff_t ncap=2*(ptrdiff_t)nside*(nside-1);
00044 int nrings=4*nside-1;
00045
00046 double *theta=RALLOC(double,nrings);
00047 double *weight_=RALLOC(double,nrings);
00048 int *nph=RALLOC(int,nrings);
00049 double *phi0=RALLOC(double,nrings);
00050 ptrdiff_t *ofs=RALLOC(ptrdiff_t,nrings);
00051 int *stride_=RALLOC(int,nrings);
00052 for (int m=0; m<nrings; ++m)
00053 {
00054 int ring=m+1;
00055 ptrdiff_t northring = (ring>2*nside) ? 4*nside-ring : ring;
00056 stride_[m] = stride;
00057 if (northring < nside)
00058 {
00059 theta[m] = 2*asin(northring/(sqrt(6.)*nside));
00060 nph[m] = 4*northring;
00061 phi0[m] = pi/nph[m];
00062 ofs[m] = 2*northring*(northring-1)*stride;
00063 }
00064 else
00065 {
00066 double fact1 = (8.*nside)/npix;
00067 double costheta = (2*nside-northring)*fact1;
00068 theta[m] = acos(costheta);
00069 nph[m] = 4*nside;
00070 if ((northring-nside) & 1)
00071 phi0[m] = 0;
00072 else
00073 phi0[m] = pi/nph[m];
00074 ofs[m] = (ncap + (northring-nside)*nph[m])*stride;
00075 }
00076 if (northring != ring)
00077 {
00078 theta[m] = pi-theta[m];
00079 ofs[m] = (npix - nph[m])*stride - ofs[m];
00080 }
00081 weight_[m]=4.*pi/npix*((weight==NULL) ? 1. : weight[northring-1]);
00082 }
00083
00084 sharp_make_geom_info (nrings, nph, ofs, stride_, phi0, theta, weight_,
00085 geom_info);
00086
00087 DEALLOC(theta);
00088 DEALLOC(weight_);
00089 DEALLOC(nph);
00090 DEALLOC(phi0);
00091 DEALLOC(ofs);
00092 DEALLOC(stride_);
00093 }
00094
00095 static inline double one_minus_x2 (double x)
00096 { return (fabs(x)>0.1) ? (1.+x)*(1.-x) : 1.-x*x; }
00097
00098
00099
00100
00101
00102
00103
00104
00105 static void gauss_legendre_tbl(int n, double *x, double *w)
00106 {
00107 const double pi = 3.141592653589793238462643383279502884197;
00108 const double eps = 3e-14;
00109 int m = (n+1)>>1;
00110
00111 double t0 = 1 - (1-1./n) / (8.*n*n);
00112 double t1 = 1./(4.*n+2.);
00113
00114 #pragma omp parallel
00115 {
00116 int i;
00117 #pragma omp for schedule(dynamic,100)
00118 for (i=1; i<=m; ++i)
00119 {
00120 double x0 = cos(pi * ((i<<2)-1) * t1) * t0;
00121
00122 int dobreak=0;
00123 int j=0;
00124 double dpdx;
00125 while(1)
00126 {
00127 double P_1 = 1.0;
00128 double P0 = x0;
00129 double dx, x1;
00130
00131 for (int k=2; k<=n; k++)
00132 {
00133 double P_2 = P_1;
00134 P_1 = P0;
00135
00136 P0 = x0*P_1 + (k-1.)/k * (x0*P_1-P_2);
00137 }
00138
00139 dpdx = (P_1 - x0*P0) * n / one_minus_x2(x0);
00140
00141
00142 x1 = x0 - P0/dpdx;
00143 dx = x0-x1;
00144 x0 = x1;
00145 if (dobreak) break;
00146
00147 if (fabs(dx)<=eps) dobreak=1;
00148 UTIL_ASSERT(++j<100,"convergence problem");
00149 }
00150
00151 x[i-1] = -x0;
00152 x[n-i] = x0;
00153 w[i-1] = w[n-i] = 2. / (one_minus_x2(x0) * dpdx * dpdx);
00154 }
00155 }
00156 }
00157
00158 void sharp_make_gauss_geom_info (int nrings, int nphi, double phi0,
00159 int stride_lon, int stride_lat, sharp_geom_info **geom_info)
00160 {
00161 const double pi=3.141592653589793238462643383279502884197;
00162
00163 double *theta=RALLOC(double,nrings);
00164 double *weight=RALLOC(double,nrings);
00165 int *nph=RALLOC(int,nrings);
00166 double *phi0_=RALLOC(double,nrings);
00167 ptrdiff_t *ofs=RALLOC(ptrdiff_t,nrings);
00168 int *stride_=RALLOC(int,nrings);
00169
00170 gauss_legendre_tbl(nrings,theta,weight);
00171 for (int m=0; m<nrings; ++m)
00172 {
00173 theta[m] = acos(-theta[m]);
00174 nph[m]=nphi;
00175 phi0_[m]=phi0;
00176 ofs[m]=(ptrdiff_t)m*stride_lat;
00177 stride_[m]=stride_lon;
00178 weight[m]*=2*pi/nphi;
00179 }
00180
00181 sharp_make_geom_info (nrings, nph, ofs, stride_, phi0_, theta, weight,
00182 geom_info);
00183
00184 DEALLOC(theta);
00185 DEALLOC(weight);
00186 DEALLOC(nph);
00187 DEALLOC(phi0_);
00188 DEALLOC(ofs);
00189 DEALLOC(stride_);
00190 }
00191
00192
00193 void sharp_make_fejer1_geom_info (int nrings, int ppring, double phi0,
00194 int stride_lon, int stride_lat, sharp_geom_info **geom_info)
00195 {
00196 const double pi=3.141592653589793238462643383279502884197;
00197
00198 double *theta=RALLOC(double,nrings);
00199 double *weight=RALLOC(double,nrings);
00200 int *nph=RALLOC(int,nrings);
00201 double *phi0_=RALLOC(double,nrings);
00202 ptrdiff_t *ofs=RALLOC(ptrdiff_t,nrings);
00203 int *stride_=RALLOC(int,nrings);
00204
00205 weight[0]=2.;
00206 for (int k=1; k<=(nrings-1)/2; ++k)
00207 {
00208 weight[2*k-1]=2./(1.-4.*k*k)*cos((k*pi)/nrings);
00209 weight[2*k ]=2./(1.-4.*k*k)*sin((k*pi)/nrings);
00210 }
00211 if ((nrings&1)==0) weight[nrings-1]=0.;
00212 real_plan plan = make_real_plan(nrings);
00213 real_plan_backward_fftpack(plan,weight);
00214 kill_real_plan(plan);
00215
00216 for (int m=0; m<(nrings+1)/2; ++m)
00217 {
00218 theta[m]=pi*(m+0.5)/nrings;
00219 theta[nrings-1-m]=pi-theta[m];
00220 nph[m]=nph[nrings-1-m]=ppring;
00221 phi0_[m]=phi0_[nrings-1-m]=phi0;
00222 ofs[m]=(ptrdiff_t)m*stride_lat;
00223 ofs[nrings-1-m]=(ptrdiff_t)((nrings-1-m)*stride_lat);
00224 stride_[m]=stride_[nrings-1-m]=stride_lon;
00225 weight[m]=weight[nrings-1-m]=weight[m]*2*pi/(nrings*nph[m]);
00226 }
00227
00228 sharp_make_geom_info (nrings, nph, ofs, stride_, phi0_, theta, weight,
00229 geom_info);
00230
00231 DEALLOC(theta);
00232 DEALLOC(weight);
00233 DEALLOC(nph);
00234 DEALLOC(phi0_);
00235 DEALLOC(ofs);
00236 DEALLOC(stride_);
00237 }
00238
00239
00240 void sharp_make_cc_geom_info (int nrings, int ppring, double phi0,
00241 int stride_lon, int stride_lat, sharp_geom_info **geom_info)
00242 {
00243 const double pi=3.141592653589793238462643383279502884197;
00244
00245 double *theta=RALLOC(double,nrings);
00246 double *weight=RALLOC(double,nrings);
00247 int *nph=RALLOC(int,nrings);
00248 double *phi0_=RALLOC(double,nrings);
00249 ptrdiff_t *ofs=RALLOC(ptrdiff_t,nrings);
00250 int *stride_=RALLOC(int,nrings);
00251
00252 int n=nrings-1;
00253 SET_ARRAY(weight,0,nrings,0.);
00254 double dw=-1./(n*n-1.+(n&1));
00255 weight[0]=2.+dw;
00256 for (int k=1; k<=(n/2-1); ++k)
00257 weight[2*k-1]=2./(1.-4.*k*k) + dw;
00258 weight[2*(n/2)-1]=(n-3.)/(2*(n/2)-1) -1. -dw*((2-(n&1))*n-1);
00259 real_plan plan = make_real_plan(n);
00260 real_plan_backward_fftpack(plan,weight);
00261 kill_real_plan(plan);
00262 weight[n]=weight[0];
00263
00264 for (int m=0; m<(nrings+1)/2; ++m)
00265 {
00266 theta[m]=pi*m/(nrings-1.);
00267 if (theta[m]<1e-15) theta[m]=1e-15;
00268 theta[nrings-1-m]=pi-theta[m];
00269 nph[m]=nph[nrings-1-m]=ppring;
00270 phi0_[m]=phi0_[nrings-1-m]=phi0;
00271 ofs[m]=(ptrdiff_t)m*stride_lat;
00272 ofs[nrings-1-m]=(ptrdiff_t)((nrings-1-m)*stride_lat);
00273 stride_[m]=stride_[nrings-1-m]=stride_lon;
00274 weight[m]=weight[nrings-1-m]=weight[m]*2*pi/(n*nph[m]);
00275 }
00276
00277 sharp_make_geom_info (nrings, nph, ofs, stride_, phi0_, theta, weight,
00278 geom_info);
00279
00280 DEALLOC(theta);
00281 DEALLOC(weight);
00282 DEALLOC(nph);
00283 DEALLOC(phi0_);
00284 DEALLOC(ofs);
00285 DEALLOC(stride_);
00286 }
00287
00288
00289 void sharp_make_fejer2_geom_info (int nrings, int ppring, double phi0,
00290 int stride_lon, int stride_lat, sharp_geom_info **geom_info)
00291 {
00292 const double pi=3.141592653589793238462643383279502884197;
00293
00294 double *theta=RALLOC(double,nrings);
00295 double *weight=RALLOC(double,nrings+1);
00296 int *nph=RALLOC(int,nrings);
00297 double *phi0_=RALLOC(double,nrings);
00298 ptrdiff_t *ofs=RALLOC(ptrdiff_t,nrings);
00299 int *stride_=RALLOC(int,nrings);
00300
00301 int n=nrings+1;
00302 SET_ARRAY(weight,0,n,0.);
00303 weight[0]=2.;
00304 for (int k=1; k<=(n/2-1); ++k)
00305 weight[2*k-1]=2./(1.-4.*k*k);
00306 weight[2*(n/2)-1]=(n-3.)/(2*(n/2)-1) -1.;
00307 real_plan plan = make_real_plan(n);
00308 real_plan_backward_fftpack(plan,weight);
00309 kill_real_plan(plan);
00310 for (int m=0; m<nrings; ++m)
00311 weight[m]=weight[m+1];
00312
00313 for (int m=0; m<(nrings+1)/2; ++m)
00314 {
00315 theta[m]=pi*(m+1)/(nrings+1.);
00316 theta[nrings-1-m]=pi-theta[m];
00317 nph[m]=nph[nrings-1-m]=ppring;
00318 phi0_[m]=phi0_[nrings-1-m]=phi0;
00319 ofs[m]=(ptrdiff_t)m*stride_lat;
00320 ofs[nrings-1-m]=(ptrdiff_t)((nrings-1-m)*stride_lat);
00321 stride_[m]=stride_[nrings-1-m]=stride_lon;
00322 weight[m]=weight[nrings-1-m]=weight[m]*2*pi/(n*nph[m]);
00323 }
00324
00325 sharp_make_geom_info (nrings, nph, ofs, stride_, phi0_, theta, weight,
00326 geom_info);
00327
00328 DEALLOC(theta);
00329 DEALLOC(weight);
00330 DEALLOC(nph);
00331 DEALLOC(phi0_);
00332 DEALLOC(ofs);
00333 DEALLOC(stride_);
00334 }
00335
00336 void sharp_make_mw_geom_info (int nrings, int ppring, double phi0,
00337 int stride_lon, int stride_lat, sharp_geom_info **geom_info)
00338 {
00339 const double pi=3.141592653589793238462643383279502884197;
00340
00341 double *theta=RALLOC(double,nrings);
00342 int *nph=RALLOC(int,nrings);
00343 double *phi0_=RALLOC(double,nrings);
00344 ptrdiff_t *ofs=RALLOC(ptrdiff_t,nrings);
00345 int *stride_=RALLOC(int,nrings);
00346
00347 for (int m=0; m<nrings; ++m)
00348 {
00349 theta[m]=pi*(2.*m+1.)/(2.*nrings-1.);
00350 if (theta[m]>pi-1e-15) theta[m]=pi-1e-15;
00351 nph[m]=ppring;
00352 phi0_[m]=phi0;
00353 ofs[m]=(ptrdiff_t)m*stride_lat;
00354 stride_[m]=stride_lon;
00355 }
00356
00357 sharp_make_geom_info (nrings, nph, ofs, stride_, phi0_, theta, NULL,
00358 geom_info);
00359
00360 DEALLOC(theta);
00361 DEALLOC(nph);
00362 DEALLOC(phi0_);
00363 DEALLOC(ofs);
00364 DEALLOC(stride_);
00365 }