00001 #ifndef __INCLUDE_CHCALC_CC__
00002 #define __INCLUDE_CHCALC_CC__
00003 #include "sf.h"
00004
00005 using namespace std;
00006
00007 int CCHCalc::INITIALIZED=0;
00008 int CCHCalc::LMAXFACT=56;
00009 double *CCHCalc::fact=NULL;
00010 double *CCHCalc::doublefact=NULL;
00011 double **CCHCalc::binomial=NULL;
00012 double *****CCHCalc::overlap=NULL;
00013
00014 CCHCalc::CCHCalc(){
00015 if(INITIALIZED==0){
00016 InitStaticData();
00017 }
00018 INITIALIZED+=1;
00019 };
00020
00021 CCHCalc::~CCHCalc(){
00022 INITIALIZED-=1;
00023 if(INITIALIZED==0){
00024 ClearStaticData();
00025 printf("CCHCalc static data cleared\n");
00026 }
00027 }
00028
00029 void CCHCalc::InitStaticData(){
00030 int lx,ly,lz,lymax,lzmax,L;
00031 int m;
00032 if(fact==NULL){
00033 fact=new double[LMAXFACT+1];
00034 fact[0]=fact[1]=1.0;
00035 for(m=2;m<=LMAXFACT;m++) fact[m]=fact[m-1]*double(m);
00036 }
00037 if(doublefact==NULL){
00038 doublefact=new double[2*LMAXFACT+2];
00039 doublefact[0]=doublefact[1]=1.0;
00040 for(m=2;m<=2*LMAXFACT+1;m++) doublefact[m]=doublefact[m-2]*double(m);
00041 }
00042
00043 if(binomial==NULL){
00044 binomial=new double *[LMAXFACT+1];
00045 for(L=0;L<=LMAXFACT;L++){
00046 binomial[L]=new double [L+1];
00047 binomial[L][0]=1.0;
00048 for(lx=1;lx<=L;lx++)
00049 binomial[L][lx]=binomial[L][lx-1]*double(L-lx+1)/double(lx);
00050 }
00051 }
00052
00053 if(overlap==NULL){
00054 overlap=new double ****[LMAXFACT+1];
00055 for(lx=0;lx<=LMAXFACT;lx++){
00056 overlap[lx]=new double ***[LMAXFACT-lx+1];
00057 for(ly=0;ly<=LMAXFACT-lx;ly++){
00058 for(lz=0;lz<=LMAXFACT-lx-ly;lz++){
00059 L=lx+ly+lz;
00060 }
00061 }
00062 lymax=lx;
00063 if(lymax+lx>LMAXFACT) lymax=LMAXFACT-lx;
00064 for(ly=0;ly<=lymax;ly++){
00065 overlap[lx][ly]=new double **[LMAXFACT-lx-ly+1];
00066 lzmax=ly;
00067 if(lx+ly+lzmax>LMAXFACT) lzmax=LMAXFACT-lx-ly;
00068 for(lz=0;lz<=lzmax;lz++){
00069 overlap[lx][ly][lz]=NULL;
00070
00071 }
00072 }
00073 }
00074 }
00075 }
00076
00077 void CCHCalc::ClearStaticData(){
00078 int lx,ly,lz,lymax,lzmax,mx,L;
00079 printf("Clearing static data used for charray calc.s. \nDon't do this unless you are finished with charray objects\n");
00080 delete [] fact;
00081 delete [] doublefact;
00082 for(L=0;L<=LMAXFACT;L++) delete [] binomial[L];
00083 delete [] binomial;
00084 for(lx=0;lx<=LMAXFACT;lx++){
00085 lymax=LMAXFACT-lx;
00086 if(lymax>lx) lymax=lx;
00087 for(ly=0;ly<=lymax;ly++){
00088 lzmax=LMAXFACT-lx-ly;
00089 if(lzmax>ly) lzmax=ly;
00090 for(lz=0;lz<=lzmax;lz++){
00091 if(overlap[lx][ly][lz]!=NULL){
00092 L=lx+ly+lz;
00093 for(mx=lx%2;mx<=L/2;mx++){
00094 delete [] overlap[lx][ly][lz][mx];
00095 }
00096 }
00097 delete [] overlap[lx][ly][lz];
00098 }
00099 delete [] overlap[lx][ly];
00100 }
00101 delete [] overlap[lx];
00102 }
00103 delete overlap;
00104 overlap=NULL;
00105 doublefact=NULL;
00106 fact=NULL;
00107 binomial=NULL;
00108 }
00109
00110 double CCHCalc::Factorial(int n){
00111 return fact[n];
00112 }
00113
00114 double CCHCalc::DoubleFactorial(int n){
00115 return doublefact[n];
00116 }
00117
00118 double CCHCalc::Binomial(int lx,int ly){
00119 return binomial[lx+ly][lx];
00120 }
00121
00122 double CCHCalc::Trinomial(int lx,int ly,int lz){
00123 int L;
00124 L=lx+ly+lz;
00125 if(lx<ly) iswitch(lx,ly);
00126 if(ly<lz) iswitch(ly,lz);
00127 if(lx<ly) iswitch(lx,ly);
00128 return binomial[L][lz]*binomial[lx+ly][lx];
00129 }
00130
00131 void CCHCalc::iswitch(int &i,int &j){
00132 int k;
00133 k=i;
00134 i=j;
00135 j=k;
00136 }
00137
00138 double CCHCalc::GetOverlap(int lx,int ly,int lz,
00139 int lxprime,int lyprime,int lzprime){
00140 int LMAX,L,Lprime,mx,my;
00141 L=lx+ly+lz;
00142 Lprime=lxprime+lyprime+lzprime;
00143 if(Lprime>L) LMAX=Lprime;
00144
00145 if(L!=Lprime){
00146 return 0.0;
00147 }
00148 else if(((lx-lxprime)%2)!=0){
00149 return 0.0;
00150 }
00151 else if(((ly-lyprime)%2)!=0){
00152 return 0.0;
00153 }
00154 else if(((lz-lzprime)%2)!=0){
00155 return 0.0;
00156 }
00157 else if(L<=LMAXFACT){
00158 if(ly>lx){
00159 iswitch(lx,ly);
00160 iswitch(lxprime,lyprime);
00161 }
00162 if(lz>ly){
00163 iswitch(ly,lz);
00164 iswitch(lyprime,lzprime);
00165 if(ly>lx){
00166 iswitch(lx,ly);
00167 iswitch(lxprime,lyprime);
00168 }
00169 }
00170 if(lx<ly || ly<lz) {
00171 printf("l out of order\n");
00172 exit(1);
00173 }
00174 if(overlap[lx][ly][lz]==NULL) overlapinit(lx,ly,lz);
00175 mx=lxprime/2;
00176 my=lyprime/2;
00177
00178
00179
00180
00181 return overlap[lx][ly][lz][mx][my];
00182 }
00183 else{
00184 return GetOverlap0(lx,ly,lz,lxprime,lyprime,lzprime);
00185 }
00186 }
00187
00188 void CCHCalc::overlapinit(int lx,int ly,int lz){
00189 int lxprime,lyprime,lzprime,L,mx,my;
00190 L=lx+ly+lz;
00191 if(overlap[lx][ly][lz]==NULL){
00192 overlap[lx][ly][lz]=new double *[1+L/2];
00193 for(mx=0;mx<=L/2;mx++){
00194 lxprime=lx%2+2*mx;
00195 overlap[lx][ly][lz][mx]=new double[1+(L-lxprime)/2];
00196 for(my=0;my<=(L-lxprime)/2;my++){
00197 lyprime=ly%2+2*my;
00198 lzprime=L-lxprime-lyprime;
00199
00200
00201 overlap[lx][ly][lz][mx][my]
00202 =GetOverlap0(lx,ly,lz,lxprime,lyprime,lzprime);
00203
00204
00205 }
00206 }
00207 }
00208 }
00209
00210
00211 double CCHCalc::GetMFromE(int lx,int ly,int lz,
00212 double ex,double ey,double ez){
00213 return pow(ex,lx)*pow(ey,ly)*pow(ez,lz);
00214 }
00215
00216 double CCHCalc::GetMFromThetaPhi(int lx,int ly,int lz,
00217 double theta,double phi){
00218 double stheta,ex,ey,ez;
00219 stheta=sin(theta);
00220 ex=stheta*cos(phi);
00221 ey=stheta*sin(phi);
00222 ez=cos(theta);
00223 return GetMFromE(lx,ly,lz,ex,ey,ez);
00224 }
00225
00226 double CCHCalc::GetAFromE(int lx,int ly,int lz,
00227 double ex,double ey,double ez){
00228 int L,m,mx,my,mz;
00229 double answer,factor,fx,fy,fz,fl;
00230 L=lx+ly+lz;
00231 if(L==0) return 1.0;
00232 else{
00233 answer=0.0;
00234 fl=fact[lx]*fact[ly]*fact[lz]/doublefact[2*L-1];
00235 for(mx=0;mx<=lx/2;mx++){
00236 fx=pow(-0.5,mx)*pow(ex,lx-2*mx)/(fact[mx]*fact[lx-2*mx]);
00237 for(my=0;my<=ly/2;my++){
00238 fy=pow(-0.5,my)*pow(ey,ly-2*my)/(fact[my]*fact[ly-2*my]);
00239 for(mz=0;mz<=lz/2;mz++){
00240 fz=pow(-0.5,mz)*pow(ez,lz-2*mz)/(fact[mz]*fact[lz-2*mz]);
00241 m=mx+my+mz;
00242 factor=fl*fx*fy*fz;
00243 if(L>m) factor*=doublefact[2*L-2*m-1];
00244 answer+=factor;
00245 }
00246 }
00247 }
00248 return answer;
00249 }
00250 }
00251
00252 double CCHCalc::GetAFromThetaPhi(int lx,int ly,int lz,double theta,double phi){
00253 double stheta,ex,ey,ez;
00254 stheta=sin(theta);
00255 ex=stheta*cos(phi);
00256 ey=stheta*sin(phi);
00257 ez=cos(theta);
00258 return GetAFromE(lx,ly,lz,ex,ey,ez);
00259 }
00260
00261
00262 double CCHCalc::GetOverlap0(int lx,int ly,int lz,
00263 int lxprime,int lyprime,int lzprime){
00264 const double PI=4.0*atan(1.0);
00265 int LMAX,L,Lprime;
00266 double prefactor,factor,sum;
00267 int mxmin,mymin,mzmin,m,mx,my,mz,kx,ky,kz;
00268 L=lx+ly+lz;
00269 Lprime=lxprime+lyprime+lzprime;
00270 LMAX=L;
00271 if(Lprime>L) LMAX=Lprime;
00272
00273 if(L!=Lprime){
00274 return 0.0;
00275 }
00276 else if(((lx-lxprime)%2)!=0){
00277 return 0.0;
00278 }
00279 else if(((ly-lyprime)%2)!=0){
00280 return 0.0;
00281 }
00282 else if(((lz-lzprime)%2)!=0){
00283 return 0.0;
00284 }
00285 else{
00286 prefactor=4.0*PI*fact[lx]*fact[ly]*fact[lz]*fact[lxprime]*fact[lyprime]
00287 *fact[lzprime]/((2.0*double(L)+1.0));
00288 if(L>0)
00289 prefactor=prefactor/pow(doublefact[2*L-1],2);
00290 sum=0.0;
00291 mxmin=mymin=mzmin=0;
00292 if(lx>lxprime) mxmin=(lx-lxprime)/2;
00293 if(ly>lyprime) mymin=(ly-lyprime)/2;
00294 if(lz>lzprime) mzmin=(lz-lzprime)/2;
00295 for(mx=mxmin;mx<=lx/2;mx++){
00296 for(my=mymin;my<=ly/2;my++){
00297 for(mz=mzmin;mz<=lz/2;mz++){
00298 m=mx+my+mz;
00299 if(2*L-2*m-1>0) factor=doublefact[2*L-2*m-1]*fact[m];
00300 else factor=1.0;
00301 if(m>0) factor*=pow(-0.5,m);
00302 kx=mx+(lxprime-lx)/2;
00303 ky=my+(lyprime-ly)/2;
00304 kz=mz+(lzprime-lz)/2;
00305 factor=factor/double(fact[mx]*fact[kx]*fact[lx-2*mx]);
00306 factor=factor/double(fact[my]*fact[ky]*fact[ly-2*my]);
00307 factor=factor/double(fact[mz]*fact[kz]*fact[lz-2*mz]);
00308 sum+=factor;
00309 }
00310 }
00311 }
00312 return sum*prefactor;
00313 }
00314 }
00315
00316 #endif