00001 #ifndef __COULWAVE_CC
00002 #define __COULWAVE_CC
00003 #define NO_GSLCOULWAVE_BUG
00004 #include "sf.h"
00005
00006 using namespace std;
00007
00008 complex<double> CoulWave::cgamma(complex<double> z){
00009 complex<double> ci(0.0,1.0);
00010 gsl_sf_result gsl_lnr,gsl_arg;
00011 int dummy=gsl_sf_lngamma_complex_e(real(z),imag(z),&gsl_lnr,&gsl_arg);
00012 return exp(gsl_lnr.val)*(cos(gsl_arg.val)+ci*sin(gsl_arg.val));
00013 }
00014
00015
00016
00017 void CoulWave::GetFG(int L,double x,double eta,double *FL,double *GL){
00018 double expF,expG,sigma;
00019 complex<double> cg,ci(0.0,1.0);
00020 double *fc,*gc;
00021 fc=new double[L+1];
00022 gc=new double[L+1];
00023 cg=CoulWave::cgamma(double(L+1)+ci*eta);
00024 sigma=atan2(imag(cg),real(cg));
00025
00026
00027 int dummy=gsl_sf_coulomb_wave_FG_array(0,L,eta,x,fc,gc,&expF,&expG);
00028 *FL=fc[L]*exp(expF);
00029 *GL=gc[L]*exp(expG);
00030 #ifndef NO_GSLCOULWAVE_BUG
00031 if(x>2.0){
00032 phase=atan2(*GL,*FL);
00033 phase=phase+x-0.5*PI*(L+1)+sigma-eta*log(2.0*x);
00034 phase+=0.5*double(L*(L+1))/x;
00035 phase=phase-2.0*PI*floor(0.5*phase/PI);
00036 if(phase>PI) phase=phase-2.0*PI;
00037 if(fabs(phase)>2.0){
00038 *FL=-*FL;
00039 *GL=-*GL;
00040
00041 }
00042 }
00043 #endif
00044 delete [] fc;
00045 delete [] gc;
00046 }
00047
00048
00049 void CoulWave::GetFGprime(int L,double x,double eta,double *FL,double *GL,double *FLprime,double *GLprime){
00050 double expF,expG;
00051 double *fc,*gc,*fcp,*gcp;
00052 int k=0;
00053 fc=new double[k+1];
00054 gc=new double[k+1];
00055 fcp=new double[k+1];
00056 gcp=new double[k+1];
00057
00058 int dummy=gsl_sf_coulomb_wave_FGp_array(L,k,eta,x,fc,fcp,gc,gcp,
00059 &expF,&expG);
00060 *FL=fc[0]*exp(expF);
00061 *GL=gc[0]*exp(expG);
00062 *FLprime=fcp[0]*exp(expF);
00063 *GLprime=gcp[0]*exp(expG);
00064 delete [] fc;
00065 delete [] gc;
00066 delete [] fcp;
00067 delete [] gcp;
00068 }
00069
00070 complex<double> CoulWave::CWoutgoing(int ell,double x,double eta){
00071 double FL,GL;
00072 complex<double> ci(0.0,1.0);
00073 GetFG(ell,x,eta,&FL,&GL);
00074 return FL-ci*GL;
00075 }
00076
00077 complex<double> CoulWave::CWincoming(int ell,double x,double eta){
00078 double FL,GL;
00079 complex<double> ci(0.0,1.0);
00080 GetFG(ell,x,eta,&FL,&GL);
00081 return FL+ci*GL;
00082 }
00083
00084
00085
00086 void CoulWave::phaseshift_CoulombCorrect(int ell,double q,double eta,
00087 double &delta,double &ddeltadq){
00088 const double PI=4.0*atan(1.0);
00089 double *gamow,*dgamowdq;
00090 double tandelta0,tandelta,dtandelta0dq,dtandeltadq;
00091 int i;
00092
00093 if(fabs(eta)>1.0E-10){
00094 gamow=new double[ell+1];
00095 dgamowdq=new double[ell+1];
00096 gamow[0]=2.0*PI*eta/(exp(2.0*PI*eta)-1.0);
00097 dgamowdq[0]=(gamow[0]/q)*(gamow[0]*exp(2.0*PI*eta)-1.0);
00098 for(i=0;i<ell;i++){
00099 gamow[i+1]=gamow[i]*(double((i+1)*(i+1))+eta*eta);
00100 dgamowdq[i+1]=dgamowdq[i]*(double((i+1)*(i+1))+eta*eta)
00101 -(2.0*eta*eta/q)*gamow[i];
00102 }
00103
00104 tandelta0=tan(delta);
00105 dtandelta0dq=ddeltadq*(1.0+tandelta0*tandelta0);
00106
00107 tandelta=tandelta0*gamow[ell];
00108 if(cos(delta)>0.0) delta=atan(tandelta);
00109 else delta=atan(tandelta)+PI;
00110 if(delta>PI) delta=delta-2.0*PI;
00111
00112 dtandeltadq=gamow[ell]*dtandelta0dq+tandelta0*dgamowdq[ell];
00113 ddeltadq=dtandeltadq/(1.0+tandelta*tandelta);
00114 delete [] gamow;
00115 delete [] dgamowdq;
00116 }
00117 }
00118
00119 void CoulWave::GetFGprime_ImagQ(int ellmax,double x,double eta,double *FL,double *GL,double *FLprime,double *GLprime){
00120 double *F,*G,*Fprime,*Gprime;
00121 F=new double[ellmax+1]; G=new double[ellmax+1]; Fprime=new double[ellmax+1]; Gprime=new double[ellmax+1];
00122 double ff,root,sign;
00123 int n,l,nmax;
00124 const complex<double> ci(0.0,1.0);
00125 double *A,*B;
00126 nmax=24+lrint(fabs(x));
00127 A=new double[nmax+1];
00128 B=new double[nmax+1];
00129
00130 A[0]=0.0; A[1]=1.0;
00131 for(n=0;n<=nmax;n++) B[n]=0.0;
00132 for(n=0;n<=nmax-2;n++) A[n+2]=(2.0*eta*A[n+1]+A[n])/double((n+1)*(n+2));
00133 F[0]=Fprime[0]=0.0;
00134 for(n=1;n<=nmax;n++){
00135 F[0]+=A[n]*pow(x,n);
00136 Fprime[0]+=double(n)*A[n]*pow(x,n-1);
00137 }
00138 for(l=0;l<ellmax;l++){
00139 root=(l+1.0)*(l+1.0)-eta*eta;
00140 if(root>=0){
00141 root=sqrt(root);
00142 sign=1;
00143 }
00144 else{
00145 root=sqrt(-root);
00146 sign=-1;
00147 }
00148
00149 ff=(((l+1.0)*(l+1.0)/x)+eta);
00150 F[l+1]=(ff*F[l]-(l+1.0)*Fprime[l])/root;
00151 Fprime[l+1]=-(sign*root*F[l]+ff*F[l+1])/(l+1.0);
00152 }
00153
00154 A[0]=1.0; A[1]=0.0; B[1]=2.0*eta*A[0]; B[0]=0.0;
00155 for(n=0;n<=nmax-2;n++){
00156 B[n+2]=(2.0*eta*B[n+1]+B[n])/((n+1.0)*(n+2.0));
00157 A[n+2]=(2.0*eta*A[n+1]+A[n]+(1.0-2.0*(n+2.0))*B[n+2])/((n+1.0)*(n+2.0));
00158 }
00159 G[0]=1; Gprime[0]=0.0;
00160 for(n=1;n<=nmax;n++){
00161 G[0]+=(A[n]+B[n]*log(fabs(x)))*pow(x,n);
00162 Gprime[0]+=double(n)*(A[n]+B[n]*log(fabs(x)))*pow(x,n-1)+B[n]*pow(x,n-1);
00163 }
00164 for(l=0;l<ellmax;l++){
00165 root=(l+1.0)*(l+1.0)-eta*eta;
00166 if(root>=0){
00167 root=sqrt(root);
00168 sign=1;
00169 }
00170 else{
00171 root=sqrt(-root);
00172 sign=-1;
00173 }
00174 ff=((l+1.0)*(l+1.0)/x)+eta;
00175 G[l+1]=(ff*G[l]-(l+1.0)*Gprime[l])/root;
00176 Gprime[l+1]=-(sign*root*G[l]+ff*G[l+1])/(l+1.0);
00177 }
00178
00179 *FL=F[ellmax];
00180 *GL=G[ellmax];
00181 *FLprime=Fprime[ellmax];
00182 *GLprime=Gprime[ellmax];
00183
00184 delete[] A;
00185 delete[] B;
00186 delete[] F;
00187 delete [] G;
00188 delete [] Fprime;
00189 delete [] Gprime;
00190 }
00191
00192 void CoulWave::GetFGprime_ComplexQ(int ell,complex<double> cx,complex<double> ceta,double *FL,double *GL,double *FLprime,double *GLprime){
00193
00194 if(fabs(imag(cx)) > fabs(real(cx))){
00195
00196
00197 if(abs(ceta)>1.0E-8) CoulWave::GetFGprime_ImagQ(ell,imag(cx),-imag(ceta),FL,GL,FLprime,GLprime);
00198 else Bessel::CalcJN_imag(ell,imag(cx),*FL,*GL,*FLprime,*GLprime);
00199 }
00200 else{
00201 if(abs(ceta)>1.0E-8) CoulWave::GetFGprime(ell,real(cx),real(ceta),FL,GL,FLprime,GLprime);
00202 else Bessel::CalcJN_real(ell,real(cx),*FL,*GL,*FLprime,*GLprime);
00203 }
00204 return;
00205 }
00206
00207 complex<double> CoulWave::cw2_small_r(int l,complex<double> r,
00208 complex<double> eta){
00209 const double PI=4.0*atan(1.0);
00210 const double EULER=0.5772156649015328606;
00211
00212
00213
00214 double psi1,psi2,sum2;
00215 complex<double> delsum1,sum1,lterm,answer,ci(0.0,1.0);
00216 double cdcon1,cdcon2,factor,cx,delp,psi3,fact1,fact2,rr,ceta;
00217 int k;
00218 rr=real(-ci*r);
00219 ceta=real(-ci*eta);
00220
00221
00222 cdcon1=real(CoulWave::cgamma(-double(l)+ceta));
00223 cdcon2=real(CoulWave::cgamma(double(l+1)+ceta));
00224
00225 factor=pow(-1,double(2*l+1))*pow(2.0*rr,double(l+1))
00226 *exp(rr)/(cdcon1*cdcon2);
00227 psi1=-EULER;
00228 psi2=-EULER;
00229 for(k=1;k<=2*l+1;k++){
00230 psi2=psi2+1.0/(double)k;
00231 }
00232 cx=l+1+ceta;
00233 psi3=-EULER-(1.0/cx)+cx*(PI*PI/6.0);
00234 for(k=1;k<100000;k++){
00235 delp=-cx*cx/(double(k*k)*(cx+(double)k));
00236 psi3=psi3+delp;
00237
00238 if(fabs(delp)<1.0E-12) goto CONVERGE1;
00239 }
00240 printf("never escaped loop1 in cw2_small_r!\n");
00241 CONVERGE1:
00242 lterm=ci*PI+log(2.0*rr);
00243 fact1=cdcon2/dgamma(2*l+2);
00244 sum1=fact1*(psi1+psi2-psi3-lterm);
00245 for(k=1;k<=10000;k++){
00246 fact1=fact1*(-2.0*rr)*(double(l+k)+ceta)
00247 /(double(k)*double(2*l+1+k));
00248 psi1=psi1+1.0/double(k);
00249 psi2=psi2+1.0/double(2*l+1+k);
00250 psi3=psi3+1.0/(double(k-1)+cx);
00251 delsum1=fact1*(psi1+psi2-psi3-lterm);
00252 sum1=sum1+delsum1;
00253 if(abs(delsum1)<1.0E-15) goto CONVERGE2;
00254 }
00255 printf("never escaped loop2 in cw2_small_r!\n");
00256 CONVERGE2:
00257 fact2=dgamma(2.0*l+1)*cdcon1/pow(2.0*rr,2*l+1);
00258 sum2=fact2;
00259
00260
00261 for(k=1;k<=2*l;k++){
00262 fact2=fact2*(double(k-l-1)+ceta)*rr/(double(k)*double(2*l-k+1));
00263
00264 sum2=sum2+fact2;
00265 }
00266 sum1=factor*sum1;
00267 sum2=factor*sum2;
00268 answer=(sum1+sum2);
00269
00270
00271
00272
00273
00274 return answer;
00275 }
00276
00277
00278 double CoulWave::dgamma(int mm){
00279
00280
00281 double dg;
00282 int j;
00283 dg=1.0;
00284 if(mm<1) {
00285 for(j=1;j<=-mm+1;j++){
00286 dg=dg/(1.0+double(-j));
00287 }
00288 }
00289 if(mm>1){
00290 for(j=1;j<=mm-1;j++){
00291 dg=dg*((double)j);
00292 }
00293 }
00294 return dg;
00295 }
00296
00297
00298 void CoulWave::SphericalCW(int L,double x,double eta,double *FL,double *GL){
00299 double expF,expG;
00300 double *fc,*gc;
00301 fc=new double[L+1];
00302 gc=new double[L+1];
00303
00304
00305 int dummy=gsl_sf_coulomb_wave_FG_array(0,L,eta,x,fc,gc,&expF,&expG);
00306 *FL=fc[L]*exp(expF);
00307 *GL=gc[L]*exp(expG);
00308 delete [] fc;
00309 delete [] gc;
00310 }
00311
00312
00313 void CoulWave::SphericalCWprime(int L,double x,double eta,double *FL,double *GL,double *FLprime,double *GLprime){
00314 double expF,expG;
00315 double *fc,*gc,*fcp,*gcp;
00316 int k=0;
00317 fc=new double[k+1];
00318 gc=new double[k+1];
00319 fcp=new double[k+1];
00320 gcp=new double[k+1];
00321
00322 int dummy=gsl_sf_coulomb_wave_FGp_array(L,k,eta,x,fc,fcp,gc,gcp,&expF,&expG);
00323 *FL=fc[0]*exp(expF);
00324 *GL=gc[0]*exp(expG);
00325 *FLprime=fcp[0]*exp(expF);
00326 *GLprime=gcp[0]*exp(expG);
00327 delete [] fc;
00328 delete [] gc;
00329 delete [] fcp;
00330 delete [] gcp;
00331 }
00332
00333 #endif