52 #include "libsharp/sharp_cxx.h" 53 #include "lsconstants.h" 83 double dprod(
const vector<double> &a,
const vector<double> &b)
84 {
return inner_product(a.begin(),a.end(),b.begin(),0.); }
86 tsize n_fullweights (
int nside)
87 {
return ((3*nside+1)*(nside+1))/4; }
89 template <
typename T>
void apply_weight (T &pix,
double w,
bool setwgt)
98 const vector<double> &wgt,
bool setwgt)
100 planck_assert (map.
Scheme()==
RING,
"bad map ordering scheme");
101 int nside=map.
Nside();
102 planck_assert(wgt.size()==n_fullweights(nside),
103 "incorrect size of weight array");
105 for (
int i=0; i<2*nside; ++i)
107 bool shifted = (i<nside-1) || ((i+nside)&1);
108 int qpix=min(nside,i+1);
110 int wpix=((qpix+1)>>1) + ((odd||shifted) ? 0 : 1);
111 int psouth=map.
Npix()-pix-(qpix<<2);
112 for (
int j=0; j<(qpix<<2); ++j)
115 int rpix=min(j4,qpix - (shifted ? 1:0) - j4);
116 apply_weight (map[pix+j],wgt[vpix+rpix],setwgt);
118 apply_weight(map[psouth+j],wgt[vpix+rpix],setwgt);
127 planck_assert (map.
Scheme()==
RING,
"bad map ordering scheme");
128 int nside=map.
Nside();
129 vector<double> res; res.reserve(n_fullweights(nside));
131 for (
int i=0; i<2*nside; ++i)
133 bool shifted = (i<nside-1) || ((i+nside)&1);
134 int qpix=min(nside,i+1);
136 int wpix=((qpix+1)>>1) + ((odd||shifted) ? 0 : 1);
137 for (
int j=0; j<wpix; ++j)
138 res.push_back(map[pix+j]);
144 tsize n_weightalm (
int lmax,
int mmax)
146 int nmsteps=(mmax>>2)+1;
147 return nmsteps * (((lmax+2)>>1) - nmsteps+1);
149 vector<double> extract_weightalm (
const Alm<xcomplex<double> > &alm)
151 vector<double> res; res.reserve(n_weightalm(alm.Lmax(),alm.Mmax()));
152 for (
int m=0; m<=alm.Mmax(); m+=4)
153 for (
int l=m; l<=alm.Lmax(); l+=2)
154 res.push_back(real(alm(l,m)) * ((m==0) ? 1 : sqrt(2.)));
157 void expand_weightalm (
const vector<double> &calm,
Alm<xcomplex<double> > &alm)
159 planck_assert(calm.size()==n_weightalm(alm.Lmax(), alm.Mmax()),
160 "incorrect size of weight array");
163 for (
int m=0; m<=alm.Mmax(); m+=4)
164 for (
int l=m; l<=alm.Lmax(); l+=2)
165 alm(l,m) = calm[idx++] * ((m==0) ? 1 : sqrt(0.5));
171 int lmax, mmax, nside;
174 using vectype=vector<double>;
175 STS_hpwgt (
int lmax_,
int mmax_,
int nside_)
176 : lmax(lmax_), mmax(mmax_), nside(nside_)
177 { planck_assert((lmax&1)==0,
"lmax must be even"); }
178 vectype S (
const vectype &x)
const 181 expand_weightalm(x,ta);
184 return extract_fullweights(tm);
186 vectype ST (
const vectype &x)
const 192 return extract_weightalm(ta);
194 vectype apply (
const vectype &x)
const 202 sharp_cxxjob<double> job;
205 using vectype=vector<double>;
206 STS_hpring (
int lmax_,
int nside_)
207 : lmax(lmax_), nside(nside_)
209 planck_assert((lmax&1)==0,
"lmax must be even");
211 vector<double> dbl0(nring,0.),theta(nring);
212 vector<int> int1(nring,1);
213 vector<ptrdiff_t> ofs(nring);
215 for (
int i=0; i<nring; ++i)
220 base.get_ring_info2 (i+1, idum1, idum2, theta[i], bdum);
222 job.set_general_geometry (nring, int1.data(), ofs.data(),
223 int1.data(), dbl0.data(), theta.data(), dbl0.data());
224 job.set_triangular_alm_info (lmax, 0);
226 vectype S(
const vectype &alm)
const 228 planck_assert(
int(alm.size())==lmax/2+1,
"bad input size");
229 vectype res(2*nside);
230 vector<xcomplex<double> > alm2(2*alm.size()-1,0.);
231 for (tsize i=0; i<alm.size(); ++i)
233 job.alm2map(&alm2[0],&res[0],
false);
236 vectype ST(
const vectype &map)
const 238 planck_assert(
int(map.size())==2*nside,
"bad input size");
239 vector<xcomplex<double> > alm2(lmax+1,0.);
240 job.alm2map_adjoint(&map[0],&alm2[0],
false);
241 vectype res(lmax/2+1);
242 for (tsize i=0; i<res.size(); ++i)
243 res[i]=real(alm2[2*i]);
246 vectype apply (
const vectype &x)
const 250 vector<double> muladd (
double fct,
const vector<double> &a,
251 const vector<double> &b)
253 planck_assert(a.size()==b.size(),
"types not conformable");
254 vector<double> res(b);
255 for (tsize i=0; i<a.size(); ++i)
261 template<
typename M>
double cg_solve (
const M &A,
typename M::vectype &x,
262 const typename M::vectype &b,
double epsilon,
int itmax)
264 typename M::vectype r=muladd(-1.,A.apply(x),b), d(r);
265 double delta0=dprod(r,r), deltanew=delta0;
266 cout <<
"res0: " << sqrt(delta0) << endl;
267 for (
int iter=0; iter<itmax; ++iter)
270 double alpha = deltanew/dprod(d,q);
273 r=muladd(-1.,A.apply(x),b);
275 r=muladd(-alpha,q,r);
276 double deltaold=deltanew;
278 cout <<
"\rIteration " << iter
279 <<
": residual=" << sqrt(deltanew/delta0)
281 if (deltanew<epsilon*epsilon*delta0) { cout << endl;
break; }
282 double beta=deltanew/deltaold;
285 return sqrt(deltanew/delta0);
292 vector<double> x, rhs, r, d;
293 double delta0, delta_cur;
297 FullWeightImpl(
int nside,
int lmax)
298 : mat(lmax, lmax, nside), x(n_weightalm(lmax,lmax),0.), iter(0)
300 planck_assert((lmax&1)==0,
"lmax must be even");
301 rhs = mat.ST(vector<double>(n_fullweights(nside),-1.));
302 rhs[0]+=12*nside*nside/sqrt(4*pi);
303 r=muladd(-1.,mat.apply(x),rhs);
308 void iterate(
int niter)
311 for (; iter<iend; ++iter)
314 double alpha = delta_cur/dprod(d,q);
317 r=muladd(-1.,mat.apply(x),rhs);
319 r=muladd(-alpha,q,r);
320 double deltaold=delta_cur;
321 delta_cur=dprod(r,r);
322 cout <<
"\rIteration " << iter
323 <<
": residual=" << sqrt(delta_cur/delta0)
325 double beta=delta_cur/deltaold;
329 std::vector<double> current_alm()
const {
return x; }
330 std::vector<double> alm2wgt(
const vector<double> &alm)
const 331 {
return mat.S(alm); }
332 double current_epsilon()
const {
return sqrt(delta_cur/delta0); }
333 int current_iter()
const {
return iter; }
343 planck_assert((lmax&1)==0,
"lmax must be even");
344 STS_hpwgt mat(lmax, lmax, nside);
345 vector<double> x(n_weightalm(lmax,lmax),0.);
346 vector<double> rhs=mat.ST(vector<double> (n_fullweights(nside),-1.));
347 rhs[0]+=12*nside*nside/sqrt(4*pi);
348 epsilon_out=cg_solve(mat, x, rhs, epsilon, itmax);
352 FullWeightComputer::FullWeightComputer(
int nside,
int lmax)
353 : impl(new FullWeightImpl(nside, lmax)) {}
355 FullWeightComputer::~FullWeightComputer() {}
357 void FullWeightComputer::iterate(
int niter) { impl->iterate(niter); }
359 std::vector<double> FullWeightComputer::current_alm()
const 360 {
return impl->current_alm(); }
362 std::vector<double> FullWeightComputer::alm2wgt(
const vector<double> &alm)
const 363 {
return impl->alm2wgt(alm); }
365 double FullWeightComputer::current_epsilon()
const 366 {
return impl->current_epsilon(); }
368 int FullWeightComputer::current_iter()
const 369 {
return impl->current_iter(); }
372 const vector<double> &wgt)
376 const vector<double> &wgt);
378 const vector<double> &wgt);
383 planck_assert((lmax&1)==0,
"lmax must be even");
384 STS_hpring mat(lmax,nside);
385 vector<double> nir(2*nside), x(lmax/2+1,0.);
386 for (tsize ith=0; ith<nir.size(); ++ith)
387 nir[ith]=8*min<int>(ith+1,nside);
390 for (tsize i=0; i<b.size(); ++i)
392 b[0]+=12*nside*nside/sqrt(4*pi);
393 epsilon_out=cg_solve(mat, x, b, epsilon, itmax);
395 for (tsize i=0; i<mtmp.size(); ++i)
vector< double > get_fullweights(int nside, int lmax, double epsilon, int itmax, double &epsilon_out)
void apply_fullweights(Healpix_Map< T > &map, const std::vector< double > &wgt)
void alm2map_adjoint(const Healpix_Map< T > &map, Alm< xcomplex< T > > &alm, bool add_alm)
Healpix_Ordering_Scheme Scheme() const
void alm2map(const Alm< xcomplex< T > > &alm, Healpix_Map< T > &map, bool add_map)
const double Healpix_undef
Healpix value representing "undefined".
vector< double > get_ringweights(int nside, int lmax, double epsilon, int itmax, double &epsilon_out)