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