| [658] | 1 | #include <math.h> | 
|---|
|  | 2 | #include "lambuilder.h" | 
|---|
|  | 3 | #include <iostream.h> | 
|---|
|  | 4 | //++ | 
|---|
|  | 5 | // Class        Lambda2Builder | 
|---|
|  | 6 | // | 
|---|
|  | 7 | //    (see separate documentation) | 
|---|
|  | 8 | //-- | 
|---|
|  | 9 |  | 
|---|
|  | 10 | double Lambda2Builder::bignorm = 1.e268; // = 1e-20*1.d288 | 
|---|
|  | 11 |  | 
|---|
|  | 12 | Lambda2Builder::Lambda2Builder(){} | 
|---|
|  | 13 |  | 
|---|
|  | 14 | Lambda2Builder::Lambda2Builder(double theta, int lmax, int mmax): | 
|---|
|  | 15 | LambdaBuilder(theta, lmax, mmax){ | 
|---|
|  | 16 | fact_=0; | 
|---|
|  | 17 | w_=0; | 
|---|
|  | 18 | ix_=0; | 
|---|
|  | 19 | } | 
|---|
|  | 20 |  | 
|---|
|  | 21 | Lambda2Builder::Lambda2Builder(const Lambda2Builder& lb): | 
|---|
|  | 22 | LambdaBuilder(lb){ | 
|---|
|  | 23 | fact_=lb.fact_; | 
|---|
|  | 24 | w_=lb.w_; | 
|---|
|  | 25 | ix_=lb.ix_; | 
|---|
|  | 26 | } | 
|---|
|  | 27 |  | 
|---|
|  | 28 | void Lambda2Builder::reset(){ | 
|---|
|  | 29 | LambdaBuilder::reset(); | 
|---|
|  | 30 | fact_=0; | 
|---|
|  | 31 | w_=0; | 
|---|
|  | 32 | ix_=0; | 
|---|
|  | 33 | } | 
|---|
|  | 34 |  | 
|---|
|  | 35 | double Lambda2Builder::lam2lmp(int flip){ | 
|---|
|  | 36 | if (flip < 0){ | 
|---|
|  | 37 | return -fact_*par_lm_*(w_+ix_); | 
|---|
|  | 38 | } else{ | 
|---|
|  | 39 | return lam2lmp(); | 
|---|
|  | 40 | } | 
|---|
|  | 41 | } | 
|---|
|  | 42 |  | 
|---|
|  | 43 | double Lambda2Builder::lam2lmp(int l, int m){ | 
|---|
|  | 44 | if ((l <= lmax_ && l==l_+1 && m==m_) || | 
|---|
|  | 45 | (m <= mmax_ && m==m_+1 && l==m && l_==lmax_)){ | 
|---|
|  | 46 | step(); | 
|---|
|  | 47 | return lam2lmp(); | 
|---|
|  | 48 | } else if (l==l_ && m==m_){ | 
|---|
|  | 49 | return lam2lmp(); | 
|---|
|  | 50 | } else if ((l < l_ && m <= mmax_) || (m == m_ && l < l_) || m<m_){ | 
|---|
|  | 51 | reset(); | 
|---|
|  | 52 | while (l != l_ || m != m_){ | 
|---|
|  | 53 | step(); | 
|---|
|  | 54 | } | 
|---|
|  | 55 | return lam2lmp(); | 
|---|
|  | 56 | } else if (l <= lmax_ && m <= mmax_ && (m > m_ || (m==m_ && l > l_))){ | 
|---|
|  | 57 | while (l != l_ || m != m_){ | 
|---|
|  | 58 | step(); | 
|---|
|  | 59 | } | 
|---|
|  | 60 | return lam2lmp(); | 
|---|
|  | 61 | } else{ | 
|---|
|  | 62 | return -1; | 
|---|
|  | 63 | } | 
|---|
|  | 64 | } | 
|---|
|  | 65 |  | 
|---|
|  | 66 | double Lambda2Builder::lam2lmp(int l, int m, int flip){ | 
|---|
|  | 67 |  | 
|---|
|  | 68 | if ((l <= lmax_ && l==l_+1 && m==m_) || | 
|---|
|  | 69 | (m <= mmax_ && m==m_+1 && l==m && l_==lmax_)){ | 
|---|
|  | 70 | step(); | 
|---|
|  | 71 | return lam2lmp(flip); | 
|---|
|  | 72 | } else if (l==l_ && m==m_){ | 
|---|
|  | 73 | return lam2lmp(flip); | 
|---|
|  | 74 | } else if ((l < l_ && m <= mmax_) || (m == m_ && l < l_) || m<m_){ | 
|---|
|  | 75 | reset(); | 
|---|
|  | 76 | while (l != l_ || m != m_){ | 
|---|
|  | 77 | step(); | 
|---|
|  | 78 | } | 
|---|
|  | 79 | return lam2lmp(flip); | 
|---|
|  | 80 | } else if (l <= lmax_ && m <= mmax_ && (m > m_ || (m==m_ && l > l_))){ | 
|---|
|  | 81 | while (l != l_ || m != m_){ | 
|---|
|  | 82 | step(); | 
|---|
|  | 83 | } | 
|---|
|  | 84 | return lam2lmp(flip); | 
|---|
|  | 85 | } else{ | 
|---|
|  | 86 | return -1; | 
|---|
|  | 87 | } | 
|---|
|  | 88 | } | 
|---|
|  | 89 |  | 
|---|
|  | 90 | double Lambda2Builder::lam2lmm(int flip){ | 
|---|
|  | 91 | if (flip < 0){ | 
|---|
|  | 92 | return -fact_*par_lm_*(w_-ix_); | 
|---|
|  | 93 | } else{ | 
|---|
|  | 94 | return lam2lmp(); | 
|---|
|  | 95 | } | 
|---|
|  | 96 | } | 
|---|
|  | 97 |  | 
|---|
|  | 98 | double Lambda2Builder::lam2lmm(int l, int m){ | 
|---|
|  | 99 | if ((l <= lmax_ && l==l_+1 && m==m_) || | 
|---|
|  | 100 | (m <= mmax_ && m==m_+1 && l==m && l_==lmax_)){ | 
|---|
|  | 101 | step(); | 
|---|
|  | 102 | return lam2lmm(); | 
|---|
|  | 103 | } else if (l==l_ && m==m_){ | 
|---|
|  | 104 | return lam2lmm(); | 
|---|
|  | 105 | } else if ((l < l_ && m <= mmax_) || (m == m_ && l < l_) || m<m_){ | 
|---|
|  | 106 | reset(); | 
|---|
|  | 107 | while (l != l_ || m != m_){ | 
|---|
|  | 108 | step(); | 
|---|
|  | 109 | } | 
|---|
|  | 110 | return lam2lmm(); | 
|---|
|  | 111 | } else if (l <= lmax_ && m <= mmax_ && (m > m_ || (m==m_ && l > l_))){ | 
|---|
|  | 112 | while (l != l_ || m != m_){ | 
|---|
|  | 113 | step(); | 
|---|
|  | 114 | } | 
|---|
|  | 115 | return lam2lmm(); | 
|---|
|  | 116 | } else{ | 
|---|
|  | 117 | return -1; | 
|---|
|  | 118 | } | 
|---|
|  | 119 | } | 
|---|
|  | 120 |  | 
|---|
|  | 121 | double Lambda2Builder::lam2lmm(int l, int m, int flip){ | 
|---|
|  | 122 | if ((l <= lmax_ && l==l_+1 && m==m_) || | 
|---|
|  | 123 | (m <= mmax_ && m==m_+1 && l==m && l_==lmax_)){ | 
|---|
|  | 124 | step(); | 
|---|
|  | 125 | return lam2lmm(flip); | 
|---|
|  | 126 | } else if (l==l_ && m==m_){ | 
|---|
|  | 127 | return lam2lmm(flip); | 
|---|
|  | 128 | } else if ((l < l_ && m <= mmax_) || (m == m_ && l < l_) || m<m_){ | 
|---|
|  | 129 | reset(); | 
|---|
|  | 130 | while (l != l_ || m != m_){ | 
|---|
|  | 131 | step(); | 
|---|
|  | 132 | } | 
|---|
|  | 133 | return lam2lmm(flip); | 
|---|
|  | 134 | } else if (l <= lmax_ && m <= mmax_ && (m > m_ || (m==m_ && l > l_))){ | 
|---|
|  | 135 | while (l != l_ || m != m_){ | 
|---|
|  | 136 | step(); | 
|---|
|  | 137 | } | 
|---|
|  | 138 | return lam2lmm(flip); | 
|---|
|  | 139 | } else{ | 
|---|
|  | 140 | return -1; | 
|---|
|  | 141 | } | 
|---|
|  | 142 | } | 
|---|
|  | 143 |  | 
|---|
|  | 144 | void Lambda2Builder::step(){ | 
|---|
|  | 145 | if (l_>=lmax_ && m_>=mmax_){return;} | 
|---|
|  | 146 | if (l_==lmax_){//move on to the next m and calculate l=m | 
|---|
|  | 147 | LambdaBuilder::step(); | 
|---|
|  | 148 | if (l_>=2){ | 
|---|
|  | 149 | w_=-2.*(m_*(2.*m_+1.)-m_*(m_-1.)/sth_/sth_)*lamlm_; | 
|---|
|  | 150 | ix_=-2.*m_*(m_-1.)*cth_/sth_/sth_*lamlm_; | 
|---|
|  | 151 | fact_=sqrt(1./(m_-1.)/m_/(m_+1.)/(m_+2.)); | 
|---|
|  | 152 | } else{ | 
|---|
|  | 153 | w_=0; | 
|---|
|  | 154 | ix_=0; | 
|---|
|  | 155 | fact_=0; | 
|---|
|  | 156 | } | 
|---|
|  | 157 | } else{ | 
|---|
|  | 158 | double lastlamlm=lamlm_; | 
|---|
|  | 159 | LambdaBuilder::step(); | 
|---|
|  | 160 | if (l_>=2){ | 
|---|
|  | 161 | w_=-2.*(-((l_-m_*m_)/sth_/sth_+.5*l_*(l_-1.))*lamlm_+ | 
|---|
|  | 162 | (l_+m_)*cth_/sth_/sth_*sqrt((2.*l_+1.)/(2.*l_-1.)*(l_-m_)/(l_+m_))* | 
|---|
|  | 163 | lastlamlm); | 
|---|
|  | 164 | ix_=-2.*m_/sth_/sth_*((l_-1.)*cth_*lamlm_-(l_+m_)* | 
|---|
|  | 165 | sqrt((2.*l_+1.)/(2.*l_-1.)*(l_-m_)/(l_+m_))* | 
|---|
|  | 166 | lastlamlm); | 
|---|
|  | 167 | fact_=sqrt(1./(l_-1.)/l_/(l_+1.)/(l_+2.)); | 
|---|
|  | 168 | } else{ | 
|---|
|  | 169 | w_=0; | 
|---|
|  | 170 | ix_=0; | 
|---|
|  | 171 | fact_=0; | 
|---|
|  | 172 | } | 
|---|
|  | 173 | } | 
|---|
|  | 174 | } | 
|---|
|  | 175 |  | 
|---|
|  | 176 | LambdaBuilder::LambdaBuilder(){} | 
|---|
|  | 177 |  | 
|---|
|  | 178 | LambdaBuilder::LambdaBuilder(double theta, int lmax, int mmax){ | 
|---|
|  | 179 | lmax_=lmax; | 
|---|
|  | 180 | mmax_=mmax; | 
|---|
|  | 181 | l_=0; | 
|---|
|  | 182 | m_=0; | 
|---|
|  | 183 | lamlm_=1. / sqrt(4.*M_PI); | 
|---|
|  | 184 | cth_=cos(theta); | 
|---|
|  | 185 | sth_=sin(theta); | 
|---|
|  | 186 | lammm_=1. / sqrt(4.*M_PI) *bignorm; | 
|---|
|  | 187 | par_lm_=1.; | 
|---|
|  | 188 | lam_0_=0.; | 
|---|
|  | 189 | lam_1_=1./bignorm; | 
|---|
|  | 190 | a_rec_=sqrt(3.); | 
|---|
|  | 191 | b_rec_=0; | 
|---|
|  | 192 | fm2_=0; | 
|---|
|  | 193 | } | 
|---|
|  | 194 |  | 
|---|
|  | 195 | LambdaBuilder::LambdaBuilder(const LambdaBuilder& lb){ | 
|---|
|  | 196 | lmax_=lb.lmax_; | 
|---|
|  | 197 | mmax_=lb.mmax_; | 
|---|
|  | 198 | l_=lb.l_; | 
|---|
|  | 199 | m_=lb.m_; | 
|---|
|  | 200 | lamlm_=lb.lamlm_; | 
|---|
|  | 201 | cth_=lb.cth_; | 
|---|
|  | 202 | sth_=lb.sth_; | 
|---|
|  | 203 | lammm_=lb.lammm_; | 
|---|
|  | 204 | par_lm_=lb.par_lm_; | 
|---|
|  | 205 | lam_0_=lb.lam_0_; | 
|---|
|  | 206 | lam_1_=lb.lam_1_; | 
|---|
|  | 207 | a_rec_=lb.a_rec_; | 
|---|
|  | 208 | b_rec_=lb.b_rec_; | 
|---|
|  | 209 | fm2_=lb.fm2_; | 
|---|
|  | 210 | } | 
|---|
|  | 211 |  | 
|---|
|  | 212 | void LambdaBuilder::reset(){ | 
|---|
|  | 213 | l_=0; | 
|---|
|  | 214 | m_=0; | 
|---|
|  | 215 | lamlm_=1. / sqrt(4.*M_PI); | 
|---|
|  | 216 | lammm_=1. / sqrt(4.*M_PI) *bignorm; | 
|---|
|  | 217 | par_lm_=1.; | 
|---|
|  | 218 | lam_0_=0.; | 
|---|
|  | 219 | lam_1_=1./bignorm; | 
|---|
|  | 220 | a_rec_=sqrt(3.); | 
|---|
|  | 221 | b_rec_=0; | 
|---|
|  | 222 | fm2_=0; | 
|---|
|  | 223 | } | 
|---|
|  | 224 |  | 
|---|
|  | 225 | double LambdaBuilder::lamlm(int flip){ | 
|---|
|  | 226 | if (flip < 0){ | 
|---|
|  | 227 | return par_lm_*lamlm(); | 
|---|
|  | 228 | } else{ | 
|---|
|  | 229 | return lamlm(); | 
|---|
|  | 230 | } | 
|---|
|  | 231 | } | 
|---|
|  | 232 |  | 
|---|
|  | 233 | double LambdaBuilder::lamlm(int l, int m){ | 
|---|
|  | 234 | if ((l <= lmax_ && l==l_+1 && m==m_) || | 
|---|
|  | 235 | (m <= mmax_ && m==m_+1 && l==m && l_==lmax_)){ | 
|---|
|  | 236 | step(); | 
|---|
|  | 237 | return lamlm(); | 
|---|
|  | 238 | } else if (l==l_ && m==m_){ | 
|---|
|  | 239 | return lamlm_; | 
|---|
|  | 240 | } else if ((l < l_ && m <= mmax_) || (m == m_ && l < l_) || m<m_){ | 
|---|
|  | 241 | reset(); | 
|---|
|  | 242 | while (l != l_ || m != m_){ | 
|---|
|  | 243 | step(); | 
|---|
|  | 244 | } | 
|---|
|  | 245 | return lamlm(); | 
|---|
|  | 246 | } else if (l <= lmax_ && m <= mmax_ && (m > m_ || (m==m_ && l > l_))){ | 
|---|
|  | 247 | while (l != l_ || m != m_){ | 
|---|
|  | 248 | step(); | 
|---|
|  | 249 | } | 
|---|
|  | 250 | return lamlm(); | 
|---|
|  | 251 | } else{ | 
|---|
|  | 252 | return -1; | 
|---|
|  | 253 | } | 
|---|
|  | 254 | } | 
|---|
|  | 255 |  | 
|---|
|  | 256 | double LambdaBuilder::lamlm(int l, int m, int flip){ | 
|---|
|  | 257 | if ((l <= lmax_ && l==l_+1 && m==m_) || | 
|---|
|  | 258 | (m <= mmax_ && m==m_+1 && l==m && l_==lmax_)){ | 
|---|
|  | 259 | step(); | 
|---|
|  | 260 | return lamlm(flip); | 
|---|
|  | 261 | } else if (l==l_ && m==m_){ | 
|---|
|  | 262 | return lamlm(flip); | 
|---|
|  | 263 | } else if ((l < l_ && m <= mmax_) || (m == m_ && l < l_) || m<m_){ | 
|---|
|  | 264 | reset(); | 
|---|
|  | 265 | while (l != l_ || m != m_){ | 
|---|
|  | 266 | step(); | 
|---|
|  | 267 | } | 
|---|
|  | 268 | return lamlm(flip); | 
|---|
|  | 269 | } else if (l <= lmax_ && m <= mmax_ && (m > m_ || (m==m_ && l > l_))){ | 
|---|
|  | 270 | while (l != l_ || m != m_){ | 
|---|
|  | 271 | step(); | 
|---|
|  | 272 | } | 
|---|
|  | 273 | return lamlm(flip); | 
|---|
|  | 274 | } else{ | 
|---|
|  | 275 | return -1; | 
|---|
|  | 276 | } | 
|---|
|  | 277 | } | 
|---|
|  | 278 |  | 
|---|
|  | 279 | void LambdaBuilder::step(){ | 
|---|
|  | 280 | /*----------------------------------------------------------------------- | 
|---|
|  | 281 | computes lambda_lm(theta) in an optimal fashion | 
|---|
|  | 282 | looping over m | 
|---|
|  | 283 | For example, if nlmax =3 and nmmax=3 the order is | 
|---|
|  | 284 | (l,m)=(0,0),(1,0),(2,0),(3,0),(1,1),(2,1),(3,1),(2,2),(3,2),(3,3) | 
|---|
|  | 285 | -----------------------------------------------------------------------*/ | 
|---|
|  | 286 | if (l_>=lmax_ && m_>=mmax_){return;} | 
|---|
|  | 287 | if (l_==lmax_){//move on to the next m and calculate l=m | 
|---|
|  | 288 | m_=m_+1; | 
|---|
|  | 289 | l_=m_; | 
|---|
|  | 290 | double f2m = 2. * m_; | 
|---|
|  | 291 | fm2_ = ((double) m_)*m_; | 
|---|
|  | 292 | par_lm_ = 1.;  // = (-1)^(l+m) | 
|---|
|  | 293 | if (m_ >= 1) { /* lambda_0_0 for m>0*/ | 
|---|
|  | 294 | lammm_ = - lammm_ * sth_ * sqrt( (f2m+1.)/ f2m ); | 
|---|
|  | 295 | } | 
|---|
|  | 296 | lamlm_ = lammm_ / bignorm; | 
|---|
|  | 297 | lam_0_ = 0.; | 
|---|
|  | 298 | lam_1_ = 1. / bignorm;   /*small number --> to avoid overflow*/ | 
|---|
|  | 299 | a_rec_ = sqrt( f2m + 3.); | 
|---|
|  | 300 | b_rec_ = 0.; | 
|---|
|  | 301 | } else{ | 
|---|
|  | 302 | l_=l_+1; | 
|---|
|  | 303 | par_lm_ = - par_lm_; /*  = (-1)^(l+m)*/ | 
|---|
|  | 304 | double lam_2 = (cth_ * lam_1_ - b_rec_ * lam_0_) * a_rec_; | 
|---|
|  | 305 | //    cout<<lam_2<<" "<<cth_<<" "<<lam_1_<<" "<<b_rec_<<" "<<lam_0_<<" "<<a_rec_<<endl; | 
|---|
|  | 306 | //actual lambda_lm (small and big numbers cancel out) | 
|---|
|  | 307 | lamlm_ = lam_2 * lammm_; | 
|---|
|  | 308 |  | 
|---|
|  | 309 | b_rec_ = 1. / a_rec_; | 
|---|
|  | 310 | double fl2 = (l_+1.)*(l_+1.); | 
|---|
|  | 311 | a_rec_ = sqrt( (4. * fl2 - 1.) / (fl2-fm2_) ); | 
|---|
|  | 312 | //    cout <<fl2<<" "<<fm2<<endl; | 
|---|
|  | 313 | lam_0_ = lam_1_; | 
|---|
|  | 314 | lam_1_ = lam_2; | 
|---|
|  | 315 | } | 
|---|
|  | 316 | } | 
|---|