| [2633] | 1 | #include <stdlib.h> | 
|---|
|  | 2 | #include <stdio.h> | 
|---|
|  | 3 | #include "machdefs.h" | 
|---|
|  | 4 | #include <iostream> | 
|---|
|  | 5 | #include <float.h> | 
|---|
|  | 6 | #include <math.h> | 
|---|
|  | 7 | #include "harmspher.h" | 
|---|
|  | 8 |  | 
|---|
|  | 9 | using namespace std; | 
|---|
|  | 10 |  | 
|---|
|  | 11 | /* | 
|---|
|  | 12 | ---------------------------------------------------------------- | 
|---|
|  | 13 | ----- Calcul des fonctions de Legendre Plm(cos(Theta)) ------ | 
|---|
|  | 14 | ---------------------------------------------------------------- | 
|---|
|  | 15 | (partie theta des harmoniques spheriques) | 
|---|
|  | 16 |  | 
|---|
|  | 17 | HarmSph_array(int lmax,int m,double cost,double *Plm) | 
|---|
|  | 18 | HarmSph_array_teta(int lmax,int m,double teta,double *Plm) | 
|---|
|  | 19 |  | 
|---|
|  | 20 | - Input: | 
|---|
|  | 21 | lmax, m and teta or cos(teta)    (lmax>=m) | 
|---|
|  | 22 | array Plm with size at least "lmax-m+1" | 
|---|
|  | 23 | (calling with HarmSph_array_teta for small teta is more accurate) | 
|---|
|  | 24 |  | 
|---|
|  | 25 | - Action: | 
|---|
|  | 26 | compute Psph for fixed "m" and all "l" from "m" to "lmax" | 
|---|
|  | 27 |  | 
|---|
|  | 28 | - Return array: Psph(l,m) | 
|---|
|  | 29 | index Psph(l,m) = Plm[l-m] | 
|---|
|  | 30 |  | 
|---|
|  | 31 | - Return value: | 
|---|
|  | 32 | Psph(lmax,m) = Plm[lmax-m] | 
|---|
|  | 33 |  | 
|---|
|  | 34 | - Rappel:    x = cos(teta) | 
|---|
|  | 35 | Polynomes de Legendre associes: P(l,m) | 
|---|
|  | 36 | Polynomes de Legendre pour les harmoniques spheriques: Psph(l,m) | 
|---|
|  | 37 | (souvent appelles lambda_lm) | 
|---|
|  | 38 | Psph(l,m) = sqrt((2l+1)/4Pi) * sqrt((l-m)!/(l+m)!) * P(l,m) | 
|---|
|  | 39 | ---------------------------------------------------------------- | 
|---|
|  | 40 | */ | 
|---|
|  | 41 |  | 
|---|
|  | 42 | double HarmSph_array_teta(int lmax,int m,double teta,double *xlm) | 
|---|
|  | 43 | { | 
|---|
|  | 44 | // Debug level | 
|---|
|  | 45 | const int lp=0; | 
|---|
|  | 46 | // Si une valeur finale est <10^EXPO_MINI on retourne zero | 
|---|
|  | 47 | const double EXPO_MINI = DBL_MIN_10_EXP +5; | 
|---|
|  | 48 | // Si une valeur dans la reccurence est <FACTMINI on renormalise | 
|---|
|  | 49 | const double FACTMINI = 1.e-50; | 
|---|
|  | 50 |  | 
|---|
|  | 51 | if(m<0 || m>lmax) { | 
|---|
|  | 52 | cout<<"HarmSph_array_Error: bad arguments lmax="<<lmax<<" m="<<m<<endl; | 
|---|
|  | 53 | return(0.); | 
|---|
|  | 54 | } | 
|---|
|  | 55 |  | 
|---|
|  | 56 | double x = cos(teta); | 
|---|
|  | 57 | if(lp) cout<<"HarmSph_array_teta: x="<<x<<" lmax="<<lmax<<" m="<<m<<endl; | 
|---|
|  | 58 |  | 
|---|
|  | 59 | /* ---- calcul Psph(0,0) = 1/sqrt(4Pi) */ | 
|---|
|  | 60 | xlm[0] = M_2_SQRTPI/4.; | 
|---|
|  | 61 | if(m==0 && lmax==0) return xlm[0]; | 
|---|
|  | 62 |  | 
|---|
|  | 63 | /* ---- calcul Psph(m,m): | 
|---|
|  | 64 | Recurrence: | 
|---|
|  | 65 | P(l,m) = (-1)^m * (2m-1)!! * (1-x^2)^(m/2) | 
|---|
|  | 66 | Psph(m+1,m+1) = -Psph(m,m) * sin(teta)*sqrt((2m+3)/(2m+2)) | 
|---|
|  | 67 | ou Psph(m,m) = - Psph(m-1,m-1) * sin(teta)*sqrt((2m+1)/2m) | 
|---|
|  | 68 | et Psph(0,0) = 1/sqrt(4Pi) | 
|---|
|  | 69 | Pb: pour m grand et sin(teta) petit sin(teta)^m devient | 
|---|
|  | 70 | plus petit que la limite machine (1e-300) et on obtient zero | 
|---|
|  | 71 | */ | 
|---|
|  | 72 | double expos = 0.; | 
|---|
|  | 73 | if(m>0) {          // Psph(0,0) == xlm[0] | 
|---|
|  | 74 | //double st = sqrt((1.-x)*(1.+x)); | 
|---|
| [2634] | 75 | double st = fabs(sin(teta)); | 
|---|
| [2633] | 76 | for(int i=1;i<=m;i++) { | 
|---|
|  | 77 | xlm[0] *= -sqrt(((double)i+0.5)/(double)i) *st; | 
|---|
|  | 78 | double fxlm = fabs(xlm[0]); | 
|---|
|  | 79 | if(fxlm<FACTMINI && fxlm>0.) { | 
|---|
|  | 80 | if(lp>1) cout<<i<<" renorm: xlm[0]="<<xlm[0]<<" e="<<log10(fxlm); | 
|---|
|  | 81 | xlm[0] = (xlm[0]>0.)? 1.: -1.; | 
|---|
|  | 82 | expos += log10(fxlm); | 
|---|
|  | 83 | if(lp>1) cout<<" --> "<<xlm[0]<<", expos="<<expos<<endl; | 
|---|
|  | 84 | } | 
|---|
|  | 85 | } | 
|---|
|  | 86 | } | 
|---|
|  | 87 | if(lp) cout<<"End computing Pmm="<<xlm[0]<<", expos="<<expos<<endl; | 
|---|
|  | 88 |  | 
|---|
|  | 89 | /* ---- calcul Psph(m+1,m): | 
|---|
|  | 90 | Formule: | 
|---|
| [2892] | 91 | P(m+1,m) = cos(teta)*sqrt(2m+1)*P(m,m) | 
|---|
|  | 92 | Psph(m+1,m) = cos(teta)*sqrt(2m+3)*Psph(m,m) | 
|---|
| [2633] | 93 | En fait cela s'integre sans probleme dans la recurrence generale ci-dessous | 
|---|
|  | 94 | */ | 
|---|
|  | 95 | /* ---- calcul de Psph(l,m)  pour l>m+1 : | 
|---|
|  | 96 | Recurrence: | 
|---|
|  | 97 | P(l,m)  = [ (2l-1)*x * P(l-1,m) - (l-1+m) * P(l-2,m) ] / (l-m) | 
|---|
|  | 98 | Psph(l,m) = sqrt((4*l^2-1)/(l^2-m^2)) | 
|---|
|  | 99 | * [ cos(teta) * Psph(l-1,m) | 
|---|
|  | 100 | - sqrt(((l-1)^2-m^2)/(4*(l-1)^2-1)) * Psph(l-2,m) ] | 
|---|
|  | 101 | Psph(l,m) = sqrt((2l-1)*(2l+1)/((l-m)*(l+m))) | 
|---|
|  | 102 | * [ cos(teta) * Psph(l-1,m) | 
|---|
|  | 103 | - sqrt((l-m-1)*(l-1+m)/((2l-3)*(2l-1))) * Psph(l-2,m) ] | 
|---|
|  | 104 |  | 
|---|
|  | 105 | */ | 
|---|
|  | 106 | if(lmax>m) { | 
|---|
|  | 107 | const double expo_factmini = log10(FACTMINI); | 
|---|
|  | 108 | double factmaxi = 1./FACTMINI; | 
|---|
|  | 109 | double pm2=0., pm1=xlm[0], b_rec=0.; | 
|---|
|  | 110 | for(int ll=m+1;ll<=lmax;ll++) { | 
|---|
|  | 111 | int il = ll-m; | 
|---|
|  | 112 | double a_rec = sqrt( (2.*ll-1.)*(2.*ll+1.)/((ll-m)*(ll+m)) ); | 
|---|
|  | 113 | xlm[il] = a_rec*(x*pm1-b_rec*pm2); | 
|---|
|  | 114 | double fxlm = fabs(xlm[il]); | 
|---|
|  | 115 | // Par construction "expos" est negatif ou nul (car FACTMINI<1) | 
|---|
|  | 116 | if(expos<0. && fxlm>factmaxi) { | 
|---|
|  | 117 | // On renormalise par factmaxi si on a encore de la reserve d'exposant | 
|---|
|  | 118 | double fact,efact; | 
|---|
|  | 119 | if(expos<expo_factmini) { | 
|---|
|  | 120 | fact  = factmaxi; | 
|---|
|  | 121 | efact = -expo_factmini; | 
|---|
|  | 122 | expos += efact; | 
|---|
|  | 123 | } else { | 
|---|
|  | 124 | fact = pow(10.,expos); | 
|---|
|  | 125 | efact = expos; | 
|---|
|  | 126 | expos = 0.; | 
|---|
|  | 127 | if(lp>1) cout<<"!! expos==0 !!"<<endl; | 
|---|
|  | 128 | } | 
|---|
|  | 129 | if(lp>1) cout<<ll<<" renorm: xlm["<<il<<"]="<<xlm[il]<<", expos="<<expos<<endl; | 
|---|
|  | 130 | for(int i=0;i<=ll-m;i++) xlm[i] /= fact; | 
|---|
|  | 131 | } | 
|---|
|  | 132 | pm2 = xlm[il-1]; | 
|---|
|  | 133 | pm1 = xlm[il]; | 
|---|
|  | 134 | b_rec = 1./a_rec; | 
|---|
|  | 135 | } | 
|---|
|  | 136 | } | 
|---|
|  | 137 |  | 
|---|
|  | 138 | if(lp) cout<<"Return: Final expos="<<expos<<endl; | 
|---|
|  | 139 | if(expos!=0.) { | 
|---|
|  | 140 | for(int i=0;i<=lmax-m;i++) { | 
|---|
| [2635] | 141 | double fxml=fabs(xlm[i]); | 
|---|
|  | 142 | if(lp>1) cout<<"     xlm["<<i<<"]="<<xlm[i]; | 
|---|
|  | 143 | if(fxml>0.) { | 
|---|
|  | 144 | double e = log10(fxml); | 
|---|
|  | 145 | if(lp>1) cout<<" (e="<<e<<")"; | 
|---|
|  | 146 | if(expos+e<EXPO_MINI) xlm[i] = 0.; | 
|---|
|  | 147 | else if(expos>EXPO_MINI) xlm[i] *= pow(10.,expos); | 
|---|
|  | 148 | else xlm[i] = pow(10.,expos+e); | 
|---|
|  | 149 | } | 
|---|
| [2633] | 150 | if(lp>1) cout<<" ---> "<<xlm[i]<<endl; | 
|---|
|  | 151 | } | 
|---|
|  | 152 | } | 
|---|
|  | 153 | return xlm[lmax-m]; | 
|---|
|  | 154 |  | 
|---|
|  | 155 | } | 
|---|