source: Sophya/trunk/SophyaLib/Samba/lambdaBuilder.cc@ 2715

Last change on this file since 2715 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

File size: 9.8 KB
RevLine 
[2615]1#include "sopnamsp.h"
[729]2#include "lambdaBuilder.h"
3#include "nbconst.h"
4
5
[1218]6/*!
7 \class SOPHYA::Legendre
8generate Legendre polynomials : use in two steps :
9
10a) instanciate Legendre(\f$x\f$, \f$lmax\f$) ; \f$x\f$ is the value for wich Legendre polynomials will be required (usually equal to \f$\cos \theta\f$) and \f$lmax\f$ is the MAXIMUM value of the order of polynomials wich will be required in the following code (all polynomials, from \f$l=0 to lmax\f$, are computed once for all by an iterative formula).
11
12b) get the value of Legendre polynomial for a particular value of \f$l\f$ by calling the method getPl.
13
14*/
15
16
[729]17Legendre::Legendre(r_8 x, int_4 lmax)
18{
[1428]19 if (fabs(x) > 1. )
[729]20 {
21 throw RangeCheckError("variable for Legendre polynomials must have modules inferior to 1" );
22 }
23 x_ = x;
24 array_init(lmax);
25}
[1218]26
27/*! \fn void SOPHYA::Legendre::array_init(int_4 lmax)
28
29compute all \f$P_l(x,l_{max})\f$ for \f$l=1,l_{max}\f$
30*/
[729]31void Legendre::array_init(int_4 lmax)
32{
33 lmax_ = lmax;
34 Pl_.ReSize(lmax_+1);
35 Pl_(0)=1.;
[2277]36 if (lmax>0) Pl_(1)=x_;
[729]37 for (int k=2; k<Pl_.NElts(); k++)
38 {
39 Pl_(k) = ( (2.*k-1)*x_*Pl_(k-1)-(k-1)*Pl_(k-2) )/k;
40 }
41}
42
[1756]43TriangularMatrix<r_8> LambdaLMBuilder::a_recurrence_ = TriangularMatrix<r_8>();
44TriangularMatrix<r_8> LambdaLMBuilder::lam_fact_ = TriangularMatrix<r_8>();
[729]45TVector<r_8>* LambdaLMBuilder::normal_l_ = NULL;
46
[1218]47
48
49/*! \class SOPHYA::LambdaLMBuilder
50
51
52This class generate the coefficients :
53\f[
54 \lambda_l^m=\sqrt{\frac{2l+1}{4\pi}\frac{(l-m)!}{(l+m)!}}
55 P_l^m(\cos{\theta})
56\f]
57where \f$P_l^m\f$ are the associated Legendre polynomials. The above coefficients contain the theta-dependance of spheric harmonics :
58\f[
59 Y_{lm}(\cos{\theta})=\lambda_l^m(\cos{\theta}) e^{im\phi}.
60\f]
61
62Each object has a fixed theta (radians), and maximum l and m to be calculated
63(lmax and mmax).
64 use the class in two steps :
65a) instanciate LambdaLMBuilder(\f$\theta\f$, \f$lmax\f$, \f$mmax\f$) ; \f$lmax\f$ and \f$mmax\f$ are MAXIMUM values for which \f$\lambda_l^m\f$ will be required in the following code (all coefficients, from \f$l=0 to lmax\f$, are computed once for all by an iterative formula).
66b) get the values of coefficients for particular values of \f$l\f$ and \f$m\f$ by calling the method lamlm.
67*/
68
69
[729]70LambdaLMBuilder::LambdaLMBuilder(r_8 theta,int_4 lmax, int_4 mmax)
71 {
72 cth_=cos(theta);
73 sth_=sin(theta);
74 array_init(lmax, mmax);
75 }
[1683]76LambdaLMBuilder::LambdaLMBuilder(r_8 costet, r_8 sintet,int_4 lmax, int_4 mmax)
77 {
78 cth_=costet;
79 sth_=sintet;
80 array_init(lmax, mmax);
81 }
[729]82void LambdaLMBuilder::array_init(int lmax, int mmax)
83 {
[1756]84 if (a_recurrence_.Size() == 0)
[729]85 {
[1756]86 // a_recurrence_ = new TriangularMatrix<r_8>;
[729]87 updateArrayRecurrence(lmax);
88 }
89 else
[1756]90 if ( lmax > (a_recurrence_).rowNumber()-1 )
[729]91 {
92 cout << " WARNING : The classes LambdaXXBuilder will be more efficient if instanciated with parameter lmax = maximum value of l index which will be needed in the whole application (arrays not recomputed) " << endl;
[1756]93 cout << "lmax= " << lmax << " previous instanciation with lmax= " << (a_recurrence_).rowNumber() << endl;
[729]94 updateArrayRecurrence(lmax);
95 }
96 lmax_=lmax;
97 mmax_=mmax;
98 r_8 bignorm2 = 1.e268; // = 1e-20*1.d288
99
100 lambda_.ReSizeRow(lmax_+1);
101
102 r_8 lam_mm = 1. / sqrt(4.*Pi) *bignorm2;
103
104 for (int m=0; m<=mmax_;m++)
105 {
106
107
108 lambda_(m,m)= lam_mm / bignorm2;
109
110 r_8 lam_0=0.;
111 r_8 lam_1=1. /bignorm2 ;
112 // r_8 a_rec = LWK->a_recurr(m,m);
[1756]113 r_8 a_rec = a_recurrence_(m,m);
[729]114 r_8 b_rec = 0.;
115 for (int l=m+1; l<=lmax_; l++)
116 {
117 r_8 lam_2 = (cth_*lam_1-b_rec*lam_0)*a_rec;
118 lambda_(l,m) = lam_2*lam_mm;
119 b_rec=1./a_rec;
120 // a_rec= LWK->a_recurr(l,m);
[1756]121 a_rec= a_recurrence_(l,m);
[729]122 lam_0 = lam_1;
123 lam_1 = lam_2;
124 }
125
126 lam_mm = -lam_mm*sth_* sqrt( (2.*m+3.)/ (2.*m+2.) );
127
128 }
129 }
130
131
[1218]132/*! \fn void SOPHYA::LambdaLMBuilder::updateArrayRecurrence(int_4 lmax)
133
134 compute a static array of coefficients independant from theta (common to all instances of the LambdaBuilder Class
135*/
[729]136void LambdaLMBuilder::updateArrayRecurrence(int_4 lmax)
137 {
[1756]138 a_recurrence_.ReSizeRow(lmax+1);
[729]139 for (int m=0; m<=lmax;m++)
140 {
[1756]141 a_recurrence_(m,m) = sqrt( 2.*m +3.);
[729]142 for (int l=m+1; l<=lmax; l++)
143 {
144 r_8 fl2 = (l+1.)*(l+1.);
[1756]145 a_recurrence_(l,m)=sqrt( (4.*fl2-1.)/(fl2-m*m) );
[729]146 }
147 }
148 }
149
[1218]150/*! \fn void SOPHYA::LambdaLMBuilder::updateArrayLamNorm()
[729]151
[1218]152 compute static arrays of coefficients independant from theta (common to all instances of the derived classes
153*/
[729]154void LambdaLMBuilder::updateArrayLamNorm()
155 {
[1756]156 lam_fact_.ReSizeRow(lmax_+1);
[729]157 for(int m = 0;m<= lmax_; m++)
158 {
159 for (int l=m; l<=lmax_; l++)
160 {
[1756]161 lam_fact_(l,m) =2.*(r_8)sqrt( (2.*l+1)*(l+m)*(l-m)/(2.*l-1) );
[729]162 }
163 }
164 (*normal_l_).ReSize(lmax_+1);
165 (*normal_l_)(0)=0.;
166 (*normal_l_)(1)=0.;
167 for (int l=2; l< (*normal_l_).NElts(); l++)
168 {
169 (*normal_l_)(l) =(r_8)sqrt( 2./( (l+2)*(l+1)*l*(l-1) ) );
170 }
171 }
172
173
[1218]174/*! \class SOPHYA::LambdaWXBuilder
[729]175
[1218]176This class generates the coefficients :
177\f[
178 _{w}\lambda_l^m=-2\sqrt{\frac{2(l-2)!}{(l+2)!}\frac{(2l+1)}{4\pi}\frac{(l-m)!}{(l+m)!}} G^+_{lm}
179\f]
180\f[
181 _{x}\lambda_l^m=-2\sqrt{\frac{2(l-2)!}{(l+2)!}\frac{(2l+1)}{4\pi}\frac{(l-m)!}{(l+m)!}}G^-_{lm}
182\f]
183where
184\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})
185\f]
186and
187\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)
188\f]
189 \f$P_l^m\f$ are the associated Legendre polynomials.
[729]190
[1218]191The coefficients express the theta-dependance of the \f$W_{lm}(\cos{\theta})\f$ and \f$X_{lm}(\cos{\theta})\f$ functions :
192\f[W_{lm}(\cos{\theta}) = \sqrt{\frac{(l+2)!}{2(l-2)!}}_w\lambda_l^m(\cos{\theta})e^{im\phi}
193\f]
194\f[X_{lm}(\cos{\theta}) = -i\sqrt{\frac{(l+2)!}{2(l-2)!}}_x\lambda_l^m(\cos{\theta})e^{im\phi}
195\f]
196 where \f$W_{lm}(\cos{\theta})\f$ and \f$X_{lm}(\cos{\theta})\f$ are defined as :
197
198\f[
199W_{lm}(\cos{\theta})=-\frac{1}{2}\sqrt{\frac{(l+2)!}{(l-2)!}}\left(
200_{+2}Y_l^m(\cos{\theta})+_{-2}Y_l^m(\cos{\theta})\right)
201\f]
202\f[X_{lm}(\cos{\theta})=-\frac{i}{2}\sqrt{\frac{(l+2)!}{(l-2)!}}\left(
203_{+2}Y_l^m(\cos{\theta})-_{-2}Y_l^m(\cos{\theta})\right)
204\f]
205
206*/
207
208
[729]209LambdaWXBuilder::LambdaWXBuilder(r_8 theta, int_4 lmax, int_4 mmax) : LambdaLMBuilder(theta, lmax, mmax)
210 {
211 array_init();
212 }
213
214
215void LambdaWXBuilder::array_init()
216 {
[1756]217 if (lam_fact_.Size() < 1 || normal_l_ == NULL)
[729]218 {
[1756]219 // lam_fact_ = new TriangularMatrix<r_8>;
[729]220 normal_l_ = new TVector<r_8>;
221 updateArrayLamNorm();
222 }
223 else
[1756]224 if ( lmax_ > lam_fact_.rowNumber()-1 || lmax_ > (*normal_l_).NElts()-1 )
[729]225 {
226 updateArrayLamNorm();
227 }
228
229 r_8 one_on_s2 = 1. / (sth_*sth_) ; // 1/sin^2
230 r_8 c_on_s2 = cth_*one_on_s2;
231 lamWlm_.ReSizeRow(lmax_+1);
232 lamXlm_.ReSizeRow(lmax_+1);
233
234 // calcul des lambda
235 for(int m = 0;m<= mmax_; m++)
236 {
237 for (int l=m; l<=lmax_; l++)
238 {
239 lamWlm_(l,m) = 0.;
240 lamXlm_(l,m) = 0.;
241 }
242 }
243 for(int l = 2;l<= lmax_; l++)
244 {
245 r_8 normal_l = (*normal_l_)(l);
246 for (int m=0; m<=l; m++)
247 {
248 r_8 lam_lm1m = LambdaLMBuilder::lamlm(l-1,m);
249 r_8 lam_lm = LambdaLMBuilder::lamlm(l,m);
[1756]250 r_8 lam_fact_l_m = lam_fact_(l,m);
[729]251 r_8 a_w = 2. * (l - m*m) * one_on_s2 + l*(l-1.);
252 r_8 b_w = c_on_s2 * lam_fact_l_m;
253 r_8 a_x = 2. * cth_ * (l-1.);
254 lamWlm_(l,m) = normal_l * ( a_w * lam_lm - b_w * lam_lm1m );
255 lamXlm_(l,m) = - normal_l * m* one_on_s2* ( a_x * lam_lm - lam_fact_l_m * lam_lm1m );
256 }
257 }
258
259 }
260
[1218]261/*! \class SOPHYA::LambdaPMBuilder
[729]262
[1218]263This class generates the coefficients
264\f[
265 _{\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)
266\f]
267where
268\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})
269\f]
270and
271\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)
272\f]
273and \f$P_l^m\f$ are the associated Legendre polynomials.
274The coefficients express the theta-dependance of the spin-2 spherical harmonics :
275\f[_{\pm2}Y_l^m(\cos{\theta})=_\pm\lambda_l^m(\cos{\theta})e^{im\phi}
276\f]
277*/
278
[729]279LambdaPMBuilder::LambdaPMBuilder(r_8 theta, int_4 lmax, int_4 mmax) : LambdaLMBuilder(theta, lmax, mmax)
280 {
281 array_init();
282 }
283
284
285void LambdaPMBuilder::array_init()
286 {
[1756]287 if (lam_fact_.Size() < 1 || normal_l_ == NULL)
[729]288 {
[1756]289 // lam_fact_ = new TriangularMatrix<r_8>;
[729]290 normal_l_ = new TVector<r_8>;
291 updateArrayLamNorm();
292 }
293 else
[1756]294 if ( lmax_ > lam_fact_.rowNumber()-1 || lmax_ > (*normal_l_).NElts()-1 )
[729]295 {
296 updateArrayLamNorm();
297 }
298
299 r_8 one_on_s2 = 1. / (sth_*sth_) ;
300 r_8 c_on_s2 = cth_*one_on_s2;
301 lamPlm_.ReSizeRow(lmax_+1);
302 lamMlm_.ReSizeRow(lmax_+1);
303
304 // calcul des lambda
305 for(int m = 0;m<= mmax_; m++)
306 {
307 for (int l=m; l<=lmax_; l++)
308 {
309 lamPlm_(l,m) = 0.;
310 lamMlm_(l,m) = 0.;
311 }
312 }
313
314 for(int l = 2;l<= lmax_; l++)
315 {
316 r_8 normal_l = (*normal_l_)(l);
317 for (int m=0; m<=l; m++)
318 {
319 r_8 lam_lm1m = LambdaLMBuilder::lamlm(l-1,m);
320 r_8 lam_lm = LambdaLMBuilder::lamlm(l,m);
[1756]321 r_8 lam_fact_l_m = lam_fact_(l,m);
[729]322 r_8 a_w = 2. * (l - m*m) * one_on_s2 + l*(l-1.);
323 r_8 f_w = lam_fact_l_m/(sth_*sth_);
324 r_8 c_w = 2*m*(l-1.) * c_on_s2;
325
326 lamPlm_(l,m) = normal_l * ( -(a_w+c_w) * lam_lm + f_w*( cth_ + m) * lam_lm1m )/Rac2;
327 lamMlm_(l,m) = normal_l * ( -(a_w-c_w) * lam_lm + f_w*( cth_ - m) * lam_lm1m )/Rac2;
328 }
329 }
330
331 }
332
333
Note: See TracBrowser for help on using the repository browser.