| [658] | 1 | #ifndef LAMBUILDER_H_SEEN | 
|---|
|  | 2 | #define LAMBUILDER_H_SEEN | 
|---|
|  | 3 |  | 
|---|
|  | 4 | #include <math.h> | 
|---|
|  | 5 |  | 
|---|
|  | 6 |  | 
|---|
|  | 7 | class LambdaBuilder{ | 
|---|
|  | 8 | public: | 
|---|
|  | 9 | LambdaBuilder(); | 
|---|
|  | 10 | LambdaBuilder(double theta,int lmax, int mmax); | 
|---|
|  | 11 | LambdaBuilder(const LambdaBuilder& lb); | 
|---|
|  | 12 | void reset(); | 
|---|
|  | 13 | double lamlm() const {return lamlm_;} | 
|---|
|  | 14 | double lamlm(int flip); | 
|---|
|  | 15 | double lamlm(int l, int m); | 
|---|
|  | 16 | double lamlm(int l, int m, int flip); | 
|---|
|  | 17 | int l() const {return l_;} | 
|---|
|  | 18 | int m() const {return m_;} | 
|---|
|  | 19 | int lmax() const {return lmax_;} | 
|---|
|  | 20 | int mmax() const {return mmax_;} | 
|---|
|  | 21 | void step(); | 
|---|
|  | 22 | protected: | 
|---|
|  | 23 | double par_lm_; | 
|---|
|  | 24 | int lmax_; | 
|---|
|  | 25 | int mmax_; | 
|---|
|  | 26 | int l_; | 
|---|
|  | 27 | int m_; | 
|---|
|  | 28 | double lamlm_; | 
|---|
|  | 29 | double cth_; | 
|---|
|  | 30 | double sth_; | 
|---|
|  | 31 | double lammm_; | 
|---|
|  | 32 | double lam_0_; | 
|---|
|  | 33 | double lam_1_; | 
|---|
|  | 34 | double a_rec_; | 
|---|
|  | 35 | double b_rec_; | 
|---|
|  | 36 | double fm2_; | 
|---|
|  | 37 | //  static const double bignorm=1e-20*HUGE_VAL; | 
|---|
|  | 38 | //  static const double bignorm=1e-20*1.d288; | 
|---|
|  | 39 | static const double bignorm; | 
|---|
|  | 40 | }; | 
|---|
|  | 41 |  | 
|---|
|  | 42 | class Lambda2Builder : public LambdaBuilder { | 
|---|
|  | 43 | public: | 
|---|
|  | 44 | Lambda2Builder(); | 
|---|
|  | 45 | Lambda2Builder(double theta,int lmax, int mmax); | 
|---|
|  | 46 | Lambda2Builder(const Lambda2Builder& lb); | 
|---|
|  | 47 | void reset(); | 
|---|
|  | 48 | double lam2lmp() const {return -fact_*(w_-ix_);} | 
|---|
|  | 49 | double lam2lmp(int flip); | 
|---|
|  | 50 | double lam2lmp(int l, int m); | 
|---|
|  | 51 | double lam2lmp(int l, int m, int flip); | 
|---|
|  | 52 | double lam2lmm() const {return -fact_*(w_+ix_);} | 
|---|
|  | 53 | double lam2lmm(int flip); | 
|---|
|  | 54 | double lam2lmm(int l, int m); | 
|---|
|  | 55 | double lam2lmm(int l, int m, int flip); | 
|---|
|  | 56 | void step(); | 
|---|
|  | 57 | private: | 
|---|
|  | 58 | double fact_; | 
|---|
|  | 59 | double w_; | 
|---|
|  | 60 | double ix_; | 
|---|
|  | 61 | }; | 
|---|
|  | 62 | #endif | 
|---|
|  | 63 |  | 
|---|
|  | 64 | /*! \class LambdaBuilder | 
|---|
|  | 65 | \brief A lambda building class | 
|---|
|  | 66 |  | 
|---|
|  | 67 | Objects in this class generate | 
|---|
|  | 68 | \f[ | 
|---|
|  | 69 | \lambda_l^m=\sqrt{\frac{2l+1}{4\pi}\frac{(l-m)!}{(l+m)!}} | 
|---|
|  | 70 | P_l^m(\cos{\theta}) | 
|---|
|  | 71 | \f] | 
|---|
|  | 72 | where \f$P_l^m\f$ are the associated Legendre polynomials.  The interest | 
|---|
|  | 73 | of course is that | 
|---|
|  | 74 | \f[ | 
|---|
|  | 75 | Y_{lm}(\cos{\theta})=\lambda_l^m(\cos{\theta}) e^{im\phi}. | 
|---|
|  | 76 | \f] | 
|---|
|  | 77 |  | 
|---|
|  | 78 | Each object has a fixed theta, and maximum l and m to be calculated | 
|---|
|  | 79 | (lmax and mmax). | 
|---|
|  | 80 |  | 
|---|
|  | 81 | The algorithm solves the \f$\lambda_l^m\f$'s iteratively so there | 
|---|
|  | 82 | is an optimal sequance of l and m's as follows... | 
|---|
|  | 83 |  | 
|---|
|  | 84 | \code | 
|---|
|  | 85 | for (int m = 0; m <= nmmax; m++){ | 
|---|
|  | 86 | dum=lb.lamlm(m,m) | 
|---|
|  | 87 | for (int l = m+1; l<= nlmax; l++){ | 
|---|
|  | 88 | dum = lb.lamlm(l,m) | 
|---|
|  | 89 | } | 
|---|
|  | 90 | }\endcode | 
|---|
|  | 91 | The function LambdaBuilder::step() automatically shifts the l and | 
|---|
|  | 92 | m's to the next optimal value. | 
|---|
|  | 93 | However, \f$\lambda_l^m\f$ can be calculated for any l and m less than | 
|---|
|  | 94 | or equal to lmax and lmax by going through the loop or restarting the | 
|---|
|  | 95 | loop. | 
|---|
|  | 96 |  | 
|---|
|  | 97 | \f$\lambda_l^m(-\cos{\theta})\f$ can be quickly obtained using | 
|---|
|  | 98 | symmetry relations, which can be more efficient that creating a new | 
|---|
|  | 99 | LambdaBuilder object. | 
|---|
|  | 100 |  | 
|---|
|  | 101 | The algorithm is based on the HEALPIX code. | 
|---|
|  | 102 | */ | 
|---|
|  | 103 |  | 
|---|
|  | 104 | /*!  \fn LambdaBuilder::LambdaBuilder(double theta,int lmax, int mmax) | 
|---|
|  | 105 | \param theta the desired \f$\theta\f$ | 
|---|
|  | 106 | \param lmax the maximum value of l | 
|---|
|  | 107 | \param mmax the maximum value of m | 
|---|
|  | 108 | */ | 
|---|
|  | 109 | /*! | 
|---|
|  | 110 | \fn LambdaBuilder::LambdaBuilder(const LambdaBuilder& lb) | 
|---|
|  | 111 | \param lb the LambdaBuilder object to be copied | 
|---|
|  | 112 | */ | 
|---|
|  | 113 | /*! \fn void LambdaBuilder::reset() | 
|---|
|  | 114 | \brief Resets the object to l=0, m=0 | 
|---|
|  | 115 | */ | 
|---|
|  | 116 | /*! \fn double LambdaBuilder::lamlm() const | 
|---|
|  | 117 | \returns \f$\lambda_l^m\f$ for current l and m | 
|---|
|  | 118 | */ | 
|---|
|  | 119 | /*! | 
|---|
|  | 120 | \fn double LambdaBuilder::lamlm(int flip) | 
|---|
|  | 121 | \param flip \f$\theta\f$ to be multiplied by sign(flip) | 
|---|
|  | 122 | \returns \f$\lambda_l^m(\cos{(sign(flip)\theta}))\f$ for the current l and m. | 
|---|
|  | 123 | Uses symmetry relations to get this value. | 
|---|
|  | 124 | */ | 
|---|
|  | 125 | /*! \fn double LambdaBuilder::lamlm(int l, int m) | 
|---|
|  | 126 | \param l the desired l | 
|---|
|  | 127 | \param m the desired m | 
|---|
|  | 128 | \returns \f$\lambda_l^m\f$ for l and m | 
|---|
|  | 129 | */ | 
|---|
|  | 130 | /*!   \fn double LambdaBuilder::lamlm(int l, int m, int flip) | 
|---|
|  | 131 | \param l the desired l | 
|---|
|  | 132 | \param m the desired m | 
|---|
|  | 133 | \param flip \f$\theta\f$ to be multiplied by sign(flip) | 
|---|
|  | 134 | \returns \f$\lambda_l^m(\cos{(sign(flip)\theta}))\f$ for the given l and m. | 
|---|
|  | 135 | Uses symmetry relations to get this value. | 
|---|
|  | 136 | */ | 
|---|
|  | 137 | /*!   \fn int LambdaBuilder::l() const | 
|---|
|  | 138 | \returns current value of l | 
|---|
|  | 139 | */ | 
|---|
|  | 140 | /*!   \fn int LambdaBuilder::m() const | 
|---|
|  | 141 | \returns current value of m | 
|---|
|  | 142 | */ | 
|---|
|  | 143 | /*!   \fn int LambdaBuilder::lmax() const | 
|---|
|  | 144 | \returns the maximum value of l | 
|---|
|  | 145 | */ | 
|---|
|  | 146 | /*!   \fn int LambdaBuilder::mmax() const | 
|---|
|  | 147 | \returns the maximum value of m | 
|---|
|  | 148 | */ | 
|---|
|  | 149 | /*!   \fn void LambdaBuilder::step() | 
|---|
|  | 150 | \brief Steps to the next l and m | 
|---|
|  | 151 | */ | 
|---|
|  | 152 |  | 
|---|
|  | 153 | /*! \class Lambda2Builder | 
|---|
|  | 154 | \brief A lambda building class | 
|---|
|  | 155 |  | 
|---|
|  | 156 | Objects in this class generate | 
|---|
|  | 157 | \f[ | 
|---|
|  | 158 | _\pm\lambda_l^m=2\sqrt{\frac{(l-2)!}{(l+2)!}\frac{(2l+1)}{4\pi}\frac{(l-m)!}{(l+m)!}}\left( G^+_{lm} \mp G^-_{lm}\right) | 
|---|
|  | 159 | \f] | 
|---|
|  | 160 | where | 
|---|
|  | 161 | \f[G^+_{lm}(\cos{\theta})=-\left( \frac{l-m^2}{\sin^2{\theta}}+\frac{1}{2}l\left(l-1\right)\right)P_l^m(\cos{\theta})+\left(l+m\right)\frac{\cos{\theta}}{\sin^2{\theta}}P^m_{l-1}(\cos{\theta}) | 
|---|
|  | 162 | \f] | 
|---|
|  | 163 | and | 
|---|
|  | 164 | \f[G^-_{lm}(\cos{\theta})=\frac{m}{\sin^2{\theta}}\left(\left(l-1\right)\cos{\theta}P^m_l(\cos{\theta})-\left(l+m\right)P^m_{l-1}(\cos{\theta})\right) | 
|---|
|  | 165 | \f] | 
|---|
|  | 166 | and \f$P_l^m\f$ are the associated Legendre polynomials. | 
|---|
|  | 167 | The interest in all this is that | 
|---|
|  | 168 | \f[_{\pm2}Y_l^m(\cos{\theta})=_\pm\lambda_l^m(\cos{\theta})e^{im\phi} | 
|---|
|  | 169 | \f] | 
|---|
|  | 170 | where \f$_{\pm2}Y_l^m\f$ are the spin-2 spherical harmonics. | 
|---|
|  | 171 | */ | 
|---|
|  | 172 |  | 
|---|
|  | 173 | /*!   \fn  Lambda2Builder::Lambda2Builder(double theta,int lmax, int mmax) | 
|---|
|  | 174 | \param theta the desired \f$\theta\f$ | 
|---|
|  | 175 | \param lmax the maximum value of l | 
|---|
|  | 176 | \param mmax the maximum value of m | 
|---|
|  | 177 | */ | 
|---|
|  | 178 | /*!   \fn  Lambda2Builder::Lambda2Builder(const Lambda2Builder& lb) | 
|---|
|  | 179 | \param lb the Lambda2Builder object to be copied | 
|---|
|  | 180 | */ | 
|---|
|  | 181 | /*!   \fn  double Lambda2Builder::lam2lmp() const | 
|---|
|  | 182 | \returns \f$_+\lambda_l^m\f$ for current l and m | 
|---|
|  | 183 | */ | 
|---|
|  | 184 | /*!   \fn  double Lambda2Builder::lam2lmp(int flip); | 
|---|
|  | 185 | \param flip \f$\theta\f$ to be multiplied by sign(flip) | 
|---|
|  | 186 | \returns \f$_+\lambda_l^m(\cos{(sign(flip)\theta}))\f$ for the current l and m. | 
|---|
|  | 187 | Uses symmetry relations to get this value. | 
|---|
|  | 188 | */ | 
|---|
|  | 189 | /*!   \fn  double Lambda2Builder::lam2lmp(int l, int m) | 
|---|
|  | 190 | \param l the desired l | 
|---|
|  | 191 | \param m the desired m | 
|---|
|  | 192 | \returns \f$_+\lambda_l^m\f$ for l and m | 
|---|
|  | 193 | */ | 
|---|
|  | 194 | /*!   \fn  double Lambda2Builder::lam2lmp(int l, int m, int flip) | 
|---|
|  | 195 | \param l the desired l | 
|---|
|  | 196 | \param m the desired m | 
|---|
|  | 197 | \param flip \f$\theta\f$ to be multiplied by sign(flip) | 
|---|
|  | 198 | \returns \f$_+\lambda_l^m(\cos{(sign(flip)\theta}))\f$ for the given l and m. | 
|---|
|  | 199 | Uses symmetry relations to get this value. | 
|---|
|  | 200 | */ | 
|---|
|  | 201 | /*!   \fn  double Lambda2Builder::lam2lmm() const | 
|---|
|  | 202 | \returns \f$_-\lambda_l^m\f$ for current l and m | 
|---|
|  | 203 | */ | 
|---|
|  | 204 | /*!   \fn  double Lambda2Builder::lam2lmm(int flip) | 
|---|
|  | 205 | \param flip \f$\theta\f$ to be multiplied by sign(flip) | 
|---|
|  | 206 | \returns \f$_-\lambda_l^m(\cos{(sign(flip)\theta}))\f$ for the current l and m. | 
|---|
|  | 207 | Uses symmetry relations to get this value. | 
|---|
|  | 208 | */ | 
|---|
|  | 209 | /*!   \fn  double Lambda2Builder::lam2lmm(int l, int m) | 
|---|
|  | 210 | \param l the desired l | 
|---|
|  | 211 | \param m the desired m | 
|---|
|  | 212 | \returns \f$_-\lambda_l^m\f$ for l and m | 
|---|
|  | 213 | */ | 
|---|
|  | 214 | /*!   \fn  double Lambda2Builder::lam2lmm(int l, int m, int flip) | 
|---|
|  | 215 | \param l the desired l | 
|---|
|  | 216 | \param m the desired m | 
|---|
|  | 217 | \param flip \f$\theta\f$ to be multiplied by sign(flip) | 
|---|
|  | 218 | \returns \f$_-\lambda_l^m(\cos{(sign(flip)\theta}))\f$ for the given l and m. | 
|---|
|  | 219 | Uses symmetry relations to get this value. | 
|---|
|  | 220 | )*/ | 
|---|