dcomplex pl_base1_triT<tiny_cpx<T> >::atan(value_type x) { #if _MSC_VER>1600 return std::atan(k(x)); #else dcomplex _tmp =pl_log::g(dcomplex(1.0+x.imag(),-x.real()))-pl_log::g(dcomplex(1.0-x.imag(),x.real())); return dcomplex(-0.5*_tmp.imag(),0.5*_tmp.real()); #endif }
dcomplex pl_base1_triT<tiny_cpx<T> >::asin(value_type x) { #if _MSC_VER>1600 return std::asin(k(x)); #else dcomplex _tmp=pl_log::g(dcomplex(-x.imag(),x.real())+pl_sqrt::g(-pl_pow::g(x,2)+1.0)); return dcomplex(_tmp.imag(),-_tmp.real()); #endif }
log_value<dcomplex> TransposeInverseMatrix(const Array2 < complex <doublevar> > & a, Array2 < complex <doublevar> > & a1, const int n) { Array2 <complex <doublevar> > temp(n,n); Array1 <int> indx(n); doublevar d; // a(i,j) first index i is row index (convention) // elements of column vectors are stored contiguous in memory in C style arrays // a(i) refers to a column vector // calculate the inverse of the transposed matrix because this // allows to pass a column vector to lubksb() instead of a row // put the transposed matrix in temp //cout << "temp " << endl; for(int i=0;i<n;++i) { for(int j=0;j<n;++j) { temp(i,j)=a(i,j); a1(i,j)=complex <doublevar> (0.0,0.0); } a1(i,i)=complex <doublevar> (1.0,0.0); } //cout << "ludcmp" << endl; //if the matrix is singular, the determinant is zero. if(ludcmp(temp,n,indx,d)==0) { #ifdef SUPERDEBUG cout << "log_value<dcomplex>TransposeInverseMatrix:zero determinant " << endl; #endif return dcomplex(0.0,0.0); } //cout << "lubksb" << endl; for(int j=0;j<n;++j) { // get column vector Array1 <complex <doublevar> > yy;//(a1(j)); yy.refer(a1(j)); lubksb(temp,n,indx,yy); } //complex <doublevar> det(d,0); log_value<dcomplex> det=dcomplex(d,0); for(int j=0;j<n;++j) { det *= temp(j,j); } return det; }
void Wf_return::mpiRecieve(int node) { #ifdef USE_MPI int nwf, nst; MPI_Status status; MPI_Recv(&nwf, 1, MPI_INT, node, 0, MPI_Comm_grp, &status); MPI_Recv(&nst, 1, MPI_INT, node, 0, MPI_Comm_grp, &status); MPI_Recv(&is_complex, 1, MPI_INT, node, 0, MPI_Comm_grp, &status); Resize(nwf, nst); MPI_Recv(amp.v, nwf*nst, MPI_DOUBLE, node, 0, MPI_Comm_grp, & status); MPI_Recv(phase.v, nwf*nst, MPI_DOUBLE, node, 0, MPI_Comm_grp, &status); if(is_complex) { for(int w=0; w < nwf; w++) { for(int i=0; i < nst; i++) { doublevar tmp1, tmp2; MPI_Recv(&tmp1, 1, MPI_DOUBLE, node, 0, MPI_Comm_grp, &status); MPI_Recv(&tmp2, 1, MPI_DOUBLE, node, 0, MPI_Comm_grp, &status); cvals(w,i)=dcomplex(tmp1, tmp2); } } } #endif }
dcomplex PatchFaceDataNormOpsComplex::dot( const std::shared_ptr<pdat::FaceData<dcomplex> >& data1, const std::shared_ptr<pdat::FaceData<dcomplex> >& data2, const hier::Box& box, const std::shared_ptr<pdat::FaceData<double> >& cvol) const { TBOX_ASSERT(data1 && data2); tbox::Dimension::dir_t dimVal = box.getDim().getValue(); dcomplex retval = dcomplex(0.0, 0.0); if (!cvol) { for (tbox::Dimension::dir_t d = 0; d < dimVal; ++d) { const hier::Box face_box = pdat::FaceGeometry::toFaceBox(box, d); retval += d_array_ops.dot(data1->getArrayData(d), data2->getArrayData(d), face_box); } } else { for (tbox::Dimension::dir_t d = 0; d < dimVal; ++d) { const hier::Box face_box = pdat::FaceGeometry::toFaceBox(box, d); retval += d_array_ops.dotWithControlVolume( data1->getArrayData(d), data2->getArrayData(d), cvol->getArrayData(d), face_box); } } return retval; }
dcomplex PatchSideDataNormOpsComplex::integral( const boost::shared_ptr<pdat::SideData<dcomplex> >& data, const hier::Box& box, const boost::shared_ptr<pdat::SideData<double> >& vol) const { TBOX_ASSERT(data); int dimVal = box.getDim().getValue(); dcomplex retval = dcomplex(0.0, 0.0); const hier::IntVector& directions = data->getDirectionVector(); TBOX_ASSERT(directions == hier::IntVector::min(directions, vol->getDirectionVector())); for (tbox::Dimension::dir_t d = 0; d < dimVal; ++d) { if (directions(d)) { retval += d_array_ops.integral( data->getArrayData(d), vol->getArrayData(d), pdat::SideGeometry::toSideBox(box, d)); } } return retval; }
/*! Complex band solver using ZGBSV * * n Size of the matrix (number of equations) * kl Number of subdiagonals * ku Number of superdiagonals * nrhs Number of RHS vectors to solve * ab Array values (2D array) * ldab Leading dim. size of ab = 2*KL+KU+1 * ipiv output integer array containing pivot permutation * b RHS vectors, and solution * ldb length of b (= n) * info output status * * This code is about 25% faster than NR * Timing for 260 points (s): NR: 5.698204e-05, LAPACK: 4.410744e-05 */ void cband_solve(dcomplex **a, int n, int m1, int m2, dcomplex *b) { int kl, ku, nrhs; int ldab, ldb; int info; nrhs = 1; kl = m1; ku = m2; ldab = 2*kl + ku + 1; ldb = n; static int *ipiv; static int len = 0, alen = 0; static fcmplx *x, *AB; if(alen < ldab*n) { if(alen > 0) delete[] AB; AB = new fcmplx[ldab*n]; alen = ldab*n; } if(len < n) { if(len > 0) { delete[] ipiv; delete[] x; } ipiv = new int[n]; x = new fcmplx[n]; len = n; } // Copy RHS data for(int i=0;i<n;i++) { x[i].r = b[i].Real(); x[i].i = b[i].Imag(); } // Put matrix elements into AB(ldab, N) (FORTRAN -> loops over ldab fastest) // A is organised into rows, but AB is in columns. First kl not set for(int j=0;j<n;j++) { for(int i=0;i<=(ku+kl); i++) { // AB(kl + i, j) = A[j - ku + i][kl+ku - i] if( ((j - ku + i) >= 0) && ((j - ku + i) < n) ) { AB[j*ldab + kl + i].r = a[j - ku + i][kl+ku - i].Real(); AB[j*ldab + kl + i].i = a[j - ku + i][kl+ku - i].Imag(); } } } zgbsv_(&n, &kl, &ku, &nrhs, AB, &ldab, ipiv, x, &ldb, &info); // Copy result back for(int i=0;i<n;i++) { b[i] = dcomplex(x[i].r, x[i].i); } }
void EigenSystemSolverRealSymmetricMatrix(const Array2 <doublevar > & Ain, Array1 <doublevar> & evals, Array2 <doublevar> & evecs){ //returns eigenvalues from largest to lowest and //eigenvectors, where for i-th eigenvalue, the eigenvector components are evecs(*,i) #ifdef USE_LAPACK //if LAPACK int N=Ain.dim[0]; Array2 <doublevar> Ain2(N,N); //need to copy the array!! Ain2=Ain; /* allocate and initialise the matrix */ Array1 <doublevar> W, Z, WORK; Array1 <int> ISUPPZ, IWORK; int M; /* allocate space for the output parameters and workspace arrays */ W.Resize(N); Z.Resize(N*N); ISUPPZ.Resize(2*N); WORK.Resize(26*N); IWORK.Resize(10*N); int info; /* get the eigenvalues and eigenvectors */ info=dsyevr('V', 'A', 'L', N, Ain2.v, N, 0.0, 0.0, 0, 0, dlamch('S'), &M, W.v, Z.v, N, ISUPPZ.v, WORK.v, 26*N, IWORK.v, 10*N); if(info>0) error("Internal error in the LAPACK routine dsyevr"); if(info<0) error("Problem with the input parameter of LAPACK routine dsyevr in position "-info); for (int i=0; i<N; i++) evals(i)=W[N-1-i]; for (int i=0; i<N; i++) { for (int j=0; j<N; j++) { evecs(j,i)=Z[j+(N-1-i)*N]; } } //END OF LAPACK #else //IF NO LAPACK const int n = Ain.dim[0]; Array2 < dcomplex > Ain_complex(n,n); Array2 <dcomplex> evecs_complex(n,n); for (int i=0; i < n; i++) for (int j=0; j < n; j++) { Ain_complex(i,j)=dcomplex(Ain(i,j),0.0); } Jacobi(Ain_complex, evals, evecs_complex); for (int i=0; i < n; i++) for (int j=0; j < n; j++){ evecs(i,j)=real(evecs_complex(i,j)); } #endif //END OF NO LAPACK }
dcomplex PatchFaceDataNormOpsComplex::integral( const std::shared_ptr<pdat::FaceData<dcomplex> >& data, const hier::Box& box, const std::shared_ptr<pdat::FaceData<double> >& vol) const { TBOX_ASSERT(data); tbox::Dimension::dir_t dimVal = box.getDim().getValue(); dcomplex retval = dcomplex(0.0, 0.0); for (tbox::Dimension::dir_t d = 0; d < dimVal; ++d) { retval += d_array_ops.integral(data->getArrayData(d), vol->getArrayData(d), pdat::FaceGeometry::toFaceBox(box, d)); } return retval; }
void GeneralizedEigenSystemSolverRealGeneralMatrices(Array2 < doublevar > & Ain, Array1 <dcomplex> & W, Array2 <doublevar> & VL, Array2 <doublevar> & VR) { #ifdef USE_LAPACK //if LAPACK int N=Ain.dim[0]; Array2 <doublevar> A_temp=Ain; //,VL(N,N),VR(N,N); Array1 <doublevar> WORK,RWORK(2*N),WI(N),WR(N); WI.Resize(N); VL.Resize(N,N); VR.Resize(N,N); int info; int NB=64; int NMAX=N; int lda=NMAX; int ldb=NMAX; int LWORK=5*NMAX; WORK.Resize(LWORK); info= dgeev('V','V',N,A_temp.v, lda,WR.v,WI.v,VL.v,lda,VR.v,lda,WORK.v,LWORK); if(info>0) error("Internal error in the LAPACK routine dgeev",info); if(info<0) error("Problem with the input parameter of LAPACK routine dgeev in position ",-info); W.Resize(N); for(int i=0; i< N; i++) { W(i)=dcomplex(WR(i),WI(i)); } // for (int i=0; i<N; i++) // evals(i)=W[N-1-i]; // for (int i=0; i<N; i++) { // for (int j=0; j<N; j++) { // evecs(j,i)=A_temp(N-1-i,j); // } // } //END OF LAPACK #else //IF NO LAPACK error("need LAPACK for eigensystem solver for general matrices"); #endif //END OF NO LAPACK }
dcomplex PatchSideDataNormOpsComplex::dot( const boost::shared_ptr<pdat::SideData<dcomplex> >& data1, const boost::shared_ptr<pdat::SideData<dcomplex> >& data2, const hier::Box& box, const boost::shared_ptr<pdat::SideData<double> >& cvol) const { TBOX_ASSERT(data1 && data2); TBOX_ASSERT(data1->getDirectionVector() == data2->getDirectionVector()); int dimVal = box.getDim().getValue(); dcomplex retval = dcomplex(0.0, 0.0); const hier::IntVector& directions = data1->getDirectionVector(); if (!cvol) { for (tbox::Dimension::dir_t d = 0; d < dimVal; ++d) { if (directions(d)) { const hier::Box side_box = pdat::SideGeometry::toSideBox(box, d); retval += d_array_ops.dot(data1->getArrayData(d), data2->getArrayData(d), side_box); } } } else { TBOX_ASSERT(directions == hier::IntVector::min(directions, cvol->getDirectionVector())); for (tbox::Dimension::dir_t d = 0; d < dimVal; ++d) { if (directions(d)) { const hier::Box side_box = pdat::SideGeometry::toSideBox(box, d); retval += d_array_ops.dotWithControlVolume( data1->getArrayData(d), data2->getArrayData(d), cvol->getArrayData(d), side_box); } } } return retval; }
//*************************************************TERM 1************************************************* //brute force sum dcomplex Zetafunc::term1full(const double q2){ dcomplex result(0.,0.),tmpcomp; double fact,rsq,theta,phi; threevec<double> nvec,npar,nperp,rvec; double resultre=0.,resultim=0.; #pragma omp parallel for reduction(+:resultre) reduction(+:resultim) private(rvec,rsq,theta,phi,nvec,fact,tmpcomp,npar,nperp) for(int z=-MAXRUN; z<=MAXRUN; z++){ for(int y=-MAXRUN; y<=MAXRUN; y++){ for(int x=-MAXRUN; x<=MAXRUN; x++){ nvec(static_cast<double>(x),static_cast<double>(y),static_cast<double>(z)); //compute r: if(!is_zeroboost){ orthogonal_projection(nvec,boost,npar,nperp); rvec=npar/gamma-boost/(2.*gamma)+nperp; } else{ rvec=nvec; } rvec.get_spherical_coordinates(rsq,theta,phi); if(l!=0)fact=::std::pow(rsq,l); //compute |r|^l else fact=1.; rsq*=rsq; //compute r^2 //compute prefact: fact*=::std::exp(-lambda*(rsq-q2))/(rsq-q2); //compute the ratio tmpcomp=fact*spherical_harmonicy(l,m,theta,phi); //multiply with spherical harmonics resultre+=tmpcomp.re(); resultim+=tmpcomp.im(); //result+=tmpcomp; } } } result=dcomplex(resultre,resultim); return result; }
bool trianglematrix1(dyn_matrix& A, dcomplex *x, int n){ for(int i = 0 ; i < n ; i++){ transf1(A,x,i,n); dcomplex A_d = A[i][i]; if(abs(A_d) < 1E-20) return false; for(int p = i; p < n; p++){ A[i][p] /= A_d; } x[i] /= A_d; for(int j = i + 1; j < n; j++){ dcomplex A_j = A[j][i]; if(A_j != dcomplex(0, 0)){ for(int k = i; k < n; k++) A[j][k] -= A[i][k]*A_j; x[j] -= x[i]*A_j; } } } return true; }
//---------------------------------------------------------------------- void Average_ekt::write_summary(Average_return &avg,Average_return &err, ostream & os) { Array2 <dcomplex> obdm_up(nmo,nmo),obdm_down(nmo,nmo), obdm_up_err(nmo,nmo),obdm_down_err(nmo,nmo), cndc_up(nmo, nmo), cndc_down(nmo, nmo), vlnc_up(nmo, nmo), vlnc_down(nmo, nmo), cndc_up_err(nmo, nmo), cndc_down_err(nmo, nmo), vlnc_up_err(nmo, nmo), vlnc_down_err(nmo, nmo); //Array4 <dcomplex> // tbdm_uu(nmo,nmo),tbdm_uu_err(nmo,nmo), // tbdm_ud(nmo,nmo),tbdm_ud_err(nmo,nmo), // tbdm_du(nmo,nmo),tbdm_du_err(nmo,nmo), // tbdm_dd(nmo,nmo),tbdm_dd_err(nmo,nmo); os << "EKT: nmo " << nmo << endl; os << "EKT: states { "; for(int i=0; i< nmo; i++) { os << occupations[0][i]+1 << " " ; } os << " } \n"; os << "Orbital normalization " << endl; for(int i=0; i< nmo; i++) { os << avg.vals(i) << " +/- " << err.vals(i) << endl; } // for(int i=0; i < nmo; i++) { // avg.vals(i)=1.0/nmo; //assume that the orbitals are normalized. // } if (eval_obdm) { dcomplex i_c(0.,1.); int place=0; for(int i=0; i < nmo; i++) { for(int j=0; j < nmo; j++) { doublevar norm=sqrt(avg.vals(i)*avg.vals(j)); int index=nmo + place; obdm_up(i,j)=dcomplex(avg.vals(index),avg.vals(index+1))/norm; obdm_up_err(i,j)=dcomplex(err.vals(index),err.vals(index+1))/norm; index+=2*nmo*nmo; obdm_down(i,j)=dcomplex(avg.vals(index),avg.vals(index+1))/norm; obdm_down_err(i,j)=dcomplex(err.vals(index),err.vals(index+1))/norm; place+=2; } } os << "One-body density matrix " << endl; int colwidth=40; if(!complex_orbitals) colwidth=20; os << setw(10) << " " << setw(10) << " " << setw(colwidth) << "up" << setw(colwidth) << "up err" << setw(colwidth) << "down" << setw(colwidth) << "down err" << endl; for(int i=0; i< nmo ; i++) { for(int j=0; j<nmo; j++) { if(complex_orbitals) { os << setw(10) << i << setw(10) << j << setw(colwidth) << obdm_up(i,j) << setw(colwidth) << obdm_up_err(i,j) << setw(colwidth) << obdm_down(i,j) << setw(colwidth) << obdm_down_err(i,j) << endl; } else { os << setw(10) << i << setw(10) << j << setw(colwidth) << obdm_up(i,j).real() << setw(colwidth) << obdm_up_err(i,j).real() << setw(colwidth) << obdm_down(i,j).real() << setw(colwidth) << obdm_down_err(i,j).real() << endl; } } } } if (eval_valence) { dcomplex i_c(0.,1.); int place=0; for(int i=0; i < nmo; i++) { for(int j=0; j < nmo; j++) { doublevar norm=sqrt(avg.vals(i)*avg.vals(j)); int index=nmo+4*nmo*nmo + place; vlnc_up(i,j)=dcomplex(avg.vals(index),avg.vals(index+1))/norm; vlnc_up_err(i,j)=dcomplex(err.vals(index),err.vals(index+1))/norm; index+=2*nmo*nmo; vlnc_down(i,j)=dcomplex(avg.vals(index),avg.vals(index+1))/norm; vlnc_down_err(i,j)=dcomplex(err.vals(index),err.vals(index+1))/norm; place+=2; } } os << "Valence band matrix " << endl; int colwidth=40; if(!complex_orbitals) colwidth=20; os << setw(10) << " " << setw(10) << " " << setw(colwidth) << "up" << setw(colwidth) << "up err" << setw(colwidth) << "down" << setw(colwidth) << "down err" << endl; for(int i=0; i< nmo ; i++) { for(int j=0; j<nmo; j++) { if(complex_orbitals) { os << setw(10) << i << setw(10) << j << setw(colwidth) << vlnc_up(i,j) << setw(colwidth) << vlnc_up_err(i,j) << setw(colwidth) << vlnc_down(i,j) << setw(colwidth) << vlnc_down_err(i,j) << endl; } else { os << setw(10) << i << setw(10) << j << setw(colwidth) << vlnc_up(i,j).real() << setw(colwidth) << vlnc_up_err(i,j).real() << setw(colwidth) << vlnc_down(i,j).real() << setw(colwidth) << vlnc_down_err(i,j).real() << endl; } } } } if (eval_conduction) { dcomplex i_c(0.,1.); int place=0; for(int i=0; i < nmo; i++) { for(int j=0; j < nmo; j++) { doublevar norm=sqrt(avg.vals(i)*avg.vals(j)); int index=nmo + 8*nmo*nmo + place; cndc_up(i,j)=dcomplex(avg.vals(index),avg.vals(index+1))/norm; cndc_up_err(i,j)=dcomplex(err.vals(index),err.vals(index+1))/norm; index+=2*nmo*nmo; cndc_down(i,j)=dcomplex(avg.vals(index),avg.vals(index+1))/norm; cndc_down_err(i,j)=dcomplex(err.vals(index),err.vals(index+1))/norm; place+=2; } } os << "Conduction band matrix " << endl; int colwidth=40; if(!complex_orbitals) colwidth=20; os << setw(10) << " " << setw(10) << " " << setw(colwidth) << "up" << setw(colwidth) << "up err" << setw(colwidth) << "down" << setw(colwidth) << "down err" << endl; for(int i=0; i< nmo ; i++) { for(int j=0; j<nmo; j++) { if(complex_orbitals) { os << setw(10) << i << setw(10) << j << setw(colwidth) << cndc_up(i,j) << setw(colwidth) << cndc_up_err(i,j) << setw(colwidth) << cndc_down(i,j) << setw(colwidth) << cndc_down_err(i,j) << endl; } else { os << setw(10) << i << setw(10) << j << setw(colwidth) << cndc_up(i,j).real() << setw(colwidth) << cndc_up_err(i,j).real() << setw(colwidth) << cndc_down(i,j).real() << setw(colwidth) << cndc_down_err(i,j).real() << endl; } } } } /* totnelectrons = 2; cout << "Ntot: " << totnelectrons << endl; for(int i=0; i < totnelectrons; i++) { cout << "Kin: " << i << " " << avg.vals(nmo + 12*nmo*nmo + i) << "+/-" << err.vals(nmo + 12*nmo*nmo + i) << endl; cout << "Pot: " << i << " " << avg.vals(nmo + 12*nmo*nmo + totnelectrons + i) << "+/-" << err.vals(nmo + 12*nmo*nmo + totnelectrons + i) << endl; }*/ dcomplex trace=0; for(int i=0;i< nmo; i++) trace+=obdm_up(i,i); os << "Trace of the obdm: up: " << trace; trace=0; for(int i=0; i< nmo; i++) trace+=obdm_down(i,i); os << " down: " << trace << endl; }
void Average_ekt::evaluate_obdm(Wavefunction_data * wfdata, Wavefunction * wf, System * sys, Sample_point * sample, Average_return & avg) { wf->updateVal(wfdata,sample); Wf_return wfval_base(wf->nfunc(),2); wf->getVal(wfdata,0,wfval_base); int nup=sys->nelectrons(0); int ndown=sys->nelectrons(1); int nelectrons=nup+ndown; Array1 <Array2 <dcomplex> > movals1_base(nelectrons); for(int e=0; e< nelectrons; e++) { movals1_base(e).Resize(nmo,1); calc_mos(sample,e,movals1_base(e)); /*! Huihuo Here, permutation symmetry has been applied, the real evaluation quantity is sum_(e=1)^N phi_i* (r_e) phi_j(r') psi(r_1,... r',...r_N)/psi(r_1, ..., r_n, ..., r_N) Therefore, movals1_base[e, i] = phi_i(r_e), where e is the index of the electron. !!!One need to be careful about the off-gamma point 1 RDM */ } // avg.vals.Resize(nmo+4*nmo*nmo); // avg.vals=0; Array2 <dcomplex> movals1(nmo,1); Array1 <Wf_return> wfs(nelectrons); Wavefunction_storage * store; wf->generateStorage(store); for(int i=0; i< npoints_eval; i++) { Array1 <doublevar> oldpos(3); sample->getElectronPos(0,oldpos); sample->setElectronPosNoNotify(0,saved_r(i)); calc_mos(sample,0,movals1); /*! This is simply to calculate phi_j(r'): Noted that r' has been given, therefore, movals1 is a one dimentional array, with matrix element to be phi_j(r') -- j is the index */ sample->setElectronPosNoNotify(0,oldpos); Array1 <Wf_return> wf_eval; wf->evalTestPos(saved_r(i),sample,wfs); //Testing the evalTestPos //for(int e=0; e< nelectrons; e++) { // Wf_return test_wf(wf->nfunc(),2); // sample->getElectronPos(e,oldpos); // wf->saveUpdate(sample,e,store); // sample->setElectronPos(e,saved_r(i)); // wf->updateVal(wfdata,sample); // wf->getVal(wfdata,e,test_wf); // sample->setElectronPos(e,oldpos); // wf->restoreUpdate(sample,e,store); // cout << "e " << e << " test " << test_wf.amp(0,0) << " evalTestPos " << wfs(e).amp(0,0) << endl; //} doublevar dist1=0; for(int m=0; m < nmo; m++) dist1+=norm(movals1(m,0)); for(int orbnum=0; orbnum < nmo; orbnum++) { avg.vals(orbnum)+=norm(movals1(orbnum,0))/(dist1*npoints_eval); } for(int e=0; e< nelectrons; e++) { dcomplex psiratio_1b=exp(dcomplex(wfs(e).amp(0,0)-wfval_base.amp(0,0), wfs(e).phase(0,0)-wfval_base.phase(0,0))); /*! psi(r_1,...,r',...,r_N)/psi(r_1,...,r_e,...,r_N), the ratio of the new with respect to the old if one change the position of the e-th electron from r_e to r' */ int which_obdm=0; if(e >= nup) { which_obdm=1; } dcomplex tmp; int place=0; dcomplex prefactor=psiratio_1b/(dist1*npoints_eval); for(int orbnum=0; orbnum < nmo; orbnum++) { for(int orbnum2=0; orbnum2 < nmo; orbnum2++) { //tmp=movals1(orbnum,0)*conj(movals1_base(e)(orbnum2,0))*prefactor; /*! Huihuo Zheng This is to based on my new definition: \rho(r, r') = N\int dR psi*(r, R) psi(r', R) = \sum rho_{ij} phi_i*(r) phi_j(r') in this way, one will find that, the phase factor is cancelled */ tmp=conj(movals1(orbnum,0))*movals1_base(e)(orbnum2,0)*prefactor; avg.vals(nmo+2*which_obdm*nmo*nmo+place)+=tmp.real(); avg.vals(nmo+2*which_obdm*nmo*nmo+place+1)+=tmp.imag(); place+=2; } } } } delete store; }
void Average_ekt::evaluate_valence(Wavefunction_data * wfdata, Wavefunction * wf, System * sys, Pseudopotential *psp, Sample_point * sample, Average_return & avg) { /* This is to evaluate the v_ij in extended Koopmans' theorem -- for valence bands */ wf->updateVal(wfdata,sample); Wf_return wfval_base(wf->nfunc(),2); wf->getVal(wfdata,0,wfval_base); int nup=sys->nelectrons(0); int ndown=sys->nelectrons(1); int nelectrons=nup+ndown; Array1 <doublevar> rn(3), rnp(3), rnpp(3); Array1 <Array2 <dcomplex> > movals1_base(nelectrons); Array2 <dcomplex> movals_p(nmo, 1); Array1 <doublevar> VLoc(nelectrons); Array1 <doublevar> VLoc0(nelectrons); Array1 <doublevar> Vtest(nelectrons+1); Array1 <dcomplex> pseudo_t(nmo); /*************************************** Routines to get Kin and Vloc ****************************************/ Array2<doublevar> Kin(nelectrons, wf->nfunc()); //Array2<doublevar> Kin0(nelectrons, wf->nfunc()); Array2<dcomplex> movals_lap(nmo, 5); for(int e=0; e< nelectrons; e++) { movals1_base(e).Resize(nmo,1); //Kin(e).Resize(1); //The Kinetic energy calc_mos(sample, e, movals1_base(e)); } // sys->calcKineticSeparated(sample,saved_r(i),Kin); //***** calculate kinetic energy and potential energy sys->calcKineticSeparated(wfdata, sample, wf, Kin); sys->calcLocSeparated(sample, VLoc); Array1 <Wf_return> wfs(nelectrons); Wavefunction_storage * store; wf->generateStorage(store); for(int i=0; i< npoints_eval; i++) { Array1 <doublevar> oldpos(3); sample->getElectronPos(0,oldpos); sample->setElectronPosNoNotify(0, saved_r(i)); calc_mosLap(sample, 0, movals_lap); int nrandvar=psp->nTest(); Array1 <doublevar> rand_num(nrandvar); for(int l=0; l< nrandvar; l++) rand_num(l)=rng.ulec(); calc_mos(sample,0,movals_p); calcPseudoMo(sys, sample, psp, rand_num, pseudo_t); sample->setElectronPosNoNotify(0,oldpos); Array1 <Wf_return> wf_eval; wf->evalTestPos(saved_r(i),sample,wfs); sys->calcLocWithTestPos(sample, saved_r(i), Vtest); doublevar vtot = 0.0; for (int e=0; e<nelectrons; e++) { vtot += Vtest(e); } doublevar dist1=0; for(int m=0; m < nmo; m++) dist1+=norm(movals_p(m,0)); for(int orbnum=0; orbnum < nmo; orbnum++) { avg.vals(orbnum)+=norm(movals_p(orbnum,0))/(dist1*npoints_eval);//this is the normalization } Array2<doublevar> totalv(nelectrons, wf->nfunc()); totalv = 0.0; psp->calcNonlocSeparated(wfdata, sys, sample, wf, totalv); int place = 0; for (int orbnum = 0; orbnum < nmo; orbnum++ ) { for (int orbnum2 = 0; orbnum2 < nmo; orbnum2++ ) { dcomplex tmp3=conj(movals_p(orbnum, 0))* (pseudo_t(orbnum2) + Vtest(nelectrons)*movals_p(orbnum2, 0) -0.5*movals_lap(orbnum2, 4) +movals_p(orbnum2, 0)*vtot) /(dist1*npoints_eval); // tmp3=conj(movals_p(orbnum, 0))*(movals_p(orbnum2, 0))/(dist1*npoints_eval); //dcomplex tmp3=conj(movals_p(orbnum, 0))*(pseudo_t(orbnum2))/(dist1*npoints_eval); int which_obdm = 0; avg.vals(nmo+8*nmo*nmo + 2*which_obdm*nmo*nmo+place) += tmp3.real(); avg.vals(nmo+8*nmo*nmo + 2*which_obdm*nmo*nmo+place+1) += tmp3.imag(); which_obdm = 1; //tmp3=conj(movals_p(orbnum, 0))*(-0.5*movals_lap(orbnum2, 4))/(dist1*npoints_eval); avg.vals(nmo+8*nmo*nmo + 2*which_obdm*nmo*nmo+place) += tmp3.real(); avg.vals(nmo+8*nmo*nmo + 2*which_obdm*nmo*nmo+place+1) += tmp3.imag(); place += 2; } } ofstream dump; if(dump_data) { dump.open("EKT_DUMP",ios::app); } for(int e=0; e< nelectrons; e++) { dcomplex psiratio_1b=conj(exp(dcomplex(wfs(e).amp(0,0) -wfval_base.amp(0,0), wfs(e).phase(0,0) -wfval_base.phase(0,0)))); int which_obdm=0; if(e >= nup) { which_obdm=1; } dcomplex tmp, tmp2, tmp3; int place=0; dcomplex prefactor=psiratio_1b/(dist1*npoints_eval); //cout << "Local potential" << " Kinetic" << " Pseudo" << endl; // cout << VLoc(e) << " " << Kin(e, 0) << " " << totalv(e, 0) << endl; for(int orbnum=0; orbnum < nmo; orbnum++) { for(int orbnum2=0; orbnum2 < nmo; orbnum2++) { // assert(wf->nfunc()==1); tmp = 0.5*(movals_p(orbnum,0)*conj(movals1_base(e)(orbnum2,0))*prefactor + movals1_base(e)(orbnum, 0)*conj(movals_p(orbnum2, 0))*conj(prefactor)); tmp2 = tmp*(VLoc(e) + Kin(e, 0) + totalv(e, 0)); //rho_ij part the one body reduced density matrix doublevar tmp2_mag=abs(tmp2); if(tmp2_mag > ekt_cutoff) { tmp2*=ekt_cutoff/tmp2_mag; } avg.vals(nmo+2*which_obdm*nmo*nmo+place) += tmp.real(); avg.vals(nmo+2*which_obdm*nmo*nmo+place+1) += tmp.imag(); //v_ij^v part //tmp3 = 0.0; avg.vals(nmo+4*nmo*nmo + 2*which_obdm*nmo*nmo+place)+=tmp2.real(); avg.vals(nmo+4*nmo*nmo + 2*which_obdm*nmo*nmo+place+1)+=tmp2.imag(); if(dump_data) { if(orbnum==orbnum2 and orbnum==0) { sample->getElectronPos(e,oldpos); dump << which_obdm << "," << tmp2.real() << "," << tmp.real() << "," << VLoc(e) << "," << Kin(e,0) << "," << totalv(e,0) << "," << oldpos(0) << "," << oldpos(1) << "," << oldpos(2) << endl; } } if (eval_conduction) { //tmp3 = -1.0*psiratio_1b*conj(movals1_base(e)(orbnum, 0))*(vtot*movals_lap(orbnum2, 0) // + pseudo_t(orbnum2) - 0.5*movals_lap(orbnum2, 4) + Vtest(nelectrons)*movals_lap(orbnum2, 0))/(dist1*npoints_eval); tmp3 = -1.0*conj(movals1_base(e)(orbnum, 0))*movals_p(orbnum2, 0)*prefactor*(VLoc(e) + Kin(e, 0) + totalv(e, 0) + Vtest(e)); doublevar tmp3_mag=abs(tmp3); if(tmp3_mag > ekt_cutoff) { tmp3*=ekt_cutoff/tmp3_mag; } avg.vals(nmo+8*nmo*nmo + 2*which_obdm*nmo*nmo+place) += tmp3.real(); avg.vals(nmo+8*nmo*nmo + 2*which_obdm*nmo*nmo+place+1) += tmp3.imag(); } place+=2; } } } } delete store; }
dcomplex Zetafunc::term3noboost(const double q2){ dcomplex result(0.,0.),sphfact,tmpcomp; double tmp,r,theta,phi; //zero term is zero: result=dcomplex(0.,0.); //line terms //x>0, y=z=0 and y>0, x=z=0 and z>0, x=y=0: //note that z->-z is equivalent to theta->pi-theta, similar to this: x->-x yields phi->pi-phi and y->-y is phi->2pi-phi sphfact= spherical_harmonicy(l,m,pimath/2. , 0.); //x>0 sphfact+= spherical_harmonicy(l,m,pimath/2. , pimath); //x<0 sphfact+= spherical_harmonicy(l,m,pimath/2. , pimath/2.); //y>0 sphfact+= spherical_harmonicy(l,m,pimath/2. , 3.*pimath/2.); //y<0 sphfact+= spherical_harmonicy(l,m,0. , 0.); //z>0 sphfact+= spherical_harmonicy(l,m,pimath , 0.); //z<0 double resultre=0., resultim=0.; #pragma omp parallel { Zetafuncint integrand2; #pragma omp parallel for reduction(+:resultre) private(tmp) for(int x=1; x<=MAXRUN; x++){ integrand2.set(q2,x,l); Midpnt<TFunctor> int2(integrand2,0.,lambda); tmp=qromo(int2); if(l!=0) tmp*=::std::pow(x,static_cast<double>(l)); resultre+=tmp; } } result+=resultre*sphfact; //plane-terms resultre=0.; resultim=0.; double* integrals=new double[MAXRUN*MAXRUN]; #pragma omp parallel { Zetafuncint integrand2; //do integrals first: #pragma omp parallel for shared(integrals) private(r,theta,phi,tmp) for(int y=1; y<=MAXRUN; y++){ for(int x=y; x<=MAXRUN; x++){ threevec<int>(x,y,0).get_spherical_coordinates(r,theta,phi); //integral integrand2.set(q2,r,l); Midpnt<TFunctor> int2(integrand2,0.,lambda); tmp=qromo(int2); if(l!=0) tmp*=::std::pow(r,static_cast<double>(l)); //store results: it is symmetrc in x and y: integrals[x-1+MAXRUN*(y-1)]=tmp; integrals[y-1+MAXRUN*(x-1)]=tmp; } } //angular parts //x,y!>0, z=0: //the four ylm account for the possibilities +/+, +/-, -/+, -/-: #pragma omp parallel for reduction(+:resultre) reduction(+:resultim) shared(integrals) private(r,theta,phi,tmp,tmpcomp) for(int y=1; y<=MAXRUN; y++){ for(int x=1; x<=MAXRUN; x++){ threevec<int>(x,y,0).get_spherical_coordinates(r,theta,phi); //z=0: sphfact= spherical_harmonicy(l,m,theta , phi); //x,y>0 sphfact+= spherical_harmonicy(l,m,theta , pimath-phi); //x<0,y>0 sphfact+= spherical_harmonicy(l,m,theta , pimath+phi); //x,y<0 sphfact+= spherical_harmonicy(l,m,theta , 2.*pimath-phi); //x>0,y<0 //result tmpcomp=integrals[y-1+MAXRUN*(x-1)]*sphfact; resultre+=tmpcomp.re(); resultre+=tmpcomp.im(); } } //x,z>0, y=0 and y,z>0, x=0: #pragma omp parallel for reduction(+:resultre) reduction(+:resultim) shared(integrals) private(r,theta,phi,tmp,tmpcomp) for(int z=1; z<=MAXRUN; z++){ for(int x=1; x<=MAXRUN; x++){ threevec<int>(x,0,z).get_spherical_coordinates(r,theta,phi); //y=0: sphfact= spherical_harmonicy(l,m,theta , 0); //x,z>0 sphfact+= spherical_harmonicy(l,m,pimath-theta , 0); //x>0,z<0 sphfact+= spherical_harmonicy(l,m,theta , pimath); //x<0,z>0 sphfact+= spherical_harmonicy(l,m,pimath-theta , pimath); //x,z<0 //x=0: sphfact+= spherical_harmonicy(l,m,theta , pimath/2.); //y,z>0 sphfact+= spherical_harmonicy(l,m,pimath-theta , pimath/2.); //y>0,z<0 sphfact+= spherical_harmonicy(l,m,theta , 3.*pimath/2.); //y<0,z>0 sphfact+= spherical_harmonicy(l,m,pimath-theta , 3.*pimath/2.); //y,z<0 //result: tmpcomp=integrals[z-1+MAXRUN*(x-1)]*sphfact; resultre+=tmpcomp.re(); resultre+=tmpcomp.im(); } } } delete [] integrals; result+=dcomplex(resultre,resultim); //cubic terms: resultre=0.; resultim=0.; integrals=new double[MAXRUN*MAXRUN*MAXRUN]; #pragma omp parallel { //do integrals first Zetafuncint integrand2; #pragma omp parallel for shared(integrals) private(r,theta,phi,tmp) for(int z=1; z<=MAXRUN; z++){ for(int y=z; y<=MAXRUN; y++){ for(int x=y; x<=MAXRUN; x++){ threevec<int>(x,y,z).get_spherical_coordinates(r,theta,phi); //integral integrand2.set(q2,r,l); Midpnt<TFunctor> int2(integrand2,0.,lambda); tmp=qromo(int2); if(l!=0) tmp*=::std::pow(r,static_cast<double>(l)); //store results: it is symmetrc in x and y: integrals[x-1+MAXRUN*((y-1)+MAXRUN*(z-1))]=tmp; integrals[z-1+MAXRUN*((x-1)+MAXRUN*(y-1))]=tmp; integrals[y-1+MAXRUN*((z-1)+MAXRUN*(x-1))]=tmp; } } } #pragma omp parallel for reduction(+:resultre) reduction(+:resultim) shared(integrals) private(r,theta,phi,tmpcomp) for(int z=1; z<=MAXRUN; z++){ for(int y=1; y<=MAXRUN; y++){ for(int x=1; x<=MAXRUN; x++){ threevec<int>(x,y,z).get_spherical_coordinates(r,theta,phi); //compute sphfact: account for all possible orientations sphfact=dcomplex(0.,0.); for(unsigned int thetaa=0; thetaa<2; thetaa++){ sphfact+=spherical_harmonicy(l,m,static_cast<double>(thetaa)*pimath-theta,phi); //x,y>0 sphfact+=spherical_harmonicy(l,m,static_cast<double>(thetaa)*pimath-theta,pimath-phi); //x<0,y>0 sphfact+=spherical_harmonicy(l,m,static_cast<double>(thetaa)*pimath-theta,pimath+phi); //x,y<0 sphfact+=spherical_harmonicy(l,m,static_cast<double>(thetaa)*pimath-theta,2.*pimath-phi); //x>0,y<0 } //compute the result: tmpcomp=integrals[x-1+MAXRUN*((y-1)+MAXRUN*(z-1))]*sphfact; //integral * ylm factor resultre+=tmpcomp.re(); resultim+=tmpcomp.im(); } } } } delete [] integrals; result+=dcomplex(resultre,resultim); //multiply result by factor: result*=::std::pow(pimath,static_cast<double>(1.5+l)); return result; }
/// Use LAPACK routine ZGTSV. About 25% slower than the simple NR routine for 260 points int tridag(const dcomplex *a, const dcomplex *b, const dcomplex *c, const dcomplex *r, dcomplex *u, int n) { int nrhs = 1; int info; // Lapack routines overwrite their inputs, so need to copy static int len = 0; static fcmplx *dl, *d, *du, *x; if(n > len) { // Allocate more memory (as a single block) if(len > 0) delete[] dl; dl = new fcmplx[4*n]; d = dl + n; du = d + n; x = du + n; len = n; } for(int i=0;i<n;i++) { // Diagonal d[i].r = b[i].Real(); d[i].i = b[i].Imag(); // Off-diagonal terms if(i != (n-1)) { dl[i].r = a[i+1].Real(); dl[i].i = a[i+1].Imag(); du[i].r = c[i].Real(); du[i].i = c[i].Imag(); } x[i].r = r[i].Real(); x[i].i = r[i].Imag(); } /* LAPACK ZGTSV routine. n - Size of the array nrhs - Number of RHS vectors to solve dl - lower band d - diagonal values du - upper band x - input and output values info - output status */ zgtsv_(&n, &nrhs, dl, d, du, x, &n, &info); if(info != 0) { // Some sort of problem output.write("Problem in LAPACK ZGTSV routine\n"); return 1; } // Copy result back for(int i=0;i<n;i++) { u[i] = dcomplex(x[i].r, x[i].i); } return 0; }
//---------------------------------------------------------------------- void Wannier_method::calculate_overlap(Array1 <int> & orb_list, Array3 <dcomplex> & eikr, Array2 <doublevar> & phi2phi2) { Array1 <Array1 <int> > tmp_list(1); tmp_list(0)=orb_list; mymomat->buildLists(tmp_list); int list=0; Array2 <doublevar> gvec(3,3); if(!sys->getPrimRecipLattice(gvec) ) error("Need getPrimRecipLattice"); int norb=orb_list.GetDim(0); eikr.Resize(3,norb,norb); phi2phi2.Resize(norb,norb); eikr=0.0; phi2phi2=0.0; Array1 <doublevar> prop(3); Array1 <doublevar> n_lat(3); n_lat=0.0; for(int d=0; d < 3; d++) { for(int d1=0; d1 < 3; d1++) n_lat(d)+=LatticeVec(d,d1)*LatticeVec(d,d1); n_lat(d)=sqrt(n_lat(d)); prop(d)=resolution/double(n_lat(d)); //cout << "prop " << prop(d) << " res " << resolution << " norm " << n_lat(d) << endl; } cout << "calculating...." << endl; mymovals.Resize(norb,1); Array1 <doublevar> r(3),x(3); Array1 <doublevar> norm_orb(norb); norm_orb=0.0; int totpts=0; for(r(0)=origin(0); r(0) < 1.0; r(0)+=prop(0)) { cout << "percent done: " << r(0)*100 << endl; for(r(1)=origin(1); r(1) < 1.0; r(1)+=prop(1)) { for(r(2)=origin(2); r(2) < 1.0; r(2)+=prop(2)) { totpts++; for(int d=0; d< 3; d++) { x(d)=0.0; for(int d1=0; d1 < 3; d1++) { x(d)+=r(d1)*LatticeVec(d1,d); } } mywalker->setElectronPos(0,x); mymomat->updateVal(mywalker,0,list,mymovals); for(int i=0; i < norb; i++) norm_orb(i)+=mymovals(i,0)*mymovals(i,0); for(int d=0; d< 3; d++) { doublevar gdotr=0; for(int d1=0; d1 < 3; d1++) { gdotr+=gvec(d,d1)*x(d1); } dcomplex exp_tmp=exp(dcomplex(0,-1)*2.*pi*gdotr); for(int i=0; i< norb; i++) { for(int j=0; j< norb; j++) { eikr(d,i,j)+=exp_tmp*mymovals(i,0)*mymovals(j,0); } } } for(int i=0; i< norb; i++) { for(int j=0; j< norb; j++) { phi2phi2(i,j)+=mymovals(i,0)*mymovals(i,0)*mymovals(j,0)*mymovals(j,0); } } } } } for(int i=0; i< norb; i++) norm_orb(i)=sqrt(norm_orb(i)); for(int d=0; d< 3; d++) { for(int i=0; i < norb; i++) { for(int j=0; j< norb; j++) { eikr(d,i,j)/=norm_orb(i)*norm_orb(j); //cout << d << " " << i << " " << j << " " << eikr(d,i,j) << endl; } } } cout << "square overlap " << endl; for(int i=0; i < norb; i++) { for(int j=0; j< norb; j++) { phi2phi2(i,j)/=(norm_orb(i)*norm_orb(i)*norm_orb(j)*norm_orb(j)); cout << sqrt(phi2phi2(i,j)) << " "; } cout << endl; } }
//A is an antisymmetric matrix and B is the output rotation matrix void make_rotation_matrix_notworking(const Array2 <doublevar> & A, Array2 <doublevar> & B) { int n=A.GetDim(0); assert(A.GetDim(1)==n); B.Resize(n,n); Array2 <dcomplex> skew(n,n),VL(n,n),VR(n,n); Array1 <dcomplex> evals(n); for(int i=0; i< n; i++) { for(int j=0; j < n; j++) { skew(i,j)=A(i,j); } } GeneralizedEigenSystemSolverComplexGeneralMatrices(skew,evals,VL,VR); cout << "evals " << endl; for(int i=0; i< n; i++) cout << evals(i) << " "; cout << endl; cout << "VR " << endl; for(int i=0; i< n; i++) { for(int j=0; j< n; j++) { cout << VR(i,j) << " "; } cout << endl; } cout << "VL " << endl; for(int i=0; i< n; i++) { for(int j=0; j< n; j++) { cout << VL(i,j) << " "; } cout << endl; } //this is horribly inefficient,most likely skew=dcomplex(0.0,0.); //we don't need that any more so we reuse it Array2 <dcomplex> work(n,n); work=dcomplex(0.0,0.); for(int i=0; i< n; i++) { skew(i,i)=exp(evals(i)); } for(int i=0; i< n; i++) { for(int j=0; j<n; j++) { for(int k=0; k< n; k++) { work(i,k)+=skew(i,j)*VR(j,k); } } } skew=dcomplex(0.,0.); for(int i=0; i< n; i++) { for(int j=0; j<n; j++) { for(int k=0; k< n; k++) { //skew(i,k)+=conj(VL(i,j))*work(j,k); skew(i,k)=conj(VR(j,i))*work(j,k); } } } cout << "rotation " << endl; for(int i=0; i< n; i++) { for(int j=0; j< n; j++) { cout << skew(i,j) << " "; } cout << endl; } }
void RealTime<double>::formUTrans() { // // Form the unitary transformation matrix: // U = exp(-i*dT*F) // auto NTCSxNBASIS = this->nTCS_*this->nBasis_; // Set up Eigen Maps ComplexMap uTransA(this->uTransAMem_,NTCSxNBASIS,NTCSxNBASIS); ComplexMap scratch(this->scratchMem_,NTCSxNBASIS,NTCSxNBASIS); ComplexMap uTransB(this->uTransBMem_,0,0); if(!this->isClosedShell_ && this->Ref_ != SingleSlater<double>::TCS) { new (&uTransB) ComplexMap(this->uTransBMem_,NTCSxNBASIS,NTCSxNBASIS); } // FIXME: Eigen's Eigensolver is terrible, replace with LAPACK routines if (this->methFormU_ == EigenDecomp) { // Eigen-decomposition char JOBZ = 'V'; char UPLO = 'L'; int INFO; dcomplex *A = this->scratchMem_; double *W = this->REAL_LAPACK_SCR; double *RWORK = W + std::max(1,3*NTCSxNBASIS-2); dcomplex *WORK = this->CMPLX_LAPACK_SCR; RealVecMap E(W,NTCSxNBASIS); ComplexMap V(A,NTCSxNBASIS,NTCSxNBASIS); ComplexMap S(WORK,NTCSxNBASIS,NTCSxNBASIS); E.setZero(); V.setZero(); S.setZero(); std::memcpy(A,this->ssPropagator_->fockA()->data(), NTCSxNBASIS*NTCSxNBASIS*sizeof(dcomplex)); V.transposeInPlace(); // BC Col major zheev_(&JOBZ,&UPLO,&NTCSxNBASIS,A,&NTCSxNBASIS,W,WORK,&this->lWORK,RWORK, &INFO); V.transposeInPlace(); // BC Col major std::memcpy(WORK,A,NTCSxNBASIS*NTCSxNBASIS*sizeof(dcomplex)); for(auto i = 0; i < NTCSxNBASIS; i++) { S.col(i) *= dcomplex(std::cos(this->deltaT_ * W[i]), -std::sin(this->deltaT_ * W[i])); } uTransA = S * V.adjoint(); if(!this->isClosedShell_ && this->Ref_ != SingleSlater<dcomplex>::TCS) { E.setZero(); V.setZero(); S.setZero(); std::memcpy(A,this->ssPropagator_->fockB()->data(), NTCSxNBASIS*NTCSxNBASIS*sizeof(dcomplex)); V.transposeInPlace(); // BC Col major zheev_(&JOBZ,&UPLO,&NTCSxNBASIS,A,&NTCSxNBASIS,W,WORK,&this->lWORK,RWORK, &INFO); V.transposeInPlace(); // BC Col major std::memcpy(WORK,A,NTCSxNBASIS*NTCSxNBASIS*sizeof(dcomplex)); for(auto i = 0; i < NTCSxNBASIS; i++) { S.col(i) *= dcomplex(std::cos(this->deltaT_ * W[i]), -std::sin(this->deltaT_ * W[i])); } uTransB = S * V.adjoint(); } } else if (this->methFormU_ == Taylor) { // Taylor expansion CErr("Taylor expansion NYI",this->fileio_->out); /* This is not taylor and breaks with the new memory scheme scratch = -math.ii * deltaT_ * (*this->ssPropagator_->fockA()); uTransA = scratch.exp(); // FIXME if(!this->isClosedShell_ && this->Ref_ != SingleSlater<double>::TCS) { scratch = -math.ii * deltaT_ * (*this->ssPropagator_->fockB()); uTransB = scratch.exp(); // FIXME } */ } // prettyPrint(this->fileio_->out,(*this->uTransA_),"uTransA"); // if(!this->isClosedShell_ && this->Ref_ != SingleSlater<double>::TCS) prettyPrint(this->fileio_->out,(*this->uTransB_),"uTransB"); };
void Average_ekt::jsonOutput(Average_return &avg,Average_return &err, ostream & os) { Array2 <dcomplex> obdm_up(nmo,nmo),obdm_down(nmo,nmo), obdm_up_err(nmo,nmo),obdm_down_err(nmo,nmo), cndc_up(nmo, nmo), cndc_down(nmo, nmo), vlnc_up(nmo, nmo), vlnc_down(nmo, nmo), cndc_up_err(nmo, nmo), cndc_down_err(nmo, nmo), vlnc_up_err(nmo, nmo), vlnc_down_err(nmo, nmo); os <<"\""<< avg.type << "\":{" << endl; os << "\"nmo\":" << nmo <<","<< endl; os << "\"states\":["; for(int i=0; i< nmo; i++) { if(i==nmo-1) os << occupations[0][i]+1 ; else os << occupations[0][i]+1 << "," ; } os << "]," << endl; os << "\"normalization\":{" << endl; os << "\"value\":["; for(int i=0; i< nmo; i++) { if(i< nmo-1) os << avg.vals(i) << ","; else os << avg.vals(i); } os << "],"<< endl; os << "\"error\":["; for(int i=0; i< nmo; i++) { if(i< nmo-1) os << err.vals(i) << ","; else os << err.vals(i); } os << "]"<< endl; os << "}," << endl; if(eval_obdm) { dcomplex i_c(0.,1.); int place=0; for(int i=0; i < nmo; i++) { for(int j=0; j < nmo; j++) { doublevar norm=sqrt(avg.vals(i)*avg.vals(j)); int index=nmo + place; obdm_up(i,j)=dcomplex(avg.vals(index),avg.vals(index+1))/norm; obdm_up_err(i,j)=dcomplex(err.vals(index),err.vals(index+1))/norm; index+=2*nmo*nmo; obdm_down(i,j)=dcomplex(avg.vals(index),avg.vals(index+1))/norm; obdm_down_err(i,j)=dcomplex(err.vals(index),err.vals(index+1))/norm; place+=2; } } os << "\"obdm\":{" << endl; int colwidth=40; if(!complex_orbitals) colwidth=20; os << "\"up\":["<< endl; for(int i=0; i< nmo ; i++) { os << "["; for(int j=0; j<nmo; j++) { if(complex_orbitals) { if(j==nmo-1) os << "["<< obdm_up(i,j).real() <<","<< obdm_up(i,j).imag()<<"]"; else os << "["<< obdm_up(i,j).real() <<","<< obdm_up(i,j).imag()<<"],"; } else { if(j==nmo-1) os << obdm_up(i,j).real(); else os << obdm_up(i,j).real() << ","; } } if(i==nmo-1) os << "]" << endl; else os <<"]," << endl; } os << "]," << endl; os << "\"up_err\":["<< endl; for(int i=0; i< nmo ; i++) { os << "["; for(int j=0; j<nmo; j++) { if(complex_orbitals) { if(j==nmo-1) os <<"["<<obdm_up_err(i,j).real() <<","<< obdm_up_err(i,j).imag()<<"]"; else os <<"["<< obdm_up_err(i,j).real() <<","<< obdm_up_err(i,j).imag()<<"],"; } else { if(j==nmo-1) os << obdm_up_err(i,j).real(); else os << obdm_up_err(i,j).real() << ","; } } if(i==nmo-1) os << "]" << endl; else os <<"]," << endl; } os << "]," << endl; os << "\"down\":["<< endl; for(int i=0; i< nmo ; i++) { os << "["; for(int j=0; j<nmo; j++) { if(complex_orbitals) { if(j==nmo-1) os << "["<< obdm_down(i,j).real() <<","<< obdm_down(i,j).imag()<<"]"; else os << "["<< obdm_down(i,j).real() <<","<< obdm_down(i,j).imag()<<"],"; } else { if(j==nmo-1) os << obdm_down(i,j).real(); else os << obdm_down(i,j).real() << ","; } } if(i==nmo-1) os << "]" << endl; else os <<"]," << endl; } os << "]," << endl; os << "\"down_err\":["<< endl; for(int i=0; i< nmo ; i++) { os << "["; for(int j=0; j<nmo; j++) { if(complex_orbitals) { if(j==nmo-1) os <<"["<< obdm_down_err(i,j).real() <<","<< obdm_down_err(i,j).imag()<<"]"; else os << "[" << obdm_down_err(i,j).real() <<","<< obdm_down_err(i,j).imag()<<"],"; } else { if(j==nmo-1) os << obdm_down_err(i,j).real(); else os << obdm_down_err(i,j).real() << ","; } } if(i==nmo-1) os << "]" << endl; else os <<"]," << endl; } os << "]" << endl; os << "}," << endl; } if (eval_valence) { dcomplex i_c(0.,1.); int place=0; for(int i=0; i < nmo; i++) { for(int j=0; j < nmo; j++) { doublevar norm=sqrt(avg.vals(i)*avg.vals(j)); int index=nmo+4*nmo*nmo + place; vlnc_up(i,j)=dcomplex(avg.vals(index),avg.vals(index+1))/norm; vlnc_up_err(i,j)=dcomplex(err.vals(index),err.vals(index+1))/norm; index+=2*nmo*nmo; vlnc_down(i,j)=dcomplex(avg.vals(index),avg.vals(index+1))/norm; vlnc_down_err(i,j)=dcomplex(err.vals(index),err.vals(index+1))/norm; place+=2; } } os << "\"valence\":{" << endl; int colwidth=40; if(!complex_orbitals) colwidth=20; os << "\"up\":["<< endl; for(int i=0; i< nmo ; i++) { os << "["; for(int j=0; j<nmo; j++) { if(complex_orbitals) { if(j==nmo-1) os << "["<< vlnc_up(i,j).real() <<","<< vlnc_up(i,j).imag()<<"]"; else os << "["<< vlnc_up(i,j).real() <<","<< vlnc_up(i,j).imag()<<"],"; } else { if(j==nmo-1) os << vlnc_up(i,j).real(); else os << vlnc_up(i,j).real() << ","; } } if(i==nmo-1) os << "]" << endl; else os <<"]," << endl; } os << "]," << endl; os << "\"up_err\":["<< endl; for(int i=0; i< nmo ; i++) { os << "["; for(int j=0; j<nmo; j++) { if(complex_orbitals) { if(j==nmo-1) os <<"["<<vlnc_up_err(i,j).real() <<","<< vlnc_up_err(i,j).imag()<<"]"; else os <<"["<< vlnc_up_err(i,j).real() <<","<< vlnc_up_err(i,j).imag()<<"],"; } else { if(j==nmo-1) os << vlnc_up_err(i,j).real(); else os << vlnc_up_err(i,j).real() << ","; } } if(i==nmo-1) os << "]" << endl; else os <<"]," << endl; } os << "]," << endl; os << "\"down\":["<< endl; for(int i=0; i< nmo ; i++) { os << "["; for(int j=0; j<nmo; j++) { if(complex_orbitals) { if(j==nmo-1) os << "["<< vlnc_down(i,j).real() <<","<< vlnc_down(i,j).imag()<<"]"; else os << "["<< vlnc_down(i,j).real() <<","<< vlnc_down(i,j).imag()<<"],"; } else { if(j==nmo-1) os << vlnc_down(i,j).real(); else os << vlnc_down(i,j).real() << ","; } } if(i==nmo-1) os << "]" << endl; else os <<"]," << endl; } os << "]," << endl; os << "\"down_err\":["<< endl; for(int i=0; i< nmo ; i++) { os << "["; for(int j=0; j<nmo; j++) { if(complex_orbitals) { if(j==nmo-1) os <<"["<< vlnc_down_err(i,j).real() <<","<< vlnc_down_err(i,j).imag()<<"]"; else os << "[" << vlnc_down_err(i,j).real() <<","<< vlnc_down_err(i,j).imag()<<"],"; } else { if(j==nmo-1) os << vlnc_down_err(i,j).real(); else os << vlnc_down_err(i,j).real() << ","; } } if(i==nmo-1) os << "]" << endl; else os <<"]," << endl; } os << "]" << endl; os << "}," << endl; } if (eval_conduction) { dcomplex i_c(0.,1.); int place=0; for(int i=0; i < nmo; i++) { for(int j=0; j < nmo; j++) { doublevar norm=sqrt(avg.vals(i)*avg.vals(j)); int index=nmo + 8*nmo*nmo + place; cndc_up(i,j)=dcomplex(avg.vals(index),avg.vals(index+1))/norm; cndc_up_err(i,j)=dcomplex(err.vals(index),err.vals(index+1))/norm; index+=2*nmo*nmo; cndc_down(i,j)=dcomplex(avg.vals(index),avg.vals(index+1))/norm; cndc_down_err(i,j)=dcomplex(err.vals(index),err.vals(index+1))/norm; place+=2; } } os << "\"conduction\":{" << endl; int colwidth=40; if(!complex_orbitals) colwidth=20; os << "\"up\":["<< endl; for(int i=0; i< nmo ; i++) { os << "["; for(int j=0; j<nmo; j++) { if(complex_orbitals) { if(j==nmo-1) os << "["<< cndc_up(i,j).real() <<","<< cndc_up(i,j).imag()<<"]"; else os << "["<< cndc_up(i,j).real() <<","<< cndc_up(i,j).imag()<<"],"; } else { if(j==nmo-1) os << cndc_up(i,j).real(); else os << cndc_up(i,j).real() << ","; } } if(i==nmo-1) os << "]" << endl; else os <<"]," << endl; } os << "]," << endl; os << "\"up_err\":["<< endl; for(int i=0; i< nmo ; i++) { os << "["; for(int j=0; j<nmo; j++) { if(complex_orbitals) { if(j==nmo-1) os <<"["<<cndc_up_err(i,j).real() <<","<< cndc_up_err(i,j).imag()<<"]"; else os <<"["<< cndc_up_err(i,j).real() <<","<< cndc_up_err(i,j).imag()<<"],"; } else { if(j==nmo-1) os << cndc_up_err(i,j).real(); else os << cndc_up_err(i,j).real() << ","; } } if(i==nmo-1) os << "]" << endl; else os <<"]," << endl; } os << "]," << endl; os << "\"down\":["<< endl; for(int i=0; i< nmo ; i++) { os << "["; for(int j=0; j<nmo; j++) { if(complex_orbitals) { if(j==nmo-1) os << "["<< cndc_down(i,j).real() <<","<< cndc_down(i,j).imag()<<"]"; else os << "["<< cndc_down(i,j).real() <<","<< cndc_down(i,j).imag()<<"],"; } else { if(j==nmo-1) os << cndc_down(i,j).real(); else os << cndc_down(i,j).real() << ","; } } if(i==nmo-1) os << "]" << endl; else os <<"]," << endl; } os << "]," << endl; os << "\"down_err\":["<< endl; for(int i=0; i< nmo ; i++) { os << "["; for(int j=0; j<nmo; j++) { if(complex_orbitals) { if(j==nmo-1) os <<"["<< cndc_down_err(i,j).real() <<","<< cndc_down_err(i,j).imag()<<"]"; else os << "[" << cndc_down_err(i,j).real() <<","<< cndc_down_err(i,j).imag()<<"],"; } else { if(j==nmo-1) os << cndc_down_err(i,j).real(); else os << cndc_down_err(i,j).real() << ","; } } if(i==nmo-1) os << "]" << endl; else os <<"]," << endl; } os << "]" << endl; os << "}" << endl; } //dcomplex trace=0; //for(int i=0;i< nmo; i++) trace+=obdm_up(i,i); //os << "\"Trace of the obdm\":{" << endl; //os << "\"up\":[" << trace.real()<< "," << trace.imag()<<"]" << "," << endl; //trace=0; //for(int i=0; i< nmo; i++) trace+=obdm_down(i,i); //os << "\"down\":[" << trace.real()<< "," << trace.imag()<<"]" << endl; //os << "}" << endl; os << "}" << endl; }
const Field3D DDZ(const Field3D &f, CELL_LOC outloc, DIFF_METHOD method, bool inc_xbndry) { deriv_func func = fDDZ; // Set to default function DiffLookup *table = FirstDerivTable; CELL_LOC inloc = f.getLocation(); // Input location CELL_LOC diffloc = inloc; // Location of differential result if(StaggerGrids && (outloc == CELL_DEFAULT)) { // Take care of CELL_DEFAULT case outloc = diffloc; // No shift (i.e. same as no stagger case) } if(StaggerGrids && (outloc != inloc)) { // Shifting to a new location if(((inloc == CELL_CENTRE) && (outloc == CELL_ZLOW)) || ((inloc == CELL_ZLOW) && (outloc == CELL_CENTRE))) { // Shifting in Z. Centre -> Zlow, or Zlow -> Centre func = sfDDZ; // Set default table = FirstStagDerivTable; // Set table for others diffloc = (inloc == CELL_CENTRE) ? CELL_ZLOW : CELL_CENTRE; } else { // A more complicated shift. Get a result at cell centre, then shift. if(inloc == CELL_ZLOW) { // Shifting func = sfDDZ; // Set default table = FirstStagDerivTable; // Set table for others diffloc = CELL_CENTRE; } else if(inloc != CELL_CENTRE) { // Interpolate then (centre -> centre) then interpolate return DDZ(interp_to(f, CELL_CENTRE), outloc, method); } } } if(method != DIFF_DEFAULT) { // Lookup function func = lookupFunc(table, method); } Field3D result; if(func == NULL) { // Use FFT real shift = 0.; // Shifting result in Z? if(StaggerGrids) { if((inloc == CELL_CENTRE) && (diffloc == CELL_ZLOW)) { // Shifting down - multiply by exp(-0.5*i*k*dz) shift = -1.; } else if((inloc == CELL_ZLOW) && (diffloc == CELL_CENTRE)) { // Shifting up shift = 1.; } } result.Allocate(); // Make sure data allocated static dcomplex *cv = (dcomplex*) NULL; int jx, jy, jz; real kwave; real flt; int xge = MXG, xlt = ngx-MXG; if(inc_xbndry) { // Include x boundary region (for mixed XZ derivatives) xge = 0; xlt = ngx; } if(cv == (dcomplex*) NULL) cv = new dcomplex[ncz/2 + 1]; for(jx=xge; jx<xlt; jx++) { for(jy=0; jy<ngy; jy++) { rfft(f[jx][jy], ncz, cv); // Forward FFT for(jz=0; jz<=ncz/2; jz++) { kwave=jz*2.0*PI/zlength; // wave number is 1/[rad] if (jz>0.4*ncz) flt=1e-10; else flt=1.0; cv[jz] *= dcomplex(0.0, kwave) * flt; if(StaggerGrids) cv[jz] *= exp(Im * (shift * kwave * dz)); } irfft(cv, ncz, result[jx][jy]); // Reverse FFT result[jx][jy][ncz] = result[jx][jy][0]; } } #ifdef CHECK // Mark boundaries as invalid result.bndry_xin = result.bndry_xout = result.bndry_yup = result.bndry_ydown = false; #endif } else { // All other (non-FFT) functions result = applyZdiff(f, func, dz); } result.setLocation(diffloc); return interp_to(result, outloc); }
//--------------------------------------------------------------------- // Computes NY N-point complex-to-complex FFTs of X using an algorithm due // to Swarztrauber. X is both the input and the output array, while Y is a // scratch array. It is assumed that N = 2^M. Before calling // Swarztrauber to // perform FFTs //--------------------------------------------------------------------- static void Swarztrauber(int is, int m, int vlen, int n, int xd1, void *ox, dcomplex exponent[n]) { dcomplex (*x)[xd1] = (dcomplex (*)[xd1])ox; int i, j, l; dcomplex u1, x11, x21; int k, n1, li, lj, lk, ku, i11, i12, i21, i22; if (timers_enabled) timer_start(4); //--------------------------------------------------------------------- // Perform one variant of the Stockham FFT. //--------------------------------------------------------------------- n1 = n / 2; lj = 1; li = 1 << m; for (l = 1; l <= m; l += 2) { lk = lj; lj = 2 * lk; li = li / 2; ku = li; for (i = 0; i <= li - 1; i++) { i11 = i * lk; i12 = i11 + n1; i21 = i * lj; i22 = i21 + lk; if (is >= 1) { u1 = exponent[ku+i]; } else { u1 = dconjg(exponent[ku+i]); } for (k = 0; k <= lk - 1; k++) { for (j = 0; j < vlen; j++) { x11 = x[i11+k][j]; x21 = x[i12+k][j]; scr[i21+k][j] = dcmplx_add(x11, x21); scr[i22+k][j] = dcmplx_mul(u1, dcmplx_sub(x11, x21)); } } } if (l == m) { for (k = 0; k < n; k++) { for (j = 0; j < vlen; j++) { x[k][j] = scr[k][j]; } } } else { lk = lj; lj = 2 * lk; li = li / 2; ku = li; for (i = 0; i <= li - 1; i++) { i11 = i * lk; i12 = i11 + n1; i21 = i * lj; i22 = i21 + lk; if (is >= 1) { u1 = exponent[ku+i]; } else { u1 = dconjg(exponent[ku+i]); } for (k = 0; k <= lk - 1; k++) { for (j = 0; j < vlen; j++) { x11 = scr[i11+k][j]; x21 = scr[i12+k][j]; x[i21+k][j] = dcmplx_add(x11, x21); x[i22+k][j] = dcmplx_mul(u1, dcmplx_sub(x11, x21)); } } } } } if (timers_enabled) timer_stop(4); }
/** * 1D crystal * Randomize the on-site energies to be between 0 an 1 * Fix the hopping terms to be 1 for the nearest neighbours and decaying as 1/r^3 * Fix the dynamical terms to be 1 for the nearest neighbours and decaying as 1/r^3 * * calculate * 1/two_particle_localization_length * = - lim_{|n-m|--> infty} << ln|<m, m+a|G(z)|n, n+a>| >> / |n-m| * where << ... >> represents the average over different configurations of disorder * * In the current case, we let a = 1 and * we want z.real to be at the center of the band */ TEST(LocalizationTest, RandomOnSiteEnergy) { LatticeShape lattice1D(1); int xmax; READ_INPUT("input.txt", "int", xmax); lattice1D.setXmax(xmax); //xsite = xmax + 1 int initialSeperation=1; //default value is 1 /* set up interaction data */ double onsiteE, hop, dyn; bool randomOnsite, randomHop, randomDyn; int maxDistance; unsigned seed; bool longRangeHop, longRangeDyn; READ_INPUT("input.txt", "double", onsiteE); READ_INPUT("input.txt", "double", hop); READ_INPUT("input.txt", "double", dyn); READ_INPUT("input.txt", "bool", randomOnsite); READ_INPUT("input.txt", "bool", randomHop); READ_INPUT("input.txt", "bool", randomDyn); READ_INPUT("input.txt", "int", maxDistance); READ_INPUT("input.txt", "unsigned", seed); READ_INPUT("input.txt", "bool", longRangeHop); READ_INPUT("input.txt", "bool", longRangeDyn); READ_INPUT("input.txt", "int", initialSeperation); int n = xmax/2; int nPlusa = n + initialSeperation; Basis initialSites(n, nPlusa); InteractionData interactionData = { onsiteE, hop, dyn, randomOnsite, randomHop, randomDyn, maxDistance, seed, longRangeHop, longRangeDyn}; setUpIndexInteractions(lattice1D, interactionData); std::vector< dcomplex > zList; double E; READ_INPUT("input.txt", "double", E); double eta; READ_INPUT("input.txt", "double", eta); zList.push_back(dcomplex(E, eta)); std::vector<std::string> fileList; //fileList.push_back("GF.txt"); fileList.push_back("GF.bin"); calculateAllGreenFunc(lattice1D, initialSites, interactionData, zList, fileList); // extract Green's function from the file CDMatrix gf; loadMatrix(fileList[0], gf); std::ofstream myFile; std::string output = "a_" + itos(initialSeperation)+".txt"; myFile.open(output.c_str()); for (int m=n; m<=xmax-initialSeperation; ++m ) { dcomplex element = gf(m, m+initialSeperation); double G_n_m = std::log( std::abs( element ) ); myFile << (m-n) << "\t"<< G_n_m << std::endl; } myFile.close(); EXPECT_TRUE(true); }
//can be used if boost is zero: dcomplex Zetafunc::term1noboost(const double q2){ dcomplex result(0.,0.),sphfact,tmpcomp; double fact,rsq,r,theta,phi,resultre,resultim; threevec<double> nvec; //zero term is zero: result=dcomplex(0.,0.); //line terms //x>0, y=z=0 and y>0, x=z=0 and z>0, x=y=0: //note that z->-z is equivalent to theta->pi-theta, similar to this: x->-x yields phi->pi-phi and y->-y is phi->2pi-phi sphfact= spherical_harmonicy(l,m,pimath/2. , 0.); //x>0 sphfact+= spherical_harmonicy(l,m,pimath/2. , pimath); //x<0 sphfact+= spherical_harmonicy(l,m,pimath/2. , pimath/2.); //y>0 sphfact+= spherical_harmonicy(l,m,pimath/2. , 3.*pimath/2.); //y<0 sphfact+= spherical_harmonicy(l,m,0. , 0.); //z>0 sphfact+= spherical_harmonicy(l,m,pimath , 0.); //z<0 //reduce resultre=0.,resultim=0.; #pragma omp parallel for reduction(+:resultre) reduction(+:resultim) firstprivate(q2,sphfact) private(rsq,r,tmpcomp) schedule(static) for(int x=1; x<=MAXRUN; x++){ rsq=x*x; tmpcomp=dcomplex(::std::exp(-lambda*(rsq-q2))*::std::pow(static_cast<double>(x),l)/(rsq-q2),0.)*sphfact; resultre+=tmpcomp.re(); resultim+=tmpcomp.im(); } result+=dcomplex(resultre,resultim); //plane terms //x,y!>0, z=0: //the four ylm account for the possibilities +/+, +/-, -/+, -/-: resultre=0.,resultim=0.; #pragma omp parallel for reduction(+:resultre) reduction(+:resultim) firstprivate(q2) private(rsq,r,theta,phi,sphfact,tmpcomp) schedule(static) for(int y=1; y<=MAXRUN; y++){ for(int x=1; x<=MAXRUN; x++){ threevec<int>(x,y,0).get_spherical_coordinates(r,theta,phi); rsq=r*r; //z=0: sphfact= spherical_harmonicy(l,m,theta , phi); //x,y>0 sphfact+= spherical_harmonicy(l,m,theta , pimath-phi); //x<0,y>0 sphfact+= spherical_harmonicy(l,m,theta , pimath+phi); //x,y<0 sphfact+= spherical_harmonicy(l,m,theta , 2.*pimath-phi); //x>0,y<0 //result tmpcomp=dcomplex(::std::exp(-lambda*(rsq-q2))*::std::pow(r,l)/(rsq-q2),0.)*sphfact; resultre+=tmpcomp.re(); resultim+=tmpcomp.im(); } } result+=dcomplex(resultre,resultim); //x,z>0, y=0 and y,z>0, x=0: resultre=0.,resultim=0.; #pragma omp parallel for reduction(+:resultre) reduction(+:resultim) firstprivate(q2) private(rsq,r,theta,phi,sphfact,tmpcomp) schedule(static) for(int z=1; z<=MAXRUN; z++){ for(int x=1; x<=MAXRUN; x++){ threevec<int>(x,0,z).get_spherical_coordinates(r,theta,phi); rsq=r*r; //y=0: sphfact= spherical_harmonicy(l,m,theta , 0); //x,z>0 sphfact+= spherical_harmonicy(l,m,pimath-theta , 0); //x>0,z<0 sphfact+= spherical_harmonicy(l,m,theta , pimath); //x<0,z>0 sphfact+= spherical_harmonicy(l,m,pimath-theta , pimath); //x,z<0 //x=0: sphfact+= spherical_harmonicy(l,m,theta , pimath/2.); //y,z>0 sphfact+= spherical_harmonicy(l,m,pimath-theta , pimath/2.); //y>0,z<0 sphfact+= spherical_harmonicy(l,m,theta , 3.*pimath/2.); //y<0,z>0 sphfact+= spherical_harmonicy(l,m,pimath-theta , 3.*pimath/2.); //y,z<0 //result: tmpcomp=dcomplex(::std::exp(-lambda*(rsq-q2))*::std::pow(r,l)/(rsq-q2),0.)*sphfact; resultre+=tmpcomp.re(); resultim+=tmpcomp.im(); } } result+=dcomplex(resultre,resultim); //cubic terms //x,y,z>0 resultre=0., resultim=0.; #pragma omp parallel for reduction(+:resultre) reduction(+:resultim) firstprivate(q2) private(nvec,rsq,r,theta,phi,fact,tmpcomp) schedule(static) for(int z=1; z<=MAXRUN; z++){ for(int y=1; y<=MAXRUN; y++){ for(int x=1; x<=MAXRUN; x++){ nvec(static_cast<double>(x),static_cast<double>(y),static_cast<double>(z)); nvec.get_spherical_coordinates(r,theta,phi); fact=::std::pow(r,l); //compute |r|^l rsq=r*r; //compute r^2 fact*=::std::exp(-lambda*(rsq-q2))/(rsq-q2); //compute the ratio //compute sphfact: account for all possible orientations sphfact=dcomplex(0.,0.); for(unsigned int thetaa=0; thetaa<2; thetaa++){ sphfact+=spherical_harmonicy(l,m,static_cast<double>(thetaa)*pimath-theta,phi); //x,y>0 sphfact+=spherical_harmonicy(l,m,static_cast<double>(thetaa)*pimath-theta,pimath-phi); //x<0,y>0 sphfact+=spherical_harmonicy(l,m,static_cast<double>(thetaa)*pimath-theta,pimath+phi); //x,y<0 sphfact+=spherical_harmonicy(l,m,static_cast<double>(thetaa)*pimath-theta,2.*pimath-phi); //x>0,y<0 } //compute the result: tmpcomp=fact*sphfact; //ratio * ylm factor resultre+=tmpcomp.re(); resultim+=tmpcomp.im(); } } } result+=dcomplex(resultre,resultim); return result; }