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