00001 #ifndef __INCLUDE_CARTHARMCALC_CC
00002 #define __INCLUDE_CARTHARMCALC_CC
00003 #include "arrays.h"
00004 using namespace std;
00005
00006 void ArrayCalc::CalcAExpArrayFromMArray(CCHArray *M,int irm,CCHArray *A,int ira){
00007 int dlx=1,dly=1,dlz=1;
00008 if(A->GetXSYM()) dlx=2;
00009 if(A->GetYSYM()) dly=2;
00010 if(A->GetZSYM()) dlz=2;
00011
00012 int LMAX=A->GetLMAX();
00013 if(M->GetLMAX()!=LMAX){
00014 printf("LMAX from M does not match LMAX from A\n");
00015 exit(1);
00016 }
00017 int L,lx,ly,lz;
00018 A->SetElement(0,0,0,ira,M->GetElement(0,0,0,ira));
00019
00020 for(lx=0;lx<=1;lx+=dlx){
00021 for(ly=0;ly<=LMAX-lx;ly+=dly){
00022 for(lz=0;lz<=LMAX-lx-ly;lz+=dlz){
00023 L=lx+ly+lz;
00024 if(L>0) A->SetElement(lx,ly,lz,ira,
00025 M->GetAExpElementFromMArray(lx,ly,lz,irm));
00026 }
00027 }
00028 }
00029 A->FillRemainderX(ira);
00030 }
00031
00032 void ArrayCalc::CalcMArrayFromAExpArray(CCHArray *A,int ira,CCHArray *M,int irm){
00033 int LMAX=A->GetLMAX();
00034 if(M->GetLMAX()!=LMAX){
00035 printf("LMAX from M does not match LMAX from A\n");
00036 exit(1);
00037 }
00038 int lx,ly,lz,L;
00039 int dlx=1,dly=1,dlz=1;
00040 if(M->GetXSYM()) dlx=2;
00041 if(M->GetYSYM()) dly=2;
00042 if(M->GetZSYM()) dlz=2;
00043
00044 M->SetElement(0,0,0,irm,A->GetElement(0,0,0,ira));
00045 for(lx=0;lx<=LMAX;lx+=dlx){
00046 for(ly=0;ly<=LMAX-lx;ly+=dly){
00047 for(lz=0;lz<=LMAX-lx-ly;lz+=dlz){
00048 L=lx+ly+lz;
00049 if(L>0) M->SetElement(lx,ly,lz,irm,
00050 A->GetMElementFromAExpArray(lx,ly,lz,ira));
00051 }
00052 }
00053 }
00054 }
00055
00056 void ArrayCalc::AddArrays(CCHArray *A,int ira,CCHArray *B,int irb,CCHArray *C,int irc){
00057 int LMAX,lx,ly,lz;
00058 int dlx=1,dly=1,dlz=1;
00059 if(C->GetXSYM()) dlx=2;
00060 if(C->GetYSYM()) dly=2;
00061 if(C->GetZSYM()) dlz=2;
00062 LMAX=A->GetLMAX();
00063 if(LMAX>B->GetLMAX()) LMAX=B->GetLMAX();
00064 for(lx=0;lx<=LMAX;lx+=dlx){
00065 for(ly=0;ly<=LMAX-lx;ly+=dly){
00066 for(lz=0;lz<=LMAX-lx-ly;lz+=dlz){
00067 C->SetElement(lx,ly,lz,irc,A->GetElement(lx,ly,lz,ira)
00068 +B->GetElement(lx,ly,lz,irb));
00069 }
00070 }
00071 }
00072 }
00073
00074 void ArrayCalc::SubtractArrays(CCHArray *A,int ira,CCHArray *B,int irb,CCHArray *C,int irc){
00075 int LMAX,lx,ly,lz;
00076 int dlx=1,dly=1,dlz=1;
00077 if(C->GetXSYM()) dlx=2;
00078 if(C->GetYSYM()) dly=2;
00079 if(C->GetZSYM()) dlz=2;
00080 LMAX=A->GetLMAX();
00081 if(LMAX>B->GetLMAX()) LMAX=B->GetLMAX();
00082 for(lx=0;lx<=LMAX;lx+=dlx){
00083 for(ly=0;ly<=LMAX-lx;ly+=dly){
00084 for(lz=0;lz<=LMAX-lx-ly;lz+=dlz){
00085 C->SetElement(lx,ly,lz,irc,A->GetElement(lx,ly,lz,ira)
00086 -B->GetElement(lx,ly,lz,irb));
00087 }
00088 }
00089 }
00090 }
00091
00092 void ArrayCalc::AddArrays(CCHArray *A,CCHArray *B,CCHArray *C){
00093 int ir;
00094 if((!CompareArrayParameters(A,B)) || (!CompareArrayParameters(B,C))){
00095 printf("fatal error, parameters mismatch in ArrayCalc::AddArrays\n");
00096 exit(1);
00097 }
00098 for(ir=0;ir<A->GetNRADIAL();ir++) AddArrays(A,ir,B,ir,C,ir);
00099 }
00100
00101 void ArrayCalc::SubtractArrays(CCHArray *A,CCHArray *B,CCHArray *C){
00102 int ir;
00103 if((!CompareArrayParameters(A,B)) || (!CompareArrayParameters(B,C))){
00104 printf("fatal error, parameters mismatch in ArrayCalc::AddArrays\n");
00105 exit(1);
00106 }
00107 for(ir=0;ir<A->GetNRADIAL();ir++) SubtractArrays(A,ir,B,ir,C,ir);
00108 }
00109
00110 void ArrayCalc::DivideArrays(CCHArray *A,CCHArray *B,CCHArray *C){
00111 int ir;
00112 if((A->GetNRADIAL()!=B->GetNRADIAL()) || (B->GetNRADIAL()!=C->GetNRADIAL())){
00113 printf("FATAL: NRADIAL mismatch in ArrayCalc::DivideArrays\n");
00114 exit(1);
00115 }
00116 for(ir=0;ir<A->GetNRADIAL();ir++) DivideArrays(A,ir,B,ir,C,ir);
00117 }
00118
00119 void ArrayCalc::MultiplyArrays(CCHArray *A,CCHArray *B,CCHArray *C){
00120 int ir;
00121 if((!CompareArrayParameters(A,B)) || (!CompareArrayParameters(B,C))){
00122 printf("fatal error, parameters mismatch in ArrayCalc::MultiplyArrays\n");
00123 exit(1);
00124 }
00125 for(ir=0;ir<A->GetNRADIAL();ir++) MultiplyArrays(A,ir,B,ir,C,ir);
00126 }
00127
00128 void ArrayCalc::CopyArray(CCHArray *A,CCHArray *B){
00129 int ir;
00130 if(!CompareArrayParameters(A,B)){
00131 printf("fatal error, parameters mismatch in ArrayCalc::CopyArray\n");
00132 exit(1);
00133 }
00134 for(ir=0;ir<A->GetNRADIAL();ir++) CopyArray(A,ir,B,ir);
00135 }
00136
00137 void ArrayCalc::CalcMArrayFromAExpArray(CCHArray *A,CCHArray *M){
00138 int ir;
00139 if(!CompareArrayParameters(A,M)){
00140 printf("fatal error, parameters mismatch in ArrayCalc::CalcMArrayFromAExpArray\n");
00141 exit(1);
00142 }
00143 for(ir=0;ir<A->GetNRADIAL();ir++) CalcMArrayFromAExpArray(A,ir,M,ir);
00144 }
00145
00146 void ArrayCalc::CalcAExpArrayFromMArray(CCHArray *M,CCHArray *A){
00147 int ir;
00148 if(!CompareArrayParameters(A,M)){
00149 printf("fatal error, parameters mismatch in ArrayCalc::CalcAExpArrayFromMArray\n");
00150 exit(1);
00151 }
00152 for(ir=0;ir<A->GetNRADIAL();ir++) CalcAExpArrayFromMArray(M,ir,A,ir);
00153 }
00154
00155 void ArrayCalc::CalcAExpArrayFromXExpArray(CCHArray *X,CCHArray *A){
00156 int ir;
00157 if(!CompareArrayParameters(A,X)){
00158 printf("fatal error, parameters mismatch in ArrayCalc::CalcAExpArrayFromXExpArray\n");
00159 exit(1);
00160 }
00161 for(ir=0;ir<A->GetNRADIAL();ir++) CalcAExpArrayFromXExpArray(X,ir,A,ir);
00162 }
00163
00164 void ArrayCalc::CalcXExpArrayFromAExpArray(CCHArray *A,CCHArray *X){
00165 int ir;
00166 if(!CompareArrayParameters(A,X)){
00167 printf("fatal error, parameters mismatch in ArrayCalc::CalcXExpArrayFromAExpArray\n");
00168 exit(1);
00169 }
00170 for(ir=0;ir<A->GetNRADIAL();ir++) CalcXExpArrayFromAExpArray(X,ir,A,ir);
00171 }
00172
00173 void ArrayCalc::Detrace(CCHArray *M,CCHArray *A){
00174 int ir;
00175 if(!CompareArrayParameters(M,A)){
00176 printf("fatal error, parameters mismatch in ArrayCalc::Detrace\n");
00177 exit(1);
00178 }
00179 for(ir=0;ir<A->GetNRADIAL();ir++) Detrace(M,ir,A,ir);
00180 }
00181
00182 void ArrayCalc::CopyArray(CCHArray *A,int ira,CCHArray *B,int irb){
00183 int lx,ly,lz,LMAX,LMAXA,L;
00184 int dlx=1,dly=1,dlz=1;
00185 if(A->GetXSYM()) dlx=2;
00186 if(A->GetYSYM()) dly=2;
00187 if(A->GetZSYM()) dlz=2;
00188 LMAX=B->GetLMAX();
00189 LMAXA=A->GetLMAX();
00190 for(lx=0;lx<=LMAX;lx+=dlx){
00191 for(ly=0;ly<=LMAX-lx;ly+=dly){
00192 for(lz=0;lz<=LMAX-lx-ly;lz+=dlz){
00193 L=lx+ly+lz;
00194 if(L<=LMAXA)
00195 B->SetElement(lx,ly,lz,irb,A->GetElement(lx,ly,lz,ira));
00196 else
00197 B->SetElement(lx,ly,lz,irb,0);
00198 }
00199 }
00200 }
00201 }
00202
00203 void ArrayCalc::CalcYlmExpArrayFromAExpArray(CCHArray *A,int ira,CYlmArray *YlmArray,int irlm){
00204 CCHCalc chcalc;
00205 const double PI=4.0*atan(1.0);
00206 int LMAX,L,lx,ly,lz,M;
00207 double flm;
00208 complex<double> factor,ci(0.0,1.0);
00209
00210 int dlx=1,dly=1,dlm=1,delL=1,Mstart;
00211 if(A->GetXSYM()) dlx=2;
00212 if(A->GetZSYM()) dlm=2;
00213 if(A->GetXSYM() && A->GetYSYM() && A->GetZSYM()) delL=2;
00214 if(A->GetYSYM()) dly=2;
00215
00216 LMAX=YlmArray->GetLMAX();
00217
00218 YlmArray->SetElement(0,0,irlm,A->GetElement(0,0,0,ira));
00219 for(L=delL;L<=LMAX;L+=delL){
00220 Mstart=0;
00221 if(A->GetZSYM()) Mstart=L%2;
00222 for(M=Mstart;M<=L;M+=dlm){
00223 YlmArray->SetElement(L,M,irlm,0.0);
00224 lz=L-M;
00225 if(dlm==1 || lz%2==0){
00226 flm=pow(-1.0,M)/sqrt((2.0*L+1)*4*PI*chcalc.Factorial(L+M)*chcalc.Factorial(L-M));
00227 flm=flm*chcalc.Factorial(M)*sqrt(4.0*PI)*chcalc.Factorial(L);
00228
00229 for(lx=0;lx<=M;lx+=dlx){
00230 ly=M-lx;
00231 if(dly==1 || ly%2==0){
00232 factor=flm*pow(ci,M-lx)/(chcalc.Factorial(lx)*chcalc.Factorial(M-lx));
00233 YlmArray->IncrementElement(L,M,irlm,
00234 factor*A->GetElement(lx,ly,lz,ira));
00235
00236 }
00237 }
00238 }
00239 }
00240 }
00241 }
00242
00243 void ArrayCalc::CalcAExpArrayFromYlmExpArray(CYlmArray *YlmArray,int irlm,CCHArray *A,int ira){
00244 CCHCalc chcalc;
00245 const double PI=4.0*atan(1.0);
00246 int LMAX,L,lx,ly,lz,M,k;
00247 complex<double> factor,ci(0.0,1.0);
00248 int dlx=1,dly=1,dlz=1;
00249 if(A->GetXSYM()) dlx=2;
00250 if(A->GetYSYM()) dly=2;
00251 if(A->GetZSYM()) dlz=2;
00252
00253 LMAX=A->GetLMAX();
00254
00255 A->SetElement(0,0,0,ira,real(YlmArray->GetElement(0,0,irlm)));
00256 for(lx=0;lx<=1;lx+=dlx){
00257 for(ly=0;ly<=LMAX-lx;ly+=dly){
00258 for(lz=0;lz<=LMAX-lx-ly;lz+=dlz){
00259 L=lx+ly+lz;
00260 if(L>0){
00261 A->SetElement(lx,ly,lz,ira,0);
00262 for(M=0;M<=L;M++){
00263 factor=0.0;
00264 for(k=0;k<=M;k++){
00265 factor+=pow(-ci,M-k)
00266 *(chcalc.Factorial(M)/(chcalc.Factorial(k)*chcalc.Factorial(M-k)))*chcalc.GetOverlap(lx,ly,lz,k,M-k,L-M);
00267 }
00268 factor*=pow(-1.0,M)*double(chcalc.DoubleFactorial(2*L-1));
00269 factor*=sqrt(double(2*L+1)/(4*PI*chcalc.Factorial(L+M)*chcalc.Factorial(L-M)));
00270 factor*=chcalc.DoubleFactorial(2*L+1)/(chcalc.Factorial(L)*sqrt(4*PI));
00271
00272 if(M==0)
00273 A->IncrementElement(lx,ly,lz,ira,
00274 real(factor
00275 *YlmArray->GetElement(L,M,irlm)));
00276 else
00277 A->IncrementElement(lx,ly,lz,ira,
00278 real(2.0*factor
00279 *YlmArray->GetElement(L,M,irlm)));
00280
00281 }
00282 }
00283 }
00284 }
00285 }
00286 A->FillRemainderX(ira);
00287
00288 }
00289
00290
00291
00292
00293
00294 void ArrayCalc::Detrace(CCHArray *M,int irm,CCHArray *A,int ira){
00295
00296 CCHCalc chcalc;
00297 int dlx=1,dly=1,dlz=1;
00298 double factor;
00299 const double PI=4.0*atan(1.0);
00300
00301
00302 if(M->GetXSYM()) dlx=2;
00303 if(M->GetYSYM()) dly=2;
00304 if(M->GetZSYM()) dlz=2;
00305
00306 A->ZeroArray(ira);
00307 int L,LMAX,lx,ly,lz,m,mx,my,mz,lxprime,lyprime,lzprime;
00308 int LMAXM=M->GetLMAX();
00309 int LMAXA=A->GetLMAX();
00310 LMAX=LMAXM;
00311 if(LMAXA>LMAX) LMAX=LMAXA;
00312
00313 CCHArray *Atilde;
00314 Atilde=new CCHArray(LMAXA,1,1.0,M->GetXSYM(),
00315 M->GetYSYM(),M->GetZSYM());
00316 for(lx=0;lx<=LMAXA;lx+=dlx){
00317 for(ly=0;ly<=LMAXA-lx;ly+=dly){
00318 for(lz=0;lz<=LMAXA-lx-ly;lz+=dlz){
00319 L=lx+ly+lz;
00320 for(mx=0;mx<=(LMAXM-L)/2;mx++){
00321 for(my=0;my<=(LMAXM-L-2*mx)/2;my++){
00322 for(mz=0;mz<=(LMAXM-L-2*mx-2*my)/2;mz++){
00323 m=mx+my+mz;
00324 if(L+2*m>LMAXM){
00325 printf("L+2m is tooooo big\n");
00326 exit(1);
00327 }
00328 factor=pow(0.5,m);
00329 factor*=chcalc.Factorial(L+2*m)*chcalc.DoubleFactorial(2*L+1)
00330 /(chcalc.Factorial(L)*chcalc.Factorial(mx)*chcalc.Factorial(my)*chcalc.Factorial(mz)*chcalc.DoubleFactorial(2*L+2*m+1));
00331 Atilde->IncrementElement(lx,ly,lz,0,
00332 factor*M->GetElement(lx+2*mx,ly+2*my,
00333 lz+2*mz,irm));
00334 }
00335 }
00336 }
00337 }
00338 }
00339 }
00340 for(lx=0;lx<=1;lx+=dlx){
00341 for(ly=0;ly<=LMAXA-lx;ly+=dly){
00342 for(lz=0;lz<=LMAXA-lx-ly;lz+=dlz){
00343 L=lx+ly+lz;
00344 for(lxprime=lx;lxprime<=L;lxprime+=2){
00345 for(lyprime=ly%2;lyprime<=L-lxprime;lyprime+=2){
00346 lzprime=L-lxprime-lyprime;
00347 factor=chcalc.DoubleFactorial(2*L+1)/(chcalc.Factorial(L)*4.0*PI);
00348 factor*=chcalc.GetOverlap(lx,ly,lz,lxprime,lyprime,lzprime)
00349 *Atilde->GetElement(lxprime,lyprime,lzprime,0);
00350 factor*=chcalc.Factorial(L)/(chcalc.Factorial(lxprime)*chcalc.Factorial(lyprime)*chcalc.Factorial(lzprime));
00351 A->IncrementElement(lx,ly,lz,ira,factor);
00352 }
00353 }
00354 }
00355 }
00356 }
00357 A->FillRemainderX(ira);
00358 delete Atilde;
00359 }
00360
00361 void ArrayCalc::MultiplyArrays(CCHArray *A,int ira,CCHArray *B,int irb,CCHArray *C,int irc){
00362 int LMAXA=A->GetLMAX();
00363 int LMAXB=B->GetLMAX();
00364 int LMAXC=C->GetLMAX();
00365 bool XSYMd=0,YSYMd=0,ZSYMd=0;
00366
00367 if(A->GetXSYM() && B->GetXSYM()) XSYMd=1;
00368 if(A->GetYSYM() && B->GetYSYM()) YSYMd=1;
00369 if(A->GetZSYM() && B->GetZSYM()) ZSYMd=1;
00370
00371 CCHArray *D;
00372 D=new CCHArray(LMAXC,1,1.0,XSYMd,YSYMd,ZSYMd);
00373 MultiplyArrays_Partial(LMAXA,A,ira,LMAXB,B,irb,LMAXC,D,0);
00374 Detrace(D,0,C,irc);
00375 delete D;
00376
00377 }
00378
00379 void ArrayCalc::MultiplyArrays_Partial(int LMAXA,CCHArray *A,int ira,int LMAXB,CCHArray *B,int irb,int LMAXC,CCHArray *C,int irc){
00380 CCHCalc chcalc;
00381 int dlxa=1,dlya=1,dlza=1;
00382 if(A->GetXSYM()) dlxa=2;
00383 if(A->GetYSYM()) dlya=2;
00384 if(A->GetZSYM()) dlza=2;
00385 int dlxb=1,dlyb=1,dlzb=1;
00386 if(B->GetXSYM()) dlxb=2;
00387 if(B->GetYSYM()) dlyb=2;
00388 if(B->GetZSYM()) dlzb=2;
00389
00390 if(LMAXC>LMAXA+LMAXB) LMAXC=LMAXA+LMAXB;
00391 if(LMAXC>C->GetLMAX()) LMAXC=C->GetLMAX();
00392 if(LMAXA>LMAXC) LMAXA=LMAXC;
00393 if(LMAXB>LMAXC) LMAXB=LMAXC;
00394
00395 int La,Lb,lxa,lya,lza,lxb,lyb,lzb,lxc,lyc,lzc,lmaxbprime;
00396 double gammaa,gammab,gammac,delC;
00397
00398 C->ZeroArray(irc);
00399
00400 for(lxa=0;lxa<=LMAXA;lxa+=dlxa){
00401 for(lya=0;lya<=LMAXA-lxa;lya+=dlya){
00402 for(lza=0;lza<=LMAXA-lxa-lya;lza+=dlza){
00403 La=lxa+lya+lza;
00404 gammaa=chcalc.Trinomial(lxa,lya,lza);
00405 lmaxbprime=LMAXC-La;
00406 if(lmaxbprime>LMAXB) lmaxbprime=LMAXB;
00407 for(lxb=0;lxb<=lmaxbprime;lxb+=dlxb){
00408 for(lyb=0;lyb<=lmaxbprime-lxb;lyb+=dlyb){
00409 for(lzb=0;lzb<=lmaxbprime-lxb-lyb;lzb+=dlzb){
00410 Lb=lxb+lyb+lzb;
00411 if(La+Lb<=LMAXC){
00412 lxc=lxa+lxb;
00413 lyc=lya+lyb;
00414 lzc=lza+lzb;
00415 gammab=chcalc.Trinomial(lxb,lyb,lzb);
00416 gammac=chcalc.Trinomial(lxc,lyc,lzc);
00417 delC=gammaa*gammab*A->GetElement(lxa,lya,lza,ira)
00418 *B->GetElement(lxb,lyb,lzb,irb)/gammac;
00419 C->IncrementElement(lxc,lyc,lzc,irc,delC);
00420 }
00421 }
00422 }
00423 }
00424 }
00425 }
00426 }
00427 }
00428
00429 void ArrayCalc::DivideArrays(CCHArray *A,int ira,CCHArray *B,int irb,CCHArray *C,int irc){
00430 if( ((!A->GetXSYM() || !B->GetXSYM()) && C->GetXSYM())
00431 || ((!A->GetYSYM() || !B->GetYSYM()) && C->GetYSYM())
00432 || ((!A->GetZSYM() || !B->GetZSYM()) && C->GetZSYM())){
00433 printf("FATAL: Symmetry mismatch in ArrayCalc::DivdeArrays\n");
00434 exit(1);
00435 }
00436 CCHCalc chcalc;
00437 CCHArray *D;
00438 int LMAXA=A->GetLMAX();
00439 int LMAXB=B->GetLMAX();
00440 int LMAXD=55;
00441 bool XSYMd=0,YSYMd=0,ZSYMd=0;
00442 if(A->GetXSYM() && B->GetXSYM()) XSYMd=1;
00443 if(A->GetYSYM() && B->GetYSYM()) YSYMd=1;
00444 if(A->GetZSYM() && B->GetZSYM()) ZSYMd=1;
00445 D=new CCHArray(LMAXD,1,1.0,XSYMd,YSYMd,ZSYMd);
00446 int Lb,Ld,lxb,lyb,lzb,lxd,lyd,lzd,m,mx,my,mz;
00447 double gammad,delD,delDsumtest=1.0,olddelDsumtest=1.0,delDsum;
00448 double qthresh,Asum=0.0,B0=B->GetElement(0,0,0,irb);
00449 bool qtest=0;
00450 const double EPSILON=1.0E-6;
00451 int dlxa=1,dlya=1,dlza=1;
00452 if(A->GetXSYM()) dlxa=2;
00453 if(A->GetYSYM()) dlya=2;
00454 if(A->GetZSYM()) dlza=2;
00455 int dlxb=1,dlyb=1,dlzb=1;
00456 if(B->GetXSYM()) dlxb=2;
00457 if(B->GetYSYM()) dlyb=2;
00458 if(B->GetZSYM()) dlzb=2;
00459 int dlxd=1,dlyd=1,dlzd=1;
00460 if(A->GetXSYM() && B->GetXSYM()) dlxd=2;
00461 if(A->GetYSYM() && B->GetYSYM()) dlyd=2;
00462 if(A->GetZSYM() && B->GetZSYM()) dlzd=2;
00463 int dLd=1;
00464 if(A->GetXSYM() && A->GetYSYM() && A->GetZSYM()
00465 && B->GetXSYM() && B->GetYSYM() && B->GetZSYM())
00466 dLd=2;
00467
00468 Ld=0;
00469 do{
00470 delDsumtest=0.0;
00471 for(lxd=0;lxd<=Ld;lxd+=dlxd){
00472 for(lyd=0;lyd<=Ld-lxd;lyd+=dlyd){
00473 lzd=Ld-lxd-lyd;
00474 if(lzd%dlzd==0){
00475 gammad=chcalc.Trinomial(lxd,lyd,lzd);
00476 if(Ld<=LMAXA && lxd%dlxa==0 && lyd%dlya==0 && lzd%dlza==0){
00477 delD=A->GetElement(lxd,lyd,lzd,ira)/B0;
00478 Asum+=fabs(A->GetElement(lxd,lyd,lzd,ira));
00479 }
00480 else delD=0.0;
00481 D->SetElement(lxd,lyd,lzd,0,delD);
00482 delDsum=0.0;
00483 for(m=0;m<Ld;m+=dLd){
00484 for(mx=0;mx<=m;mx+=dlxd){
00485 for(my=0;my<=m-mx;my+=dlyd){
00486 mz=m-mx-my;
00487 if(mz%dlzd==0){
00488 lxb=lxd-mx;
00489 lyb=lyd-my;
00490 lzb=lzd-mz;
00491 Lb=lxb+lyb+lzb;
00492 if(Lb<=LMAXB && lxb>=0 && lyb>=0 && lzb>=0
00493 && lxb%dlxb==0 && lyb%dlyb==0 && lzb%dlzb==0){
00494 delD=-B->GetElement(lxb,lyb,lzb,irb)
00495 *D->GetElement(mx,my,mz,0)
00496 *(chcalc.Trinomial(lxb,lyb,lzb)*chcalc.Trinomial(mx,my,mz))
00497 /(gammad*B0);
00498 delDsum+=delD;
00499 }
00500 }
00501 }
00502 }
00503 }
00504 D->IncrementElement(lxd,lyd,lzd,0,delDsum);
00505 delDsumtest+=fabs(delDsum);
00506 }
00507 }
00508 }
00509 qtest=0;
00510 qthresh=EPSILON*Asum/B0;
00511 if(olddelDsumtest<qthresh && delDsumtest<qthresh) qtest=1;
00512 olddelDsumtest=delDsumtest;
00513 Ld+=dLd;
00514
00515 } while((qtest==0 || Ld<=LMAXA) && Ld<=LMAXD);
00516 printf("INFO: Sum in DivideAExpArrays satisfied convergence criteria at L=%d\n",
00517 Ld-1);
00518 D->SetLMAX(Ld-1);
00519
00520
00521 Detrace(D,0,C,irc);
00522 delete D;
00523 }
00524
00525 void ArrayCalc::CalcAExpArrayFromXExpArray(CCHArray *X,int irx,CCHArray *A,int ira){
00526
00527 double snorm,biggy,btest;
00528 CCHArray *bb,*C,*AA,*oldC;
00529 bool XSYM,YSYM,ZSYM;
00530 int n,LMAX,XLMAX,GNMAX;
00531 XSYM=YSYM=ZSYM=0;
00532 if(X->GetXSYM()) XSYM=1;
00533 if(X->GetYSYM()) YSYM=1;
00534 if(X->GetZSYM()) ZSYM=1;
00535
00536 GNMAX=48;
00537 XLMAX=X->GetLMAX();
00538 LMAX=A->GetLMAX();
00539 if(LMAX<XLMAX) LMAX=XLMAX;
00540
00541 C=new CCHArray(LMAX,1,1.0,XSYM,YSYM,ZSYM);
00542 AA=new CCHArray(LMAX,1,1.0,XSYM,YSYM,ZSYM);
00543 oldC=new CCHArray(LMAX,1,1.0,XSYM,YSYM,ZSYM);
00544 bb=new CCHArray(XLMAX,1,1.0,XSYM,YSYM,ZSYM);
00545 CopyArray(X,irx,bb,0);
00546
00547 snorm=exp(bb->GetElement(0,0,0,0));
00548 bb->SetElement(0,0,0,0,0.0);
00549
00550 AA->ZeroArray(0);
00551 AA->SetElement(0,0,0,0,1);
00552
00553 oldC->ZeroArray(0);
00554 oldC->SetElement(0,0,0,0,1.0);
00555 n=1;
00556 biggy=1.0;
00557 while(n<GNMAX && biggy>1.0E-8){
00558 if(n%6==0) biggy=0.0;
00559 MultiplyArrays_Partial(XLMAX,bb,0,XLMAX*(n-1),oldC,0,XLMAX*n,C,0);
00560 C->ScaleArray(1.0/double(n));
00561 btest=fabs(C->GetBiggest(0));
00562 if(btest>biggy) biggy=btest;
00563 AddArrays(C,0,AA,0,AA,0);
00564 CopyArray(C,0,oldC,0);
00565 n+=1;
00566 }
00567
00568
00569 Detrace(AA,0,A,ira);
00570 A->ScaleArray(snorm,ira);
00571
00572 delete bb;
00573 delete C;
00574 delete oldC;
00575 delete AA;
00576 }
00577
00578 void ArrayCalc::CalcXExpArrayFromAExpArray(CCHArray *A,int ira,CCHArray *X,int irx){
00579
00580 double snorm,biggy,btest;
00581 CCHArray *bb,*C,*XX,*oldC;
00582 bool XSYM,YSYM,ZSYM;
00583 int n,LMAX,ALMAX,GNMAX;
00584 XSYM=YSYM=ZSYM=0;
00585 if(A->GetXSYM()) XSYM=1;
00586 if(A->GetYSYM()) YSYM=1;
00587 if(A->GetZSYM()) ZSYM=1;
00588
00589 GNMAX=50;
00590 ALMAX=A->GetLMAX();
00591 LMAX=X->GetLMAX();
00592 if(LMAX<ALMAX) LMAX=ALMAX;
00593
00594 C=new CCHArray(LMAX,1,1.0,XSYM,YSYM,ZSYM);
00595 XX=new CCHArray(LMAX,1,1.0,XSYM,YSYM,ZSYM);
00596 oldC=new CCHArray(LMAX,1,1.0,XSYM,YSYM,ZSYM);
00597 bb=new CCHArray(LMAX,1,1.0,XSYM,YSYM,ZSYM);
00598 CopyArray(A,ira,bb,0);
00599
00600 snorm=bb->GetElement(0,0,0,0);
00601 bb->ScaleArray(1.0/snorm,0);
00602 bb->SetElement(0,0,0,0,0);
00603
00604 XX->ZeroArray(0);
00605 XX->SetElement(0,0,0,0,log(snorm));
00606
00607 oldC->ZeroArray(0);
00608 oldC->SetElement(0,0,0,0,1.0);
00609 n=1;
00610 biggy=1.0;
00611 while(n<GNMAX && biggy>1.0E-8){
00612 if(n%6==0) biggy=0.0;
00613
00614
00615 MultiplyArrays_Partial(LMAX,bb,0,LMAX*(n-1),oldC,0,LMAX*n,C,0);
00616 if(n>1) C->ScaleArray(-double(n-1)/double(n),0);
00617 btest=fabs(C->GetBiggest(0));
00618 if(btest>biggy) biggy=btest;
00619 AddArrays(C,0,XX,0,XX,0);
00620 CopyArray(C,0,oldC,0);
00621 n+=1;
00622 }
00623
00624
00625 Detrace(XX,0,X,irx);
00626
00627 delete bb;
00628 delete C;
00629 delete oldC;
00630 delete XX;
00631 }
00632
00633 void ArrayCalc::CalcAExpArrayFrom3DArray(C3DArray *threed,CCHArray *A){
00634 double x,y,z,r,cthetamin,phimin,phimax,delx,dely,delz,ex,ey,ez;
00635 double ctheta,stheta,phi,interpolate;
00636 const double PI=4.0*atan(1.0);
00637 int ictheta,iphi,nctheta=60,nphi=60,ir;
00638 bool XSYM,YSYM,ZSYM;
00639 CompareArrayParameters(threed,A);
00640 XSYM=A->GetXSYM();
00641 YSYM=A->GetYSYM();
00642 ZSYM=A->GetZSYM();
00643 if(ZSYM) cthetamin=0.0;
00644 else cthetamin=-1.0;
00645 if(XSYM && ZSYM){
00646 phimin=0.0;
00647 phimax=0.5*PI;
00648 }
00649 else if(XSYM && !YSYM){
00650 phimin=-0.5*PI;
00651 phimax=0.5*PI;
00652 }
00653 else if(YSYM && !XSYM){
00654 phimin=-0.5*PI;
00655 phimax=0.5*PI;
00656 }
00657 else{
00658 phimin=-PI;
00659 phimax=PI;
00660 }
00661 delx=threed->GetDELX();
00662 dely=threed->GetDELY();
00663 delz=threed->GetDELZ();
00664 for(ir=0;ir<A->GetNRADIAL();ir++){
00665 r=(ir+0.5)*A->GetRADSTEP();
00666 for(ictheta=0;ictheta<nctheta;ictheta++){
00667 ctheta=cthetamin+(ictheta+0.5)*(1.0-cthetamin)/double(nctheta);
00668 stheta=sqrt(1.0-ctheta*ctheta);
00669 for(iphi=0;iphi<nphi;iphi++){
00670 phi=phimin+(0.5+iphi)*(phimax-phimin)/double(nphi);
00671 x=r*stheta*cos(phi);
00672 y=r*stheta*sin(phi);
00673 z=r*ctheta;
00674 if(fabs(x)<delx*threed->GetNXMAX() && fabs(y)<dely*threed->GetNYMAX()
00675 && fabs(z)<delz*threed->GetNZMAX()){
00676 interpolate=threed->GetElement(x,y,z);
00677 ex=x/r;
00678 ey=y/r;
00679 ez=z/r;
00680 interpolate=interpolate/(double(nctheta*nphi));
00681 A->IncrementAExpArrayFromE(ex,ey,ez,interpolate,ir);
00682 }
00683 }
00684 }
00685 }
00686 }
00687
00688 void ArrayCalc::Calc3DArrayFromAExpArray(CCHArray *A,C3DArray *threed){
00689 int ix,iy,iz,isx,isy,isz,nsx,nsy,nsz;
00690 double interpolate,x,y,z;
00691 if(!CompareArrayParameters(threed,A)) exit(1);
00692
00693 nsx=nsy=nsz=2;
00694 if(A->GetXSYM()) nsx=1;
00695 if(A->GetYSYM()) nsy=1;
00696 if(A->GetZSYM()) nsz=1;
00697 for(isx=0;isx<nsx;isx++){
00698 for(ix=0;ix<threed->GetNXMAX();ix++){
00699 x=(0.5+ix)*threed->GetDELX();
00700 if(isx==1) x=-x;
00701 for(isy=0;isy<nsy;isy++){
00702 for(iy=0;iy<threed->GetNYMAX();iy++){
00703 y=(0.5+iy)*threed->GetDELY();
00704 if(isy==1) y=-y;
00705 for(isz=0;isz<nsz;isz++){
00706 for(iz=0;iz<threed->GetNZMAX();iz++){
00707 z=(0.5+iz)*threed->GetDELZ();
00708 if(isz==1) z=-z;
00709 interpolate=A->AExpand(x,y,z);
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 threed->SetElement(isx,ix,isy,iy,isz,iz,interpolate);
00734 }
00735 }
00736 }
00737 }
00738 }
00739 }
00740 }
00741
00742 bool ArrayCalc::CompareArrayParameters(C3DArray *threed,CCHArray *A){
00743 if(A->GetXSYM()!=threed->GetXSYM() || A->GetYSYM()!=threed->GetYSYM()
00744 || A->GetZSYM()!=threed->GetZSYM()){
00745 printf("X: %d=?%d, Y: %d=?%d Z: %d=?%d\n",
00746 A->GetXSYM(),threed->GetXSYM(),
00747 A->GetYSYM(),threed->GetYSYM(),
00748 A->GetZSYM(),threed->GetZSYM());
00749 printf("Symmetry mismatch between CHArray and 3DArray!!!\n");
00750 return 0;
00751 }
00752 return 1;
00753 }
00754
00755 bool ArrayCalc::CompareArrayParameters(CCHArray *A,C3DArray*threed){
00756 if(A->GetXSYM()!=threed->GetXSYM() || A->GetYSYM()!=threed->GetYSYM()
00757 || A->GetZSYM()!=threed->GetZSYM()){
00758 printf("Symmetry mismatch between CHArray and 3DArray!!!\n");
00759 return 0;
00760 }
00761 return 1;
00762 }
00763
00764 bool ArrayCalc::CompareArrayParameters(CCHArray *A,CCHArray *B){
00765 if(A->GetXSYM()!=B->GetXSYM() || A->GetYSYM()!=B->GetYSYM()
00766 || A->GetZSYM()!=B->GetZSYM()){
00767 printf("Symmetry mismatch between CHArrays!!!\n");
00768 return 0;
00769 }
00770 if(A->GetNRADIAL()!=B->GetNRADIAL()){
00771 printf("NRADIAL mismatch between CCHArrays!!!\n");
00772 return 0;
00773 }
00774 if(fabs(A->GetRADSTEP())-fabs(B->GetRADSTEP())>1.0E-10){
00775 printf("RADSTEP mismatch between CCHArrays!!!\n");
00776 return 0;
00777 }
00778 if(A->GetLMAX()!=B->GetLMAX()){
00779 printf("LMAX mismatch metween CCHArrays!!!\n");
00780 return 0;
00781 }
00782 return 1;
00783 }
00784
00785 bool ArrayCalc::CompareArrayParameters(C3DArray *threeda,C3DArray *threedb){
00786 bool XSYM,YSYM,ZSYM;
00787 XSYM=threeda->GetXSYM();
00788 YSYM=threeda->GetYSYM();
00789 ZSYM=threeda->GetZSYM();
00790 if(XSYM!=threedb->GetXSYM() || YSYM!=threedb->GetYSYM()
00791 || ZSYM!=threedb->GetZSYM()){
00792 printf("Symmetry mismatch between 3DArrays!!!\n");
00793 threeda->PrintPars();
00794 threedb->PrintPars();
00795 return 0;
00796 }
00797 if(threeda->GetNXMAX()!=threedb->GetNXMAX()
00798 || threeda->GetNYMAX()!=threedb->GetNYMAX()
00799 || threedb->GetNZMAX()!=threedb->GetNZMAX()){
00800 printf("NXYZMAX mismatch between 3DArrays!!!\n");
00801 return 0;
00802 }
00803 if(fabs(threeda->GetDELX()-threedb->GetDELX())>1.0E-10
00804 || fabs(threeda->GetDELY()-threedb->GetDELY())>1.0E-10
00805 || fabs(threeda->GetDELZ()-threedb->GetDELZ())>1.0E-10){
00806 printf("DELXYZ mismatch between 3DArrays!!!\n");
00807 return 0;
00808 }
00809 return 1;
00810 }
00811
00812 void ArrayCalc::MultiplyArrays(C3DArray *threeda,C3DArray *threedb,C3DArray *threedc){
00813 int ix,iy,iz,isx,isy,isz,nsx,nsy,nsz;
00814 if(!CompareArrayParameters(threeda,threedb)) exit(1);
00815 if(!CompareArrayParameters(threeda,threedc)) exit(1);
00816 nsx=nsy=nsz=2;
00817 if(threeda->GetXSYM()) nsx=1;
00818 if(threeda->GetYSYM()) nsy=1;
00819 if(threeda->GetZSYM()) nsz=1;
00820 for(isx=0;isx<nsx;isx++){
00821 for(ix=0;ix<threeda->GetNXMAX();ix++){
00822 for(isy=0;isy<nsy;isy++){
00823 for(iy=0;iy<threeda->GetNYMAX();iy++){
00824 for(isz=0;isz<nsz;isz++){
00825 for(iz=0;iz<threeda->GetNZMAX();iz++){
00826 threedc->SetElement(isx,ix,isy,iy,isz,iz,
00827 threeda->GetElement(isx,ix,isy,iy,isz,iz)
00828 *threedb->GetElement(isx,ix,isy,iy,isz,iz));
00829 }
00830 }
00831 }
00832 }
00833 }
00834 }
00835
00836 }
00837
00838 void ArrayCalc::DivideArrays(C3DArray *threeda,C3DArray *threedb,C3DArray *threedc){
00839 int ix,iy,iz,isx,isy,isz,nsx,nsy,nsz;
00840 if(!CompareArrayParameters(threeda,threedb)) exit(1);
00841 if(!CompareArrayParameters(threeda,threedc)) exit(1);
00842 nsx=nsy=nsz=2;
00843 if(threeda->GetXSYM()) nsx=1;
00844 if(threeda->GetYSYM()) nsy=1;
00845 if(threeda->GetZSYM()) nsz=1;
00846 for(isx=0;isx<nsx;isx++){
00847 for(ix=0;ix<threeda->GetNXMAX();ix++){
00848 for(isy=0;isy<nsy;isy++){
00849 for(iy=0;iy<threeda->GetNYMAX();iy++){
00850 for(isz=0;isz<nsz;isz++){
00851 for(iz=0;iz<threeda->GetNZMAX();iz++){
00852 threedc->SetElement(isx,ix,isy,iy,isz,iz,
00853 threeda->GetElement(isx,ix,isy,iy,isz,iz)
00854 /threedb->GetElement(isx,ix,isy,iy,isz,iz));
00855 }
00856 }
00857 }
00858 }
00859 }
00860 }
00861
00862 }
00863
00864 void ArrayCalc::AddArrays(C3DArray *threeda,C3DArray *threedb,C3DArray *threedc){
00865 int ix,iy,iz,isx,isy,isz,nsx,nsy,nsz;
00866 if(!CompareArrayParameters(threeda,threedb)) exit(1);
00867 if(!CompareArrayParameters(threeda,threedc)) exit(1);
00868 nsx=nsy=nsz=2;
00869 if(threeda->GetXSYM()) nsx=1;
00870 if(threeda->GetYSYM()) nsy=1;
00871 if(threeda->GetZSYM()) nsz=1;
00872 for(isx=0;isx<nsx;isx++){
00873 for(ix=0;ix<threeda->GetNXMAX();ix++){
00874 for(isy=0;isy<nsy;isy++){
00875 for(iy=0;iy<threeda->GetNYMAX();iy++){
00876 for(isz=0;isz<nsz;isz++){
00877 for(iz=0;iz<threeda->GetNZMAX();iz++){
00878 threedc->SetElement(isx,ix,isy,iy,isz,iz,
00879 threeda->GetElement(isx,ix,isy,iy,isz,iz)
00880 +threedb->GetElement(isx,ix,isy,iy,isz,iz));
00881 }
00882 }
00883 }
00884 }
00885 }
00886 }
00887
00888 }
00889
00890 void ArrayCalc::SubtractArrays(C3DArray *threeda,C3DArray *threedb,C3DArray *threedc){
00891 int ix,iy,iz,isx,isy,isz,nsx,nsy,nsz;
00892 if(!CompareArrayParameters(threeda,threedb)) exit(1);
00893 if(!CompareArrayParameters(threeda,threedc)) exit(1);
00894 nsx=nsy=nsz=2;
00895 if(threeda->GetXSYM()) nsx=1;
00896 if(threeda->GetYSYM()) nsy=1;
00897 if(threeda->GetZSYM()) nsz=1;
00898 for(isx=0;isx<nsx;isx++){
00899 for(ix=0;ix<threeda->GetNXMAX();ix++){
00900 for(isy=0;isy<nsy;isy++){
00901 for(iy=0;iy<threeda->GetNYMAX();iy++){
00902 for(isz=0;isz<nsz;isz++){
00903 for(iz=0;iz<threeda->GetNZMAX();iz++){
00904 threedc->SetElement(isx,ix,isy,iy,isz,iz,
00905 threeda->GetElement(isx,ix,isy,iy,isz,iz)
00906 -threedb->GetElement(isx,ix,isy,iy,isz,iz));
00907 }
00908 }
00909 }
00910 }
00911 }
00912 }
00913 }
00914
00915 void ArrayCalc::CopyArray(C3DArray *threeda,C3DArray *threedb){
00916 int ix,iy,iz,isx,isy,isz,nsx,nsy,nsz;
00917 if(!CompareArrayParameters(threeda,threedb)) exit(1);
00918 nsx=nsy=nsz=2;
00919 if(threeda->GetXSYM()) nsx=1;
00920 if(threeda->GetYSYM()) nsy=1;
00921 if(threeda->GetZSYM()) nsz=1;
00922 for(isx=0;isx<nsx;isx++){
00923 for(ix=0;ix<threeda->GetNXMAX();ix++){
00924 for(isy=0;isy<nsy;isy++){
00925 for(iy=0;iy<threeda->GetNYMAX();iy++){
00926 for(isz=0;isz<nsz;isz++){
00927 for(iz=0;iz<threeda->GetNZMAX();iz++){
00928 threedb->SetElement(isx,ix,isy,iy,isz,iz,
00929 threeda->GetElement(isx,ix,isy,iy,isz,iz));
00930 }
00931 }
00932 }
00933 }
00934 }
00935 }
00936
00937 }
00938
00939 void ArrayCalc::InvertArray(C3DArray *A,C3DArray *B){
00940 int ix,iy,iz,isx,isy,isz,nsx,nsy,nsz;
00941 if(!CompareArrayParameters(A,B)) exit(1);
00942 nsx=nsy=nsz=2;
00943 if(A->GetXSYM()) nsx=1;
00944 if(A->GetYSYM()) nsy=1;
00945 if(A->GetZSYM()) nsz=1;
00946 for(isx=0;isx<nsx;isx++){
00947 for(ix=0;ix<A->GetNXMAX();ix++){
00948 for(isy=0;isy<nsy;isy++){
00949 for(iy=0;iy<A->GetNYMAX();iy++){
00950 for(isz=0;isz<nsz;isz++){
00951 for(iz=0;iz<A->GetNZMAX();iz++){
00952 B->SetElement(isx,ix,isy,iy,isz,iz,
00953 1.0/A->GetElement(isx,ix,isy,iy,isz,iz));
00954 }
00955 }
00956 }
00957 }
00958 }
00959 }
00960 }
00961
00962 void ArrayCalc::InvertArray(CCHArray *A,CCHArray *B){
00963 int ir;
00964 if(A->GetNRADIAL()!=B->GetNRADIAL()){
00965 printf("FATAL: NRADIAL mismatch in ArrayCalc::InvertArrays\n");
00966 exit(1);
00967 }
00968 for(ir=0;ir<A->GetNRADIAL();ir++) InvertArray(A,ir,B,ir);
00969 }
00970
00971 void ArrayCalc::InvertArray(CCHArray *A,int ira,CCHArray *B,int irb){
00972 if( (A->GetXSYM()!=B->GetXSYM())
00973 || (!A->GetYSYM()!=B->GetYSYM())
00974 || (!A->GetZSYM()!=B->GetZSYM()) ){
00975 printf("FATAL: Symmetry mismatch in ArrayCalc::InvertArray\n");
00976 exit(1);
00977 }
00978 CCHArray *C;
00979 C=new CCHArray(A->GetLMAX(),1,1.0,A->GetXSYM(),
00980 A->GetYSYM(),A->GetZSYM());
00981 C->ZeroArray();
00982 C->IncrementElement(0,0,0,0,1.0);
00983 DivideArrays(A,ira,C,0,B,irb);
00984 delete (C);
00985 }
00986
00987 #endif