| 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 | )*/ | 
|---|