From 7ba93db9e3b637ac1156f1d9b08291fc64a6afd4 Mon Sep 17 00:00:00 2001 From: Xing Zhang Date: Sun, 4 May 2025 22:56:19 -0700 Subject: [PATCH 1/2] add rt-tddft --- examples/rttddft/01_molOAS.py | 186 ++ pyscf/lib/CMakeLists.txt | 13 + pyscf/lib/rttddft/libpp01/FortInt.h | 7 + pyscf/lib/rttddft/libpp01/Gaussian.c | 352 +++ pyscf/lib/rttddft/libpp01/Gaussian.h | 54 + pyscf/lib/rttddft/libpp01/Properties.c | 98 + pyscf/lib/rttddft/libpp01/Properties.h | 16 + .../rttddft/libpp01/README_clib_fix20210801a | 1 + .../libpp01/README_pyscf_csrc_20210728 | 1 + pyscf/lib/rttddft/libpp01/cConstants.h | 62 + pyscf/lib/rttddft/libpp01/cmplx.c | 146 + pyscf/lib/rttddft/libpp01/cstrutil.c | 353 +++ pyscf/lib/rttddft/libpp01/cstrutil.h | 20 + pyscf/lib/rttddft/libpp01/dalloc.c | 878 ++++++ pyscf/lib/rttddft/libpp01/dalloc.h | 114 + pyscf/lib/rttddft/libpp01/dcmplx.h | 28 + pyscf/lib/rttddft/libpp01/govlp.c | 596 ++++ pyscf/lib/rttddft/libpp01/govlp.h | 17 + pyscf/lib/rttddft/libpp01/macro_util.h | 183 ++ pyscf/lib/rttddft/libpp01/makefile | 50 + pyscf/lib/rttddft/libpp01/mathfn.c | 626 ++++ pyscf/lib/rttddft/libpp01/mathfn.h | 41 + pyscf/lib/rttddft/libpp01/tgz_pySCF.sh.tmstmp | 30 + pyscf/lib/rttddft/libpp01/ushort.h | 4 + pyscf/lib/rttddft/libpp01/xgaussope.c | 2216 +++++++++++++ pyscf/lib/rttddft/libpp01/xgaussope.h | 158 + pyscf/rttddft/Constants.py | 3 + pyscf/rttddft/Dbglogger.py | 31 + pyscf/rttddft/GEAR.py | 242 ++ pyscf/rttddft/Logger.py | 452 +++ pyscf/rttddft/Loglv.py | 176 ++ pyscf/rttddft/MPIutils01.py | 90 + pyscf/rttddft/Moldyn.py | 2232 +++++++++++++ pyscf/rttddft/README.md | 6 + pyscf/rttddft/Stdlogger.py | 21 + pyscf/rttddft/__init__.py | 3 + pyscf/rttddft/bandstructure.py | 1569 ++++++++++ pyscf/rttddft/calcNacm.py | 1442 +++++++++ pyscf/rttddft/calcNacm2.py | 1048 +++++++ pyscf/rttddft/calc_OAS.py | 345 ++ pyscf/rttddft/diis.py | 438 +++ pyscf/rttddft/diis01.py | 1196 +++++++ pyscf/rttddft/eldyn.py | 2083 +++++++++++++ pyscf/rttddft/filter_by_exponent.py | 176 ++ pyscf/rttddft/futils.py | 51 + pyscf/rttddft/gto_ps_pp_int01.py | 2200 +++++++++++++ pyscf/rttddft/gto_ps_pp_int01_bf20210608.py | 945 ++++++ pyscf/rttddft/heapcheck.py | 9 + pyscf/rttddft/laserfield.py | 536 ++++ pyscf/rttddft/mpiutils.py | 167 + pyscf/rttddft/physicalconstants.py | 116 + pyscf/rttddft/print_00.py | 37 + pyscf/rttddft/pyscf_common.py | 749 +++++ pyscf/rttddft/rttddft01.py | 2502 +++++++++++++++ pyscf/rttddft/rttddft02.py | 422 +++ pyscf/rttddft/rttddft_common.py | 665 ++++ pyscf/rttddft/serialize.py | 1004 ++++++ pyscf/rttddft/test_mol_or_cell.py | 157 + pyscf/rttddft/update_dict.py | 119 + pyscf/rttddft/utils.py | 2772 +++++++++++++++++ pyscf/rttddft/with_fftdf_get_pp.py | 283 ++ 61 files changed, 30537 insertions(+) create mode 100644 examples/rttddft/01_molOAS.py create mode 100644 pyscf/lib/rttddft/libpp01/FortInt.h create mode 100644 pyscf/lib/rttddft/libpp01/Gaussian.c create mode 100644 pyscf/lib/rttddft/libpp01/Gaussian.h create mode 100644 pyscf/lib/rttddft/libpp01/Properties.c create mode 100644 pyscf/lib/rttddft/libpp01/Properties.h create mode 100644 pyscf/lib/rttddft/libpp01/README_clib_fix20210801a create mode 100644 pyscf/lib/rttddft/libpp01/README_pyscf_csrc_20210728 create mode 100644 pyscf/lib/rttddft/libpp01/cConstants.h create mode 100644 pyscf/lib/rttddft/libpp01/cmplx.c create mode 100644 pyscf/lib/rttddft/libpp01/cstrutil.c create mode 100644 pyscf/lib/rttddft/libpp01/cstrutil.h create mode 100644 pyscf/lib/rttddft/libpp01/dalloc.c create mode 100644 pyscf/lib/rttddft/libpp01/dalloc.h create mode 100644 pyscf/lib/rttddft/libpp01/dcmplx.h create mode 100644 pyscf/lib/rttddft/libpp01/govlp.c create mode 100644 pyscf/lib/rttddft/libpp01/govlp.h create mode 100644 pyscf/lib/rttddft/libpp01/macro_util.h create mode 100644 pyscf/lib/rttddft/libpp01/makefile create mode 100644 pyscf/lib/rttddft/libpp01/mathfn.c create mode 100644 pyscf/lib/rttddft/libpp01/mathfn.h create mode 100644 pyscf/lib/rttddft/libpp01/tgz_pySCF.sh.tmstmp create mode 100644 pyscf/lib/rttddft/libpp01/ushort.h create mode 100644 pyscf/lib/rttddft/libpp01/xgaussope.c create mode 100644 pyscf/lib/rttddft/libpp01/xgaussope.h create mode 100644 pyscf/rttddft/Constants.py create mode 100644 pyscf/rttddft/Dbglogger.py create mode 100644 pyscf/rttddft/GEAR.py create mode 100644 pyscf/rttddft/Logger.py create mode 100644 pyscf/rttddft/Loglv.py create mode 100644 pyscf/rttddft/MPIutils01.py create mode 100644 pyscf/rttddft/Moldyn.py create mode 100644 pyscf/rttddft/README.md create mode 100644 pyscf/rttddft/Stdlogger.py create mode 100644 pyscf/rttddft/__init__.py create mode 100644 pyscf/rttddft/bandstructure.py create mode 100644 pyscf/rttddft/calcNacm.py create mode 100644 pyscf/rttddft/calcNacm2.py create mode 100644 pyscf/rttddft/calc_OAS.py create mode 100644 pyscf/rttddft/diis.py create mode 100644 pyscf/rttddft/diis01.py create mode 100644 pyscf/rttddft/eldyn.py create mode 100644 pyscf/rttddft/filter_by_exponent.py create mode 100644 pyscf/rttddft/futils.py create mode 100644 pyscf/rttddft/gto_ps_pp_int01.py create mode 100644 pyscf/rttddft/gto_ps_pp_int01_bf20210608.py create mode 100644 pyscf/rttddft/heapcheck.py create mode 100644 pyscf/rttddft/laserfield.py create mode 100644 pyscf/rttddft/mpiutils.py create mode 100644 pyscf/rttddft/physicalconstants.py create mode 100644 pyscf/rttddft/print_00.py create mode 100644 pyscf/rttddft/pyscf_common.py create mode 100644 pyscf/rttddft/rttddft01.py create mode 100644 pyscf/rttddft/rttddft02.py create mode 100644 pyscf/rttddft/rttddft_common.py create mode 100644 pyscf/rttddft/serialize.py create mode 100644 pyscf/rttddft/test_mol_or_cell.py create mode 100644 pyscf/rttddft/update_dict.py create mode 100644 pyscf/rttddft/utils.py create mode 100644 pyscf/rttddft/with_fftdf_get_pp.py diff --git a/examples/rttddft/01_molOAS.py b/examples/rttddft/01_molOAS.py new file mode 100644 index 000000000..6d3e77f4a --- /dev/null +++ b/examples/rttddft/01_molOAS.py @@ -0,0 +1,186 @@ +import time +import numpy as np +import os +from pyscf.rttddft.eldyn import calc_OAS +from pyscf.rttddft.Moldyn import Moldyn,calc_mo_energies +from pyscf import gto +from pyscf.pbc import gto as pbcgto +from pyscf.rttddft.physicalconstants import PhysicalConstants +from pyscf.rttddft.utils import read_xyzf +from pyscf.rttddft.rttddft_common import rttddft_common +## Molecular calculation ## +TASK="OAS_noxyzf" + +## YOU CAN MODIFY HERE TO TEST either h-BN or CH4 .... +target_system="h-BN" # "CH4" # ; +# possible restart +restart=None +#restart=1 +params_restart={ + "moldyn_pscf":"OAS_noxyzf_h-BN_gth-dzvp_PBE,PBE_k3.3.1_gth-pbe_FFTDF_VG_Ez1.0e-03_dt8as01.pscf", + "tm_fs_offset":0.16, + "dmfilepath":"OAS_noxyzf_h-BN_gth-dzvp_PBE,PBE_k3.3.1_gth-pbe_FFTDF_VG_Ez1.0e-03_dt8as_dm.dat"} + + +df=None; pseudo=None; basis=None; mol=None; cell=None; + +#1. Target system / DFT +if( target_system == "CH4"): + PBC=False + ### xyzf="CH4_acct_bfgs_optg.xyz" + basis="aug-ccpvTz" + gauge_LorV="L" + Evector=(0.0, 0.0, 1.0e-3) + DFT='RKS';xc="LDA,VWN"; + mol = gto.M(atom = 'C -0.00002631 0.00024432 0.00007638;'\ + +'H 1.09719302 -0.00099542 -0.00067323;'\ + +'H -0.36460184 1.03512412 0.00149901;'\ + +'H -0.36573517 -0.51759524 0.89561804;'\ + +'H -0.36696120 -0.51556008 -0.89613718', basis="aug-ccpvTz") +elif( target_system == "h-BN"): + PBC=True + ### xyzf="hBN_monolayer_a250.4pm_1x1x1.xyz" + basis="gth-dzvp" + gauge_LorV='V' + ## Evector=(0.0, 1.0e-3, 0.0) + Evector=(0.0, 0.0, 1.0e-3) + DFT='RKS';xc="PBE,PBE";df="FFTDF";pseudo="gth-pbe" + ## nKpoints=[9,9,1];cell_dimension=2 + nKpoints=[3,3,1];cell_dimension=2 + cell = pbcgto.Cell() + cell.build( + atom = '''B 0.00000000 0.00000000 0.00000000; N 1.44568507 0.00000000 0.00000000''', + a=np.array([ [2.168528, -1.252000, 0.000000], [2.168528, 1.252000, 0.000000], [0.000000, 0.000000, 20.00] ]), + basis = basis, + pseudo = pseudo) + ### dict_latticevectors={"a":None};R,Sy=read_xyzf(xyzf,dict=dict_latticevectors) +else: + assert False,"Please set params manually" + +#print(type(Evector)) +#Evector2=[0,0,1e-3] +#print(type(Evector2)) +#print(Evector2.copy()) +#print(Evector.copy()) # ERROR +#if( isinstance(Evector,tuple) ): +# print("tuple->list") +# print(list(Evector).copy()) # OKAY +# Evector3=np.array(Evector2) +# print(Evector3.copy()) # OKAY +# assert False,"" + +#3. rt-propagation +str_dt_as="8" +tm_fs_step=float(str_dt_as)*1e-3 +tm_fs_end=24.0 +propagator="CN" + +#4. externalfield + +#5. dump file output +Nstep_dump=10 #100 +tsecond_dump=3600 # 3600*47 +dumpfilename=None + +#6. additional output control +Nstep_calcEng=None #1 # None # or some integer value +Nstep_calcDOS=None #1 # None +check_timing=None + + + +#6. misc + +if( basis is None ): + if( mol is not None ): + basis=mol.basis + elif( cell is not None): + basis=cell.basis +assert basis is not None,"" + +strfield='E' +Eabs=np.sqrt( np.vdot(Evector,Evector) ) +STRxyz=('x','y','z') +for k in range(3): + if( abs(Evector[k])/Eabs > 1e-3 ): + strfield=strfield+STRxyz[k] +strfield=strfield+("%6.1e"%(Eabs)).strip() + +if( not PBC ): + job="_".join( [TASK, target_system, basis, xc, gauge_LorV+'G', strfield, "dt"+str_dt_as+"as"]) +else: + strKpoints='.'.join( [ '%d'%(nkj) for nkj in nKpoints ] ) + job="_".join( [TASK, target_system, basis, xc, "k"+strKpoints, pseudo, df, gauge_LorV+'G', strfield, "dt"+str_dt_as+"as"]) + +if(restart is not None): + job=job+"_%02d"%(restart) + +rttddft_common.Setup() +rttddft_common.set_job(job) + +## print(job);assert False,""+job + +dmfilepath = job+"_dm.dat" +dumpfilename = job + +dt_AU=tm_fs_step/PhysicalConstants.aut_in_femtosec() + +tm_fs_offset=( None if( restart is None) else params_restart["tm_fs_offset"]) + + +WCt00=time.time() + +## some parameter check ... +if( PBC ): + assert nKpoints is not None,"nKpoints" + + + +set_occ=( None if(restart is None ) else True ) +if(restart is None): + #1. Construct Moldyn object + if( not PBC ): + moldyn=Moldyn( pbc=False, basis=basis, molecule=mol, #xyzf=xyzf, + DFT=DFT, xc=xc, gauge_LorV=None, + fixednucleiapprox=True, dt_AU=dt_AU) + else: + moldyn=Moldyn( pbc=True, basis=basis, pseudo=pseudo, unitcell=cell, #xyzf=xyzf, + gauge_LorV=None,df=df, DFT=DFT, xc=xc, + nKpoints=nKpoints, cell_dimension=cell_dimension, + dt_AU=dt_AU) + + #2. Get rttddft + rttddft=moldyn.gen_rttddft(set_occ=set_occ) + #3. calc GS + moldyn.calc_gs(rttddft) + ## R,Sy=read_xyzf(xyzf);distinctAtms=distinct_set(Sy); + if( PBC ): + if( gauge_LorV == 'V' ): + rttddft.set_constantfield(True) + +else: + # required parameters for restart calc. + assert ( params_restart["moldyn_pscf"] is not None),"" + assert os.path.exists(params_restart["moldyn_pscf"]),"" + assert ( params_restart["tm_fs_offset"] is not None),"" + assert ( params_restart["dmfilepath"] is not None),"" + + moldyn=Moldyn.load(params_restart["moldyn_pscf"]) + rttddft = moldyn.gen_rttddft(set_occ=set_occ) + + tm_fs_offset=float( params_restart["tm_fs_offset"] ) + tm_au_offset=tm_fs_offset/PhysicalConstants.aut_in_femtosec() + dmfilepath=params_restart["dmfilepath"] + + if( Nstep_calcEng is not None ): + if( rttddft.mo_occ is None ): + rttddft.mo_occ = rttddft._mo_occ + calc_mo_energies(moldyn,rttddft,update_rttddft=True) + +calc_OAS(moldyn, rttddft, Evector, gauge_LorV, dmfilepath, + tm_fs_end=tm_fs_end, tm_fs_step=tm_fs_step, tm_fs_offset=tm_fs_offset, + logfile="OAS_"+job+".log", + propagator=propagator, Nstep_dump=Nstep_dump, tsecond_dump=tsecond_dump, WCt00=WCt00, + dumpfilename=dumpfilename, Nstep_calcEng=Nstep_calcEng, + Nstep_calcDOS=Nstep_calcDOS) + diff --git a/pyscf/lib/CMakeLists.txt b/pyscf/lib/CMakeLists.txt index 0ad10308f..bdea6a730 100644 --- a/pyscf/lib/CMakeLists.txt +++ b/pyscf/lib/CMakeLists.txt @@ -151,3 +151,16 @@ set_target_properties (clib_csf PROPERTIES add_subdirectory(sfnoci) +# RT-TDDFT +add_custom_target(make_libpp01 ALL + COMMAND make + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/rttddft/libpp01 + COMMENT "Building libpp01.so using existing Makefile" +) + +add_custom_command(TARGET make_libpp01 POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "Moving .so files to parent directory" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_SOURCE_DIR}/rttddft/libpp01/*.so + ${CMAKE_SOURCE_DIR}/ +) diff --git a/pyscf/lib/rttddft/libpp01/FortInt.h b/pyscf/lib/rttddft/libpp01/FortInt.h new file mode 100644 index 000000000..f969102e5 --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/FortInt.h @@ -0,0 +1,7 @@ +#ifndef _INCLUDE_FortInt_H +#define _INCLUDE_FortInt_H + +#define FortInt_I4 +#define FortInt int + +#endif diff --git a/pyscf/lib/rttddft/libpp01/Gaussian.c b/pyscf/lib/rttddft/libpp01/Gaussian.c new file mode 100644 index 000000000..26377e83f --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/Gaussian.c @@ -0,0 +1,352 @@ +#include +#include +#include +#include +#include "ushort.h" +#include "mathfn.h" +#include "macro_util.h" +#include "dcmplx.h" +#include "dalloc.h" +#include "Gaussian.h" +double calc_Ng(const double alpha,const ushort *pw){ + double prod=1.0;int i; + for(i=0;i<3;i++){ + prod=prod* gamma_hfint(2*pw[i]+1) * pow( ( sqrt(1.0/(2.0*alpha)) ), 2.0*pw[i]+1.0 );} + return prod; +} +double calc_Nl(const double alpha,const int l){ + return 0.5*gamma_hfint(2*l+3)/ pow( sqrt( 2*alpha ), 2*l+3 ); + //prod=HALF*gamma_hfint(2*l+3)/( (sqrt(TWO*alpha))** (2*l+3) ) +} +double calc_Nlx(const double alpha,const int l,const int I){ + return 0.5*gamma_hfint(2*(l+2*I)+3)/ pow( sqrt( 2*alpha ), 2*(l+2*I)+3 ); + //prod=HALF*gamma_hfint(2*l+3)/( (sqrt(TWO*alpha))** (2*l+3) ) +} +/* +see macros in Gaussian.h ... +void Gaussian_toString(Gaussian *G){ + char *ret=ch1alloc(1000+1); + int i,off=0; + for(i=0;iN;i++){ + } +} +void print_Bset(Gaussian **BS,const int Nb,const char *fpath,const char *description){ + FILE *fp=fopen(fpath,"w"); + int ib; + for(ib=0;ibdescription=NULL; + this->N=N;this->Jnuc=Jnuc; + // this->pows=(ushort **)malloc(N*sizeof(ushort *)); + // this->pows[0]=(ushort *)malloc(N*3*sizeof(ushort)); + this->pows=ush2alloc(N,3); + int j,k; + + if(pow_a !=NULL){ + for(j=0;jpows[j][k]=pow_a[j][k]; + } else { + for(j=0;jpows[j][k]=pow1[k]; + } + this->alpha=d1clone(alpha,N); + this->cofs=d1clone(cof,N); + this->R=d1clone(R,3); + this->Ng=d1alloc(N); + for(j=0;jNg[j]=calc_Ng(alpha[j],this->pows[j]); + if(divide_by_Ng){ + for(j=0;jcofs[j]/=sqrt(this->Ng[j]); + } + /* + int i; + for(i=0;iN;i++){ + printf("#new_Gaussian:%p %d %f %f (%f)\n",this,i,this->alpha[i],this->cofs[i],cof[i]); + }*/ + //printf("#new_Gaussian:%p %d,%d,%d %f,%f,%f\n",this,this->pows[0],this->pows[1],this->pows[2],this->R[0],this->R[1],this->R[2]); + return this; +} +SphericalGaussian *new_SphericalGaussian(const double *alpha, const double *R,int l,int m,int N, const double *cof,int Jnuc){ + return new_SphericalGaussianX(alpha,R,l,m,N,cof,Jnuc,0); +} +SphericalGaussian *new_SphericalGaussianX(const double *alpha,const double *R,int l,int m,int N,const double *cof,int Jnuc,int Ipow){ + + SphericalGaussian *this=(SphericalGaussian *)malloc(sizeof(SphericalGaussian)); + this->description=(char *)malloc(60*N); + int jj,off=0; + this->I=Ipow; + this->N=N;this->Jnuc=Jnuc; + this->l=(ushort)l;this->m=m; //printf("#new_SphericalGaussian:%d,%d\n",this->l,this->m);fflush(stdout); + + this->alpha=d1clone(alpha,N); + this->cofs=d1clone(cof,N); + //printf("#new_SphericalGaussian:%d,%d\n",this->l,this->m);fflush(stdout); + __assertf( (this->m>=-(this->l) && this->m<=(this->l)),("wrong m:%d/l=%d",this->m,this->l),-1) + + this->R=d1clone(R,3); + this->Nl=d1alloc(N); int k; + for(k=0;kNl[k]=calc_Nlx(alpha[k],this->l,this->I);// 0.5 Gamma_hfint(2l+3)/ + for(k=0;kcofs[k]/=sqrt(this->Nl[k]); + sprintf(this->description,"l=%d,m=%d,I=%d,N=%d",l,m,Ipow,N);off=strlen(this->description); + int verbose=0; + if(verbose){ + for(jj=0;jjdescription + off,"%12.6f %12.6f %12.6f\n",alpha[jj],cof[jj],this->cofs[jj]);off=strlen(this->description);} + } + //printf("#new_SphericalGaussian:%d,%d\n",this->l,this->m);fflush(stdout); + int i; + if(verbose){ + for(i=0;iN;i++){ + printf("#new_SphericalGaussian:%p %d %f %f %f\n",this,i,this->alpha[i],this->cofs[i],this->cofs[i]*sqrt(this->Nl[i])); + } + } + //printf("#new_SphericalGaussian:%p %d,%d %f,%f,%f\n",this,this->l,this->m,this->R[0],this->R[1],this->R[2]); + return this; +} +Gaussian *Spherical_to_Cartesian(SphericalGaussian *src){ + ushort **Ppows[1]={NULL};double *Pcofs[1]={NULL}; + int Nmult=Xlm_to_Cartesian(src->l,src->m,Ppows,Pcofs); + //printf("#Xlm_to_Cartesian:%d,%d >> %d\n",src->l,src->m,Nmult);fflush(stdout); + ushort **xlmpws=Ppows[0];double *xlmcofs=Pcofs[0]; + // Gaussian with Npgto * N elements + // sh_0.0 : pows[0] cofs[0]*alph[0] + // sh_0.1 : pows[1] cofs[1]*alph[0] ... + const int N_More_A[3]={1,3,6}; + const int N_more=N_More_A[src->I]; + __assertf( (src->I<3),("wrong Ipow:%d",src->I),-1); // here I=0,1,2 (:=i-1) + const int Npgto0 = src->N; + const int npgto1 = Npgto0 * Nmult; + const int Npgto2 = Npgto0 * Nmult * N_more; + + double *alph=d1alloc(Npgto2),*cofs=d1alloc(Npgto2); + ushort **pows=ush2alloc(Npgto2,3); + int I_more; int off=0; + // printf("#%d N_more=%d\n",src->I,N_More_A[src->I]);fflush(stdout); + for(I_more=0;I_moreI==1){ Ipw=I_more;n_add=2;fac=1;} // add 2 to x,y,z ... + else if(src->I==2){ int iarr[12]={ 0,0, 1,1, 2,2, 0,1, 0,2, 1,2}; + Ipw=iarr[2*I_more];Jpw=iarr[2*I_more+1]; fac=( (Ipw==Jpw) ? 1:2 );n_add=2;} + int Ipgto,Jmult,IxJ; + for(Ipgto=0,IxJ=0;Ipgto=0){ pows[ npgto1*I_more + IxJ ][Ipw]+=2;} + if(Jpw>=0){ pows[ npgto1*I_more + IxJ ][Jpw]+=2;} + + double Ng=calc_Ng(src->alpha[Ipgto],pows[IxJ]); + alph[ npgto1*I_more + IxJ] = src->alpha[Ipgto]; + cofs[ npgto1*I_more + IxJ] = src->cofs[Ipgto] * xlmcofs[Jmult]*fac; + /* printf("#%d:%d.%d.%d %f %f",npgto1*I_more + IxJ, + pows[ npgto1*I_more + IxJ ][0], pows[ npgto1*I_more + IxJ ][1], pows[ npgto1*I_more + IxJ ][2], + alph[ npgto1*I_more + IxJ ], cofs[ npgto1*I_more + IxJ ]);*/ + } + } + } + //printf("#generating new..");fflush(stdout); + Gaussian *Ga=new_Gaussian_1( 0, alph,src->R,NULL,pows,Npgto2,cofs,src->Jnuc); + d1free(alph);d1free(cofs);ush2free(pows);alph=NULL;cofs=NULL;pows=NULL; + ush2free(Ppows[0]);d1free(Pcofs[0]);Ppows[0]=NULL;Pcofs[0]=NULL; + Ga->description=ch1clone(src->description); + //printf("#generating new..%p\n",Ga);fflush(stdout); + return Ga; +} +#define SQRDIST(A,B) ( (A[0]-B[0])*(A[0]-B[0]) + (A[1]-B[1])*(A[1]-B[1]) + (A[2]-B[2])*(A[2]-B[2]) ) +double Gaussian_value(Gaussian *G, const double *R){ + int i,N=G->N; + double sqrdist=SQRDIST(R,G->R); + double xA[3]={ R[0]-G->R[0], R[1]-G->R[1], R[2]-G->R[2]}; + double retv=0.0; + for(i=0;ipows[i][dir]);j++)prod*=xA[dir]; + + double dum= prod * (G->cofs[i])*exp(-(G->alpha[i])*sqrdist ); // XXX /sqrt(G->Ng[i]); + retv+=dum; + //printf("#Gaussian_value:%d %f %f %f %f\n",i,dum*sqrt(G->Ng[i]),dum,retv,sqrdist); + } + return retv; +} +void free_Bset(Gaussian **BS,int Nb){ + int i; + // printf("#Freeing Bset:%d....",Nb);fflush(stdout); + for(i=0;ipows,this->alpha,this->cofs);fflush(stdout); + } + free(this->pows[0]);free(this->pows);this->pows=NULL; + if(this->description !=NULL) {free(this->description);this->description=NULL;} + d1free(this->alpha); + d1free(this->cofs); + d1free(this->R); + d1free(this->Ng); + free(this);this=NULL; + if(verbose){ + printf("#freeing Gaussian01:...END\n");fflush(stdout); + } + +} +void free_Gaussian(Gaussian *this){ + free_Gaussian01(this,0); +} +void free_SphericalGaussian(SphericalGaussian *this){ + d1free(this->alpha); + if(this->description !=NULL){free(this->description);this->description=NULL;} + d1free(this->cofs); + d1free(this->R); + d1free(this->Nl); + free(this);this=NULL; + +} +double SphericalGaussian_value(SphericalGaussian *G,const double *R){ + int i,N=G->N; + double polar[3]; + double sqrdist=SQRDIST(R,G->R); + + double xA[3]={ R[0]-G->R[0], R[1]-G->R[1], R[2]-G->R[2]}; + xyz_to_polar(polar,xA);double rxxel=pow(polar[0],G->l); + //printf("#SphericalGaussian:%d,%d\n",G->l,G->m);fflush(stdout); + double Ylm=dSpher(G->l,G->m,polar[1],polar[2]); + double fac =rxxel * Ylm; + double retv=0.0; + for(i=0;icofs[i]*exp(-(G->alpha[i])*sqrdist ); // XXX /sqrt(G->Nl[i]); + retv+=dum; + //printf("#sphGaussian_value:%d %f %f %f %f %f\n",i,dum*sqrt(G->Nl[i]),dum,retv,retv*fac,sqrdist); + } + if(G->I){ + double Rsqr=polar[0]*polar[0]; + for(i=0;iI;i++)retv*=Rsqr; //R^{2*I} + } + return retv*fac; +} + +// +#define PUSH3(arr,p,q,r) { arr[0]=p;arr[1]=q;arr[2]=r; } +int Xlm_to_Cartesian(const int l,const int m,ushort ***pows,double **cofs){ + // on return, ***pows[0]=i2alloc(N,3) + // **cofs[0]=d1alloc(N) and returns N + const double PI=3.1415926535897932384626433832795; + int N; + if(l==0){ N=1; + pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + PUSH3(pows[0][0],0,0,0); + cofs[0][0]=sqrt(1.0/(4.0*PI)); return N; + } + if(l==1){ N=1; + pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); double dum=sqrt(3.0/((4.0d+00)*PI)); + if(m==-1){ PUSH3(pows[0][0],0,1,0); cofs[0][0]=dum; return N;} + else if(m==0){ PUSH3(pows[0][0],0,0,1); cofs[0][0]=dum; return N;} + else if(m==1){ PUSH3(pows[0][0],1,0,0); cofs[0][0]=dum; return N;} + } else if(l==2){ + const int Nret[5]={1,1,3,1,2};int N=Nret[m+2]; + pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + double dum=sqrt( 15.0/(4.0*PI) ); + if(m==-2){ PUSH3(pows[0][0],1,1,0); cofs[0][0]=dum; return N; + } else if(m==-1){ PUSH3(pows[0][0],0,1,1); cofs[0][0]=dum;return N; + } else if(m== 0){ dum=sqrt(5.0/(4.0*PI)); + PUSH3(pows[0][0],0,0,2); cofs[0][0]=dum; + PUSH3(pows[0][1],2,0,0); cofs[0][1]=-0.5*dum; + PUSH3(pows[0][2],0,2,0); cofs[0][2]=-0.5*dum; return N; + } else if(m== 1){ PUSH3(pows[0][0],1,0,1); cofs[0][0]=dum; return N; + } else if(m== 2){ PUSH3(pows[0][0],2,0,0); cofs[0][0]=0.5*dum; + PUSH3(pows[0][1],0,2,0); cofs[0][1]=-0.5*dum; return N;} + } else if(l==3){ + double dum=sqrt(35.0/(32.0*PI)); + if(m==-3){ N=2;pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + PUSH3(pows[0][0],2,1,0); cofs[0][0]= 3*dum; + PUSH3(pows[0][1],0,3,0); cofs[0][1]= -dum; return N; + } else if(m== 3){ N=2;pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + PUSH3(pows[0][0],3,0,0); cofs[0][0]= dum; + PUSH3(pows[0][1],1,2,0); cofs[0][1]= -3*dum; return N; + } else { + N=(m==-2 ? 1:(m==2 ? 2:3)); + pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + dum=sqrt(105.0/(4.0*PI)); + if(m==-2){ PUSH3(pows[0][0],1,1,1); cofs[0][0]=dum; return N; + } else if(m== 2){ PUSH3(pows[0][0],2,0,1); cofs[0][0]=0.5*dum; + PUSH3(pows[0][1],0,2,1); cofs[0][1]=-0.5*dum;return N; + } else { + dum=sqrt(21.0/(32.0*PI)); + if(m==-1){ PUSH3(pows[0][0],0,1,2); cofs[0][0]=4*dum; + PUSH3(pows[0][1],2,1,0); cofs[0][1]=-dum; + PUSH3(pows[0][2],0,3,0); cofs[0][2]=-dum;return N; + } if(m== 1){ PUSH3(pows[0][0],1,0,2); cofs[0][0]=4*dum; + PUSH3(pows[0][1],3,0,0); cofs[0][1]=-dum; + PUSH3(pows[0][2],1,2,0); cofs[0][2]=-dum;return N; + } else { + dum=sqrt(7.0/(16.0*PI)); + PUSH3(pows[0][0],0,0,3); cofs[0][0]=2*dum; + PUSH3(pows[0][1],2,0,1); cofs[0][1]=-3*dum; + PUSH3(pows[0][2],0,2,1); cofs[0][2]=-3*dum; return N; + } + } + } + }else if(l==4){ + double dum; + switch (abs(m)){ + // sqrt(2) times Ylm-prefactor (with sign (-)^{|m|}) ... except m==0 + case(4): dum= (3/16.0)*sqrt(35.0/PI);break; + case(3): dum= (3/8.0)*sqrt(70.0/PI);break; + case(2): dum= (15.0/8.0)*sqrt( 1.0/(5*PI) );break; + case(1): dum= (15.0/8.0)*sqrt( 2.0/(5*PI) );break; + case(0): dum= sqrt(9.0/(4*PI))/8.0;break; + } + switch(m){ + case(-4): N=2; pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + PUSH3(pows[0][0],1,3,0);cofs[0][0]=-4*dum; + PUSH3(pows[0][1],3,1,0);cofs[0][1]= 4*dum; return N; + case( 4): N=3; pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + PUSH3(pows[0][0],0,4,0);cofs[0][0]= dum; + PUSH3(pows[0][1],2,2,0);cofs[0][1]=-6*dum; + PUSH3(pows[0][2],4,0,0);cofs[0][2]= dum; return N; + case(-3): N=2; pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + PUSH3(pows[0][0],2,1,1);cofs[0][0]= 3*dum; + PUSH3(pows[0][1],0,3,1);cofs[0][1]= -dum; return N; + case( 3): N=2; pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + PUSH3(pows[0][0],3,0,1);cofs[0][0]= dum; + PUSH3(pows[0][1],1,2,1);cofs[0][1]=-3*dum; return N; + + case(-2): N=3; pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + PUSH3(pows[0][0],1,1,2);cofs[0][0]= 12*dum; + PUSH3(pows[0][1],3,1,0);cofs[0][1]=-2*dum; + PUSH3(pows[0][2],1,3,0);cofs[0][2]=-2*dum; return N; + case( 2): N=4; pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + PUSH3(pows[0][0],2,0,2);cofs[0][0]= 6*dum; + PUSH3(pows[0][1],4,0,0);cofs[0][1]= -dum; + PUSH3(pows[0][2],0,2,2);cofs[0][2]=-6*dum; + PUSH3(pows[0][3],0,4,0);cofs[0][3]= dum; return N; + + case(-1): N=3;pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + PUSH3(pows[0][0],0,1,3);cofs[0][0]= 4*dum; + PUSH3(pows[0][1],2,1,1);cofs[0][1]=-3*dum; + PUSH3(pows[0][2],0,3,1);cofs[0][2]=-3*dum; return N; + case( 1): N=3;pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + PUSH3(pows[0][0],1,0,3);cofs[0][0]= 4*dum; + PUSH3(pows[0][1],3,0,1);cofs[0][1]=-3*dum; + PUSH3(pows[0][2],1,2,1);cofs[0][2]=-3*dum; return N; + case( 0): N=6;pows[0]=ush2alloc(N,3);cofs[0]=d1alloc(N); + PUSH3(pows[0][0],0,0,4);cofs[0][0]= 8*dum; + PUSH3(pows[0][1],0,4,0);cofs[0][1]= 3*dum; + PUSH3(pows[0][2],4,0,0);cofs[0][2]= 3*dum; + + PUSH3(pows[0][3],2,0,2);cofs[0][3]=-24*dum; + PUSH3(pows[0][4],0,2,2);cofs[0][4]=-24*dum; + PUSH3(pows[0][5],2,2,0);cofs[0][5]= 6*dum; return N; + } + } + __assertf(0,("Xlm_to_Cartesian:%d.%d",l,m),-1); + return -1; +} diff --git a/pyscf/lib/rttddft/libpp01/Gaussian.h b/pyscf/lib/rttddft/libpp01/Gaussian.h new file mode 100644 index 000000000..2eeca4b8b --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/Gaussian.h @@ -0,0 +1,54 @@ +#ifndef INCLUDE_GAUSSIANH +#define INCLUDE_GAUSSIANH +#include +#include +#include +#include "ushort.h" +#include "dcmplx.h" +#include "mathfn.h" +double calc_Ng(const double alpha,const ushort *pows); +double calc_Nl(const double alpha,const int l); + +typedef struct struct_gaussian{ + ushort N,Jnuc,**pows; + double *alpha,*cofs,*R,*Ng; + char *description; +} Gaussian; + +typedef struct struct_spherical_gaussian{ + ushort N,Jnuc,l; int m,I; + double *alpha,*cofs,*R,*Nl; + char *description; +} SphericalGaussian; + +void free_Bset(Gaussian **BS,int Nb); +void free_Gaussian01(Gaussian *this,const int verbose); +void free_Gaussian(Gaussian *this); +void free_SphericalGaussian(SphericalGaussian *this); +#define Gaussian_fprtout(msg,fptr,this) { fprintf(fptr,"#Gaussian_prtout:");fprintf msg;\ +fprintf(fptr,"#Nsh=%d R=(%9.4f %9.4f %9.4f)\n",this->N,this->R[0],this->R[1],this->R[2]);\ +int i;for(i=0;i<(this->N);i++){ fprintf(fptr,"%d: %d.%d.%d %f %f %f\n",\ +i,this->pows[i][0],this->pows[i][1],this->pows[i][2],this->alpha[i],this->cofs[i]*sqrt(this->Ng[i]),this->cofs[i]);}} + +#define BSet_fprtout(msg,fptr,BS,N) { fprintf msg;\ +int ib;for(ib=0;ib<(N);ib++){Gaussian_fprtout((fptr,"#BS_%d",ib),fptr,BS[ib]);}} +#define BSet_fwrite(description,fpath,BS,N) { FILE *fptr1=fopen(fpath,"w");\ +BSet_fprtout((fptr1,"#%s",description),fptr1,BS,N);fclose(fptr1); } + +#define BSet_prtout(msg,BS,N) { printf msg;\ +int ib;for(ib=0;ib<(N);ib++){Gaussian_prtout(("#BS_%d",ib),BS[ib]);}} + +#define Gaussian_prtout(msg,this) { printf("#Gaussian_prtout:");printf msg;\ +printf("#Nsh=%d R=(%9.4f %9.4f %9.4f)\n",this->N,this->R[0],this->R[1],this->R[2]);\ +int i;for(i=0;i<(this->N);i++){ printf("%d: %d.%d.%d %f %f %f\n",\ +i,this->pows[i][0],this->pows[i][1],this->pows[i][2],this->alpha[i],this->cofs[i]*sqrt(this->Ng[i]),this->cofs[i]);}} + +Gaussian *new_Gaussian(const double *alpha,const double *R,const ushort *pw,int N,const double *cof,int Jnuc); +Gaussian *new_Gaussian_1(char divide_by_Ng,const double *alpha,const double *R,const ushort *pow1,ushort **pow_a,int N,const double *cof,int Jnuc); +SphericalGaussian *new_SphericalGaussian(const double *alpha, const double *R,int l,int m,int N, const double *cof,int Jnuc); +SphericalGaussian *new_SphericalGaussianX(const double *alpha,const double *R,int l,int m,int N,const double *cof,int Jnuc,int Ipow); +Gaussian *Spherical_to_Cartesian(SphericalGaussian *src); +double Gaussian_value(Gaussian *G,const double *R); +double SphericalGaussian_value(SphericalGaussian *spg,const double *R); +int Xlm_to_Cartesian(const int l,const int m,ushort ***pows,double **cofs); +#endif diff --git a/pyscf/lib/rttddft/libpp01/Properties.c b/pyscf/lib/rttddft/libpp01/Properties.c new file mode 100644 index 000000000..f8c3b5455 --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/Properties.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include "cstrutil.h" +#include "dalloc.h" +#include "dcmplx.h" +#include "macro_util.h" + +//#include "futils.h" +//#include "flib.h" +//#include "utils.h" +//#include "cutils.h" +//#include "FortInt.h" +#include "Properties.h" +Properties *new_Properties(const char *fpath,int size){ + Properties *ret=(Properties *)malloc(sizeof(Properties)); + ret->size=size; ret->N=0; + ret->keylist=(char **)malloc(size*sizeof(char *));int i;for(i=0;ikeylist[i]=NULL; + ret->values=(char **)malloc(size*sizeof(char *));for(i=0;ivalues[i]=NULL; + ret->fpath=ch1clone(fpath); + return ret; +} +void Properties_update(Properties *this, const char *key,const char *value){ + int i; + for(i=0;iN;i++){ + if(strcmp(this->keylist[i],key)==0)break; + } + if(i>=this->N){ + if(this->N>=this->size){ int newsize=this->size+20; + char **newK=(char **)realloc(this->keylist,(newsize*sizeof(char *)));__assertf(newK!=NULL,("newK"),-1); + this->keylist=newK; + char **newV=(char **)realloc(this->values,(newsize*sizeof(char *)));__assertf(newV!=NULL,("newV"),-1); + this->values=newV; + this->size=newsize; + } + i=this->N; this->N=this->N+1; + this->keylist[i]=ch1clone(key); + } + this->values[i]=ch1clone(value); + return i; +} +char *Properties_getvalue(Properties *this,const char *key){ + int i; + for(i=0;iN;i++){ + if(strcmp(this->keylist[i],key)==0)break; + } + if(i>=this->N) return NULL; + return this->values[i]; +} +void Properties_setvalue(Properties *this, const char *key,const char *type,const void *value){ + char sbuf[50+1]=""; + if(type[0]=='i') { const int *p=(int *)value; sprintf(sbuf,"%d",p[0]);Properties_update(this,key,sbuf);return;} + if(type[0]=='d') { const double *p=(double *)value; sprintf(sbuf,"%24.10e",p[0]);Properties_update(this,key,sbuf);return;} + if(type[0]=='c') { const char *p=(char *)value; sprintf(sbuf,"%c",p[0]);Properties_update(this,key,sbuf);return;} + if(type[0]=='z') { const dcmplx *p=(dcmplx *)value; sprintf(sbuf,"%24.10e %24.10e",__RandI(p[0]));Properties_update(this,key,sbuf);return;} + if(type[0]=='s') { const char *p=(char *)value; Properties_update(this,key,p);return;} + if(type[0]=='I') { int rank=0,*Ndim=parse_ints(&rank,type+1);__assertf(rank==1,(""),-1); + char *sdum=i1toa((int *)value,Ndim[0]);Properties_update(this,key,sdum);free(sdum);return;} + if(type[0]=='D') { int rank=0,*Ndim=parse_ints(&rank,type+1);__assertf(rank==1,(""),-1); + char *sdum=d1toa((double *)value,Ndim[0]);Properties_update(this,key,sdum);free(sdum);return;} + if(type[0]=='Z') { int rank=0,*Ndim=parse_ints(&rank,type+1);__assertf(rank==1,(""),-1); + char *sdum=z1toa((dcmplx *)value,Ndim[0]);Properties_update(this,key,sdum);free(sdum);return;} + __assertf(0,("type:%s",type),-1); +} +int Properties_load(Properties *this, const char *fpath){ + const char *path=( fpath==NULL ? this->fpath:fpath ); + int llenmax=2048;char *sbuf=ch1alloc(llenmax+1),*line=NULL; + FILE *fp=fopen(path,"r");int Nret=0; + while( (line=fgets(sbuf,llenmax,fp))!=NULL ){ + int le=strlen(line); + if(le<1)continue; + int off=0; + while(offfpath:fpath ); + FILE *fp=fopen(path,"w"); + int i; + for(i=0;i<(this->N);i++){ + fprintf(fp,"%s:%s\n",this->keylist[i],this->values[i]); + } + fclose(fp);return this->N; +} + + diff --git a/pyscf/lib/rttddft/libpp01/Properties.h b/pyscf/lib/rttddft/libpp01/Properties.h new file mode 100644 index 000000000..b4a4df5bf --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/Properties.h @@ -0,0 +1,16 @@ +#ifndef _INCLUDE_Properties_H +#define _INCLUDE_Properties_H +typedef struct struct_properties { + char **keylist; + char **values; + int size;int N; + const char *fpath; +} Properties; +Properties *new_Properties(const char *fpath,int size); +void Properties_update(Properties *this, const char *key,const char *value); +char *Properties_getvalue(Properties *this,const char *key); +void Properties_setvalue(Properties *this, const char *key,const char *type,const void *value); +int Properties_load(Properties *this, const char *fpath); +int Properties_save(Properties *this, const char *fpath); + +#endif diff --git a/pyscf/lib/rttddft/libpp01/README_clib_fix20210801a b/pyscf/lib/rttddft/libpp01/README_clib_fix20210801a new file mode 100644 index 000000000..4929434a3 --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/README_clib_fix20210801a @@ -0,0 +1 @@ +xgaussope.c: calc_pbc_overlaps_f01 calc_pbc_overlaps02x_f01 gto_ps_pp_int01.py has DBGNG section.. PLS grep dbgng_libf01 in output log diff --git a/pyscf/lib/rttddft/libpp01/README_pyscf_csrc_20210728 b/pyscf/lib/rttddft/libpp01/README_pyscf_csrc_20210728 new file mode 100644 index 000000000..552f26052 --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/README_pyscf_csrc_20210728 @@ -0,0 +1 @@ +#pyscf_csrc_20210728.tgz Wed, Jul 28, 2021 10:05:20 AM : minor revision of Aind_over_c: dipvel reflects Aind_over_c diff --git a/pyscf/lib/rttddft/libpp01/cConstants.h b/pyscf/lib/rttddft/libpp01/cConstants.h new file mode 100644 index 000000000..1395e0163 --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/cConstants.h @@ -0,0 +1,62 @@ +#ifndef _INCLUDE_cConstants_H +#include "macro_util.h" +#include "FortInt.h" +#define _INCLUDE_cConstants_H + +#define __SQRT2 1.4142135623730950488016887242097 +#define AMUinAU 1822.8884855409495559369254593646 +#define Planck_eVfs 4.1356673336325151050603328445925 +#define HARTREEinEV 27.21138386 +#define PI 3.141592653589793238 +#define __fourPI 12.566370614359172952 +#define EXP_ONE 2.718281828459045235 +#define BOHRinANGS 0.52917720859 +#define AUinFS 0.024188843262 +// hbar/HARTREE = 4.1356673336325151050603328445925/dPI/HARTREEinEV +#define byte char +#define Dlnk double +#define Ilnk int +static char __AtomicSymbols[118][3]={ + "H", "He", + "Li","Be", "B", "C", "N", "O", "F","Ne", + "Na","Mg", "Al","Si", "P", "S","Cl","Ar", + "K","Ca","Sc","Ti", "V","Cr","Mn","Fe","Co","Ni","Cu","Zn","Ga","Ge","As","Se","Br","Kr", + "Rb","Sr", "Y","Zr","Nb","Mo","Tc","Ru","Rh","Pb","Ag","Cd","In","Sn","Sb","Te", "I","Xe", + "Cs","Ba", //56 + "La","Ce","Pr","Nd","Pm","Sm","Eu","Gd","Tb","Dy", "Ho","Er","Tm","Yb","Lu", + "Hf","Ta","W","Re","Os", "Ir","Pt","Au","Hg","Tl","Pb","Bi","Po","At","Rn", + "","","","","","","","","","", "","","","","","","","","","", "",""}; + +static const double __AmassInAMU[118]={ + 1.00790, 4.00260, 6.94000, 9.01218, + 10.81000, 12.01100, 14.00670, 15.99940, + 18.99840, 20.17900, 22.98977, 24.30500, + 26.98154, 28.08550, 30.97376, 32.06000, + 35.45300, 39.94800, 39.09830, 40.08000, + 44.95590, 47.90000, 50.94150, 51.99600, + 54.93800, 55.84700, 58.93320, 58.71000, + 63.54600, 65.38000, 69.73500, 72.59000, + 74.92160, 78.96000, 79.90400, 83.80000, + 85.46780, 87.62000, 88.90590, 91.22000, + 92.90640, 95.94000, 98.90620, 101.0700, +102.9055, 106.4000, 107.8680, 112.4100, +114.8200, 118.6900, 121.7500, 127.6000, +126.9045, 131.3000, // this is Xe(Z=54) +132.9054, 137.3300, +-1,-1,-1,-1,-1, -1,-1,-1,-1,-1, -1,-1,-1,-1,-1, // 57-71 +178.4900, +180.9479, +183.8500, 186.2070, 190.2000, 192.2200, +195.0900, +196.9665, 200.5900, 204.3700, 207.2000, +208.9804, // this is Bi(Z=83) +-1,-1,-1,-1,-1, -1,-1,-1,-1,-1, -1,-1,-1,-1,-1, +-1,-1,-1,-1,-1, -1,-1,-1,-1,-1, -1,-1,-1,-1,-1, +-1,-1,-1,-1,-1}; + +#define __AtSymbolToZnuc(X,nz) { for(nz=0;nz<118;nz++){ if(strcmp(X,__AtomicSymbols[nz])==0)break;} if(nz>=118)nz=-1;else nz++;} +#define __ZnucToAmass(nz) ( __AmassInAMU[((nz)-1)] ) +#define __AtSymbolToAmass(X,val) { int iznuctmp;for(iznuctmp=0;iznuctmp<118;iznuctmp++){ if(strcmp(X,__AtomicSymbols[iznuctmp])==0)break;}\ +if(iznuctmp>=118){ __assertf(0,("unknown alabel:%s\n",X),-1);} val=__AmassInAMU[(iznuctmp)]; } + +#endif diff --git a/pyscf/lib/rttddft/libpp01/cmplx.c b/pyscf/lib/rttddft/libpp01/cmplx.c new file mode 100644 index 000000000..7e9738f7b --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/cmplx.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include + +#include "macro_util.h" +#include "dcmplx.h" + +dcmplx *z1alloc(int n){ + dcmplx *v; + v=(dcmplx *)malloc( (size_t) (n*sizeof(dcmplx)) ); + return v; +} +dcmplx *z1alloc_i(int n,const dcmplx val){ + dcmplx *ret=z1alloc(n); + int i; + for(i=0;i +#include +#include +#include +#include +#include "macro_util.h" +#include "cstrutil.h" +#include "dalloc.h" +#include "dcmplx.h" +#include "xgaussope.h" +int fcountup(const char *fpath, const char incm){ + int retv=0; + FILE *fp=fopen(fpath,"r"); + if(fp==NULL) { retv=0;} + else { char sbuf[21];int ngot=0;long ldum=-1; + while(fgets(sbuf, 20, fp)!=NULL){ int le=strlen(sbuf); + if(le<1)continue;if(sbuf[le-1]=='\n'){ sbuf[le-1]='\0';le--; if(le<1)continue;} + ngot=sscanf(sbuf,"%ld",&ldum);if(ngot){ retv=(int)ldum;break;} + } fclose(fp); + __assertf( ngot,("fcountup:read from %s failed",fpath),1); + } + if(incm){ + retv+=1;fp=fopen(fpath,"w");fprintf(fp,"%d",retv);fclose(fp); + } + return retv; +} + +double z3diff(dcmplx ***a,dcmplx ***b,const int *Ndim,int *maxdiffloc,const char *title){ + int i,j,k;double maxdiff=cabs(a[0][0][0]-b[0][0][0]);int at[3]={0,0,0};double sqresum=0; + for(i=0;imaxdiff){ maxdiff=diff;at[0]=i;at[1]=j;at[2]=k;} + sqresum+=diff*diff; + }}} + if( maxdiffloc != NULL ){ + maxdiffloc[0]=at[0];maxdiffloc[1]=at[1];maxdiffloc[2]=at[2]; + } + if( title !=NULL){ + printf("#z3diff:%s sqrediff %16.6e dist %16.6e [%d][%d][%d] %f+j%f / %f+j%f\n", + title,sqresum,sqrt(sqresum),at[0],at[1],at[2], __CtoRI( a[at[0]][at[1]][at[2]] ), + __CtoRI( b[at[0]][at[1]][at[2]] ) ); + } + return maxdiff; +} +dcmplx ***read_z3f(char *fpath,int *Ndim){ + FILE *fp=fopen(fpath,"r");__assertf( fp!=NULL,("fopen:%s fails",fpath),-1);int kk; + const int llenmax=4096; char *line=NULL,*sbuf=(char *)malloc( (llenmax+1)*sizeof(char) ); + if( Ndim[0]<=0 ){ + while( (line=fgets(sbuf, llenmax, fp))!=NULL ){ + int le=strlen(line);if(le<1)continue; + int off=0; while(off1)Iblc++; nblank=0; + int ngot1=0,jj; + double *dbuf=parse_doubles(&ngot1,line);__assertf( (ngot1%2==0),(""),-1); + ngot1/=2; + for(jj=0;jj=0;i--){ if(line[i]==']'){ le=i;break;} } + } else { + for(i=offset;i0,("parse_ints;%d for %s",n,line+offset),-1); + types[nbuf]=top;lengths[nbuf]=n;bufs[nbuf]=(void *)ibuf;nbuf++; + if(verbose){ printf("#read_file:I:%d:%d %s\n",(nline++),n,i1toa(ibuf,n));} + } else { + double *dbuf=parse_doubles(&n,line+offset); + if( top=='D' || top=='d' ){ + types[nbuf]=top;lengths[nbuf]=n;bufs[nbuf]=(void *)dbuf;nbuf++; + if(verbose){ printf("#read_file:D:%d:%d %s\n",(nline++),n,d1toa(dbuf,n));} + } else if( top=='Z' || top=='z'){ + __assertf( n%2==0,("read_file:odd n=%d",n),-1); + n=n/2; + dcmplx *zbuf=z1alloc(n); + int k;for(k=0;k=lp) return 1; + return 0; +} +double *parse_doubles(int *pnGot,char *org){ + double *dbuf=NULL; + int loop;int N=0; + for(loop=0;loop<2;loop++){ + int i=0, len=strlen(org), nGot=0; + while( i> %lf\n",nGot,i,j,dbuf[nGot]); + if(dbuf!=NULL){ dbuf[nGot]=dum; } + if(igot>0)nGot++; + if( j=0;i--){ if(line[i]==']'){ le=i;break;} } + } else { + for(i=offset;i0,("parse_ints;%d for %s",n,line+offset),-1); + if(verbose){ printf("#read_file:I:%d:%d %s\n",(nline++),n,i1toa(ibuf,n));} + } else { + dbuf=parse_doubles(&n,line+offset); + if( top=='D' || top=='d' ){ + if(verbose){ printf("#read_file:D:%d:%d %s\n",(nline++),n,d1toa(dbuf,n));} + } + } + printf("#%d i:%p d:%p z:%p n=%d\n",nbuf,ibuf,dbuf,zbuf,n);fflush(stdout); + if(nbuf==0) { nAtm=ibuf[0];__assertf(ibuf!=NULL,("nAtm"),-1);} + else if(nbuf==1) { Rnuc=dbuf; __assertf(dbuf!=NULL,("Rnuc..%d",nbuf),-1);} + else if(nbuf==2) { IZnuc=ibuf; __assertf(ibuf!=NULL,("IZnuc..%d",nbuf),-1);} + else if(nbuf==3) { nDa=ibuf[0]; __assertf(ibuf!=NULL,("nDa..%d",nbuf),-1);} + else if(nbuf==4) { distinctIZnuc=ibuf;__assertf(ibuf!=NULL,("spdm..%d",nbuf),-1);} + else if(nbuf==5) { Nsh=ibuf; __assertf(ibuf!=NULL,("Nsh..%d",nbuf),-1);} + else if(nbuf==6) { ell=ibuf; __assertf(ibuf!=NULL,("ell..%d",nbuf),-1);} + else if(nbuf==7) { npGTO=ibuf; __assertf(ibuf!=NULL,("npGTO..%d",nbuf),-1);} + else if(nbuf==8) { alph=dbuf; __assertf(dbuf!=NULL,("alph..%d",nbuf),-1);} + else if(nbuf==9) { cofs=dbuf; __assertf(dbuf!=NULL,("cofs..%d",nbuf),-1);} + else if(nbuf==10) { nAtmB=ibuf[0]; __assertf(ibuf!=NULL,("spdm..%d",nbuf),-1);} + else if(nbuf==11) { RnucB=dbuf; __assertf(dbuf!=NULL,("RnucB..%d",nbuf),-1);} + else if(nbuf==12) { IZnucB=ibuf; __assertf(ibuf!=NULL,("IZnucB..%d",nbuf),-1);} + else if(nbuf==13) { nDb=ibuf[0]; __assertf(ibuf!=NULL,("nDb..%d",nbuf),-1);} + + else if(nbuf==14) { distinctIZnucB=ibuf;__assertf(ibuf!=NULL,("spdm..%d",nbuf),-1);} + else if(nbuf==15) { NshB=ibuf; __assertf(ibuf!=NULL,("spdm..%d",nbuf),-1);} + else if(nbuf==16) { ellB=ibuf; __assertf(ibuf!=NULL,("spdm..%d",nbuf),-1);} + else if(nbuf==17) { n_cols=ibuf;__assertf(ibuf!=NULL,("spdm..%d",nbuf),-1);} + else if(nbuf==18) { npGTOB=ibuf;__assertf(ibuf!=NULL,("spdm..%d",nbuf),-1);} + else if(nbuf==19) { alphB=dbuf; __assertf(dbuf!=NULL,("Rnuc..%d",nbuf),-1);} + else if(nbuf==20) { cofsB=dbuf; __assertf(dbuf!=NULL,("cofsB..%d",nbuf),-1);} + else if(nbuf==21) { spdm=ibuf[0];__assertf(ibuf!=NULL,("spdm..%d",nbuf),-1);} + else if(nbuf==22) { BravisVectors=dbuf;__assertf(dbuf!=NULL,("BravisVectors..%d",nbuf),-1);} + else if(nbuf==23) { Vectorfield=dbuf;__assertf(dbuf!=NULL,("Vectorfield..%d",nbuf),-1);} + + else if(nbuf==24) { nKpoints=ibuf[0];__assertf(ibuf!=NULL,("nKpoints%d",nbuf),-1);} + else if(nbuf==25) { kvectors=dbuf; __assertf(dbuf!=NULL,("kvectors..%d",nbuf),-1);} + else if(nbuf==26) { Lx=ibuf[0];__assertf(ibuf!=NULL,("Lx:nbuf=%d",nbuf),-1);} + else if(nbuf==27) { Ly=ibuf[0];__assertf(ibuf!=NULL,("Ly:nbuf=%d",nbuf),-1);} + else if(nbuf==28) { Lz=ibuf[0];__assertf(ibuf!=NULL,("Lz:nbuf=%d",nbuf),-1);} + else if(nbuf==29) { nCGTO_2=ibuf[0];__assertf(ibuf!=NULL,("nCGTO_1:nbuf=%d",nbuf),-1);} + else if(nbuf==30) { nCGTO_1=ibuf[0];__assertf(ibuf!=NULL,("nCGTO_1:nbuf=%d",nbuf),-1);} + nbuf++; + } + fclose(fp);fp=NULL; + free(sbuf);sbuf=NULL; + calc_pbc_overlaps01(nAtm, Rnuc, IZnuc, nDa, distinctIZnuc, + Nsh, ell, npGTO, alph, cofs, + nAtmB, RnucB, IZnucB, nDb, distinctIZnucB, + NshB, ellB, n_cols, npGTOB, alphB, + cofsB, spdm, BravisVectors, Vectorfield,nKpoints, + kvectors, Lx,Ly,Lz, nCGTO_2, nCGTO_1); +} + + +/* +int main(int narg,char **args){ + char fpath[160]="calc_pbc_overlaps01.in"; + calcone(fpath); + printf("#calcone ends here\n");fflush(stdout); + return 0; + __assertf(0,("end here"),-1); + int bfsz=31; + void **bufs=(void **)malloc( bfsz*sizeof(void *) ); + int *lengths=i1alloc(bfsz); + char *types=ch1alloc(bfsz); + read_file(fpath, bufs,types,lengths,bfsz); + int *ibuf=(int *)bufs[0]; + + printf("i0:%d",ibuf[0]);fflush(stdout); + int i0=ibuf[0]; + int *i3=(int *)bufs[3],*i4=(int *)bufs[4],*i10=(int *)bufs[10], *i26=(int *)bufs[26], *i27=(int *)bufs[27] , *i28=(int *)bufs[28]; + int *i13=(int *)bufs[13]; + int *i21=(int *)bufs[21], *i24=(int *)bufs[24], *i29=(int *)bufs[29], *i30=(int *)bufs[30]; + calc_pbc_overlaps01( i0, (double *)bufs[1], (int *)bufs[2], i3[0], i4[0], + (int *)bufs[5], (int *)bufs[6], (int *)bufs[7], (double *)bufs[8], (double *)bufs[9], + i10[0], (double *)bufs[11], (int *)bufs[12], i13[0],(int *)bufs[14], + (int *)bufs[15], (int *) bufs[16], (int *)bufs[17], (int *)bufs[18], (double *)bufs[19], + (double *)bufs[20], i21[0], (double *)bufs[22], (double *)bufs[23], i24[0], + (double *)bufs[25], i26[0], i27[0], i28[0], + i29[0], i30[0] ); +}*/ +/* const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs, + int nAtmB, double *RnucB, int *IZnucB, int nDb, int *distinctIZnucB, + const int *NshB, const int *ellB, const int *n_cols, const int *npGTOB, const double *alphB, + const double *cofsB, int spdm, double *BravisVectors, double *Vectorfield,int nKpoints, + double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_2, const int nCGTO_1){*/ diff --git a/pyscf/lib/rttddft/libpp01/cstrutil.h b/pyscf/lib/rttddft/libpp01/cstrutil.h new file mode 100644 index 000000000..b2d037f69 --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/cstrutil.h @@ -0,0 +1,20 @@ +#ifndef _INCLUDE_cstrutil_H +#define _INCLUDE_cstrutil_H +#include "dcmplx.h" +int fcountup(const char *fpath, const char incm); +double z3diff(dcmplx ***a,dcmplx ***b,const int *Ndim,int *maxdiffloc,const char *title); +dcmplx ***read_z3f(char *fpath,int *Ndim); +char *write_z3(const char *fpath,dcmplx ***zbuf,const int *Ndim); +int startswith(const char *str,const char *ptn); + +char *get_datetime_x(char *sbuf,const char *format); +char *get_datetime(); +char *z1toa(const dcmplx *a,const int N); +char *i1toa(const int *a,const int N); +char *d1toa(const double *a,const int N); + +int read_file(const char *fpath,void **bufs,char *types,int *lengths,int bfsz); +double *parse_doubles(int *pnGot,char *org); +int *parse_ints(int *N,char *org); // or parseInts_all + +#endif diff --git a/pyscf/lib/rttddft/libpp01/dalloc.c b/pyscf/lib/rttddft/libpp01/dalloc.c new file mode 100644 index 000000000..0bd1b98c4 --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/dalloc.c @@ -0,0 +1,878 @@ +#include +#include +#include +#include +#include "dalloc.h" +#include "macro_util.h" +// #include "dcmplx.h" +// #define dCmplx double complex +#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr + +#ifdef NALLOCTST +#define ALLOCMSG(T,P) fprintf(stdout,"%%c-ALLOC:%s: %p\n",T,P) +#define ALLOCMSG3(T,P,N) fprintf(stdout,"%%c-ALLOC:%s: %p %d\n",T,P,N) +#define DELOCMSG(T,P) fprintf(stdout," %%c-FREE:%s: %p\n",T,P) +#else +#define ALLOCMSG(T,P) +#define ALLOCMSG3(T,P,N) +#define DELOCMSG(T,P) +#endif +#define CABORT(MSG) fprintf(stdout,"!E c-program exitting due to error\n");fprintf(stdout,MSG);fflush(stdout);fflush(stderr);exit(1) +#define CABORT2(MSG,PMT) fprintf(stdout,"!E c-program exitting due to error\n");fprintf(stdout,MSG,PMT);fflush(stdout);fflush(stderr);exit(1) +#define CABORT3(MSG,PMT,ARG) fprintf(stdout,"!E c-program exitting due to error\n");fprintf(stdout,MSG,PMT,ARG);fflush(stdout);fflush(stderr);exit(1) + +#define CKNULPO(v,WHERE) if((void *)v == NULL){CABORT2("null pointer at %s",WHERE);} +#define CKNULPO2(v,WHERE,PMT) if((void *)v == NULL){CABORT3("null pointer at %s %d",WHERE,PMT);} + +static long __Nheap_D1=0, __Nheap_D2=0,__Nheap_D3=0, __Nheap_I1=0, __Nheap_I2=0,__Nheap_I3=0, + __Nheap_L1=0, __Nheap_L2=0,__Nheap_L3=0, __Nheap_UL1=0, __Nheap_UL2=0,__Nheap_UL3=0, + __Nheap_US1=0, __Nheap_US2=0,__Nheap_US3=0, __Nheap_C1=0, __Nheap_C2=0,__Nheap_C3=0; +#define __d1alc_(N) __Nheap_D1++; +#define __d2alc_(N,L) __Nheap_D2++; +#define __d3alc_(N,L,M) __Nheap_D3++; +#define __i1alc_(N) __Nheap_I1++; +#define __i2alc_(N,L) __Nheap_I2++; +#define __i3alc_(N,L,M) __Nheap_I3++; +#define __l1alc_(N) __Nheap_L1++; +#define __l2alc_(N,L) __Nheap_L2++; +#define __l3alc_(N,L,M) __Nheap_L3++; + +#define __ul1alc_(N) __Nheap_UL1++; +#define __ul2alc_(N,L) __Nheap_UL2++; +#define __ul3alc_(N,L,M) __Nheap_UL3++; +#define __ush1alc_(N) __Nheap_US1++; +#define __ush2alc_(N,L) __Nheap_US2++; +#define __ush3alc_(N,L,M) __Nheap_US3++; +#define __ch1alc_(N) __Nheap_C1++; +#define __ch2alc_(N,L) __Nheap_C2++; +#define __ch3alc_(N,L,M) __Nheap_C3++; + +// 2021.05.19: we remove this assertion since it now appears that not necessarily all -alloc- subroutines counts up the allocation. #define __SBTRwCHK( N ) { N--;if(N<0){printf("!E Nheap reaches negative value\n");fflush(stdout);fflush(stderr);exit(1);} } +#define __SBTRwCHK( N ) +#define __d1free_ __SBTRwCHK(__Nheap_D1 ) +#define __d2free_ __SBTRwCHK(__Nheap_D2 ) +#define __d3free_ __SBTRwCHK(__Nheap_D3 ) +#define __i1free_ __SBTRwCHK(__Nheap_I1 ) +#define __i2free_ __SBTRwCHK(__Nheap_I2 ) +#define __i3free_ __SBTRwCHK(__Nheap_I3 ) +#define __l1free_ __SBTRwCHK(__Nheap_L1 ) +#define __l2free_ __SBTRwCHK(__Nheap_L2 ) +#define __l3free_ __SBTRwCHK(__Nheap_L3 ) + +#define __ul1free_ __SBTRwCHK(__Nheap_UL1 ) +#define __ul2free_ __SBTRwCHK(__Nheap_UL2 ) +#define __ul3free_ __SBTRwCHK(__Nheap_UL3 ) +#define __ush1free_ __SBTRwCHK(__Nheap_US1 ) +#define __ush2free_ __SBTRwCHK(__Nheap_US2 ) +#define __ush3free_ __SBTRwCHK(__Nheap_US3 ) +#define __ch1free_ __SBTRwCHK(__Nheap_C1 ) +#define __ch2free_ __SBTRwCHK(__Nheap_C2 ) +#define __ch3free_ __SBTRwCHK(__Nheap_C3 ) + +#define __ush2realc_(N,L,NN,LL) +#define __ul2realc_(N,L,NN,LL) + +dmatr **d2matr(int N){ + dmatr **ret=(dmatr **)malloc( N*sizeof(dmatr *)); + int i; + for(i=0;i +#undef I +#define _I _Complex_I + +// Note: double cabs dcmplx conj are available +#define dcmplx double complex + +extern void zfdot4_(dcmplx *ret,dcmplx *F, dcmplx *f1,dcmplx *f2,double *w,int *N); // see futils.f90 + +#define __RandI(z) creal(z),cimag(z) +#define __CtoRI(z) creal(z),cimag(z) +#define __dcmplx(x,y) ((x)+_I*(y)) + +#define ZabsSQR(v) ( creal(v)*creal(v) + cimag(v)*cimag(v) ) +#define ZsqrDist(a,b) ( creal((a-b))*creal((a-b)) + cimag((a-b))*cimag((a-b)) ) +dcmplx *z1alloc(int n); +dcmplx **z2alloc(int n,int m); +dcmplx ***z3alloc(int n,int m,int l); +dcmplx ***z3alloc_i(int N1,int N2,int N3, dcmplx val); +dcmplx ****z4alloc(int I,int J,int K,int L); +dcmplx *z1alloc_i(int n,const dcmplx val); +void z1free(dcmplx *z); +void z2free(dcmplx **z); +void z3free(dcmplx ***z); +void z4free(dcmplx ****v); +#endif diff --git a/pyscf/lib/rttddft/libpp01/govlp.c b/pyscf/lib/rttddft/libpp01/govlp.c new file mode 100644 index 000000000..d34e1cb34 --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/govlp.c @@ -0,0 +1,596 @@ +#include +#include +#include +#include +#include "dalloc.h" +#include "dcmplx.h" +#include "macro_util.h" +#include "xgaussope.h" +#include "Gaussian.h" +#include "govlp.h" + +void test_nrmz2(){ + const int N=2,Ipow=1; + double alph[2]={1.192, 0.0645},A[3]={0,0,0},cofs[2]={0.7, 0.5}; + double beta[2]={1.868, 0.375 },B[3]={0.645,1.192,0.794}; + Gaussian *sA=Spherical_to_Cartesian( new_SphericalGaussianX(alph,A,0,0,N,cofs,0,Ipow) ); + Gaussian *xB=Spherical_to_Cartesian( new_SphericalGaussianX(beta,B,0,0,N,cofs,0,Ipow) ); + double VecField[3]={0.794,-1.192,0.8848},displ[3]={0,0,0}; + dcmplx v0=Gaussian_overlap(sA,xB,VecField,displ); + dcmplx v1=Gaussian_ovlpNew(sA,xB,VecField,displ); + printf("### %f+j%f / %f+j%f\n", creal(v1),cimag(v1),creal(v0),cimag(v0) ); +} +void test_nrmz1(){ + printf("#test_nrmz1");fflush(stdout);//__assertf(0,(""),-1); + double alph[3]={0.7122640246E+00, 0.2628702203E+00, 0.1160862609E+00}; + double cofs_s[3]={-0.3088441214E+00, 0.1960641165E-01, 0.1131034442E+01}; + double cofs_p[3]={-0.1215468600E+00, 0.5715227604E+00, 0.5498949471E+00}; + double *cofs=cofs_p; + double R[3]={0,0,0};int N=3,Ipow=0; + const double PI=3.1415926535897932384626433832795; + int i,j;double cum=0; + for(i=0;idescription,BS[J]->description,creal(v1),cimag(v1),t_new,creal(v0),cimag(v0),t_old, + creal(v1ZF),cimag(v1ZF), creal(v0ZF),cimag(v0ZF)); + double dev=ZabsSQR((v0-v1));dev=sqrt(dev); + double devZF=ZabsSQR((v0ZF-v1ZF));devZF=sqrt(devZF); + __assertf( (devZF<1.0e-6),("DEV=%e",devZF),-1); + } + } + __assertf(0,("end"),-1); + + for(Ipow=0;Ipow<=2;Ipow++){ + for(el=0;el<=3;el++){ + for(em=-el;em<=el;em++){ + Gaussian *lhs=Spherical_to_Cartesian( new_SphericalGaussianX(alph,A,el,em,3,cofs,0,Ipow)); + int Jpow,l,m; + for(Jpow=0;Jpow<=2;Jpow++){ + for(l=0;l<=3;l++){ + double t0,t1,t2,t_old,t_new; + for(m=-l;m<=l;m++){ + //Gaussian *rhs=Spherical_to_Cartesian( new_SphericalGaussianX(beta,B,l,m,4,cofs,0,Jpow)); + Gaussian *rhs=Spherical_to_Cartesian( new_SphericalGaussianX(beta,A,l,m,4,cofs,0,Jpow)); + t0=__ctime;t1=t0; + dcmplx v0=Gaussian_overlap(lhs,rhs,VecField,displ); + t2=t1;t1=__ctime;t_old=t1-t2; + dcmplx v1=Gaussian_ovlpNew(lhs,rhs,VecField,displ); + t2=t1;t1=__ctime;t_new=t1-t2; + double dev=ZabsSQR((v0-v1));dev=sqrt(dev); + printf("OVLP:%d %d %d * %d %d %d : %f+j%f (%f)/ %f+j%f (%f)\n",Ipow,el,em,Jpow,l,m,creal(v1),cimag(v1),t_new, creal(v0),cimag(v0),t_old); + __assertf(dev<1.0e-6,("wrong OVLP %f / %f+j%f\n",v1,creal(v0),cimag(v0)),-1); + } + } + }}}} + +} +*/ +dcmplx Gaussian_ovlpNew_verbose(Gaussian *lhs,Gaussian *rhs,const double *VecField,const double *displ){ + int i,j; + + const int Nlhs=lhs->N,Nrhs=rhs->N; + dcmplx zsum=0; + for(i=0;iR[0]+displ[0], rhs->R[1]+displ[1], rhs->R[2]+displ[2]}; + dcmplx ovlp=pgovlp(lhs->pows[i],lhs->alpha[i],lhs->R, rhs->pows[j],rhs->alpha[j],B, VecField); + double re=creal(ovlp),im=cimag(ovlp); + if( __isNaNInf(re) || __isNaNInf(im) ){ printf("#pgovlp:NaNinf:%f %f\n",re,im); + pgovlp_(lhs->pows[i],lhs->alpha[i],lhs->R, rhs->pows[j],rhs->alpha[j],B, VecField,1); + __assertf(0,("NaNInf at Gaussian_ovlpNew_verbose"),-1);} + zsum+=(lhs->cofs[i])*(rhs->cofs[j])*ovlp; + } + return zsum; +} +#define _Check_NaN(ztgt) {if(__isNaN(ztgt)){ __assertf(0,("#check_NaN:%f %f ... isnan:%d,%d\n",creal(ztgt),cimag(ztgt),__isNaN(creal(ztgt)),__isNaN(cimag(ztgt))),1);\ +__assertf(( !(__isNaN(creal(ztgt))) && !(__isNaN(cimag(ztgt)))),("_Check_NaN"),-1);} } +// 2021.08.30 revision +// 1: < lhs(r-A) | rhs(r-(B+D)) e^{iA.r} > e^{iKD} +// 2: < lhs(r-(A-D))| rhs(r-B) e^{iA.r} > e^{i(K+A)D} +/* +dcmplx Gaussian_ovlpNew_B(Gaussian *lhs,Gaussian *rhs,const double *VecField,const double *displ){ + int i,j; + const int Nlhs=lhs->N,Nrhs=rhs->N; + dcmplx zsum=0; + for(i=0;iR[0]-displ[0], lhs->R[1]-displ[1], lhs->R[2]-displ[2]}; + dcmplx ovlp=pgovlp(lhs->pows[i],lhs->alpha[i],A, rhs->pows[j],rhs->alpha[j],rhs->R, VecField); + zsum+=(lhs->cofs[i])*(rhs->cofs[j])*ovlp; + } + _Check_NaN(zsum); + return zsum; +} */ +dcmplx Gaussian_ovlpNew(Gaussian *lhs,Gaussian *rhs,const double *VecField,const double *displ){ + int i,j; + + const int Nlhs=lhs->N,Nrhs=rhs->N; + dcmplx zsum=0; + for(i=0;iR[0]+displ[0], rhs->R[1]+displ[1], rhs->R[2]+displ[2]}; + dcmplx ovlp=pgovlp(lhs->pows[i],lhs->alpha[i],lhs->R, rhs->pows[j],rhs->alpha[j],B, VecField); + zsum+=(lhs->cofs[i])*(rhs->cofs[j])*ovlp; + } + _Check_NaN(zsum); + return zsum; +} +dcmplx Gaussian_ovlpNewX(Gaussian *lhs,Gaussian *rhs,const int ixyz,const dcmplx overlap0,const double *VecField,const double *displ){ + int i,j; + + const int Nlhs=lhs->N,Nrhs=rhs->N; + dcmplx zsum=0; + for(i=0;ipows[i][0], lhs->pows[i][1], lhs->pows[i][2] }; + lhs_pows[ixyz]+=1; + for(j=0;jR[0]+displ[0], rhs->R[1]+displ[1], rhs->R[2]+displ[2]}; + dcmplx ovlp=pgovlp( lhs_pows, lhs->alpha[i],lhs->R, rhs->pows[j],rhs->alpha[j],B, VecField); + zsum+=(lhs->cofs[i])*(rhs->cofs[j])*ovlp; + } + } + // we have calculated + zsum+= lhs->R[ixyz] * overlap0; + _Check_NaN(zsum); + return zsum; +} + +#define _INTpow(a,n) ((n)<2 ? ((n)==0 ? 1.0:(a)):((n)==2 ? ((a)*(a)):( (n)==3 ? (a)*(a)*(a):pow(a,n)))) +//#define _INTpow_safe(a,n,wksp) ((n)<2 ? ((n)==0 ? 1.0:(a)):((n)==2 ? ((a)*(a)):( (n)==3 ? (a)*(a)*(a):pow(a,n)))) +dcmplx pgovlp(ushort *xpow_A,const double alph,const double *A, + ushort *xpow_B,const double beta,const double *B,const double *Vecfield){ + return pgovlp_(xpow_A,alph,A,xpow_B,beta,B,Vecfield,0); +} +dcmplx pgovlp_(ushort *xpow_A,const double alph,const double *A, + ushort *xpow_B,const double beta,const double *B,const double *Vecfield,const int verbose){ + double sqrDist=( (A[0]-B[0])*(A[0]-B[0]) + (A[1]-B[1])*(A[1]-B[1]) + (A[2]-B[2])*(A[2]-B[2]) ); + // a*b/(a+b) = a/(a/b+1.0) + double gamma=( beta > alph ? ( alph/(alph/beta + 1.0)):(beta/((beta/alph)+1.0)) ); + + double G[3]={ (alph*A[0]+beta*B[0])/(alph+beta), (alph*A[1]+beta*B[1])/(alph+beta), (alph*A[2]+beta*B[2])/(alph+beta) }; + double G_dot_A= G[0]*Vecfield[0] + G[1]*Vecfield[1] + G[2]*Vecfield[2]; + dcmplx zfac=( cos(G_dot_A)+_I*sin(G_dot_A) ); + + const double Asqr=Vecfield[0]*Vecfield[0] + Vecfield[1]*Vecfield[1] + Vecfield[2]*Vecfield[2]; + const char zerofield=(Asqr<1.0e-20); + // - 0.25*Asqr/(alph[0]+alph[1])); + const double expofac=exp(-gamma*sqrDist - 0.25*Asqr/(alph+beta)); + char dbgng=1; + int dir; + dcmplx prod=1.0; + if(verbose){ printf("#pgovlp: sqrDist:%f Asqr:%f gamma:%f G:%f,%f,%f zfac:%f %f\n",sqrDist,Asqr,gamma,G[0],G[1],G[2],creal(zfac),cimag(zfac));fflush(stdout);} + for(dir=0;dir<3;dir++){ + dcmplx zsum=0; + double Gd=(alph*A[dir]+beta*B[dir])/(alph+beta); + double GA=Gd-A[dir], GB=Gd-B[dir]; + const int a=xpow_A[dir],b=xpow_B[dir];const int el=a+b; + int j,k,m; + if(fabs(GA)<1.0e-8){ + //printf("#Case GA==0..\n");fflush(stdout); // const double invsqrt_alph_plus_beta = sqrt(1/(alph+beta)); + for(m=a;m<=el;m++){ // l_nCk(a,j) * l_nCk(b,m-j) * pow( GA, a-j) * pow( GB, b-m+j ) + if(zerofield && m%2)continue; + // printf("#dir=%d m=%d / a=%d b=%d\n",dir,m,a,b); + // j==a only. here MAX(0,m-b)<= j + j=a;k=m-j; + dcmplx zdum= l_nCk(b,(m-j)) * _INTpow( GB, b-k ); // pow(GA,a-j)==1 + // double argIpw=sqrt(1/(alph+beta)); + zdum*=gaussian_integ1D_vcfield_((alph+beta),m,Vecfield[dir]); //gamma_hfint(m+1)*_INTpow( argIpw, m+1 ); + if(verbose){ dcmplx cdmy=gaussian_integ1D_vcfield_verbose_((alph+beta),m,Vecfield[dir]); + printf("#pgovlp:m=%d:a=%d,b=%d, %d_C_%d:%ld cdmy:%f %f\n",m,a,b, b,m-j,l_nCk(b,m-j), creal(cdmy),cimag(cdmy) );fflush(stdout);} + zsum+=zdum;// printf("j=%d k=%d %f %f %f\n",j,k,dum,sum,l_nCk(b,(m-j)) * pow( GB, b-k )*pow(GA,(a-j))*pow(GB,b-k) ); + } + } else { + double GBoverGA=GB/GA; + if(verbose){ printf("#pgovlp: GBoverGA:%f %f/%f\n",GBoverGA,GB,GA);fflush(stdout);} + // expand (y+GA)**a ... + const int m_skip=(zerofield ? 2:1); + for(m=0;m<=el;m+=m_skip){ // collecting term with y**m j from a, m-j from b.. + const int jmin=__MAX( (m-b), 0); + const int jmax=__MIN( a, m); + double cum=0; + double fac=pow(GA, a-jmin)*pow(GB, b-m+jmin); + for(j=jmin;j<=jmax;j++){ + double dum=l_nCk(a,j) * l_nCk(b,m-j) * fac; + cum+= dum; + if(verbose){ printf("#pgovlp:%d: %d C %d:%ld %d C %d:%ld fac:%f\n",m, a,j,l_nCk(a,j), b,m-j,l_nCk(b,m-j), fac);fflush(stdout);} + /* if(dbgng){ + double ref=l_nCk(a,j) * l_nCk(b,m-j) * pow(GA,(a-j)) * pow(GB,(b-m+j)); + double dev1=fabs(ref-dum);double scle=0.50*( fabs(ref)+fabs(dum) ); + if(scle>1.0) dev1=dev1/scle; + // this fails if ref or dum is of size ~ 1e+10 __assertf( fabs(ref-dum)<1.0e-6,("#pgovlp: dum=%f / ref=%f %d %d %d %d %f %f fac=%f",dum,ref, a,j,b,m-j, pow(GA,(a-j)), pow(GB,(b-m+j)), fac),-1); + __assertf( dev1<1.0e-6,("#pgovlp: dum=%f / ref=%f : dev=%e (scle=%e) %d %d %d %d %f %f fac=%f",dum,ref,dev1,scle, a,j,b,m-j, pow(GA,(a-j)), pow(GB,(b-m+j)), fac),-1); + } */ + fac*=GBoverGA; // for next step + } + zsum+= cum* gaussian_integ1D_vcfield_((alph+beta),m,Vecfield[dir]); //gamma_hfint(m+1)*_INTpow( sqrt(1/(alph+beta)),m+1 ); + if(verbose){ printf("#pgovlp:%d: %f %f\n",m,creal(gaussian_integ1D_vcfield_((alph+beta),m,Vecfield[dir])), + cimag(gaussian_integ1D_vcfield_((alph+beta),m,Vecfield[dir])));fflush(stdout);} + + } + } + prod*=zsum; + } + dcmplx retv=prod*expofac*zfac; + +/* double absG=sqrt(G[0]*G[0] + G[1]*G[1] + G[2]*G[2]),absA=sqrt(Asqr); + if( absG>1.0e-6 && absA>1.0e-6 && fabs(prod*expofac)>1.0e-7){ + printf("#pgovlp:|G|=%9.4f |A|=%9.4f GdotA=%9.4f AB=%f zf=%f,%f ovlp=%f ret=%f,%f\n", + absG, absA, G_dot_A,sqrt(sqrDist),creal(zfac),cimag(zfac),prod*expofac,creal(retv),cimag(retv));} */ + //printf("#zfac:%f %f*j%f\n",G_dot_A,creal(zfac),cimag(zfac)); + return retv; + //return prod*expofac*zfac; +} + + +void test_ovlpx(Gaussian **BS1,int nBS1, Gaussian **BS2, int nBS2, const double *BravaisVectors){ + const double *ax=BravaisVectors, *ay=BravaisVectors+3, *az=BravaisVectors+6; + int ilh,jrh; double h,h0=0.05;int jh,nh=5;dcmplx vals[5];int Idspl;int Ixyz; double wc0,wc1; + double Aref[3]={0.645, -0.3776, 0.1192}; + dcmplx refv[4];const char revision[3]=".1";//.1: we fixed Gaussian_ovlpNew and Gaussian_ovlpNewX .. + char fpath[40];sprintf(fpath,"test_ovlpx%s.log",revision);int seqno=0; + for(ilh=0,seqno=0;ilhR;double Rlb[3],Rrt[3]; + double B[3]={ rhs->R[0]+displ[0],rhs->R[1]+displ[1], rhs->R[2]+displ[2]}; + + int i; double bmin,amin; + bmin=rhs->alpha[0];for(i=1;iN;i++) bmin=__MIN(rhs->alpha[i],bmin); + amin=lhs->alpha[0];for(i=1;iN;i++) amin=__MIN(lhs->alpha[i],amin); + int kk;for(kk=0;kk<3;kk++){ Rlb[kk]=__MIN( B[kk]-scale/sqrt(bmin), A[kk]-scale/sqrt(amin)); + Rrt[kk]=__MAX( B[kk]+scale/sqrt(bmin), A[kk]+scale/sqrt(amin)); } + double dvol=h*h*h; + int N[3];for(kk=0;kk<3;kk++){ N[kk]=(int) ceil( (Rrt[kk]-Rlb[kk])/h );} + double R[3];double re=0.0,im=0.0;double AxR[3]={0,0,0};int I,J,K;int on_edge=0; double edge_max=0.0; + double edgesum_re=0,edgesum_im=0; + printf("#nmrinteg gridsize:%d,%d,%d\n",N[0],N[1],N[2]); + if(Ixyz_or_0==0){ + for(I=0;IB+displ) + double vrh=Gaussian_value(rhs, Rrhs); double arg=AxR[0]+AxR[1]+AxR[2]; + double prd=vlh*vrh; double xi=prd*cos(arg),eta=prd*sin(arg); + re+= xi; im+= eta; + if(on_edge){ edge_max=__MAX(edge_max,prd); edgesum_re+=xi; edgesum_im+=eta;} + }}} + } else { + const int ixyz=Ixyz_or_0-1; + for(I=0;IB+displ) + double vrh=Gaussian_value(rhs, Rrhs); double arg=AxR[0]+AxR[1]+AxR[2]; + double prd=vlh*vrh*R[ixyz]; double xi=prd*cos(arg),eta=prd*sin(arg); + re+= xi; im+= eta; + if(on_edge){ edge_max=__MAX(edge_max,prd); edgesum_re+=xi; edgesum_im+=eta;} + }}} + } + double wc1=__ctime; + *pWalltime=(wc1-wc0);*pEdge_max=edge_max;*pEdge_sum=( edgesum_re*dvol+_I*(edgesum_im*dvol) ); + printf("#nmrinteg gridsize:%d,%d,%d elapsed:%f\n",N[0],N[1],N[2],wc1-wc0); + return re*dvol+_I*(im*dvol); + +} +// \int dx (x**ell) exp(-gamma*(x**2))e^{iVx} without exp(-0.25*(V**2)/gamma ) +// this replaces (Gamma_hfint(m+1)*pow( sqrt(1/gamma),m+1 ) in presence of Vector field ... +// !!! NOTE WE DO NOT INCLUDE exp(-0.25*(A-dot-A)/gamma ) here !!! +// ell==0 sqrt(pi)*sqrt(1/gamma) +// ell==1 sqrt(pi)*sqrt(1/gamma) * (iV/2gamma) +dcmplx gaussian_integ1D_vcfield_(const double gamma, const int ell, const double Vmu){ + const double sqrt_pi=1.7724538509055160272981674833411; + const double Vmu_TINY=1.0e-20; + if(ell<2){ if(ell==0) return sqrt_pi*sqrt(1.0/gamma); + else return sqrt_pi*sqrt(1.0/gamma)*(0.5*Vmu/gamma)*_I;} + if(fabs(Vmu) TOL ){ + double scalefac2[2]={scalefac[0]*1.50, scalefac[1]*0.66666}; + dcmplx refr2=nmr_gaussian_integ1D_vcfield(gamma, ell, Vmu, scalefac2); + double dev2=cabs(refr2-testee); + fprintf(fp," %3d %16.8f %16.8f %16.8f %16.8f %14.4e %16.8f %16.8f %14.4e\n", + ell, creal(testee),cimag(testee), creal(refr2),cimag(refr2),dev2, + creal(refr),cimag(refr),dev,( dev2=TOL)nerr++; + } else { + fprintf(fp," %3d %16.8f %16.8f %16.8f %16.8f %14.4e\n", + ell, creal(testee),cimag(testee), creal(refr),cimag(refr),dev); + } + } + fclose(fp); + system("ls -ltrh dbg_gaussian_integ1D_vcfield.log"); + return nerr; +} + +// \int dx x^{ell} e^{-\gamma x**2 } e^{iVmu x} +// = +// obviously, ell == 0 : \sqrt(pi/gamma) etc +// for Vmu==0 : Gamma_hfint(ell+1) \sqrt(1/gamma)**(ell+1) +dcmplx gaussian_integ1D_vcfield_verbose_(const double gamma, const int ell, const double Vmu){ + printf("#gaussian_integ1D_vcfield_verbose_:%f %d %f\n",gamma,ell,Vmu);fflush(stdout); + const double sqrt_pi=1.7724538509055160272981674833411; + if(ell<2){ if(ell==0) return sqrt_pi*sqrt(1.0/gamma); + else return sqrt_pi*sqrt(1.0/gamma)*(0.5*Vmu/gamma)*_I;} + if(fabs(Vmu)<1.0e-9){ double argIpw=sqrt(1/gamma); return gamma_hfint(ell+1)*_INTpow( argIpw, (ell+1) );} + int j; + double inv_gamma = 1.0/gamma; + + // overall factor _I**ell ... + dcmplx zfac=1; + switch (ell%4){ + case(1):zfac=_I;break; + case(2):zfac=(-1.0);break; + case(3):zfac=(-_I);break; + } + double arg_intpow=0.5*Vmu*inv_gamma; + double dum = sqrt_pi * sqrt( inv_gamma ) * _INTpow( arg_intpow, ell); + printf("#gaussian_integ1D_vcfield_verbose_:arg:%f dum:%f\n",arg_intpow,dum);fflush(stdout); + //#gaussian_integ1D_vcfield_verbose_:arg:0.000000 dum:0.000000 + double cum = dum; + double fac = -4.0*gamma/(Vmu*Vmu); double hfint=0.50; // -(0.5*Vmu*inv_gamma)^{-2}/gamma; + for(j=2;j<=ell;j+=2){ + dum*= fac * hfint; + printf("#gaussian_integ1D_vcfield_verbose_:j:%d dum:%f\n",j,dum);fflush(stdout); + cum += l_nCk(ell,j)*dum; // ell_C_j * dum*(hfint*sqrt_pi*( + hfint+=1.0; + } + return cum*zfac; +} \ No newline at end of file diff --git a/pyscf/lib/rttddft/libpp01/govlp.h b/pyscf/lib/rttddft/libpp01/govlp.h new file mode 100644 index 000000000..6f5b5293b --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/govlp.h @@ -0,0 +1,17 @@ +#ifndef _INCLUDE_govlp_H +#define _INCLUDE_govlp_H +dcmplx Gaussian_ovlpNew_B(Gaussian *lhs,Gaussian *rhs,const double *VecField,const double *displ); +dcmplx Gaussian_ovlpNew(Gaussian *lhs,Gaussian *rhs,const double *VecField,const double *displ); +dcmplx Gaussian_ovlpNewX(Gaussian *lhs,Gaussian *rhs,const int ixyz,const dcmplx overlap0,const double *VecField,const double *displ); +dcmplx pgovlp(ushort *xpow_A,const double alph,const double *A, + ushort *xpow_B,const double beta,const double *B,const double *Vecfield); +dcmplx pgovlp_(ushort *xpow_A,const double alph,const double *A, + ushort *xpow_B,const double beta,const double *B,const double *Vecfield,const int verbose); +void test_ovlpx(Gaussian **BS1,int nBS1, Gaussian **BS2, int nBS2, const double *BravaisVectors); +dcmplx nmrinteg_ovlp1(double h,Gaussian *lhs,Gaussian *rhs,const double scale,const int Ixyz_or_0,const double *VecField,const double *displ, + double *pWalltime, double *pEdge_max, dcmplx *pEdge_sum); +dcmplx gaussian_integ1D_vcfield_(const double gamma, const int ell, const double Vmu); +dcmplx Gaussian_ovlpNew_verbose(Gaussian *lhs,Gaussian *rhs,const double *VecField,const double *displ); +dcmplx gaussian_integ1D_vcfield_verbose_(const double gamma, const int ell, const double Vmu); +int dbg_gaussian_integ1D_vcfield(const double gamma,const int elmax,const double Vmu,const double *scalefac); +#endif diff --git a/pyscf/lib/rttddft/libpp01/macro_util.h b/pyscf/lib/rttddft/libpp01/macro_util.h new file mode 100644 index 000000000..6dea5f316 --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/macro_util.h @@ -0,0 +1,183 @@ +#ifndef MACRO_UTILH +#define MACRO_UTILH +#include + +#define _I1Free(buf) {i1free(buf);buf=NULL;} +#define _D1Free(buf) {d1free(buf);buf=NULL;} +#define _Z1Free(buf) {z1free(buf);buf=NULL;} +#define _Ch1Free(buf) {ch1free(buf);buf=NULL;} + +#define _I2Free(buf) {i2free(buf);buf=NULL;} +#define _D2Free(buf) {d2free(buf);buf=NULL;} +#define _Z2Free(buf) {z2free(buf);buf=NULL;} +#define _Ch2Free(buf) {ch2free(buf);buf=NULL;} + +#define __fprtdtme(fptr1732,strheader,strtrailer) {time_t time_t_instance_2718 = time(NULL); struct tm struct_tm_instance_31415 = *localtime(&time_t_instance_2718);\ +fprintf(fptr1732,"%s%04d%02d%02d%c%02d%02d%02d%s", strheader,struct_tm_instance_31415.tm_year + 1900, struct_tm_instance_31415.tm_mon + 1, struct_tm_instance_31415.tm_mday, '_', struct_tm_instance_31415.tm_hour, struct_tm_instance_31415.tm_min, struct_tm_instance_31415.tm_sec,strtrailer);} + +//extern void fflush_(void); +// cimag(PBCovlps[kkp]) for kkp in range(nKpoints) +#define ___prtI2xx(msg,A,Ld,Ndim) {printf("#prtI2xx:");printf msg;int ii,iixjj;for(ii=0,iixjj=0;ii<(Ld);ii++){int jj;for(jj=0;jj retv){ jjat=itrt;retv=(val_at_jj);}}} +#define __minval(retv,jjat,itrt,val_at_jj,jjINI,jjUPL) {int itrt=jjINI; retv=val_at_jj; jjat=(jjINI);\ +for( itrt=(jjINI)+1; itrt<(jjUPL); itrt++ ){ if( (val_at_jj) < retv){ jjat=itrt;retv=(val_at_jj);}}} + +#ifndef dmatr + #define dmatr double +#endif +#ifndef imatr + #define imatr int +#endif +#define __FLOOR(a) ((a)<0 ? (-((int)(-a))-1):(int)(a)) +#define ___DBGLGR(msg) {printf("#DBGLGR:"); printf msg;fflush(stdout);} +#define __spdf_to_el(c) ((c)=='s'?0:((c)=='p'?1:((c)=='d'?2:((c)=='f'?3:((c)=='g'?4:(printf("macro_util.h.spdf_to_el:illegal arg for spdf:%c\n",(c)),fflush(stdout),exit(1),-999) ))))) +//#define __spdf_to_el(c) ((c)=='s'?0:((c)=='p'?1:((c)=='d'?2: (int)((c)-'f')+3))) +#define __el_to_spdf(l) ((l)<3 ? ((l)==0 ? 's':((l)==1 ? 'p':'d') ): (char)('f'+(char)((l)-3))) +/* #define __Enuc( ret, Z, R, Na, dum,ja,ka,kk) {\ + ret=0.0;for(ja=0;ja<(Na);ja++){ for(ka=0;ka=(N)){ret=-1;} } +#define __hasNaNinf(ret,A,N) { ret=0;int k_hasnaninf;for(k_hasnaninf=0;k_hasnaninf<(N);k_hasnaninf++){if(__isNaNInf(A[ k_hasnaninf ]))break;}if( k_hasnaninf <(N)){ret=1;} } +#define __d1dff_max(ret,at,A,B,N,kk) { at=0;ret=fabs(A[at]-B[at]);for(kk=0;kk<(N);kk++){ if(fabs(A[kk]-B[kk])>ret){ ret=fabs(A[kk]-B[kk]);at=kk;} } } +#define __count(ret,b_kk,N,kk) { ret=0; for(kk=0;kk<(N);kk++) { if( b_kk ) ret++; } } +#define __ctime ((double)clock())/CLOCKS_PER_SEC +#define __isNaN(v) ( (v)!=(v) ) +#define __isInf(v) ( ((v)+(v))==(v) && ( (v)>1 || (v)<(-1)) ) +#define __isNaNInf(v) ( __isNaN(v) || __isInf(v) ) +#define __opt_dot(dum,A,B,N) { int __opt_dot_k; dum=0; for(__opt_dot_k=0;__opt_dot_k<(N);__opt_dot_k++){ dum+=A[__opt_dot_k]*B[__opt_dot_k]; } } +#define __isDigit(c) ('0'<=(c) && (c)<='9') +#define __isDnumeric(c) ( __isDigit(c) || (c)=='-' || (c)=='+'|| (c)=='.' ||(c)=='E' ||(c)=='e') +#define __isDnumeric1(c,nsgn,ndot,nexpo) ( __isDigit(c) || ((c)=='-' && (++nsgn)==1) || ((c)=='+'&& (++nsgn)==1)|| ((c)=='.' && (--ndot)==1) ||( (c)=='E' && (++nexpo)==1 && ( (nsgn=0)==0 ) ) || ( (c)=='e' && (++nexpo)==1 && ((nsgn=0)==0) ) ) + +#define __isInumeric(c) ( __isDigit(c) || (c)=='-' || (c)=='+') +#define __isAlphabet(c) ( 'a'<=(c)<='z' || 'A'<=(c)<='Z' ) + +#define __sumof(ret,Ajj,N,jj) { ret=0; for(jj=0;jj<(N);jj++){ ret+=Ajj; } } +#define __a1sum(ret,A,N,kk) { ret=0; for(kk=0;kk<(N);kk++) ret+=A[kk]; } +#define __maxv(ret,Akk,N,kk) { kk=0;ret=(Akk);for(kk=1;kk<(N);kk++){ if( (Akk) > ret )ret=(Akk); } } +#define __maxvAt(ret,at,Akk,N,kk) { kk=0;at=0;ret=(Akk);for(kk=1;kk<(N);kk++){ if( (Akk) > ret ){ ret=(Akk);at=kk; } } } +#define __minv(ret,Akk,N,kk) { kk=0;ret=(Akk);for(kk=1;kk<(N);kk++){ if( (Akk) < ret )ret=(Akk); } } +#define __minvAt(ret,at,Akk,N,kk) { kk=0;at=0;ret=(Akk);for(kk=1;kk<(N);kk++){ if( (Akk) < ret ){ ret=(Akk);at=kk; } } } + +#define __c_toUpperCase(c) ( ((c)>='a' && (c)<='z') ? (c)+('A'-'a'):(c) ) +#define __c_toLowerCase(c) ( ((c)>='A' && (c)<='Z') ? (c)-('A'-'a'):(c) ) +#define __toUpperCaseN(ret,s,kk) { for(kk=0;kk(w) ){ printf("#assert_Dev0;%lf deviates from %lf by %e\n",v,shdb,fabs(v-shdb) );__assertf(0,msg,( ((e)>=0 && fabs((v)-(shdb))>(e)) ? (-1):1) ); } } +#define __DBGLGR( msg ) { printf msg; fflush(stdout); } +#define __seekMaxAbs(R,J,A,L,kk) { R=fabs(A[0]);J=0;for(kk=0;kkR)){J=kk;R=fabs(A[kk]);} } } +// 1676581944693513195484 +//static char _abortAt_cbuf[32]; +//#define __abortAt(msg) { for(kk=0;kk<999;kk++){ getarg_(&kk,-abortAT_); +#define __abort(msg) { printf("#c abort:Aborting..");printf msg; fflush(stdout); fflush(stderr); exit(1); } +#define __a1eqlAt(A,B,L,iat) { for(iat=0;iat=L)iat=-1; } +#define __a1NeqAt(A,B,L,iat) { for(iat=0;iat=L)iat=-1; } +#define __checkNaNinf( lvl, ttl, A, L, kk ) { for(kk=0;kk<(L);kk++) if(__isNaNInf(A[kk])){ __assertf(0,("NaNinf@%s,%d:%e\n",ttl,kk,A[kk]),lvl)} } + +#define __checkNaNinfx( lvl, ttl, A, L, kk ) { for(kk=0;kk<(L);kk++) if(__isNaNInf(A[kk])){\ + printf("#checkNaNinfx:%f @%d..",A[kk],kk);printf ttl;__assertf(0,("NaNinf@%d:%e\n",kk,A[kk]),lvl)} } + +#define __CheckPoint(key,msg) { char __CheckPoint_buffer=ch1alloc(64);\ + if( cseekarg("-AbortAt",__CheckPoint_buffer,64) ){\ + if(strcmp(key,__CheckPoint_buffer)==0 ){ printf("AbortAt CheckPoint:%s\n",key);__abort(msg);}\ + else printf("#CheckPoint: passing through %s\n");}} +#define __CheckPt(key) __CheckPoint(key,("")); +#define ___prtI1(msg,A,L) { printf msg;int kkprti1; for(kkprti1=0;kkprti1M)printf("...%d-th:%f ",L-1,A[L-1]);printf("\n");} +#define __prtI1(msg,A,L,kk) { printf msg; for(kk=0;kk>>\n"); for(jj=0;jj>>\n"); for(jj=0;jj>>\n"); for(jprtfd2=0;jprtfd2>>\n"); for(jprtfd2=0;jprtfd2v ? (vmin=v,iat=i, 1):0 ) +#define __updMax(i,v,iat,vmx) ( (vmx)=L)k=-1; } +#define __A1comp(k,A,B,L) { k=L-1;while( A[k]==B[k] && k>=0)k--; k=( k<0 ? 0:( A[k]=L); } +#define __seekA2(i,vec,U,Nv,Ld,kk,idum) { for(i=0;i=Nv)i=-1; } +#define __append_A2(TYPE, elmt,Ld, buf,len,bufsz,inc,dflt,jj,kk) { \ +if(len>=bufsz){ TYPE tmpbf1=NULL; tmpbf1=(TYPE)realloc(buf[0],(bufsz+inc)*Ld); free(buf); buf=(TYPE *)malloc( (bufsz+inc)*sizeof(TYPE)); \ + buf[0]=tmpbf1;for(jj=1;jj<(bufsz+inc);jj++)buf[jj]=buf[jj-1]+Ld;\ + for(jj=bufsz;jj<(bufsz+inc);jj++)for(kk=0;kk0 ? (int)((v)+0.50):(int)((v)-0.50) ) +#define __cvt_fstr(dir,org,len,kk) { if(dir<0){ for(kk=len-1;kk>=0;kk--){if(org[kk]=='\0')org[kk]=' ';break;} }\ +else{ for(kk=len-1;kk>=0;kk--)if(org[kk]!=' ')break; if(kk(b) ? (b):(a) ) +#define __ijAsym(i,j,sg) ((j)<(i) ? (sg=1,((i)-1)*(i)/2+(j)) : (sg=-1,((j)-1)*(j)/2+(i)) ) +#define __ijSyn(i,j) ( (j)<(i) ? (i)*((i)+1)/2+(j) : (j)*((j)+1)/2 + (i) ) +#define __CHECK_DEV(msg,a,b) { if(fabs((a)-(b))>1.0e-07){ printf msg;printf("#CHECK_DEV:%f %f\n",a,b); } } +#define __DBGPRNT(msg) { printf("###DBGPRNT>>>>\n");printf msg; fflush(stdout); } +#define __print_legend( content, bool ) if( bool ){ printf content;printf("\n"); } +#define __countChar( ret, src, c, kk) { ret=0; kk=-1; while( src[++kk]!='\0'){ if(src[kk]==c)ret++; } } +#define __pythag(a,b) (fabs(a)>fabs(b) ? fabs(a)*sqrt(1.0+(b/a)*(b/a)):\ +((b)==0.0 ? 0.0:fabs(b)*sqrt(1.0+(a/b)*(a/b))) ) + +#endif diff --git a/pyscf/lib/rttddft/libpp01/makefile b/pyscf/lib/rttddft/libpp01/makefile new file mode 100644 index 000000000..0162c338b --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/makefile @@ -0,0 +1,50 @@ +.SUFFIXES: +.SUFFIXES: .f90 .f .o .c +.f.o: + gfortran -c -Wall $< +.f90.o: + gfortran -c -Wall $< +.c.o : + gcc -fPIC -Wall -lm -c $< + + + +libpp01:xgaussope.o Gaussian.o dalloc.o mathfn.o cmplx.o govlp.o cstrutil.o Properties.o + gcc -Wall -shared -o $@.so $^ $(GOPT) -lm -llapack -lblas -lgfortran + +test2:xgaussope.o Gaussian.o dalloc.o mathfn.o cmplx.o govlp.o cstrutil.o Properties.o + gcc -Wall -o $@.x $^ $(GOPT) -lm -llapack -lblas -lgfortran + ls -ltrh $@.x + +MAIN_OBJ=Gaussian.o xgaussope.o testmain.o dalloc.o mathfn.o cmplx.o +test_main: $(MAIN_OBJ) + gcc -Wall -Wall -o $@.x $^ $(GOPT) -lm -llapack -lblas -lgfortran + ls -ltrh $@.x +.PHONY: clean +clean: + @rm -f *.o *.mod + +#testlib:zgaussope.o Gaussian.o dalloc.o mathfn.o cmplx.o govlp.o cstrutil.o Properties.o +# gcc -Wall -shared -o $@.so $^ $(GOPT) -lm -llapack -lblas -lgfortran + +testread:cstrutil.o xgaussope.o Gaussian.o dalloc.o mathfn.o cmplx.o govlp.o + gcc -Wall -o $@.x $^ $(GOPT) -lm -llapack -lblas -lgfortran + +libctest:xgaussope.o Gaussian.o dalloc.o mathfn.o cmplx.o + gcc -Wall -shared -o $@.so $^ $(GOPT) -lm -llapack -lblas -lgfortran + +testmain:testmain01.o xgaussope.o Gaussian.o dalloc.o mathfn.o cmplx.o + gcc -Wall -o $@.x $^ $(GOPT) -lm -llapack -lblas -lgfortran + +test_alloc:test_alloc.o xgaussope.o Gaussian.o dalloc.o mathfn.o cmplx.o + gcc -Wall -o $@.x $^ $(GOPT) -lm -llapack -lblas -lgfortran + + +test_govlp:govlp.o xgaussope.o Gaussian.o dalloc.o mathfn.o cmplx.o + gcc -Wall -o $@.x $^ $(GOPT) -lm -llapack -lblas -lgfortran + +testlib:testlib.o + gcc -Wall -shared -o $@.so $^ $(GOPT) -lm -llapack -lblas -lgfortran + +test_Gaussian:test_Gaussian.o Gaussian.o xgaussope.o dalloc.o cstrutil.o mathfn.o govlp.o cmplx.o + gcc -Wall -o $@.x $^ $(GOPT) -lm -llapack -lblas -lgfortran diff --git a/pyscf/lib/rttddft/libpp01/mathfn.c b/pyscf/lib/rttddft/libpp01/mathfn.c new file mode 100644 index 000000000..30f3eea3d --- /dev/null +++ b/pyscf/lib/rttddft/libpp01/mathfn.c @@ -0,0 +1,626 @@ +#include +#include +#include +#include "mathfn.h" +#include "macro_util.h" +#include "cConstants.h" +#include "dcmplx.h" +#include "dalloc.h" + +int i1sum(const int *a,const int n){ + int ret=0;int i;for(i=0;i 0,1,2,... and retv[p]= Gamma((2p+1)/2) = ((2p-1)/2)*Gamma[p-1] + static double retv[N_fctrl]={ sqrt_pi, 0.5*sqrt_pi, 0.75*sqrt_pi, 1.875*sqrt_pi, 6.5625*sqrt_pi, + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 }; + static int n_last=4;int i; + if(p<=n_last){ return retv[p];} + for(i=n_last+1;(i=0,("factln arg<0"),-1); + if(n<=1) return 0.0; + if(n<101) return a[n] ? a[n]:( a[n]=( gammln(n+1.0) ) ); + return gammln(n+1.0); +} +double gammln(double xx){ + const double cof[6]={76.18009172947146e+00, + -86.50532032941677e+00, + 24.01409824083091e+00, -1.231739572450155e+00, + 0.1208650973866179e-02, -0.5395239384953e-05}; + int j; + double x,y,tmp,ser; + y=x=xx; + tmp=x+5.5; tmp=tmp-(x+0.5)*log(tmp); + ser=1.000000000190015; + for(j=0;j<6;j++)ser+=cof[j]/++y; + return -tmp+log(2.5066282746310005*ser/x); +} +void c_gammln_(double *ret,double *x){ + *ret=gammln(*x); +} +#define ITMAX 100 +#define EPS 3.0e-07 +#define FPMIN 1.0e-30 +double gammp(double a,double x){ +double gamser,gammcf,gln; +//if(x<0.0||a<=0)__assertf(0,("wrongArg")); +if(x<(a+1.0)){ gser(&gamser,a,x,&gln);return gamser;} +else { gcf(&gammcf,a,x,&gln); return 1-gammcf;} +} +void gser(double *gamser,double a,double x,double *gln){ + int n; double sum,del,ap; + *gln=gammln(a); + if( x<=0.0 ){ + if(x<0.0){ __assertf(0,("x<0 in gser"),-1); } + *gamser=0.0;return; + } else { + ap=a; del=sum=1.0/a; + for(n=1;n<=ITMAX;n++){ + ++ap; del*=x/ap; sum+=del; + if(fabs(del)ITMAX){ __assertf(0,("gcf:did not reach convergence.."),-1); } + *gammcf=exp(-x+a*log(x)-(*gln))*h; +} + +double BoysFn(int n,double zeta){ + if( fabs(zeta)l){ + __abort( ("illegal arg in Plgndr %d %d %f %d%d\n",l,m,x,0,0) ); + } + if(fabs(x)>1.0){ + if(fabs(x)>1.0+TINY) + __abort( ("illegal arg in Plgndr %d %d %f %d%d\n",l,m,x,0,0) ); + x=(x>0.0 ? x-TINY:x+TINY); + // XXX XXX this frequently happens... XXX fprintf(stdout,"#Plgndr:!W arg modified:%f\n",x); + } +/* if(m<0||m>l||fabs(x)>1.0){ + __ABORT6("illegal arg in Plgndr %d %d %f\n",l,m,x,0,0) + }*/ + pmm=1.0; + if(m>0){ + somx2=sqrt((1.0-x)*(1.0+x)); + fact=1.0; + for(i=1;i<=m;i++){ + // pmm*=-fact*somx2; ! WW phase convention is different from XMOLECULE + pmm*=fact*somx2; + fact+=2.0; + } + } + if(l==m)return pmm; + else { + pmmp1=x*(2*m+1)*pmm; + if(l==(m+1))return pmmp1; + else { + for(ll=m+2;ll<=l;ll++){ + pll=(x*(2*ll-1)*pmmp1-(ll+m-1)*pmm)/(ll-m); + pmm=pmmp1; + pmmp1=pll; + } + return pll; + } + } +} + +double dlgndr(int l,double x){ + // recursion-1 : P'_{n+1}=xP_{n}'+(n+1)P_{n} + double cur=0.0; + int j; + if(l==0) return 0.0; + if(l==1) return 1.0; + if(l==2) return 3.0*x; + cur=3.0*x; + for(j=2;j0 && m%2 ) p=-p; + return p*cos(m*phi) + _I*p*sin(m*phi); + //return new_dCmplx( p*cos(m*phi), p*sin(m*phi)); +} +/* !$ dSpher m=0: sqrt((2l+1)/4PI) P_l(Cos) = Y_{l0} + !$ m>0: sqrt((2l+1)/4PI) sqrt( (l-|m|)!/(l+|m|)! ) P_l^{|m|}(Cos) cos(|m|phi) = \sqrt{2} Re( Y_l^{-|m|} ) inc. (-)^{(m+|m|)/2} factor + !$ sin(|m|phi) + */ +double dSpher(int l,int m,double theta,double phi){ + // + // printf("dSpher:%d,%d\n",l,m);fflush(stdout); + if(m==0) return sqrt( ((double)(2*l+1.0)) / (4.0*PI) ) * Plgndr(l,0,cos(theta)); + double p=sqrt( ((double)(2*l+1.0)) / (2.0*PI) * factorial_2( l-abs(m), l+abs(m) ) ) * Plgndr(l,abs(m),cos(theta)); + if(m<0) return p*sin(-m*phi); + return p*cos(m*phi); +} + + +void c_dSpher_(double *ret,int *l,int *m,double *theta,double *ph){ + *ret=dSpher(*l,*m,*theta,*ph); +} + + +/* +void test_spher(){ + int l=2;int N=100; + int j,k; +// for(m=-l;m<=l;m++){ + double phi=0; + double c,theta,c0=-1,c1=1,dc=2.0/N; + double sum1[5]={0,0,0,0,0};double sum2[5]={0,0,0,0,0}; + for(j=0;j<=N;j++){ c=c0+dc*j;theta=acos(c);double s=sin(theta); + dcmplx vals[5]={ zSpher(2,-2,theta,phi)[0], zSpher(2,-1,theta,phi)[0], zSpher(2,0,theta,phi)[0], zSpher(2,1,theta,phi)[0], zSpher(2,2,theta,phi)[0] }; + double comp[5]={ sqrt(15.0/(32*PI))*s*s*cos(2*phi), -sqrt(15.0/(8*PI))*s*c*cos(phi), sqrt(5.0/(16*PI))*(3*c*c-1.0), + sqrt(15.0/(8*PI))*s*c*cos(phi),sqrt(15.0/(32*PI))*s*s*cos(2*phi)}; + printf("%lf %lf ",theta,cos(theta)); + for(k=0;k<5;k++)printf("%lf %lf ",vals[k],comp[k]); + printf("\n"); + for(k=0;k<5;k++){ sum1[k]+=( (j==0 || j==N) ? vals[k]*vals[k]/2 : vals[k]*vals[k])*dc; + sum2[k]+=( (j==0 || j==N) ? comp[k]*comp[k]/2 : comp[k]*comp[k])*dc; + } + } + printf("#Sum: "); + for(k=0;k<5;k++)printf("%lf %lf ",sum1[k]*2*PI,sum2[k]*2*PI); + +}*/ +void test_spher2(){ + int N=400,M=400,j,k,ib,Jb,ijb; + double phi,dphi=2*PI/M; + double c,theta,c0=-1,c1=1,dc=2.0/N; + int l,m,lm,Nb=0,lmax=4;for(l=0;l<=lmax;l++){ Nb+=(l+1)*(l+1); } + double *sum=d1alloc_i(Nb*(Nb+1)/2,0); + double *vals=d1alloc(Nb); + for(j=0;j<=N;j++){ c=c0+dc*j;theta=acos(c);double s=sin(theta); + for(phi=0,k=0;kN; +__DBGLGR( ("gen_LebedevGrid done") ); + for(k=0;kx[k],grid->y[k]); + }} + for(ijb=0,ib=0;ibw[k]*fn[ib]*fn[Jb]; + } + } +#define _ln10 2.3025850929940456840179914546844 +#define __PrtDev(v,ref) { if( fabs(v-ref)>1e-5 ) printf("%lf ",fabs(v-ref));\ + else { printf("0(%d) ",(int) floor( log(fabs(v-ref))/_ln10 )+1 ); } } + //else { printf("%7.1e(%d) ",fabs(v-ref),(int) floor( log(fabs(v-ref))/_ln10 )+1 ); } } + double devMx1=-1,devMx2=-1; + for(ijb=0,ib=0;ib>> int main(int argn,char **args){ + //test_spher2(); + test_spher3(4); + test_spher3(5); + test_spher3(6); + test_spher3(7); + test_spher3(8); + test_spher3(9); + test_spher3(10); + test_spher3(11); + test_spher3(12); + test_spher3(13); + test_spher3(14); + test_spher3(15); + test_spher3(16); + test_spher3(17); + test_spher3(18); + test_spher3(19); + + test_spher3(20); + test_spher3(21); + test_spher3(22); + test_spher3(23); + test_spher3(24); + test_spher3(25); + test_spher3(26); + test_spher3(27); + test_spher3(28); + test_spher3(29); + +} +*/ +/* +ldXXXX doneDEV:0.000000: 1.000000 0.000000 0.000000 / 1.000000 0.000000 0.000000 +DEV:0.000000: -1.000000 0.000000 0.000000 / -1.000000 0.000000 0.000000 +DEV:0.000000: -0.888074 0.459701 0.000000 / -0.888074 0.459701 0.000000 +gen_LebedevGrid done:0x600039f60 lmax=4 N=38,38,38gen_LebedevGrid done#devMx:4:1.554312e-15 5.932754e-16 +ldXXXX donegen_LebedevGrid done:0x60004bfc0 lmax=5 N=50,50,50gen_LebedevGrid done#devMx:5:1.110223e-15 1.165734e-15 +ldXXXX donegen_LebedevGrid done:0x60004f190 lmax=6 N=74,74,74gen_LebedevGrid done#devMx:6:1.998401e-15 1.106754e-15 +ldXXXX doneDEV:0.000000: 0.369603 0.369603 -0.852518 / 0.369603 0.369603 -0.852518 +gen_LebedevGrid done:0x600054320 lmax=7 N=86,86,86gen_LebedevGrid done#devMx:7:1.998401e-15 2.445960e-15 +ldXXXX doneDEV:0.000000: 0.185116 0.185116 -0.965124 / 0.185116 0.185116 -0.965124 +gen_LebedevGrid done:0x60005be30 lmax=8 N=110,110,110gen_LebedevGrid done#devMx:8:2.331468e-15 1.703498e-15 +ldXXXX donegen_LebedevGrid done:0x600067470 lmax=9 N=146,146,146gen_LebedevGrid done#devMx:9:3.108624e-15 1.292369e-15 +ldXXXX donegen_LebedevGrid done:0x600077ae0 lmax=10 N=170,170,170gen_LebedevGrid done#devMx:10:1.159783e-11 1.098080e-15 +ldXXXX donegen_LebedevGrid done:0x60008e630 lmax=11 N=194,194,194gen_LebedevGrid done#devMx:11:1.473377e-11 1.400789e-15 +ldXXXX donegen_LebedevGrid done:0x6000ad160 lmax=12 N=230,230,230gen_LebedevGrid done#devMx:12:1.801959e-11 1.039707e-14 +ldXXXX donegen_LebedevGrid done:0x6000d5ea0 lmax=13 N=266,266,266gen_LebedevGrid done#devMx:13:2.138711e-11 4.100127e-15 +ldXXXX doneDEV:0.000000: 0.096183 0.096183 0.990706 / 0.096183 0.096183 0.990706 +DEV:0.000000: 0.096183 0.096183 -0.990706 / 0.096183 0.096183 -0.990706 +gen_LebedevGrid done:0x60010b2b0 lmax=14 N=302,302,302gen_LebedevGrid done#devMx:14:2.480482e-11 1.553445e-15 +ldXXXX donegen_LebedevGrid done:0x60010f3f0 lmax=15 N=350,350,350gen_LebedevGrid done#devMx:15:2.823164e-11 4.359794e-15 +ldXXXX donegen_LebedevGrid done:0x600113f30 lmax=16 N=434,434,434gen_LebedevGrid done#devMx:16:3.162814e-11 2.719816e-15 +ldXXXX donegen_LebedevGrid done:0x600119b50 lmax=17 N=590,590,590gen_LebedevGrid done#devMx:17:3.497891e-11 2.722540e-15 +ldXXXX donegen_LebedevGrid done:0x6001215d0 lmax=18 N=770,770,770gen_LebedevGrid done#devMx:18:3.827128e-11 1.598006e-15 +ldXXXX donegen_LebedevGrid done:0x60012b350 lmax=19 N=974,974,974gen_LebedevGrid done#devMx:19:4.149225e-11 1.904177e-15 +ldXXXX donegen_LebedevGrid done:0x600137850 lmax=20 N=1202,1202,1202gen_LebedevGrid done#devMx:20:4.465173e-11 5.415048e-15 +ldXXXX donegen_LebedevGrid done:0x600146970 lmax=21 N=1454,1454,1454gen_LebedevGrid done#devMx:21:4.769396e-11 2.924635e-15 +ldXXXX doneDEV:0.000000: 0.028609 0.028609 0.999181 / 0.028609 0.028609 0.999181 +gen_LebedevGrid done:0x600158b30 lmax=22 N=1730,1730,1730gen_LebedevGrid done#devMx:22:5.068579e-11 2.685677e-15 +ldXXXX donegen_LebedevGrid done:0x60016e230 lmax=23 N=2030,2030,2030gen_LebedevGrid done#devMx:23:5.355638e-11 2.752572e-15 +ldXXXX donegen_LebedevGrid done:0x6001872f0 lmax=24 N=2354,2354,2354gen_LebedevGrid done#devMx:24:5.635303e-11 3.331306e-15 +ldXXXX donegen_LebedevGrid done:0x6001a4210 lmax=25 N=2702,2702,2702gen_LebedevGrid done#devMx:25:5.905143e-11 4.468431e-15 +ldXXXX doneDEV:0.000000: 0.018861 0.018861 0.999644 / 0.018861 0.018861 0.999644 +gen_LebedevGrid done:0x6001c5410 lmax=26 N=3074,3074,3074gen_LebedevGrid done#devMx:26:6.169043e-11 4.222722e-15 +ldXXXX donegen_LebedevGrid done:0x6001ead90 lmax=27 N=3470,3470,3470gen_LebedevGrid done#devMx:27:6.422685e-11 4.174395e-15 +ldXXXX donegen_LebedevGrid done:0x600215310 lmax=28 N=3890,3890,3890gen_LebedevGrid done#devMx:28:6.669365e-11 3.789802e-15 +ldXXXX donegen_LebedevGrid done:0x600244930 lmax=29 N=4334,4334,4334gen_LebedevGrid done#devMx:29:6.902567e-11 4.344739e-15 + + +*/ +/* +int main(int argn,char **args){ +int n,k,Nmx=40;double dum,pre=1.0; +for(n=0;n0 ) printf("Error %d: (%d)%ld %ld %d (%d)%ld\n", + n-1,k-1,nCk[n-1][k-1],nCk[n-1][k],n,k,nCk[n][k]); + } + } + double p=1.0,f; + for(n=0;n<30;n++){ + f=factorial(n); + printf("%d %f %f\n",n,f,f/p); p=f; + } +}*/ +double gamma_hfodd(int odd){ + #define bfsz 30 + #define sqrtPI 1.7724538509055160272981674833411 + const double hf=0.5, qd3=0.75, oc15=1.875, qoc105=3.28125,ooc945=14.765625, dmy=-1.0, one=1.0, quad=0.25, + sqrt2=1.4142135623730950488016887242097; + // [i]: Gamma((2*i+1)/2) so [i+1]=[i]*(i+0.5) + static double gambuf[bfsz]={ + sqrtPI, sqrtPI*0.5, sqrtPI*0.75, sqrtPI*1.875, sqrtPI*6.5625, + sqrtPI*29.53125,-1, -1, -1, -1, + -1,-1,-1,-1,-1, -1,-1,-1,-1,-1, -1,-1,-1,-1,-1, -1,-1,-1,-1,-1}; + static int nbuf=6; + int ia=(odd-1)/2;//$1->0 3->1 etc. + if(ia +#include +#include +#include +#include "dcmplx.h" +#include "ushort.h" +#include "Gaussian.h" +#include "cstrutil.h" +#include "xgaussope.h" +#include "macro_util.h" +#include "dalloc.h" +static char Ope_='\0'; //'o' or 'x' +static int N_call_=0; //0:default, +static int MPIrank_=0; //caller's threadno... +#define _Printf(args) { if(MPIrank_==0){ printf args;} } +#define _Fprintf(args) { if(MPIrank_==0){ fprintf args;} } +#define _Fwrite(fpath,Append,dtme,dmyfp,args) { FILE *dmyfp=fopen(fpath, ((Append) ? "a":"w") );fprintf args;\ +if(dtme){__fprtdtme(dmyfp,"\t\t ","\n") } fclose(dmyfp);} + +#define Dot_3d(A,B) (A[0]*B[0] + A[1]*B[1] + A[2]*B[2]) +#define dist3D(A,B) (sqrt( (A[0]-B[0])*(A[0]-B[0]) + (A[1]-B[1])*(A[1]-B[1]) + (A[2]-B[2])*(A[2]-B[2]) )) + +unsigned short *get_ush1(unsigned short L){ + return (unsigned short *)malloc(L*sizeof(unsigned short)); +} +void free_ush1(unsigned short *p){ + free(p); +} + +#define _get_ush1( ret, L, lret){\ +ret=get_ush1(L);} +#define _free_ush1( ptr, L, laddr){\ +free(ptr);} +#define _clone_ush1( org, ret, L, lret, kk) {\ +_get_ush1( ret,L,lret);for(kk=0;kk> nCGTO+=1 + 4563.240 0.00196665 + 682.0240 0.0152306 + 154.9730 0.0761269 + 44.45530 0.2608010 + 13.02900 0.6164620 + 1.827730 0.2210060 + +shell_1 : C SP nCGTO+=( +shell_2 : nCGTO+=(2*l+1) + 20.96420 0.114660 0.0402487 + 4.803310 0.919999 0.237594 + 1.459330 -0.00303068 0.815854 +shell_3 : C SP nCGTO+=( +shell_4 : nCGTO+=(2*l+1) +C SP + 0.4834560 1.000000 1.000000 +C SP + 0.1455850 1.000000 1.000000 +*/ +// ell[ \sum(Nsh[:]) ] npGTO[ \sum(Nsh[:]) ] alph[ \sum(npGTO[:]) +// +Gaussian ***gen_bsetx3(int *pNcGTO,const int nAtm,double *Rnuc,const int *IZnuc,const int nDa,const int *distinctIZnuc, + const int *Nsh,const int *ell,const int *n_cols,const int *npGTO,const double *alph,const double *cofs){ + static int n_call_loc=0;n_call_loc++; + Gaussian ***ret=(Gaussian ***)malloc(3*sizeof(Gaussian **)); + int n0=0,n1=0,n2=0;const int verbose=0; + __assertf(n_cols!=NULL,("gen_bsetx3.000"),-1); + ret[0]=gen_bset01(&n0,nAtm,Rnuc,IZnuc, nDa, distinctIZnuc, Nsh, ell, n_cols, npGTO, alph, cofs, 0, verbose); + ret[1]=gen_bset01(&n1,nAtm,Rnuc,IZnuc, nDa, distinctIZnuc, Nsh, ell, n_cols, npGTO, alph, cofs, 1, verbose); + ret[2]=NULL; + const int NshSUM=i1sum(Nsh,nDa); + int i;int nMx=-1; for(i=0;i2){ ret[2]=gen_bset01(&n2,nAtm,Rnuc,IZnuc, nDa, distinctIZnuc, Nsh, ell, n_cols, npGTO, alph, cofs, 2, (verbose||(n_call_loc==1 && N_call_==1 && MPIrank_==0))); + if( (N_call_==1||N_call_==2) && MPIrank_==0 ){ printf("#gen_bsetX3 allocating 02-th bset %d...\n",n2);fflush(stdout);} } + pNcGTO[0]=n0; + pNcGTO[1]=n1; + pNcGTO[2]=n2; + return ret; +} +Gaussian **gen_bset(int *pNcGTO,const int nAtm,double *Rnuc,const int *IZnuc,const int nDa,const int *distinctIZnuc, + const int *Nsh,const int *ell,const int *n_cols,const int *npGTO,const double *alph,const double *cofs, const int I_col){ + const int verbose=0; + return gen_bset01(pNcGTO, nAtm, Rnuc, IZnuc, nDa, distinctIZnuc, Nsh, ell, n_cols, npGTO, alph, cofs, I_col, verbose); +} +Gaussian **gen_bset01(int *pNcGTO,const int nAtm,double *Rnuc,const int *IZnuc,const int nDa,const int *distinctIZnuc, + const int *Nsh,const int *ell,const int *n_cols,const int *npGTO,const double *alph,const double *cofs,const int I_col,char verbose){ + if(verbose){ printf("#gen_bset01:I_col=%d %p %d %p %p %d %p %p\n",I_col,pNcGTO,nAtm,Rnuc,IZnuc,nDa,distinctIZnuc,Nsh); + fflush(stdout); + int NshSUM=i1sum(Nsh,nDa); + ___prtD1(("#gen_bset01:Rnuc"),Rnuc,(nAtm*3)) + ___prtI1(("#gen_bset01:IZnuc"),IZnuc,(nAtm)) + ___prtI1(("#gen_bset01:distinctIZnuc"),distinctIZnuc,nDa) + ___prtI1(("#gen_bset01:Nsh"),Nsh,nDa); + ___prtI1(("#gen_bset01:ell"),ell,NshSUM); + if(n_cols !=NULL ){ + ___prtI1(("#gen_bset01:n_cols"),n_cols,NshSUM); + } + ___prtI1(("#gen_bset01:npGTO"),npGTO,NshSUM); + int npgtoSUM=i1sum(npGTO,NshSUM); + ___prtD1(("#gen_bset01:alph"),alph,npgtoSUM); + ___prtD1(("#gen_bset01:cofs"),cofs,npgtoSUM); + } +#define ___fprtD1(fptr,msg,A,L) { int kprtd1; fprintf msg;\ +for(kprtd1=0;kprtd10){ __assertf( (n_cols !=NULL),("n_cols %d",I_col),-1);} + int idbgng=3; + int **Ncols=NULL; + int **Ell=i2allocx(nDa,Nsh); + if(verbose && idbgng){ printf("#gen_bset01.DBGNG:0010\n");fflush(stdout);} + int **Npgto=i2allocx(nDa,Nsh); + if(verbose && idbgng){ printf("#gen_bset01.DBGNG:0020\n");fflush(stdout);} + int ida,jsh,ixj,ko,ixjxk; + for(ida=0,ixj=0;ida=Ncols[ida][jsh]){ /*printf("gen_bset:skipping.. el=%d",el);*/ continue;} // I_col==1 && Ncols[ida][jsh]<=1 skip + } + const int nmult=2*el+1; int m; + if( BS != NULL ){ + const int p_to_xyz[3]={1,-1,0}; // somehow p-type AOs are aligned in x,y,z order + for(m=-el;m<=el;m++){ const int em=(el==1 ? p_to_xyz[m+el]:m); + if(verbose){ printf("#gen_bset01:BS:%d:el=%d nMult=%d\n",nCGTO+1,el,nmult);fflush(stdout);} + SphericalGaussian *spg=new_SphericalGaussianX(Alph[ida][jsh],Rnuc+3*iat,el,em,Npgto[ida][jsh],Cofs[ida][jsh],iat,I_col); + if(verbose){ printf("#gen_bset01:BS:%d:el=%d nMult=%d\n",nCGTO+1,el,nmult);fflush(stdout);} + //if(I_col){ + // FILE *fptr=fopen("gen_bset01.log",( append_logf ? "a":"w"));append_logf=1; + // fprintf(fptr,"#%d:%s\n",nCGTO,spg->description);fclose(fptr); + //} + BS[nCGTO]=Spherical_to_Cartesian(spg); free_SphericalGaussian(spg);spg=NULL; + double zerovec[3]={0,0,0}; + dcmplx ovlp=Gaussian_overlap(BS[nCGTO],BS[nCGTO],zerovec,zerovec); + // FILE *fp2=fopen("gen_bset01_BS.log","a"); + if( fpBSLOG !=NULL ){ Gaussian_fprtout((fpBSLOG,"#gen_bset01:%d %d,%d ovlp:%f",nCGTO,el,m,creal(ovlp)),fpBSLOG,BS[nCGTO]);} + nCGTO++; + } + } else { + nCGTO+=nmult; + if(verbose){ printf("#gen_bset01:prep:Counting up:el=%d nMult=%d %d\n",el,nmult,nCGTO);fflush(stdout);} + } + } + //printf("#end of jsh loop:iat=%d",iat);fflush(stdout); + } + if(BS==NULL){ /* printf("#gen_bset01;allocating %d\n",nCGTO);fflush(stdout); */ + BS=(Gaussian **)malloc(nCGTO*sizeof(Gaussian *)); *pNcGTO=nCGTO;} + } + if( fpBSLOG !=NULL ) fclose(fpBSLOG); + int ngot=*pNcGTO; +#ifdef PRTOUT_BSET + if(verbose){ BSet_prtout(("gen_bset:%d",ngot),BS,ngot);} +#endif + //if(1){FILE *fp1=fopen("xgaussope_check_free.txt","a");fprintf(fp1,"BF:%p %p %p %p %p\n",Alph,Cofs,Ell,Npgto,Ncols);fclose(fp1);} + d3free(Alph);Alph=NULL; d3free(Cofs);Cofs=NULL; + //if(1){FILE *fp1=fopen("xgaussope_check_free.txt","a");fprintf(fp1,"#1:%p %p %p %p %p\n",Alph,Cofs,Ell,Npgto,Ncols);fclose(fp1);} + i2free(Ell);Ell=NULL;i2free(Npgto);Npgto=NULL; + //if(1){FILE *fp1=fopen("xgaussope_check_free.txt","a");fprintf(fp1,"#2:%p %p %p %p %p\n",Alph,Cofs,Ell,Npgto,Ncols);fclose(fp1);} + if(Ncols!=NULL){ i2free(Ncols);Ncols=NULL; } + //FILE *fp2=fopen("xgaussope_check_free.txt","a");fprintf(fp2,"AF:%p %p %p %p %p\n",Alph,Cofs,Ell,Npgto,Ncols);fclose(fp2); + //__assertf(0,("BSet"),-1) + return BS; +} +double check_nrmz(const char *title,Gaussian **BS,int Nb){ + return check_nrmz01(title,BS,Nb,0); +} +double check_nrmz01(const char *title,Gaussian **BS,int Nb,const char fix_nrmz){ + int i; + double displ[3]={0.0, 0.0, 0.0}; + double vectorfield[3]={0.0, 0.0, 0.0}; + double maxdev=-1,devsum=0; + dcmplx as=0;int at=-1; + int prtout=0; + FILE *fperr=stdout,*fpOUT=NULL; + double devTOL=(fix_nrmz ? 1.0e-6:1.0e-3); + int idbgng=2;char strbuf50[50]; +#define PRTOUT_NRMZ01 // XXX XXX +#ifdef PRTOUT_NRMZ01 + if( fix_nrmz || idbgng ){ sprintf(strbuf50,"xgaussope_fix_nrmz_%s.log",title);fperr=( fpOUT=fopen(strbuf50,"w") ); } +#endif + + for(i=0;idevTOL){ +#ifdef PRTOUT_NRMZ01 + fprintf(fperr,"#un-normalized Gaussian:%s.%03d:ovlp=%f+j%f Ga:%s\n",title,i,creal(ovlp),cimag(ovlp),BS[i]->description); +#else + if(!fix_nrmz){ printf("#un-normalized Gaussian:%s.%03d:ovlp=%f+j%f Ga:%s\n",title,i,creal(ovlp),cimag(ovlp),BS[i]->description);} +#endif + if(fix_nrmz){ + __assertf( fabs(cimag(ovlp))<1.0e-7,(""),-1); + double fac=1.0/sqrt( creal(ovlp) ); + int j; for(j=0;j<(BS[i]->N);j++) BS[i]->cofs[j]*=fac; + ovlp=Gaussian_overlap(BS[i],BS[i],vectorfield,displ); + double dev2=sqrt( (creal(ovlp)-1.0)*(creal(ovlp)-1.0) + cimag(ovlp)*cimag(ovlp) ); + __assertf(dev2<1.0e-7,(""),-1); + } +/* +#un-normalized Gaussian:ovlp=1.205603+j0.000000 Ga: 0.712264 -0.308844 + 0.262870 0.019606 + 0.116086 1.131034 + +*/ + } + if(dev>maxdev){ maxdev=dev;at=i;as=ovlp;} + devsum+=sqrdev; + } +#ifdef PRTOUT_NRMZ01 + fprintf(fperr,"#check_nrmz:%s:maxdev=%e [%d]:S=%f+j%f",title,maxdev,at,creal(as),cimag(as)); + if(fpOUT!=NULL){ fclose(fpOUT);} fperr=NULL; +#else + if( (!fix_nrmz) && (maxdev>devTOL) ){ printf("#check_nrmz:%s:maxdev=%e [%d]:S=%f+j%f",title,maxdev,at,creal(as),cimag(as));} +#endif + if(maxdev>1.0e-4 && (!fix_nrmz) ){ + int j;Gaussian *G=BS[at]; + printf("#BS_%04d",at);for(j=0;jN;j++){ printf("%d.%d.%d %f \t %f\n", G->pows[j][0],G->pows[j][1],G->pows[j][2],G->alpha[j],G->cofs[j]);} + } + return maxdev; + //__assertf( maxdev<1.0e-3,("wrong ovlp:%e [%d]:S=%f+j%f",maxdev,at,creal(as),cimag(as)),-1) +} +dcmplx *calc_pbc_overlaps_dmy(const int nAtm, const double *Rnuc, const int *IZnuc, const int nDa, const int *distinctIZnuc, //1,2,3,4,5 + const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs,// 6,7,8,9,10 + const int nAtmB, const double *RnucB, const int *IZnucB,const int nDb, const int *distinctIZnucB,//11,12,13,14,15 + const int *NshB, const int *ellB, const int *n_cols,const int *npGTOB, const double *alphB, + const double *cofsB, const int spdm, const double *BravisVectors, const double *Vectorfield,const int nKpoints, + const double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_2, + const int nCGTO_1){ + dcmplx ****ret=z4alloc(3,nKpoints,nCGTO_2,nCGTO_1); + int i,j,k,l; + for(i=0;i<3;i++)for(j=0;j i=0,1,2,3 +dcmplx *calc_pbc_overlaps02x(int nAtm, double *Rnuc, int *IZnuc, int nDa, int *distinctIZnuc, + const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs, + int nAtmB, double *RnucB, int *IZnucB, int nDb, int *distinctIZnucB, + const int *NshB, const int *ellB, const int *n_cols, const int *npGTOB, const double *alphB, + const double *cofsB, int spdm, double *BravaisVectors, double *Vectorfield,int nKpoints, + double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_2, const int nCGTO_1, const int MPIrank){ + return calc_pbc_overlaps02_(nAtm,Rnuc,IZnuc,nDa,distinctIZnuc,Nsh,ell,npGTO,alph,cofs,nAtmB,RnucB,IZnucB,nDb,distinctIZnucB, + NshB,ellB,n_cols,npGTOB, alphB,cofsB,spdm,BravaisVectors, Vectorfield,nKpoints, + kvectors,Lx,Ly,Lz,nCGTO_2,nCGTO_1,MPIrank, 'x'); +} +int calc_pbc_overlaps02x_f(int nAtm, double *Rnuc, int *IZnuc, int nDa, int *distinctIZnuc, + const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs, + int nAtmB, double *RnucB, int *IZnucB, int nDb, int *distinctIZnucB, + const int *NshB, const int *ellB, const int *n_cols, const int *npGTOB, const double *alphB, + const double *cofsB, int spdm, double *BravaisVectors, double *Vectorfield,int nKpoints, + double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_2, const int nCGTO_1, const int MPIrank, const int filenumber){ + dcmplx *zbuf=calc_pbc_overlaps02_(nAtm,Rnuc,IZnuc,nDa,distinctIZnuc,Nsh,ell,npGTO,alph,cofs,nAtmB,RnucB,IZnucB,nDb,distinctIZnucB, + NshB,ellB,n_cols,npGTOB, alphB,cofsB,spdm,BravaisVectors, Vectorfield,nKpoints, + kvectors,Lx,Ly,Lz,nCGTO_2,nCGTO_1,MPIrank, 'x'); + int Ld=4*3*nKpoints*nCGTO_2*nCGTO_1; // 3*nKpoints*nBS2a[0]*nBS1; + char filename[50]; + sprintf(filename,"calc_pbc_overlapsx_%03d.retf",filenumber); + write_z1buf(filename,zbuf,Ld); + z1free(zbuf); + return Ld; +} +int calc_pbc_overlaps_f(int nAtm, double *Rnuc, int *IZnuc, int nDa, int *distinctIZnuc, + const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs, + int nAtmB, double *RnucB, int *IZnucB, int nDb, int *distinctIZnucB, + const int *NshB, const int *ellB, const int *n_cols, const int *npGTOB, const double *alphB, + const double *cofsB, int spdm, double *BravaisVectors, double *Vectorfield,int nKpoints, + double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_2, const int nCGTO_1, const int MPIrank, const int filenumber){ + dcmplx *z1a=calc_pbc_overlaps02_(nAtm,Rnuc,IZnuc,nDa,distinctIZnuc,Nsh,ell,npGTO,alph,cofs,nAtmB,RnucB,IZnucB,nDb,distinctIZnucB, + NshB,ellB,n_cols,npGTOB, alphB,cofsB,spdm,BravaisVectors, Vectorfield,nKpoints, + kvectors,Lx,Ly,Lz,nCGTO_2,nCGTO_1,MPIrank, 'o'); + int Ld=3*nKpoints*nCGTO_2*nCGTO_1; // 3*nKpoints*nBS2a[0]*nBS1; + char filename[50]; + sprintf(filename,"calc_pbc_overlaps_%03d.retf",filenumber); + write_z1buf(filename,z1a,Ld); + z1free(z1a);z1a=NULL; + return Ld; +} +#define _GEN_BS1 1 +#define _GEN_BS2 2 +#define _CALC_OVLPo 4 +#define _WRITE_OVLPo 8 +#define _CALC_OVLPx 16 +#define _WRITE_OVLPx 32 + +int calc_pbc_overlaps_f01(int nAtm, double *Rnuc, int *IZnuc, int nDa, int *distinctIZnuc, + const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs, + int nAtmB, double *RnucB, int *IZnucB, int nDb, int *distinctIZnucB, + const int *NshB, const int *ellB, const int *n_cols, const int *npGTOB, const double *alphB, + const double *cofsB, int spdm, double *BravaisVectors, double *Vectorfield,int nKpoints, + double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_2, const int nCGTO_1, const int MPIrank,const int filenumber){ + int iflag=_GEN_BS1+_GEN_BS2+_CALC_OVLPo+_WRITE_OVLPo; + calc_pbc_overlaps_dbg_(nAtm, Rnuc, IZnuc, nDa, distinctIZnuc, Nsh, ell, npGTO, alph, cofs, nAtmB, RnucB, IZnucB, nDb, distinctIZnucB, + NshB, ellB, n_cols, npGTOB, alphB, cofsB, spdm, BravaisVectors, Vectorfield, nKpoints, kvectors, Lx, Ly, Lz, + nCGTO_2, nCGTO_1, MPIrank, iflag, filenumber); + return 0; +} +int calc_pbc_overlaps02x_f01(int nAtm, double *Rnuc, int *IZnuc, int nDa, int *distinctIZnuc, + const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs, + int nAtmB, double *RnucB, int *IZnucB, int nDb, int *distinctIZnucB, + const int *NshB, const int *ellB, const int *n_cols, const int *npGTOB, const double *alphB, + const double *cofsB, int spdm, double *BravaisVectors, double *Vectorfield,int nKpoints, + double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_2, const int nCGTO_1, const int MPIrank,const int filenumber){ + int iflag=_GEN_BS1+_GEN_BS2+_CALC_OVLPx+_WRITE_OVLPx; + calc_pbc_overlaps_dbg_(nAtm, Rnuc, IZnuc, nDa, distinctIZnuc, Nsh, ell, npGTO, alph, cofs, nAtmB, RnucB, IZnucB, nDb, distinctIZnucB, + NshB, ellB, n_cols, npGTOB, alphB, cofsB, spdm, BravaisVectors, Vectorfield, nKpoints, kvectors, Lx, Ly, Lz, + nCGTO_2, nCGTO_1, MPIrank, iflag, filenumber); + return 0; +} +// for backward compatibility.... +int calc_pbc_overlaps_dbg(int nAtm, double *Rnuc, int *IZnuc, int nDa, int *distinctIZnuc, + const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs, + int nAtmB, double *RnucB, int *IZnucB, int nDb, int *distinctIZnucB, + const int *NshB, const int *ellB, const int *n_cols, const int *npGTOB, const double *alphB, + const double *cofsB, int spdm, double *BravaisVectors, double *Vectorfield,int nKpoints, + double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_2, const int nCGTO_1, const int MPIrank, const int iflag){ + int filenumber=MPIrank; + calc_pbc_overlaps_dbg_(nAtm, Rnuc, IZnuc, nDa, distinctIZnuc, Nsh, ell, npGTO, alph, cofs, nAtmB, RnucB, IZnucB, nDb, distinctIZnucB, + NshB, ellB, n_cols, npGTOB, alphB, cofsB, spdm, BravaisVectors, Vectorfield, nKpoints, kvectors, Lx, Ly, Lz, + nCGTO_2, nCGTO_1, MPIrank, iflag, filenumber); + return 0; +} +int calc_pbc_overlaps_dbg_(int nAtm, double *Rnuc, int *IZnuc, int nDa, int *distinctIZnuc, + const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs, + int nAtmB, double *RnucB, int *IZnucB, int nDb, int *distinctIZnucB, + const int *NshB, const int *ellB, const int *n_cols, const int *npGTOB, const double *alphB, + const double *cofsB, int spdm, double *BravaisVectors, double *Vectorfield,int nKpoints, + double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_2, const int nCGTO_1, const int MPIrank, const int iflag,const int filenumber){ + int nBS1=0, nBS2a[3]={0,0,0}, verbose=0; + int fix_nrmz=1;char *sdum=getenv("calc_pbc_overlaps.fix_nrmz"); + if(sdum!=NULL){ long ldum=0;int iretv=sscanf(sdum,"%ld",&ldum);if(iretv){ fix_nrmz=(int)ldum;} } + Gaussian **BS=NULL,***BS2=NULL; + if( (iflag & _GEN_BS1 )!=0 ){ BS =gen_bset01(&nBS1,nAtm,Rnuc,IZnuc,nDa,distinctIZnuc,Nsh,ell,NULL,npGTO,alph,cofs,0,verbose); + check_nrmz01("BS1",BS,nBS1,( (fix_nrmz&1)==0 ? 0:1 )); } + if( (iflag & _GEN_BS2 )!=0 ){ BS2=gen_bsetx3(nBS2a,nAtmB,RnucB,IZnucB,nDb,distinctIZnucB,NshB,ellB,n_cols,npGTOB,alphB,cofsB); + check_nrmz01("BS2",BS2[0],nBS2a[0], ( (fix_nrmz&2)==0 ? 0:1 ) ); } + int i2LH,j1RH,I_cols,kp;int iargs[3]={Lx,Ly,Lz}; + int Ldim_margin=5; + if( (iflag & _CALC_OVLPo )!=0 && (BS!=NULL && BS2!=NULL) ){ + dcmplx **ret=(dcmplx **)malloc(3*sizeof(dcmplx *)); + ret[0]=z1alloc_i( 3*nKpoints*nBS2a[0]*nBS1, 0.0); ret[1]= ret[0] + (nKpoints*nBS2a[0]*nBS1); ret[2]= ret[1] + (nKpoints*nBS2a[0]*nBS1); + for(I_cols=0;I_cols<3;I_cols++){ if(nBS2a[I_cols]<=0)continue; + for(i2LH=0;i2LH0){ free_Bset(BS2[2],nBS2a[2]);} + } + //printf("#calc_pbc_overlaps_DBG:$%02d END\n",MPIrank_); + return 0; +} +#undef _GEN_BS1 +#undef _GEN_BS2 +#undef _CALC_OVLPo +#undef _WRITE_OVLPo +#undef _CALC_OVLPx +#undef _WRITE_OVLPx + +dcmplx *calc_pbc_overlaps02_(int nAtm, double *Rnuc, int *IZnuc, int nDa, int *distinctIZnuc, + const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs, + int nAtmB, double *RnucB, int *IZnucB, int nDb, int *distinctIZnucB, + const int *NshB, const int *ellB, const int *n_cols, const int *npGTOB, const double *alphB, + const double *cofsB, int spdm, double *BravisVectors, double *Vectorfield,int nKpoints, + double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_2, const int nCGTO_1,const int MPIrank,const char o_OR_x){ + MPIrank_=MPIrank; + if(MPIrank_==0){ N_call_=fcountup("xgaussope_c", 1);} + Ope_=o_OR_x; + int verbose=1; + static int append_logf=0; + if( MPIrank_==0 && append_logf==0 ){ int narg=0; + char *str=NULL; + FILE *fptr=fopen("calc_pbc_overlaps_input.log",(append_logf ? "a":"w"));append_logf=1; + fprintf(fptr,"#pbc_overlaps01:%02d:nAtm:%d\n",(narg++),nAtm); + fprintf(fptr,"#pbc_overlaps01:%f:%f\n",Rnuc[0],Rnuc[1]); + fprintf(fptr,"#pbc_overlaps01:%d:%d\n",IZnuc[0],IZnuc[1]); + fprintf(fptr,"#pbc_overlaps01:%02d:Rnuc:%s\n",(narg++), (str=d1toa(Rnuc,3*nAtm)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:nAtm:%s\n",(narg++), (str=i1toa(IZnuc,nAtm)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:nAtm:%d\n",(narg++),nDa); + fprintf(fptr,"#pbc_overlaps01:%02d:nAtm:%s\n",(narg++), (str=i1toa(distinctIZnuc,nDa)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:nAtm:%s\n",(narg++), (str=i1toa(Nsh,nDa)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:nAtm:%s\n",(narg++), (str=i1toa(ell,nDa)));free(str); + int NshSUM=i1sum(Nsh,nDa); + fprintf(fptr,"#pbc_overlaps01:%02d:nAtm:%s\n",(narg++), (str=i1toa(npGTO,NshSUM)));free(str); + int Npgto=i1sum(npGTO,NshSUM); + fprintf(fptr,"#pbc_overlaps01:%02d:nAtm:%s\n",(narg++), (str=d1toa(alph,Npgto)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:nAtm:%s\n",(narg++), (str=d1toa(cofs,Npgto)));free(str); + + fprintf(fptr,"#pbc_overlaps01:%02d:nAtm:%d\n",(narg++),nAtmB); + fprintf(fptr,"#pbc_overlaps01:%02d:RnucB:%s\n",(narg++), (str=d1toa(RnucB,3*nAtmB)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:IZnucB:%s\n",(narg++), (str=i1toa(IZnucB,nAtmB)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:nAtm:%d\n",(narg++),nDb); + fprintf(fptr,"#pbc_overlaps01:%02d:distinctIZnucB:%s\n",(narg++), (str=i1toa(distinctIZnucB,nDb)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:NshB:%s\n",(narg++), (str=i1toa(NshB,nDb)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:ellB:%s\n",(narg++), (str=i1toa(ellB,nDb)));free(str); + NshSUM=i1sum(NshB,nDb); + fprintf(fptr,"#pbc_overlaps01:%02d:npGTOB:%s\n",(narg++), (str=i1toa(npGTOB,NshSUM)));free(str); + if(n_cols!=NULL){ + fprintf(fptr,"#pbc_overlaps01:%02d:n_cols:%s\n",(narg++), (str=i1toa(n_cols,NshSUM)));free(str); + } + Npgto=i1sum(npGTOB,NshSUM); + fprintf(fptr,"#pbc_overlaps01:%02d:alphB:%s\n",(narg++), (str=d1toa(alphB,Npgto)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:cofsB:%s\n",(narg++), (str=d1toa(cofsB,Npgto)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:spdm:%d\n",(narg++), spdm); + fprintf(fptr,"#pbc_overlaps01:%02d:BravisVectors:%s\n",(narg++), (str=d1toa(BravisVectors,3*spdm)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:Vectorfield:%s\n",(narg++), (str=d1toa(Vectorfield,3)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:kvectors:%s\n",(narg++), (str=d1toa(kvectors,3*spdm)));free(str); + fprintf(fptr,"#pbc_overlaps01:%02d:spdm:%d,%d %d %d %d\n",(narg++), Lx,Ly,Lz,nCGTO_2,nCGTO_1); + fclose(fptr); + } + dcmplx *ret=NULL; + if( o_OR_x == 'o'){ + dcmplx **zbuf=calc_pbc_overlaps(nAtm, Rnuc, IZnuc, nDa, distinctIZnuc, + Nsh, ell, npGTO, alph, cofs, nAtmB, RnucB, IZnucB, nDb, distinctIZnucB, + NshB, ellB, n_cols, npGTOB, alphB, cofsB, spdm, BravisVectors, Vectorfield,nKpoints, + kvectors, Lx,Ly,Lz, nCGTO_2, nCGTO_1); + ret=zbuf[0]; free(zbuf); + } else { __assertf( o_OR_x=='x',(""),-1); + ret=calc_pbc_overlapsx(nAtm, Rnuc, IZnuc, nDa, distinctIZnuc, + Nsh, ell, npGTO, alph, cofs, nAtmB, RnucB, IZnucB, nDb, distinctIZnucB, + NshB, ellB, n_cols, npGTOB, alphB, cofsB, spdm, BravisVectors, Vectorfield,nKpoints, + kvectors, Lx,Ly,Lz, nCGTO_2, nCGTO_1); + } + //printf("#clib:calc_pbc_overlaps01 END...\n");fflush(stdout); + return ret; +} + +double *calc_pbc_overlaps03(int nAtm, double *Rnuc, int *IZnuc, int nDa, int *distinctIZnuc, + const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs, + int nAtmB, double *RnucB, int *IZnucB, int nDb, int *distinctIZnucB, + const int *NshB, const int *ellB, const int *n_cols, const int *npGTOB, const double *alphB, + const double *cofsB, int spdm, double *BravisVectors, double *Vectorfield,int nKpoints, + double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_2, const int nCGTO_1){ + //printf("#calc_pbc_overlaps:\n");fflush(stdout); + int verbose=0; + int nBS1=0,nBS2a[3]={0,0,0}; + Gaussian **BS =gen_bset01(&nBS1,nAtm,Rnuc,IZnuc,nDa,distinctIZnuc,Nsh,ell,NULL,npGTO,alph,cofs,0,verbose); + Gaussian ***BS2=gen_bsetx3(nBS2a,nAtmB,RnucB,IZnucB,nDb,distinctIZnucB,NshB,ellB,n_cols,npGTOB,alphB,cofsB); + printf("#calc_pbc_overlaps:\n");fflush(stdout); + free_Bset(BS,nBS1); + printf("#calc_pbc_overlaps:END.010:\n");fflush(stdout); + + free_Bset(BS2[0],nBS2a[0]); + printf("#calc_pbc_overlaps:END.020:\n");fflush(stdout); + free_Bset(BS2[1],nBS2a[1]); + printf("#calc_pbc_overlaps:END.030\n");fflush(stdout); + //return ret[0][0][0]; + double *ret=d1alloc( 3*nKpoints*nBS2a[0]*nBS1*2); + int i,kp,j2,k1,ijk,ri; + for(i=0,ijk=0;i<3;i++){ for(kp=0;kpdescription, G2->pows[0][0],G2->pows[0][1],G2->pows[0][2], + Gaussian_overlap(G2,G2,zerovec,zerovec)); + fclose(fpx); + }*/ + for(j1RH=0;j1RH10.0 ) printf("pbc_overlap:LH=%d:I=%d RH=%d elapsed step=%f avg=%f total=%f\n",i2LH,I_cols,j1RH,clock01-clock02,(clock01-clock00)/n,(clock01-clock00)); + int kp; + if(prtout1){ fprintf(fp1,"%d %d ",i2LH,j1RH); + for(kp=0;kp0 && BS2[2]!=NULL ){ + printf("#calc_pbc_overlaps:END.030:%p\n",ret);fflush(stdout); + free_Bset(BS2[2],nBS2a[2]);BS2[2]=NULL; + } + //printf("#calc_pbc_overlaps:END.030:%p\n",ret);fflush(stdout); + //return ret[0][0][0]; + return ret; +} + +int fill_zbuf(dcmplx ****p_zbuf,int **p_Hj,const double abs_thr, + Gaussian *lhs,Gaussian *rhs,int spdm,double *BravisVectors,double *Vectorfield,const int *margin){ + int hj[3]={1,1,1};double ermax=0; + return fill_zbuf1(hj,p_zbuf,p_Hj,abs_thr,lhs,rhs,spdm,BravisVectors,Vectorfield,margin,&ermax); +} + +// p_Hj (INOUT) defines buffer size and offset : zbuf[ 2Hj[0]+1 ][ ... ] +// and istep[0] displ is stored in the manner zbuf[ istep[0] + Hj[0] ][ ... ] +// it can change when realloc occurs in this subroutine +// hj (INOUT) defines the range you actually filled the buffer ... +// (INPUT) we first fill [ -hj[0]:hj[0] ][ ... ] and check convergence +// returns cvgd (1 or 0) +/* +int fill_zbuf1b(int *hj,dcmplx ****p_zbuf,int **p_Hj,const double abs_thr, + Gaussian *lhs,Gaussian *rhs,int spdm,double *BravisVectors,double *Vectorfield,const int *margin,double *ermax){ + return fill_zbuf1_(hj,p_zbuf,p_Hj,abs_thr,lhs,rhs,spdm,BravisVectors,Vectorfield,margin,ermax, Gaussian_ovlpNew_B); +}*/ +int fill_zbuf1(int *hj,dcmplx ****p_zbuf,int **p_Hj,const double abs_thr, + Gaussian *lhs,Gaussian *rhs,int spdm,double *BravisVectors,double *Vectorfield,const int *margin,double *ermax){ + return fill_zbuf1_(hj,p_zbuf,p_Hj,abs_thr,lhs,rhs,spdm,BravisVectors,Vectorfield,margin,ermax, Gaussian_ovlpNew); +} +int fill_zbuf1_(int *hj,dcmplx ****p_zbuf,int **p_Hj,const double abs_thr, + Gaussian *lhs,Gaussian *rhs,int spdm,double *BravisVectors,double *Vectorfield,const int *margin,double *ermax, + dcmplx (*fnGaussian_ovlpNew)(Gaussian *,Gaussian *,const double *,const double *) ){ + double *ax=BravisVectors,*ay=BravisVectors+3,*az=BravisVectors+6; + *ermax=-1.0; + int *Hj_ini=p_Hj[0]; + static int hj_0[3]={1,1,1}; + static int hj_step[3]={1,1,1}; + __assertf(hj[0]>=1 && hj[1]>=0 && hj[2]>=1,("wrong ini hj 001"),-1); + __assertf(hj[0]<=Hj_ini[0] && hj[1]<=Hj_ini[1] && hj[2]<=Hj_ini[2],("wrong ini hj 002"),-1); + // hj[0]=__MIN(Hj_ini[0],hj_0[0]);hj[1]=__MIN(Hj_ini[1],hj_0[1]);hj[2]=__MIN(Hj_ini[2],hj_0[2]); + int cvgd=0; + int Ia[3]={0,0,0}; + int nloop=0;int hjLAST[3]={-1,-1,-1}; + int n_extra_loop=0;int N_cum=0; + while( (nloop++)<999 ){ int kk; + dcmplx ***zbuf=p_zbuf[0]; + int *Hj=p_Hj[0]; + // printf("#fill_zbuf:loop%d %d %d %d",nloop,hj[0],hj[1],hj[2]);fflush(stdout); + double abs_max=-1;int maxat[3]={0,0,0};int N_eff=0; + //printf("#loop:%d %d,%d,%d / %d,%d,%d prev:%d,%d,%d\n",nloop,hj[0],hj[1],hj[2], Hj[0],Hj[1],Hj[2], hjLAST[0],hjLAST[1],hjLAST[2]); + for(Ia[0]=-hj[0];Ia[0]<=hj[0];Ia[0]++){ int o0=( abs(Ia[0])<=hjLAST[0]); + for(Ia[1]=-hj[1];Ia[1]<=hj[1];Ia[1]++){ int o1=(o0 && abs(Ia[1])<=hjLAST[1]); + for(Ia[2]=-hj[2];Ia[2]<=hj[2];Ia[2]++){ int o2=(o1 && abs(Ia[2])<=hjLAST[2]); + if(o2) { + continue;} + N_eff++; + double displ[3]={ ax[0]*Ia[0] + ay[0]*Ia[1] + az[0]*Ia[2], + ax[1]*Ia[0] + ay[1]*Ia[1] + az[1]*Ia[2], ax[2]*Ia[0] + ay[2]*Ia[1] + az[2]*Ia[2]}; + dcmplx cdmy=zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]; + dcmplx ovlp=fnGaussian_ovlpNew(lhs,rhs,Vectorfield,displ); + + zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]=ovlp; + double dum=cabs(ovlp); + if( dum>abs_max ){ abs_max=dum; for(kk=0;kk<3;kk++) maxat[kk]=Ia[kk];} + }}} + int prod=(2*hj[0]+1)*(2*hj[1]+1)*(2*hj[2]+1); + N_cum+=N_eff;__assertf( (N_cum==prod),("N_cum:%d/%d",N_cum,prod),-1); + for(kk=0;kk<3;kk++) hjLAST[kk]=hj[kk]; + + // (ia) expands outward if any of f(x) at boundary is larger than abs_thr ... + int ninc=0;char iInc[3]={0,0,0};int I; + for(I=0;I<3;I++){ + int J=(I+1)%3,K=(I+2)%3; + Ia[J]=0;Ia[K]=0; + Ia[I]=-hj[I]; double dum1=cabs(zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]); + Ia[I]=hj[I]; double dum2=cabs(zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]); + if( dum1>=abs_thr || dum2>=abs_thr ){ hj[I]+=hj_step[I]; ninc+=1; iInc[I]=1;} + } + *ermax=abs_max; + // (ib) any of f(x) in the final shell exceeds abs_thr expand in all direction by 1 ... + // (ii) if ( margin != NULL ) expands in each direction by margin[:] + if( ninc == 0 ){ + if(abs_max>abs_thr){ + hj[0]+=1;hj[1]+=1;hj[2]+=1; + } else { + if( (margin != NULL) && (n_extra_loop==0) ){ + hj[0]+=margin[0];hj[1]+=margin[1];hj[2]+=margin[2];n_extra_loop++; + } else { + cvgd=1; break; + } + } + } + //printf("#fill_zbuf:loop%d %d %d %d DONE ninc:%d absmax:%e/thr:%e\n",nloop,hj[0],hj[1],hj[2],ninc,abs_max,abs_thr);fflush(stdout); + int Noverflow=0,ioverflow[3]={0,0,0}; + for (I=0;I<3;I++) { if(hj[I]>Hj[I]) Noverflow++;ioverflow[I]=1;} + if( Noverflow==0 ) continue; + int margin=2; + int Hj_new[3]={0,0,0}; + for(I=0;I<3;I++){ + if(iInc[I]==0){ if(hj[I]+margin<=Hj[I]){ Hj_new[I]=Hj[I]; } + else { Hj_new[I]=hj[I]+margin;} } + else { Hj_new[I]=hj[I]+margin;} + } + dcmplx ***zbuf_new=z3alloc_i( 2*Hj_new[0]+1, 2*Hj_new[1]+1, 2*Hj_new[2]+1, 0.0 ); + for(Ia[0]=-Hj[0];Ia[0]<=Hj[0];Ia[0]++){ + for(Ia[1]=-Hj[1];Ia[1]<=Hj[1];Ia[1]++){ + for(Ia[2]=-Hj[2];Ia[2]<=Hj[2];Ia[2]++){ + dcmplx cdum=zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]; + zbuf_new[ Ia[0]+Hj_new[0] ][ Ia[1]+Hj_new[1] ][ Ia[2]+Hj_new[2] ] = cdum; + }}} + for(kk=0;kk<3;kk++) p_Hj[0][kk]=Hj_new[kk]; + p_zbuf[0]=zbuf_new; + //printf("#zbuf switches from %p %p to %p %p Hj %d,%d,%d\n",zbuf,zbuf[0][0], + // p_zbuf[0],p_zbuf[0][0][0], p_Hj[0][0], p_Hj[0][1], p_Hj[0][2]); + z3free(zbuf);zbuf=NULL; + continue; + } + return cvgd; +} + +int fill_zbuf1x(int *hj,dcmplx ****p_zbuf,int **p_Hj,const double abs_thr, + const int ixyz,Gaussian *lhs,Gaussian *rhs,int spdm,double *BravisVectors,double *Vectorfield,const int *margin,double *ermax, + dcmplx ***zbuf_REFR,const int *Hj_REFR,const int *hj_REFR){ + double *ax=BravisVectors,*ay=BravisVectors+3,*az=BravisVectors+6; + *ermax=-1.0; + int *Hj_ini=p_Hj[0]; + static int hj_0[3]={1,1,1}; + static int hj_step[3]={1,1,1}; + __assertf(hj[0]>=1 && hj[1]>=1 && hj[2]>=1,("wrong ini hj 001"),-1); + __assertf(hj[0]<=Hj_ini[0] && hj[1]<=Hj_ini[1] && hj[2]<=Hj_ini[2],("wrong ini hj 002"),-1); + // hj[0]=__MIN(Hj_ini[0],hj_0[0]);hj[1]=__MIN(Hj_ini[1],hj_0[1]);hj[2]=__MIN(Hj_ini[2],hj_0[2]); + int cvgd=0; + int Ia[3]={0,0,0}; + int nloop=0;int hjLAST[3]={-1,-1,-1}; + int n_extra_loop=0;int N_cum=0; + while( (nloop++)<999 ){ int kk; + dcmplx ***zbuf=p_zbuf[0]; + int *Hj=p_Hj[0]; + // printf("#fill_zbuf:loop%d %d %d %d",nloop,hj[0],hj[1],hj[2]);fflush(stdout); + double abs_max=-1;int maxat[3]={0,0,0};int N_eff=0; + int in_REFR=0; if( hj[0]<=hj_REFR[0] && hj[1]<=hj_REFR[1] && hj[2]<=hj_REFR[2] ) in_REFR=1; + //printf("#loop:%d %d,%d,%d / %d,%d,%d prev:%d,%d,%d\n",nloop,hj[0],hj[1],hj[2], Hj[0],Hj[1],Hj[2], hjLAST[0],hjLAST[1],hjLAST[2]); + for(Ia[0]=-hj[0];Ia[0]<=hj[0];Ia[0]++){ int o0=( abs(Ia[0])<=hjLAST[0]); + for(Ia[1]=-hj[1];Ia[1]<=hj[1];Ia[1]++){ int o1=(o0 && abs(Ia[1])<=hjLAST[1]); + for(Ia[2]=-hj[2];Ia[2]<=hj[2];Ia[2]++){ int o2=(o1 && abs(Ia[2])<=hjLAST[2]); + if(o2) { + continue;} + N_eff++; + double displ[3]={ ax[0]*Ia[0] + ay[0]*Ia[1] + az[0]*Ia[2], + ax[1]*Ia[0] + ay[1]*Ia[1] + az[1]*Ia[2], ax[2]*Ia[0] + ay[2]*Ia[1] + az[2]*Ia[2]}; + //dcmplx cdmy=zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]; + dcmplx ovlp00; + if( in_REFR || ( abs(Ia[0])<=hj_REFR[0] && abs(Ia[1])<=hj_REFR[1] && abs(Ia[2])<=hj_REFR[2] ) ){ + ovlp00 = zbuf_REFR[ Ia[0]+Hj_REFR[0] ][ Ia[1]+Hj_REFR[1] ][ Ia[2]+Hj_REFR[2] ]; + } else { ovlp00 = Gaussian_ovlpNew(lhs,rhs,Vectorfield,displ);} + + dcmplx ovlp=Gaussian_ovlpNewX(lhs,rhs,ixyz,ovlp00,Vectorfield,displ); + + zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]=ovlp; + double dum=cabs(ovlp); + if( dum>abs_max ){ abs_max=dum; for(kk=0;kk<3;kk++) maxat[kk]=Ia[kk];} + }}} + int prod=(2*hj[0]+1)*(2*hj[1]+1)*(2*hj[2]+1); + N_cum+=N_eff;__assertf( (N_cum==prod),("N_cum:%d/%d",N_cum,prod),-1); + for(kk=0;kk<3;kk++) hjLAST[kk]=hj[kk]; + + // (ia) expands outward if any of f(x) at boundary is larger than abs_thr ... + int ninc=0;char iInc[3]={0,0,0};int I; + for(I=0;I<3;I++){ + int J=(I+1)%3,K=(I+2)%3; + Ia[J]=0;Ia[K]=0; + Ia[I]=-hj[I]; double dum1=cabs(zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]); + Ia[I]=hj[I]; double dum2=cabs(zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]); + if( dum1>=abs_thr || dum2>=abs_thr ){ hj[I]+=hj_step[I]; ninc+=1; iInc[I]=1;} + } + *ermax=abs_max; + // (ib) any of f(x) in the final shell exceeds abs_thr expand in all direction by 1 ... + // (ii) if ( margin != NULL ) expands in each direction by margin[:] + if( ninc == 0 ){ + if(abs_max>abs_thr){ + hj[0]+=1;hj[1]+=1;hj[2]+=1; + } else { + if( (margin != NULL) && (n_extra_loop==0) ){ + hj[0]+=margin[0];hj[1]+=margin[1];hj[2]+=margin[2];n_extra_loop++; + } else { + cvgd=1; break; + } + } + } + //printf("#fill_zbuf:loop%d %d %d %d DONE ninc:%d absmax:%e/thr:%e\n",nloop,hj[0],hj[1],hj[2],ninc,abs_max,abs_thr);fflush(stdout); + int Noverflow=0,ioverflow[3]={0,0,0}; + for (I=0;I<3;I++) { if(hj[I]>Hj[I]) Noverflow++;ioverflow[I]=1;} + if( Noverflow==0 ) continue; + int margin=2; + int Hj_new[3]={0,0,0}; + for(I=0;I<3;I++){ + if(iInc[I]==0){ if(hj[I]+margin<=Hj[I]){ Hj_new[I]=Hj[I]; } + else { Hj_new[I]=hj[I]+margin;} } + else { Hj_new[I]=hj[I]+margin;} + } + dcmplx ***zbuf_new=z3alloc_i( 2*Hj_new[0]+1, 2*Hj_new[1]+1, 2*Hj_new[2]+1, 0.0 ); + for(Ia[0]=-Hj[0];Ia[0]<=Hj[0];Ia[0]++){ + for(Ia[1]=-Hj[1];Ia[1]<=Hj[1];Ia[1]++){ + for(Ia[2]=-Hj[2];Ia[2]<=Hj[2];Ia[2]++){ + dcmplx cdum=zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]; + zbuf_new[ Ia[0]+Hj_new[0] ][ Ia[1]+Hj_new[1] ][ Ia[2]+Hj_new[2] ] = cdum; + }}} + for(kk=0;kk<3;kk++) p_Hj[0][kk]=Hj_new[kk]; + p_zbuf[0]=zbuf_new; + //printf("#zbuf switches from %p %p to %p %p Hj %d,%d,%d\n",zbuf,zbuf[0][0], + // p_zbuf[0],p_zbuf[0][0][0], p_Hj[0][0], p_Hj[0][1], p_Hj[0][2]); + z3free(zbuf);zbuf=NULL; + continue; + } + return cvgd; +} + +//ovlp=Gaussian_ovlpNew(lhs,rhs,Vectorfield,displ); +int fill_zbuf_oldver(dcmplx ****p_zbuf,int **p_Hj,const double abs_thr, + Gaussian *lhs,Gaussian *rhs,int spdm,double *BravisVectors,double *Vectorfield,const int *margin){ + double *ax=BravisVectors,*ay=BravisVectors+3,*az=BravisVectors+6; + + int *Hj_ini=p_Hj[0]; + static int hj_0[3]={1,1,1}; + static int hj_step[3]={1,1,1}; + int hj[3]={__MIN(Hj_ini[0],hj_0[0]), __MIN(Hj_ini[1],hj_0[1]), __MIN(Hj_ini[2],hj_0[2])}; + int cvgd=0; + int Ia[3]={0,0,0}; + int nloop=0;int hjLAST[3]={-1,-1,-1}; + int n_extra_loop=0;int N_cum=0; + while( (nloop++)<999 ){ int kk; + dcmplx ***zbuf=p_zbuf[0]; + int *Hj=p_Hj[0]; + double abs_max=-1;int maxat[3]={0,0,0};int N_eff=0; + //printf("#loop:%d %d,%d,%d / %d,%d,%d prev:%d,%d,%d\n",nloop,hj[0],hj[1],hj[2], Hj[0],Hj[1],Hj[2], hjLAST[0],hjLAST[1],hjLAST[2]); + for(Ia[0]=-hj[0];Ia[0]<=hj[0];Ia[0]++){ int o0=( abs(Ia[0])<=hjLAST[0]); + for(Ia[1]=-hj[1];Ia[1]<=hj[1];Ia[1]++){ int o1=(o0 && abs(Ia[1])<=hjLAST[1]); + for(Ia[2]=-hj[2];Ia[2]<=hj[2];Ia[2]++){ int o2=(o1 && abs(Ia[2])<=hjLAST[2]); + if(o2) { /*printf("#skipping %d,%d,%d:%f+j%f\n",Ia[0],Ia[1],Ia[2], + creal( zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ] ), + cimag( zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ] ));*/ + continue;} + N_eff++; + double displ[3]={ ax[0]*Ia[0] + ay[0]*Ia[1] + az[0]*Ia[2], + ax[1]*Ia[0] + ay[1]*Ia[1] + az[1]*Ia[2], ax[2]*Ia[0] + ay[2]*Ia[1] + az[2]*Ia[2]}; + dcmplx cdmy=zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]; + //printf("#Gaussian_ovlpNew... %d %d %d / %d %d %d\n",Ia[0],Ia[1],Ia[2], Hj[0],Hj[1],Hj[2]);fflush(stdout); + dcmplx ovlp=Gaussian_ovlpNew(lhs,rhs,Vectorfield,displ); + // if( (Ia[0]==0 && Ia[1]==0 && Ia[2]==0) || cabs(ovlp)>1.0e-3 ){ + // printf("%d,%d,%d displ=%f %f %f ovlp:%f %f\n",Ia[0],Ia[1],Ia[2],displ[0],displ[1],displ[2],creal(ovlp),cimag(ovlp)); + // } + zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]=ovlp; + double dum=cabs(ovlp); + if( dum>abs_max ){ abs_max=dum; for(kk=0;kk<3;kk++) maxat[kk]=Ia[kk];} + }}} + int prod=(2*hj[0]+1)*(2*hj[1]+1)*(2*hj[2]+1); + N_cum+=N_eff;__assertf( (N_cum==prod),("N_cum:%d/%d",N_cum,prod),-1); + //printf("#end loop:%d %d,%d,%d / %d,%d,%d prev:%d,%d,%d N_cum=%d absMAX=%e\n", + // nloop,hj[0],hj[1],hj[2], Hj[0],Hj[1],Hj[2], hjLAST[0],hjLAST[1],hjLAST[2],N_cum,abs_max); + for(kk=0;kk<3;kk++) hjLAST[kk]=hj[kk]; + + // check values at boundary... + int ninc=0;char iInc[3]={0,0,0};int I; + for(I=0;I<3;I++){ + int J=(I+1)%3,K=(I+2)%3; + Ia[J]=0;Ia[K]=0; + Ia[I]=-hj[I]; double dum1=cabs(zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]); + Ia[I]=hj[I]; double dum2=cabs(zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]); + if( dum1>=abs_thr || dum2>=abs_thr ){ hj[I]+=hj_step[I]; ninc+=1; iInc[I]=1;} + } + if( ninc == 0 ){ + if(abs_max>abs_thr){ + // printf("#! abs_max=%e at %d,%d,%d / %d,%d,%d\n",abs_max,maxat[0],maxat[1],maxat[2], hj[0],hj[1],hj[2]); + hj[0]+=1;hj[1]+=1;hj[2]+=1; + } else { + // printf("#Loop converges at %d,%d,%d: abs_max=%e at %d,%d,%d ",hj[0],hj[1],hj[2],abs_max,maxat[0],maxat[1],maxat[2]); + if( (margin != NULL) && (n_extra_loop==0) ){ + hj[0]+=margin[0];hj[1]+=margin[1];hj[2]+=margin[2];n_extra_loop++; + // printf("....... adding to extra loop:%d,%d,%d\n",hj[0],hj[1],hj[2]); + } else { + // if( margin != NULL ) printf("OK n_extra:%d\n",n_extra_loop); + // else printf(" no extra loop\n"); + cvgd=1; break; + } + } + } /*else { + printf("#Loop expands in xyz:%d,%d,%d\n",iInc[0],iInc[1],iInc[2]); + }*/ + int Noverflow=0,ioverflow[3]={0,0,0}; + for (I=0;I<3;I++) { if(hj[I]>Hj[I]) Noverflow++;ioverflow[I]=1;} + if( Noverflow==0 ) continue; + int margin=2; + int Hj_new[3]={0,0,0}; + for(I=0;I<3;I++){ + if(iInc[I]==0){ if(hj[I]+margin<=Hj[I]){ Hj_new[I]=Hj[I]; } + else { Hj_new[I]=hj[I]+margin;} } + else { Hj_new[I]=hj[I]+margin;} + } + dcmplx ***zbuf_new=z3alloc_i( 2*Hj_new[0]+1, 2*Hj_new[1]+1, 2*Hj_new[2]+1, 0.0 ); + for(Ia[0]=-Hj[0];Ia[0]<=Hj[0];Ia[0]++){ + for(Ia[1]=-Hj[1];Ia[1]<=Hj[1];Ia[1]++){ + for(Ia[2]=-Hj[2];Ia[2]<=Hj[2];Ia[2]++){ + dcmplx cdum=zbuf[ Hj[0]+Ia[0] ][ Hj[1]+Ia[1] ][ Hj[2]+Ia[2] ]; + zbuf_new[ Ia[0]+Hj_new[0] ][ Ia[1]+Hj_new[1] ][ Ia[2]+Hj_new[2] ] = cdum; + }}} + for(kk=0;kk<3;kk++) p_Hj[0][kk]=Hj_new[kk]; + p_zbuf[0]=zbuf_new; + //printf("#zbuf switches from %p %p to %p %p Hj %d,%d,%d\n",zbuf,zbuf[0][0], + // p_zbuf[0],p_zbuf[0][0][0], p_Hj[0][0], p_Hj[0][1], p_Hj[0][2]); + z3free(zbuf);zbuf=NULL; + continue; + } + if(0){ + int *Hjf=p_Hj[0];dcmplx ***zbuf=p_zbuf[0]; + int hjp[3]={1,1,1};int Ia[3]={0,0,0}; + for(Ia[0]=-hjp[0];Ia[0]<=hjp[0];Ia[0]++){ + printf("#zbuf:%02d\n",Ia[0]); + for(Ia[1]=-hjp[1];Ia[1]<=hjp[1];Ia[1]++){ + for(Ia[2]=-hjp[2];Ia[2]<=hjp[2];Ia[2]++){ + dcmplx cdum=zbuf[ Ia[0]+Hjf[0] ][ Ia[1]+Hjf[1] ][ Ia[2]+Hjf[2] ]; + printf("%10.4f+j%10.4f ",creal(cdum),cimag(cdum)); + } + printf("\n"); + } + printf("\n\n"); + } + } + return cvgd; +} +#define FPATH_checkFTx "checkFTx_pbcoverlap.dat" +#define FPATH_FTwarningx "checkFTx_pbcoverlap_warning.log" + +dcmplx **pbc_overlapx(int Iblock,int Ilhs,int Jrhs,Gaussian *lhs,Gaussian *rhs,int spdm,double *BravisVectors,double *Vectorfield, + int nKpoints,double *kvectors, + int *iargs,const int clear_buffer,const int Ldim_margin){ + double *ax=BravisVectors,*ay=BravisVectors+3,*az=BravisVectors+6; + const int Idbgng=0; + const int O_=0,X_=1,Y_=2,Z_=3;int I; +#ifdef STATIC_ZBUFX + static dcmplx ***p_zbuf[4]={NULL,NULL,NULL,NULL}; static int *p_Hj[4]={NULL,NULL,NULL,NULL}; + if( clear_buffer < 0 ){ + for(I=0;I<4;I++){ z3free(p_zbuf[I]);p_zbuf[I]=NULL;i1free(p_Hj[I]);p_Hj[I]=NULL;} return NULL;} +#else + dcmplx ***p_zbuf[4]={NULL,NULL,NULL,NULL}; int *p_Hj[4]={NULL,NULL,NULL,NULL}; + if( clear_buffer < 0 ) return NULL; +#endif + static double buf_ermax_[4]={0,0,0,0}, FT_ermax_[4]={0,0,0,0}, walltimeAVG[4]={0,0,0,0};const double FT_errthr=1.0e-6; + static double FTavgERR[4]={0,0,0,0}; static long FTavgERR_count[4]={0,0,0,0},walltimeAVG_count[4]={0,0,0,0}; + static double FTmaxERR[4]={-1,-1,-1,-1};static int FTmaxERR_Hjx[4]={-1,-1,-1,-1},FTmaxERR_Hjy[4]={-1,-1,-1,-1},FTmaxERR_Hjz[4]={-1,-1,-1,-1}; +#define upd_FTmaxERR(Idx,val,hjs) { if((val)>FTmaxERR[(Idx)]){ FTmaxERR[(Idx)]=val; FTmaxERR_Hjx[(Idx)]=hjs[0]; FTmaxERR_Hjy[(Idx)]=hjs[1]; FTmaxERR_Hjz[(Idx)]=hjs[2];} } + + if( p_zbuf[0]==NULL ){ + const int Hx=3,Hy=3,Hz=3; + for(I=0;I<4;I++){ + p_Hj[I]=i1alloc(3); p_Hj[I][0]=Hx; p_Hj[I][1]=Hy; p_Hj[I][2]=Hz; + p_zbuf[I]=z3alloc_i(2*Hx+1,2*Hy+1,2*Hz+1, 0.0);} + /* printf("#pbc_overlap:zbuf allocates:%p %p Hj[%d]:%p:%d,%d,%d\n",p_zbuf[I],p_zbuf[I][0][0],I,p_Hj[I], + p_Hj[I][0],p_Hj[I][1],p_Hj[I][2]); }*/ + } + __assertf((p_zbuf[0]!=NULL && p_Hj[0]!=NULL),("pbc_overlap.0000"),-1); + static int n_call=0; n_call++; + double abs_thr=1.0e-7; int kp; + double **kXa=d2alloc(nKpoints,3),*kvec=NULL; + for(kp=0,kvec=kvectors;kp 0 ) { margin=i1alloc(3); margin[0]=Ldim_margin;margin[1]=Ldim_margin;margin[2]=Ldim_margin;} + int hj_O[3]={1,1,1}; + for(I=0;I<4;I++){ const int Ixyz=I-1; + int hj_1[3]={1,1,1}; // requirement: hj[:]=1 + double wct02=__ctime; + if(I==0 || I==3){ + if(n_call==1 || n_call==20 || n_call == 100 || buf_ermax_[I] < ermx){ buf_ermax_[I]=__MAX(ermx,buf_ermax_[I]); + _Printf( ("#%06d:pbc_overlap%c: hj=%d,%d,%d ermx=%e elapsed:%f buf_ermax_:%e\n",n_call,ctype,hj[0],hj[1],hj[2],ermx,wct02-wct01,buf_ermax_[I]) );} + } + + const double *ax=BravisVectors,*ay=BravisVectors+3,*az=BravisVectors+6; + for(kp=0;kp FT_errthr ){ + if(MPIrank_==0){ + int N_error=fcountup("FTerror_warn__countup.txt", 1); + if(N_error<50){ _Fwrite( "FTerror_warn.log", 1, 1,fpdmy, + (fpdmy,"#pbc_overlapx:%02d.%03d.%03d %c [%02d]:ERR=%12.4e %16.8f+j%16.8f / %16.8f+j%16.8f %d,%d,%d ", + Iblock,Ilhs,Jrhs,kp,ctype,FT_errbuf[I][kp],creal(cur),cimag(cur),creal(prev),cimag(prev),Hj_I[0],Hj_I[1],Hj_I[2] ) );} } + } + } + double wct03=__ctime; walltimeAVG[I]+=(wct03-wct01);walltimeAVG_count[I]++; + } + if( margin != NULL ) {i1free(margin);margin=NULL;} + //int N_call=fcountup("FTerror__countup.txt", 1); + if( FTavgERR_count[0] == 1000 || FTavgERR_count[0] == 10000 || FTavgERR_count[0] == 20000 ){ + double avgERR[4],tavg[4]; + for(I=0;I<4;I++) { avgERR[I]=sqrt( FTavgERR[I]/(double) FTavgERR_count[I]); tavg[I]=walltimeAVG[I]/(double) walltimeAVG_count[I]; + _Fwrite( "FTerror.log",1,1,fpdmy,(fpdmy,"#pbc_overlapx:#$%02d:avgERR:%e,%e,%e,%e maxERR:%e (%d,%d,%d) avgTIME:%f %f %f %f LdMARGIN:%d ",\ + MPIrank_,avgERR[0],avgERR[1],avgERR[2],avgERR[3], FTmaxERR[0],FTmaxERR_Hjx[0],FTmaxERR_Hjy[0],FTmaxERR_Hjz[0],\ + tavg[0],tavg[1],tavg[2],tavg[3], Ldim_margin) );} + } + d2free(kXa);kXa=NULL;d2free(FT_errbuf);FT_errbuf=NULL; +#ifdef STATIC_ZBUFX + if( clear_buffer ){ + for(I=0;I<4;I++){ z3free(p_zbuf[I]);p_zbuf[I]=NULL; i1free(p_Hj[I]); p_Hj[I]=NULL; } } +#else + for(I=0;I<4;I++){ z3free(p_zbuf[I]); p_zbuf[I]=NULL; i1free(p_Hj[I]); p_Hj[I]=NULL; } +#endif + return retbuf; +#undef upd_FTmaxERR +} +#define _Dbglogger(fptr1,msg,Append) +#define _Dbglogger_Gaussian(fptr1,msg,Append) +#define _Dbglogger_zbuf(fptr1,msg, hxyz,Append) + +int free_buf(void *buf){ + printf("#free_buf:releasing mem:%p %ld..",buf,(long)buf);fflush(stdout); + free(buf); + printf("#free_buf:released mem\n");fflush(stdout); + return 0; + +} +int free_zbuf(dcmplx *zbuf){ + printf("#free_zbuf:releasing mem:%p %ld..",zbuf,(long)zbuf);fflush(stdout); + z1free(zbuf); + printf("#free_zbuf:released mem\n");fflush(stdout); + return 0; +} +dcmplx *test_alloc(const int N1,const int N2,const int N3){ + dcmplx ***zbuf=z3alloc_i(N1,N2,N3,1.192+_I*1.868);dcmplx *retv=zbuf[0][0];free(zbuf[0]);free(zbuf); + long laddr=(long)retv; + printf("#test_alloc:returning:%p(%ld) %d*%d*%d\n",retv,laddr,N1,N2,N3); + return retv; +} +/* +#define _Dbglogger(fptr1,msg,Append) {char dbgfnme[50];sprintf(dbgfnme,"pbc_overlap_%02d_%02d_%02d_%04d.log",MPIrank_,Ilhs,Jrhs,n_loop);\ +FILE *fptr1=fopen(dbgfnme,( (Append) ? "w":"a"));fprintf msg;fclose(fptr1);}// +#define _Dbglogger_Gaussian(fptr1,msg,Append) {char dbgfnme[50];sprintf(dbgfnme,"pbc_overlap_%02d_%02d_%02d_%04d.log",MPIrank_,Ilhs,Jrhs,n_loop);\ +FILE *fptr1=fopen(dbgfnme,( (Append) ? "w":"a"));fprintf msg;Gaussian_fprtout((fptr1,"#LHS:%02d:",Ilhs),fptr1,lhs);\ +Gaussian_fprtout((fptr1,"#RHS:%02d:",Jrhs),fptr1,rhs);fclose(fptr1);}// + +#define _Dbglogger_zbuf(fptr1,msg, hxyz,Append) {char dbgfnme[50];sprintf(dbgfnme,"pbc_overlap_%02d_%02d_%02d_%04d.log",MPIrank_,Ilhs,Jrhs,n_loop);\ +FILE *fptr1=fopen(dbgfnme,"a");int ii,jj,kk;fprintf msg;\ +for(ii=-hxyz[0];ii<=hxyz[0];ii++){ for(jj=-hxyz[1];jj<=hxyz[1];jj++){ for(kk=-hxyz[2];kk<=hxyz[2];kk++){\ +fprintf(fptr1,"%12.6f %12.6f ", creal( p_zbuf[0][ ii+p_Hj[0][0] ][ jj+p_Hj[0][1] ][ kk+p_Hj[0][2] ] ),\ + cimag( p_zbuf[0][ ii+p_Hj[0][0] ][ jj+p_Hj[0][1] ][ kk+p_Hj[0][2] ] ) );}}} fclose(fptr1); }// +*/ + +dcmplx *pbc_overlap(int Iblock,int Ilhs,int Jrhs,Gaussian *lhs,Gaussian *rhs,int spdm,double *BravisVectors,double *Vectorfield, + int nKpoints,double *kvectors, + int *iargs,const int clear_buffer,const int Ldim_margin){ + const int Idbgng=0; + static int n_loop=0; if(Ilhs==0 && Jrhs==0)n_loop++;char Append_dbglogf=(n_loop==1); + static int n_call=0; n_call++; + static dcmplx ***p_zbuf[1]={NULL}; + static int *p_Hj[1]={NULL}; + if( clear_buffer < 0 ){ + z3free(p_zbuf[0]);p_zbuf[0]=NULL; i1free(p_Hj[0]); p_Hj[0]=NULL; return NULL; } + if( p_zbuf[0]==NULL ){ + //int Lx=iargs[0],Ly=iargs[1],Lz=iargs[2]; + //int Hx=Lx/2,Hy=Ly/2,Hz=Lz/2; + const int Hx=3,Hy=3,Hz=3; + p_Hj[0]=i1alloc(3); + p_Hj[0][0]=Hx; p_Hj[0][1]=Hy; p_Hj[0][2]=Hz; + p_zbuf[0]=z3alloc_i(2*Hx+1,2*Hy+1,2*Hz+1, 0.0); + _Dbglogger(dbgfp1,(dbgfp1,"#zbuf allocates:%p:%d,%d,%d\n",p_zbuf[0],Hx,Hy,Hz),Append_dbglogf);Append_dbglogf=1; + printf("#pbc_overlap:zbuf allocates:%p %p Hj:%d,%d,%d\n",p_zbuf[0],p_zbuf[0][0][0],p_Hj[0][0],p_Hj[0][1],p_Hj[0][2]); + } + _Dbglogger_Gaussian(dbgfp1,(dbgfp1,""),Append_dbglogf);Append_dbglogf=1; + __assertf((p_zbuf[0]!=NULL && p_Hj[0]!=NULL),("pbc_overlap.0000"),-1); + double abs_thr=1.0e-7; + int *margin=NULL; + if( Ldim_margin > 0 ) { margin=i1alloc(3); margin[0]=Ldim_margin;margin[1]=Ldim_margin;margin[2]=Ldim_margin;} + int hj[3]={1,1,1}; double ermax=0; + static double error_max=-1; + double wct01=__ctime; + +/* if(Ilhs==1 && Jrhs==2){ double displ[3]={0,0,0}; + dcmplx zdum=Gaussian_ovlpNew_verbose(lhs,rhs,Vectorfield,displ);printf("#zovlp:%f %f\n",__RandI(zdum)); + __assertf( 0,("pbc_overlap.0000"),-1); + }*/ + fill_zbuf1(hj, p_zbuf,p_Hj,abs_thr, lhs, rhs, spdm, BravisVectors, Vectorfield, margin, &ermax); + _Dbglogger_zbuf(dbgfp1,(dbgfp1,"fill_zbuf1:%d,%d,%d/%d,%d,%d",hj[0],hj[1],hj[2],p_Hj[0][0],p_Hj[0][1],p_Hj[0][2]), hj, Append_dbglogf);Append_dbglogf=1; + double wct02=__ctime; + if(n_call==1 || n_call==20 || n_call == 100 || error_max < ermax){ error_max=__MAX(ermax,error_max); + printf("#%06d:pbc_overlap: hj=%d,%d,%d ermax=%e elapsed:%f error_max:%e\n",n_call,hj[0],hj[1],hj[2],ermax,wct01-wct01,error_max);} + if( margin != NULL ) {i1free(margin);margin=NULL;} + double *ax=BravisVectors,*ay=BravisVectors+3,*az=BravisVectors+6; + int kp; + double **kXa=d2alloc(nKpoints,3),*kvec=NULL; + for(kp=0,kvec=kvectors;kp2) fprintf(fp," \t p2rev:%12.6f %12.6f (%12.4e)",creal(p2rev),cimag(p2rev),cabs(cur-p2rev)); + if(nstep>3) fprintf(fp," \t p2rev:%12.6f %12.6f (%12.4e)",creal(p3rev),cimag(p3rev),cabs(cur-p3rev)); + if(nstep>4) fprintf(fp," \t p2rev:%12.6f %12.6f (%12.4e)",creal(p4rev),cimag(p4rev),cabs(cur-p4rev)); + fprintf(fp,"\n"); + } + if(ft_ermax 1.0e-6 ){ fprintf((fp==NULL ? stdout:fp), + "#!W pbc_overlap:%02d.%03d.%03d [%02d]:ERR=%12.4e %16.8f+j%16.8f / %16.8f+j%16.8f %d,%d,%d\n", + Iblock,Ilhs,Jrhs,kp,err[kp],creal(cur),cimag(cur),creal(prev),cimag(prev),Hj[0],Hj[1],Hj[2] );} + double dum=fabs(cimag(cur));if(dum>max_absIM){ max_absIM=dum;kp_maxabsIM=kp;} + } + if(fp!=NULL) fprintf(fp,"### pbc_overlap:%02d.%03d.%03d estimated ermax:%12.4e @[%02d] %16.8f+j%16.8f / %16.8f+j%16.8f %d,%d,%d\n", + Iblock,Ilhs,Jrhs,err[kp],kp,creal(values[0]),cimag(values[0]),creal(values[1]),cimag(values[1]),Hx,Hy,Hz); + if(fp!=NULL) fprintf(fp,"### MAX abs IM:%14.6f as [%d] %14.6f %14.6f\n",max_absIM,kp_maxabsIM,creal(ret[kp_maxabsIM]),cimag(ret[kp_maxabsIM])); + if( ft_ermax > 1.0e-6 ){ FILE *fpA[2]={NULL,NULL};fpA[0]=(fp==NULL ? stdout:fp);fpA[1]=fopen(FPATH_FTwarning,"a");int kk; + for(kk=0;kk<2;kk++){ fprintf(fpA[kk], + "#!W pbc_overlap:%02d.%03d.%03d ermax [%02d]:ERR=%12.4e cur: %16.8f+j%16.8f / prev_step: %16.8f+j%16.8f Hj:%d,%d,%d\n", + Iblock,Ilhs,Jrhs,kp_ermax,err[kp_ermax],creal(values[0]),cimag(values[0]),creal(values[1]),cimag(values[1]),Hj[0],Hj[1],Hj[2]);} + fclose(fpA[1]); } + if( fpOUT!=NULL )fclose(fpOUT); + //printf("#pbc_overlap:%f+j%f\n",creal(ret[0]),cimag(ret[0]));fflush(stdout); + d2free(kXa);kXa=NULL;d1free(err);err=NULL; + if( clear_buffer ){ + z3free(p_zbuf[0]);p_zbuf[0]=NULL; + i1free(p_Hj[0]); p_Hj[0]=NULL; + } + return ret; +} + +dcmplx *pbc_overlap_old(Gaussian *lhs,Gaussian *rhs,int spdm,double *BravisVectors,double *Vectorfield,int nKpoints,double *kvectors, + int *iargs){ + const int Lx=iargs[0],Ly=iargs[1],Lz=iargs[2]; + double *ax=BravisVectors,*ay=BravisVectors+3,*az=BravisVectors+6; + int kp,Ix,Jy,Kz; const int Hx=Lx/2, Hy=Ly/2, Hz=Lz/2, Qx=Lx/4, Qy=Ly/4, Qz=Lz/4; + double **kXa=d2alloc(nKpoints,3),*kvec=NULL; + for(kp=0,kvec=kvectors;kpR,rhs->R),creal(ovlp),cimag(ovlp),creal(ret[0]),cimag(ret[0])); + }}} + //printf("#pbc_overlap:%f+j%f\n",creal(ret[0]),cimag(ret[0]));fflush(stdout); + d2free(kXa);kXa=NULL; + return ret; +} + + +dcmplx Gaussian_overlap(Gaussian *lhs,Gaussian *rhs,const double *Vecfield,const double *Rdispl){ + int i,j; const int Nlhs=lhs->N, Nrhs=rhs->N; + double R[6]={lhs->R[0],lhs->R[1],lhs->R[2], rhs->R[0] + Rdispl[0],rhs->R[1]+ Rdispl[1],rhs->R[2]+ Rdispl[2]}; + double alpha[2]={0,0}; const int Nga=2; + ushort xe_pows[6]; + dcmplx ret=0.0; + for(i=0;ialpha[i]; + xe_pows[0]=lhs->pows[i][0]; xe_pows[1]=lhs->pows[i][1]; xe_pows[2]=lhs->pows[i][2]; + for(j=0;jalpha[j]; + xe_pows[3]=rhs->pows[j][0]; xe_pows[4]=rhs->pows[j][1]; xe_pows[5]=rhs->pows[j][2]; + ushort diffs[6]={0,0,0, 0,0,0}; + dcmplx ovlp=calc_matrix( ope_xovlp1, xe_pows, diffs, R, alpha, Nga, Vecfield, 3); + ret+= ovlp* lhs->cofs[i]* rhs->cofs[j]; + } + } + return ret; +} +#define NgaMax_3 36 +#define NnucPowsMax 6 // in fact 3 +// matrix elmt of normalized Cartesian Gaussian +// e.g. overlap = sqrt(__PI/(alph[0]+alph[1]))**3 *exp(-(al*bt/(al+bt))*( (A-B)**2 ) +// @param xe_pows[3+3] +// @param diffs [3+3] +// @param A [3+3] +// @param alph [1+1] +// @param nga :=2 for ope overlap +// @param args A_over_c[3] +dcmplx calc_matrix( dcmplx (*ope)(ushort *,ushort *,double *,double *,ushort,double *,ushort), + ushort *xe_pows,ushort *diffs, double *A,double *alph,ushort nga,double *args,ushort nargs){ + int i,j,ij,kk; + double dF,F_2,ret=0.0; + ushort diffs1[NgaMax_3],xe_pows1[NgaMax_3]; + ushort Xnuc_pows[NnucPowsMax]; + ij=0; for(i=0;i1){ + xe_pows1[ij]=xe_pows[ij]-2; + F_2=calc_matrix(ope,xe_pows1,diffs,A,alph,nga,args,nargs); + ret=ret+( xe_pows[ij]-1)*0.50*F_2/alph[i]; + } + return ret; + } + }} + __a1clr(Xnuc_pows,NnucPowsMax,kk); // empty array + // printf("at bottom\n"); fflush(stdout); + ret=ope(diffs,Xnuc_pows,A,alph,nga,args,nargs); + // printf("at bottom %f\n",ret); fflush(stdout); + return ret; +} + +// diffs[6] xdiff_LHS,ydiff_LHS,... +// Xnuc_Pows[3] power of (A-B)^{\mu} should be [0,0,0] at first call +dcmplx ope_xovlp1(ushort *diffs,ushort *Xnuc_Pows,double *A,double *alph,ushort Nga,double *args,ushort Nargs){ + double ret=0.0, dum,prod; + double gam=alph[0]*alph[1]/(alph[0]+alph[1]); + ushort i,j,ij,kk; + ushort *newdiffs,*newpows; long lnwdiffs,lnwpows; + short sgn=1; + double *AoverC=args; //printf("#VectorPotential:%f %f %f",AoverC[0],AoverC[1],AoverC[2]); + ij=0;for(i=0;i<2;i++){ + sgn=1-i*2; double fac=(alph[i]/(alph[0]+alph[1])); + for(j=0;j<3;j++,ij++){ + if(diffs[ij]){ + _clone_ush1( diffs, newdiffs, 6, lnwdiffs, kk); + _clone_ush1( Xnuc_Pows, newpows, 3, lnwpows, kk); + newdiffs[ij]--; + // reduce diffs by one and multiply i VecF^{\mu} al/(al+bt) + ret = _I * AoverC[j] * fac * ope_xovlp1(newdiffs,newpows,A,alph,Nga,args,Nargs); + newpows[j]++; // further multiply (A-B) + ret += -sgn*2.0*gam*ope_xovlp1(newdiffs,newpows,A,alph,Nga,args,Nargs); + if( Xnuc_Pows[j]>0 ){ + newpows[j]=Xnuc_Pows[j]-1; + dum=ope_xovlp1(newdiffs,newpows,A,alph,Nga,args,Nargs); + ret=ret+sgn*Xnuc_Pows[j]*dum; + } + _free_ush1( newpows, 3, lnwpows); + _free_ush1( newdiffs, 6, lnwdiffs); + + return ret; + } + } + } + double sqrDist,*B=A+3, expofac; + sqrDist=_sqrdist1(A,B); //sum( (A(:)-B(:))**2 ) + double Asqr=AoverC[0]*AoverC[0] + AoverC[1]*AoverC[1] + AoverC[2]*AoverC[2]; + expofac=exp(-gam*sqrDist - 0.25*Asqr/(alph[0]+alph[1])); + double G[3]={ (alph[0]*A[0]+alph[1]*B[0])/(alph[0]+alph[1]), (alph[0]*A[1]+alph[1]*B[1])/(alph[0]+alph[1]), (alph[0]*A[2]+alph[1]*B[2])/(alph[0]+alph[1]) }; + double G_dot_A=G[0]*AoverC[0] + G[1]*AoverC[1] + G[2]*AoverC[2]; + dcmplx zfac=( cos(G_dot_A)+_I*sin(G_dot_A) ); + dum= sqrt(__PI/(alph[0]+alph[1])); + ret= (dum*dum*dum) * expofac; +//printf("#cGaussian:ope_ovlp:dum:%f %f %f",dum,expofac,ret); + for(i=0;i<3;i++){ + prod=1.0;for(kk=0;kkJnuc,BS[i]->R[0],BS[i]->R[1],BS[i]->R[2]); + fprintf(fp,"#Gaussian_prtout:%s %d nPGTO:%d\n",title,i+1,BS[i]->N); + fprintf(fp,"##sub.pows:"); + for(j=0;jN;j++){ + fprintf(fp," %1d %1d %1d ",BS[i]->pows[j][0],BS[i]->pows[j][1],BS[i]->pows[j][2]);} fprintf(fp,"\n"); + fprintf(fp,"##sub.alph:"); + for(j=0;jN;j++){ + fprintf(fp,"%12.4e ",BS[i]->alpha[j]);} fprintf(fp,"\n"); + fprintf(fp,"##sub.cofs:"); + for(j=0;jN;j++){ fprintf(fp,"%12.6f ",BS[i]->cofs[j]);} fprintf(fp,"\n"); + } + fclose(fp); +} + +// [spdm+1,3,nKpoints,nCGTO_2,nCGTO_1,2] +dcmplx *calc_pbc_overlapsx(int nAtm, double *Rnuc, int *IZnuc, int nDa, int *distinctIZnuc, + const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs, + int nAtmB, double *RnucB, int *IZnucB, int nDb, int *distinctIZnucB, + const int *NshB, const int *ellB, const int *n_cols, const int *npGTOB, const double *alphB, + const double *cofsB, int spdm, double *BravisVectors, double *Vectorfield,int nKpoints, + double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_2, const int nCGTO_1){ + __assertf( spdm==3,("calc_pbc_overlapsx:spdm=%d",spdm),-1); + int fix_nrmz=1; // 2^{1}: fix nrmz of BS2 2^{0} fix nrmz of BS1 + char sbuf10[10]; + char *sdum=getenv("calc_pbc_overlaps.fix_nrmz"); + if(sdum!=NULL){ long ldum=0;int iretv=sscanf(sdum,"%ld",&ldum);if(iretv){ fix_nrmz=(int)ldum;} } + //printf("#calc_pbc_overlaps:entering:%d %d %d fix_nrmz=%d",ellB[0],ellB[1],ellB[2],fix_nrmz);fflush(stdout); + int nBS1=0;int verbose=0; + int iargs[3]={Lx,Ly,Lz}; +//printf("#calc_pbc_overlapsx:gen_bset01:nAtm:%d IZnuc:%d\n",nAtm,IZnuc[0]);fflush(stdout); + Gaussian **BS =gen_bset01(&nBS1,nAtm,Rnuc,IZnuc,nDa,distinctIZnuc,Nsh,ell,NULL,npGTO,alph,cofs,0,verbose); + check_nrmz01("BS1",BS,nBS1,( (fix_nrmz&1)==0 ? 0:1 )); + int nBS2a[3]={0,0,0}; +//printf("#calc_pbc_overlapsx:gen_bsetx3:nAtm:%d Nsh:%d,%d IZnuc:%d\n",nAtmB,NshB[0],NshB[1],IZnucB[0]);fflush(stdout); + Gaussian ***BS2=gen_bsetx3(nBS2a,nAtmB,RnucB,IZnucB,nDb,distinctIZnucB,NshB,ellB,n_cols,npGTOB,alphB,cofsB); + check_nrmz01("BS2",BS2[0],nBS2a[0], ( (fix_nrmz&2)==0 ? 0:1 ) ); + __assertf( (nCGTO_2==nBS2a[0]) && (nCGTO_1==nBS1),("%d,%d / %d,%d",nBS2a[0],nBS1,nCGTO_2,nCGTO_1),-1); + +//test_ovlpx( BS, nBS1, BS2[0], nBS2a[0], BravisVectors); XXX XXX XXX + + int i2LH,j1RH; + char dbgng=1; + int Ldim_margin=5;int I; const int N_I=(spdm+1); + dcmplx ***zbuf=z3alloc_i(N_I,3,(nKpoints*nBS2a[0]*nBS1), 0.0); + double clock00=__ctime; double clock01=clock00, clock02=clock00; + int n=0; int append_1=0; int I_cols; + for(I_cols=0;I_cols<3;I_cols++){ + if(nBS2a[I_cols]<=0)continue; + int ijk=0; + double wct_00=__ctime; + for(i2LH=0;i2LH0 && BS2[2]!=NULL ){ free_Bset(BS2[2],nBS2a[2]);} + //printf("#calc_pbc_overlaps:END.030:%p\n",zbuf);fflush(stdout); + dcmplx *ret=zbuf[0][0];free(zbuf[0]);zbuf[0]=NULL; free(zbuf); zbuf=NULL; + //printf("#calc_pbc_overlaps:returning:%p\n",zbuf);fflush(stdout); + return ret; +} +/* +int fcountup(const char *fpath, const char incm){ + int retv=0; + FILE *fp=fopen(fpath,"r"); + if(fp==NULL) { retv=0;} + else { char sbuf[21];int ngot=0;long ldum=-1; + while(fgets(sbuf, 20, fp)!=NULL){ int le=strlen(sbuf); + if(le<1)continue;if(sbuf[le-1]=='\n'){ sbuf[le-1]='\0';le--; if(le<1)continue;} + ngot=sscanf(sbuf,"%ld",&ldum);if(ngot){ retv=(int)ldum;break;} + } fclose(fp); + __assertf( ngot,("fcountup:read from %s failed",fpath),1); + } + if(incm){ + retv+=1;fp=fopen(fpath,"w");fprintf(fp,"%d",retv);fclose(fp); + } + return retv; +}*/ +double d1min(const double *A,int N){ + int i,at=0;double val=A[at]; + for(i=1;ival){ at=i;val=A[at];}} + return val; +} +int calc_nabla_f(int nAtm, double *Rnuc, int *IZnuc, int nDa, int *distinctIZnuc, + const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs, + int spdm, double *BravaisVectors, int nKpoints, + double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_1, const int MPIrank, const int filenumber){ + printf("#calc_nabla_f:%d ... %d,%d,%d\n",nAtm,nCGTO_1,MPIrank,filenumber);fflush(stdout); + int nBS1=0; const int verbose=0; + Gaussian **BS =gen_bset01(&nBS1,nAtm,Rnuc,IZnuc,nDa,distinctIZnuc,Nsh,ell,NULL,npGTO,alph,cofs,0,verbose); + dcmplx ****zbuf=pbc_nabla(BS,nBS1, spdm, BravaisVectors, nKpoints, kvectors, Lx,Ly,Lz); + char fnme[50];sprintf(fnme,"calc_nabla_f%03d.retf",filenumber); + write_z1buf(fnme, zbuf[0][0][0], 3*nKpoints*nBS1*nBS1 ); + z4free(zbuf);free_Bset(BS,nBS1); + return 0; +} +// returns as Matr[:][I][J] .... +dcmplx ****pbc_nabla(Gaussian **BS,const int nBS, int spdm, double *BravaisVectors, int nKpoints, + double *kvectors, int Lx,int Ly,int Lz){ + dcmplx ****ret=z4alloc(nKpoints,3,nBS,nBS); const double Vectorfield[3]={0,0,0}; + int kp,dir,iRH,jLH;int iargs[3]={Lx,Ly,Lz};int Ldim_margin=5; + for(iRH=0;iRHN; +#define _Cpy3( src, dst ) { dst[0]=src[0];dst[1]=src[1];dst[2]=src[2];} + for(dir=0;dir<3;dir++){ + int Nnew=0; + for(I=0;Ipows[I][dir]>0 )Nnew++; } + double *cofs=d1alloc(Nnew),*alph=d1alloc(Nnew);ushort **pws=ush2alloc(Nnew,3); + int Inew=0; + for(I=0;Ipows[I][dir]>0 ){ cofs[Inew]=org->cofs[I]*( org->pows[I][dir] ); alph[Inew]=org->alpha[I]; + _Cpy3( org->pows[I], pws[Inew] ); pws[Inew][dir]--; Inew++;} + cofs[Inew]=org->cofs[I]*(-2*(org->alpha[I])); alph[Inew]=org->alpha[I]; + _Cpy3( org->pows[I], pws[Inew] ); pws[Inew][dir]++; Inew++; + } + ret[dir]=new_Gaussian_1( 0, alph,org->R,NULL,pws,Nnew,cofs,org->Jnuc); + d1free(cofs);d1free(alph);ush2free(pws); + } + /* dir=0; + if(1){ + FILE *fp=fopen("Gaussian_nabla_x.log","a"); + int Inew=0; + for(I=0;Ipows[I][0],org->pows[I][1],org->pows[I][2],org->alpha[I],org->cofs[I], + Inew, ret[dir]->pows[Inew][0],ret[dir]->pows[Inew][1],ret[dir]->pows[Inew][2],ret[dir]->alpha[Inew],ret[dir]->cofs[Inew]); Inew++; + if( org->pows[I][0]==0 )break;} + } fclose(fp); + }*/ + if(dbgng){ + double almin=d1min(org->alpha,org->N);double sqrt_almin=sqrt(almin);double fac=2.0; + double Rlb[3]={ org->R[0]-fac/sqrt_almin, org->R[1]-fac/sqrt_almin, org->R[2]-fac/sqrt_almin}; + double Rrt[3]={ org->R[0]+fac/sqrt_almin, org->R[1]+fac/sqrt_almin, org->R[2]+fac/sqrt_almin}; + double Ndim[3]={ 16,16,16 }; const double h=0.02; + double dR[3]={ (Rrt[0]-Rlb[0])/Ndim[0], (Rrt[1]-Rlb[1])/Ndim[1], (Rrt[2]-Rlb[2])/Ndim[2] }; + double devmx[3]={-1,-1,-1},lhs,rhs;const double devTOL=1.0e-5; int ix,jy,kz; double R[3]={0,0,0}; + for(ix=0,R[0]=Rlb[0];ixdevTOL){ printf("#nmdiff:%f testee:%f dev=%e @%f,%f,%f\n",nmdif,testee,dev,R[0],R[1],R[2]);} + if(dev>devmx[dir]) { devmx[dir]=dev;lhs=nmdif; rhs=testee;} + } + }}} + printf("#Gaussian_nabla:compto nmdiff:devmax=%e ( nmdiff:%f / val:%f)\n",devmx[dir],lhs,rhs); + } +// if(dbgng>0) dbgng--; + + return ret; +} + +// scheme 1 (lshift==1): < lh(r+T) | rh(r) e^{iAr} > ( ... to be summed over T with factor e^{ikT}) +// scheme 0 (lshift==0): < lh(r) | rh(r-T) e^{iAr} > ( ... to be summed over T with factor e^{ikT}) +dcmplx nmrovlp1(Gaussian *lh,Gaussian *rh,const double *VecField, const double *T, const char Lshift, + const double *scalefacs,const char verbose){ + double almin1=d1min(lh->alpha,lh->N),almin2=d1min(rh->alpha,rh->N); + double almax1=d1max(lh->alpha,lh->N),almax2=d1max(rh->alpha,rh->N); + double almin=__MIN( almin1, almin2); + double sqrt_almin=sqrt(almin); const double fac=scalefacs[0];//double fac=2.0; + double almax=__MIN( almax1, almax2); + double sqrt_almax=sqrt(almax); + double Rlb[3],Rrt[3]; int jj; + if(Lshift){ //lh center is shifted by -T + double Rlb1[3]={ lh->R[0]-T[0] -fac/sqrt_almin, lh->R[1]-T[1] -fac/sqrt_almin, lh->R[2]-T[2] -fac/sqrt_almin}; + double Rrt1[3]={ lh->R[0]-T[0] +fac/sqrt_almin, lh->R[1]-T[1] +fac/sqrt_almin, lh->R[2]-T[2] +fac/sqrt_almin}; + double Rlb2[3]={ rh->R[0]-fac/sqrt_almin, rh->R[1]-fac/sqrt_almin, rh->R[2]-fac/sqrt_almin}; + double Rrt2[3]={ rh->R[0]+fac/sqrt_almin, rh->R[1]+fac/sqrt_almin, rh->R[2]+fac/sqrt_almin}; + for(jj=0;jj<3;jj++){ Rlb[jj]=__MIN(Rlb1[jj],Rlb2[jj]);Rrt[jj]=__MAX(Rrt1[jj],Rrt2[jj]);} + } else { + double Rlb1[3]={ rh->R[0]+T[0] -fac/sqrt_almin, rh->R[1]+T[1] -fac/sqrt_almin, rh->R[2]+T[2] -fac/sqrt_almin}; + double Rrt1[3]={ rh->R[0]+T[0] +fac/sqrt_almin, rh->R[1]+T[1] +fac/sqrt_almin, rh->R[2]+T[2] +fac/sqrt_almin}; + double Rlb2[3]={ lh->R[0]-fac/sqrt_almin, lh->R[1]-fac/sqrt_almin, lh->R[2]-fac/sqrt_almin}; + double Rrt2[3]={ lh->R[0]+fac/sqrt_almin, lh->R[1]+fac/sqrt_almin, lh->R[2]+fac/sqrt_almin}; + for(jj=0;jj<3;jj++){ Rlb[jj]=__MIN(Rlb1[jj],Rlb2[jj]);Rrt[jj]=__MAX(Rrt1[jj],Rrt2[jj]);} + } + const double h=__MIN( 0.02, scalefacs[1]/sqrt_almax); + double dR[3]={ h,h,h }; + int Ndim[3]={ __NINT( (Rrt[0]-Rlb[0])/dR[0] ), __NINT( (Rrt[1]-Rlb[1])/dR[1] ), __NINT( (Rrt[2]-Rlb[2])/dR[2] ) }; + + if( verbose ){ + printf("#nmrovlp1: R:[%f,%f]x[%f,%f]x[%f,%f]/%fx%fx%f %d,%d,%d\n",Rlb[0],Rrt[0],Rlb[1],Rrt[1],Rlb[2],Rrt[2],h,h,h,Ndim[0],Ndim[1],Ndim[2]); + fflush(stdout); + } + int ix,jy,kz;dcmplx cum=0.0; double dVol=dR[0]*dR[1]*dR[2]; + double Rminus[3],Rplus[3],lhv,rhv,R[3]; + for(ix=0,R[0]=Rlb[0],Rminus[0]=Rlb[0]-T[0],Rplus[0]=Rlb[0]+T[0];ixabsmx){ absmx=dum;} + }}} + printf("#nmrpbcovlp1:loop%d:h:%d,%d,%d absmx:%e cum:%f,%f\n",nloop,hj[0],hj[1],hj[2],absmx,creal(cum),cimag(cum)); + if( absmx < TOL ){ + if( extra_loop>0 ){ hj[0]+=1;hj[1]+=1;hj[2]+=1;extra_loop--;continue;} + break; + } else { + hj[0]+=1;hj[1]+=1;hj[2]+=1;continue; + } + } + return cum; +} +void testovlp03(){ + double scalefacs_1[2]={2.6, 0.30}; + double scalefacs_2[2]={3.2, 0.15}; +#define Ng_LH 2 +#define Ng_RH 3 + const char Lshift=0; + double BravaisVectors[9] = { 1.582, 0, 0, 0,1.333,0, 0,0,1.543 }; + double kvector[3]={ -0.3, 0.2, 0.05 }; + double VecField[3]={ 0.3776, -0.08848, 0.0 }; + int ell1,ell2,emm1,emm2; + const double dev_TINY=1.0e-7; + double displ[3]={0,0,0};char verbose=1; + double alph_LH[Ng_LH]={ 0.20, 4.00 },cofs_LH[Ng_LH]={ 0.30, 0.85}; + double alph_RH[Ng_RH]={ 0.3776, 0.8848, 1.868 },cofs_RH[Ng_LH]={ 0.645, 0.794, 1.192}; + double R_LH[3]={ 0.0894, -0.0710, 0.1333 }, R_RH[3]={ 0.0710, -0.0645, -0.1467}; +/* FILE *fp=fopen("testovlp03b.002.dat","w"); FILE *fpA[2]={fp,stdout};int I; + fprintf(fp,"#displ:%f %f %f VF:%f %f %f\n", displ[0], displ[1], displ[2], VecField[0], VecField[1], VecField[2]); + for(ell1=0;ell1<4;ell1++){ for(emm1=-ell1;emm1<=ell1;emm1++){ + Gaussian *lh= Spherical_to_Cartesian( new_SphericalGaussian(alph_LH, R_LH,ell1,emm1,Ng_LH, cofs_LH,0) ); + for(ell2=0;ell2<4;ell2++){ for(emm2=-ell2;emm2<=ell2;emm2++){ + Gaussian *rh= Spherical_to_Cartesian( new_SphericalGaussian(alph_RH, R_RH,ell2,emm2,Ng_RH, cofs_RH,1) ); + dcmplx ovlpO=Gaussian_ovlpNew(lh,rh,VecField,displ); + dcmplx ovlpN=nmrovlp1(lh,rh,VecField, displ, Lshift, scalefacs_1,verbose);verbose=0; + double dev=cabs(ovlpO-ovlpN); + if(dev>dev_TINY){ + dcmplx ovlpN2=nmrovlp1(lh,rh,VecField, displ, Lshift, scalefacs_2,verbose); + double dev2=cabs(ovlpO-ovlpN2); + for(I=0;I<2;I++) + fprintf(fpA[I],"%d,%d x %d,%d : %16.8f %16.8f %16.8f %16.8f %14.4e %16.8f %16.8f %14.4e %s\n", + ell1,emm1,ell2,emm2,creal(ovlpO),cimag(ovlpO), creal(ovlpN2),cimag(ovlpN2),dev2, creal(ovlpN),cimag(ovlpN),dev, + (dev2 pbc_overlap_B(0,0,0, lh, rh,3, BravaisVectors, VecField, 1, kvector,iargs,0,Ldim_margin); + dcmplx *ovlpsO=pbc_overlap_old(lh,rh,3, BravaisVectors, VecField, 1, kvector,iargs); + printf(" %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f\n", + creal(ovlps[0]),cimag(ovlps[0]), creal(ovlpsB[0]),cimag(ovlpsB[0]),creal(ovlpsO[0]),cimag(ovlpsO[0]) ); + + printf("#testovlp03:start nmrintg...\n");fflush(stdout); + dcmplx nmrovlp=nmrpbcovlp1( lh, rh, Lshift, kvector, BravaisVectors, VecField, scalefacs_1); + + FILE *fp1=fopen("testovlp03b.log","a"); + fprintf(fp1," %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f\n", + creal(nmrovlp),cimag(nmrovlp), creal(ovlps[0]),cimag(ovlps[0]), creal(ovlpsB[0]),cimag(ovlpsB[0]), + creal(ovlpsO[0]),cimag(ovlpsO[0]) ); + fclose(fp1); +} +void testovlp04(){ + const double dev_TINY=1.0e-7;const double dev_TOL=1.0e-7; + double alph_s[10]={8236.0, 1235.0, 280.8, 79.27, 25.59, 8.997, 3.319, 0.9059, 0.3643, 0.1285}; + double cofs_s[10]={0.000531, 0.004108, 0.021087, 0.081853, 0.234817, 0.434401, 0.346129, 0.039378, -0.008983, 0.002385}; + double alph_d[9]={403.83, 121.17, 46.345, 19.721, 8.8624, 3.9962, 1.7636, 0.70619, 0.2639}; + double cofs_d[9]={ 0.0014732, 0.0126725, 0.0580451, 0.1705103, 0.3185958, 0.3845023, 0.2737737, 0.0743967, 0.0}; + double alph_p[13]={8676.5, 2055.9, 666.23, 253.1, 106.12, 47.242, 21.825, 9.9684, 4.5171, 1.9982, 0.70988, 0.28145, 0.10204}; + double cofs_p1[13]={0.0004357, 0.0037815, 0.0204782, 0.0792834, 0.2178473, 0.3878585, 0.359435, 0.1121995, 0.0043874, 0.0017809, -0.0004576, 0.0002122, -7.34e-05}; + double cofs_p2[13]={-0.0001748, -0.0015263, -0.0083399, -0.0332203, -0.095418, -0.1824026, -0.1558308, 0.1867899, 0.5427733, 0.3873309, 0.0453069, -0.0043784, 0.0018111}; + double cofs_p3[13]={4.51e-05, 0.0003964, 0.0021555, 0.008672, 0.024868, 0.0485472, 0.0396156, -0.0605749, -0.1871699, -0.1377757, 0.2928021, 0.5760896, 0.3078617}; + + double alph_sB[20]={10639000.0, 1593400.0, 362610.0, 102700.0, 33501.0, 12093.0, 4715.9, 1955.6, 852.61, 387.67, 182.68, 88.245, 39.263, 19.234, 9.4057, 4.1601, 1.8995, 0.60472, 0.30114, 0.12515}; + double cofs_s1[20]={5.9e-06, 4.61e-05, 0.0002422, 0.0010226, 0.0037113, 0.0119785, 0.0346927, 0.0891239, 0.1934557, 0.3209019, 0.3299233, 0.1494121, 0.0149938, -0.0009165, 0.000438, -0.0002398, 7.36e-05, -3.67e-05, 2.39e-05, -5.6e-06}; + double cofs_s2[20]={-1.9e-06, -1.45e-05, -7.61e-05, -0.000321, -0.0011709, -0.0037968, -0.0112307, -0.0299277, -0.0712706, -0.1403136, -0.2030763, -0.0960985, 0.3558086, 0.5921792, 0.2215977, 0.0137648, 0.0008395, -4.51e-05, -8.5e-06, -1.24e-05}; + double cofs_s3[20]={7e-07, 5.7e-06, 3.03e-05, 0.0001275, 0.0004659, 0.0015096, 0.0044852, 0.0119835, 0.0289571, 0.0581566, 0.0888133, 0.0445244, -0.2060387, -0.5127017, -0.1509349, 0.6789203, 0.5817697, 0.0467555, -0.0111825, 0.0024402}; + double cofs_s4[20]={-2e-07, -1.8e-06, -9.3e-06, -3.91e-05, -0.0001428, -0.0004628, -0.001375, -0.0036784, -0.0088981, -0.0179529, -0.0275732, -0.0140953, 0.0672561, 0.1766928, 0.0528861, -0.3075955, -0.4700658, 0.2558761, 0.6980341, 0.2967256}; + double R_1[3]={ -0.645, -0.894, 0.1192}; + double R_2[3]={ -0.1467, 0.375, 0.3776}; + //(const double *alpha, const double *R,int l,int m,int N, const double *cof,int Jnuc) + int ell1[12]={ 0, 1,1,1, 1,1,1, 2,2,2,2,2}; + int emm1[12]={ 0, -1,0,1, -1,0,1, -2,-1,0,1,2}; + Gaussian *BS1[12]={ Spherical_to_Cartesian( new_SphericalGaussian( alph_s, R_1, 0, 0, 10, cofs_s, 0) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_p, R_1, 1, -1, 13, cofs_p1, 0) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_p, R_1, 1, 0, 13, cofs_p1, 0) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_p, R_1, 1, 1, 13, cofs_p1, 0) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_p, R_1, 1, -1, 13, cofs_p3, 0) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_p, R_1, 1, 0, 13, cofs_p3, 0) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_p, R_1, 1, 1, 13, cofs_p3, 0) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_d, R_1, 2, -2, 9, cofs_d, 0) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_d, R_1, 2, -1, 9, cofs_d, 0) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_d, R_1, 2, 0, 9, cofs_d, 0) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_d, R_1, 2, 1, 9, cofs_d, 0) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_d, R_1, 2, 2, 9, cofs_d, 0) ) }; + int ell2[10]={ 0,0, 1,1,1, 2,2,2,2,2}; + int emm2[10]={ 0,0, -1,0,1, -2,-1,0,1,2}; + Gaussian *BS2[10]={ Spherical_to_Cartesian( new_SphericalGaussian( alph_sB, R_2, 0, 0, 20, cofs_s1, 0 ) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_sB, R_2, 0, 0, 20, cofs_s4, 0 ) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_p, R_2, 1, -1, 13, cofs_p2, 0 ) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_p, R_2, 1, 0, 13, cofs_p2, 0 ) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_p, R_2, 1, 1, 13, cofs_p2, 0 ) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_d, R_2, 2, -2, 9, cofs_d, 0 ) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_d, R_2, 2, -1, 9, cofs_d, 0 ) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_d, R_2, 2, 0, 9, cofs_d, 0 ) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_d, R_2, 2, 1, 9, cofs_d, 0 ) ), + Spherical_to_Cartesian( new_SphericalGaussian( alph_d, R_2, 2, 2, 9, cofs_d, 0 ) ) }; + double scalefacs_1[2]={2.6, 0.30}; + double scalefacs_2[2]={3.2, 0.15};int verbose=1; + const int Lshift=0; + double V_al[3*4]={ 0,0,0, 0.1192,0.0645,0.0, 1.467,-1.333,1.868, 64.58,37.76,8.848}; const int nV=4; + double D_al[3*2]={ 0.5,-0.2,0.3, 2.4,1.8,1.6 }; const int nD=2; + int iV,jD,Ib,Jb,I; double *V,*D; const int Nb1=12,Nb2=10; + FILE *fpA[2]={ fopen("testovlp04.log","w"),stdout }; + for(iV=0,V=V_al;iVdev_TOL){ dcmplx ovlpN2=nmrovlp1(BS1[Ib],BS2[Jb],V,D, Lshift, scalefacs_2,verbose);double dev2=cabs(ovlpO-ovlpN2); + for(I=0;I<2;I++) + fprintf(fpA[I],"%d,%d x %d,%d : %16.8f %16.8f %16.8f %16.8f %14.4e %16.8f %16.8f %14.4e %s\n", + ell1[Ib],emm1[Ib],ell2[Jb],emm2[Jb],creal(ovlpO),cimag(ovlpO), creal(ovlpN2),cimag(ovlpN2),dev2, creal(ovlpN),cimag(ovlpN),dev, + (dev2dev_TOL){ dcmplx ovlpN2=nmrovlp1(BS1[Ib],BS1[Jb],V,D, Lshift, scalefacs_2,verbose);double dev2=cabs(ovlpO-ovlpN2); + for(I=0;I<2;I++) + fprintf(fpA[I],"%d,%d x %d,%d : %16.8f %16.8f %16.8f %16.8f %14.4e %16.8f %16.8f %14.4e %s\n", + ell1[Ib],emm1[Ib],ell1[Jb],emm1[Jb],creal(ovlpO),cimag(ovlpO), creal(ovlpN2),cimag(ovlpN2),dev2, creal(ovlpN),cimag(ovlpN),dev, + (dev2 rather than <\mu|\nabla|\nu> ... + ## 2021.08.04 : see pyscf_work/DATA/pbc_int1e_ipovlp where I printed out my own <\mu|\nabla|\nu> and int1e_ipovlp .. \ No newline at end of file diff --git a/pyscf/rttddft/Dbglogger.py b/pyscf/rttddft/Dbglogger.py new file mode 100644 index 000000000..666b02ea9 --- /dev/null +++ b/pyscf/rttddft/Dbglogger.py @@ -0,0 +1,31 @@ +from .futils import futils +class Dbglogger: + nlog=-1 + filenumber=0 + logfile=None + @staticmethod + def set_filenumber(num): + Dbglogger.filenumber=num + @staticmethod + def write(msg,refresh=False,stdout=False): +# if( world.rank != 0 ): TODO XXX MPI RANK +# return + if( Dbglogger.filenumber<0 ): + print("#log:"+msg) + return + Dbglogger.nlog=Dbglogger.nlog+1 + if( Dbglogger.logfile is None ): + Dbglogger.logfile="Dbglogger.log" + if( Dbglogger.filenumber > 0 ): + Dbglogger.logfile="Dbglogger_%d.log"%(Dbglogger.filenumber) + + fd=futils.fopen(Dbglogger.logfile,("w" if(refresh or Dbglogger.nlog==0) else "a")); + print(msg,file=fd) + if( stdout ): + print(msg) + futils.fclose(fd) + +Dbglogger.write("#logging..") + +#def dbglogger(msg,refresh=False,stdout=False): +# Dbglogger.write(msg,refresh,stdout) diff --git a/pyscf/rttddft/GEAR.py b/pyscf/rttddft/GEAR.py new file mode 100644 index 000000000..a678538a5 --- /dev/null +++ b/pyscf/rttddft/GEAR.py @@ -0,0 +1,242 @@ +import numpy as np +import os +# +# Zc,Zp = dGEA2ndOne(dh,Zc,Zp,Accel,iFirst) +# Zc[5][Ld] corrector, F(t), F'(t), ... +# Zp[5][Ld] predictor, F(t+h),F'(t+h),... + +# You DO NEED to set Accel(t=0) when you initialize this array ... it is reflected on Zp vector as well +# rGEAR2ndOne updates Zc[2] and propagates Zp[2] .. +def initz_rGEARvec(dh,Xini,Vini,Accel,Ld): + + ZcOUT=np.zeros([5,Ld],dtype=np.float64) + ZpOUT=np.zeros([5,Ld],dtype=np.float64) + assert isinstance(Xini,np.ndarray),"" + assert isinstance(Vini,np.ndarray),"" + assert isinstance(Accel,np.ndarray),"" + + ZpOUT[0]=Xini + ZpOUT[1]=Vini*dh; ## d1Scle(Zp1,Ld,dh,1) + ZpOUT[2]=Accel*(0.5*(dh**2)) ## d1Scle(Accel,Ld,dh,2) + ZpOUT[3]=0.0; ## Zp3(:)=0.0d+0; Zp4(:)=0.0d+0; + ZpOUT[4]=0.0; + ZcOUT[0]=ZpOUT[0]; ## Zc0(:)=Zp0(:); + ZcOUT[1]=ZpOUT[1]; ## Zc1(:)=Zp1(:); + ZcOUT[2]=ZpOUT[2]; ## Zc2(:)=Zp2(:); + ZcOUT[3]=0.0; ## Zc3(:)=0.0d+0; + ZcOUT[4]=0.0; ## Zc4(:)=0.0d+0; + + return ZcOUT,ZpOUT + +## +## converted from my own f90 source dGEA2ndOne +## +def rGEAR2ndOne(dh,Zc,Zp,Accel,Ld): + assert isinstance(Accel,np.ndarray),"" + Zc[2]=Accel*(0.5*(dh**2)) + return rGEARstp(Zc[2], 2,Zc,Zp,Ld) + +def rGEARstp(Zcj,jIndx,Zc,Zp,iDim): + if(jIndx == 2): + c0=(1.9e+01)/(1.2e+02) + c1=0.75e+00 + c2=1.0e+00 + c3=0.50e+00 + c4=(1.0e+00)/(1.2e+01) + else: + c0=(2.51e+00)/(7.2e+00) + c1=1.0e+00 + c2=(1.1e+00)/(1.2e+00) + c3=(1.0e+00)/(3.0e+00) + c4=(1.0e+00)/(2.4e+01) + if(jIndx == 2 ): + dv=Zcj - Zp[2] + else: + dv=Zcj - Zp[1] + + Zc[0]=Zp[0]+c0*dv + Zc[1]=Zp[1]+c1*dv + Zc[2]=Zp[2]+c2*dv + Zc[3]=Zp[3]+c3*dv + Zc[4]=Zp[4]+c4*dv + + Zp[0]= Zc[0]+ Zc[1]+ Zc[2]+ Zc[3]+ Zc[4] + Zp[1]= Zc[1]+ 2.0*Zc[2]+ 3.0*Zc[3]+ 4.0*Zc[4] + Zp[2]= Zc[2]+ 3.0*Zc[3]+ 6.0*Zc[4] + Zp[3]= Zc[3]+ 4.0*Zc[4] + Zp[4]= Zc[4] + + return Zc,Zp + +def polynomial(o,x,cofs): + if(o==0): + return polynomial_0(x,cofs) + else: + N=len(cofs); + if(o==1): + if(N<2): # N==1 constant -> 0 + return 0.0 + cofs1=[ k*cofs[k] for k in range(1,N) ] + return polynomial_0(x,cofs1) + elif(o==2): + if( N<3): + return 0.0 + cofs1=[ k*(k-1)*cofs[k] for k in range(2,N) ] + return polynomial_0(x,cofs1) + else: + assert False,"" + +def polynomial_0(x,cofs): + Nupl=len(cofs) + retv=cofs[Nupl-1]; + for J in range(1,Nupl): + retv=retv*x + cofs[Nupl-J-1] + return retv + +def fn1(o,x,xc,alphcofs): + expf=np.exp( -alphcofs[0]*(x-xc)**2 ); + if(o==0): + ### print("Alphcofs:",alphcofs[1:]) + return expf*polynomial(0,x,alphcofs[1:]) + elif(o==1): + return -2*alphcofs[0]*(x-xc)*expf*polynomial(0,x,alphcofs[1:])\ + +expf*polynomial(1,x,alphcofs[1:]) + else: + return (-2*alphcofs[0] + 4*alphcofs[0]*alphcofs[0]*( (x-xc)**2 ) )*expf*polynomial(0,x,alphcofs[1:]) \ + +2*(-2*alphcofs[0]*(x-xc))*expf*polynomial(1,x,alphcofs[1:]) \ + + expf*polynomial(2,x,alphcofs[1:]) + + + + +## T=2.0 +## x0=0.0 +## xc=1.603 +## Ld=3 +## alphCofs=[ [1.192, -1.868, 1.192, 1.467, 0.645], +## [3.142, 1.543, 0.894, 0.794, 0.375], +## [0.645, 3.776,-8.848, 0.314, 0.272] ] +## N_iter=5 +## ## Implicit Scheme +## ## initz GEAR vector +## ## t_0 : a(0) : Xp(h) Xc(0) +## ## t_1 : a(h) : Xp(2h) Xc(h) +## +## R0=np.array( [ fn1(0,x0,xc,alphCofs[k]) for k in range(Ld) ] ) +## V0=np.array( [ fn1(1,x0,xc,alphCofs[k]) for k in range(Ld) ] ) +## +## Implicit=True +## for strh in ["0.1", "0.05", "0.01"]: +## h=float(strh) +## N=int(round(T/h)) +## Accel=np.zeros([Ld],dtype=np.float64) +## Zc,Zp=initz_rGEARvec( h,R0,V0,Accel,Ld) +## Zc_nxt=np.zeros([5,Ld],dtype=np.float64);Zp_nxt=np.zeros([5,Ld],dtype=np.float64) +## fnme="testInteg.1%s_"%("IMPLICIT" if(Implicit) else "EXPLICIT")+strh;fd=open(fnme+".dat","w"); +## Rref=np.zeros([Ld],dtype=np.float64) +## Vref=np.zeros([Ld],dtype=np.float64) +## x=x0 +## for step in range(N+1): +## for iter in range(N_iter): +## for k in range(Ld): +## Accel[k]=fn1(2,x,xc,alphCofs[k]) +## #OK: for ii in range(5): +## #OK: for jj in range(Ld): +## #OK: Zc_nxt[ii][jj]=Zc[ii][jj];Zp_nxt[ii][jj]=Zp[ii][jj] +## #OK: Zc_nxt,Zp_nxt=rGEAR2ndOne(h,Zc_nxt,Zp_nxt,Accel,Ld) +## Zc_nxt,Zp_nxt=rGEAR2ndOne(h,Zc,Zp,Accel,Ld) +## ## update Zc,Zp using the latest one.. +## for ii in range(5): +## for jj in range(Ld): +## Zc[ii][jj]=Zc_nxt[ii][jj];Zp[ii][jj]=Zp_nxt[ii][jj] +## +## if(Implicit): +## R=Zc[0]; V=Zc[1]/h +## for k in range(Ld): +## Rref[k]=fn1(0,x,xc,alphCofs[k]); Vref[k]=fn1(1,x,xc,alphCofs[k]) +## xDev=np.vdot( R-Rref, R-Rref) +## vDev=np.vdot( V-Vref, V-Vref) +## print("%12.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6e %14.6e"%(\ +## x, R[0],R[1],R[2], Rref[0],Rref[1],Rref[2], V[0],V[1],V[2], Vref[0],Vref[1],Vref[2], np.sqrt(xDev), np.sqrt(vDev)),file=fd) +## else: +## R=Zp[0]; V=Zp[1]/h +## for k in range(Ld): +## Rref[k]=fn1(0,x+h,xc,alphCofs[k]); Vref[k]=fn1(1,x+h,xc,alphCofs[k]) +## xDev=np.vdot( R-Rref, R-Rref) +## vDev=np.vdot( V-Vref, V-Vref) +## print("%12.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6e %14.6e"%(\ +## x+h, R[0],R[1],R[2], Rref[0],Rref[1],Rref[2], V[0],V[1],V[2], Vref[0],Vref[1],Vref[2], np.sqrt(xDev), np.sqrt(vDev)),file=fd) +## +## x=x+h +## +## +## ## Explicit Scheme ... +## ###for strh in ["0.05", "0.10", "0.01"]: +## ### h=float(strh) +## ### N=int(round(T/h)) +## ### Zc=np.zeros([5,Ld],dtype=np.float64) +## ### Zp=np.zeros([5,Ld],dtype=np.float64) +## ### R=np.zeros([Ld],dtype=np.float64) +## ### V=np.zeros([Ld],dtype=np.float64) +## ### Rref=np.zeros([Ld],dtype=np.float64) +## ### Vref=np.zeros([Ld],dtype=np.float64) +## ### Accel=np.zeros([Ld],dtype=np.float64) +## ### +## ### x=x0; +## ### ## set IC on Zp array... +## ### for k in range(Ld): +## ### Zp[0][k]=fn1(0,x,xc,alphCofs[k]) +## ### Zp[1][k]=fn1(1,x,xc,alphCofs[k]) +## ### +## ### fnme="testInteg_"+strh;fd=open(fnme+".dat","w"); +## ### iFirst=True +## ### for J in range(N): +## ### for k in range(Ld): +## ### Accel[k]=fn1(2,x,xc,alphCofs[k]) +## ### Zc,Zp=rGEAR2ndOne(h,Zc,Zp,Accel,Ld,iFirst);iFirst=False +## ### R=Zp[0]; V=Zp[1]/h +## ### for k in range(Ld): +## ### Rref[k]=fn1(0,x,xc,alphCofs[k]); Vref[k]=fn1(1,x,xc,alphCofs[k]) +## ### xDev=np.vdot( R-Rref, R-Rref) +## ### vDev=np.vdot( V-Vref, V-Vref) +## ### print("%12.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %14.6e %14.6e"%(\ +## ### x+h, R[0],R[1],R[2], Rref[0],Rref[1],Rref[2], V[0],V[1],V[2], Vref[0],Vref[1],Vref[2], np.sqrt(xDev), np.sqrt(vDev)),file=fd) +## ### x=x+h +## ### fd.close() +## os.system("ls -ltrh "+fnme+".dat") +## os.system("gnuf.sh "+fnme) +## fd=open(fnme+".plt","a") +## print("plot \"%s.dat\" using 1:2 with lines ls 1,\\"%(fnme),file=fd); +## print("\"\" using 1:5 with lines ls 101,\\",file=fd); +## print("\"\" using 1:3 with lines ls 2,\\",file=fd); +## print("\"\" using 1:6 with lines ls 102,\\",file=fd); +## print("\"\" using 1:4 with lines ls 3,\\",file=fd); +## print("\"\" using 1:7 with lines ls 103",file=fd); +## +## print("plot \"%s.dat\" using 1:8 with lines ls 1,\\"%(fnme),file=fd); +## print("\"\" using 1:11 with lines ls 101,\\",file=fd); +## print("\"\" using 1:9 with lines ls 2,\\",file=fd); +## print("\"\" using 1:12 with lines ls 102,\\",file=fd); +## print("\"\" using 1:10 with lines ls 3,\\",file=fd); +## print("\"\" using 1:13 with lines ls 103",file=fd); +## fd.close() +## ### INTEGER,intent(in) :: iDim,jIndx +## ### Double Precision,intent(inout) :: zc0(iDim),zc1(iDim),zc2(iDim),zc3(iDim),zc4(iDim),zcj(iDim),& +## ### zp0(iDim),zp1(iDim),zp2(iDim),zp3(iDim),zp4(iDim),dv(iDim) +## ### DOUBLE PRECISION :: c0,c1,c2,c3,c4 +## ### IF(jIndx .EQ. 2) THEN +## ### dv(:) = zcj(:)-zp2(:) +## ### ELSE +## ### dv(:) = zcj(:)-zp1(:) +## ### END IF +## ### zc0(:)=zp0(:)+c0*dv(:) +## ### zc1(:)=zp1(:)+c1*dv(:) +## ### zc2(:)=zp2(:)+c2*dv(:) +## ### zc3(:)=zp3(:)+c3*dv(:) +## ### zc4(:)=zp4(:)+c4*dv(:) +## ### +## ### zp0(:)=zc0(:)+zc1(:)+zc2(:)+zc3(:)+zc4(:) +## ### zp1(:)=zc1(:)+(2.0d+0)*zc2(:)+(3.0d+0)*zc3(:)+(4.0d+0)*zc4(:) +## ### zp2(:)=zc2(:)+(3.0d+0)*zc3(:)+(6.0d+0)*zc4(:) +## ### zp3(:)=zc3(:)+(4.0d+0)*zc4(:) +## ### zp4(:)=zc4(:) diff --git a/pyscf/rttddft/Logger.py b/pyscf/rttddft/Logger.py new file mode 100644 index 000000000..2ee4ffaa5 --- /dev/null +++ b/pyscf/rttddft/Logger.py @@ -0,0 +1,452 @@ +import numpy as np +import os +import time +import sys +import datetime +from pyscf.pbc.gto import Cell +from .rttddft_common import rttddft_common +from .futils import futils +from .serialize import serialize, read_strtype, diff_objects, load_fromlist +from mpi4py import MPI + +def suppress_prtout(): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); + return ( MPIrank!=0 ) + +def fill_dict(tgt,value=None): + for key in tgt: + tgt[key]=value +def clone_dict(org): + ret={}; + for key in org: + ret.update({key:org[key]}) + return ret + +class Logger: + _Logfile=None + _TimingLogfile=None + _WarningLogfile=None + _Append=False + _Nwarning=0 + _Warnings={} + _Params={} + _Counter={} + _Table={} + @staticmethod + def Getlogfpath(extension="_Logger.log"): + job=rttddft_common.get_job(False) + if( job is None ): + fpath="Logger"+extension + else: + fpath=job + extension + return fpath; + @staticmethod + def Setv(key,value): + if( key in Logger._Table ): + oldv=Logger._Table[key]; + if( oldv != value ): + Logger.Warning("value of "+str(key)+" changes:"+str(oldv)+" >> "+str(value)) + Logger._Table[key]=value; return 2; + else: + return 0; + else: + Logger._Table.update({key:value}) + return 1 + @staticmethod + def Getv(key,default=None): + if( key in Logger._Table ): + return Logger._Table[key] + else: + return default + @staticmethod + def Check_MOs(mf,MO): + if( Logger.Getv("nAO") is not None ): + return 0 + ndim_MO=np.shape(MO) + pbc= isinstance( mf.mol,Cell );Logger.Setv("pbc",pbc) + # UHF [2,nkpt,nAO,nMO] / [2,nAO,nMO] + # RHF [nkpt,nAO,nMO] / [nAO,nMO] + nkpt=None;nAO=None;nMO=None; + if(pbc): + if(len(ndim_MO)==4): + if(ndim_MO[0]==2): + nkpt=ndim_MO[1];nAO=ndim_MO[2];nMO=ndim_MO[3] + else: + Logger.Warning("ndim_MO:"+str(ndim_MO)) + elif( len(ndim_MO)==3 ): + nkpt=ndim_MO[0];nAO=ndim_MO[1];nMO=ndim_MO[2] + if(nAO is not None): + Logger.Setv("nkpt",nkpt); + Logger.Setv("nAO",nAO);Logger.Setv("nMO",nMO); + return 1 + else: + return -1 + else: + if(len(ndim_MO)==3): + if(ndim_MO[0]==2): + nAO=ndim_MO[1];nMO=ndim_MO[2] + else: + Logger.Warning("ndim_MO:"+str(ndim_MO)) + elif( len(ndim_MO)==2 ): + nAO=ndim_MO[0];nMO=ndim_MO[1] + if(nAO is not None): + Logger.Setv("nAO",nAO);Logger.Setv("nMO",nMO); + return 1 + else: + return -1 + + + @staticmethod + def Countup(key): + if( key in Logger._Counter ): + Logger._Counter[key]+=1 + else: + Logger._Counter.update({key:1}) + return Logger._Counter[key] + @staticmethod + def Check_meshsize(mol_or_cell,refresh=False): + if( "meshsz" in Logger._Params ): + if( not refresh ): + return Logger._Params["meshsz"] + if( mol_or_cell is None ): + return -1 + mesh=getattr( mol_or_cell,"mesh",None ) + if( mesh is not None): + meshLd=max(mesh) + le=len(mesh); + meshsz=1; + for j in range(le): + meshsz=meshsz*mesh[j] + Logger._Params.update({"meshsz":meshsz}) + fdOut=open("meshsize.log","a"); + for fd1 in [fdOut,sys.stdout]: + print("#mesh:"+str(mesh)+" %d "%(meshsz)+rttddft_common.get_job(True)+" "+str(datetime.datetime.now())) + fdOut.close() + return Logger._Params["meshsz"] + else: + return -1 + @staticmethod + def Warning(title,msg): + text="#!W:"+msg+" \tjob:"+rttddft_common.get_job(True)+" \t"+str( datetime.datetime.now() ) + wORa='a' + if( Logger._WarningLogfile is None ): + Logger._WarningLogfile=Logger.Getlogfpath(extension="_Warning.log");wORa='w' + fd=open(Logger._WarningLogfile, wORa); + print(text,file=fd);fd.close() + Logger.log(text); + + if( title in Logger._Warnings ): + if(not (msg in Logger._Warnings[title]) ): + n=len(Logger._Warnings[title]) + if( n<10 ): + Logger._Warnings[title].append(msg);n+=1 + if(n==10): + fd=open("Logger.warning",("w" if(Logger._Nwarning==0) else "a"));Logger._Nwarning+=1 + for fd1 in [fd,sys.stdout]: + print(text+str(Logger._Warnings[title]),file=fd1); + fd.close() + print(text,flush=True);return + else: + Logger._Warnings.update({title:[msg]}) + fd=open("Logger.warning",("w" if(Logger._Nwarning==0) else "a"));Logger._Nwarning+=1 + for fd1 in [fd,sys.stdout]: + print(text+str(Logger._Warnings[title]),file=fd1); + fd.close() + + verbose=False + @staticmethod + def serialize_logger(this,delimiter=';'): + ret="type:"+str(type(this)) + print("serialize_logger:"+str(this)) + sdum=serialize(this,delimiter=delimiter,verbose=0) + if(sdum is None): + print("serialize "+str(this)+" returns None");assert False,"" + ret+=delimiter+ serialize(this,delimiter=delimiter,verbose=0) + dbgng=False + if(dbgng): + fpath1="test_serialize_logger01.pscf" + fpath2="test_serialize_logger02.pscf" + serialize(this,fpath=fpath1,additional_fields={"type":str(type(this))} ) + fd1=open(fpath1,"r"); + string=None + for line in fd1: + line=line.strip(); + if(len(line)==0): + continue + if(line[0]=='#'): + continue + if(string is None): + string=line + else: + string+=delimiter+line + fd1.close() + logger2=Logger.construct_logger(string,delimiter=delimiter) + serialize(logger2,fpath=fpath2,additional_fields={"type":str(type(this))}) + os.system("ls -ltrh "+fpath1); + os.system("ls -ltrh "+fpath2); + dict_logs={} + Nd,Ns,Ne=diff_objects(this,logger2,dict_logs=dict_logs) + print([Nd,Ns,Ne]); + print(dict_logs) + assert False,"" + return ret + @staticmethod + def construct_logger(string, delimiter=';'): + print("construct_logger from:"+string) + print(str(string.split(delimiter))) + if( string=="None" ): + return None + retv=None + sbuf=string.split(delimiter) + col0=sbuf.pop(0) + sarr=col0.split(':'); + key=sarr[0].strip() + assert (key=="type"),"" + print(col0); + print(sarr); + strtype=sarr[1].strip(); + ty=read_strtype(strtype) + if( ty=="Logger.Logger" or ty=="Logger" ): + retv=Logger(filepath="dummy.log") + assert (retv is not None),""+ty + load_fromlist(retv,sbuf) + retv.time_00=time.time() + return retv + _Array=[]; + _Dict={}; +### _timing={"get_hcore":None,"get_veff":None,"get_ovlp":None,"energy_tot":None,"SCF":None,"SCF_iter":None} + _timing={"get_hcore":None,"get_veff":None,"get_ovlp":None,"energy_tot":None,"SCF_calculation":None, + "nSCFcycle":None,"avg_SCF_cycle":None,"single_SCF_cycle":None} + _timing_buffer={} + @staticmethod + def Clear_timing(uniquetitle=None,printout=False): + if(uniquetitle is not None): + Logger._timing_buffer.update({uniquetitle:clone_dict(Logger._timing)}) + if(printout): + Logger.log( "#timing_summary:"+("" if(uniquetitle is None) else uniquetitle+":")+str(Logger._timing)) + fill_dict(Logger._timing, None) + Time_00_=None + def __init__(self,filepath=None,append=False): + if( Logger.Time_00_ is None): + Logger.Time_00_ = time.time() + self.filepath=filepath; + self._append=append + self.time_00=time.time() + self.time=[0,0,0] # time[0]:timing("start") time[1]=time[2];time[1]=time.time() + self.function="" + self._array=[] + print("logger:initlz"+filepath); + @staticmethod + def log(text,timing=True,end='\n',filepath=None,stdout=False,flush=False): + if( suppress_prtout() ): + return ## XXX XXX + if( Logger.Time_00_ is None): + Logger.Time_00_ = time.time() + if(timing): + tcur=time.time(); + text+=" time:%12.3f"%(tcur-Logger.Time_00_) + if( Logger._Logfile is None ): + Logger._Logfile = Logger.Getlogfpath(); + fd1=futils.fopen(Logger._Logfile,("a" if Logger._Append else "w"));Logger._Append=True + ### print("#Logger:printing on "+Logger._Logfile); + fd2=None + fdlist=[ fd1 ] + if( stdout ): fdlist.append( sys.stdout ) + if( filepath is not None ): + fd2=futils.fopen( filepath,("a" if Append else "w")); fdlist.append(fd2) + for fd in fdlist: + print(text,end=end,file=fd,flush=flush); + futils.fclose(fd1); + if(fd2 is not None): + futils.fclose(fd2) + @staticmethod + def write(logger,text,level=None,end="\n",timing=False): + if( suppress_prtout() ): + return ## XXX XXX + if( Logger.Time_00_ is None): + Logger.Time_00_ = time.time() + + if( logger is None ): + if( timing ): + tcur=time.time() + text+=" time:%12.3f"%(tcur-Logger.Time_00_) + Logger.log(text) + print(text,end=end);return + if(level is None): + logger.info(text,end=end,timing=timing) + if( level == 'i'): + logger.info(text,end=end,timing=timing) + elif( level == 'I'): + logger.info(text,end=end,timing=timing) + elif( level == 'w'): + logger.warning(text,end=end,timing=timing) + @staticmethod + def write_once(logger,title,content,fnme=None,append=False): + if( suppress_prtout() ): + return + if( title in Logger._Array ): + return 0 + if(fnme is not None): + fd=futils.fopen(fnme,("a" if(append) else "w")) + print(content,file=fd);futils.fclose(fd); + fd=open("Logger_write_once.log","a"); + print("title:"+str(title)+" content:"+str(content)+" job:"+str(rttddft_common.get_job(True))+" date:"+str(datetime.datetime.now())) + if( rttddft_common.get_job(False) is not None ): + print(title+":"+content+"\t\t"+rttddft_common.get_job(True)+" "+str(datetime.datetime.now()),file=fd); + else: + print(title+":"+content+"\t\t"+" "+str(datetime.datetime.now()),file=fd); + + fd.close() + Logger._Array.append(title) + Logger.write(logger,content); return 1 + @staticmethod + def write_maxv(logger,title,value): + if( suppress_prtout() ): + return + if( not (title in Logger._Dict) ): + Logger._Dict.update({title:value}); + Logger.write(logger,"#Logger:maxv:set:"+title+":%e"%(value)); + return 1; + old=Logger._Dict[title] + if( value > old ): + Logger._Dict[title]=value; + Logger.write(logger,"#Logger:maxv:upd:"+title+":%e <- %e"%(value,old)); + @staticmethod + def write_minv(logger,title,value): + if( suppress_prtout() ): + return ## XXX XXX + if( not (title in Logger._Dict) ): + Logger._Dict.update({title:value}); + Logger.write(logger,"#Logger:minv:set:"+title+":%e"%(value)); + return 1; + old=Logger._Dict[title] + if( value < old ): + Logger._Dict[title]=value; + Logger.write(logger,"#Logger:minv:upd:"+title+":%e <- %e"%(value,old)); + + def only_once(self,title,content): + if( suppress_prtout() ): + return 0 ## XXX XXX + if( title in self._array ): + return 0 + self._array.append(title) + self.Info(content) + + #timing(FUNCTIONNAME,start=True); + #timing("end of XXX") + #timing(None,end=True) + def timing(self, title,start=False,end=False, stdout=False, flush=False): + if(start): + self.function=title + self.time[0]=time.time() + self.time[1]=self.time[0];self.time[2]=self.time[0]; + return self.time[0] + else: + self.time[2]=self.time[1];self.time[1]=time.time(); + self.print_timing( \ + (("#end of function:"+self.function+("" if title is None else title)) if end else title) \ + +" elapsed: step=%f function=%f total=%f"%(self.time[1]-self.time[2],self.time[1]-self.time[0],self.time[1]-self.time_00),stdout=stdout,flush=flush ) + + def _printout(self,msg,end="\n",timing=False,fpath=None,Append=False,stdout=False,flush=False): + if( suppress_prtout() ): + return ## XXX XXX + if( timing ): + tcur=time.time() + msg+=" \t time:%12.3f"%(tcur-self.time_00) + fdA=[] + if( fpath is not None ): + fd=open(fpath,("a" if(Append) else "w"));fdA.append(fd) + if( self.filepath is not None ): + fd=open(self.filepath,("a" if(self._append) else "w"));self._append=True;fdA.append(fd) + for fd in fdA: + print(msg,file=fd,end=end,flush=flush);fd.close(); + + Logger.log(msg,stdout=stdout,flush=flush); + + def print_timing(self,msg,end="\n",stdout=False,flush=False): + if( suppress_prtout() ): + return ## XXX XXX + fd=None + if( Logger._TimingLogfile is None ): + Logger._TimingLogfile = Logger.Getlogfpath(extension='_timing.log') + fd=open( Logger._TimingLogfile,'w') + else: + fd=open( Logger._TimingLogfile,'a') + print(msg,file=fd,flush=flush); + fd.close() + Logger.log(msg,end=end,stdout=stdout,flush=flush) + + def Info(self,msg,end="\n",timing=False,stdout=False,flush=False): ## ~ only once or twice per function call + if( suppress_prtout() ): + return ## XXX XXX + self._printout(msg,end=end,timing=timing,stdout=stdout,flush=flush) + + def info(self,msg,end="\n",timing=False,stdout=False,flush=False): + if( suppress_prtout() ): + return ## XXX XXX + self._printout(msg,end=end,timing=timing,stdout=stdout,flush=flush) + + def warning(self,msg,end="\n",timing=False,stdout=True,flush=False): + if( suppress_prtout() ): + return ## XXX XXX + self._printout(msg,end=end,timing=timing,stdout=stdout,flush=flush) + +class filewriter(Logger): + def __init__(self,filepath,bfsz=40,append=False): + self.time_00=time.time() + self.time=[0,0,0] # time[0]:timing("start") time[1]=time[2];time[1]=time.time() + self.filepath=filepath;self._append=append;self.block=-1 + self.buffer=[];self.bfsz=bfsz;self.len=0 + def newblock(self,title): + if( suppress_prtout() ): + return ## XXX XXX + if( self.len>0 ): + self.flush() + self.block+=1; + self.append("\n\n\n"+"#%d:"%(self.block) + title) + + def flush(self): + if( suppress_prtout() ): + return ## XXX XXX + ### print("writing on "+self.filepath); + ### assert(self._append),"not in append mode" + fd=futils.fopen(self.filepath,("a" if(self._append) else "w")) + for item in self.buffer: + print(item,file=fd) + futils.fclose(fd);self._append=True;self.len=0;self.buffer=[]; + def append(self,item,Flush=False,end="\n",timing=False,stdout=False,flush=False): + if( suppress_prtout() ): + return ## XXX XXX + if(self.block<0): + self.block=0 + if( timing ): + tcur=time.time() + item+=" time:%12.3f"%(tcur-self.time_00) + + self.buffer.append(item);self.len+=1 + if( self.len>=self.bfsz or Flush or flush): + self.flush() + if(stdout): + print(item,flush=flush) + def close(self, rename=None): + if( len(self.buffer)>0 ): + self.flush() + if( rename is not None): + os.system("mv "+self.filepath+" "+rename) + self.filepath=rename + + def Info(self,msg,end="\n",timing=False,stdout=False,flush=False): ## ~ only once or twice per function call + if( suppress_prtout() ): + return ## XXX XXX + self.append(msg,end=end,timing=timing,stdout=stdout,flush=flush) + + def info(self,msg,end="\n",timing=False,stdout=False,flush=False): + if( suppress_prtout() ): + return ## XXX XXX + self.append(msg,end=end,timing=timing,stdout=stdout,flush=flush) + + def warning(self,msg,end="\n",timing=False,stdout=True,flush=True): + if( suppress_prtout() ): + return ## XXX XXX + self.append(msg,end=end,timing=timing,stdout=stdout,flush=flush) diff --git a/pyscf/rttddft/Loglv.py b/pyscf/rttddft/Loglv.py new file mode 100644 index 000000000..62e20136a --- /dev/null +++ b/pyscf/rttddft/Loglv.py @@ -0,0 +1,176 @@ +from .pyscf_common import pyscf_common +from mpi4py import MPI +import datetime +import sys + +# SUPER THIS SUBORDINATES +# --- never import -- +# pyscf_common <- Loglv <- mpiutils +# <- update_dict +# +class Loglv: + loglv_default_={'mpi':1,'dbg':1,'default':1} + loglv_keyset=['mpi','dbg','default'] + _Logfile_format={'format':None,'append':[]} ## _Logfile_format%(MPIrank) + _Logfile={'path':None,'append':None} + _Print_datetime=False + warnings_=[] + loglv_=None ## {'mpi':INT,'dbg':INT} + @staticmethod + def Set_Logfile(fpath,Append=False): + if( Loglv._Logfile['path'] is not None ): + if( fpath != Loglv._Logfile['path'] ): + pyscf_common.Warning("Loglv._Logfile: %s is NOT overridden by %s"%(Loglv._Logfile['path'],fpath)) + return + Loglv._Logfile['path']=fpath;Loglv._Logfile['append']=Append + @staticmethod + def Set_Logfileformat(format,Append=False): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank() + MPIsize=comm.Get_size() + if( Loglv._Logfile_format['format'] is not None ): + if( fpath != Loglv._Logfile_format['format'] ): + pyscf_common.Warning("Loglv._Logfile: %s is NOT overridden by %s"%(Loglv._Logfile_format['format'],format)) + return + Loglv._Logfile_format['format']=format;Loglv._Logfile_format['append']=[] + for I in range(MPIsize): + Loglv._Logfile_format['append'].append(Append) + @staticmethod + def Logfile(buf=None,update=True): + if( Loglv._Logfile['path'] is None ): + return None + if(buf is not None): + buf.clear();buf.append(Loglv._Logfile['append']) + if(update): + Loglv._Logfile['append']=True + return Loglv._Logfile['path'] + + @staticmethod + def Logfile_format(buf=None,update=True): + if( Loglv._Logfile_format['format'] is None ): + return None + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank() + if(buf is not None): + buf.clear();buf.append(Loglv._Logfile_format['append'][MPIrank]) + if(update): + Loglv._Logfile_format['append'][MPIrank]=True + return Loglv._Logfile['format'] + @staticmethod + def loglv(key="dbg"): + + if( Loglv.loglv_ is None ): + if( pyscf_common.params is not None ): + if( 'loglv' in pyscf_common.params ): + dum=pyscf_common.params['loglv'] + if( dum is not None ): + if( isinstance(dum,int) ): + Loglv.loglv_={'mpi':dum,'dbg':dum,'default':dum} + elif( isinstance(dum,dict) ): + Loglv.loglv_=Loglv.loglv_default_.copy(); + for ky in dum: + Loglv.loglv_.update({ky:int(dum[ky])}) + else: + assert False,":"+str(type(dum)) + else: + Loglv.loglv_=Loglv.loglv_default_.copy(); + else: + Loglv.loglv_=Loglv.loglv_default_.copy(); + if(key in Loglv.loglv_): + return Loglv.loglv_[key] + else: + dum="unknownkey:"+key + if ( dum not in Loglv.warnings_ ): + Loglv.warnings_.append(dum) + print("#!W Loglv.loglv_:unknown key:"+str(key)); + + return Loglv.loglv_['default']; + +## printout : please do not use -file- option +def printout(text,end='\n',flush=False, + Threads=None,fpath=None,fnme_format=None, + Append=False,dtme=None,stdout=None, + Type='default',redundancy=None, warning=None): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank() + MPIsize=comm.Get_size() + + loglv=Loglv.loglv(Type) + Threads_default_stdout=[0] + Threads_default_multifiles=[ j for j in range(MPIsize) ] + Threads_default_singlefile=[0] + + buf=[] + if( fnme_format is None ): + fnme_format=Loglv.Logfile_format(buf); + if(fnme_format is not None): + Append=buf[0] + + if( Threads is not None ): + if( isinstance(Threads,str) ): + if( Threads=='all' ): + Threads=[ j for j in range(MPIsize) ] + path=None; + if( fpath is not None): ## (1) given path (assuming it as multithread-adapted filename) + threads=( Threads if(Threads is not None) else Threads_default_multifiles ) + path=fpath; + else: + if( fnme_format is not None): + threads=( Threads if(Threads is not None) else Threads_default_multifiles ) + path=( fnme_format%(MPIrank) if(MPIrank in threads) else None ) ## (2) newly given format or (3) _Logfile_format + else: + threads=( Threads if(Threads is not None) else Threads_default_stdout ) + path = ( None if(MPIrank not in threads) else Loglv.Logfile( buf ) ) ## (4) _Logfile + if( path is not None ): + Append=buf[0] + + if(dtme is None):dtme=Loglv._Print_datetime + if(dtme): + text+=' \t\t'+str(datetime.datetime.now()) + + if( redundancy is None ): + redundancy=(0 if(path is not None) else 1) + + if( redundancy >= loglv and (warning is None)): + return + +## threads=( Threads if( (Threads is not None) and (fpath is None) and (fnme_format is None) )\ +## else Threads_default_stdout ) + if( MPIrank not in threads ): + return + + if( path is not None ): + fd=open(path,('a' if(Append) else 'w')) + print(text,file=fd);fd.close() + if( warning is not None): + severity=( warning if(isinstance(warning,int)) else 1 ) + pyscf_common.Print_warning(text,severity=severity); + + if( stdout is None ): + stdout = (True if(path is None) else False) + if( not stdout ): + return + + print(text,flush=flush,end=end) + +def dbgtrace(text,flush=None,redundancy=1,key=None,dtm=False): + loglv=Loglv.loglv('dbg') + if( redundancy >= loglv ): + return + if( flush is None): + flush=( redundancy<(loglv-1) ) + + from mpi4py import MPI + comm = MPI.COMM_WORLD + MPIsize = comm.Get_size() + MPIrank = comm.Get_rank() + string="#dbgtrace:" + ("" if(key is None) else str(key)+":") + + if( MPIsize > 1 ): + string+="%02d:"%(MPIrank) + string+=text + + if( dtm ): + string+=" \t\t"+str(datetime.datetime.now()) + print(string,flush=flush) + diff --git a/pyscf/rttddft/MPIutils01.py b/pyscf/rttddft/MPIutils01.py new file mode 100644 index 000000000..4b3565d25 --- /dev/null +++ b/pyscf/rttddft/MPIutils01.py @@ -0,0 +1,90 @@ +from mpi4py import MPI +from .pyscf_common import pyscf_common +import datetime +import time +import math +import numpy as np + +## +## since 2021.Nov +## controls parallelization +## 2021.12.25 renamed from MPIutils -> MPIutils01 +## +class MPIutils01: + initialized_=False + size_=None;rank_=None + multithreading_=False + stop_parallel_=None + logfpath_=None + + @staticmethod + def logger(content,dtme=True,Threads=[0]): ## set Threads=None to force print out + if( Threads is not None ): + if( MPIutils01.rank_ not in Threads ): + return + else: + content="#$%02d:"%(MPIutils01.rank_) + if( MPIutils01.logfpath_ is None ): + MPIutils01.logfpath_= ("" if(pyscf_common.job is None) else pyscf_common.job)+"_MPIutils01.log" + fd=open(MPIutils01.logfpath_,"w"); + else: + fd=open(MPIutils01.logfpath_,"a"); + if( dtme ): + content=content + " \t\t "+str(datetime.datetime.now()) + print(content,file=fd);fd.close() + + + @staticmethod + def Multithreading(): + return MPIutils01.multithreading_ + @staticmethod + def DebugLog(content,warning=0): + if( warning == 0 ): + MPIutils01.logger(content) + else: + MPIutils01.logger(content, Threads=None) + + @staticmethod + def DebugTrace(key,content,warning=0): + AUinFS=2.418884326058678e-2 + if( (pyscf_common.step_ is not None) and (pyscf_common.time_AU_ is not None) ): + content+=" step:%6d %12.4f %12.4f"%(pyscf_common.step_, pyscf_common.time_AU_, \ + pyscf_common.time_AU_*AUinFS) + if( warning == 0 ): + MPIutils01.logger("#DebugTrace:"+key+":"+content,dtme=True) + else: + MPIutils01.logger(content, Threads=None) + @staticmethod + def setup(multithreading=True): + if( MPIutils01.initialized_ ): + return + comm = MPI.COMM_WORLD + MPIutils01.size_ = comm.Get_size() + MPIutils01.rank_ = comm.Get_rank() + MPIutils01.multithreading_ = ( multithreading and (MPIutils01.size_>1) ) + print("#MPIutils01.$%02d:setup:%d %d %r"%( MPIutils01.rank_,MPIutils01.rank_,MPIutils01.size_,MPIutils01.multithreading_)) + return MPIutils01.rank_, MPIutils01.size_ + @staticmethod + def stop_parallel(reason="",barrier=True): + if( not MPIutils01.multithreading_ ): + return + if( barrier ): + comm = MPI.COMM_WORLD + comm.Barrier() + + MPIutils01.stop_parallel_=reason; + MPIutils01.multithreading_=False + MPIutils01.logger("stop_parallel"+str(reason),Threads=None) + @staticmethod + def restart_parallel(reason="",barrier=True): + if( MPIutils01.multithreading_ ): + return + if( barrier ): + comm = MPI.COMM_WORLD + comm.Barrier() + reason_stop=MPIutils01.stop_parallel_ + MPIutils01.stop_parallel_=None; + MPIutils01.multithreading_=True + MPIutils01.logger("restart_parallel"+str(reason_stop)+"->",str(reason),Threads=None) + + diff --git a/pyscf/rttddft/Moldyn.py b/pyscf/rttddft/Moldyn.py new file mode 100644 index 000000000..4af951cf5 --- /dev/null +++ b/pyscf/rttddft/Moldyn.py @@ -0,0 +1,2232 @@ +import sys +from scipy import linalg +import numpy as np +import os +import time +import math +import os.path +import datetime +from mpi4py import MPI + +from pyscf.pbc import scf as pyscf_pbc_scf +from pyscf.scf.diis import ADIIS,CDIIS,EDIIS +from .diis import DIIS_dmat +from pyscf import lib as pyscf_lib +import pyscf.gto as molgto +from pyscf.gto import Mole +from pyscf.pbc.gto import Cell +from pyscf.gto.mole import nao_nr +from pyscf.pbc import gto, df + +from .rttddft_common import rttddft_common +from .print_00 import print_00, close_00, open_00 +from .Loglv import printout + +from .physicalconstants import physicalconstants,PhysicalConstants +from .Logger import Logger +from .futils import futils +from .serialize import svld_aNbuf,diff_aNbuf + +# i1eqb, +#from utils import print_bset,make_tempfile,dNtoa,d1toa,zNtoa,z1toa_polar,write_xyzf,write_xyzstring,read_xyzf,arrayclone,aNmaxdiff,calc_eorbs,hdiag,modify_filename,deviation_from_unitmatrix,z1maxloc,i1prod,parse_dict,dic_to_string,parse_xyzstring +from .utils import print_bset,make_tempfile,dNtoa,d1toa,zNtoa,write_xyzf,write_xyzstring,read_xyzf,arrayclone,\ + dic_to_string,parse_xyzstring,i1prod,prtout_MOocc,calc_eorbs,hdiag,modify_filename,deviation_from_unitmatrix,\ + print_00,open_00,close_00,z1maxloc,i1eqb,z1toa,z1toa_polar,aNmaxdiff,check_wfNorm,popsum,print_TDeorbs,normalize,update_dict,printout_dict +from .rttddft01 import construct_Aind_args,rttddft_set_Aind_args,rttddft_get_Aind_args,rttddftMOL,rttddftPBC,Logger,check_nao_nr +# from rttddft02 import rttddftMOL_UKS,rttddftMOL_ROKS,rttddftPBC_UKS,rttddftPBC_ROKS +from .serialize import load_fromfile,parse_file,serialize,construct_tdfield + +Dic_wctm={} +# Alternative for read_xyzf +# +# !! in read_xyzf, -outputunit- was implicit (defaulted to ANGS, since xyzf is in ANGS unit) +# !! whereas in this subroutine, you MUST explicitly specify A or B. +# +# !! outputunit (A or B) also applies to lattice vectors +# +def read_mol_or_cell(mol_or_cell,dict=None,outputunit=None): + assert (outputunit=='A' or outputunit=='B'), "PLS specify outputunit" + spdm=3 + natm=mol_or_cell.natm + BOHRinANGS=PhysicalConstants.BOHRinANGS() + if(isinstance(mol_or_cell,Cell)): + # + latticevectors_BOHR = np.array( mol_or_cell.lattice_vectors() ) + # print("latticevectors_BOHR",latticevectors_BOHR) + if( outputunit == 'A' ): + dict.update({'a':latticevectors_BOHR*BOHRinANGS}) + else: + dict.update({'a':latticevectors_BOHR}) +# We assume that _atom = [ row_1, row_2, ... ,row_nAtm ] + assert len(mol_or_cell._atom)==natm,"unexpected size of mol_or_cell._atom" + Sy=[];Rnuc_BOHR=[] + for ia in range(natm): + row=mol_or_cell._atom[ia] + s=row[0]; + assert isinstance(s,str),"" + Sy.append(s) + xyz=row[1] + assert len(xyz)==spdm,"" + assert isinstance(xyz[0],float) or isinstance(xyz[0],np.float64),"" + Rnuc_BOHR.append(xyz) + if(outputunit=='A'): + Rnuc_ANGS=np.array(Rnuc_BOHR)*BOHRinANGS + return Rnuc_ANGS,Sy + else: + return Rnuc_BOHR,Sy + + +def print_in_MOrep(pbc,nmult_matrix,header,AOmatrix,MOvcs,nmult_MOvcs,Threads=[0]): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if( MPIrank not in Threads ): + return + + nmult=max( nmult_matrix, nmult_MOvcs ) + for sp in range(nmult): + xtn=("" if(nmult==0) else ("_upSpin" if(sp==0) else "_dnSpin")) + Matr=( AOmatrix if(nmult_matrix == 0) else AOmatrix[sp]) + Vcs =( MOvcs if(nmult_MOvcs == 0) else MOvcs[sp] ) + print_in_MOrep_1(pbc,header+xtn,Matr,Vcs,Threads=Threads) + +def kpoints_diamondlattice(BravaisVectors_au,N_div=None): + PIx2=6.283185307179586476925286766559 + PI=3.1415926535897932384626433832795 + sqrt2=1.4142135623730950488016887242097 + a=sqrt2*np.sqrt( np.vdot( BravaisVectors_au[0], BravaisVectors_au[0] ) ) + print(a) + X_=np.array([ PIx2/a, 0.0, 0.0 ]) + W_=np.array([ PIx2/a, PI/a, 0.0 ]) + K_=np.array([ 1.5*PI/a, 1.5*PI/a, 0.0 ]) + L_=np.array([ PI/a, PI/a, PI/a ]) + G_=np.array([ 0.0, 0.0, 0.0 ]) + vertices=[ L_, G_, X_, W_, K_, G_];Nsect=5 +## Ndim=[ 20, 20, 20, 20, 20 ];Nsect=5 + if(N_div is None): + Ndim=[ 2, 2, 2, 2, 2 ] + else: + Ndim=[ N_div,N_div,N_div,N_div,N_div ] + + labels=['L', 'G', 'X', 'W', 'K', 'G'] + ret=[];trlen=[];s=0.0 + for Isect in range(Nsect): + A=vertices[Isect];B=vertices[Isect+1] + N=Ndim[Isect] + d=np.zeros([3],dtype=np.float64); P=np.zeros([3],dtype=np.float64) + + d[0]=(B[0]-A[0])/float(N); d[1]=(B[1]-A[1])/float(N); d[2]=(B[2]-A[2])/float(N); + P[0]=A[0]; P[1]=A[1]; P[2]=A[2]; + dL=np.sqrt( np.vdot(d,d) ) + for J in range(N): + ret.append(P.copy());trlen.append(s); + P=P+d;s=s+dL + ret.append(P.copy());trlen.append(s); + return ret,trlen,Ndim,labels ## ret[NdSUM],trlen[NdSUM],Ndim[Nsect],labels[Nsect+1] Nsect=5,NdSUM=100 + +def print_in_MOrep_1(pbc,header,AOmatrix,MOvcs,Threads=[0]): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if( MPIrank not in Threads ): + return + Ndim=np.shape(AOmatrix) + nkp=1;nAO=Ndim[0];nMO=Ndim[1] + if( pbc ): + nkp=Ndim[0];nAO=Ndim[1];nMO=Ndim[2] + for kp in range(nkp): + MO=( MOvcs if(not pbc) else MOvcs[kp]) + DM=( AOmatrix if(not pbc) else AOmatrix[kp]) + dMO=np.matmul( np.matrix.getH(MO), np.matmul( DM, MO) ) + for I in range(nMO): + str=""; + for J in range(nMO): + str+=("%16.6f "%(DM[I][I].real) if(I==J) else "%7.3f %7.3fj "%(DM[I][J].real,DM[I][J].imag)) + print(header+":%02d:%3d"%(kp,I)+str) ### thread-0 only + +#$ +#$ check_wfNorms: checks wf norms and (i) fix if deviation exceeds TOL and (ii) print result to logger +#$ @param:AOrep : True if AOrep / False if orthogonal rep (i.e. \sum |wf[:]|**2 = 1.0) +def check_wfNorms(nkpt,nAO,nMO, rttddft,pbc,spinrestriction,wfn,AOrep,sqrdevtol_FIX=1.0e-6,title="",logger=None): + assert( nAO is not None),"check_wfNorms.." + ## wfn: R,O:spin-sym U:spin-pol + if( spinrestriction == 'U' ): + check_wfNorm1(nkpt,nAO,nMO, rttddft,pbc,wfn[0],AOrep,sqrdevtol_FIX=sqrdevtol_FIX, title=title+"_upSpin",logger=logger) + check_wfNorm1(nkpt,nAO,nMO, rttddft,pbc,wfn[1],AOrep,sqrdevtol_FIX=sqrdevtol_FIX, title=title+"_dnSpin",logger=logger) + else: + check_wfNorm1(nkpt,nAO,nMO, rttddft,pbc,wfn,AOrep,sqrdevtol_FIX=sqrdevtol_FIX, title=title,logger=logger) + +def check_wfNorm1(nkpt,nAO,nMO, rttddft,pbc,wfn,AOrep,sqrdevtol_FIX=1.0e-6,title="",logger=None): + sqrNorms=np.zeros(nMO) + kvectors = (None if (not pbc) else np.reshape( rttddft.kpts, (-1,3))) + maxdev=-1.0; Nfix=0 + for kp in range(nkpt): + if(AOrep): + if( not pbc ): + tgt=wfn; S1e=rttddft.get_ovlp() + else: + tgt=wfn[kp]; S1e=rttddft.get_ovlp( rttddft.cell, kvectors[kp]) + for I in range(nMO): + sqrNorms[I]=np.vdot( tgt[:,I], np.matmul( S1e, tgt[:,I] ) ).real + dev = abs( sqrNorms[I]-1.0 ) + if( dev > maxdev ): + maxdev = dev + if( sqrdevtol_FIX>=0 and dev > sqrdevtol_FIX ): + fac=1.0/np.sqrt( sqrNorms[I] );Nfix+=1 + for K in range(nAO): + tgt[K][I]=tgt[K][I]*fac + else: + if( not pbc ): + tgt=wfn; + else: + tgt=wfn[kp]; + for I in range(nMO): + sqrNorms[I]=np.vdot( tgt[:,I], tgt[:,I] ).real + dev = abs( sqrNorms[I]-1.0 ) + if( dev > maxdev ): + maxdev = dev + if( sqrdevtol_FIX>=0 and dev > sqrdevtol_FIX ): + fac=1.0/np.sqrt( sqrNorms[I] );Nfix+=1 + for K in range(nAO): + tgt[K][I]=tgt[K][I]*fac + if(logger is not None): + logger.Info("#orth_tdMO:%s sqrdevMax:%e Nfix:%d/%d"%(title,maxdev,Nfix,nMO)); ## multithread-adapted + return maxdev,Nfix + +## +## compare_MOs: prints out (LHS^{\dagger} S1e RHS) +## +def compare_MOs(LHS,RHS,S1e_k,title=""): + + NdL=np.shape(LHS);NdR=np.shape(RHS) + pbc=( len(NdL)==3 ) + nkp=1;nAO=NdL[0];nMO=NdL[1] + if( pbc ): + nkp=NdL[0];nAO=NdL[1];nMO=NdL[2] + for kp in range(nkp): + lh=LHS;rh=RHS;S1=S1e_k + if( pbc ): + lh=LHS[kp];rh=RHS[kp];S1=S1e_k[kp] + T=np.matmul( np.matrix.getH(lh), np.matmul(S1,rh)) + + for lmo in range(nMO): + print_00("#compare_MOs:%s:%02d:%3d:"%(title,kp,lmo) + z1toa_polar(T[lmo])) + +def prteorbs01(CanonicalMO,moldyn,rttddft,fpath=None,Append=False,kpoints=None,description="", diamondlattice=False): + if(fpath is None): + fpath=(rttddft_common.get_job(True))+( "_Canonicaleorbs0.dat" if(CanonicalMO) else "_prteorbs01.dat") + fdOUT=open(fpath,('a' if(Append) else 'w')) + + for Loop in range(1): + #if( Loop==1 ): + # fpath=(rttddft_common.get_job(True))+"_Canonicaleorbs1.dat" + # fdOUT=open(fpath,"w") + print('## Moldyn.print_canonicaleorbs:'+description+" \t\t "+str(datetime.datetime.now()),file=fdOUT) + ## diamondlattice=(Loop==1) + trlen=None;Ndim=None;labels=None + ##if(kpoints is None): + if(diamondlattice): + kpoints,trlen,Ndim,labels=kpoints_diamondlattice( moldyn.BravaisVectors_au,N_div=3 ) + else: + kpoints=np.reshape( rttddft.kpts, (-1,3) ) + nKpoints=len(kpoints);trlen=[];s=0.0 + for j in range(nKpoints): + trlen.append(s); + if(j=dagdevWRN or ofddev >=ofddevWRN or devsum>=devsumWRN): + warning=1 + else: + warning=-1 + if(warning != 0 ): + print_matrix(dum,"Invsqrt X S X Invsqrt:dev=%e,%e,%e"%(dagdev,ofddev,devsum),"Invsqrt.log",Append=False,format="%12.4e") + print_matrix(S,"S Invsqrt:dev=%e,%e,%e"%(dagdev,ofddev,devsum),"SAO.log",Append=False,format="%14.6e") + if( Moldyn_static_.Ssqrt_dev_max_[0] < dagdev or Moldyn_static_.Ssqrt_dev_max_[1] < ofddev ): + print_00("#get_Sinvsqrt:dev:DAG%e OFD%e devsum%e"%(dagdev,ofddev,devsum),warning=warning) + Moldyn_static_.Ssqrt_dev_max_[0]=max( Moldyn_static_.Ssqrt_dev_max_[0],dagdev ) + Moldyn_static_.Ssqrt_dev_max_[1]=max( Moldyn_static_.Ssqrt_dev_max_[1],ofddev ) + assert (dagdev 1e-6 or dev2 > 1e-6 ): + Xnuc_mol =np.ravel( Rnuc_mol ) + Xnuc =np.ravel( Rnuc_au ) + Xnuc_dfcell=np.ravel( Rnuc_dfcell ) + le=len(Xnuc) + print("# no retv.mol.atom Rnuc retv.df.cell.atom"); + for j in range(le): + print(" %3d %14.6f %14.6f %14.6f"%(j,Xnuc_mol[j],Xnuc[j],Xnuc_dfcell[j])) + + + assert dev1<2e-5,""; assert dev2<2e-5,"" + else: + print("#gen_rttddft:Rnuc:%e"%(dev1));assert dev1<1e-6,""; + return retv + def gen_rttddft_(self, mol_or_cell=None, Rnuc=None,unit=None, nKpoints=None, td_field=None, + gauge_LorV=None, logger=None, set_occ=None, xc=None, check_timing=None, + set_timeAU=True, kpts=None, auxbasis=None): + + """ a private function, generates an rtTDDFT object for given Rnuc (default: self.Rnuc)""" + + docheck_timing=False + if( check_timing is not None ): + docheck_timing=check_timing + else: + if(self.check_timing is not None ): + docheck_timing=self.check_timing + + if(docheck_timing): + assert self.pbc,"not yet implemented " + + Rnuc_au=None + if( Rnuc is not None): + assert (unit =='A' or unit=='B'),"unit:"+unit + if( unit=='B'): + Rnuc_au=Rnuc + else: + Rnuc_au=arrayclone(Rnuc);Rnuc_au = Rnuc_au/physicalconstants.BOHRinANGS + else: + Rnuc_au=self.Rnuc + if mol_or_cell is None: mol_or_cell = self.gen_mol_or_cell(Rnuc_au); + if nKpoints is None: nKpoints = self.nKpoints; + if td_field is None: td_field = self.td_field; + if gauge_LorV is None: gauge_LorV = self.gauge_LorV; + if xc is None: xc=self.xc; + Logger.write(self.logger,"#gen_rttddft"); + Logger.Check_meshsize(mol_or_cell) + if( td_field is None): + assert (gauge_LorV is None),"Gauge should be None" + else: + assert ( (gauge_LorV is not None) and ( (gauge_LorV == 'L') or (gauge_LorV == 'V') ) ),"gauge" + + dipolegauge=False + if( gauge_LorV is not None): + dipolegauge = (gauge_LorV == 'L') + + ret=None + if( not self.pbc ): + if( self.spinrestriction == 'R' ): + ret=rttddftMOL(mol_or_cell,td_field=td_field,dipolegauge=dipolegauge,xc=xc) + elif( self.spinrestriction == 'O' ): + ret=rttddftMOL_ROKS(mol_or_cell,td_field=td_field,dipolegauge=dipolegauge,xc=xc) + elif( self.spinrestriction == 'U' ): + ret=rttddftMOL_UKS(mol_or_cell,td_field=td_field,dipolegauge=dipolegauge,xc=xc) + else: + assert False,"unknown DFT:"+self.spinrestriction + ##sprint(type(ret)) + else: + # print_00("#Moldyn.gen_rttddft:kpts cell.make_kpts(%s):"%(str(nKpoints))+str(mol_or_cell.make_kpts(nKpoints))) + if(kpts is None ): + kpts = mol_or_cell.make_kpts(nKpoints) + else: + print("#use given kpts:",kpts); + + if( self.spinrestriction == 'R' ): + ### print_00("nKpoints:",end="");print_00(nKpoints) + if( docheck_timing ): + ret=rttddftPBC_timing(mol_or_cell,kpts=kpts, + td_field=td_field,dipolegauge=dipolegauge,xc=xc) + else: + ret=rttddftPBC(mol_or_cell,kpts=kpts, + td_field=td_field,dipolegauge=dipolegauge,xc=xc) + elif( self.spinrestriction == 'O' ): + ret=rttddftPBC_ROKS(mol_or_cell,kpts=kpts, + td_field=td_field,dipolegauge=dipolegauge,xc=xc) + elif( self.spinrestriction == 'U' ): + ret=rttddftPBC_UKS(mol_or_cell,kpts=kpts, + td_field=td_field,dipolegauge=dipolegauge,xc=xc) + if(self.pbc): + ret.set_calc_Aind(self._calc_Aind, self._alpha_Aind_over_c); ret._calc_Aind = self._calc_Aind; + ret._dt_AU=self._dt_AU; ret.BravaisVectors_au=self.BravaisVectors_au + rttddft_common.Write_once("Moldyn.calc_Aind", "#gen_rttddft:calc_Aind:%d dt_AU:%s"%(self._calc_Aind,str(ret._dt_AU)),\ + filename="Aind") + + if(self._fixednucleiapprox is not None ): ## 20210610:fixednucleiapprox + ret._fixednucleiapprox = self._fixednucleiapprox + print_00("#gen_rttddft:fixednucleiapprox:%r"%(ret._fixednucleiapprox)) + + ret.set_nOrbs( nkpt=self.nkpt, nAO=self.nAO, nMO=self.nMO) + dbgng=True;fdLog=sys.stdout + if(dbgng): + fdLog=open_00("gen_rttddft.log","a") + print("job:"+str(rttddft_common.get_job(True))+"ret:"+str(ret)) + print_00("#gen:"+str(type(ret))+" \t"+rttddft_common.get_job(True)+" \t\t"+str(datetime.datetime.now()),file=fdLog) + if( self.tdMO is not None ): + ret.mo_coeff=arrayclone( self.tdMO, dtype=np.complex128 ) + print_00("mo_coeff set:"+zNtoa(ret.mo_coeff,Nlimit=5),file=fdLog) + if( set_occ is not None ): + if(set_occ): + ret.set_mo_occ( self.mo_occ,fix_occ=True,clone=False) + print_00("#mo_occ set:"+dNtoa(self.mo_occ),file=fdLog) + if(dbgng): + close_00(fdLog); ##fdLog.close() + + if( logger is not None): + ret.set_logger(logger) + + if( self.pbc ): + assert ( self.df is not None ),"df" + + if( self.df is not None ): + if( self.df == "GDF" ): + gdf=df.GDF( mol_or_cell ); + if( nKpoints is not None): + if( kpts is None ): + kpts = mol_or_cell.make_kpts(nKpoints) + else: + kpts=arrayclone(kpts) + gdf.kpts= kpts ## NEVER FORGET THIS... + + + printout("#GDF:"+" \t\t"+str(rttddft_common.get_job(True)),fpath="df.log",Append=True,dtme=True) + if( auxbasis is not None): + printout("#GDF:gen_rttddft:auxbasis.org:"+str(gdf.auxbasis)+"_%d"%( gdf.get_naoaux() ), + fpath="df.log",Append=True,dtme=True,stdout=True) + gdf.auxbasis=auxbasis + printout("#GDF:gen_rttddft:auxbasis.new:"+str(gdf.auxbasis)+"_%d"%( gdf.get_naoaux() ), + fpath="df.log",Append=True,dtme=True,stdout=True) + else: + printout("#GDF:gen_rttddft:auxbasis:"+str(gdf.auxbasis)+"_%d"%( gdf.get_naoaux() ), + fpath="df.log",Append=True,dtme=True) + + ret.with_df=gdf + elif( self.df == "FFTDF" ): + fftdf = df.FFTDF(mol_or_cell) + if( nKpoints is not None): + if( kpts is None ): + kpts = mol_or_cell.make_kpts(nKpoints) + else: + kpts=arrayclone(kpts) + fftdf.kpts= kpts ## NEVER FORGET THIS... + ret.with_df=fftdf + printout("#FFTDF:"+str(fftdf.mesh)+" \t\t"+str(rttddft_common.get_job(True)),fpath="df.log",Append=True,dtme=True) + elif( self.df == "MDF" ): + if( kpts is None ): + kpts = mol_or_cell.make_kpts(nKpoints) + mdf = df.MDF(mol_or_cell,kpts=kpts) + ret.with_df= mdf + print("mdf.kpts:",mdf.kpts) + printout("#MDF:"+str(mdf.mesh)+ " auxbasis:"+str(mdf.auxbasis)+"_%d"%( mdf.get_naoaux() ) + +" \t\t"+str(rttddft_common.get_job(True)),fpath="df.log",Append=True,dtme=True) + + else: + assert False,"unimplemented" + if( self._calc_Aind != 0 ): + if( self._Aind_args is not None): + rttddft_set_Aind_args(ret, self._Aind_args) + else: + print("#Aind_args is None.."); ## TODO: XXX XXX in future this SHOULD lead abortion + + if( set_timeAU ): + ret._time_AU=self.time_AU + if( self._calc_Aind != 0 and (ret._Aind_tmAU is not None) ): + tdiff=abs( ret._time_AU - ret._Aind_tmAU) + assert tdiff<1.0e-6,"tmAU differs:%f %f %f"%(self.time_AU,ret._time_AU,ret._Aind_tmAU) + printout("#set_timeAU:%f %f %f"%(self.time_AU,ret._time_AU,ret._Aind_tmAU),fpath="Aind_tmAU.log",Append=True,dtme=True) + + #2021.12.25 addons ---- + if( self.Temperature_au is not None): + rttddft_common.Write_once("Moldyn.Temperature","smearing:%f au"%(self.Temperature_au),filename="rttddft") + ret = pyscf_pbc_scf.addons.smearing_(ret, sigma=self.Temperature_au, method='fermi') + if( self.levelshift is not None ): + rttddft_common.Write_once("Moldyn.levelshift","levelshift:%f au"%(self.levelshift),filename="rttddft") + ret.level_shift=self.levelshift + if( self.DIIS_params is not None ): + algorithm= self.DIIS_params["algorithm"] + diis_space=( 6 if("diis_space" not in self.DIIS_params) else self.DIIS_params["diis_space"] ) + diis_space_rollback = ( False if( "diis_space_rollback" not in self.DIIS_params) else \ + self.DIIS_params["diis_space_rollback"] ) + rttddft_common.Write_once("Moldyn.DIIS","DIIS:%s %d %r"%(algorithm,diis_space,diis_space_rollback),filename="rttddft") + if( algorithm == "ADIIS" ): + ret.diis=ADIIS(ret, ret.diis_file) + elif( algorithm == "EDIIS" ): + ret.diis=EDIIS(ret, ret.diis_file) + elif( algorithm == "CDIIS" ): + ret.diis=CDIIS(ret, ret.diis_file) ## this is the default choice + elif( algorithm == "DIIS_dmat" ): + ret.diis=DIIS_dmat(6,PBC,scheme="SDFFDS") + else: + assert False,"unknown DIIS"+str(params["DIIS"]) + ret.diis.diis_space = diis_space; + ret.diis.diis_space_rollback = diis_space_rollback + ### heapcheck("Moldyn.gen_mol_or_cell:AF") + return ret + + def gen_mol_or_cell( self, Rnuc=None, unit='B', spin=None, charge=None ): + assert (unit=='B'),"gen_mol_or_cell" + if Rnuc is None:Rnuc=self.Rnuc; + if spin is None:spin=self.spin; + if charge is None:charge=self.charge; + + if( not self.pbc ): + ret = molgto.Mole() + else: + ret = gto.Cell() + + if( self.mesh is not None): + ret.mesh=self.mesh + ### print_00("#cell.mesh set:",end="");print_00(self.mesh) + if( self.rcut is not None): + ret.rcut=self.rcut + print_00("#cell.rcut set:",end="");print_00(self.rcut) + + if( self.exp_to_discard is not None): + ret.exp_to_discard = self.exp_to_discard + + if( self.cell_dimension is not None ): + ret.dimension = self.cell_dimension + if( charge is not None ): + ret.charge=charge; + if( self.cell_precision is not None ): + ret.precision=self.cell_precision; + ret.atom = write_xyzstring(Rnuc,self.Symbols,input_unit='B',output_unit='A') + ret.basis = self.basis + + if( self.pseudo is not None): + ret.pseudo = self.pseudo + + if( self.pbc ): + ret.a = self.a ### this should be an intrinsic property so I leave it .. but let's use .BravaisVectors_au for our calculations + ret.BravaisVectors_au = self.BravaisVectors_au + kpts=ret.make_kpts(self.nKpoints) + rttddft_common.Write_once("Moldyn.kpoints","#Moldyn:kpts cell.make_kpts(%s):"%(str(self.nKpoints))+str(kpts), + filename="Moldyn") + + if( spin is not None ): + ret.spin=spin + ret.build() + + if( self.nAO is None ): + self.nAO=check_nao_nr(ret) + print_00("#Moldyn.nAO:%d"%(self.nAO)) + + if( self.basis not in Moldyn_static_.Bsets_): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank();MPIsize=comm.Get_size() + if( MPIsize < 2 or MPIrank==0 ): + fnme=rttddft_common.get_job(True)+"_Bset.dat" + print_bset(fnme,ret,Append=(len(Moldyn_static_.Bsets_)>0)) + + Moldyn_static_.Bsets_.append(self.basis) + return ret + +# i) use existing tdDM : dm=self.tdDM,(update_tdDM=None) +# ii)recalculate tdDM and update md.tdDM : dm=None,(update_tdDM=None) +# but no update dm=None update_tdDM=False + def calc_energy_tot(self,rttddft,dm=None,h1e=None,vhf=None,time_AU=None,update_tdDM=None,dict=None, + filename=None, filename_refr=None): + + from .utils import update_dict,printout_dict + import time + + h1eNone=(h1e is None);vhfNone=(vhf is None) + fncnme='calc_energy_tot';fncdepth=5 ## fncdepth ~ SCF:0 vhf:1 get_j:2 + Wctm000=time.time();Wctm010=Wctm000;dic1_wctm={} + + if time_AU is None:time_AU=self.time_AU + if update_tdDM is None:update_tdDM=True + if (dm is None): + print_00("#calc_energy_tot:dm is None.."); + dm=self.calc_tdDM(rttddft, ovrd=update_tdDM ) + ### if dm is None: dm=self.calc_tdDM(rttddft, ovrd=update_tdDM ) + # ??? 2021.05.14 commented out print("#calc_energy_tot:shape of dm:",end="");print(np.shape(dm)) + if h1e is None:h1e=self.calc_hcore(rttddft,time_AU) + if( h1eNone ): + Wctm020=Wctm010;Wctm010=time.time();update_dict(fncnme,dic1_wctm,Dic_wctm,"h1e",Wctm010-Wctm020,depth=fncdepth) + if vhf is None:vhf=self.calc_veff(rttddft,dm=dm) + if( vhfNone ): + Wctm020=Wctm010;Wctm010=time.time();update_dict(fncnme,dic1_wctm,Dic_wctm,"vhf",Wctm010-Wctm020,depth=fncdepth) + + + + # hf.py: def energy_elec(mf, dm=None, h1e=None, vhf=None): + # rks.py: def energy_elec(ks, dm=None, h1e=None, vhf=None): + # krks.py:def energy_elec(self, dm_kpts=None, h1e_kpts=None, vhf=None) + ec_plus_exc=None + dbgng=True + if(dbgng): + ec=getattr(vhf, 'ecoul', None) + exc=getattr(vhf, 'exc', None) + # print("vhf.ecoul:",end="");print(ec) + # ec1=getattr(vhf[1], 'ecoul', None) + # print("vhf1.ecoul:",end="");print(ec1) + if( (ec is not None) and (exc is not None) ): + ec_plus_exc=ec+exc + if( dict is not None): + dict.update({'ecoulxc':ec_plus_exc}) + nkpt=(1 if(not self.pbc) else self.nkpt) + eh1=0.0 + nmult=(2 if(self.spinrestriction=='U') else 1); + ## h1e[nkp][nAO][nAO] / h1e[nAO][nAO] + for kp in range(nkpt): + h1e_k= ( h1e if(not self.pbc) else h1e[kp]) + if(self.spinrestriction=='U'): + eh1+=np.einsum('ij,ji->', h1e_k, ( dm[0] if(not self.pbc) else dm[0][kp] ))\ + + np.einsum('ij,ji->', h1e_k, ( dm[1] if(not self.pbc) else dm[1][kp] )) + else: + eh1+=np.einsum('ij,ji->', h1e_k,( dm if(not self.pbc) else dm[kp])) + if( self.pbc ): + eh1 = eh1/float(nkpt) + if( dict is not None): + dict.update({'ekin':eh1}) + Wctm020=Wctm010;Wctm010=time.time();Wctm_einsum=Wctm010-Wctm020 + update_dict(fncnme,dic1_wctm,Dic_wctm,"einsum_h1e_k",Wctm010-Wctm020,depth=fncdepth) + if( self.pbc ): + test=np.einsum('kij,kji->',h1e,dm,optimize="greed");test/=float(nkpt) + Wctm020=Wctm010;Wctm010=time.time();Wctm_OptEinsum=Wctm010-Wctm020 + print("calc_eng:OptEinSum:%f elapsed:%f / old:%f elapsed:%f diff %e"%(test,Wctm_OptEinsum,\ + eh1,Wctm_einsum,abs(eh1-test))) + + + Eel,eCoulXC = rttddft.energy_elec(dm,h1e,vhf) ## note: + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_wctm,Dic_wctm,"rttddft.energy_elec",Wctm010-Wctm020,depth=fncdepth) + if( ec_plus_exc is not None ): + assert abs(eCoulXC-ec_plus_exc)<1.0e-5,"" + else: + if( dict is not None): + dict.update({'ecoulxc':eCoulXC}) + + ec=getattr(vhf, 'ecoul', None) + print_00("vhf.ecoul:",end="");print_00(ec) + e1=rttddft.scf_summary['e1'] +#Moldyn:calc_energy_tot:eCoulXC:-16.630561609700713 / -16.630561609700713 ekin:(25.370127214648235+0j)/25.370127214648235 + print_00("Moldyn:calc_energy_tot:eCoulXC:"+str(ec_plus_exc)+" / "+str(eCoulXC)+" ekin:"+str(eh1)+"/"+str(e1)) + + + Enuc = rttddft.energy_nuc() + + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_wctm,Dic_wctm,"rttddft.energy_nuc",Wctm010-Wctm020,depth=fncdepth) + printout_dict(fncnme,dic1_wctm,Dic_wctm,Wctm010-Wctm000,depth=fncdepth) + + if( filename is not None ): + comment="Moldyn.calc_energy_tot:%f,%f,%f,%f \t\t"%( Eel+Enuc, Enuc, eCoulXC, Eel-eCoulXC)\ + + rttddft_common.get_job(True) + str(self.step) + svld_aNbuf('S',filename+"_dm.dat",buf=dm,comment=comment) + svld_aNbuf('S',filename+"_vhf.dat",buf=vhf,comment=comment) + if( filename_refr is not None ): + sbuf=[] + dmREF=svld_aNbuf('L',filename_refr+"_dm.dat",get_comments=sbuf) + vhfREF=svld_aNbuf('L',filename_refr+"_vhf.dat") + dev1=aNmaxdiff(dmREF,dm);dev2=aNmaxdiff(vhf,vhfREF) + print("#CompTo:"+sbuf[0]) + print("#dmDIFF:%e"%(dev1)) + print("#vhfDIFF:%e"%(dev2)) + diff_aNbuf(dm,dmREF) + + return Eel+Enuc,Enuc,eCoulXC,Eel-eCoulXC ## EelSum, ncCoul,elCoul,elKE + + def svld_energy(self,SorL,pscfpath,eDict=None,Threads=[0]): + ## o Checks Energy expectation value at saving/loading Moldyn + ## o + ## + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + fname=pscfpath.replace(".pscf","") + fname_logf=fname+"_recalc_eng.log" + if( SorL == 'L'): + if( not os.path.exists(fname_logf) ): + rttddft_common.Assert(False,"#!W missing logfile:"+fname_logf,1) ## 2022.03.03 we do not stop here + return None + + rttddft=self.gen_rttddft( Rnuc=self.Rnuc, unit='B') + Eel,ncCoul,elCoul,elKE=self.calc_energy_tot(rttddft,filename=fname+"_recalc_eng") + if( MPIsize<2 or (MPIrank in Threads) ): + print("#Moldyn.load:Energies:%16.8f %16.8f %16.8f %16.8f"%(Eel,ncCoul,elCoul,elKE)) + if( eDict is not None): + eDict.update({"Eel":Eel,"ncCoul":ncCoul,"elCoul":elCoul,"elKE":elKE}) + if( SorL == 'S' ): + fd=open(fname_logf,"w") + print("%6d %14.6f %16.8f %16.8f %16.8f %16.8f"%(self.step, self.time_AU, Eel,ncCoul,elCoul,elKE),file=fd) + fd.close() + return None + else: + dev=None + fd=open(fname_logf,"r");ok=False + for line in fd: + line=line.strip() + sA=line.split();nA=len(sA) + if(nA>=6): + step=int(sA[0]); tm_AU=float(sA[1]); Eel_1=float(sA[2]); ncCoul_1=float(sA[3]); + elCoul_1=float(sA[4]); elKE_1=float(sA[5]); + diffs= [ abs(Eel-Eel_1), abs(ncCoul-ncCoul_1), abs(elCoul-elCoul_1), abs(elKE-elKE_1) ] + dev=max(diffs) + print("#Moldyn.load:energy deviations:"+str(diffs)) + print("#Moldyn.load:Energies:CALC:%16.8f %16.8f %16.8f %16.8f"%(Eel,ncCoul,elCoul,elKE)) + print("#Moldyn.load:Energies:READ:%16.8f %16.8f %16.8f %16.8f"%(Eel_1,ncCoul_1,elCoul_1,elKE_1)) + + ok=True + fd.close() + assert ok,"failed reading from:"+fname_logf ## TODO PLS WEAKEN THIS ASSERTION + return dev + def save(self,fpath,delimiter='\n',comment=None,Threads=[0],rttddft=None,caller=None, Barrier=False): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if( self._calc_Aind != 0 ): + dbgng=True ## XXX XXX + assert rttddft is not None,"PLS set rttddft in save method !!" + self._Aind_args={}; rttddft_get_Aind_args(rttddft,self._Aind_args) + if(dbgng): + fd1=open("Aind_over_c_SAVE.log","w");print(self._Aind_args,file=fd1);fd1.close() + wt0=time.time(); wt1=wt0; wt_ser=0; wt_sync=0 + STRcaller=("" if(caller is None) else caller), + print("#moldyn.save:$%02d:%s start \t\t %s"%( MPIrank, STRcaller, str(datetime.datetime.now())),flush=True) + serialize(self,fpath=fpath,delimiter=delimiter,comment=comment,serializers=Moldyn.Serializers__, + Threads=Threads,return_None=True) + wt2=wt1; wt1=time.time(); wt_ser=wt1-wt2 + print("#moldyn.save:$%02d:%s end elapsed:%f \t\t %s"%( MPIrank, STRcaller, wt_ser,str(datetime.datetime.now())),flush=True) + if( (wt_ser > 30.0) and (MPIsize<2 or MPIrank==0) ): + fd1=open("Moldyn_save.log","a") + print("#Moldyn.save:$%02d:%s elapsed:%f \t\t "%( MPIrank, STRcaller, wt_ser)+str(rttddft_common.get_job(True))+" \t\t %s"%(str(datetime.datetime.now())),file=fd1) + fd1.close() + + if( Barrier and MPIsize > 1 ): + comm.Barrier() + wt2=wt1; wt1=time.time(); wt_sync=wt1-wt2 + self.svld_energy('S',fpath) + self._Aind_args=None; + print("#moldyn.save:$%02d:%s DONE %f(ser:%f,sync:%f)\t\t %s"%( MPIrank, STRcaller, + wt_ser+wt_sync, wt_ser,wt_sync, str(datetime.datetime.now()) ),flush=True) + @staticmethod + def load(fpath,eDict=None): + BOHRinANGS = physicalconstants.BOHRinANGS; + types,values=parse_file(fpath) + assert "Rnuc" in values,""; assert "Symbols" in values,""; assert "pbc" in values,"" + strRnuc_au=values["Rnuc"] + if( strRnuc_au.startswith("!") ): + get_comments=[];fnme1=strRnuc_au[1:] + Rnuc_au=svld_aNbuf("L",fnme1,get_comments=get_comments) + Rnuc_au=np.ravel(Rnuc_au);le=len(Rnuc_au);Nat=le//3;assert le==3*Nat,"le=%d"%(le) + Rnuc_ANGS = np.reshape( [ Rnuc_au[k]*BOHRinANGS for k in range(le) ], [Nat,3] ) + fpath_ref=get_comments[0]; + if(fpath_ref[0]=="#"): + fpath_ref=(fpath_ref[1:]).strip() + assert fpath_ref==fpath,"FILE:%s says it belongs to %s %d, not %s %d"%(fnme1,fpath_ref,len(fpath_ref),fpath,len(fpath)) + else: + strbuf=strRnuc_au.split();le=len(strbuf);Nat=le//3;assert le==3*Nat,"le=%d"%(le) + Rnuc_au = [ float(strbuf[k]) for k in range(le) ] + Rnuc_ANGS = np.reshape( [ float(strbuf[k])*BOHRinANGS for k in range(le) ], [Nat,3] ) + Sy= values["Symbols"].split(); assert (len(Sy)==Nat),"" + pbc=eval( values["pbc"] ) + LatticeVectors=None + if( pbc ): + assert "a" in values,""; + LatticeVectors=values["a"] + if( LatticeVectors.startswith("!") ): + get_comments=[] + LatticeVectors= np.ravel( svld_aNbuf("L",LatticeVectors[1:],get_comments=get_comments) ) + else: + if( isinstance(LatticeVectors,str)): + sA=LatticeVectors.split();nA=len(sA) + LatticeVectors=[ float(sA[k]) for k in range(nA) ] + xyzf=make_tempfile(head="tempwks_delete_on_exit",tail=".xyz") + write_xyzf(xyzf,Rnuc_ANGS,Sy,description="temporarily created for Moldyn.load",LatticeVectors=LatticeVectors) + + basis=values["basis"] + retv= Moldyn(pbc=pbc,xyzf=xyzf, basis=basis) + ## print("#Moldyn.load:constructed. load_fromfile...",flush=True) + load_fromfile( retv, fpath, constructors=Moldyn.Constructors__, logfile="Moldyn_loader.log") + print("#Moldyn.load:...load END:Gauge:%s:tdF:"%(retv.gauge_LorV)+str(retv.td_field),flush=True) + dbgng=False + if(dbgng): + print("#Moldyn.load:testing REserialization...",flush=True) + serialize( retv, fpath="Moldyn_load.tmpwks", serializers=Moldyn.Serializers__) + os.system("diff "+fpath+" Moldyn_load.tmpwks") + print("#Moldyn.load:check diff...",flush=True) + ### assert False,"" + if( retv._calc_Aind != 0 ): + dbgng=True ## XXX XXX + if(dbgng): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank();MPIsize=comm.Get_size() + if(MPIsize<2 or MPIrank==0): + fd1=open("Aind_over_c_LOAD.log","w");print(retv._Aind_args,file=fd1);fd1.close() + + E_dev = retv.svld_energy("L",fpath,eDict=eDict) + if(E_dev is not None): + print("#Moldyn.load:deviation:%e"%(E_dev));assert abs(E_dev)<1.0e-6,"" + else: + rttddft_common.Assert(False,"#Moldyn.load:missing _recalc_eng.log file for pscf file:"+fpath,1) + return retv + + def check_matrixShape(self,name,A,nkpt=None,nAO=None,nMO=None): + if nkpt is None: nkpt=self.nkpt + if nAO is None: nAO=self.nAO + if nMO is None: nMO=self.nMO + ### print_00("check_matrixShape:%d %d %d %d"%(nkpt,nAO,nMO,self.nAO)) + Ndim=np.shape(A) + dft=self.get_DFT() + ### print_00("#check_matrixShape:",end="");print_00([nkpt,nAO,nMO,self.nkpt,self.nAO,self.nMO]) + if(name=="MO"): + if( self.spinrestriction == 'U'): + assert ( ( self.pbc and i1eqb( Ndim,[2,nkpt,nAO,nMO]) ) or\ + ( (not self.pbc) and i1eqb( Ndim,[2,nAO,nMO]) ) ),dft+","+name+":"+str(Ndim) + else: + assert ( ( self.pbc and i1eqb( Ndim,[nkpt,nAO,nMO]) ) or\ + ( (not self.pbc) and i1eqb( Ndim,[nAO,nMO]) ) ),dft+","+name+":"+str(Ndim) + elif(name=="eOrbs"): + # ROKS : e(eigenvalue of ROOTHAAN fock matr) e.mo_ea, e.mo_eb + # KROKS: e[k](...) e[k].mo_ea, e[k].mo_eb + if( self.spinrestriction == 'U'): + assert ( ( self.pbc and i1eqb( Ndim,[2,nkpt,nMO]) ) or\ + ( (not self.pbc) and i1eqb( Ndim,[2,nMO]) ) ),dft+","+name+":"+str(Ndim) + else: + assert ( ( self.pbc and i1eqb( Ndim,[nkpt,nMO]) ) or\ + ( (not self.pbc) and i1eqb( Ndim,[nMO]) ) ),dft+","+name+":"+str(Ndim) + elif(name=="DM"): + if( self.spinrestriction != 'R'): + assert ( ( self.pbc and i1eqb( Ndim,[2,nkpt,nAO,nAO]) ) or\ + ( (not self.pbc) and i1eqb( Ndim,[2,nAO,nAO]) ) ),dft+","+name+":"+str(Ndim)+"/"+str([2,nAO,nAO]) + else: + assert ( ( self.pbc and i1eqb( Ndim,[nkpt,nAO,nAO]) ) or\ + ( (not self.pbc) and i1eqb( Ndim,[nAO,nAO]) ) ),dft+","+name+\ + ":"+str(Ndim)+"/"+( str([nkpt,nAO,nAO]) if(self.pbc) else str([nAO,nAO]) ) + elif(name=="Fock"): + ## ROKS Fock.focka, .fockb [nAO][nAO] + ## KROKS Fock.focka, .fockb [nkpt][nAO][nAO] + if( self.spinrestriction == 'U'): + assert ( ( self.pbc and i1eqb( Ndim,[2,nkpt,nAO,nAO]) ) or\ + ( (not self.pbc) and i1eqb( Ndim,[2,nAO,nAO]) ) ),dft+","+name+":"+str(Ndim) + else: + assert ( ( self.pbc and i1eqb( Ndim,[nkpt,nAO,nAO]) ) or\ + ( (not self.pbc) and i1eqb( Ndim,[nAO,nAO]) ) ),dft+","+name+":"+str(Ndim) + + def get_MOvcs(self): + if( self._tempOrbs is None): + if( self._tempFockMat is not None ): + print_00("#get_MOvcs:solving MO from _tempFockMat..."); + self.solve_MO(update=True) + MOvcs=self._tempOrbs + else: + print_00("#get_MOvcs:use canonicalMOs..."); + MOvcs=self._canonicalMOs + else: + MOvcs=self._tempOrbs + return MOvcs + + def print_Fock(self,rttddft,title,FockMat=None,MOvcs=None,Threads=[0]): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if( MPIrank not in Threads ): + return + if FockMat is None:FockMat=self.calc_fock(rttddft) + if MOvcs is None: MOvcs=self.get_MOvcs() + if( MOvcs is None): + print_00("print_Fock:"+title +"!W no MOvcs..");return + nmult_Fock=(2 if(self.spinrestriction=='U')else 1) + nmult_MO =(2 if(self.spinrestriction=='U')else 1) + print_in_MOrep(self.pbc,nmult_Fock,"#print_Fock:"+title,FockMat,MOvcs,nmult_MO) + def print_DMO(self,title,dmat=None,MOvcs=None,Threads=[0]): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if( MPIrank not in Threads ): + return + + if dmat is None: dmat=self.tdDM + if MOvcs is None: MOvcs=self.get_MOvcs() + if (MOvcs is None): + print("print_DMO:"+title +"!W no MOvcs..");return + nmult_DM=(2 if(self.spinrestriction!='R')else 1) + nmult_MO=(2 if(self.spinrestriction=='U')else 1) + print_in_MOrep(self.pbc, nmult_DM,"#print_DMO:"+title,dmat,MOvcs,nmult_MO) + + def print_AO(self,header="",Threads=[0]): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if( MPIrank not in Threads ): + return + + mol_or_cell = self.gen_mol_or_cell(); + print("#print_AO:"+header+":format_basis:",end="");print( format_basis(mol_or_cell.basis) ) + Nsh=len(mol_or_cell._bas) + for ish in range(Nsh): + print("#print_AO:"+header+":_bas_%03d:"%(ish),end="");print(mol_or_cell._bas[ish]) + + def solve_MO(self,rttddft=None,FockMat=None,update=None,comment=None): + if update is None: update=(FockMat is None); ## default: diagonalize _tempFockMat and put it to .. + if FockMat is None: FockMat=self._tempFockMat + info=0 + if( FockMat is None): + print_00("#solve_MO:missing FockMat %r"%(self._tempFockMat is not None)); + return None + Ndim=np.shape(FockMat); + nAO=( self.nAO if(self.nAO is not None) else rttddft.nAO ) + nMO=( self.nMO if(self.nMO is not None) else rttddft.nMO ) + nkpt=( self.nkpt if(self.nkpt is not None) else rttddft.nkpt ) + self.check_matrixShape("Fock",FockMat,nkpt,nAO,nMO) + + nmult_MO=(2 if(self.spinrestriction=='U') else 1) + refMO=(self._tempOrbs if(self._tempOrbs is not None) else self._canonicalMOs) + EA=None;UA=None + for sp in range(nmult_MO): + FM=( FockMat if(nmult_MO==1) else FockMat[sp]) + if(self.pbc): + E=[];U=[] + for kp in range(Ndim[0]): + E1,U1,info = hdiag(FM[kp]) + E.append(E1); U.append(U1); + if( nmult_MO == 1 ): + EA=E;UA=U + else: + if(EA is None): + EA=[];UA=[] + EA.append(E);UA.append(U) + else: + E1,U1,info= hdiag(FM) + if( nmult_MO == 1 ): + EA=E1;UA=U1 + else: + if(EA is None): + EA=[];UA=[] + EA.append(E1);UA.append(U1) + if( update ): + if( (comment is not None) and (rttddft is not None)): + if( not pbc ): + S1e=rttddft.get_ovlp() + for sp in range(nmult_MO): + if( nmult_MO==1 ): + compare_MOs(UA,refMO,S1e,title=comment) + else: + compare_MOs(UA[sp],refMO[sp],S1e,title=comment) + else: + for sp in range(nmult_MO): + refMO_sp=( refMO if(nmult_MO==1) else refMO[sp] ) + UA_sp=( UA if(nmult_MO==1) else UA[sp] ) + kvectors=np.reshape( rttddft.kpts, (-1,3) ) + for kp in range(Ndim[0]): + S1e=rttddft.get_ovlp( rttddft.cell, kvectors[kp]) + compare_MOs(UA_sp[kp],refMO_sp[kp],S1e,title=comment) + self._tempOrbs=np.array(UA);self._tempEngs=np.array(EA) + self.check_matrixShape("MO",UA) + self.check_matrixShape("eOrbs",EA) + return EA,UA,info + + def set_Rnuc(self,Rnew,unit): + fac=1.0 + if( unit=='ANGS' or unit=='A' ): + fac=1.0/physicalconstants.BOHRinANGS + for I in range(self.Nat): + for J in range(3): + self.Rnuc[I][J] = Rnew[I][J] * fac + + # update_Rnuc : updates (generates) rttddft object with specified Rnuc + # (i) partial update (IandJ,coordinate) from md.Rnuc + # (ii) full update to Rnew + # @param update_moldyn: whether or not update md.Rnuc + # if you only temporarily need rttddft(R+dR), leave it False + def update_Rnuc(self, Rnew=None, IandJ=None, coordinate=None, update_moldyn=None, fix_occ=True, + update_canonicalMOs=0,sync=False, R_dbg=None): + assert (update_moldyn is not None),"update_Rnuc:set update_moldyn explicitly" + + if( Rnew is None ): + assert ( (IandJ is not None) and (coordinate is not None) ),"update_Rnuc.000a" + Rnew = np.zeros( [self.Nat,3] ) + for I in range(self.Nat): + for J in range(3): + Rnew[I][J]=self.Rnuc[I][J] + Rnew[ IandJ[0] ][ IandJ[1] ] = coordinate + + if( R_dbg is not None ): + diff= max( abs( np.ravel(Rnew) - np.ravel(R_dbg)) ) + print("#diff:%e"%(diff),Rnew,R_dbg); + assert diff<1.0e-7,"" + + if( update_moldyn ): + self.Rnuc[ IandJ[0] ][ IandJ[1] ] = coordinate + else: + assert ( (IandJ is None) and (coordinate is None) ),"update_Rnuc.000b" + if( update_moldyn ): + for I in range(self.Nat): + for J in range(3): + self.Rnuc[I][J]=Rnew[I][J] + + + logger=self.get_logger(set=True) + + ## here, None means "default" so it perfectly makes sense to pass None to gen_rttddft .. 2021.12.07 + ## ## assert (not self.pbc),"2021.12.06 --- it seems that you are passing nKpoints=None to gen_rttddft.. PLS check the results" + + if( update_canonicalMOs!=0 ): + temp=self.gen_rttddft(mol_or_cell=None,Rnuc=Rnew,unit='B',nKpoints=None,logger=logger) + temp._fix_occ=False + E_gs=temp.calc_gs() + + Fock=None + if( update_canonicalMOs & 4 ): + self._GSfockMat = arrayclone( temp.get_fock() ) + Fock=self._GSfockMat + if( update_canonicalMOs & 2): + self._canonicalMOs=arrayclone( temp.mo_coeff ) + self._cMOs_Rnuc = arrayclone( Rnew ) + if( update_canonicalMOs & 1): + if( Fock is None ): + Fock=temp.get_fock() + if( self.spinrestriction=='U'): + self._canonicalEorbs=\ + np.array( [ calc_eorbs(temp.mo_coeff[0], Fock[0]),calc_eorbs(temp.mo_coeff[1], Fock[1]) ] ) + elif( self.spinrestriction=='R'): + self._canonicalEorbs=calc_eorbs(temp.mo_coeff, Fock) + else: + assert False,"ROKS?" + + ret=self.gen_rttddft(mol_or_cell=None,Rnuc=Rnew,unit='B',nKpoints=None,logger=logger) # None in order to apply default + print("#gen_rttddft:",np.ravel(Rnew)) + if( fix_occ ): + ret.set_mo_occ(self.mo_occ,fix_occ,clone=True) + + if( sync ): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if(MPIsize > 1 ): + R_loc=arrayclone( self.Rnuc ) + comm.Bcast(self.Rnuc) + diff=max( np.ravel(R_loc) - np.ravel(self.Rnuc) ) + if( diff > 1e-7 ): + print("#Sync:$%02d:non-trivial sync Rnuc:%e"%(diff)+str(R_loc)+">"+str(self.Rnuc)) + + rttddft_common.Set_Rnuc( self.Rnuc, step=self.step, time_AU=self.time_AU, Logging=range(0,MPIsize) ) + rttddft_common.Check_cellRnuc( ret.mol, "Moldyn.update_Rnuc") + if( self.pbc ): + if( ret.with_df is not None): + if( hasattr( ret.with_df, "cell" ) ): + rttddft_common.Check_cellRnuc( ret.with_df.cell, "Moldyn.update_Rnuc:df.cell") + + return ret + + def set_logger(self,logger=None,filename=None,replace=True,rttddft=None): + if( not replace ): + if( self.logger is not None): + print_00("#moldyn already has a logger"); + if( rttddft is not None): + return rttddft.set_logger(logger=logger, filename=filename, replace=replace); + return False + if( logger is None ): + assert (filename is not None),"" + self.logger = Logger(filename) + print_00("#Moldyn.set_logger:creates:"+str(self.logger)) + else: + self.logger = logger + print_00("#Moldyn.set_logger:sets:"+str(self.logger)) + if( rttddft is not None): + retv = rttddft.set_logger(logger=logger, filename=filename, replace=replace); +# os.system("fopen " + self.logger.filepath); + os.system("ls -ltrh "+self.logger.filepath); + return True + + def get_logger(self,set=False): + if( (self.logger is None) and set ): + self.set_logger(filename="moldyn_dbg.log"); + return self.logger; + + def set_time_AU(self,time,step=None,rttddft=None): + self.time_AU=time + if( step is not None ): + self.step = step + if( rttddft is not None): + rttddft._time_AU = time + rttddft._step = step + def set_step(self,step,rttddft=None): + self.step = step + if( rttddft is not None): + rttddft._step = step + + def export_DM(self,fpath,dm=None,comment=None): + if(dm is None): + dm=self.tdDM + svld_aNbuf('S',fpath,buf=dm,comment=comment) + + def read_DM(self,fpath,update_self=False,get_comments=None): + dm=svld_aNbuf('L',fpath,get_comments=get_comments) + return dm + + # Projects current tdMO onto self._canonicalMOs to get \langle canonical MO_{\ell} | tdMO_j \rangle + # results are (i) printed out on fpath + # (ii) partly exported into dict + def calc_MOprojection( self, rttddft, header,fpath=None,mo_coeff=None,kpts=None,append=True,dict=None): + fd=sys.stdout + # assert False,"MOprojection" + if( self._canonicalMOs is None ): + assert False,"please set _canonicalMOs .." + if mo_coeff is None: mo_coeff = self.tdMO + pbc=self.pbc + kvectors = (None if (not pbc) else np.reshape( rttddft.kpts, (-1,3))) + nkpt=(1 if(not pbc) else self.nkpt ) + nAO =self.nAO + psit_jmoRH=np.zeros( [nAO],dtype=np.complex128) + excitedstate_populations=None; + nmult_MO=(2 if(self.spinrestriction=='U') else 1) + for sp in range(nmult_MO): + header_spl = "" if(nmult_MO==1) else ("_alpha" if(sp==0) else "_beta") + ### U : FockMat is two-fold Fa,Fb + ### O : + Fock_sp1=None; FM1=None + if( self._GSfockMat is not None ): + Fock_sp1= ( self._GSfockMat if( self.spinrestriction != 'U' ) else self._GSfockMat[sp] ) + + for kp in range(nkpt): + if( not pbc ): + S1e = rttddft.get_ovlp() + else: + S1e = rttddft.get_ovlp(rttddft.cell,kvectors[kp]) + + if( kpts is not None ): + if( not ( kp in kpts ) ): + continue + if( Fock_sp1 is not None ): + FM1=( Fock_sp1 if(not pbc) else Fock_sp1[kp]) + + if( self.spinrestriction == 'O'): + eorbREF =(self._canonicalEorbs if(not pbc) else self._canonicalEorbs[kp]) + ### if( hasattr( eorbREF, ('mo_ea' if(sp==0) else 'mo_eb'),None) is not None ): + ### eorbREF = ( eorbREF.mo_ea if(sp==0) else eorbREF.mo_eb ) + elif( self.spinrestriction == 'U'): + eorbREF =(self._canonicalEorbs[sp] if(not pbc) else self._canonicalEorbs[sp][kp]) + else: + eorbREF =(self._canonicalEorbs if(not pbc) else self._canonicalEorbs[kp]) + + if( self.spinrestriction == 'U'): + cofsRH = (mo_coeff[sp] if(not pbc) else mo_coeff[sp][kp]) + cofsLH = (self._canonicalMOs[sp] if(not pbc) else self._canonicalMOs[sp][kp]) + else: + cofsRH = (mo_coeff if(not pbc) else mo_coeff[kp]) + cofsLH = (self._canonicalMOs if(not pbc) else self._canonicalMOs[kp]) + + assert ( i1eqb(np.shape(cofsRH),[self.nAO, self.nMO]) ),str(np.shape(cofsRH))+"/"+str([self.nAO, self.nMO]) + assert ( i1eqb(np.shape(cofsLH),[self.nAO, self.nMO]) ),str(np.shape(cofsLH))+"/"+str([self.nAO, self.nMO]) + + nMOlh=len(cofsLH[0]); nMOrh=len(cofsRH) + + if( excitedstate_populations is None ): + excitedstate_populations =( [] if(not pbc) else [ [] for i in range(self.nkpt) ]) if(self.spinrestriction == 'R') else \ + ( [ [], [] ] if(not pbc) else [ [ [] for i in range(self.nkpt) ],\ + [ [] for i in range(self.nkpt) ] ] ) + eorbs = ( [] if(not pbc) else [ [] for i in range(self.nkpt) ]) if( self.spinrestriction == 'R') else \ + ( [ [], [] ] if(not pbc) else [ [ [] for i in range(self.nkpt) ],\ + [ [] for i in range(self.nkpt) ] ] ) + Xpop1 =( excitedstate_populations if( not pbc) else excitedstate_populations[kp]) if(self.spinrestriction == 'R') else \ + ( excitedstate_populations[sp] if( not pbc) else excitedstate_populations[sp][kp]) + eOrbs1 = ( eorbs if( not pbc ) else eorbs[kp] ) if(self.spinrestriction == 'R') else \ + ( eorbs[sp] if( not pbc ) else eorbs[sp][kp] ) + + pop=np.zeros([nMOrh,nMOlh]) + + for jmoRH in range(nMOrh): + if( fpath is not None ): + if( nkpt>1 ): + fd=futils.fopen_00(fpath.replace(".dat","")+"_%d.%d.dat"%(kp,jmoRH),("a" if append else "w") )#OK + else: + fd=futils.fopen_00(fpath.replace(".dat","")+"_%d.dat"%(jmoRH),("a" if append else "w"));#OK + else: + fd=sys.stdout + ## get single tdMO ----------- + for k in range(nAO): + psit_jmoRH[k]=cofsRH[k][jmoRH] + + for kLH in range(nMOlh): + cdum=np.vdot( cofsLH[:,kLH], np.matmul(S1e,psit_jmoRH) ) + pop[jmoRH][kLH]=cdum.real**2 + cdum.imag**2 + + eorb=0 + if( FM1 is not None ): + eorb=np.vdot( psit_jmoRH, np.matmul( FM1, psit_jmoRH)).real + if( self.spinrestriction == 'O' and hasattr(FM1,'focka')): + ea=np.vdot( psit_jmoRH, np.matmul( FM1.focka, psit_jmoRH)).real + eb=np.vdot( psit_jmoRH, np.matmul( FM1.fockb, psit_jmoRH)).real + eorb = lib.tag_array(eorb, mo_ea=ea, mo_eb=eb) + Xpop1.append( 1.0-pop[jmoRH][jmoRH] ) + eOrbs1.append( eorb ) + if( self.spinrestriction == 'O' and hasattr(FM1,'focka') ): + print_00("%s %f %f %f %f %f "%(header+header_spl,eorbREF[jmoRH],eorb,ea,eb,pop[jmoRH][jmoRH]) + +d1toa(pop[jmoRH]),file=fd) + else: + print_00("%s %f %f %f "%(header+header_spl,eorbREF[jmoRH],eorb,pop[jmoRH][jmoRH])+d1toa(pop[jmoRH]),file=fd) + if( fpath is not None ): + futils.fclose_00(fd) + if( dict is not None ): + if( "excitedstate_populations" in dict ): + dict[ "excitedstate_populations" ] = excitedstate_populations + if( "eorbs" in dict ): + dict[ "eorbs" ] = eorbs + print_00("calc_MOprojection done");## assert False,"projection"+fpath + + def calc_MOprojection01( self, rttddft, header,FileName,MO_Coeff=None,kpts=None,append=True): + fd=sys.stdout + if( self._canonicalMOs is None ): + assert False,"please set _canonicalMOs .." + if MO_Coeff is None: MO_Coeff = self.tdMO + pbc=self.pbc + kvectors = (None if (not pbc) else np.reshape( rttddft.kpts, (-1,3))) + nkpt=(1 if(not pbc) else self.nkpt ) + nAO =self.nAO; NcanMO=None; NtdMO=None + nmult_MO=(2 if(self.spinrestriction=='U') else 1) + for sp in range(nmult_MO): + mo_coef1=( MO_Coeff if(nmult_MO==1) else MO_Coeff[sp] ) + canonicalMO1=( self._canonicalMOs if(nmult_MO==1) else self._canonicalMOs[sp]) + S1e=(None if(pbc) else rttddft.get_ovlp()) + filename1 = FileName + ("" if(nmult_MO==1) else "_s%d"%(sp)) + for kp in range(nkpt): + fnme= filename1 + ("" if(not pbc) else "_k%d"%(kp)) + fdP= open_00(fnme+"_MOphases.dat",("a" if(append) else "w")) + tdMO =(mo_coef1 if(not pbc) else mo_coef1[kp]); + canMO=(canonicalMO1 if(not pbc) else canonicalMO1[kp]); #[nAO][nMO] + + Ndim_tdMO=np.shape(tdMO); NtdMO=Ndim_tdMO[1]; LdAO=Ndim_tdMO[0]; + Ndim_canMO=np.shape(canMO); NcanMO=Ndim_canMO[1]; assert LdAO==Ndim_canMO[0],"" + Pstring="" + if(pbc): + S1e = rttddft.get_ovlp(rttddft.cell,kvectors[kp]) + PI=3.1415926535897932384626433832795 + for itdMO in range(NtdMO): + fdA= open_00(fnme+"_MOampd%03d.dat"%(itdMO),("a" if(append) else "w")) + arr =[ np.vdot( canMO[:,jcMO],np.matmul( S1e, tdMO[:,itdMO])) for jcMO in range(NcanMO) ] + + string="" + for jcMO in range(NcanMO): + string+=(' '*3) + "%14.6e %12.6f"%( abs(arr[jcMO]), math.atan2( arr[jcMO].imag, arr[jcMO].real )/PI) + print_00(header+string,file=fdA);close_00(fdA);### fdA.close() + jcMaxLoc =z1maxloc(arr) + Pstring+= "%14.6e %12.6f"%( abs(arr[jcMaxLoc]), math.atan2( arr[jcMaxLoc].imag, arr[jcMaxLoc].real )/PI) + print_00(header+Pstring,file=fdP) + close_00(fdP);### fdP.close() + if( not append ): + gnu="calc_MOprojection01";os.system("gnuf.sh "+gnu);gnuf=gnu+".plt" + fdg=open_00(gnuf,"a") + for sp in range(nmult_MO): + filename1 = FileName + ("" if(nmult_MO==1) else "_s%d"%(sp)) + for kp in range(nkpt): + print_00('set title "sp=%d kp=%d'%(sp,kp)+'"',file=fdg) + fnme= filename1 + ("" if(not pbc) else "_k%d"%(kp)) + fnmP= fnme+"_MOphases.dat";PLOT="plot ";sty=1; + for itdMO in range(NtdMO): + ENDL=("" if(itdMO+1==NtdMO) else ",\\" ) + print_00(PLOT+'"'+fnmP+'" using 3:%d with lines ls %d'%(5+2*itdMO,sty)+ENDL,file=fdg);sty+=1;PLOT="" + for itdMO in range(NtdMO): + fnmA=fnme+"_MOampd%03d.dat"%(itdMO) + print_00('set title "sp=%d kp=%d MO%03d'%(sp,kp,itdMO)+'"',file=fdg) + for jcMO in range(NcanMO): + ENDL=("" if(itdMO+1==NtdMO) else ",\\" ) + print_00(PLOT+'"'+fnmA+'" using 3:%d with lines ls %d'%(4+2*jcMO,sty)+ENDL,file=fdg);sty+=1;PLOT="" + close_00(fdg);### fdg.close() + + def transform_tdMO(self,rttddft, ForB, check_norm=True,sqrdevtol=1.0e-6,title="",logger=None): + # Ssqrt * tdMO + if logger is None: logger=self.get_logger(True) + FWD = (ForB=='F') + Src= ( self.tdMO if(FWD) else self._orth_MO ) + rttddft.update_Sinv() + + nkpt=self.nkpt;nAO=self.nAO;nMO=self.nMO; assert (nAO is not None),"" + nmult_WF=(2 if(self.spinrestriction=='U') else 1) + for sp in range(nmult_WF): + srcWF=( Src if(nmult_WF==1) else Src[sp]) + for kp in range(nkpt): + tgt=srcWF; Matr=(rttddft._Ssqrt if(FWD) else rttddft._Sinvrt ) + if( self.pbc ): + tgt=srcWF[kp];Matr=(rttddft._Ssqrt[kp] if(FWD) else rttddft._Sinvrt[kp] ) + + tgt = np.matmul( Matr, tgt) ## Ssqrt[nAO][nAO] * MO_k[nAO][nMO] + if( check_norm ): + check_wfNorms( self.nkpt, self.nAO, self.nMO, rttddft, + self.pbc, self.spinrestriction, Src, AOrep=(not FWD), sqrdevtol_FIX=1.0e-6, title=title, logger=logger) + if( FWD ): + self._orth_MO = Src + self.tdMO = None + else: + self.tdMO = Src + self._orth_MO = None + + def calc_MOpopul(self,Rnuc,target_MOs=None,deviations=None): + if( deviations is not None ): + deviations["N_overpop"]=0 + deviations["Ne"]=0 + deviations["max_overpop"]=0 + if target_MOs is None: target_MOs=self.tdMO + dev=aNmaxdiff(Rnuc,self.Rnuc);TINY=1.0e-7 + + rttddft=self.gen_rttddft( Rnuc=Rnuc, unit='B') + CanonicalMOsAL=None + + nMO=self.nMO; + if( (self._canonicalMOs is not None) and (self._cMOs_Rnuc is not None) and nMO>0 ): + Rdev=max( np.ravel(Rnuc)- np.ravel(self._cMOs_Rnuc) ) + if( Rdev < 1e-7 ): + CanonicalMOsAL=self._canonicalMOs + else: + Egnd=rttddft.calc_gs() + CanonicalMOsAL=rttddft.mo_coeff + rttddft.update_nOrbs(); nMO=rttddft.nMO + if( self.nMO != nMO ): + assert self.nMO<=0,"%d / %d"%(nMO,self.nMO) + print("#Moldyn.nMO set:%d"%(nMO));self.nMO=nMO + assert nMO>0,"" + + kvectors=( None if(not self.pbc) else np.reshape(rttddft.kpts, (-1,3))) + MO_Occ=self.mo_occ + Ne=sum( np.ravel(MO_Occ) ) + ### rttddft.update_nOrbs() + + nkpt=(1 if(not self.pbc) else rttddft.nkpt) + nmult_MO=(2 if(self.spinrestriction=='U') else 1) + Ret=[] + S1e=( rttddft.get_ovlp() if(not self.pbc) else None) + N_overpop=0;max_overpop=-1 + for sp in range(nmult_MO): + canonicalMOs = (CanonicalMOsAL if(nmult_MO==1) else CanonicalMOsAL[sp]) + tgtMOs = (target_MOs if(nmult_MO==1) else target_MOs[sp]) + OCC = (MO_Occ[sp] if(self.spinrestriction=='U') else MO_Occ) + ret_s=[] + for kp in range(nkpt): + if( self.pbc ): + print(nkpt,len(kvectors),kp) + S1e=rttddft.get_ovlp(rttddft.cell,kvectors[kp]) + cMOs= (canonicalMOs if(not self.pbc) else canonicalMOs[kp]) + tMOs= (tgtMOs if(not self.pbc) else tgtMOs[kp]) + Occ = (OCC if(not self.pbc) else OCC[kp]) + ## both are nAO * nMO matrices + pop=np.zeros([nMO,nMO]) + for Iorb in range(nMO): + tmo=tMOs[:,Iorb] + wgsum=0.0 + Sxt=np.matmul(S1e,tmo) + for jorb in range(nMO): + cof=np.vdot(cMOs[:,jorb],Sxt) + wg =cof.real**2 + cof.imag**2 + pop[Iorb][jorb]=wg*Occ[Iorb]; wgsum+=wg + if(abs(wgsum-1)>1.0e-6): + print_00("Wgsum %f deviates from unity"%(wgsum)); + assert abs(wgsum-1)<0.1,"" + + popsum=np.zeros([nMO]) + for jorb in range(nMO): + popsum[jorb]=0 + for Iorb in range(nMO): + popsum[jorb]+=pop[Iorb][jorb] + if(popsum[jorb]>1.0): + N_overpop=N_overpop+1 + max_overpop=max(max_overpop,(popsum[jorb]-1.0)) + + if(not self.pbc and nmult_MO==1 ): + if( deviations is not None ): + deviations["Ne"]=abs(popsum-Ne); deviations["N_overpop"]=N_overpop + deviations["max_overpop"]=max_overpop + return pop + else: + if( not self.pbc ): + Ret.append(pop) ### non-pbc && nmult==2 + else: + ret_s.append(pop) ## pbc + if(self.pbc and nmult_MO==1 ): + if( deviations is not None ): + deviations["Ne"]=abs(popsum-Ne); deviations["N_overpop"]=N_overpop + deviations["max_overpop"]=max_overpop + return ret_s ### pbc && nmult==1 + else: + if(self.pbc): + Ret.append(ret_s) ### pbc && nmult==2 + popsum=sum(np.ravel(Ret)) + if( deviations is not None ): + deviations["Ne"]=abs(popsum-Ne) + deviations["N_overpop"]=N_overpop + deviations["max_overpop"]=max_overpop + print_00("#calc_MOpopul:%f/%f"%(popsum,Ne));assert abs(popsum-Ne)<0.1,"" + return Ret + + def print_MOpopul(self,filename,header="",append=False,Rnuc=None,target_MOs=None,deviations=None): + if Rnuc is None:Rnuc=self.Rnuc + if target_MOs is None:target_MOs=self.tdMO + POP=self.calc_MOpopul(Rnuc=Rnuc,target_MOs=target_MOs,deviations=deviations) + nkpt=(1 if(not self.pbc) else self.nkpt) + nMO=self.nMO + nmult_MO=(2 if(self.spinrestriction=='U') else 1) + for sp in range(nmult_MO): + + Pop=POP if(nmult_MO==1) else POP[sp] + for kp in range(nkpt): + fpath=modify_filename( filename,self.pbc, nmult_MO,sp,kp) + #modify_filename( org,pbc,nmult,spin,kpt) + pop=Pop if (not self.pbc) else Pop[kp] + arr=[] + for Iorb in range(nMO): + pop_I=0.0 + for tdo in range(nMO): + ### print_00("%d %d /"%(tdo,Iorb)+str(np.shape(pop))) + pop_I+=pop[tdo][Iorb] + arr.append(pop_I) + fd=futils.fopen_00(fpath,("a" if(append) else "w")) ## OK + if(not append): + hlen=len(header.split()) + print_00("#--header:%d-- %d:MO_pop ..."%(hlen,hlen+1),file=fd) + print_00(header + d1toa(arr),file=fd) + futils.fclose_00(fd) + + def normalize_MOcofs(self,rttddft,MO_Coeffs=None,update_self=True,devsum_TOL=1.0e-7, + ofddev_TOL=1.0e-7,dagdev_TOL=1.0e-7,verbose=0,dict=None): + if MO_Coeffs is None: MO_Coeffs=self.tdMO + nmult_MO=(2 if(self.spinrestriction=='U') else 1) + pbc = self.pbc + kvectors = (None if (not pbc) else np.reshape( rttddft.kpts, (-1,3))) + nkpt =(1 if(not pbc) else self.nkpt) + S1e = ( rttddft.get_ovlp() if(not pbc) else None) + Nfix=0 + fixed_MO_Coeffs=(None if(nmult_MO==1 and (not pbc)) else (\ + [] if(nmult_MO==1 and pbc) else (\ + [] if(nmult_MO==2 and (not pbc)) else (\ + [ [], [] ] )))) + ## 20230925: normalize_MOcofs_log=BufferedWriter01("normalize_MOcofs.log",Append=True) + devsum_max=-1;dagdev_max=-1;ofddev_max=-1 + + for sp in range(nmult_MO): + MOCOEFS=( MO_Coeffs if(nmult_MO==1) else MO_Coeffs[sp]) + for kp in range(nkpt): + if( pbc ): + S1e=rttddft.get_ovlp( rttddft.cell, kvectors[kp]) + mocoefs=( MOCOEFS if(not pbc) else MOCOEFS[kp]) + CxSxC=np.matmul( np.matrix.getH( mocoefs ), np.matmul(S1e, mocoefs) ) + devsum,dagdev,ofddev=deviation_from_unitmatrix( CxSxC ) + devsum_max=max(devsum_max,devsum) + ofddev_max=max(ofddev_max,ofddev) + dagdev_max=max(dagdev_max,dagdev) + + dbgng_MOcofs=True + + fixed = mocoefs; isMOfixedHere=False + if( devsum >= devsum_TOL or ofddev >= ofddev_TOL or dagdev>=dagdev_TOL ): + # 20230925: normalize_MOcofs_log.write("#Overlap matrix deviates unity:%e %e %e at R_nuc:"%(\ + # 20230925: devsum,dagdev,ofddev)+str(self.Rnuc) ) + print_00("#Overlap matrix deviates unity:%e %e %e"%(devsum,dagdev,ofddev)) + invSSqrt= get_Sinvsqrt(CxSxC) + fixed = np.matmul( mocoefs,invSSqrt ) + Nfix+=1; isMOfixedHere=True + if( not pbc ): + if( nmult_MO==1 ): + fixed_MO_Coeffs=fixed + else: + fixed_MO_Coeffs.append( fixed ) + else: + if( nmult_MO==1 ): + fixed_MO_Coeffs.append( fixed ) + else: + fixed_MO_Coeffs[sp].append( fixed ) + + if( isMOfixedHere and dbgng_MOcofs ): + CxSxC_1=np.matmul( np.matrix.getH( fixed ), np.matmul(S1e, fixed) ) + devsum_1,dagdev_1,ofddev_1=deviation_from_unitmatrix( CxSxC_1 ) + ## 20230925: normalize_MOcofs_log.write("#Overlap matrix fixed:%e %e %e at R_nuc:"%(\ + ## 20230925: devsum_1,dagdev_1,ofddev_1)+str(self.Rnuc) ) + print_00("#Overlap matrix fixed:%e %e %e at R_nuc:"%(\ + devsum_1,dagdev_1,ofddev_1)+str(self.Rnuc) ) + assert devsum_11 or (verbose>0 and Nfix>0) ): + fd=futils.fopen_00("normalize_MOcofs.log","a") ## OK + print_00("%f %d: %e %e %e"%( self.time_AU*physicalconstants.aut_in_femtosec,Nfix,\ + devsum_max,dagdev_max,ofddev_max),file=fd) + futils.fclose_00(fd) + if( Nfix == 0 ): + print_00("#normalize_MOcofs:%f nofix: %e %e %e"%( self.time_AU*physicalconstants.aut_in_femtosec,\ + devsum_max,dagdev_max,ofddev_max)) + if(update_self): + self.check_matrixShape( "MO",fixed_MO_Coeffs ) + self.tdMO = np.array( fixed_MO_Coeffs ) + ## normalize_MOcofs_log.flush_ifnecs() + return np.array( fixed_MO_Coeffs ) + + def get_fock(self,rttddft,h1e,dm,time_AU,update_self=True): + vhf= rttddft.get_veff(rttddft.cell) + fock=rttddft.get_fock(h1e=h1e,dm=dm,vhf=vhf) + if(update_self): + self.vhf_last=vhf + self.Fock_last=fock + self.tmAU_Fock_last=time_AU + return fock + + ## Calculates MOpopulations PBC not + ## UHF : [sp][nkpt][nMO] [sp][nMO] + ## else: [nkpt][nMO] [nMO] + def calc_MOpopulations(self,rttddft, target_MOs=None, reference_MOs=None, MO_occ=None): + + if(target_MOs is None): target_MOs=self.tdMO; + if(reference_MOs is None): reference_MOs = self._canonicalMOs + if(MO_occ is None): MO_occ=self.mo_occ + nmult_MO=(2 if(self.spinrestriction=='U') else 1) + nMO=( self.nMO if(self.nMO is not None) else rttddft.nMO ) + nkpt=(1 if(not self.pbc) else self.nkpt) + kvectors=(None if(not self.pbc) else np.reshape( rttddft.kpts, (-1,3) )) + + dbgng=False;check_MOovlps=True + + N_elec=get_Nele(rttddft) + eps=1.0e-20 + S1e=(None if(self.pbc) else rttddft.get_ovlp()) + Ret=[] + for sp in range(nmult_MO): + targetMOs = ( target_MOs if(nmult_MO==1) else target_MOs[sp] ) + referenceMOs = ( reference_MOs if(nmult_MO==1) else reference_MOs[sp] ) + MOocc = ( MO_occ if(nmult_MO==1) else MO_occ[sp] ) + Nele = ( N_elec if(nmult_MO==1) else N_elec[sp] ) + Ret_sp=[] + popsum=0.0 + + for kp in range(nkpt): + pop=np.zeros([nMO]) + tgtMOs = ( targetMOs if(not self.pbc) else targetMOs[kp]) + refMOs = ( referenceMOs if(not self.pbc) else referenceMOs[kp]) + Occ = ( MOocc if(not self.pbc) else MOocc[kp] ) + if( self.pbc ): + S1e=rttddft.get_ovlp( rttddft.cell, kvectors[kp]) + + if(dbgng): + fd1=open("refMO_%02d.dat"%(kp),"a") + print("#%f"%(self.time_AU),file=fd1) + for nu in range(nMO): + string="" + for el in range(nMO): + string+="%12.6f %12.6f "%( refMOs[el][nu].real,refMOs[el][nu].imag) + print(string,file=fd1); + print("\n\n\n",file=fd1) + fd1.close() + + ovlp=np.zeros([nMO,nMO],dtype=np.complex128) + for el in range(nMO): + for nu in range(nMO): + ovlp[el][nu]=np.vdot( refMOs[:,el], np.matmul( S1e, tgtMOs[:,nu] ) ) + + if(check_MOovlps): + AUinFS=0.02418884326198665673981200055933 + fd1=open( rttddft_common.getjob(True)+"_MOovlps.log","a") + for nu in range(nMO): + string=""; + for el in range(nMO): + cdum=ovlp[el][nu];ampd=abs(cdum);arg=np.arctan2(cdum.imag,cdum.real) + string+=" %12.6f %10.4f "%(ampd,arg) +### string+="%12.6f "%(ovlp[el][nu].real) + print("#tdMO_%04d: %14.4f "%(nu,self.time_AU*AUinFS)+string,file=fd1) + fd1.close() + + for el in range(nMO): + cum=0.0 + for nu in range(nMO): + if( Occ[nu] 1.0e-7 ): + strwarn="popsum:%16.8f / %16.8f:"%(popsum,Nele)+str(pop) + rttddft_common.Printout_warning("popsum",strwarn) + assert dev<1.0e-5,""+strwarn + + if( nmult_MO == 1 ): + Ret=Ret_sp + else: + Ret.append( Ret_sp ) + Avg=None + if( (nmult_MO == 1) and (not self.pbc) ): + Avg=Ret + else: + Avg=np.zeros([nMO]) + for sp in range(nmult_MO): + Pop=(Ret if(nmult_MO==1) else Ret[sp]) + for kp in range(nkpt): + pop=(Pop if(not self.pbc) else Pop[kp]) + for el in range(nMO): + Avg[el]+=pop[el] + if( self.pbc ): + for el in range(nMO): + Avg[el]/=float(nkpt) + + return Ret,Avg + + def save_tempFockMat(self,src,t2,calc_eigvcs=False): + self.check_matrixShape("Fock",src) + Ndim=np.shape(src) + if( self._tempFockMat is None ): + self._tempFockMat = arrayclone( src ) + self._t2=t2; + else: + if( len(Ndim)==2 ): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + self._tempFockMat[I][J] = src[I][J] + elif( len(Ndim)==3 ): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + self._tempFockMat[I][J][K] = src[I][J][K] + elif( len(Ndim)==4 ): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + for L in range(Ndim[3]): + self._tempFockMat[I][J][K][L] = src[I][J][K][L] + else: + assert False,"" + if( calc_eigvcs ): + self.solve_MO(update=True) + else: + self._tempOrbs=None;self._tempEorbs=None + + def delete_Fock_last(self,description="",flag=7): + ### self._dbg_update_FockLast("delete_Fock_last:"+str(description)) + if( flag & 1 !=0 ): + self.Fock_last=None; self.tmAU_Fock_last=None + if( flag & 2 !=0 ): + self.vhf_last=None; self.tmAU_vhf_last=None + if( flag & 4 !=0 ): + self.hcore_last=None; self.tmAU_hcore_last=None + def get_DFT(self): + ret=("K" if(self.pbc) else "") + if( self.spinrestriction == 'U'): + ret+="UKS"; return ret + elif( self.spinrestriction == 'O'): + ret+="ROKS"; return ret + elif( self.spinrestriction == 'R'): + ret+="RKS"; return ret + else: + assert False,"wrong DFT:"+self.spinrestriction + + + #> Matrix routines --- + #> calc_xxx(self, rttddft, MATRICES ) + #> rttddft.get_xxx( matrices = (i) INPUT_MATRICES (ii) time-dpd matrices/wfn self.tdDM etc.) + def calc_hcore(self,rttddft,time_AU=None, dm1_kOR1=None, tmAU_dmat=None, Dict_hc=None): + if time_AU is None:time_AU=self.time_AU + if( dm1_kOR1 is None ): + dm1_kOR1 = self.tdDM; tmAU_dmat=self.time_AU + return rttddft.get_hcore(tm_AU = time_AU, dm_kOR1=dm1_kOR1, tmAU_dmat=tmAU_dmat, Dict_hc=Dict_hc) + + def calc_veff(self,rttddft,dm=None,ovrd_tdDM=None): + if dm is None: dm=self.calc_tdDM(rttddft,ovrd=(True if(ovrd_tdDM is None) else ovrd_tdDM) ) + + return rttddft.get_veff(dm=dm) + + def calc_fock(self,rttddft,h1e=None,vhf=None,dm=None,time_AU=None,ovrd_tdDM=None): + if time_AU is None:time_AU=self.time_AU + if h1e is None: h1e = self.calc_hcore(rttddft,time_AU=time_AU) + if vhf is None: vhf = self.calc_veff(rttddft,dm=dm,ovrd_tdDM=ovrd_tdDM) + if dm is None: dm=self.tdDM + if( self.spinrestriction == 'O'): + f=rttddft.get_fock( h1e=h1e,vhf=vhf,dm=dm) + else: + f = h1e + vhf + return f + + + def calc_tdDM(self,rttddft,ovrd=True): + if( not self.pbc ): + # hf.py#make_rdm1 ... this creates complex dm + ret=rttddft.make_rdm1( mo_coeff=self.tdMO, mo_occ=self.mo_occ ) + ### print_00("calc_tdDM:"+str(np.shape(ret))) + if( ovrd ): + Ndim=np.shape(ret) + if( self.spinrestriction == 'R'): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + self.tdDM[I][J]=ret[I][J] + else: + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + self.tdDM[I][J][K]=ret[I][J][K] + else: + # khf.py + ret=rttddft.make_rdm1( mo_coeff_kpts=self.tdMO, mo_occ_kpts=self.mo_occ ) + assert (ret is not None),"ret is None" + if( self.tdDM is None ): + self.tdDM=np.zeros( np.shape(ret), dtype=np.complex128 ) + print_00("#allocating tdDM:",end="");print_00( np.shape(ret) ) + if( ovrd ): + Ndim=np.shape(ret);### print_00("#ret:",end="");print_00(Ndim) + ### print_00("#tdDM:",end="");print_00(np.shape(self.tdDM)) + if( self.spinrestriction == 'R'): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + self.tdDM[I][J][K]=ret[I][J][K] + else: + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + for L in range(Ndim[3]): + self.tdDM[I][J][K][L]=ret[I][J][K][L] + self.check_matrixShape("DM",self.tdDM) + return self.tdDM + + def calc_gs(self,rttddft,save_canonicalMOs=7,abort_if_failed=None,dm0=None,errbuf=None): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); + calc_Aind_save = self._calc_Aind + assert (rttddft._calc_Aind == calc_Aind_save),"" + self._calc_Aind=0; + rttddft._calc_Aind=0; + + if( errbuf is not None ): + errbuf.clear() + + if( abort_if_failed is None ): + abort_if_failed = (errbuf is None) ## abort if errbuf is None + + verbose=True + if(verbose): + print_00("#Moldyn:calc_gs:%d"%(rttddft._calc_Aind),flush=True) + wt0=time.time() + self.Egnd=rttddft.calc_gs(dm0=dm0) + wt1=time.time() + Moldyn_static_.N_calc_gs_+=1 + if( MPIrank==0 and ( (Moldyn_static_.N_calc_gs_ == 1) or (Moldyn_static_.N_calc_gs_ == 5) or \ + (Moldyn_static_.N_calc_gs_ == 20) or (Moldyn_static_.N_calc_gs_%200==0) ) ): + rttddft_common.Print_SCFresults(fpath= rttddft_common.get_job(True) +"_SCF.log",Append=False) + if(verbose): + print_00("#Moldyn:calc_gs done",flush=True) + + print_eorbs=False + if( print_eorbs ): + prteorbs01(True,self,rttddft,description="calc_gs") + fockmat=get_FockMat(self,rttddft) + filenames=print_TDeorbs( self.spinrestriction, rttddft.mo_coeff, rttddft, self.pbc, rttddft.mo_coeff, + fockmat, rttddft.mo_occ, job=(rttddft_common.get_job(True))+"_GS", Append=False,step=0,tm_au=self.time_AU) + + SCFresult=rttddft_common.Get_SCFresult() + if( SCFresult is not None ): + if( ('cvgd' in SCFresult) and (SCFresult['cvgd'] is not None) ): + SCF_cvgd = SCFresult['cvgd'] + if( errbuf is not None ): + errbuf.append(-1) + + if( not SCFresult['cvgd'] ): + print_00("#!W SCF did not converge",warning=(-1 if(abort_if_failed) else 1)); + if( abort_if_failed ): + assert False,"SCF failed" + return None + + rttddft.update_nOrbs() + self.nkpt=( Moldyn.nkpt_for_non_pbc_ if(not self.pbc) else rttddft.nkpt) + n_call=rttddft_common.Countup('calc_gs') + if( self.pbc ): + fdlog=open_00("calc_gs.log","a") + mesh=rttddft.cell.mesh + meshsz=i1prod(mesh) + strlog=" %4d %5d %12d %3d %3d %3d %16.8f %14.4f"%(\ + n_call, rttddft.nAO, i1prod(mesh),mesh[0],mesh[1],mesh[2], self.Egnd, wt1-wt0) + strlog+=" "+str(rttddft_common.get_job(True)) + legend="#%4s %5s %12s %3s %3s %3s %16s %14s"%(\ + "call", "nAO", "meshsz","nx","ny","nz", "Egnd", "walltime") + if(n_call==1): + print_00(legend,file=fdlog) + print_00(strlog,file=fdlog); + close_00(fdlog); ### fdlog.close() + assert ( (self.nAO is None) or (self.nAO==rttddft.nAO) ),\ + "wrong nAO:%d/%d"%(self.nAO,rttddft.nAO) + self.nAO=rttddft.nAO; + self.nMO=rttddft.nMO; + print("#calc_gs:MD set:%d %d %d"%(self.nkpt,self.nAO,self.nMO)) + self.tdMO=arrayclone( rttddft.mo_coeff, dtype=np.complex128 ) + self.mo_occ = arrayclone( rttddft.mo_occ ) + prtout_MOocc( rttddft_common.get_job(True)+"_MOocc.dat",rttddft, self.pbc, rttddft._spinrestriction ) + rttddft.set_mo_occ( self.mo_occ, fix_occ=True, clone=False) + print_00("DFT_%s"%(self.spinrestriction)+"mo_occ:",end="");print_00(np.shape(self.mo_occ)) + print_00("DFT_%s"%(self.spinrestriction)+"mo_cofs:",end="");print_00(np.shape(rttddft.mo_coeff)) + print_00("DFT_%s"%(self.spinrestriction)+"DM:",end="");print_00(np.shape(rttddft.make_rdm1())) + + #Ndim=np.shape( rttddft.mo_coeff ) + #if(not self.pbc): + # self.nkpt = Moldyn.nkpt_for_non_pbc_ + # self.nAO = Ndim[0] + # self.nMO = Ndim[1] + #else: + # self.nkpt = Ndim[0] + # self.nAO = Ndim[1] + # self.nMO = Ndim[2] + dm=rttddft.make_rdm1() + self.tdDM=arrayclone( dm, dtype=np.complex128 ) + + self._canonicalMOs=None; + self._canonicalEorbs=None + self._GSfockMat = None + + if( self.spinrestriction == 'O'): + ## note: in ROHF, get_veff returns [2][nAO,nAO] + ## whereas get_fock constructs (Roothaan Fock mat[nAO,nAO]) plus .focka/.fockb extensions + FockMat=rttddft.get_fock( h1e=rttddft.get_hcore(tm_AU=self.time_AU) ) + else: + FockMat=rttddft.get_hcore(tm_AU=self.time_AU) + rttddft.get_veff(rttddft.mol,dm) + if( save_canonicalMOs & 4 ): + self._GSfockMat = arrayclone( FockMat ) + if( save_canonicalMOs & 2): + self._canonicalMOs=arrayclone( rttddft.mo_coeff ) + self._cMOs_Rnuc = arrayclone( self.Rnuc ) + if( save_canonicalMOs & 1): + if( self.spinrestriction=='U'): + self._canonicalEorbs = np.array( [ calc_eorbs(rttddft.mo_coeff[0], FockMat[0]), + calc_eorbs(rttddft.mo_coeff[1], FockMat[1]) ] ) + elif( self.spinrestriction=='R'): + self._canonicalEorbs = calc_eorbs(rttddft.mo_coeff, FockMat) + elif( self.spinrestriction=='O'): + self._canonicalEorbs = [] + nkp=(1 if(not self.pbc) else self.nkpt) + print_00( rttddft.mo_coeff ) + for kp in range(nkp): + Coefs = ( rttddft.mo_coeff if(not self.pbc) else rttddft.mo_coeff[kp] ) + fock = ( FockMat if(not self.pbc) else FockMat[kp] ) + eorbs_1 = [] + print_00(np.shape(Coefs));print_00(np.shape(fock)) + for I in range(self.nMO): + eorb=np.vdot( Coefs[:,I], np.matmul( fock, Coefs[:,I])).real + if( hasattr( fock, 'focka') ): + ea =np.vdot( Coefs[:,I], np.matmul( fock.focka,Coefs[:,I])).real + eb =np.vdot( Coefs[:,I], np.matmul( fock.fockb,Coefs[:,I])).real + eorb = pyscf_lib.tag_array(eorb, mo_ea=ea, mo_eb=eb) + eorbs_1.append( eorb ) + if( not self.pbc ): + self._canonicalEorbs = eorbs_1 + else: + self._canonicalEorbs.append( eorbs_1 ) + self._canonicalEorbs = np.array( self._canonicalEorbs ) +### self._canonicalEorbs = arrayclone( rttddft.get_hcore(tm_AU=self.time_AU) + rttddft.get_veff(rttddft.mol,rttddft.make_rdm1()) ) + + self._calc_Aind=calc_Aind_save + rttddft._calc_Aind=calc_Aind_save + + return self.Egnd + +""" Note + + + #37 methods ... + + svld_energy(self,SorL,pscfpath,eDict=None,Threads=[0]): + save(self,fpath,delimiter='\n',comment=None,Threads=[0],rttddft=None,caller=None, Barrier=False): + load(fpath,eDict=None): + save_tempFockMat(self,src,t2,calc_eigvcs=False): + delete_Fock_last(self,description="",flag=7): + get_DFT(self): + check_matrixShape(self,name,A,nkpt=None,nAO=None,nMO=None): + get_MOvcs(self): + print_Fock(self,rttddft,title,FockMat=None,MOvcs=None,Threads=[0]): + print_DMO(self,title,dmat=None,MOvcs=None,Threads=[0]): + print_AO(self,header="",Threads=[0]): + solve_MO(self,rttddft=None,FockMat=None,update=None,comment=None): + 3. gen_mol_or_cell( self, Rnuc=None, unit='B', spin=None, charge=None ): + 1. gen_rttddft(self, mol_or_cell=None, Rnuc=None,unit=None, nKpoints=None, td_field=None, + 2. gen_rttddft_(self, mol_or_cell=None, Rnuc=None,unit=None, nKpoints=None, td_field=None, + set_Rnuc(self,Rnew,unit): + update_Rnuc(self, Rnew=None, IandJ=None, coordinate=None, update_moldyn=None, fix_occ=True, + set_logger(self,logger=None,filename=None,replace=True,rttddft=None): + get_logger(self,set=False): + set_time_AU(self,time,step=None,rttddft=None): + set_step(self,step,rttddft=None): + calc_hcore(self,rttddft,time_AU=None, dm1_kOR1=None, tmAU_dmat=None, Dict_hc=None): + calc_veff(self,rttddft,dm=None,ovrd_tdDM=None): + calc_fock(self,rttddft,h1e=None,vhf=None,dm=None,time_AU=None,ovrd_tdDM=None): + calc_tdDM(self,rttddft,ovrd=True): + calc_gs(self,rttddft,save_canonicalMOs=7,abort_if_failed=None,dm0=None,errbuf=None): + export_DM(self,fpath,dm=None,comment=None): + read_DM(self,fpath,update_self=False,get_comments=None): + calc_MOprojection( self, rttddft, header,fpath=None,mo_coeff=None,kpts=None,append=True,dict=None): + calc_MOprojection01( self, rttddft, header,FileName,MO_Coeff=None,kpts=None,append=True): + calc_energy_tot(self,rttddft,dm=None,h1e=None,vhf=None,time_AU=None,update_tdDM=None,dict=None, + transform_tdMO(self,rttddft, ForB, check_norm=True,sqrdevtol=1.0e-6,title="",logger=None): + calc_MOpopul(self,Rnuc,target_MOs=None,deviations=None): + print_MOpopul(self,filename,header="",append=False,Rnuc=None,target_MOs=None,deviations=None): + normalize_MOcofs(self,rttddft,MO_Coeffs=None,update_self=True,devsum_TOL=1.0e-7, + get_fock(self,rttddft,h1e,dm,time_AU,update_self=True): + calc_MOpopulations(self,rttddft, target_MOs=None, reference_MOs=None, MO_occ=None): + + +""" diff --git a/pyscf/rttddft/README.md b/pyscf/rttddft/README.md new file mode 100644 index 000000000..329f01a1c --- /dev/null +++ b/pyscf/rttddft/README.md @@ -0,0 +1,6 @@ +# pySCF-rtTDDFT +Installation +(1) Install PySCF 1.7.6a1 following instructions on https://pyscf.org/ +(2) You will have a directory pyscf-1.7.6a1/pyscf/, in which there are gto/, scf/, pbc/ etc. Override files with those in opt_pyscf/ directory. +(3) Compile c/fortran sources in libpp01 using makefile. +(4) Put python scripts in src/ into your work directory. diff --git a/pyscf/rttddft/Stdlogger.py b/pyscf/rttddft/Stdlogger.py new file mode 100644 index 000000000..da308e3ce --- /dev/null +++ b/pyscf/rttddft/Stdlogger.py @@ -0,0 +1,21 @@ +## PLS do not import your own module +## static method only +import numpy as np +import sys +import os +import time +import datetime +class Stdlogger: + loglevel=1 + # -2:FATAL ERROR -1:WARNING 0:MILESTONE LOGS 1:DEBUG LOGS + @staticmethod + def printout(lvl=1,text="",verbose=0,wt0=None,dtme=False): + fd=open("Stdlogger.log",'a') + if( wt0 is not None ): + wt1=time.time() + text+=" elapsed: %f "%(wt1-wt0) + if( dtme ): + text+=" \t\t "+str(datetime.datetime.now()) + print(text,file=fd);fd.close() + if(lvl<( verbose+ Stdlogger.loglevel)): + print(text) diff --git a/pyscf/rttddft/__init__.py b/pyscf/rttddft/__init__.py new file mode 100644 index 000000000..ce21a5624 --- /dev/null +++ b/pyscf/rttddft/__init__.py @@ -0,0 +1,3 @@ +""" +RT-TDDFT +""" diff --git a/pyscf/rttddft/bandstructure.py b/pyscf/rttddft/bandstructure.py new file mode 100644 index 000000000..ac58513e0 --- /dev/null +++ b/pyscf/rttddft/bandstructure.py @@ -0,0 +1,1569 @@ +import numpy as np +import math +import os +import os.path +import sys +import time +import scipy +import scipy.linalg +import datetime +from .Moldyn import get_Fermilvl +from pyscf.pbc.gto import Cell +from .physicalconstants import PhysicalConstants +from .rttddft_common import rttddft_common +from .utils import d1toa,jobname,i1eqb,parse_ints,read_xyzf,write_xyzstring,isScalarNumber,check_matrixrank,\ + parse_xyzstring,atomicsymbol_to_atomicnumber,atomicnumber_to_atomicsymbol,check_equivalence +from .serialize import serialize +from pyscf.pbc import gto as pbc_gto +from pyscf.pbc import dft as pbc_dft +from pyscf.pbc import df as pbc_df +from .Loglv import printout +from mpi4py import MPI +from .rttddft01 import get_Nele + +# +# labels : common symbols of high-symmetrt points of Brillouin zones +def get_named_Kpoints(lattice,names, BravaisVectors): + # see https://en.wikipedia.org/wiki/Brillouin_zone + bravaisvectors = np.reshape( BravaisVectors, [3,3] ) + PIx2=6.283185307179586476925286766559 + PI=3.1415926535897932384626433832795 + sqrt2=1.4142135623730950488016887242097 + sqrt3=1.7320508075688772935274463415059 + if( lattice == "NaCl" or lattice == "diamond" ): + ## both lattice have the same translation vector (1/sqrt2, 1/sqrt2, 0 ) etc. + a=np.sqrt( np.vdot( bravaisvectors[0], bravaisvectors[0] ) ) + ret=[] + N=len(names) + for I in range(N): + name=names[I].strip() + if( name == "X" ): + ret.append( np.array([1.0/sqrt2, 0.0, 0.0 ])*(PIx2/a) ) + elif( name == "W"): + ret.append( np.array([1.0/sqrt2, 0.5/sqrt2, 0.0 ])*(PIx2/a) ) + elif( name == "K"): + ret.append( np.array([ 0.75/sqrt2, 0.75/sqrt2, 0.0 ])*(PIx2/a) ) + elif( name == "L"): + ret.append( np.array([ 0.5/sqrt2, 0.5/sqrt2, 0.5/sqrt2 ])*(PIx2/a) ) + elif( name == "U"): + ret.append( np.array([ 1.0/sqrt2, 0.25/sqrt2, 0.25/sqrt2 ])*(PIx2/a) ) + elif( name == "gamma" or (name.lower)=="gamma" ): + ret.append( np.array([ 0.0, 0.0, 0.0]) ) + else: + assert False,""+name + return ret + elif( lattice == "hexagonal" or lattice == "hcp" ): + ret=[] + N=len(names) + for I in range(N): + name=names[I].strip() + a=np.sqrt( np.vdot( bravaisvectors[0], bravaisvectors[0] ) ) + c=np.sqrt( np.vdot( bravaisvectors[2], bravaisvectors[2] ) ) + if( name == "K" ): + ret.append( np.array( [2*PIx2/(3.0*a), 0.0, 0.0] ) ) + elif( name == "M" ): + ret.append( np.array( [PI/a,-PI/(sqrt3*a), 0.0] ) ) +### ret.append( np.array( [0.0, PIx2/(sqrt3*a), 0.0] ) ) + elif( name == "gamma" ): + ret.append( np.array( [0.0, 0.0, 0.0] ) ) + + elif( name == "H" ): + ret.append( np.array( [2*PIx2/(3.0*a), 0.0, PI/c] ) ) + elif( name == "L" ): + ret.append( np.array( [PI/a, -PI/(sqrt3*a), PI/c] ) ) + elif( name == "A" ): + ret.append( np.array( [0.0, 0.0, PI/c] ) ) + + else: + assert False,"" + return ret + else: + assert False,""+lattice +# +# labels : common symbols of high-symmetrt points of Brillouin zones +def gen_kpoints(cell,lattice,labels,nKpoints,BravaisVectors): + PIx2=6.283185307179586476925286766559 + sqrt2=1.4142135623730950488016887242097 + sqrt3=1.7320508075688772935274463415059 + bravaisvectors = np.reshape( BravaisVectors, [3,3] ) + kpts = cell.make_kpts(nKpoints) + nkpts = len(kpts) + kbuf=[ kpts[kp] for kp in range(nkpts) ] + if( lattice == "NaCl" or lattice == "diamond" ): + a=np.sqrt( np.vdot( bravaisvectors[0], bravaisvectors[0])) + nkpt=len(kbuf) + for kp in range(nkpt): + kvc = np.array( kbuf[kp] ) + scaled = kvc / ( PIx2/a ) + print("#kvecs:%03d: %12.6f,%12.6f,%12.6f %12.6f,%12.6f,%12.6f"%(kp,\ + kvc[0],kvc[1],kvc[2], scaled[0],scaled[1],scaled[2])) + namedKpoints = get_named_Kpoints(lattice,labels, BravaisVectors) + N=len(namedKpoints) + for I in range(N): + v= np.array( namedKpoints[I] ) + dist=None; at=-1 + for j in range(nkpt): + rhs = np.array(kbuf[j]) + dum = np.sqrt( np.vdot( rhs - v, rhs - v) ) + dist = ( dum if(dist is None) else min(dist,dum)) + if( dist < 1e-6 ): + at=j;break + if( at < 0 ): + print("#%03d.%s::"%(I,labels[I])+ str(["%16.8f"%(dum) for dum in v])) + kbuf.append(v);nkpt+=1;continue + else: + print("### %03d.%s:at %03d"%(I,labels[I],at)) + kvecs=np.array(kbuf) + print("#gen_kpoints:%d"%(len(kvecs)),type(kvecs),np.shape(kvecs)) + return kvecs +def find_n_closests(tgtvc,n,Vecs,BravaisVectors=None,Ld=None, TINY=1.0e-8,pbc=None): + tgt=np.array(tgtvc) + PIx2=6.283185307179586476925286766559 + dbgng=True + if( pbc is None ): + pbc = (True if(BravaisVectors is not None) else False) + bvectors=None + if( pbc and (BravaisVectors is not None) ): + bvectors = np.transpose( np.linalg.inv( np.reshape(BravaisVectors,[3,3]) ) ) + vecs=( Vecs if(Ld is None) else np.reshape(Vecs,(-1,Ld)) ) + Nvec=len(vecs) ## c order vecs[Nvec][Ld] + assert n<=Nvec,"" + dist=None;at=None;min_at=None + shiftvecs=[ np.zeros([3],dtype=int) for J in range(Nvec) ] + dbuf=[] + for J in range(Nvec): + rhs = np.array(vecs[J]) + if( not pbc ): + dum = np.sqrt( np.vdot( rhs - tgt, rhs - tgt) ) + else: + vdiff = np.zeros([3]); + for k in range(3): + rk=np.vdot( rhs, BravaisVectors[k] ) + lk=np.vdot( tgt, BravaisVectors[k] ) + idum = int( round( (rk-lk)/PIx2 ) ) + dk=rk-lk + if( idum != 0 ): + print("shifting by Gvector..") + dk-=idum*PIx2;shiftvecs[J][k]= -idum + vdiff=vdiff + dk*bvectors[k] + dum=np.sqrt( np.vdot(vdiff,vdiff) ) ## E001 + if( dbgng ): + print("dum,rhs:",dum,rhs,tgt,shiftvecs[J],bvectors[0],bvectors[1],bvectors[2]) + vref = rhs - tgt + shiftvecs[J][0]*PIx2*bvectors[0] + shiftvecs[J][1]*PIx2*bvectors[1] \ + + shiftvecs[J][2]*PIx2*bvectors[2] + print("vref:",vref) + vdiffSQR = np.vdot(vref-vdiff, vref-vdiff); print("vdiffSQR:",vdiffSQR) + test = np.sqrt( ( np.vdot(vref-vdiff, vref-vdiff) ).real ) + assert test<1e-6,"diff=%e Ishift:"%(test)+str(shiftvecs[J]) + dbuf.append(dum) + ithTOjs=np.argsort(dbuf) + return np.array( ithTOjs[0:n] ), [ dbuf[ ithTOjs[ith] ] for ith in range(n) ],\ + [ shiftvecs[ ithTOjs[ith] ] for ith in range(n) ] + +def expand_vec(Tgt,Vecs,ierr=1): + tgt=np.array(Tgt);vecs=np.array(Vecs) + # we exclude trivial cases + mat = np.array(Vecs[:3]).transpose() + try: + invm = np.linalg.inv(mat) + except np.linalg.LinAlgError as e: + print("inversion failed:",mat) + rank=check_matrixrank(mat) + print("rank:",rank) + print("expand_vec:inversion fails:",e) + if( ierr >0 ): + return None + else: + assert False,"" + cofs = np.matmul( invm, tgt ) + dbgng=True + if( dbgng ): + test= cofs[0]*vecs[0] + cofs[1]*vecs[1] + cofs[2]*vecs[2] + diff = np.sqrt( ( np.vdot(test - tgt, test - tgt) ).real ) + assert diff<1e-6,"" + return cofs +### AP = tgt-vecs[0] +### +### AB = vecs[1]-vecs[0];eAB=AB/(np.sqrt( np.vdot(AB,AB))) +### AC = vecs[2]-vecs[0];eAC=AC/(np.sqrt( np.vdot(AC,AC))) +### +### g_AC = AC - AB * np.vdot( AC,AB )/np.vdot( AB,AB ) +### g_AB = +### work = arrayclone(AP) +### pAC = np.vdot(work,eAC) +### work -= pAC*eAC + +def interpolate_eorb(kvec,Vecs,eOrbs,BravaisVectors,TINY=1.0e-7,Description=None,Indices=None): + Nvec=len(Vecs) + n=min(7,Nvec); + indcs, distances, shifts = find_n_closests(kvec,n,Vecs,BravaisVectors=BravaisVectors,Ld=None, TINY=1.0e-8,pbc=True) + if( distances[0] < TINY ): + if(Description is not None): + Description.append("kp=%03d"%(indcs[0])) +# Description.append("K:%9.4f,%9.4f,%9.4f kp=%03d"%(kvec[0],kvec[1],kvec[2],indcs[0])) + if(Indices is not None): + Indices.clear();Indices.append(indcs[0]) + return eOrbs[ indcs[0] ][:] + else: + if( n >=3 ): + bset = select_bset(3, [ Vecs[ indcs[j] ] for j in range(n) ],TINY=1.0e-7,err=None) + cofs = expand_vec(kvec,bset,-1 ) + if(Description is not None): + Description.append("%9.4f x(%03d:%12.6f) + %9.4f x(%03d:%12.6f) + %9.4f x(%03d:%12.6f)"%( + cofs[0],indcs[0],eOrbs[ indcs[0] ][0], cofs[1],indcs[1],eOrbs[ indcs[1] ][0], + cofs[2],indcs[2],eOrbs[ indcs[2] ][0])) + if(Indices is not None): + Indices.clear(); Indices.append(indcs[0]); Indices.append(indcs[1]); Indices.append(indcs[2]) + return cofs[0]*eOrbs[ indcs[0] ] + cofs[1]*eOrbs[ indcs[1] ] + cofs[2]*eOrbs[ indcs[2] ] + else: + assert False,"" + +def select_bset(rank,Src,TINY=1.0e-7,err=None): + Orth=[];Ret=[];n=0;Isrc=0 + Nsrc=len(Src) + while(n dum) ): + dist = dum; min_at=j + if( dist < TINY ): + at=j;break + return min_at,dist,at +def plot_bandstructure(fpath,Append,lattice,eOrbs,kvecs,labels, BravaisVectors, Occ=None,gnuplot=False, Ndiv=40): + # eOrbs[nKpt][nMO] + Ndim=np.shape(eOrbs); + assert len(Ndim)==2,"" + nKpoints=Ndim[0]; nMO=Ndim[1] + # labels =["W","L","gamma","X","W","K"] + PIx2=6.283185307179586476925286766559 + bravaisvectors = np.reshape( BravaisVectors, [3,3] ) + a=np.sqrt( np.vdot( bravaisvectors[0], bravaisvectors[0])) + N=len(labels) + namedKpoints = get_named_Kpoints(lattice,labels, BravaisVectors) + fd=open(fpath,('a' if(Append) else 'w')) + nkpts=len(kvecs) + eLast=None;kvcLast=None + seqno=0;seqlen=0.0 + b_0= (PIx2/a) / float(Ndiv) + print("#%5s %12s %12s %s %12s %12s %12s %12s %12s %12s"%(\ + "seqno","seqlen","seqlen/(PIx2/a)", "eOrbs:nMO=%d"%(nMO), + "k_x","k_y","k_z", "k_x/(PIx2/a)","k_y/(PIx2/a)","k_z/(PIx2/a)"),file=fd) + + for I in range(N): + kvI= np.array( namedKpoints[I] ) + min_at,dist,at = find_closest( kvI,kvecs, TINY=1.0e-6) + sbuf="" + for m in range(nMO): + sbuf+="%16.8f "%(eOrbs[ min_at ][m]) + print("### %03d %5s %5d %10.2e %s %12.6f %12.6f %12.6f %12.6f %12.6f %12.6f"%(\ + I,labels[I],min_at,dist,sbuf, kvI[0],kvI[1],kvI[2], + kvI[0]/(PIx2/a),kvI[1]/(PIx2/a),kvI[2]/(PIx2/a)), file=fd) + + HOMO=None;SOMO=None;LUMO=None + if( Occ is not None ): + kp=0;Ndim=np.shape(Occ) + if( nKpoints == Ndim[0] and nMO==Ndim[1] ): + for j in range(nMO): + idum = int( round(Occ[kp][j])) + if( idum == 1 and (SOMO is None) ): + SOMO=j + elif( idum == 2 ): + HOMO=j + else: + if(LUMO is None): + LUMO=j + + I_to_s=[ -1 for I in range(N) ] + for I in range(N): + kvI= np.array( namedKpoints[I] ) + min_at,dist,at = find_closest( kvI,kvecs, TINY=1.0e-6) + j=( at if(at is not None) else min_at ) + if( at is None ): + print("#!W cannot find:%s:dist=%f"%(labels[I],dist)) + epsI=eOrbs[ min_at ][:] + if( eLast is not None ): + kdiff= np.array(kvI) - np.array(kvcLast) + le=np.sqrt( np.vdot( kvI-kvcLast,kvI-kvcLast)) + Nsect= int(math.ceil(le/b_0)) + b=le/float(Nsect) + kvc=np.array( kvcLast.copy() ) + r=0.0 + for k in range(Nsect): + seqno+=1;seqlen+=b;kvc+= kdiff/float(Nsect);r+=1.0/float(Nsect) + eps = (1.0 - r)*eLast + r*epsI + strbuf=[];ibuf=[] + ### eps = interpolate_eorb(kvc, kvecs,eOrbs,BravaisVectors,Description=strbuf,Indices=ibuf) + if( k==Nsect-1 ): + assert len(ibuf)==1,"" + string="" + for m in range(nMO): + string+="%16.8f "%(eps[m]) + print(" %5d %12.6f %12.6f %12.6f %s %12.6f %12.6f %12.6f %12.6f %12.6f %12.6f %s"%(\ + seqno,I+r,seqlen,seqlen/(PIx2/a), string, kvc[0],kvc[1],kvc[2], + kvc[0]/(PIx2/a),kvc[1]/(PIx2/a),kvc[2]/(PIx2/a),(labels[I] if(k==Nsect-1) else strbuf[0]) ),file=fd) + else: + sbuf="" + for m in range(nMO): + sbuf+="%16.8f "%(epsI[m]) + print(" %5d %12.6f %12.6f %12.6f %s %12.6f %12.6f %12.6f %12.6f %12.6f %12.6f %s"%(\ + seqno,0.0,seqlen,seqlen/(PIx2/a), sbuf, kvI[0],kvI[1],kvI[2], + kvI[0]/(PIx2/a),kvI[1]/(PIx2/a),kvI[2]/(PIx2/a),labels[0] ),file=fd) + eLast=np.array(epsI).copy(); kvcLast=np.array( kvI.copy() ) + I_to_s[I]=seqlen + fd.close() + if( gnuplot ): + gnu=fpath.replace(".dat","");os.system("gnuf.sh "+gnu) + gnuf=gnu+".plt"; + fd=open(gnuf,"a") + sbuf="set xtics (";dlmt="" + for I in range(N): + sbuf+=dlmt+"\"%s\" %f"%(labels[I],I_to_s[I]);dlmt="," + sbuf+=")" + print(sbuf,file=fd) + nPlot=(1 if(HOMO is None) else 2) + for p in range(nPlot): + PLOT="plot ";tgtf=fpath;lbl="" + m0=0;m1=nMO + if(p==1): + m0=max(0,HOMO-2);m1=min(nMO,(HOMO+3)) + for m in range(m0,m1): + lbl="" + if( p == 1 ): + lbl=( "HOMO-%d"%(HOMO-m) if(m1 and (MPIrank not in Threads) ): + return None + fd=open(path,mode) + return fd +def xprint(text, sep=' ', end='\n', file=None, flush=False): + if( file is None ): + return + print(text, sep=sep, end=end, file=file,flush=flush) + +def getv(dic,key,default=None): + if( key in dic ): + return dic[key] + return default + +def calc_bandstructure(params,job=None,strLatticetype=None): + + HARTREEinEV=PhysicalConstants.HARTREEinEV() + + xyzf=params["xyzf"] + spinrestriction=params["spinrestriction"] + xc=params["xc"] + if( job is None ): job=jobname( name=xyzf.replace(".xyz",""), basis=params["basis"], xc=params["xc"], + nKpoints=params["nKpoints"], spinrestriction=params["spinrestriction"] ) + "_pbcEgnd" + rttddft_common.set_params(params,job) + dic={'a':None} +### strxyz= read_xyzf_to_string(xyzf, dict=dic) + Rnuc_ANGS,Sy=read_xyzf(xyzf,dict=dic) + strxyz= write_xyzstring(Rnuc_ANGS, Sy, input_unit='A',output_unit='A') +### somehow this always fails ... +# File "/usr/src/opt_pyscf/pyscf/pyscf/gto/mole.py", line 349, in format_atom +# fmt_atoms = from_zmatrix('\n'.join(fmt_atoms)) +# File "/usr/src/opt_pyscf/pyscf/pyscf/gto/mole.py", line 3595, in from_zmatrix +# ang = float(vals[3])/180*numpy.pi +# IndexError: tuple index out of range +### cell = pbc_gto.M( a = dic['a'],atom = strxyz, basis = params["basis"]) + cell=pbc_gto.Cell(); cell.a=dic['a'];cell.atom=strxyz; cell.basis=params["basis"] + + if( getv(params,"mesh") is not None): + mesh=getv(params,"mesh") + if(isinstance(mesh,str)): + mesh=parse_ints(mesh,',') + cell.mesh= mesh + if( getv(params,"exp_to_discard") is not None): + cell.exp_to_discard= getv(params,"exp_to_discard") + cell.build() + nKpoints=parse_ints(params["nKpoints"],',');xprint("nKpoints:"+str(nKpoints)) + xprint("LatticeVectors:"+str(dic['a'])) + kpts=cell.make_kpts( nKpoints ) + ksDFT = pbc_dft.KRKS(cell,kpts,xc=xc) ##.mix_density_fit() + if( getv(params,"df") != "GDF"): + assert False,"" + else: + gdf=pbc_df.GDF(cell); gdf.kpts= kpts;ksDFT.with_df=gdf; + + cput1 =time.time(); + Egnd_au = ksDFT.kernel() + Egnd_eV = Egnd_au * HARTREEinEV + cput2 =time.time(); tstep=cput2-cput1; + xfd=xopen(job+".log","w") + xprint("#Egnd:%16.8f %16.8f \t\t %14.4f"%(Egnd_au,Egnd_eV,tstep),file=xfd) + if(xfd is not None): + xfd.close() + if( strLatticetype is not None): + plot_dispersion(strLatticetype,ksDFT,job+"_dispersion.dat") + emin_eV=float( getv(params,"emin_eV","0.0") ) + emax_eV=float( getv(params,"emax_eV","30.0") ) + de_eV=float( getv(params,"de_eV","0.025") ) + calc_ldos(ksDFT, job, emin_eV, emax_eV, de_eV=None, Nstep=None, + iappend=0, OrbitalEngs=None, Occupation=None, spinrestriction='R',TINY=1.0e-10, + widths_eV=[2.7211386024367243, 0.2123, 0.1], gnuplot=True ) + +def get_orthogonalvecs(vecs,Iref=0, vcnorm_thr=1.0e-6): ## vecs[Nvec][Ld] + Nv=len(vecs);Ld=len(vecs[0]);dtype=np.array(vecs[0]).dtype + assert dtype==complex or dtype==np.complex128 or dtype==float or dtype==np.float64,"" + ret=[];Nret=0 + vcnorms=[]; Indices=[] + WKS=np.zeros([Ld],dtype=dtype) + for Iv in range(Nv): + if(Iv==Iref): + continue + for k in range(Ld): + WKS[k]= vecs[Iv][k]-vecs[Iref][k] + + for jr in range(Nret): + ovlp=np.vdot( ret[jr], WKS ) + cof =ovlp/vcnorms[jr] + if( abs(cof)>1.0e-10 ): + for k in range(Ld): + WKS[k]-=cof*ret[jr][k] + dum= np.sqrt( ( np.vdot(WKS,WKS) ).real ) + if( dum > vcnorm_thr ): + ret.append( np.array( [ vecs[Iv][k]-vecs[Iref][k] for k in range(Ld) ] ) ) + vcnorms.append( np.sqrt( (np.vdot(vecs[Iv], vecs[Iv])).real ) ) + Indices.append( Iv ) + return ret,Indices +def plot_dispersion(strLatticetype,mf,fpath,iappend=0, header=None, trailer=None, + OrbitalEngs=None,Occupation=None,spinrestriction='R', **kwargs): + if (OrbitalEngs is None): OrbitalEngs=mf.mo_energy; + PI=3.1415926535897932384626433832795 + PIx2=6.283185307179586476925286766559 + sqrt3=1.7320508075688772935274463415059 + + BOHRinANGS=PhysicalConstants.BOHRinANGS(); + + xfd=xopen(fpath,("a" if(iappend!=0) else "w")) + if(header is not None): + xprint(header,file=xfd) + nmult_MO=(2 if(spinrestriction=='U') else 1) + if( strLatticetype[0:6]=='planer' ): + kpts=mf.kpts + assert len(kpts)>2,"" + + xfdDAF=xopen(fpath,"w"); + legend="#%4s %12s %12s %12s "%("J","kvec","kvec","kvec")+" %14s"%("eorb") + xprint(legend,file=xfdDAF) + for sp in range(nmult_MO): + if(nmult_MO>1): + xprint( ("\n\n\n" if(sp>0) else "") + "#%d:spin=%d"%(sp,sp),file=xfdDAF); + eOrbs=( OrbitalEngs if(nmult_MO==1) else OrbitalEngs[sp]) + nMO=len(eOrbs) + ebuf=np.zeros([nMO],dtype=np.float64) + N=20 + for I in range(3): + for J in range(N): + r=J/float(N) + kvec=[ (1.0-r)*kpts[I][jj] + r*kpts[(I+1)%3][jj] for jj in range(3) ] + string=" %4d %12.4f %12.4f %12.4f "%(J,kvec[0],kvec[1],kvec[2]) + for mo in range(nMO): + ebuf.append( (1.0-r)*eOrbs[I][mo] + r*eOrbs[(I+1)%3][mo]) + for mo in range(nMO): + string+=" %14.6f"%(ebuf[mo]) + xprint(string,file=xfdDAF); + if(xfdDAF is not None): + xfdDAF.close() + ### os.system("ls -ltrh "+fpath) + if( strLatticetype[0:3]=='hex' ): + + latticeVecs=mf.cell.a; + latticeVecNorms=[ np.sqrt( latticeVecs[J][0]**2 + latticeVecs[J][1]**2 + latticeVecs[J][2]**2) for J in range(2) ] + ### this should be rCC*sqrt(3) .. + rCC_ANGS =latticeVecNorms[0]/sqrt3 + xprint("#LatticeVecNorm:%14.6f rCC:%14.6f"%(latticeVecNorms[0],rCC_ANGS)) + rCC_ANGS=1.42 + rCC=rCC_ANGS/BOHRinANGS + kpREF=0 + ### rCC=float(strLatticetype[3:]) + v_Gamma=[ 0.0, 0.0, 0.0] + v_K=[ PIx2/(3*rCC), PIx2/(3.0*sqrt3*rCC), 0.0] + v_M=[ PIx2/(3*rCC), 0.0, 0.0 ] + vcs_01=[ v_Gamma,v_K,v_M,v_Gamma ] + kpts=mf.kpts + xprint("#Kpoints:"+str(kpts)) + xprint("#Gam,K,M points:"+str([v_Gamma,v_K,v_M])) + Nkpts=len(kpts) + + ## assuming [0] to be the zero-vecto + bset, kp_bset=get_orthogonalvecs(kpts);Nb=len(bset) + norms=[ np.sqrt( (np.vdot(bset[jb],bset[jb])).real ) for jb in range(Nb) ] + cofs=np.zeros([Nb],dtype=np.float64) + xfdDAF=xopen(fpath,"w"); + legend="#%4s %12s %12s %12s "%("J","kvec","kvec","kvec")+" %14s"%("eorb") + xprint(legend,file=xfdDAF) + for sp in range(nmult_MO): + if(nmult_MO>1): + xprint( ("\n\n\n" if(sp>0) else "") + "#%d:spin=%d"%(sp,sp),file=xfdDAF); + eOrbs=( OrbitalEngs if(nmult_MO==1) else OrbitalEngs[sp]) + nMO=len(eOrbs) + ebuf=np.zeros([nMO],dtype=np.float64) + N=20 + Ld=len(vcs_01[0]) + for I in range(3): + for J in range(N): + r=float(J)/float(N) + v=[ vcs_01[I][k]*(1.0-r) + vcs_01[I+1][k]*r for k in range(Ld) ] + for jb in range(Nb): + cofs[jb] = np.vdot(bset[jb],v)/norms[jb] + for k in range(Ld): + v[k] -= cofs[jb]*bset[jb][k] + for mo in range(nMO): + ebuf[mo]=eOrbs[kpREF][mo] + for jb in range(Nb): + ebuf[mo]+= cofs[jb]*( eOrbs[ kp_bset[jb] ][mo] - eOrbs[kpREF][mo] ) + string=" %4d %12.4f %12.4f %12.4f "%(J, + vcs_01[I][0]*(1.0-r) + vcs_01[I+1][0]*r, + vcs_01[I][1]*(1.0-r) + vcs_01[I+1][1]*r, + vcs_01[I][2]*(1.0-r) + vcs_01[I+1][2]*r) + for mo in range(nMO): + string+=" %14.6f"%(ebuf[mo]) + xprint(string,file=xfdDAF); + if(xfdDAF is not None): + xfdDAF.close() + os.system("ls -ltrh "+fpath) + if( strLatticetype=='X' or strLatticetype=='Y' or strLatticetype=='Z'): + # 1D dispersion + dir=( 0 if(strLatticetype=='X') else ( 1 if(strLatticetype=='Y') else (2 if(strLatticetype=='Z') else None))) + kvectors=np.reshape( mf.kpts, (-1,3)) + nkpt=len(kvectors) + kzA=[] + for kp in range(nkpt): + kzA.append(kvectors[kp][dir]) + ith_to_kp=np.argsort(kzA) + kzmin=kzA[ith_to_kp[0]];kzmax=kzA[ith_to_kp[nkpt-1]] + kz0=( kzmin if("kz0" not in kwargs) else kwargs["kz0"] ) + kz1=( kzmax if("kz1" not in kwargs) else kwargs["kz1"] ) + Ndiv=( 100 if("Ndiv" not in kwargs) else kwargs["Ndiv"] ); + + dkz=(kz1-kz0)/float(Ndiv) + dk_tiny =0.02*dkz + for J in range(Ndiv+1): + kz=kz0 + dkz*J + string="15.6f \t\t"%(kz) + ithLWR=None;ithUPR=None;ithAT=None + for ith in range(nkpt): + if( abs(kz-kzA[ ith_to_kp[ith] ])0) else \ + {key:{"count":0,"sum":0.0,"sqrsum":0.0}}) + dic2[key]["count"]+=1 + dic2[key]["sum"]+=wtm + dic2[key]["sqrsum"]+=wtm**2 + if( bfsz > 0 ): + while( len(dic2[key]["buf"])>=bfsz ): + dic2[key]["buf"].pop(0) + dic2[key]["buf"].append(wtm) + + elif(ope_PorR=="P"): + ret1="";ret2="" + delimiter=" " + ret1=delimiter.join( [ "%s:%11.3f"%(key,dic1[key]) for key in dic1 ] ) + + ## count=min( [ dic2[key]["count"] for key in dic2 ] ) + ## ret2=delimiter.join( [ "%s:%11.3f \pm %11.2e n=%d"%( key, dic2[key]["sum"]/float(dic2[key]["count"]), + ## np.sqrt(abs(sample_var(dic2[key]["sum"],dic2[key]["sqrsum"],dic2[key]["count"]))),dic2[key]["count"]) for key in dic2 ]) + fdOU=(None if(fpath is None) else open(fpath,("a" if(Append) else "w"))) + fd=(sys.stdout if(fdOU is None) else fdOU) + print("%s %s"%(description,ret1),file=fd); + ## print("## avg over %d:%s"%(count,ret2),file=fd) + if(fdOU is not None): + fdOU.close() +## note: FWHM=0.5eV corresponds to width_eV=0.2123 +## 0.5*( (FwHM/2)**2 / wid**2 ) = ln(2) +## FILENAME _ldos.dat, _eorbs.dat etc. +def calc_ldos(mf, filename, MO_coefs, FockMat, emin_eV=None, emax_eV=None, de_eV=None, Nstep=None, + moldyn=None, + iappend=0, header=None, trailer=None, OrbitalEngs=None, Occupation=None, spinrestriction='R',TINY=1.0e-10, + widths_eV=[0.2123, 2.7211386024367243, 0.1, 0.01], gnuplot=True, N_elec=None, margin_eV=None, Threads=[0] ): + if (Occupation is None): Occupation=mf.mo_occ; + if (moldyn is not None): Occupation=moldyn.mo_occ + nmult_MO=(2 if(spinrestriction=='U') else 1) + nmult_Occ=(2 if(spinrestriction!='R') else 1) + nmult_Fock=(2 if(spinrestriction=='U') else 1) + nmult_eorb=(2 if(spinrestriction=='U') else 1) + pbc=isinstance( mf.mol, Cell) + + fnm1=filename.strip();le1=len(fnm1) + if(fnm1.endswith(".dat")):fnm1=fnm1[:le1-4] + le1=len(fnm1) + for ky in ["_ldos","_lDOS"]: + if(fnm1.endswith(ky)): + fnm1=fnm1[:le1-5] + fnm_pDOS=fnm1+"_pDOS.dat"; + MO_engs=OrbitalEngs + if(MO_engs is None): + MO_engs=calc_eorbs(mf, MO_coefs, FockMat, spinrestriction) + calc_pDOS(mf,fnm_pDOS,MO_engs, MO_coefs, Occupation ) + + # UKS ROKS RKS + # MOcofs [2]([nKpt])[nAO][nMO] ([nKpt])[nAO][nMO] ([nKpt])[nAO][nMO] + # Occ [2]([nKpt])[nMO] [2]([nKpt])[nMO] ([nKpt])[nMO] + # Fock [2]([nKpt])[nAO][nAO] ([nKpt])[nAO][nAO] ([nKpt])[nAO][nAO] + # eOrbs [2]([nKpt])[nMO] ([nKpt])[nMO] ([nKpt])[nMO] + if( nmult_MO > 1 or nmult_Occ > 1 ): + FermiLv_au=( 0.0 if(not pbc) else ( mf.get_fermi() if(moldyn is None ) else \ + get_Fermilvl( moldyn,mf,FockMat=FockMat,MO_coefs=MO_coefs,MO_occ=Occupation, eOrbs=OrbitalEngs)) ) +# 2022.01.09 : rttddft generated by Moldyn.update_Rnuc does NOT have mf.mo_coefs NOR mf.mo_occ and causes trouble if you use mf.get_fermi() +# FermiLv_au=(0.0 if( not pbc ) else mf.get_fermi() ) + assert nmult_MO==2,"" + strUpDn=[ "_upSpin","_dnSpin" ] + for sp in range(nmult_MO): + fermilv_au =( FermiLv_au if( isScalarNumber(FermiLv_au) ) else FermiLv_au[sp] ) + + fockmat =( None if(FockMat is None) else ( FockMat if(nmult_Fock==1) else FockMat[sp] ) ) + mo_coefs =( None if(MO_coefs is None) else ( MO_coefs if(nmult_MO==1) else MO_coefs[sp] ) ) + occupation =( None if(Occupation is None) else ( Occupation if(nmult_Occ==1) else Occupation[sp] ) ) + orbitalengs=( None if(OrbitalEngs is None) else ( OrbitalEngs if(nmult_eorb==1) else OrbitalEngs[sp] ) ) + calc_ldos1( 1, 1, 1, 1, mf, filename+strUpDn[sp], mo_coefs, fockmat, emin_eV=emin_eV, emax_eV=emax_eV, de_eV=de_eV, Nstep=Nstep, + iappend=iappend, header=header, trailer=trailer, OrbitalEngs=orbitalengs, Occupation=occupation, TINY=TINY, + widths_eV=widths_eV, gnuplot=gnuplot, N_elec=N_elec, margin_eV=margin_eV, Threads=Threads, FermiLv_au=fermilv_au ) + fermilv_au =( FermiLv_au if( isScalarNumber(FermiLv_au) ) else FermiLv_au[0] ) + return calc_ldos1( nmult_MO, nmult_Occ, nmult_Fock, nmult_eorb, mf, filename, MO_coefs, FockMat, emin_eV=emin_eV, emax_eV=emax_eV, de_eV=de_eV, Nstep=Nstep, + iappend=iappend, header=header, trailer=trailer, OrbitalEngs=OrbitalEngs, Occupation=Occupation, TINY=TINY, + widths_eV=widths_eV, gnuplot=gnuplot, N_elec=N_elec, margin_eV=margin_eV, Threads=Threads, FermiLv_au=fermilv_au ) + + else: + print("#calc_ldos:check mf.mo_energy:",(mf.mo_energy is not None)) + if( mf.mo_energy is None ): + eorbs=[] + nKpoints=(1 if(not pbc) else len(FockMat)) + for kp in range(nKpoints): + Fock=(FockMat if(not pbc) else FockMat[kp]) + MOs=(MO_coefs if(not pbc) else MO_coefs[kp]) + ndim_MOs=np.shape(MOs);nMO=ndim_MOs[1] + eps=np.zeros([ nMO ],dtype=np.complex128 ) + for mo in range(nMO): + eps[mo]=np.vdot( MOs[:,mo], np.matmul( Fock, MOs[:,mo] )) + if( not pbc ): + eorbs=eps + else: + eorbs.append(eps) + mf.mo_energy=eorbs + print("#calc_ldos:check mf.mo_energy:",(mf.mo_energy is not None)) + FermiLv_au=(0.0 if( not pbc ) else ( mf.get_fermi() if(moldyn is None) else \ + get_Fermilvl( moldyn,mf,FockMat=FockMat,MO_coefs=MO_coefs,MO_occ=Occupation, eOrbs=OrbitalEngs) )) + return calc_ldos1( nmult_MO, nmult_Occ, nmult_Fock, nmult_eorb, mf, filename, MO_coefs, FockMat, emin_eV=emin_eV, emax_eV=emax_eV, de_eV=de_eV, Nstep=Nstep, + iappend=iappend, header=header, trailer=trailer, OrbitalEngs=OrbitalEngs, Occupation=Occupation, TINY=TINY, + widths_eV=widths_eV, gnuplot=gnuplot, N_elec=N_elec, margin_eV=margin_eV, Threads=Threads, FermiLv_au=FermiLv_au ) + # print("check FermiLv..") # (-0.21302746781232837, -0.21302746781232834) for UKS, fermilv is an array + +def calc_eorbs(mf, MO_coefs, FockMat, spinrestriction): + pbc=isinstance( mf.mol, Cell) + nmult_MO=(2 if(spinrestriction=='U') else 1) + + ret=[] + for sp in range(nmult_MO): + MOcofs=( MO_coefs if(nmult_MO==1) else MO_coefs[sp]) + fockmat=( FockMat if(nmult_MO==1) else FockMat[sp]) + ebuf_sp=[] + nkpt=( 1 if(not pbc) else len(MOcofs) ) + for kp in range(nkpt): + MOs=( MOcofs if(not pbc) else MOcofs[kp]) + fck=( fockmat if(not pbc) else fockmat[kp]) + nMO=len(MOs) + engs=[ np.vdot( MOs[:,el], np.matmul( fck, MOs[:,el] ) ).real for el in range(nMO) ] + if(pbc): + ebuf_sp.append(engs) + else: + ebuf_sp=engs + if( nmult_MO == 1 ): + ret=ebuf_sp + else: + ret.append(ebuf_sp) + return np.array(ret) + +def calc_ldos1(nmult_MO, nmult_Occ, nmult_Fock, nmult_eorb, mf, filename, MO_coefs, FockMat, emin_eV=None, emax_eV=None, de_eV=None, Nstep=None, + iappend=0, header=None, trailer=None, OrbitalEngs=None, Occupation=None, TINY=1.0e-10, + widths_eV=[0.2123, 2.7211386024367243, 0.1, 0.01], gnuplot=True, N_elec=None, margin_eV=None, Threads=[0], FermiLv_au=0.0 ): + + HARTREEinEV=PhysicalConstants.HARTREEinEV(); + + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if( MPIsize>1 and (MPIrank not in Threads) ): + return iappend + + ln_tiny=math.log(TINY) + pbc=isinstance( mf.mol, Cell) + nkpt=None + ebuf=None;wbuf=None;nbuf=0;ibuf=None;bfsz=0;nbuf_s=[0,0] + ebuf_s=None;wbuf_s=None;ibuf_s=None;nbuf_s=[0,0] + for sp in range(nmult_MO): + MOcofs=(MO_coefs if(nmult_MO==1) else MO_coefs[sp]) + fockmat=(FockMat if(nmult_MO==1) else FockMat[sp]) + ### eorbs=(OrbitalEngs if(nmult_eorbs==1) else OrbitalEngs[sp]) + orbocc=(Occupation if(nmult_Occ==1) else Occupation[sp]) + Ndim_MO=np.shape(MOcofs) # [nAO,nMO] or [nKpt,nAO,nMO] + Ndim_occ=np.shape(orbocc); ### assert i1eqb(Ndim_eorbs,Ndim_occ),"" + nkpt=(1 if(not pbc) else Ndim_MO[0]) + nMO =(Ndim_MO[1] if(not pbc) else Ndim_MO[2]) + if(ebuf is None): + bfsz=nkpt*nMO*nmult_MO + ebuf=np.zeros([bfsz],dtype=np.float64); wbuf=np.zeros([bfsz],dtype=np.float64); + ibuf=np.zeros([bfsz,3],dtype=int) + if( nmult_MO > 1 ): + ebuf_s=np.zeros([nmult_MO,nkpt*nMO ],dtype=np.float64); + wbuf_s=np.zeros([nmult_MO,nkpt*nMO],dtype=np.float64); + ibuf_s=np.zeros([nmult_MO,nkpt*nMO,3],dtype=int) + + for kp in range(nkpt): + MOs=(MOcofs if(not pbc) else MOcofs[kp]) + fck=(fockmat if(not pbc) else fockmat[kp]) + + occ=(orbocc if(not pbc) else orbocc[kp]) + for el in range(nMO): + en= np.vdot( MOs[:,el], np.matmul( fck, MOs[:,el] ) ).real + ebuf[nbuf]=en; wbuf[nbuf]=occ[el]; ibuf[nbuf]=[sp,kp,el]; nbuf+=1 + if( nmult_MO > 1 ): + ebuf_s[ sp ][ nbuf_s[sp] ]= en; + wbuf_s[ sp ][ nbuf_s[sp] ]= occ[el]; + ibuf_s[ sp ][ nbuf_s[sp] ]= [sp,kp,el]; nbuf_s[sp]+=1 + assert nbuf==bfsz,"" + ithTOjs= np.argsort(ebuf) + e_eV_sorted=np.zeros([bfsz],dtype=np.float64); + w_sorted=np.zeros([bfsz],dtype=np.float64); + i_sorted=np.zeros([bfsz,3],dtype=int) + for ith in range(bfsz): + js=ithTOjs[ith];e_eV_sorted[ith]=ebuf[js]*HARTREEinEV; + w_sorted[ith]=wbuf[js];i_sorted[ith]=ibuf[js] + if(pbc and nkpt>1): + fac=1.0/float(nkpt) + for ith in range(bfsz): + w_sorted[ith]=w_sorted[ith]*fac + eorb_min_eV=e_eV_sorted[0] + eorb_max_eV=e_eV_sorted[bfsz-1] + + + daf_eorbs=filename+"_eorbs.dat" + xfd=xopen(daf_eorbs,("a" if( iappend!=0 ) else "w")) + if( header is not None): + xprint(header,file=xfd); + xprint("#%19s %20s %5s %5s %5s"%("eorb_eV","weight","sp","kp","mo"),file=xfd) + for ith in range(bfsz): + xprint("%20.10f %20.10f %5d %5d %5d"%(e_eV_sorted[ith],w_sorted[ith], + i_sorted[ith][0],i_sorted[ith][1],i_sorted[ith][2]),file=xfd) + if(trailer is not None): + xprint(trailer,file=xfd) + if( xfd is not None): + xfd.close() + + if( (de_eV is None) and (Nstep is None ) ): + min_w=min(widths_eV) + de_eV=( 0.25*min_w if(min_w<0.1) else 0.1*min_w ) + max_w=max(widths_eV) + if( margin_eV is None ): + margin_eV=max( 2*max_w, (8.0 if de_eV is None else de_eV*20) ) + printout("#calc_ldos:margin_eV:%f %f %f %f"%(margin_eV,2*max_w,8.0,de_eV*20)) + if( emin_eV is None ): + emin_eV= eorb_min_eV - margin_eV + if( emax_eV is None ): + emax_eV= eorb_max_eV + margin_eV + + if( de_eV is not None): + Nstep=int(math.ceil((emax_eV-emin_eV)/de_eV)) + elif( Nstep is not None): + de_eV=(emax_eV-emin_eV)/float(Nstep) + printout("#calc_ldos:Nstep:%d de_eV:%f"%(Nstep,de_eV)) + + sqrt2pi=2.506628274631000502415765284811 + daf_ldos=filename+"_ldos.dat" + xfd=xopen( daf_ldos,("a" if(iappend!=0) else "w")) + if( header is not None): + xprint(header,file=xfd); + e_eV=emin_eV + wgt_ref=(1.0 if(nmult_Occ==2) else 2.0)/(1.0 if(not pbc) else float(nkpt)) + wgsum = sum(w_sorted); + printout("#calc_ldos:wgsum:%f"%(wgsum)) + if( N_elec is not None): + assert abs(N_elec-wgsum)<1.0e-3,"" + ## exp(-0.5*((e_eV-ej_eV)/wid)**2) + Nwid=len(widths_eV) + nrmz_factors=[ 1.0/(sqrt2pi*widths_eV[kwid]) for kwid in range(Nwid) ] + fn=[ 0.0 for kwid in range(Nwid) ] + fn_occ=[ 0.0 for kwid in range(Nwid) ] + cum=[ 0.0 for kwid in range(Nwid) ] + cum_occ=[ 0.0 for kwid in range(Nwid) ] + + I0=-1 + for I in range(Nstep): + e_eV=emin_eV + I*de_eV + for kwid in range(Nwid): + fn[kwid]=0.0; fn_occ[kwid]=0.0 + for js in range(bfsz): + arg=-0.5*( ((e_eV-e_eV_sorted[js])/widths_eV[kwid])**2 ) + if(arg>",mesh) + ret = gto.Cell() + ret.mesh= mesh + ret.rcut=src.rcut + ret.exp_to_discard = src.exp_to_discard + ret.dimension = src.dimension + ret.charge=src.charge + ret.spin=src.spin + ret.precision=src.precision + ret.atom = src.atom.copy() + ret.basis = src.basis + ret.pseudo = src.pseudo + ret.a = src.a.copy() ### this should be an intrinsic property so I leave it .. but let's use .BravaisVectors_au for our calculations + # ret.BravaisVectors_au = src.BravaisVectors_au + if( kpts is None ): + if( nKpoints is not None ): + kpts=ret.make_kpts(nKpoints) + elif( mf is not None ): + kpts=mf.kpts + ret.build() + dbgng=True + if( dbgng ): + fd1=open("modify_cell_SRC.log","w");print(serialize(src),file=fd1);fd1.close() + fd2=open("modify_cell_DST.log","w"); + print("#",mesh,kpts,nKpoints,file=fd2) + print(serialize(ret),file=fd2);fd2.close() + os.system("fopen modify_cell_SRC.log");os.system("fopen modify_cell_DST.log"); + return ret +# +# Here you can apply BravaisVectors of A SINGLE CELL (<=> your supercell) to plot larger BZ +# +def plot_dispersion_kLine(fpath,mf,dmat,BravaisVectors,lattice=None,NamedKpoints=None,Append=False): + bravaisvectors=BravaisVectors;description=None + dum=rttddft_common.Params_get("dimerization") + if( dum is not None ): + sA=dum.split(",");nA=len(sA);nlm=[ int(sA[k]) for k in range(nA) ] + bravaisvectors=np.array([ np.array( BravaisVectors[0] )/nlm[0],\ + np.array( BravaisVectors[1] )/nlm[1],\ + np.array( BravaisVectors[1] )/nlm[2] ]) + description=" dimerization:"+str(nlm) + if( NamedKpoints is None ): + assert lattice is not None,"" + if( lattice in [ "NaCl", "diamond" ] ): + labels=["W","L","gamma","X","W","K"] + NamedKpoints=get_named_Kpoints(lattice,labels, bravaisvectors) + elif( lattice in ["hexagonal","hcp"] ): + labels=["K","M","gamma","K"] + if( mf.cell.dimension == 3 ): + labels=["gamma","M","K","gamma","A","L","K","A"] + NamedKpoints=get_named_Kpoints(lattice,labels, bravaisvectors) + else: + assert False,"" + plot_dispersion_kLine_(fpath,mf,dmat,NamedKpoints,labels,Append=Append,description=description) +## +## You might rebuils cell with larger meshsize.. +## +def plot_dispersion_kLine_(fpath,mf,dmat,NamedKpoints,labels,dk_refr=None,cell=None,mesh=None,Append=False, + description=None): + + if( cell is None ): + if(mesh is not None): + cell=modify_cell( mf.cell, mf=mf, mesh=mesh) + else: + cell=mf.cell + + kpts_band=[] + Np=len(NamedKpoints) + # eg. 4 NamedKpoints 0,1,2,3 ---- + # 1 0.0, 0.1, 0.2 ... 0.9 + # 2 1.0, ... 1.9 + # 3 2.9 3.0 + Nkpts_array=[] + Dbgng=True + + Nkpts_UPL=None + Nkpts_UPL=rttddft_common.Params_get("Nkpts_UPL") + if(Nkpts_UPL is not None ): + Nkpts_UPL=int(Nkpts_UPL) + + for I in range(1,Np): + Kv_0= np.array(NamedKpoints[I-1]); Kv_1=np.array(NamedKpoints[I]) + Delta_K = Kv_1- Kv_0 + len_Delta_K= vecnorm(Delta_K) + if( dk_refr is None ): + dk_refr=len_Delta_K/20.0 + Ndiv = int( np.ceil( len_Delta_K/dk_refr ) ); Ndiv=max(1,Ndiv) + Nkpts_array.append(Ndiv) + dK = Delta_K*(1.0/float(Ndiv)) + Kv=Kv_0 + for J in range(Ndiv): + kpts_band.append( np.array( [ Kv[0],Kv[1],Kv[2] ] ) ) + Kv += dK + dum=vecnorm( Kv - Kv_1);assert dum<1e-6,"" + if( I+1 == Np ): + kpts_band.append( np.array( [ Kv[0],Kv[1],Kv[2] ] ) ) + Nkpts_Kline=len(kpts_band) + if(Dbgng): + kvecs=np.reshape( mf.kpts, (-1,3)) + nkvcs=len(kvecs) + for kp in range(nkvcs): + kpts_band.append( kvecs[kp] ) + + Nkpts_band=len(kpts_band) + kpts_DM = np.reshape( mf.kpts, (-1,3)) + Nkpts_DM = len(kpts_DM) + + # 2022.02.15 ... we divide kpts_band into subarrays + # hereafter we replace kpts_band_I + + nBlock=(1 if(Nkpts_UPL is None) else \ + (1 if(Nkpts_band<=Nkpts_UPL) else int( math.ceil( Nkpts_band/float(Nkpts_UPL)) )) ) + kpt_offset=0 + eig_kpts = [] + cofs=[] + wt0=time.time();wt1=wt0; wt_hc=[];wt_veff=[];wt_eig=[] + for ib in range(nBlock): + kpts_band_I= kpts_band; + if( nBlock > 1 ): + kpts_band_I = [ kpts_band[k] for k in range(ib*Nkpts_UPL, min(Nkpts_band, (ib+1)*Nkpts_UPL)) ] + Nkpts_band_I = len(kpts_band_I) + if( Nkpts_band_I < 1 ): + continue ##... never come here ... + + Hc=mf.get_hcore(cell_or_mol=mf.cell,kpts=kpts_band_I); wt2=wt1;wt1=time.time();wt_hc.append( wt1-wt2 ); + assert len(Hc)==Nkpts_band_I,"" + Veff=mf.get_veff(cell=mf.cell,kpts_band=kpts_band_I); wt2=wt1;wt1=time.time();wt_veff.append( wt1-wt2 ); + assert len(Veff)==Nkpts_band_I,"" + + nMO=None + Hmlt = Hc + Veff + # S1e=[] + for k in range(Nkpts_band_I): + ## @see khf.py#eig + S_k=mf.get_ovlp( cell, kpts_band_I[k]);# S1e.append(S_k) + e, c = mf._eigh(Hmlt[k], S_k) + if( nMO is None ): + nMO=len(e) + else: + nMO=min( len(e),nMO) + eig_kpts.append(e); + cofs.append(c) + wt2=wt1;wt1=time.time();wt_eig.append(wt1-wt2); + wt1=time.time();wt_sum=wt1-wt0; + fd1=open("plot_dispersion_kLine_walltime.log","a"); + print("Nkpt:%5d nBlock:%d walltime:%f (hc:%f,veff:%f,eig:%f)"%(Nkpts_band,nBlock,wt_sum,sum(wt_hc),sum(wt_veff),sum(wt_eig))\ + +("" if(nBlock==1) else str(wt_hc)+str(wt_veff)+str(wt_eig))+"\t\t"+str(rttddft_common.get_job(True)),file=fd1) + fd1.close();os.system("fopen plot_dispersion_kLine_walltime.log") + if(Dbgng): + fnmeDBG="plot_dispersion_kLine.log"; fdDBG=open(fnmeDBG,"w") + for I in range(Nkpts_DM): + S_kI=mf.get_ovlp( cell, kpts_band[ Nkpts_Kline + I ]); + engs_kI=np.array( eig_kpts[ Nkpts_Kline + I ] ) + cofs_kI=np.array( cofs[ Nkpts_Kline + I ] ) + eREF_kI=np.array( mf.mo_energy[I] ) + cREF_kI=np.array( mf.mo_coeff[I] ) + ediff=max( abs( engs_kI - eREF_kI ) ) + cdiff=max( abs( np.ravel(cofs_kI) - np.ravel(cREF_kI) )) + covlp=np.vdot( cREF_kI, np.matmul( S_kI, cofs_kI)) + covl_II= np.vdot( cofs_kI,np.matmul( S_kI, cofs_kI)) + covl_REF=np.vdot( cREF_kI, np.matmul( S_kI,cREF_kI)) + print("#calc_kLine:kp:%03d: ediff:%16.6e, cdiff:%16.6e |covlp|:%f (%f+j%f) / II (%f+j%f), refI,refI (%f+j%f)"%(\ + I,ediff,cdiff,abs(covlp),covlp.real,covlp.imag, covl_II.real,covl_II.imag, covl_REF.real,covl_REF.imag),file=fdDBG) + + if( nBlock==1 and (ediff > 1e-6 or cdiff > 1e-6) ): + ebuf=[] + nMO=len(engs_kI) + for ell in range(nMO): + eps=np.vdot( cREF_kI[ell],np.matmul(Hmlt[ Nkpts_Kline + I ],cREF_kI[ell] ) ) + ebuf.append(eps) + ediff1=max( abs( np.array(eps) - engs_kI)) + ediff2=max( abs( np.array(eps) - eREF_kI)) + print("#calc_kLine:kp:%03d: diff(,new_eig):%16.6e, diff(,canonical eps):%16.6e"%(I,ediff1,ediff2),file=fdDBG) + fdDBG.close() + os.system("fopen "+fnmeDBG); + fdDAF=open(fpath,("a" if(Append) else "w")) + gnu=fpath.replace(".dat","");os.system("gnuf.sh "+gnu); gnuf=gnu+".plt" + fdGNU=open(gnuf,"a"); + if( description is not None ): + print("set title \"dispersion along kline, %s\"\n"%(description),file=fdGNU) + else: + print("set title \"dispersion along kline\"\n",file=fdGNU) + + kl=0;s=0.0;I_to_s=[ 0.0 ] + for I in range(1,Np): + Kv_0= np.array(NamedKpoints[I-1]); Kv_1=np.array(NamedKpoints[I]) + Delta_K = Kv_1- Kv_0 + len_Delta_K= vecnorm(Delta_K) + Ndiv=Nkpts_array[I-1] + dk_len=len_Delta_K/float(Ndiv);dK=Delta_K*(1.0/float(Ndiv)) + Kv=Kv_0 + for J in range(Ndiv): + ## this starts from 0 + print(" %5d %14.6f %12.6f %12.6f %12.6f %s"%(kl+J,s,Kv[0],Kv[1],Kv[2], + d1toa(eig_kpts[kl+J])),file=fdDAF) + Kv+=dK;s+=dk_len; + if( I+1 == Np ): + print(" %5d %14.6f %12.6f %12.6f %12.6f %s"%(kl+Ndiv,s,Kv[0],Kv[1],Kv[2], + d1toa(eig_kpts[kl+Ndiv])),file=fdDAF) + I_to_s.append(s);kl+=Ndiv + sbuf="set xtics (";dlmt="" + for I in range(Np): + sbuf+=dlmt+"\"%s\" %f"%(labels[I],I_to_s[I]);dlmt="," + sbuf+=")" + print(sbuf,file=fdGNU) + mu_au=mf.get_fermi( mo_energy_kpts=mf.mo_energy, mo_occ_kpts=mf.mo_occ) + print("EF_au=%f"%(mu_au),file=fdGNU) + print("set ylabel \"{/Symbol e}_k-{/Symbol m} (eV)\"",file=fdGNU) + N_ele=int(round(get_Nele(mf))) + HOMO=int( (N_ele+1)//2 ) + MOstt=HOMO-2;MOupl=HOMO+4 + MOstt=max(0,HOMO-2);MOupl=min(nMO,HOMO+4) + print("MOstt:",MOstt,MOupl,HOMO,range(MOstt,MOupl)) + MOlabels=[ ("HOMO-%d"%(HOMO-mo) if(mo LdUPL): + nBlock=int( math.ceil( LdTOT/float(LdUPL) ) ) + Nstep_ref=int( math.ceil( NstepTOT/nBlock ) ) + + both = True ## TODO + AOpop_Lowdin =(None if((not LowdinPop) and (not both) ) else np.zeros([nKpt,nAO,nMO], dtype=np.float64)) + AOpop_Mulliken=(None if(LowdinPop and (not both)) else np.zeros([nKpt,nAO,nMO], dtype=np.complex128)) + if(LowdinPop or both): + # |sSQRT[mu][:]C[:][io]|**2 + mf.update_Sinv() + sSQRT=mf._Ssqrt + for kp in range(nKpt): + sSQRTxC=np.matmul(sSQRT[kp],MO_coefs[kp]) ## [nAO,nAO] x [nAO,nMO] + for ao in range(nAO): + for mo in range(nMO): + AOpop_Lowdin[kp][ao][mo]= sSQRTxC[ao][mo].real**2 + sSQRTxC[ao][mo].imag**2 + if((not LowdinPop) or both): + # S[mu][:] C[:][o] C[mu][o]^{\ast} + for kp in range(nKpt): + S1e=mf.get_ovlp( mol_or_cell,kvectors[kp] ) + SxC=np.matmul(S1e,MO_coefs[kp]) + for ao in range(nAO): + for mo in range(nMO): + AOpop_Mulliken[kp][ao][mo]= SxC[ao][mo]* np.conj(MO_coefs[kp][ao][mo]) + + rowTOpop=None;AOpop=None + AOpop=( AOpop_Lowdin if(LowdinPop) else AOpop_Mulliken ) + + if( AOpop_Lowdin is not None ): + a1d=np.ravel(AOpop_Lowdin) + Nnega=np.count_nonzero( a1d<0.0 ) + if(Nnega>0): + minv=min(a1d) + rttddft_common.Printout_warning("LowdinPop","Nnega:%d minv:%f"%(Nnega,minv)) + if( AOpop_Mulliken is not None ): + a1d=np.ravel(AOpop_Mulliken) + Nnega=np.count_nonzero( a1d<0.0 ) + if(Nnega>0): + minv=min(a1d) + rttddft_common.Printout_warning("MullikenPop","Nnega:%d minv:%f"%(Nnega,minv)) + check_populations=True + + if(check_populations): + N_ele = get_Nele(mf) + fdOU=open("populations.dat","w");delimiter=" " + rowTOlpop =(None if((not LowdinPop) and (not both) ) else np.zeros([N_rows], dtype=np.float64)) + rowTOmpop =(None if(LowdinPop and (not both)) else np.zeros([N_rows], dtype=np.complex128)) + + if(LowdinPop or both): + for kp in range(nKpt): + rowTOlpop += np.einsum('rm,mi,i -> r',P,AOpop_Lowdin[kp],MO_occ[kp]) + rowTOlpop *= (1.0/float(nKpt)) + print("LowdinPop:", delimiter.join( [ "%s:%f"%(rowTOlabel[r],rowTOlpop[r]) for r in range(N_rows) ]), file=fdOU) + if( row_sum > 0 ): + testee = rowTOlpop[row_sum];dev=abs(testee-N_ele) + print("#LowdinPop:%f / %f %e"%(testee,N_ele,dev)) + if( dev > 1e-6 ): + rttddft_common.Assert(dev<1e-6,"#LowdinPop:%f / %f %e"%(testee,N_ele,dev),1) + if((not LowdinPop) or both): + for kp in range(nKpt): + rowTOmpop += np.einsum('rm,mi,i -> r',P,AOpop_Mulliken[kp],MO_occ[kp]) + rowTOmpop *= (1.0/float(nKpt)) + print("MullikenPop:", delimiter.join( [ "%s:%f"%(rowTOlabel[r],rowTOmpop[r]) for r in range(N_rows) ]), file=fdOU) + + rowTOpop=(rowTOlpop if(LowdinPop) else rowTOmpop) + + step0=0;step1=Nstep_ref + wt2=wt1;wt1=time.time() + for iBlc in range(nBlock): + assert step0 P[JW][R][STEP] + pDOSocc += np.einsum('rm,mi,i,jip->jrp', P,AOpop[kp],MO_occ[kp],expo) + pDOStot += np.einsum('rm,mi,jip->jrp', P,AOpop[kp],expo) + #ValueError: operands could not be broadcast together with shapes (6,2,18503) (2,6,18503) (6,2,18503) + pDOSocc*=(1.0/float(nKpt)) + pDOStot*=(1.0/float(nKpt)) + + for jw in range(Nwid): + for ir in range(N_rows): + occSums[jw][ir] += sum( pDOSocc[jw][ir] )*de_eV + totSums[jw][ir] += sum( pDOStot[jw][ir] )*de_eV + + e=e0;delimiter=" "; + sA=np.ravel( [ ["%16.6e %16.6e"%(pDOSocc[jw][ir][0].real,pDOStot[jw][ir][0].real) for ir in range(N_rows)]\ + for jw in range(Nwid) ] ) + line=delimiter.join(sA) + print(" %14.6f %s"%(e,line),file=fdDAF) + for s in range(1,Nstep): + jxi=0 + for jw in range(Nwid): + for ir in range(N_rows): + sA[ jxi+ir ]="%16.6e %16.6e"%(pDOSocc[jw][ir][s].real,pDOStot[jw][ir][s].real) + jxi+=N_rows + line=delimiter.join(sA) + e+=de_eV + print(" %14.6f %s"%(e,line),file=fdDAF) + + step0+=Nstep;step1=min( step1+Nstep,NstepTOT ) #<< PLS NEVER REMOVE THIS --- + assert step0>=NstepTOT,"" + +# impartMax1=-1;impartMax2=-1 +# for jw in range(Nwid): +# for row in range(N_rows): +# string+=" ".join([ "%16.6e %16.6e"%(pDOSocc[row][jw].real,pDOStot[row][jw].real) ])+" " +# impartMax1 =max( impartMax1,abs(pDOSocc[row][jw].imag) ) +# impartMax2 =max( impartMax2,abs(pDOStot[row][jw].imag) ) +# print(string,file=fdDAF) +# print("Imaginarypart:%e,%e"%(impartMax1,impartMax2)) +# rttddft_common.Assert( impartMax1<1e-5 and impartMax2<1e-5, "Imaginarypart:%e,%e"%(impartMax1,impartMax2), 1) + fdDAF.close();fdGNU.close() + os.system("fopen "+gnuf) + check_walltime("",-1,dic_wt,dic_wtAV,ope_PorR="P",fpath="calc_pDOS_walltime.log", + description="WT for nKpt:%d,nAO:%d,Nstep:%d,Nrow:%d ... %s"%( nKpt, nAO, Nstep, N_rows, str(rttddft_common.get_job(True))) ) + + fnmeC=dafpath.replace(".dat","")+"_checksum.dat" + fd1=open(fnmeC,"a"); + for jw in range(Nwid): + delimiter=" " + sA=[ "%s:%14.6f"%(rowTOlabel[row],occSums[jw][row]) for row in range(N_rows) ] + string=delimiter.join( sA );refr="" + if( rowTOpop is not None): + refr=" pop:" + delimiter.join( [ "%s:%f"%(rowTOlabel[r],rowTOpop[r]) for r in range(N_rows) ]) + print("#wid:%f OccSum:%s %s"%( widths_eV[jw],string,refr ),file=fd1) + sA=[ "%s:%14.6f"%(rowTOlabel[row],totSums[jw][row]) for row in range(N_rows) ] + string=delimiter.join( sA ) + print("###w:%f TotSum:%s"%( widths_eV[jw],string ),file=fd1) + fd1.close() + os.system("fopen "+fnmeC) +def einsum_pDOS1_(P, SxC_kp, MO_coefs_kp, MO_occ_kp, gsf, N_row,Nwid,nAO,nMO): + ret1=np.zeros([N_row,Nwid],dtype=np.complex128); + ret2=np.zeros([N_row,Nwid],dtype=np.complex128); + for row in range(N_row): + for jw in range(Nwid): + cum1=np.complex128(0.0);cum2=np.complex128(0.0) + for mu in range(nAO): + for iMO in range(nMO): + dum= P[row][mu]*SxC_kp[mu][iMO]*np.conj(MO_coefs_kp[mu][iMO])*gsf[iMO][jw] + cum1+= dum*MO_occ_kp[iMO] + cum2+= dum + ret1[row][jw]=cum1 + ret2[row][jw]=cum2 + return ret1,ret2 + diff --git a/pyscf/rttddft/calcNacm.py b/pyscf/rttddft/calcNacm.py new file mode 100644 index 000000000..0a34caa1d --- /dev/null +++ b/pyscf/rttddft/calcNacm.py @@ -0,0 +1,1442 @@ +import numpy as np +import math +import os +import time +from .futils import futils +from .Logger import Logger +from scipy import linalg +# from physicalconstants import get_constants +from .utils import arrayclone,arrayclonex,print_z3tensor,z1diff,z2diff,d1maxdiff,nmrdff,aNtofile,aNsqrediff,d1diff,calc_eorbs +from .Moldyn import Moldyn +from .Constants import Constants +from .rttddft02 import RTTDDFT_ +from mpi4py import MPI +# from pyscf.pbc.grad.krks import Gradients +from .MPIutils01 import MPIutils01 +# from pyscf.Loglv import printout +from .calcNacm2 import numrdiff_matrices, convert_dm_AO_to_Orth, convert_dm_Orth_to_AO, get_mu_to_iat, dmtrace,get_derivMatrices_FFTDF +from .heapcheck import heapcheck + +import datetime +def aNmaxdiff( lhs,rhs,error_buf=None ): + if( error_buf is not None): + error_buf.clear() + lh=np.ravel(lhs) + rh=np.ravel(rhs) + Ld=len(lh); + if( Ld !=len(rh) ): + if( error_buf is not None): + error_buf.append( "dim differs:%d(%s)/%d(%s)"%(Ld,str(np.shape(lhs)),\ + len(rh),str(np.shape(rhs))) ) + return 1; + assert (Ld==len(rh)),"dim differs" + dev=abs(lh[0]-rh[0]) + for I in range(1,Ld): + dum=abs(lh[I]-rh[I]) + if( dum>dev ): + dev=dum + return dev + +def prtNacm(pbc,spin_restriction,Vdot_Nacm,MOrep=True,refr_MO=None,Vnuc_1D=None,job="",append=True,Istep=-1,tm_au=-1.0,logger=None): + AUinFS=2.418884326058678e-2 + assert ( spin_restriction=='R' or spin_restriction=='O' or spin_restriction=='U'),"spin_restriction:"+spin_restriction + ndim_X=np.shape(Vdot_Nacm) #[ nkpt ] [ nAO ] [ nAO ] + if( not pbc): + nkpt=1; nAO=ndim_X[0] + else: + nkpt=ndim_X[0]; nAO=ndim_X[1]; + isReal=(np.array(Vdot_Nacm).dtype == float) + if( not MOrep ): + absv=np.zeros([nAO,nAO], dtype=np.float64) + for kp in range(nkpt): + Mat= Vdot_Nacm if(not pbc) else Vdot_Nacm[kp] + fnme=( job+"_Nacm.dat" if(not pbc) else job+"_%03d_Nacm.dat"%(kp) ) + fd=futils.fopen(fnme,("a" if append else "w")) + strVnuc=("" if(Vnuc_1D is None) else "V=%f"%( np.sqrt( np.vdot(Vnuc_1D,Vnuc_1D) ) ) ) + print("#Nacm:%d t=%14.4f a.u. %14.4f fs "%(Istep,tm_au,tm_au*AUinFS) + strVnuc, file=fd) + for I in range(nAO): + sbuf="" + if( isReal ): + for J in range(nAO): + sbuf+="%9.4f "%(Mat[I][J]) + else: + for J in range(nAO): + sbuf+="%7.3f %7.3f "%(Mat[I][J].real,Mat[I][J].imag) + print(sbuf,file=fd); + for J in range(nAO): + absv[I][J]=abs(Mat[I][J]) + futils.fclose(fd) + if( logger is not None ): + N=len(np.ravel(absv)) + ithTOixj=np.argsort( np.ravel(absv) ) + logger.Info("#Nacm_%d %6d %14.4f %14.4f "%( kp, Istep, tm_au, tm_au*AUinFS),end="") + for ith in range(10): + ixj=ithTOixj[ N-ith-1 ]; + J=ixj%nAO; I=ixj//nAO + if( isReal ): + logger.Info("%d: %d,%d %9.4f "%(ith,I,J,Mat[I][J]),end="") + else: + logger.Info("%d: %d,%d %9.3e (%8.3f+%8.3fj) "%(ith,I,J,abs(Mat[I][J]), + Mat[I][J].real,Mat[I][J].imag),end="") + logger.Info("") + return + + assert (refr_MO is not None),"" + refMO=( refr_MO if( spin_restriction != 'U' ) else refr_MO[0]) + + Ndim=np.shape(refMO) + if( not pbc): + nkpt=1; nAO=Ndim[0]; nMO=Ndim[1] + else: + nkpt=Ndim[0]; nAO=Ndim[1]; nMO=Ndim[2] + VX_lm=np.zeros( [nMO,nMO], dtype=np.complex128) + absv=np.zeros([nMO,nMO], dtype=np.float64) + for kp in range(nkpt): + Mat= Vdot_Nacm if(not pbc) else Vdot_Nacm[kp] + MOs= refMO if(not pbc) else refMO[kp] + VX_lm= np.matmul( np.matrix.getH(MOs), np.matmul( Mat, MOs ) ) + fnme=( job+"_Nacm.dat" if(not pbc) else job+"_%03d_Nacm.dat"%(kp) ) + fd=futils.fopen(fnme,("a" if append else "w")) + strVnuc=("" if(Vnuc_1D is None) else "V=%f"%( np.sqrt( np.vdot(Vnuc_1D,Vnuc_1D) ) ) ) + print("#Nacm:%d t=%14.4f a.u. %14.4f fs "%(Istep,tm_au,tm_au*AUinFS) + strVnuc, file=fd) + for I in range(nMO): + sbuf="" + for J in range(nMO): + sbuf+="%8.3f %8.3fj "%(VX_lm[I][J].real, VX_lm[I][J].imag) + absv[I][J]=abs(VX_lm[I][J]) + print(sbuf,file=fd); + futils.fclose(fd) + if( not pbc ): + os.system("ls -ltrh "+fnme); + if( logger is not None ): + N=len(np.ravel(absv)) + ithTOixj=np.argsort( np.ravel(absv) ) + logger.Info("#Nacm_%d %6d %14.4f %14.4f "%( kp, Istep, tm_au, tm_au*AUinFS),end="") + for ith in range(10): + ixj=ithTOixj[ N-ith-1 ]; + J=ixj%nMO; I=ixj//nMO + logger.Info("%d: %d,%d %9.3e (%8.3f+%8.3fj) "%(ith,I,J,abs(VX_lm[I][J]), + VX_lm[I][J].real,VX_lm[I][J].imag),end="") + logger.Info("") + if( pbc ): + os.system("ls -ltrh "+job+"_???_Nacm.dat") + + +## +## \sum [ occ_n eorb_n C^{\mu}_n d S_{\mu\nu}/dR C^{\nu}_n ] +## note:(i) \nabla E|_{internal} - trCXCe = \nabla E_{GS} +## (ii) trCXCe = trFSXD at t=0 +def calc_trCXCe(this,MOcofs,MOengs,MOocc,fixedAtoms=None): + TINY=1.0e-20 + Nfix=(0 if(fixedAtoms is None) else len(fixedAtoms)) + assert ( RTTDDFT_.is_rttddft(this) ),"this"+str(type(this)) + pbc = this._pbc + kvectors = None if(not pbc) else np.reshape(this.kpts, (-1,3)) + nkpt=(1 if(not pbc) else len(kvectors) ) + nAO =(len(MOcofs) if(not pbc) else len(MOcofs[0])) + Nat = ( len(this.mol._atom) if(not pbc) else len(this.cell._atom)) + Nat_eff= Nat-Nfix + Ndir_eff=Nat_eff*3 + ret_buf=[] + + cell_or_mol = (this.mol if(not pbc) else this.cell) + bfX_al=calc_nacm_AOrep(this,cell_or_mol,pbc,fixedAtoms=fixedAtoms) + ## 2021.03.21 : iterator -dir- moves within [0,3*Nat_eff) + for kp in range(nkpt): + Cofs=( MOcofs if(not pbc) else MOcofs[kp]) + eorb=( MOengs if(not pbc) else MOengs[kp]) + occ =( MOocc if(not pbc) else MOocc[kp] ) + bfX =( bfX_al if(not pbc) else bfX_al[kp]) + nMO = len(occ) + #\sum_a w_a + vec=np.zeros( [Ndir_eff] ) + vec[:]=0.0 + + dSdR=np.zeros([ Ndir_eff,nAO,nAO],dtype=np.complex128) + + for dir in range(Ndir_eff): + for mu in range(nAO): + for nu in range(nAO): + dSdR[dir][mu][nu] = bfX[dir][mu][nu] +np.conj( bfX[dir][nu][mu] ) + + for mo in range(nMO): + if( occ[mo]< TINY ): + continue + for dir in range(Ndir_eff): + vec[dir]+= occ[mo]*eorb[mo] * ( np.vdot(Cofs[:,mo], np.matmul( dSdR[dir],Cofs[:,mo])) ).real + if( not pbc ): + return vec ## non-pbc ends here + else: + ret_buf.append(vec) + assert pbc,"otherwise never come here" + return ret_buf + +# non-pbc : complex128-ndarray[3*Nat,nAO,nAO] +# pbc : complex128-ndarray[nkpt,3*Nat,nAO,nAO] +# +# SCHEME_1 (default) : nmrdiff keeping AO-base density matr +# SCHEME_2 : nmrdiff keeping ORTH_AO-base density matr (i.e. \sqrt{S} \rho_AO \sqrt{S} ) +# +# in SCHEME_2, trFSXD has additional tr[ - S^{-1/2} \nabla Ssqrt \rho H - \rho \nabla Ssqrt S^{-1/2} H ] +# 2021.12.01 :: def calc_trFSXD(pbc,spinrestriction,this,FockMat,DensityMat,SCHEME_2=False,fixedAtoms=None): +def calc_trFSXD(pbc,spinrestriction,this,FockMat,DensityMat,SCHEME_2=None,fixedAtoms=None): + assert SCHEME_2 is not None,"" + Nfixed=( 0 if(fixedAtoms is None) else len(fixedAtoms) ) + # tr[ F(Sinv bfX D + D bfY Sinv) ] ... to be subtracted from dE/dR|_{Dmat-fixed} + assert ( RTTDDFT_.is_rttddft(this) ),"this"+str(type(this)) + ### calc_nacm_.check_scheme( (2 if(SCHEME_2) else 1) ) + mol_or_cell = ( this.mol if(not pbc) else this.cell ) + Nat=len(mol_or_cell._atom) + Nat_eff=Nat-Nfixed + dirALL=[]; + for Iat in range(Nat): + if( fixedAtoms is not None ): + if( Iat in fixedAtoms ): + continue + for J in range(3): + dirALL.append(3*Iat+J) + Ndir_eff=len(dirALL) + ndim_DM=np.shape(DensityMat) ## non PBC:[nAO][nAO] PBC:[nkpt][nAO][nAO] + nmult_DM=(1 if(spinrestriction=='R') else 2) + if( spinrestriction=='R'): + nAO=(ndim_DM[0] if(not pbc) else ndim_DM[1]) + else: + nAO=(ndim_DM[1] if(not pbc) else ndim_DM[2]) + assert ((this.nAO is None) or nAO==this.nAO),"nAO %d %d"%(nAO,this.nAO) + ret=np.zeros([3*Nat_eff]) + for I in range( 3*Nat_eff ): + ret[I]=0.0 + + if( spinrestriction=='O'): + if( not pbc ): + assert hasattr(FockMat,'focka'),"focka" + else: + assert hasattr(FockMat[0],'focka'),"focka" + + this.update_Sinv() + nmult=(1 if(spinrestriction=='R') else 2) + if( not pbc ): + Sinv = this._sINV + bfX=calc_nacm_AOrep(this,this.mol,pbc,fixedAtoms=fixedAtoms) #([nkpt])[3*Nat][nAO][nAO] + + ## dagger w.r. nu,mu + bfY=np.zeros([3*Nat_eff, nAO,nAO],dtype=np.complex128) + for kth_dir in range(3*Nat_eff): + for mu in range(nAO): + for nu in range(nAO): + bfY[kth_dir][mu][nu] =np.conj( bfX[kth_dir][nu][mu] ) + + if( SCHEME_2 ): + nabla_Ssqrt=calc_nabla_Ssqrt( this._Ssqrt, (bfX + bfY)) + + wks=np.zeros( [nAO, nAO], dtype=np.array(this._Ssqrt).dtype ) + + if( SCHEME_2 ): + #assert False,"-- please confirm you are using this option in a consistent manner --" ## please comment out this assertion after confirmation.. + assert (spinrestriction=='R'),"please check below otherwise" + for kth_dir in range(Ndir_eff): ### range(3*Nat): + wks = np.matmul( this._Ssqrt, nabla_Ssqrt[kth_dir] ) + for mu in range(nAO): + for nu in range(nAO): + bfX[ kth_dir ][mu][nu]-=wks[mu][nu] ## S^{1/2}\nabla S^{1/2} + wks = np.matmul( nabla_Ssqrt[ kth_dir ], this._Ssqrt ) + for mu in range(nAO): + for nu in range(nAO): + bfY[ kth_dir ][mu][nu]-=wks[mu][nu] ## \nabla S^{1/2} S^{1/2} + ### in fact these two must cancel each other since orthogonalized S matrix should equal unity.. + dum=bfX + bfY + #print(np.shape(dum)) + #print(np.shape( max( abs(dum)))) + dev=max( abs( np.ravel(dum)) );assert dev<1.0e-6,"bfX_Lowdin + bfY_Lowdin /= 0 :%e"%(dev) + Fockmatrices=FockMat + if( spinrestriction=='O' and hasattr(FockMat,'focka') ): + Fockmatrices=[ FockMat.focka, FockMat.fockb ] + for dir in range(3*Nat_eff): + ret[dir]=0.0 + for sp in range(nmult): + DM=( DensityMat if(nmult==1) else DensityMat[sp] ) + FM=( Fockmatrices if(nmult==1) else Fockmatrices[sp]) + wks=np.matmul( np.matmul(Sinv, bfX[dir]),DM ) +\ + np.matmul( np.matmul( DM, bfY[dir]),Sinv ) + wks=np.matmul( FM, wks) + ## ... and Trace... + csum=np.complex128(0.0) + for mu in range(nAO): + csum+= wks[mu][mu] + ret[dir]+=csum.real + return ret; + else: + assert (not SCHEME_2),"" ## PLS check carefully and comment out this assertion .. + ## do the same thing over k points... + kvectors=np.reshape( this.kpts, (-1,3)) + nkpt=len(kvectors) + if( nmult == 1 ): + assert (ndim_DM[0]==nkpt and ndim_DM[1]==ndim_DM[2]),"ndim_DM:"+str(ndim_DM) + else: + assert (ndim_DM[0]==2 and ndim_DM[1]==nkpt and ndim_DM[2]==ndim_DM[3]),"ndim_DM:"+str(ndim_DM) + bfX_kpts = calc_nacm_AOrep(this,this.cell,pbc,fixedAtoms=fixedAtoms) + for dir in range(3*Nat_eff): + ret[dir]=0.0 + + for kp in range(nkpt): + S1k = this.get_ovlp(this.cell,kvectors[kp]) + Sinv = this._sINV[kp] + bfX = bfX_kpts[kp] + + bfY = np.zeros([3*Nat_eff,nAO,nAO],dtype=np.complex128) + for dir in range(3*Nat_eff): + for mu in range(nAO): + for nu in range(nAO): + bfY[dir][mu][nu] =np.conj( bfX[dir][nu][mu] ) + + FockMatrices_kp=FockMat[kp] + if( spinrestriction=='O' and hasattr(FockMatrices_kp,'focka') ): + FockMatrices_kp=[ FockMatrices_kp.focka, FockMatrices_kp.fockb ] + elif( spinrestriction == 'U'): + FockMatrices_kp=[ FockMat[0][kp], FockMat[1][kp] ] + + for dir in range(3*Nat_eff): + for sp in range(nmult): + DM=(DensityMat[kp] if(nmult==1) else DensityMat[sp][kp]) + FM=(FockMatrices_kp if(nmult==1) else FockMatrices_kp[sp]) + wks=np.matmul( np.matmul(Sinv, bfX[dir]),DM ) +\ + np.matmul( np.matmul( DM, bfY[dir]),Sinv ) + wks=np.matmul( FM, wks) + ## ... and Trace... + csum=np.complex128(0.0) + for mu in range(nAO): + csum+=wks[mu][mu] + ret[dir]+=csum.real ## sum over kpoints + for dir in range(3*Nat_eff): + ret[dir]=ret[dir]/float(nkpt) + return ret; + + +def calcForce(md,rttddft,SCHEME_2, dm_kpts=None, fock_kpts=None, time_AU=None, Decomposition=None, flag_nmrdiff=None, + order_nmdiff=5, displ_nmdiff=0.02, debug=0, dict=None, fixedAtoms=None, force_ref=None, timing=None): + heapcheck(">> calcForce.START") + if( timing is None ): + timing={} + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); + timing.update({"prep":None,"nmdiff":None,"trFSXD":None,"analytic":None}) + print("#calcForce::$%02d:Start fixedAtoms:"%(MPIrank),fixedAtoms,flush=True) + Logger.write(md.logger,"#start calcForce..\n#MD_Rnuc:"+str(md.Rnuc) +"\n#rt_Rnuc:"+ str(rttddft.get_Rnuc('B'))) + cput0=time.time();cput1=cput0 + if time_AU is None: time_AU = md.time_AU + if dm_kpts is None: dm_kpts = md.calc_tdDM(rttddft,ovrd=True) + if(fock_kpts is None): + fock_kpts = md.calc_fock(rttddft,dm=dm_kpts,time_AU=time_AU) + assert ( (md is not None) and isinstance(md,Moldyn) ),"Moldyn" + +# flag_nmrdiff : 0 no / 1 yes, return numeric / 2 yes, return analytic + if( flag_nmrdiff is None ): flag_nmrdiff=(0 if( md.df=="FFTDF" ) else 1) + + ### calc_nacm_.check_scheme( (2 if(SCHEME_2) else 1) ) + + pbc=md.pbc + mol_or_cell = (rttddft.mol if(not pbc) else rttddft.cell) + cput2=cput1;cput1=time.time();timing["prep"]=cput1-cput2 + dbgng_nmgrads = False; gr1A=None + if( md.df=="FFTDF" ): + gr1A_decomposition={}; + if( dbgng_nmgrads ): + nmgrads = numrdiff_matrices( md, rttddft, dmat=dm_kpts, fixedAtoms=fixedAtoms) + cput2=cput1;cput1=time.time();timing["nmdiff"]=cput1-cput2 + gr1A,gr1Anmr=calcGrad_analytic_FFTDF(md,rttddft,dmat=dm_kpts, fixedAtoms=fixedAtoms,nmgrads=nmgrads,decomposition=gr1A_decomposition) + cput2=cput1;cput1=time.time();timing["analytic"]=cput1-cput2 + else: + print("#calcForce::$%02d:start calcGrad_analytic_FFTDF "%(MPIrank)+str(datetime.datetime.now()),flush=True) + gr1A=calcGrad_analytic_FFTDF(md,rttddft,dmat=dm_kpts, fixedAtoms=fixedAtoms,nmgrads=None,decomposition=gr1A_decomposition) + cput2=cput1;cput1=time.time();timing["analytic"]=cput1-cput2 + print("#calcForce::$%02d:end calcGrad_analytic_FFTDF "%(MPIrank)+str(datetime.datetime.now()),flush=True) + if( fixedAtoms is not None ): + spdm=3 + Nat=md.Nat; wks=np.zeros([ spdm*Nat ],dtype=np.float64) + IxJ=0 + for I in range(Nat): + if( I in fixedAtoms ): + continue + for J in range(spdm): + wks[ spdm*I + J ]=gr1A[ IxJ + J ] + IxJ+=spdm + assert IxJ==len(gr1A),"%d / %d"%(IxJ,len(gr1A)) + gr1A = wks + + if( flag_nmrdiff == 0 ): + print("#calcForce:analytic::$%02d:END"%(MPIrank), cput1-cput2, cput1-cput0) + heapcheck(">> calcForce.END") + return -gr1A +## XXX XXX sorry, this does NOT equal to numdiff ... gr1A=calcGrad_analytic(md,rttddft,dmat=dm_kpts) +## XXX XXX cput2=cput1;cput1=time.time();timing["analytic"]=cput1-cput2 + + print("#calcForce::$%02d:Start calcgrad_nmdiff"%(MPIrank), cput1-cput2, cput1-cput0) + gr1_ref={} + gr1=calcgrad_nmdiff(md, rttddft,dmat=dm_kpts,order=order_nmdiff, SCHEME_2=SCHEME_2, + displ=displ_nmdiff, fixedAtoms=fixedAtoms,grad_ref=gr1_ref) + cput2=cput1;cput1=time.time();timing["nmdiff"]=cput1-cput2 + print("#calcForce::$%02d:End calcgrad_nmdiff"%(MPIrank),cput1-cput2, cput1-cput0) + +# gr1A=calcGrad_analytic(md,rttddft,dmat=dm_kpts) +# cput2=cput1;cput1=time.time();timing["analytic"]=cput1-cput2 +# dev=max( abs(gr1A-gr1) ) +# printout("analyticgrad:dev=%e walltime:%f / %f"%(dev,timing["analytic"],timing["nmdiff"]),\ +# fpath="calcNacm_analyticgrad.log"); + if( Decomposition is not None): + Decomposition.update({"F1":arrayclonex(gr1,-1)}) + + gr2=calc_trFSXD(md.pbc, md.spinrestriction, rttddft,fock_kpts,dm_kpts, fixedAtoms=fixedAtoms, SCHEME_2=SCHEME_2) ## should we store those matrices ?? + if( Decomposition is not None): + Decomposition.update({"F2":arrayclone(gr2)}) + cput2=cput1;cput1=time.time();timing["trFSXD"]=cput1-cput2 + Logger.write(md.logger,"calcForce:"+str(timing)) + print("#calcForce::$%02d:End trFSXD"%(MPIrank), cput1-cput2, cput1-cput0) + + logfpath="calcForce_walltime_%02d.log"%(MPIrank) + fdOU=open(logfpath,"a") + print("#Force:$%02d:%14.4f "%( MPIrank,cput1-cput0)+("" if(Decomposition is None) else str(Decomposition)) \ + +" \t\t"+str(datetime.datetime.now()), file=fdOU) + fdOU.close() + + if( debug>0 and md.spinrestriction=='R' and (not md.pbc) and fixedAtoms is None): + if( (md._canonicalMOs is not None) and (md._canonicalEorbs is not None) ): + gr2b=calc_trCXCe( rttddft, md._canonicalMOs, md._canonicalEorbs, md.mo_occ) + eorbs=calc_eorbs( md.tdMO, md.calc_fock(rttddft) ) + gr2c=calc_trCXCe( rttddft, md.tdMO, eorbs, md.mo_occ ) + if( dict is not None ): + dict["diff_gr2c"]=d1diff(gr2c,gr2); + dict["diff_gr2"]=d1diff(gr2b,gr2);dict["Frc_gr2"]=gr1-gr2b + if( debug>1 ): + print("grad_EGND:",end="");print(gr1-gr2b) + aNtofile('S',"grad_EGND.tmpdat",dbuf=gr1-gr2b) + print("#gr1:",end="");print(gr1) + print("#gr2:",end="");print(gr2) #gr2: [ 5.21810413e-05 3.51999785e-01 1.75021151e-14 -2.03708274e-01 + print("#gr2b:",end="");print(gr2b) #gr2b:[ 5.21851825e-05 3.51999740e-01 1.35953869e-15 -2.03708634e-01 + #for I in range(len(gr1)): + # gr1[I] -= gr2b[I] + #for I in range(len(gr1)): + # gr1[I] = -gr1[I] + #return gr1 + cput2=cput1; cput1=time.time(); + print("#calcForce::$%02d:XXX DEBUG"%(MPIrank), cput1-cput2, cput1-cput0) + + + for I in range(len(gr1)): + gr1[I] -= gr2[I] + + if( force_ref is not None ): + for ky in gr1_ref: + for I in range(len(gr1_ref[ky])): + gr1_ref[ky][I] -= gr2[I] ## gr1-gr2 + for I in range(len(gr1_ref[ky])): + gr1_ref[ky][I] = -gr1_ref[ky][I] ## grad->Force + force_ref.update( {ky:gr1_ref[ky]} ); + ## now we obtained an EFFECTIVE grad ... + ## F = - GRAD + for I in range(len(gr1)): + gr1[I] = -gr1[I] + +# print("#calcForce::",gr1) + print("#calcForce:numdiff::$%02d:END"%(MPIrank), cput1-cput2, cput1-cput0) + if( gr1A is not None ): + frc1A = -gr1A + diff=max( abs( np.ravel(frc1A) - np.ravel(gr1) ) ) + print("#calcForce:comp_numdiff_to_analytic:%e "+str(gr1)+"/"+str(frc1A)) + return (gr1 if(flag_nmrdiff==1) else frc1A) + return gr1 + +#0 Li 0.2391259237 -0.0000000000 -0.0000000000 +#1 H -0.2391259237 -0.0000000000 -0.0000000000 +#calcForce:: [-2.39178948e-01 3.21501437e-13 -1.33673763e-13 +#2.39170116e-01 8.31081388e-13 2.59211751e-13] +#analyticGrad: [-5.03771029e-01 1.59390934e-11 -4.85982241e-12 5.03762197e-01 +# -1.61894379e-11 4.49591261e-12] +#analyticGradB: [-2.53758794e-01 1.13824975e-11 -3.43626669e-12 2.53749962e-01 +# -1.22217578e-11 3.05044382e-12] + +# returns grad[3*Nat] float ndArray newly allocated +def calcgrad_nmdiff_singlethread(md,rttddft,dmat=None,order=3,displ=0.02,debug=False,SCHEME_2=None,fixedAtoms=None,grad_ref=None): + ## dbgng_Eel=False ## + assert SCHEME_2 is not None,"" + Nfixed=( 0 if(fixedAtoms is None) else len(fixedAtoms) ) + cput00=time.time();cput1=cput00 + if dmat is None: dmat = md.calc_tdDM(rttddft) + ### calc_nacm_.check_scheme( (2 if(SCHEME_2) else 1) ) + dm_orth=( None if(not SCHEME_2) else convert_dm_AO_to_Orth( rttddft._Ssqrt, dmat, rttddft._pbc, rttddft._spinrestriction ) ) + dm_AOrep=( None if(SCHEME_2) else arrayclone(dmat) ) + + assert isinstance(md,Moldyn),"moldyn" + assert ( RTTDDFT_.is_rttddft(rttddft) ),"rttddft"+str(type(rttddft)) + pbc = md.pbc; Nat=md.Nat + hfo=order//2 +# _atm: [[ 8 20 1 23 0 0] [ 1 24 1 27 0 0] [ 1 28 1 31 0 0]] # pointer addresses +# _atom:[('O', [4.7940462054091055, -0.29290754930758456, 0.0]), ('H', [5.808829134300543, 0.29290754930758456, 0.0]), ('H', [3.7794522491301237, 0.29290754930758456, 0.0])] + Nat_eff=Nat-Nfixed + grad = np.zeros([3*(Nat-Nfixed)]) + Rnuc_o = np.zeros([Nat,3]); + Rref=rttddft.get_Rnuc('B') ## in a.u. + ## if( not pbc ): + ## Rref=rttddft.mol.atom_coords() + ## else: + ## Rref=rttddft.cell.atom_coords() + if(md.Rnuc is None): + print("#setting Rnuc..");md.Rnuc=arrayclone(Rref) + Rdev = d1maxdiff( np.ravel(Rref), np.ravel(md.Rnuc) ) + assert (Rdev<1.0e-6),"rttddft.R differs from md.Rnuc ..."+str(Rref)+"/"+str(md.Rnuc) + for Iat in range(Nat): + for Jdir in range(3): + Rnuc_o[Iat][Jdir]=Rref[Iat][Jdir] + R_wrk=np.zeros([Nat,3],dtype=np.float64) + for Iat in range(Nat): + for Jdir in range(3): + R_wrk[Iat][Jdir]=Rnuc_o[Iat][Jdir] +## +## Here we evaluate Energy derivative due to Rnuc difference but NOT related to density matrix change +## + if( grad_ref is None ): + grad_ref=(None if(order<=3) else {}) + else: + grad_ref.clear(); + if( order == 5 ): + grad_ref.update( {"5p":np.zeros([Nat_eff,3]),"3p":np.zeros([Nat_eff,3])} ) + elif( order==7 ): + grad_ref.update( {"7p":np.zeros([Nat_eff,3]),"5p":np.zeros([Nat_eff,3]),"3p":np.zeros([Nat_eff,3])}) + + +## grad_ref=( None if(order<=3) else (\ +## {"5p":np.zeros([Nat_eff,3]),"3p":np.zeros([Nat_eff,3])} if(order<=5) else \ +## {"7p":np.zeros([Nat_eff,3]),"5p":np.zeros([Nat_eff,3]),"3p":np.zeros([Nat_eff,3])}) ) + IJ=0; Iat_eff=-1 + for Iat in range(Nat): + if( fixedAtoms is not None ): + if( Iat in fixedAtoms ): + continue + Iat_eff+=1 + for Jdir in range(3): + Earr=[] + for step in range(-hfo,hfo+1): + if( step==0 ): + Earr.append(None);continue + calc=md.update_Rnuc( IandJ=[Iat,Jdir],coordinate=Rnuc_o[Iat][Jdir]+ step*displ, update_moldyn=False) + R_wrk[Iat][Jdir]=Rnuc_o[Iat][Jdir]+ step*displ + ## print("#%02d,%02d : %12.6f -> %12.6f"%(Iat,Jdir,Rnuc_o[Iat][Jdir],Rnuc_o[Iat][Jdir]+step*displ)) + E_nuc= calc.energy_nuc(Rnuc_au=R_wrk); + if( SCHEME_2 ): + calc.update_Sinv() + dm_AOrep= convert_dm_Orth_to_AO( calc._Sinvrt, dm_orth, calc._pbc, calc._spinrestriction) + + assert abs( calc._time_AU-md.time_AU)<1.0e-7,"time_AU:%f/%f"%(calc._time_AU,md.time_AU) + + h1e_new=calc.get_hcore() ## this potentially depends on : calc._time_AU + vhf_new=calc.get_veff(dm=dm_AOrep) ## rttddft(MOL/PBC) takes "dm" as input +# energy_elec_rks(this, dm=None, h1e=None, vhf=None, verbose=False): +# energy_elec_krks(this, dm_kpts=None, h1e_kpts=None, vhf=None,verbose=False): + E_el = ( calc.energy_elec( dm=dm_AOrep, h1e=h1e_new, vhf=vhf_new )[0] if(not pbc) else \ + calc.energy_elec( dm_kpts=dm_AOrep, h1e_kpts=h1e_new, vhf=vhf_new ) [0] ) + + ## if(dbgng_Eel): + ## trH1xDM=calc_dAOtrace(md,rttddft,dm_AOrep,h1e_new) + ## vCoul=vhf_new.ecoul + ## vXC=vhf_new.exc + ## ref=(trH1xDM + vCoul + vXC);assert abs(E_el-ref)<1e-6,"" + + cput2=cput1;cput1=time.time() + ## h1e, vhf are left default + # print("E_nuc:",end="");print(E_nuc) + # print("E_el:",end="");print(E_el) + E_tot= E_el + E_nuc + if( cput1-cput2>100): + print("#calcgrad_nmdiff:%d.%d. %d %f %f elapsed:%10.2f %10.2f"%(Iat,Jdir,step,step*displ,E_tot,cput1-cput2,cput1-cput00)) + if( debug ): + assert False,"dbg" + calc._fix_occ=False + E_gnd=calc.calc_gs() + Earr.append( np.array( [E_tot,E_el,E_nuc,E_gnd] )) + else: + Earr.append( np.array( [E_tot,E_el,E_nuc] )) + R_wrk[Iat][Jdir]=Rnuc_o[Iat][Jdir] + dict={"7p":None,"5p":None,"3p":None} + dNp = nmrdff( order,Earr,len(Earr[0]),displ,dict=dict) + grad[ Iat_eff*3+Jdir ]=dNp[0] + if( debug ): + print("Egnd_grad:%d %f %f %f %f"%(Iat_eff*3+Jdir,dNp[3],dict["7p"][3],dict["5p"][3],dict["3p"][3]) ) + if( order>3 ): + grad_ref["3p"][Iat_eff][Jdir]=dict["3p"][0]; + grad_ref["5p"][Iat_eff][Jdir]=dict["5p"][0]; + if( order>5 ): + grad_ref["7p"][Iat_eff][Jdir]=dict["7p"][0]; + if( order > 5 ): + dev75=aNsqrediff( grad_ref["7p"], grad_ref["5p"]) + dev73=aNsqrediff( grad_ref["7p"], grad_ref["3p"]) + dev53=aNsqrediff( grad_ref["5p"], grad_ref["3p"]) + + print("#grad_dev:h=%e 7-5:%e 5-3:%e 7-3:%e"%(\ + displ, math.sqrt(dev75), math.sqrt(dev53), math.sqrt(dev73) )) + elif( order>3): + dev53=aNsqrediff( grad_ref["5p"], grad_ref["3p"]) + print("#grad_dev:h=%e 5-3:%e"%(displ, math.sqrt(dev53))) + assert Iat_eff+1==Nat_eff,"Iat_eff+1:%d / Nat_eff=%d"%(Iat_eff+1,Nat_eff) + + cput1=time.time() + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); + logfpath="calcForce_walltime_%02d.log"%(MPIrank) + fdOU=open(logfpath,"a") + print("## calcgrad_nmdiff_singlethread:$%02d:%14.4f "%(MPIrank,cput1-cput00) + +" \t\t"+str(datetime.datetime.now()), file=fdOU) + fdOU.close() + + return grad + + +""" +mole.py L308: + ._atom contains [[atom1, (x, y, z)],... + if you cannot find it, you can invoke .format_atom(self.atom, unit=self.unit) +mole.py L387: + ._basis {'H': [[0, + [3.4252509099999999, 0.15432897000000001], + [0.62391373000000006, 0.53532813999999995], + [0.16885539999999999, 0.44463454000000002]]], etc. + +_bas.append([atom_id, angl, nprim, nctr, kappa, ptr_exp, ptr_coeff, 0]) +""" +# mu_to_iat:[0 0 0 0 0 0 0 0 0 1 1 2 2] + +def calc_nabla_Ssqrt(Ssqrt,dSdR): + # dSdR[3*Nat][nAO][nAO] + # Ssqrt X + X Ssqrt = dSdR + Nx3=len(dSdR) + Ndim=np.shape(dSdR) + ret=[] + for dir in range(Nx3): + ret.append( linalg.solve_sylvester( Ssqrt, Ssqrt, dSdR[dir]) ) + dbgng=True + if(dbgng): + devs=[] + for dir in range(Nx3): + wrk=np.matmul( Ssqrt, ret[dir]) + np.matmul( ret[dir], Ssqrt) + devs.append( z2diff( wrk, dSdR[dir]) ) + assert( max(devs)<1.0e-5),"" + fd1=open("solve_Sylvester.log","w") + print("#maxdev:%e"%(max(devs))+str(devs),file=fd1); + for dir in [0,1,Nx3-1]: + Nd=np.shape(ret[dir]) + for i in range(Nd[0]): + for j in range(Nd[1]): + print("%12.6f "%(ret[dir][i][j]),end="",file=fd1) + fd1.close() + Logger.write_maxv(None,"nabla_Ssqrt_dev",max(devs)) + print("#nabla_Ssqrt:devs:",end="");print(devs) + return ret + + +## +## -i Vdot_nacm_eff should be Hermitian +## +## 2020.11.28 revision : you do not need MD for this calculation +def calc_Vdot_nacm_eff(this,Vnuc_1d, Nacm_rep, check_antihermicity=True): + ## TODO : this could be replaced by some tensor_product routine + assert (Nacm_rep=='A' or Nacm_rep=='O'),"" + Ndir=len(Vnuc_1d) + assert ( RTTDDFT_.is_rttddft(this) ),"this"+str(type(this)) + pbc = this._pbc + mol_or_cell = (this.mol if(not pbc) else this.cell) + bfX_al = calc_nacm_eff(this,mol_or_cell,Nacm_rep) # nkpt Ndir nAO nAO + ndim=np.shape(bfX_al) + nkpt=(1 if(not pbc) else ndim[0]) + nAO=ndim[2] + if( pbc ): + assert (nAO==ndim[3]),"" + ret=np.zeros([nkpt,nAO,nAO],dtype=np.complex128) + for kp in range(nkpt): + for I in range(nAO): + for J in range(nAO): + dir=0 + ret[kp][I][J]=bfX_al[kp][dir][I][J]*Vnuc_1d[dir] + for dir in range(1,Ndir): + ret[kp][I][J]+=bfX_al[kp][dir][I][J]*Vnuc_1d[dir] + + else: + assert (nAO==ndim[1]),"" + ret=np.zeros([nAO,nAO],dtype=np.complex128) + for I in range(nAO): + for J in range(nAO): + dir=0 + ret[I][J]=bfX_al[dir][I][J]*Vnuc_1d[dir] + for dir in range(1,Ndir): + ret[I][J]+=bfX_al[dir][I][J]*Vnuc_1d[dir] + + if( check_antihermicity ): + # Note: S^{-1/2}[ \bfX - S^{1/2}\nabla S^{1/2} ] S^{-1/2} + # + S^{-1/2}[ \bfX^{\dagger} - \nabla S^{1/2} S^{1/2} ] S^{-1/2} + # = S^{-1/2}[ \nabla S - \nabla S ] S^{-1/2} = 0 + # + dict={"devsum":None,"dagdev":None,"ofddev":None,"dagAt":None,"ofdAt":None} + if( not pbc ): + ok=check_Hermicity(-1,ret,dict) + assert ok,"antiHermicity" + return ret + +# dict={"devsum":None,"dagdev":None,"ofddev":None,"dagAt":None,"ofdAt":None} +def check_Hermicity(type,A,dict=None,TOL=1.0e-6,ERR=None): + ## + ## dev : h[\mu][\nu] - ( - np.conj(h[\nu][\mu]) ) + ## diag : Re(h[\mu][\mu]) + ## ofd : ... + ## + Ndim=np.shape(A) + assert Ndim[0]==Ndim[1],"" + dagdev=-1;dagAt=-1; dag_as=0; + ofddev=-1;ofdAt=[-1,-1];ofd_as=None; + devsum=0.0 + if( type == 1 ): + for I in range(Ndim[0]): + for J in range(I+1): + if(I==J): + dev=abs(A[I][J].imag); devsum+=dev**2 + if( dev>dagdev ): + dagdev=dev;dagAt=I;dag_as=A[I][J] + else: + dev=abs(A[I][J] - np.conj( A[J][I] )); devsum+=dev**2 + if( dev>ofddev ): + ofddev=dev; ofdAt=[I,J]; ofd_as=[ A[I][J], A[J][I]] + elif( type == -1): + for I in range(Ndim[0]): + for J in range(I+1): + if(I==J): + dev=abs(A[I][J].real); devsum+=dev**2 + if( dev>dagdev ): + dagdev=dev;dagAt=I;dag_as=A[I][J] + else: + dev=abs(A[I][J] + np.conj( A[J][I] )); devsum+=dev**2 + if( dev>ofddev ): + ofddev=dev; ofdAt=[I,J]; ofd_as=[ A[I][J], A[J][I]] + else: + assert False,"wrong input" + if( dict is not None ): + for ky in dict: + if( ky=="devsum"): + dict[ky]=devsum + if( ky=="dagdev"): + dict[ky]=dagdev + if( ky=="ofddev"): + dict[ky]=ofddev + if( ky=="dagAt"): + dict[ky]=dagAt + if( ky=="ofdAt"): + dict[ky]=ofdAt + dev=np.sqrt(devsum) + retv = True + if( dev > TOL or dagdev>TOL or ofddev>TOL): + print("#check_Hermicity:dagdev:%e ([%d][%d]:%f+j%f)"%(dagdev,dagAt,dagAt,dag_as.real,dag_as.imag)+\ + "ofddev:%e [%d][%d] %f+j%f vs %f+j%f"%(ofddev,ofdAt[0],ofdAt[1],ofd_as[0].real,ofd_as[0].imag,\ + ofd_as[1].real,ofd_as[1].imag)) + retv=False + if( ERR is not None ): + if( dev > ERR or dagdev>ERR or ofddev>ERR): + assert False,"check_andihermicity" + return retv + +## 2020.11.28 revision : you do not need MD for this calculation +def calc_nacm_eff(this,mol_or_cell,Nacm_rep,fixedAtoms=None,SCHEME_2=True): + # this : rttddft object + dbgng=False; bfX_AOrep=None + assert (Nacm_rep=='A' or Nacm_rep=='O'),"" + pbc = this._pbc + kvectors=None + if( pbc ): + kvectors=np.reshape( this.kpts, (-1,3)) + ### calc_nacm_.check_scheme( (2 if(SCHEME_2) else 1) ) + nkpt=( 1 if(not pbc) else len(kvectors)) + Nat=len( mol_or_cell._atom) + + dirALL=[];Nat_eff=( Nat if(fixedAtoms is None) else Nat-len(fixedAtoms)) + for Iat in range(Nat): + if( fixedAtoms is not None ): + if( Iat in fixedAtoms ): + continue + for J in range(3): + dirALL.append(3*Iat+J) + N_dir=len(dirALL) + # d/dt ( Ssqrt C ) = S^{-1/2} [ H - i\hbar \dot{\bfR} [ \bfX - \sqrt{S}\nabla[\sqrt{S}] ] ]S^{-1/2} Ssqrt C + assert ( RTTDDFT_.is_rttddft(this) ),"this"+str(type(this)) + # [N_dir][nAO][nAO]/[nkpt][N_dir][nAO][nAO] + bfX_al=calc_nacm_AOrep(this,mol_or_cell,pbc,fixedAtoms=fixedAtoms,dtype=np.complex128) + + if(dbgng): + bfX_AOrep=arrayclone(bfX_al) + if(not pbc): + print_z3tensor("calcNacm.log",False,bfX_AOrep,description="Nacm,AOrep") + else: + print_z3tensor("calcNacm.log",False,bfX_AOrep[0],description="Nacm,AOrep") + ## we here subtract Ssqrt nabla_Ssqrt + ## S^{-1/2} this S^{-1/2} = nabla_Ssqrt S^{-1/2} + if( Nacm_rep=='O'): + bfY_al=(None if(not pbc) else []) + nkp=(1 if(not pbc) else len(kvectors)) + for kp in range(nkp): + bfX=(bfX_al if(not pbc) else bfX_al[kp]) + ndim=np.shape(bfX) + bfY=np.zeros(np.shape(bfX),dtype=np.complex128) + for jth_dir in range(N_dir): + dir=dirALL[jth_dir] + for mu in range( ndim[1] ): + for nu in range( ndim[2] ): + bfY[ jth_dir ][mu][nu] =np.conj( bfX[ jth_dir ][nu][mu] ) + Ssqrt=(this._Ssqrt if(not pbc) else this._Ssqrt[kp]) + nabla_Ssqrt = calc_nabla_Ssqrt(Ssqrt, bfX + bfY) ## this expects [Ndir][nAO][nAO] tensors + if(dbgng and kp==0): + print_z3tensor("calcNacm.log",True,np.array([ np.matmul( Ssqrt[dir], nabla_Ssqrt[dir]) for dir in range(3*Nat_eff) ]), + description="S^{-1/2}\nabla S^{1/2}") + assert isinstance(bfX[dir],np.ndarray),"" + for jth_dir in range(N_dir): + dir=dirALL[ jth_dir] + bfX[ jth_dir] -= np.matmul( Ssqrt, nabla_Ssqrt[ jth_dir]) + + if(dbgng and kp==0): + print_z3tensor("calcNacm.log",True, bfX, description="bfX_AOrep - S^{-1/2}\nabla S^{1/2}") + +## ??? Ndim_X=np.shape(bfX_al) ##[nkpt][Ndir][nAO][nAO] +## ??? N_xyz=( Ndim_X[0] if(not pbc) else Ndim_X[1] ) +## ??? assert N_xyz == len(dirALL),"%d / %d"%(N_xyz,dirALL) +## ??? # returns [ nkpt ] [ Nat*3 ] [ nAO ] [ nAO ] +## ??? this.update_Sinv() +## ??? dSdR_wrk=None +## ??? +## ??? for kp in range(nkpt): +## ??? S1e=(this.get_ovlp() if(not pbc) else this.get_ovlp(this.cell,kvectors[kp])) +## ??? ### Ssqrt,Sinvrt = get_Ssqrt_invsqrt_1(S1e) +## ??? bfX =(bfX_al if(not pbc) else bfX_al[kp]) # [Nx3][nAO][nAO] +## ??? Ndim_bfX=np.shape(bfX) +## ??? if( dSdR_wrk is None ): +## ??? dSdR_wrk=np.zeros( Ndim_bfX,dtype=np.complex128 ) +## ??? for I in range(Ndim_bfX[0]): +## ??? for J in range(Ndim_bfX[1]): +## ??? for K in range(Ndim_bfX[2]): +## ??? dSdR_wrk[I][J][K] = bfX[I][J][K] + np.conj( bfX[I][K][J] ) +## ??? # _Ssqrt[nkpt][nAO][nAO] +## ??? nabla_Ssqrt = calc_nabla_Ssqrt( (this._Ssqrt if(not pbc) else this._Ssqrt[kp]), dSdR_wrk ) +## ??? ### print("this._Ssqrt:",end="");print( np.shape(this._Ssqrt) ) #[nkpt][nAO][nAO] +## ??? ### print("nabla_Ssqrt:",end="");print( np.shape(nabla_Ssqrt[0]) ) #[nAO][nAO] +## ??? ith_dir=-1 +## ??? for dir_o in dirALL: ### range(Ndim_bfX[0]): +## ??? ith_dir+=1 +## ??? SxDS=np.matmul( (this._Ssqrt if(not pbc) else this._Ssqrt[kp]), nabla_Ssqrt[dir_o] ) +## ??? ### print("SxDS:",end="");print(np.shape(SxDS)) +## ??? if( not pbc ): +## ??? for J in range(Ndim_bfX[1]): +## ??? for K in range(Ndim_bfX[2]): +## ??? bfX_al[ ith_dir ][J][K]-= SxDS[J][K] +## ??? else: +## ??? for J in range(Ndim_bfX[1]): +## ??? for K in range(Ndim_bfX[2]): +## ??? bfX_al[kp][ ith_dir ][J][K]-= SxDS[J][K] + return bfX_al + +class calc_nacm_: + N_calcgrad_nmdiff=0 + N_call=0 + ##scheme_=None + scheme_=2; + @staticmethod + def check_scheme(scheme): + if( calc_nacm_.scheme_ is None ): + calc_nacm_.scheme_=scheme; + log="scheme:%d"%(scheme); + fd=futils.fopen("calcNacm.log","w"); print(log,file=fd);print(log);futils.fclose(fd); + else: + assert ( calc_nacm_.scheme_ == scheme ),"contradicting scheme"; + +## returns [ nkpt ] [ Nat_eff*3 ] [ nAO ] [ nAO ] +## X= <\mu | \Nabla | \nu> +## Y= <(\Nabla \mu) | \nu> = X^{\dagger} +## dS/dR = X + X^{\dagger} +## +## 2020.11.28 revision : you do not need MD for this calculation +## 2021.12.03 renamed for clarity : calc_nacm -> calc_nacm_AOrep +def calc_nacm_AOrep(rttddft,mol_or_cell,pbc, fixedAtoms=None, dtype=None): + # comp=3 3 component / hermi=2 anti-Hermitian / aosym,out IRRELEVANT for 1e-integ + assert (mol_or_cell is not None),"mol_or_cell" + calc_nacm_.N_call +=1 + if(dtype is None): + dtype=(np.complex128 if(pbc) else np.float64) + + Nat=len(mol_or_cell._atom) + elgrad_kptOR1=None + if( not pbc ): + elgrad_kptOR1 = rttddft.mol.intor('int1e_ipovlp', comp=3, hermi=2) + # --- result is np.float64 -- + # assert (isinstance(elgrad_kptOR1[0][0][0],np.complex128)),"float??:"+str(type(elgrad_kptOR1[0][0][0])) + # dtype1 = type( elgrad_kptOR1[0][0][0] ) + dtype1 = np.array( elgrad_kptOR1 ).dtype ## this does not distinguish btw float and np.float64 + assert (dtype1==float or dtype1==np.float64),"non-pbc mole-intor dtype1"+str(dtype1) + else: + kvectors=np.reshape( rttddft.kpts, (-1,3)) + nkpt=len(kvectors) + elgrad_kptOR1= rttddft.cell.pbc_intor('int1e_ipovlp',comp=3, hermi=2, kpts=kvectors) + dtype1 = type( elgrad_kptOR1[0][0][0][0] ) + if( dtype1==complex or dtype1==np.complex128 ): + dtype=np.complex128 + ## Note form is [ nkpt ] [ 3 ] [ nAO ] [ nAO ] + ## assert (dtype1==complex or dtype1==np.complex128 ),"pbc cell-intor dtype1"+str(dtype1) in fact the result is REAL for k=0 + + ndim_egrad = np.shape( elgrad_kptOR1 ) #[3][nAO][nAO] or [nkpt][3][nAO][nAO] + bfX_al=None + Nfixed=(0 if(fixedAtoms is None) else len(fixedAtoms)); Nat_eff=Nat-Nfixed + if( not pbc ): + assert (len(ndim_egrad)==3 and ndim_egrad[0]==3 and ndim_egrad[1]==ndim_egrad[2]),"" + nkpt = 1; nAO=ndim_egrad[1] + bfX_al = np.zeros( [3*Nat_eff, nAO,nAO],dtype=dtype) + else: + assert (len(ndim_egrad)==4 and ndim_egrad[1]==3 and ndim_egrad[2]==ndim_egrad[3]),"" + nkpt = ndim_egrad[0]; nAO = ndim_egrad[2] + bfX_al = np.zeros( [nkpt,3*Nat_eff, nAO,nAO],dtype=dtype) + + Ia_effXjd=0 + mu_to_iat = get_mu_to_iat(rttddft, (rttddft.cell if(pbc) else rttddft.mol) ) + assert len(mu_to_iat)==nAO,"wrong dim:mu_to_iat" + if( calc_nacm_.N_call == 1 ): + print("mu_to_iat:",end="");print(mu_to_iat) + + sgn_int1e_ipovlp=Constants.sgn_int1e_ipovlp ### + + for kp in range(nkpt): + elgrad=( elgrad_kptOR1 if(not pbc) else elgrad_kptOR1[kp] ) + Ia_eff=-1 + for Ia in range(Nat): + if( fixedAtoms is not None ): + if(Ia in fixedAtoms): + continue + Ia_eff+=1 + for jd in range(3): + Ia_effXjd=3*Ia_eff + jd + # < \mu | del_{Ixj} | \nu > = 0 if( \nu does not belong to atom_I ) + # = - <\mu|del_j|\nu> if( \nu belong to atom_I ) + for mu in range(nAO): + for nu in range(nAO): + val = ( (- sgn_int1e_ipovlp*elgrad[jd][mu][nu]) if(mu_to_iat[nu]==Ia) else 0.0 ) + if(not pbc): + bfX_al[ Ia_effXjd ][mu][nu] = val + else: + ### print( "bfX_al:%d,%d,%d,%d / %d (%d)"%( kp,Ia_effXjd,mu,nu,nkpt,len(bfX_al) ) ) + bfX_al[kp][ Ia_effXjd ][mu][nu] = val + return bfX_al; + +def calc_EgsGRAD_nmdiff(md,rttddft,order=5,displ=0.02,fixedAtoms=None): + grad,grad_ref=calc_EgsGRAD_nmdiff_(md,rttddft,order=order,displ=displ,fixedAtoms=fixedAtoms) + dev_uplm=max( abs(np.array(grad)-np.array(grad_ref)) ) + return grad; + +def calc_EgsGRAD_nmdiff_(md,rttddft,order=5,displ=0.02,fixedAtoms=None): + hfo=order//2 + ## here we simply numdiff GS energy.. + Rnuc_o = arrayclone( rttddft.get_Rnuc('B') );Nat=len(Rnuc_o) + wt0=time.time();wt1=wt0 + Ret=[];Ret_ref=(None if(order==3) else []) + IJ=0; Iat_eff=-1 + for Iat in range(Nat): + if( fixedAtoms is not None ): + if( Iat in fixedAtoms ): + continue + Iat_eff+=1 + for Jdir in range(3): + Earr=[] + for step in range(-hfo,hfo+1): + if( step==0 ): + Earr.append(None);continue + calc=md.update_Rnuc( IandJ=[Iat,Jdir],coordinate=Rnuc_o[Iat][Jdir]+ step*displ, update_moldyn=False) + calc._fix_occ=False + E_gs=calc.calc_gs() + Earr.append(E_gs) + wt2=wt1;wt1=time.time(); + if(IJ==0): + print("#calc_EgsGRAD_nmdiff:single step:%f"%(wt1-wt2)) + Dic={"7p":None,"5p":None,"3p":None} + dNp = nmrdff( order, Earr, 0, displ,dict=Dic) + + Ret.append(dNp); + if(order==7): + Ret_ref.append(Dic["5p"]) + elif(order==5): + Ret_ref.append(Dic["3p"]) + return Ret,Ret_ref + +def calc_EgsGRAD_hfnm(md,rttddft,order=5,displ=0.02,fixedAtoms=None,ForceDecomposition=None, use_trFSXD=True): + pbc=md.pbc + GSdm=(None if(not pbc) else []) + nkpt=(1 if(not pbc) else rttddft.nkpt) + nAO =rttddft.nAO; nMO=rttddft.nMO + iscomplexGSDM = ( False if(not pbc) else True ) + dtype_GSDM=(np.float64 if(not iscomplexGSDM) else np.complex128) + for kp in range(nkpt): + dm1=np.zeros([nAO,nAO],dtype=dtype_GSDM) + canonicalMOs=( md._canonicalMOs if(not pbc) else md._canonicalMOs[kp] ) + occ =( rttddft._mo_occ if(not pbc) else rttddft._mo_occ[kp] ) + for i in range(nMO): + for mu in range(nAO): + for nu in range(nAO): + if( iscomplexGSDM ): + dm1[mu][nu] += canonicalMOs[mu][i]* occ[i] * np.conj( canonicalMOs[nu][i] ) + else: + dm1[mu][nu] += canonicalMOs[mu][i]* occ[i] * canonicalMOs[nu][i] + if( pbc ): + GSdm.append(dm1) + else: + GSdm=dm1;break + + hfo=order//2 + ## here we simply numdiff GS energy.. + Rnuc_o = arrayclone( rttddft.get_Rnuc('B') );Nat=len(Rnuc_o) + wt0=time.time();wt1=wt0 + Gr1=[];Gr1_ref=(None if(order==3) else []) + IJ=0; Iat_eff=-1 + for Iat in range(Nat): + if( fixedAtoms is not None ): + if( Iat in fixedAtoms ): + continue + Iat_eff+=1 + for Jdir in range(3): + Earr=[] + for step in range(-hfo,hfo+1): + if( step==0 ): + Earr.append(None);continue + calc=md.update_Rnuc( IandJ=[Iat,Jdir],coordinate=Rnuc_o[Iat][Jdir]+ step*displ, update_moldyn=False) + E_nuc= calc.energy_nuc(); + E_el = ( calc.energy_elec( dm=GSdm )[0] if(not pbc) else \ + calc.energy_elec( dm_kpts=GSdm ) [0] ) + E_tot= E_el + E_nuc + Earr.append(E_tot) + Dic={"7p":None,"5p":None,"3p":None} + dNp = nmrdff( order,Earr, 0, displ, dict=Dic ) + Gr1.append( dNp ); + if(order==7): + Gr1_ref.append(Dic["5p"]) + elif(order==5): + Gr1_ref.append(Dic["3p"]) + if(ForceDecomposition is not None): + ForceDecomposition.update({"F1":arrayclonex(Gr1,-1)}) + + ## construct DM ... GSdm + if( use_trFSXD ): + fock_kpts = md.calc_fock(rttddft,dm=GSdm,time_AU=md.time_AU) + Gr2=calc_trFSXD( md.pbc, md.spinrestriction, rttddft,fock_kpts,GSdm, fixedAtoms=fixedAtoms, SCHEME_2=False) + else: + Gr2=calc_trCXCe( rttddft, md._canonicalMOs, md._canonicalEorbs, rttddft._mo_occ ) + + if(ForceDecomposition is not None): + ForceDecomposition.update({"F2":arrayclone(Gr2)}) + le=len(Gr1) + for I in range(le): + Gr1[I]=Gr1[I] - Gr2[I] + return Gr1 +# Gr2=( None if(not pbc) else [] ) +# for kp in range(nkpt): +# canonicalMOs=( md._canonicalMOs if(not pbc) else md._canonicalMOs[kp] ) +# eorbs=( md._canonicalEorbs if(not pbc) else md._canonicalEorbs[kp] ) +# occ =( rttddft._mo_occ if(not pbc) else rttddft._mo_occ[kp] ) +# Gr2=calc_trCXCe( rttddft, canonicalMOs, eorbs, occ ) + + +def calc_Egnd(md,Rnuc=None,details=False): + if(Rnuc is None): + Rnuc=md.Rnuc + calc=md.update_Rnuc( Rnew=Rnuc, update_moldyn=False) + calc._fix_occ=False + E_gs=calc.calc_gs() + if(details): + ### vhf=calc.get_veff() + Eel,eCoulXC = calc.energy_elec() ### vhf=vhf) + Enuc = calc.energy_nuc() + ### ec=getattr(vhf, 'ecoul', None) + return Eel+Enuc,Enuc,eCoulXC,Eel-eCoulXC + else: + return E_gs + +def calcgrad_nmdiff(md,rttddft,dmat=None,order=3,displ=0.02,debug=False,SCHEME_2=None, + fixedAtoms=None,grad_ref=None): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + dbgng_MPI=True ## XXX XXX + calc_nacm_.N_calcgrad_nmdiff+=1 + compto_singlethread = (dbgng_MPI and MPIsize>1 and ( calc_nacm_.N_calcgrad_nmdiff==1 or \ + calc_nacm_.N_calcgrad_nmdiff==10 or \ + calc_nacm_.N_calcgrad_nmdiff==50 or \ + calc_nacm_.N_calcgrad_nmdiff%200==0 )) + retv=None + timing={};wt00=time.time();wt01=wt00;wt_MPI=-1;wt_SINGLETHREAD=-1 + if( MPIsize > 1 ): + print("#calcForce:::calcgrad_nmdiff:$%02d:nmdiff_MPI start"%(MPIrank)) + retv=calcgrad_nmdiff_MPI( md,rttddft,dmat=dmat,order=order,displ=displ,debug=debug, + SCHEME_2=SCHEME_2, fixedAtoms=fixedAtoms, grad_ref=grad_ref, timing=timing) + wt02=wt01;wt01=time.time();wt_MPI=wt01-wt02 + print("#calcForce:::calcgrad_nmdiff:$%02d:nmdiff_MPI end"%(MPIrank),wt01-wt02) + if( MPIsize <=1 or compto_singlethread ): + retv_MPI=retv + print("#calcForce:::calcgrad_nmdiff:$%02d:XXX nmdiff_SINGLETHREAD start"%(MPIrank)) + retv=calcgrad_nmdiff_singlethread( md,rttddft,dmat=dmat,order=order,displ=displ,debug=debug, + SCHEME_2=SCHEME_2, fixedAtoms=fixedAtoms, grad_ref=grad_ref) + wt02=wt01;wt01=time.time();wt_SINGLETHREAD=wt01-wt02 + print("#calcForce:::calcgrad_nmdiff:$%02d:XXX nmdiff_SINGLETHREAD end"%(MPIrank),wt01-wt02) + if( compto_singlethread ): + dev=max( abs( np.ravel(retv) - np.ravel(retv_MPI))) + if(MPIrank==0): + fdDBG=open("calcNacm_MPI_DBG.log","a") + print("%3d:diff:%e elapsed:%f %f Rnuc:"%(calc_nacm_.N_calcgrad_nmdiff,dev, wt_MPI, wt_SINGLETHREAD)\ + +str(md.Rnuc),file=fdDBG) + if( dev > 1e-6 ): + print("#MPI:"+str( [ "%14.6f"%(retv_MPI[k]) for k in range( len(retv_MPI) ) ] ),file=fdDBG) + print("#REF:"+str( [ "%14.6f"%(retv[k]) for k in range( len(retv) ) ] ),file=fdDBG) + fdDBG.close() + return retv +def calcgrad_nmdiff_MPI(md,rttddft,dmat=None,order=3,displ=0.02,debug=False,SCHEME_2=None, + fixedAtoms=None,grad_ref=None,timing=None): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + + dbgng_Rnuc=True + dbgng_MPI=True + + assert SCHEME_2 is not None,"" + dm_orth=( None if(not SCHEME_2) else convert_dm_AO_to_Orth( rttddft._Ssqrt, dmat, rttddft._pbc, rttddft._spinrestriction ) ) + dm_AOrep=( None if(SCHEME_2) else arrayclone(dmat) ) + + if(timing is None): timing={} + timing.update({"thread":MPIrank,"calc":0,"ntask":0,"sync":0,"nmrdiff":0}) + + wt00=time.time();wt01=time.time() ## TIMING + hfo=order//2 + spdm=3; Nat=md.Nat; + Nfixed=( 0 if(fixedAtoms is None) else len(fixedAtoms) ) + Nat_eff=Nat-Nfixed + Iat_al=[] + for I in range(Nat): + if( fixedAtoms is not None): + if(I in fixedAtoms): + continue + Iat_al.append(I) + N_dir = Nat_eff*spdm + hfo_x_2=hfo*2 + N_task = N_dir * (hfo_x_2) + myTask = (N_task + MPIsize -1 )//MPIsize + Ebuf_wrk=np.zeros([N_dir,2*hfo+1]) ## + task_offset = min( N_task, MPIrank * myTask) + task_uplm = min( N_task, (MPIrank+1)*myTask) + + if(dbgng_Rnuc): + dum=d1maxdiff( np.ravel(md.Rnuc), np.ravel(rttddft.get_Rnuc('B')));assert dum<1e-6,"" + flags_dbg_wrk=None; + indcs_dbg_wrk=None + if( dbgng_MPI ): + flags_dbg_wrk=np.zeros([N_dir,2*hfo+1],dtype=int) + indcs_dbg_wrk=np.zeros([N_dir,2*hfo+1,4],dtype=int) + + MPIutils01.setup() + MPIutils01.stop_parallel("calcgrad_nmdiff_MPI") + + print("#calcForce:::calcgrad_nmdiff_MPI:$%02d:N_task:%d mine:%d [%d:%d)"%(MPIrank,N_task,myTask,task_offset,task_uplm)) + + Rnuc_o= arrayclone( md.Rnuc ) + R_wrk= arrayclone(md.Rnuc) + for task in range(task_offset,task_uplm): + step=task % (hfo_x_2); idispl=(step-hfo if(step3 ): + grad_ref.update({"3p":np.zeros([Nat_eff,3],dtype=np.float64), \ + "5p":np.zeros([Nat_eff,3],dtype=np.float64)}) + if(order>5): + grad_ref.update({"7p":np.zeros([Nat_eff,3],dtype=np.float64)}) + IxJ=-1;Iat_eff=-1 + for Iat in range(Nat): + if( fixedAtoms is not None): + if(Iat in fixedAtoms): + continue + Iat_eff+=1 + for Jdir in range(spdm): + IxJ+=1 + Dic={"7p":None,"5p":None,"3p":None}; + dNp = nmrdff( order,Ebuf[IxJ][:],dim=0,dx=displ,dict=Dic) + grad[ IxJ ]=dNp; + if( dbgng_MPI ): + for k in range(-hfo,hfo+1): + assert (k==0 and flags_dbg[IxJ][k+hfo]==0) or \ + (k!=0 and flags_dbg[IxJ][k+hfo]==1), "flag@%d:"%(IxJ)+str(flags_dbg[IxJ]) + if(k!=0): + assert indcs_dbg[IxJ][k+hfo][1]==Iat and \ + indcs_dbg[IxJ][k+hfo][2]==Jdir and \ + indcs_dbg[IxJ][k+hfo][3]==k, "indcs@%d,%d:"%(IxJ,k+hfo)+str(indcs_dbg[IxJ][k+hfo])\ + +"/"+str([Iat,Jdir,k]) + if( grad_ref is not None ): + if( order>3 ): + grad_ref["3p"][Iat_eff][Jdir]=Dic["3p"]; + grad_ref["5p"][Iat_eff][Jdir]=Dic["5p"]; + if( order>5 ): + grad_ref["7p"][Iat_eff][Jdir]=Dic["7p"]; + + wt02=wt01;wt01=time.time(); timing["nmrdiff"]=wt01-wt02 + + logfpath="calcForce_walltime_%02d.log"%(MPIrank) + fdOU=open(logfpath,"a") + print("#calcForce:::calcgrad_nmdiff_MPI:$%02d:%14.4f nTask:%d "%( MPIrank,wt01-wt00, -task_offset+task_uplm)+str(timing) + +" \t\t"+str(datetime.datetime.now()), file=fdOU) + fdOU.close() + + print("#calcForce:::calcgrad_nmdiff_MPI:$%02d:END %f"%(MPIrank,wt01-wt00)) + + return grad + +## calcNacm2.py : def calcGrad_analytic(md,rttddft,dmat=None,fixedAtoms=None): +## calcNacm2.py : from pyscf.pbc.grad.krks import Gradients +## calcNacm2.py : if dmat is None: dmat = md.calc_tdDM(rttddft) +## calcNacm2.py : pbc=md.pbc +## calcNacm2.py : if( not pbc ): +## calcNacm2.py : assert False,"" +## calcNacm2.py : grad=Gradients( rttddft ) +## calcNacm2.py : +## calcNacm2.py : mol_or_cell = (rttddft.cell if(pbc) else rttddft.mol) +## calcNacm2.py : if( pbc ): +## calcNacm2.py : hcGEN=grad.hcore_generator(mol_or_cell, rttddft.kpts) +## calcNacm2.py : else: +## calcNacm2.py : hcGEN=grad.hcore_generator(mol_or_cell) +## calcNacm2.py : +## calcNacm2.py : veffgrad=grad.get_veff(dm=dmat) +## calcNacm2.py : hcgrad =grad.get_hcore() +## calcNacm2.py : print("veff:",np.shape(veffgrad)) ##(3, 4, 26, 26) +## calcNacm2.py : print("hc:",np.shape(hcgrad)) ##(4, 3, 26, 26) +## calcNacm2.py : spdm=3;nkpt=md.nkpt +## calcNacm2.py : Nat=md.Nat +## calcNacm2.py : Nat_eff=(Nat if(fixedAtoms is None) else Nat-len(fixedAtoms)) +## calcNacm2.py : Ndir_eff=spdm*Nat_eff +## calcNacm2.py : ret=np.zeros([Ndir_eff],dtype=np.float64) +## calcNacm2.py : nAO=md.nAO;assert nAO>0,"" +## calcNacm2.py : vWRK=np.zeros( ([nkpt,nAO,nAO] if(pbc) else [nAO,nAO]),dtype=np.complex128 ) +## calcNacm2.py : hWRK=np.zeros( ([nkpt,nAO,nAO] if(pbc) else [nAO,nAO]),dtype=np.complex128 ) +## calcNacm2.py : mu_to_iat=get_mu_to_iat(rttddft, (rttddft.cell if(pbc) else rttddft.mol) ) +## calcNacm2.py : IxJ=-1;Iat_eff=-1 +## calcNacm2.py : for Iat in range(Nat): +## calcNacm2.py : if( fixedAtoms is not None ): +## calcNacm2.py : if( Iat in fixedAtoms ): +## calcNacm2.py : continue +## calcNacm2.py : hcgrads_Iat=hcGEN(Iat) +## calcNacm2.py : print("hcgrad:",np.shape(hcgrad)) +## calcNacm2.py : Iat_eff+=1 +## calcNacm2.py : for Jdir in range(spdm): +## calcNacm2.py : IxJ+=1; +## calcNacm2.py : make_vAO(vWRK,pbc,Iat,Jdir,veffgrad, 0, n_kpoints=nkpt,mu_to_iat=mu_to_iat) +## calcNacm2.py : +## calcNacm2.py : make_vAO(hWRK,pbc,Iat,Jdir,hcgrad, 1, n_kpoints=nkpt,mu_to_iat=mu_to_iat) +## calcNacm2.py : +## calcNacm2.py : print_matrices(hWRK,hcgrads_Iat[Jdir],"hWRK,hcgrad",fpath="hcgrad.dat",Append=(Iat!=0 or dir!=0)) +## calcNacm2.py : ret[IxJ]=dmtrace( pbc,vWRK+hWRK, dmat) +## calcNacm2.py : atmlst=[] +## calcNacm2.py : for Iat in range(Nat): +## calcNacm2.py : if( fixedAtoms is not None ): +## calcNacm2.py : if( Iat in fixedAtoms ): +## calcNacm2.py : continue +## calcNacm2.py : atmlst.append(Iat) +## calcNacm2.py : nucGrad=grad.grad_nuc( mol_or_cell, atmlst) +## calcNacm2.py : print("nucGrad:",np.shape(nucGrad),"ret:",np.shape(ret)) +## calcNacm2.py : nucGrad=np.reshape(nucGrad,np.shape(ret)) +## calcNacm2.py : ret=ret+nucGrad +## calcNacm2.py : return ret + +def i1eqb(lhs,rhs): + le=len(lhs); + if(len(rhs)!=le): + return False + for j in range(le): + if( lhs[j]!=rhs[j] ): + return False + return True + +def d1toa(buf,maxlen=10): + buf=np.ravel(buf) + le=len(buf);le1=min(le,maxlen) + ret="" + for j in range(le1): + ret+="%14.6f "%(buf[j]) + if(le>le1): + ret+=" ... [%d]:%14.6f"%(le-1,buf[le-1]) + return ret +def d2toa(buf,buf2=None,maxlen=8): + ndim=np.shape(buf) + le=len(buf);le1=min(le,maxlen) + le2=min(ndim[1],maxlen) + Ret="" + for I in range(le1): + ret="" + for J in range(le2): + ret+="%14.6f "%(buf[I][J]) + if( ndim[1]>le2 ): + ret+=" ... [%d]:%14.6f"%( ndim[1]-1, buf[I][ ndim[1]-1 ]) + + if( buf2 is not None): + ret+=" \t\t\t " + for J in range(le2): + ret+="%14.6f "%(buf2[I][J]) + if( ndim[1]>le2 ): + ret+=" ... [%d]:%14.6f"%( ndim[1]-1, buf2[I][ ndim[1]-1 ]) + + Ret+=("\n" if(I>0) else "")+ret + return Ret + +def d3toa(lhs,rhs=None): + NdL=np.shape(lhs); + if(rhs is not None): + NdR=np.shape(rhs) + ret="" + for kp in range(NdL[0]): + if(kp>0): ret+="\n\n"; + ret="#%02d\n"%(kp) + for ip in range(NdL[1]): + ret="%05d: " + for jp in range(NdL[2]): + ret+="%12.6f "%(lhs[kp][ip][jp]) + if(rhs is not None): + ret+=" \t\t\t " + for jp in range(NdL[2]): + ret+="%12.6f "%(rhs[kp][ip][jp]) + ret+="\n" + return ret + +def print_matrices(lhs,rhs,title,fpath=None,fopen=False,Append=True): + import sys + import os + NdL=np.shape(lhs);NdR=np.shape(rhs) + fd=sys.stdout;doclose=False + if( fpath is not None): + fd=open(fpath,("a" if(Append) else "w"));doclose=True + + errbuf=[] + dev=aNmaxdiff(lhs,rhs,errbuf) + print("#print_matrices:%s:SHAPE:%s,%s \t\t\t "%( title, str(NdL),str(NdR)) \ + + str(datetime.datetime.now()),file=fd) + if( not i1eqb(NdL,NdR) ): + print("#print_matrices:%s:!W len differs:%s / %s"%(title,str(NdL),str(NdR)),file=fd) + print("#print_matrices:%s:LHS:"+d1toa(lhs),file=fd ) + print("#print_matrices:%s:RHS:"+d1toa(rhs),file=fd ); + if(doclose):fd.close(); + if(fopen):os.system("fopen "+fpath); + return + rank=len(NdL) + if(rank==1): + print("#print_matrices:%s:LHS:"+d1toa(lhs),file=fd ) + print("#print_matrices:%s:RHS:"+d1toa(rhs),file=fd); + if(doclose): fd.close() + if(fopen):os.system("fopen "+fpath); + return + elif(rank==2): + print("#print_matrices:%s\n"+d2toa(lhs,rhs),file=fd); + if(doclose): fd.close() + if(fopen):os.system("fopen "+fpath); + return + else: + print("#print_matrices:%s:LHS:"+d3toa(lhs),file=fd ) + print("#print_matrices:%s:RHS:"+d3toa(rhs),file=fd ); + if(doclose): fd.close() + if(fopen):os.system("fopen "+fpath); + return + + +def calcGrad_analytic_FFTDF(md,rttddft,dmat=None,FockMat=None,fixedAtoms=None, decomposition=None, + nmgrads=None, SCHEME_2=False, time_AU=None): + from .calcNacm2 import get_derivMatrices_FFTDF + if dmat is None: dmat = md.calc_tdDM(rttddft) + if time_AU is None: time_AU = md.time_AU + if(FockMat is None): + FockMat = md.calc_fock(rttddft,dm=dmat,time_AU=time_AU) + DerivMatrices= get_derivMatrices_FFTDF(md,rttddft, md.Nat, dmat=dmat,fixedAtoms=fixedAtoms) + pbc=md.pbc + spdm=3;nkpt=md.nkpt + Nat=md.Nat + Nat_eff=(Nat if(fixedAtoms is None) else Nat-len(fixedAtoms)) + Ndir_eff=spdm*Nat_eff + ret=np.zeros([Ndir_eff],dtype=np.float64) + Refr=( None if( nmgrads is None ) else np.zeros([Ndir_eff],dtype=np.float64)) + + de_hc=[];de_ve=[] + nAO=md.nAO;assert nAO>0,"" + IxJ=-1;Iat_eff=-1 + print("hcore:", np.shape( DerivMatrices["hcore"] ),np.shape( DerivMatrices["veff"] ) ) + for Iat in range(Nat): + if( fixedAtoms is not None ): + if( Iat in fixedAtoms ): + continue + for Jdir in range(spdm): + IxJ+=1 + hWRK=DerivMatrices["hcore"][ IxJ ] + vWRK=DerivMatrices["veff"][ IxJ ] + print(np.shape(DerivMatrices["hcore"]),np.shape(DerivMatrices["veff"]), np.shape(hWRK),np.shape(vWRK)) + ret[ IxJ ] = dmtrace( pbc,vWRK+hWRK, dmat) + + if(decomposition is not None ): + de_hc.append( dmtrace( pbc,hWRK,dmat) ) + de_ve.append( dmtrace( pbc,vWRK,dmat) ) + + if( nmgrads is not None ): + hWRK=nmgrads["hcore"][IxJ] + vWRK=nmgrads["veff"][IxJ] + print("dmtrace:",np.shape(hWRK),np.shape(vWRK)) + Refr[ IxJ ] = dmtrace( pbc,vWRK+hWRK, dmat) + # gr2 [nkpt,3*Nat,nAO,nAO] + # see L480 : gr2(:=calc_trFSXD) is to be SUBTRACTED from gr1 + # to keep consistency with 480, we use gr2, but de_s1 :=-gr2 + gr2= calc_trFSXD(md.pbc, md.spinrestriction, rttddft, FockMat, dmat, fixedAtoms=fixedAtoms, + SCHEME_2=SCHEME_2) ## should we store those matrices ?? + gr_nc = DerivMatrices["E_nuc"] + + if(decomposition is not None): + decomposition.update({"de_hc":np.ravel(de_hc), "de_ve":np.ravel(de_ve), "de_s1":-np.ravel(gr2), "de_nc":np.ravel(gr_nc)}) + + dbgng=True + if( dbgng ): + ## returns [nKpt][Nat*3] + gr2b= calc_trCXCe(rttddft, md._canonicalMOs, md._canonicalEorbs, md.mo_occ,fixedAtoms=fixedAtoms) + print("#calc_trCXCe:",np.shape(gr2),np.shape(gr2b)) + #print("#trCXCe:diff:",max( abs( np.ravel( gr2 )-np.ravel( gr2b ) ) )) + + print("#calcGrad_analytic_FFTDF:",np.shape(ret),np.shape(gr2),np.shape(gr_nc)) + # + # see L480 : gr2(:=calc_trFSXD) is to be SUBTRACTED from gr1 + ret= np.ravel(ret) - np.ravel(gr2) + np.ravel(gr_nc) ## 2022.01.16: we included gr_nc + if(Refr is not None ): + Refr=Refr - gr2 + nmgrads.update({"Egrad_refr":arrayclone(Refr)}) + if(nmgrads is None ): + return ret + else: + return ret,Refr diff --git a/pyscf/rttddft/calcNacm2.py b/pyscf/rttddft/calcNacm2.py new file mode 100644 index 000000000..ea85a4555 --- /dev/null +++ b/pyscf/rttddft/calcNacm2.py @@ -0,0 +1,1048 @@ +import numpy as np +import math +import os +import time +import datetime +from .Loglv import printout +from .utils import i1eqb,parse_xyzstring,aNmaxdiff +from .Moldyn import get_eOrbs +from mpi4py import MPI +from .heapcheck import heapcheck +from .rttddft_common import rttddft_common +import numpy as np +from .utils import arrayclone + +def fn_save_matrices_std(key,index,dbuf,buf_matrices,atmlst): + printout=False + Nat=len(atmlst);spdm=3 + Ndim=np.shape(dbuf) + print("#fn_save_matrices_std:",key,index,Ndim) + is_scalar = ( isinstance(dbuf,float) or isinstance(dbuf,np.float64) or\ + isinstance(dbuf,int) or isinstance(dbuf,np.int64) or \ + isinstance(dbuf,complex) or isinstance(dbuf,np.complex128) ) + if( not printout ): + if( index < 0 ): + buf_matrices.update({key:(dbuf if(is_scalar) else arrayclone(dbuf,label="fn_save_matrices:"+str(key)))}) + else: + # input h1ao : [ 3 ][ nKpoints ][ nAO ][ nAO ] + if( key == "hcore"): + assert Ndim[0]==spdm,"" + if( key not in buf_matrices ): + buf_matrices.update({key:[ None for iat in range(Nat) ]}) + buf_matrices[key][ index ]=(dbuf if(is_scalar) else arrayclone(dbuf,label="fn_save_matrices:%02d:"%(index)+str(key))) +## 20220508.divide_tasks: buf_matrices.update({key:[]}) +## 20220508.divide_tasks: if( len(buf_matrices[key])==index ): +## 20220508.divide_tasks: buf_matrices[key].append( (dbuf if(is_scalar) else arrayclone(dbuf)) ) +## 20220508.divide_tasks: else: +## 20220508.divide_tasks: assert len(buf_matrices[key])==index,"" +## 20220508.divide_tasks: buf_matrices[key][index] = (dbuf if(is_scalar) else arrayclone(dbuf)) + else: + assert False,"" + + + +## D +def convert_dm_AO_to_Orth( SsqrtAL, dm_AO, pbc ,spinrestriction ): + return convert_dmat_( SsqrtAL, dm_AO, pbc ,spinrestriction ) + +def convert_dm_Orth_to_AO( SinvrtAL, dm_AO, pbc ,spinrestriction ): + return convert_dmat_( SinvrtAL, dm_AO, pbc, spinrestriction ) + +def convert_dmat_( Ssqrt_or_invrtAL, dm_AO_or_Orth, pbc, spinrestriction ): + assert spinrestriction == 'R',"UKS should call this method twice" + Ret=(None if(not pbc) else []) + nkpt=(1 if(not pbc) else len( Ssqrt_or_invrtAL)) + for kp in range(nkpt): + Ssqrt = ( Ssqrt_or_invrtAL if(not pbc) else Ssqrt_or_invrtAL[kp] ) + dAO = ( dm_AO_or_Orth if(not pbc) else dm_AO_or_Orth[kp] ) + mat =np.matmul( Ssqrt, np.matmul(dAO, Ssqrt) ) + if( not pbc ): + Ret=mat;break + else: + Ret.append(mat) + return Ret + +## v(3 ,Nkpt, nAO-d, nAO) or (3,nAO-d,nAO) xyz_at==0 +## h(Nkpt, 3, nAO-d, nAO) of (3,nAO-d,nAO) xyz_at==1 +def make_vAO(rttddft, ret,pbc,Iat,Jdir,gradMat,xyz_at, n_kpoints=None,mu_to_iat=None): + if( mu_to_iat is None ): mu_to_iat = get_mu_to_iat(rttddft, (rttddft.cell if(pbc) else rttddft.mol)); + assert xyz_at==0 or xyz_at==1,"" + Ndim=np.shape(gradMat) + nkpt=1;nAO=Ndim[1] + if( pbc ): + k_at=1-xyz_at;nkpt=Ndim[k_at];nAO=Ndim[2] + if( n_kpoints is not None): + assert n_kpoints==nkpt,"" + if(pbc): + for kp in range(nkpt): + for mu in range(nAO): + for nu in range(nAO): + ret[kp][mu][nu]=0.0 + if(mu_to_iat[mu]==Iat): + ret[kp][mu][nu]+=( gradMat[ Jdir ][ kp ][ mu ][ nu ] if(xyz_at==0) else \ + gradMat[ kp ][ Jdir ][ mu ][ nu ] ) + if(mu_to_iat[nu]==Iat): + ret[kp][mu][nu]+=np.conj( gradMat[ Jdir ][ kp ][ nu ][ mu ] if(xyz_at==0) else \ + gradMat[ kp ][ Jdir ][ nu ][ mu ] ) + + else: + for mu in range(nAO): + for nu in range(nAO): + ret[mu][nu]=0.0 + if(mu_to_iat[mu]==Iat): + ret[mu][nu]+=gradMat[ Jdir ][ mu ][ nu ] + if(mu_to_iat[nu]==Iat): + ret[mu][nu]+=np.conj( gradMat[ Jdir ][ nu ][ mu ] ) + return ret + + + +def get_elmt(array,index): + Ndim=np.shape(array);rank=len(Ndim) + le=len(index);assert le<=rank,"" + if( le == 1 ): + return array[index[0]] + elif( le == 2 ): + return array[ index[0] ][ index[1] ] + elif( le == 3 ): + return array[ index[0] ][ index[1] ][ index[2] ] + elif( le == 4 ): + return array[ index[0] ][ index[1] ][ index[2] ][ index[3] ] + elif( le == 5 ): + return array[ index[0] ][ index[1] ][ index[2] ][ index[3] ][ index[4] ] + else: + assert False,"" +# +# sqrdiff,diff,at,vals = aNsqrMaxdiffAt +def aNsqrMaxdiffAt(lhs,rhs): + Lh=lhs;Rh=rhs + Ndim=np.shape(lhs);rank=len(Ndim) + if( rank > 5 ): + Lh=np.ravel(lhs);Rh=np.ravel(rhs) + Ndim=np.shape(Lh);assert len(Ndim)<=5,"" + Ndim_RHS=np.shape(Rh) + if( not i1eqb( Ndim, Ndim_RHS ) ): + print("#!W dimension differs:",Ndim,Ndim_RHS) + Rh=np.reshape(lhs,Ndim) + + diff=-1;at=None;vals=None + for I in range(Ndim[0]): + if(rank==1): + print("aNsqrMaxDiffat:",Lh[I],Rh[I]) + if( (Lh[I] is None) or (Rh[I] is None)): + continue + dum=abs( Lh[I]-Rh[I] ) + if( dum > diff ): + diff=dum;at=[I];vals=[Lh[I],Rh[I]] + continue + for J in range(Ndim[1]): + if(rank==2): + dum=abs( Lh[I][J]-Rh[I][J] ) + if( dum > diff ): + diff=dum;at=[I,J];vals=[Lh[I][J],Rh[I][J]] + continue + for K in range(Ndim[2]): + if(rank==3): + dum=abs( Lh[I][J][K]-Rh[I][J][K] ) + if( dum > diff ): + diff=dum;at=[I,J,K];vals=[Lh[I][J][K], Rh[I][J][K]] + continue + for L in range(Ndim[3]): + if(rank==4): + dum=abs( Lh[I][J][K][L]-Rh[I][J][K][L] ) + if( dum > diff ): + diff=dum;at=[I,J,K,L];vals=[Lh[I][J][K][L],Rh[I][J][K][L]] + continue + for M in range(Ndim[4]): + if(rank==5): + dum=abs( Lh[I][J][K][L][M]-Rh[I][J][K][L][M] ) + if( dum > diff ): + diff=dum;at=[I,J,K,L,M];vals=[Lh[I][J][K][L][M],Rh[I][J][K][L][M]] + continue + Lh1D=np.ravel(Lh);Rh1D=np.ravel(Rh) + sqrdiff= np.vdot( Lh1D-Rh1D, Lh1D-Rh1D) + + return sqrdiff,diff,at,vals +## +## +def numrdiff_matrices( md, rttddft, dmat=None, fixedAtoms=None, order=5, displ=0.02, multithreading=True, Targets=None, Suppl=None,Deviations=None, + SCHEME_2=False ): + if( dmat is None ): dmat = md.calc_tdDM(rttddft,ovrd=True) + spdm=3; Nat=md.Nat; + Nfixed=( 0 if(fixedAtoms is None) else len(fixedAtoms) ) + Nat_eff=Nat-Nfixed + N_dir = Nat_eff*spdm + + if( Targets is None ): + Targets={"veff":[ None for k in range(N_dir) ], "hcore":[ None for k in range(N_dir) ], + "E_el":[ None for k in range(N_dir) ], "E_nuc":[ None for k in range(N_dir) ]} + if( Suppl is None ): + Suppl={"veff":[ None for k in range(N_dir) ], "hcore":[ None for k in range(N_dir) ], + "E_el":[ None for k in range(N_dir) ], "E_nuc":[ None for k in range(N_dir) ]} + + assert SCHEME_2 is not None,"" + dm_orth=( None if(not SCHEME_2) else convert_dm_AO_to_Orth( rttddft._Ssqrt, dmat, rttddft._pbc, rttddft._spinrestriction ) ) + dm_AOrep=( None if(SCHEME_2) else arrayclone(dmat) ) + + hfo=order//2 + Iat_al=[] + for I in range(Nat): + if( fixedAtoms is not None): + if(I in fixedAtoms): + continue + Iat_al.append(I) + hfo_x_2=hfo*2 + N_task = N_dir * (hfo_x_2) + ## 0 1 2 3 + ## -3 -2 -1 + Coeffs_3p=[ None, None, -0.50, None, 0.50, None, None ] + # -3 -2 -1 0 + Coeffs_5p=[ None, 1.0/12.0, -2.0/3.0, None, 2.0/3.0, -1.0/12.0, None ] + Coeffs_7p=[ -1.0/60.0, 0.15, -0.75,None, 0.75, -0.15, 1.0/60.0 ] + Coeffs= ( Coeffs_3p if(order==3) else ( Coeffs_5p if(order==5) else Coeffs_7p)) + Coeffs_sub=( Coeffs_3p if(order==3) else ( Coeffs_3p if(order==5) else Coeffs_5p)) + + MPIsize=1; MPIrank=0 + if( multithreading ): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + + myTask = (N_task + MPIsize -1 )//MPIsize + task_offset = min( N_task, MPIrank * myTask) + task_uplm = min( N_task, (MPIrank+1)*myTask) + + Rnuc_o= arrayclone( md.Rnuc ) + R_wrk = arrayclone( md.Rnuc ) + + print("calcNacm2:R_org:",Rnuc_o) + for task in range(task_offset,task_uplm): + step=task % (hfo_x_2); idispl=(step-hfo if(stepcalcGrad_analytic_FFTDF:start calcgrad_analytic_ref") + dE_ref=calcgrad_analytic_ref(rttddft, DerivMatrices=DerivMatrices) + print("#>calcGrad_analytic_FFTDF:end calcgrad_analytic_ref:",[ dum for dum in DerivMatrices ]) + + pbc=md.pbc + if( not pbc ): + assert False,"" + grad=Gradients( rttddft ) + + mol_or_cell = (rttddft.cell if(pbc) else rttddft.mol) + if( pbc ): + hcGEN=grad.hcore_generator(mol_or_cell, rttddft.kpts) + else: + hcGEN=grad.hcore_generator(mol_or_cell) + + veffgrad=grad.get_veff(dm=dmat) + hcgrad =grad.get_hcore() + + nmrdiff_deviations={} + print("#>calcGrad_analytic_FFTDF:start numrdiff") + nmrgrads=numrdiff_matrices( md, rttddft, dmat=dmat, order=5, Deviations=nmrdiff_deviations ) + print("#>calcGrad_analytic_FFTDF:end numrdiff") + + for ky in DerivMatrices: + if( ky in nmrgrads ): + lh=DerivMatrices[ky] + rh=nmrgrads[ky] + print("#>calcGrad_analytic_FFTDF:ref_vs_nmdiff:"+ky,aNsqrMaxdiffAt(lh,rh)) + if(ky =="veff"): + printMatrices("veffGrad.dat",lh,rh,description="v_eff:Analytic vs Numeric") +# +# +# + # assert False,"check Results" + + print("veff:",np.shape(veffgrad)) ##(3, 4, 26, 26) + print("hc:",np.shape(hcgrad)) ##(4, 3, 26, 26) + spdm=3;nkpt=md.nkpt + Nat=md.Nat + Nat_eff=(Nat if(fixedAtoms is None) else Nat-len(fixedAtoms)) + Ndir_eff=spdm*Nat_eff + ret=np.zeros([Ndir_eff],dtype=np.float64) + nAO=md.nAO;assert nAO>0,"" + vWRK=np.zeros( ([nkpt,nAO,nAO] if(pbc) else [nAO,nAO]),dtype=np.complex128 ) + hWRK=np.zeros( ([nkpt,nAO,nAO] if(pbc) else [nAO,nAO]),dtype=np.complex128 ) + mu_to_iat=get_mu_to_iat(rttddft, (rttddft.cell if(pbc) else rttddft.mol) ) + IxJ=-1;Iat_eff=-1 + for Iat in range(Nat): + if( fixedAtoms is not None ): + if( Iat in fixedAtoms ): + continue + hcgrads_Iat=hcGEN(Iat) + print("hcgrad:",np.shape(hcgrad)) + Iat_eff+=1 + for Jdir in range(spdm): + IxJ+=1; + vWRK = make_vAO(rttddft, vWRK,pbc,Iat,Jdir,veffgrad, 0, n_kpoints=nkpt,mu_to_iat=mu_to_iat) + + hWRK = make_vAO(rttddft, hWRK,pbc,Iat,Jdir,hcgrad, 1, n_kpoints=nkpt,mu_to_iat=mu_to_iat) + + ### print_matrices(hWRK,hcgrads_Iat[Jdir],"hWRK,hcgrad",fpath="hcgrad.dat",Append=(Iat!=0 or dir!=0)) + ret[IxJ]=dmtrace( pbc,vWRK+hWRK, dmat) + + vdist,vdev,v_at,v_vals = aNsqrMaxdiffAt( nmrgrads["veff"][ IxJ ], vWRK ) + print("#veffGRAD_%02d: %f %e (%s, %s)"%(IxJ, vdist, vdev, str(v_vals[0]),str(v_vals[1]))) + + printMatrices("veffGrad_%02d.dat"%(IxJ),vWRK, nmrgrads["veff"][ IxJ ]) + + hdist,hdev,h_at,h_vals = aNsqrMaxdiffAt( nmrgrads["hcore"][ IxJ ],hWRK ) + printMatrices("hcoreGrad_%02d.dat"%(IxJ),hWRK, nmrgrads["hcore"][ IxJ ]) + + print("#hcoreGRAD_%02d: %f %e (%s, %s)"%(IxJ, hdist, hdev, str(h_vals[0]),str(h_vals[1]))) + + atmlst=[] + for Iat in range(Nat): + if( fixedAtoms is not None ): + if( Iat in fixedAtoms ): + continue + atmlst.append(Iat) + nucGrad=grad.grad_nuc( mol_or_cell, atmlst) + print("nucGrad:",np.shape(nucGrad),"ret:",np.shape(ret)) + eleGrad=arrayclone( ret ) + nucGrad=np.reshape(nucGrad,np.shape(ret)) + ret=ret+nucGrad + print("#calcgrad_hfnum:",ret) + + + print("#calcgrad_analytic_ref:",dE_ref) + ### print("#DerivMatrices:",DerivMatrices) + + sqrdiff,maxdiff,at,vals = aNsqrMaxdiffAt(ret,dE_ref) + print("#Egrad:", sqrdiff,maxdiff,at,vals ) + print("#E_el:", aNsqrMaxdiffAt(eleGrad,DerivMatrices["E_el"] ) ) + print("#E_nuc:", aNsqrMaxdiffAt(nucGrad,DerivMatrices["E_nuc"] ) ) + + print("#grad_hcore:", aNsqrMaxdiffAt( nmrgrads["hcore"],DerivMatrices["hcore"] ) ) + print("#grad_veff:", aNsqrMaxdiffAt( nmrgrads["veff"],DerivMatrices["veff"] ) ) + return ret + + +def printMatrices(fpath,lhs,rhs,format=None,description=None,Append=False): + fd=open(fpath,("a" if(Append) else "w")) + + sqrdist,dev,at,vals = aNsqrMaxdiffAt(lhs,rhs) + + Lh=lhs;Rh=rhs + Ndim=np.shape(lhs);rank=len(Ndim) + dtype=( (np.array(lhs)).dtype if(rank<=2) else (np.array(lhs[0])).dtype) + T=('I' if(dtype==int or dtype==np.int64) else ( 'D' if(dtype==float or dtype==np.float64) else \ + ('Z' if(dtype==complex or dtype==np.complex128) else None ) ) ) + if( format is None ): + format=("%d" if(T=='I') else ("%14.6f" if(T=='D') else ("%12.6f,%12.6f" if(T=='Z') else None) ) ) + + print("#%s %s maxdiff:%e @%s %s / %s"%( T, str(np.shape(lhs)),dev,str(at),str(vals[0]),str(vals[1]) ),file=fd) + if( description is not None ): + print("### %s"%(description),file=fd) + + if( rank > 5 ): + Lh=np.ravel(lhs);Rh=np.ravel(rhs) + Ndim=np.shape(Lh);assert len(Ndim)<=5,"" + Ndim_RHS=np.shape(Rh) + if( not i1eqb( Ndim, Ndim_RHS ) ): + Rh=np.reshape(lhs,Ndim) + + def tostring(lv,rv,diff,T,delimiter=" \t ",delimiter2=" \t\t "): + return format%(lv) + delimiter + format%(rv) + delimiter2 + "%e"%(diff) if(T!='Z') else \ + format%(lv.real,lv.imag) + delimiter + format%(rv.real, rv.imag)+delimiter2+"%e"%(diff) + + diff=-1;at=None;vals=None + for I in range(Ndim[0]): + if(rank==1): + dum=abs( Lh[I]-Rh[I] ) + print("%d:"%(I) + tostring(Lh[I],Rh[I],dum, T),file=fd ) + continue + for J in range(Ndim[1]): + if(rank==2): + dum=abs( Lh[I][J]-Rh[I][J] ) + print("%d,%d:"%(I,J) + tostring(Lh[I][J],Rh[I][J],dum, T),file=fd ) + continue + for K in range(Ndim[2]): + if(rank==3): + dum=abs( Lh[I][J][K]-Rh[I][J][K] ) + print("%d,%d,%d:"%(I,J,K) + tostring(Lh[I][J][K],Rh[I][J][K],dum, T),file=fd ) + continue + for L in range(Ndim[3]): + if(rank==4): + dum=abs( Lh[I][J][K][L]-Rh[I][J][K][L] ) + print("%d,%d,%d,%d:"%(I,J,K,L) + tostring(Lh[I][J][K][L],Rh[I][J][K][L],dum, T),file=fd ) + continue + for M in range(Ndim[4]): + if(rank==5): + dum=abs( Lh[I][J][K][L][M]-Rh[I][J][K][L][M] ) + print("%d,%d,%d,%d,%d:"%(I,J,K,L,M) + tostring(Lh[I][J][K][L][M],Rh[I][J][K][L][M],dum, T),file=fd ) + continue + fd.close() + return sqrdist,dev,at,vals +## einsum("kij,kji",matrix_AOrep,dmAO) +## dmtrace : INPUT : matrix_AOrep[ kp, nAO, nAO ] +## dmAO[ kp, nAO, nAO ] +## OUTPUT : complex scalar +def dmtrace(pbc,matrix_AOrep,dmAO,title=None): + if(title is not None): + print("#dmtrace:"+title+":",np.shape(matrix_AOrep),np.shape(dmAO)) + nkpt=( 1 if(not pbc) else len(dmAO) ) + ret=np.complex128( 0.0 ) + dbgng=True ## XXX XXX + wt0=time.time();wt1=wt0 + for kp in range(nkpt): + dm=( dmAO if(not pbc) else dmAO[kp] ) + mat=( matrix_AOrep if(not pbc) else matrix_AOrep[kp] ) + + mxd=np.matmul( mat, dm ) + trace=mxd[0][0];Ld=len(mat) + for j in range(1,Ld): + trace+=mxd[j][j] + ret+=trace + if(pbc): + ret=ret/float(nkpt) + wt2=wt1;wt1=time.time();wt_matmul=wt1-wt2 + + if(dbgng): + refr=np.complex128( 0.0 ) + for kp in range(nkpt): + dm=( dmAO if(not pbc) else dmAO[kp] ) + mat=( matrix_AOrep if(not pbc) else matrix_AOrep[kp] ) + dum=np.einsum("ij,ji",mat,dm) + refr+=dum + if(pbc): + refr=refr/float(nkpt) + wt2=wt1;wt1=time.time();wt_einsum=wt1-wt2 + ref2=( np.einsum("kij,kji",matrix_AOrep,dmAO) if(pbc) else \ + np.einsum("ij,ji",matrix_AOrep,dmAO) ) + wt2=wt1;wt1=time.time();wt_einsum2=wt1-wt2 + + printout("#DBGNG:einsum:%s %s %s elapsed:%f %f %f dev:0,%e,%e"%(\ + str(ret),str(refr),str(ref2),wt_matmul,wt_einsum,wt_einsum2,\ + abs(ret-refr),abs(ref2-ret)),fpath="DMtrace_DBG.log",Append=True) + + + return ret + +def get_mu_to_iat(mf,mol_or_cell): + assert (mol_or_cell is not None),"mol_or_cell" + # if cell is None: cell = mf.cell + cart = mol_or_cell.cart + Nsh=len(mol_or_cell._bas) +# 631G: O (10s,4p)/[3s,2p] cart=False +# iat el Np Nc ? ? ? ? +#_bas_0:[ 0 0 6 1 0 40 46 0] Nb+=Nc*mult +#_bas_1:[ 0 0 3 1 0 52 55 0] Nb+=Nc*mult +#_bas_2:[ 0 0 1 1 0 58 59 0] Nb+=Nc*mult +#_bas_3:[ 0 1 3 1 0 60 63 0] ... +#_bas_4:[ 0 1 1 1 0 66 67 0] +#_bas_5:[ 1 0 3 1 0 32 35 0] +#_bas_6:[ 1 0 1 1 0 38 39 0] +#_bas_7:[ 2 0 3 1 0 32 35 0] +#_bas_8:[ 2 0 1 1 0 38 39 0] +# acct: (11s,6p,3d,2f) -> [5s,4p,3d,2f] +#_bas:iatm, el, NcGTO +#_bas_0:[ 0 0 8 2 0 54 62 0] +#_bas_1:[ 0 0 1 1 0 78 79 0] +#_bas_2:[ 0 0 1 1 0 80 81 0] +#_bas_3:[ 0 0 1 1 0 82 83 0] +#_bas_4:[ 0 1 3 1 0 84 87 0] +#_bas_5:[ 0 1 1 1 0 90 91 0] +#_bas_6:[ 0 1 1 1 0 92 93 0] +#_bas_7:[ 0 1 1 1 0 94 95 0] +#_bas_8:[ 0 2 1 1 0 96 97 0] +#_bas_9:[ 0 2 1 1 0 98 99 0] +#_bas_10:[ 0 2 1 1 0 100 101 0] +#_bas_11:[ 0 3 1 1 0 102 103 0] +#_bas_12:[ 0 3 1 1 0 104 105 0] +#_bas_13:[ 1 0 3 1 0 32 35 0] +#_bas_14:[ 1 0 1 1 0 38 39 0] +#_bas_15:[ 1 0 1 1 0 40 41 0] +#_bas_16:[ 1 0 1 1 0 42 43 0] + +# 10s/1s, 1 (s1) (s2) (s3) (s4) +# 1.533000E+04 5.080000E-04 -1.150000E-04 0.000000E+00 0.000000E+00 +# 2.299000E+03 3.929000E-03 -8.950000E-04 0.000000E+00 0.000000E+00 +# 5.224000E+02 2.024300E-02 -4.636000E-03 0.000000E+00 0.000000E+00 +# 1.473000E+02 7.918100E-02 -1.872400E-02 0.000000E+00 0.000000E+00 +# 4.755000E+01 2.306870E-01 -5.846300E-02 0.000000E+00 0.000000E+00 +# 1.676000E+01 4.331180E-01 -1.364630E-01 0.000000E+00 0.000000E+00 +# 6.207000E+00 3.502600E-01 -1.757400E-01 0.000000E+00 0.000000E+00 +# 1.752000E+00 4.272800E-02 1.609340E-01 1.000000E+00 0.000000E+00 +# 6.882000E-01 -8.154000E-03 6.034180E-01 0.000000E+00 0.000000E+00 +# 2.384000E-01 2.381000E-03 3.787650E-01 0.000000E+00 1.000000E+00 +#O S (s5) +# 0.0737600 1.0000000 +#O P (p1) (p2) (p3) +# 3.446000E+01 1.592800E-02 0.000000E+00 0.000000E+00 +# 7.749000E+00 9.974000E-02 0.000000E+00 0.000000E+00 +# 2.280000E+00 3.104920E-01 0.000000E+00 0.000000E+00 +# 7.156000E-01 4.910260E-01 1.000000E+00 0.000000E+00 +# 2.140000E-01 3.363370E-01 0.000000E+00 1.000000E+00 +#O P (p4) +# 0.0597400 1.0000000 +#O D +# 2.314000E+00 1.000000E+00 0.000000E+00 +# 6.450000E-01 0.000000E+00 1.000000E+00 +#O D +# 0.2140000 1.0000000 +#O F +# 1.428000E+00 1.0000000 +#O F +# 0.5000000 1.0000000 + + ret=[] + nAO=0 + for ish in range(Nsh): + b=mol_or_cell._bas[ish] + iatm=b[0] + el = b[1] + ## 3Hl = (2+l) C 2 + mult=( (el+2)*(el+1)/2 if(cart) else 2*el+1 ) + NcGTO=b[3];nadd=NcGTO*mult + for k in range(nadd): + ret.append(iatm) + nAO+=nadd + return np.array(ret) + +def calcgrad_analytic_ref(rttddft, dmat=None, DerivMatrices=None): + from pyscf.pbc.grad.krks import Gradients + spdm=3 + mygrad = Gradients(rttddft) + Egrad = mygrad.kernel() + + kpts = rttddft.kpts + nkpts = len(kpts) + + print("#Egrad_REF:",Egrad, np.shape(Egrad) ) + if( dmat is None ): + dmat=rttddft.make_rdm1() + ## copy of rhf.py#kernel + mo_energy = mygrad.base.mo_energy + mo_coeff = mygrad.base.mo_coeff + mo_occ = mygrad.base.mo_occ + dme0 = mygrad.make_rdm1e(mo_energy, mo_coeff, mo_occ) + atmlst = mygrad.atmlst + + if atmlst is None: + atmlst = range( rttddft.mol.natm ) + print("atmlst:",atmlst) + de_el = mygrad.grad_elec(mo_energy, mo_coeff, mo_occ, atmlst) + de_nc = mygrad.grad_nuc(atmlst=atmlst) + + if( atmlst is not None ): + Nat=len(atmlst) + else: + Rnuc_au,Sy=parse_xyzstring( rttddft.cell.atom,unit_BorA='B') + Nat=len(Sy) + N_dir= spdm * Nat + + if( DerivMatrices is None ): + DerivMatrices={} + for ky in ["hcore","veff","E_el","E_nuc","extra", "de_hc","de_ve","de_nc","de_s1","de_sum"]: + DerivMatrices.update({ky:[ None for k in range(N_dir) ]}) + DerivMatrices.update({"E_el":de_el}); print("#calcgrad_analytic_ref:DerivMatrices.E_el:",de_el); + DerivMatrices.update({"E_nuc":de_nc});print("#calcgrad_analytic_ref:DerivMatrices.E_nuc:",de_nc); + + de_sum = np.array(de_el) + np.array(de_nc) + print("#calcgrad_analytic_ref:Grad_de_sum:",de_sum); ## #Grad_de_sum: [[ 2.39125924e-01 -1.97550365e-13 -2.43260775e-13] + ## [-2.39125924e-01 -2.99378416e-14 -9.57948807e-14]] + print("atmlst",atmlst,mygrad.atmlst) + ## copy of pbc.grad.khf.py + aoslices = rttddft.cell.aoslice_by_atom() + hcore_deriv = mygrad.hcore_generator(rttddft.mol) + de = np.zeros([Nat,3]) + + vhf_grad = mygrad.get_veff(dmat, kpts) + s1 = mygrad.get_ovlp( rttddft.cell, kpts) + dme0 = mygrad.make_rdm1e(mo_energy, mo_coeff, mo_occ) + + for x, ia in enumerate(atmlst): + p0, p1 = aoslices[ia,2:] + + print("#atmlst_%02d:"%(x),ia,p0,p1) + h1ao = hcore_deriv(ia) + de1 = np.einsum('xkij,kji->x', h1ao, dmat).real + de[x] += np.einsum('xkij,kji->x', h1ao, dmat).real + le=len(h1ao); assert le==spdm, "h1ao:"+str(np.shape(h1ao)) + print("h1ao:",np.shape(h1ao)) ## 3,nAO,nAO + for j in range(le): + DerivMatrices["hcore"][ spdm*x + j ] = arrayclone( h1ao[j] ) + DerivMatrices["de_hc"][ spdm*x + j ] = de1[j] + ## print("h1ao_j:", np.shape(h1ao[j]), np.shape( DerivMatrices["hcore"][ spdm*x + j ] )) (8, 19, 19) (8, 19, 19) + # nabla was applied on bra in vhf_grad, *2 for the contributions of nabla|ket> + de1 = np.einsum('xkij,kji->x', vhf_grad[:,:,p0:p1], dmat[:,:,p0:p1]).real * 2 + de[x] += np.einsum('xkij,kji->x', vhf_grad[:,:,p0:p1], dmat[:,:,p0:p1]).real * 2 + dbg_vhftrace(True, "", h1ao, vhf_grad,p0,p1,dmat,nkpts) + for j in range(le): + DerivMatrices["veff"][ spdm*x + j ] = arrayclonex( vhf_grad[j,:,p0:p1], np.shape(vhf_grad[j]), 1,[ p0,p1 ] ) + DerivMatrices["de_ve"][ spdm*x + j ] = de1[j] + # (3, 8, 19, 19) (3, 8, 5, 19) (3, 8, 19, 19) + # print("veff_j:", np.shape(vhf_grad), np.shape(vhf_grad[:,:,p0:p1]),np.shape( DerivMatrices["veff"][ spdm*x + j ] )) + de1 = -np.einsum('kxij,kji->x', s1[:,:,p0:p1], dme0[:,:,p0:p1]).real * 2 + de[x] -= np.einsum('kxij,kji->x', s1[:,:,p0:p1], dme0[:,:,p0:p1]).real * 2 + for j in range(le): + DerivMatrices["de_s1"][ spdm*x + j ] = de1[j] + + de[x] /= nkpts + de[x] += mygrad.extra_force(ia, locals()) + extraF = mygrad.extra_force(ia, locals()) + + # print("de[x]:",np.shape(de[x]),x,np.shape(de_nc)) ## de[x]: (3,) 1 (2, 3) + de[x] += de_nc[x] + ## this equals grad_de .. + for j in range(le): + DerivMatrices["de_nc"][ spdm*x + j ] = de_nc[x][j] + + print("#extra_Force:",extraF) # 0 + if( extraF != 0 ): + leF=len(extraF) + if( leF == 1 ): + for j in range(spdm): + DerivMatrices["extra"][ spdm*x + j ] = extraF + else: + for j in range(leF): + DerivMatrices["extra"][ spdm*x + j ] = extraF[j] + + + print("#Grad_de:",de); ## OK (egrad + ncgrad) + print("#DerivMatrices[veff]:",np.shape(DerivMatrices["veff"])) + for x, ia in enumerate(atmlst): + for j in range(3): + DerivMatrices["de_sum"][ spdm*x + j ]= DerivMatrices["de_nc"][ spdm*x + j ] + DerivMatrices["de_s1"][ spdm*x + j ]\ + + DerivMatrices["de_hc"][ spdm*x + j ] + DerivMatrices["de_ve"][ spdm*x + j ] +#Grad_de: [[ 2.39125924e-01 -1.98401564e-13 -2.43147439e-13] +# [-2.39125924e-01 -2.97821799e-14 -9.55382033e-14]] +# 0 Li 0.2391259237 -0.0000000000 -0.0000000000 +# 1 H -0.2391259237 -0.0000000000 -0.0000000000 + + diff=max( abs(np.ravel(de) - np.ravel(de_sum)) ) + ### assert diff < 1e-6,"diff:%e %s / %s"%(diff, str(de), str(de_sum)) + return de + + +def dbg_vhftrace(pbc,description,h1ao, vhf_grad,p0,p1,dmat,nKpt): + Ndim = np.shape(vhf_grad) + retv = np.einsum('xkij,kji->x', vhf_grad[:,:,p0:p1], dmat[:,:,p0:p1]).real * 2 / nKpt + refr =[] + vhf_Matr=[] + for j in range(3): + vhf_Matr.append( arrayclonex( vhf_grad[j, :, p0:p1 ]*2, np.shape( vhf_grad[j] ), 1, [p0,p1] ) ) ## we include factor 2 here + refr.append( dmtrace(pbc, vhf_Matr[j], dmat,title="DBG_vhftrace:"+description) ) + print("dbg_vhftrace:",retv,refr) +#calcForce::decomposition:de_ve: [0.18940722064783058, -1.2209338639400545e-12, 8.102987148622681e-13, -0.18940722064789706, 1.2647494007657436e-12, -7.777776706872856e-13] +# dbg_vhftrace: [ 1.89407221e-01 -1.22357588e-12 8.07765411e-13] [(0.18940722064785204+6.055902239317778e-14j), (-1.2235994094798608e-12-8.900191378437408e-12j), (8.077852155287619e-13-1.1945164388732031e-13j)] +#ref2: [(0.18940722064785204+6.055902239317778e-14j), (-1.2235994094798608e-12-8.900191378437408e-12j), (8.077852155287619e-13-1.1945164388732031e-13j)] +#ref3: [(0.18940722064785204+6.055902239317778e-14j), (-1.2235994094798608e-12-8.900191378437408e-12j), (8.077852155287619e-13-1.1945164388732031e-13j)] + +#[ 1.89407221e-01 -1.22093386e-12 8.10298715e-13] +# [(0.011837951290489439+3.78307677512285e-15j), (-7.630785384279695e-14-5.562614882754251e-13j), (5.064229449443219e-14-7.469133081230207e-15j)] + ref2=[] + for j in range(3): + cum=0.0 + 1j*0.0 + for kp in range(nKpt): + a = vhf_grad[j,kp,p0:p1]*2 ## nAO',nAO + b = dmat[kp,:,p0:p1] ## nAO, nAO' + axb=np.matmul(a,b) + le=len(axb) + tr= 0.0 + 1j*0.0 + for k in range(le): + tr+= axb[k][k] + cum +=tr + cum=cum/float(nKpt);ref2.append(cum) + print("#ref2:",ref2) +#ref2: [(0.09470361032391551+3.02646142009828e-14j), (-6.104628307423756e-13-4.450091906203401e-12j), (4.051383559554575e-13-5.975306464984165e-14j)] + ref3=[] + for j in range(3): + gr_j = arrayclonex( vhf_grad[j, :, p0:p1 ]*2, np.shape( vhf_grad[j] ), 1, [p0,p1] ) + cum=0.0 + 1j*0.0 + for kp in range(nKpt): + a = gr_j[kp] ## nAO',nAO + b = dmat[kp] ## nAO, nAO' + print("axb:",np.shape(a),np.shape(b)) + axb=np.matmul(a,b) + le=len(axb) + tr= 0.0 + 1j*0.0 + for k in range(le): + tr+= axb[k][k] + cum +=tr + cum=cum/float(nKpt);ref3.append(cum) + print("#ref3:",ref3) + return retv +#ref3: [(0.09470361032391551+3.02646142009828e-14j), (-6.104628307423756e-13-4.450091906203401e-12j), (4.051383559554575e-13-5.975306464984165e-14j)] + +def arrayclonex(src,Ndim,jth,Range): + # + # jth index [ Range[0]:Range[1] ] + # ret[:,..., (Range[0]:Range[1]),... ] = src[:,... ] + # |_ j_th + ret=np.zeros(Ndim, src.dtype) + rank=len(Ndim) + + Ndim_SRC=np.shape(src);rank_SRC=len(Ndim_SRC) + print("#arrayclonex:_%03d:[%d:%d] in %s"%(jth,Range[0],Range[1],str(Ndim))) + Ld_jth=Range[1]-Range[0]; + assert rank_SRC == rank, "" + assert jth>>get_derivMatrices_FFTDF:step:%02d/%d"%(Istep,Nstep),text=str(atmlst)) +### buf=get_derivMatrices_FFTDF_(md,rttddft,dmat=None, atmlst=atmlst) +### for ky in buf: +### item=buf[ky] +### if( ky not in ret ): +### ret.update({ky:item}) +### else: +### sub=ret[ky] +### ret.update({ky:concat_buffer(sub,item)}) +### heapcheck(">>>get_derivMatrices_FFTDF:end") +### return ret + +def get_derivMatrices_FFTDF(md,rttddft,Nat,dmat=None, fixedAtoms=None): +# +# retv :: Dict ["hcore","veff","E_el","E_nuc","extra"][ N_dir ][ scalar OR [nKpt][nAO][nAO] ] +# + import time + wt00=time.time();wt1=wt00;timing={} + atmlst=None ## default,all atoms + if( fixedAtoms is not None ): + atmlst=[] + for I in range(Nat): + if(I in fixedAtoms): + continue + atmlst.append(I) + from pyscf.pbc.grad.krks import Gradients + spdm=3 + if( dmat is None ): dmat = md.calc_tdDM(rttddft,ovrd=True) + # print("#get_derivMatrices_FFTDF:start") + if( rttddft.mo_coeff is None ): + rttddft.mo_coeff = md.tdMO + print("#get_derivMatrices_FFTDF::MO set:md.tdMO") + else: + diff=aNmaxdiff( rttddft.mo_coeff, md.tdMO ) + print("#get_derivMatrices_FFTDF::check_diff:|rttddft.mo - moldyn.tdMO|:%e"%(diff)) + + if( rttddft.mo_occ is None ): + rttddft.mo_occ = md.mo_occ + print("#get_derivMatrices_FFTDF::occ set:md.mo_occ",md.mo_occ) + else: + diff=aNmaxdiff( rttddft.mo_occ, md.mo_occ ) + print("#get_derivMatrices_FFTDF::check_diff:|rttddft.mo_occ - moldyn.mo_occ|:%e"%(diff)) + + if( rttddft.mo_energy is None ): + rttddft.mo_energy = get_eOrbs(md, rttddft) + print("#get_derivMatrices_FFTDF::mo_energy:md.mo_energy",np.shape(rttddft.mo_energy)) + else: + print("#get_derivMatrices_FFTDF::mo_energy:",np.shape(rttddft.mo_energy)) + + heapcheck(">>>> get_derivMatrices_FFTDF_.start") + mygrad = Gradients(rttddft) + wt2=wt1;wt1=time.time();timing.update({"prep":wt1-wt2}) + heapcheck(">>>> get_derivMatrices_FFTDF_.mygrad") + ## print("#get_derivMatrices_FFTDF::mygrad.base:",mygrad.base,mygrad.base.mo_occ) + Egrad_decomposition={};Dict_matrices={} + try: + if( atmlst is not None ): + Egrad = mygrad.kernel(atmlst=atmlst,decomposition=Egrad_decomposition, + fn_save_matrices=fn_save_matrices_std, buf_matrices=Dict_matrices) + heapcheck(">>>> get_derivMatrices_FFTDF_.af grad.kernel:Nat=%d/%d"%(len(atmlst),Nat) ) + else: + Egrad = mygrad.kernel(decomposition=Egrad_decomposition, + fn_save_matrices=fn_save_matrices_std, buf_matrices=Dict_matrices) + heapcheck(">>>> get_derivMatrices_FFTDF_.af grad.kernel:Nat=%d"%(Nat) ) + except TypeError as te: + print("#get_derivMatrices_FFTDF::TypeError",te) + raise + Egrad = mygrad.kernel(mo_energy=rttddft.mo_energy, mo_coeff=md.tdMO, mo_occ=md.mo_occ, + decomposition=Egrad_decomposition,fn_save_matrices=fn_save_matrices_std, buf_matrices=Dict_matrices) + wt2=wt1;wt1=time.time();timing.update({"grad_kernel":wt1-wt2}) + print("#get_derivMatrices_FFTDF::Egrad:",Egrad) + kpts = rttddft.kpts + nkpts = len(kpts) +# if( dmat is None ): +# dmat=rttddft.make_rdm1() + + mo_energy = mygrad.base.mo_energy + mo_coeff = mygrad.base.mo_coeff + mo_occ = mygrad.base.mo_occ + atmlst = mygrad.atmlst + if atmlst is None: + atmlst = range( rttddft.mol.natm ) + print("#get_derivMatrices_FFTDF:atmlst:",atmlst) + + print("#get_derivMatrices_FFTDF:Egrad_decomposition:",Egrad_decomposition); + de_el = Egrad_decomposition["de_el"] + de_nc = Egrad_decomposition["de_nc"] + ## de_el = mygrad.grad_elec(mo_energy, mo_coeff, mo_occ, atmlst) + ## de_nc = mygrad.grad_nuc(atmlst=atmlst) + + Nat=len(atmlst) + N_dir= spdm * Nat + DerivMatrices={} + for ky in ["hcore","veff","E_el","E_nuc","extra"]: ## we need "hcore","veff","E_nuc" + DerivMatrices.update({ky:[ None for k in range(N_dir) ]}) + DerivMatrices.update({"E_el":de_el}); print("#calcgrad_analytic_ref:DerivMatrices.E_el:",de_el); + DerivMatrices.update({"E_nuc":de_nc});print("#calcgrad_analytic_ref:DerivMatrices.E_nuc:",de_nc); + de_sum = np.array(de_el) + np.array(de_nc) + + aoslices = rttddft.cell.aoslice_by_atom() + hcore_deriv = None + if( "hcore" not in Dict_matrices): + hcore_deriv = mygrad.hcore_generator(rttddft.mol) + de = np.zeros([Nat,3]) + + if("vhf" in Dict_matrices): + vhf_grad = Dict_matrices["vhf"] + else: + vhf_grad = mygrad.get_veff(dmat, kpts) + wt2=wt1;wt1=time.time();timing.update({"vhf_grad":wt1-wt2}) + + s1 = mygrad.get_ovlp( rttddft.cell, kpts) + wt2=wt1;wt1=time.time();timing.update({"s1":wt1-wt2}) + dme0 = mygrad.make_rdm1e(mo_energy, mo_coeff, mo_occ) + wt2=wt1;wt1=time.time();timing.update({"rdm1e":wt1-wt2}) + + de_ve=[]; de_hc=[]; de_s1=[] + for x, ia in enumerate(atmlst): + p0, p1 = aoslices[ia,2:] + if( "hcore" not in Dict_matrices): + h1ao = hcore_deriv(ia) + wt2=wt1;wt1=time.time(); + if("h1ao" not in timing): + timing.update({"h1ao":wt1-wt2}) + else: + timing["h1ao"]+=wt1-wt2 + else: + h1ao = Dict_matrices["hcore"][x] + if( "x_to_ia" in Dict_matrices ): + idum = Dict_matrices["x_to_ia"][x] + assert (ia==idum),"%d/%d"%(ia,idum)+str(Dict_matrices["x_to_ia"]) + de_hc.append( np.einsum('xkij,kji->x', h1ao, dmat).real/float(nkpts) ) + de[x] += np.einsum('xkij,kji->x', h1ao, dmat).real + le=len(h1ao); assert le==spdm, "h1ao:"+str(np.shape(h1ao)) + ### print("h1ao:",np.shape(h1ao)) ## 3,nAO,nAO + for j in range(le): + DerivMatrices["hcore"][ spdm*x + j ] = arrayclone( h1ao[j] ) + ### print("h1ao_j:", np.shape(h1ao[j]), np.shape( DerivMatrices["hcore"][ spdm*x + j ] )) (8, 19, 19) (8, 19, 19) + + de[x] += np.einsum('xkij,kji->x', vhf_grad[:,:,p0:p1], dmat[:,:,p0:p1]).real * 2 + de_ve_einsum = np.einsum('xkij,kji->x', vhf_grad[:,:,p0:p1], dmat[:,:,p0:p1]).real * 2 /float(nkpts) + de_ve_x = []; + for j in range(le): + DerivMatrices["veff"][ spdm*x + j ] = arrayclonex( vhf_grad[j,:,p0:p1]*2, np.shape(vhf_grad[j]), 1,[ p0,p1 ] ) + trVeDm =dmtrace(md.pbc, DerivMatrices["veff"][ spdm*x + j ], dmat,title="DBG_vhftrace:") ## takes account of nkpts + de_ve_x.append( trVeDm ) + # assert abs(trVeDm - de_ve_einsum[j])<1e-7,"%e / %e"%(trVeDm,de_ve_einsum[j]) + # 2022.01.14 I added factor *2 + # (3, 8, 19, 19) (3, 8, 5, 19) (3, 8, 19, 19) + # print("veff_j:", np.shape(vhf_grad), np.shape(vhf_grad[:,:,p0:p1]),np.shape( DerivMatrices["veff"][ spdm*x + j ] )) + dev = max( np.ravel(de_ve_einsum) -np.ravel(de_ve_x)); + assert dev<1e-6,"" + de_ve.append( de_ve_x ) + de_s1_x = -np.einsum('kxij,kji->x', s1[:,:,p0:p1], dme0[:,:,p0:p1]).real * 2 /float(nkpts) + de[x] -= np.einsum('kxij,kji->x', s1[:,:,p0:p1], dme0[:,:,p0:p1]).real * 2 + de_s1.append( de_s1_x ) + + de[x] /= nkpts + if( "extra" in Dict_matrices): + extraF = Dict_matrices["extra"][x] + else: + extraF = mygrad.extra_force(ia, locals()) + de[x] += extraF + de[x] += de_nc[x] + + # print("#extra_Force:",extraF) # 0 (scalar) + if( extraF != 0 ): + leF=len(extraF) + if( leF == 1 ): + for j in range(spdm): + DerivMatrices["extra"][ spdm*x + j ] = extraF + else: + for j in range(leF): + DerivMatrices["extra"][ spdm*x + j ] = extraF[j] + wt2=wt1;wt1=time.time();timing.update({"einsum":wt1-wt2}) + diff=max( abs(np.ravel(de) - np.ravel(de_sum)) ) + assertf( diff<1e-6,"de:%s / %s"%(str(de),str(de_sum)),level=1) + de_hc=np.ravel(de_hc);de_ve=np.ravel(de_ve);de_s1=np.ravel(de_s1);de_nc1D=np.ravel(de_nc) + le=len(de_hc) + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + n_call = rttddft_common.Countup("get_derivMatrices_FFTDF") + if( (n_call < 3 or n_call == 20) and MPIrank==0 ): + print("#get_derivMatrices_FFTDF:decomposition:de_SUM_el:",[ (de_hc[k] + de_ve[k] + de_s1[k]) for k in range(le) ]) + print("#get_derivMatrices_FFTDF:decomposition:de_SUM_tot:",[ (de_hc[k] + de_ve[k] + de_s1[k] + de_nc1D[k]) for k in range(le) ]) + + assert diff<1e-6,"" + heapcheck(">>>> get_derivMatrices_FFTDF_.END") + wt2=wt1;wt1=time.time();timing.update({"misc":wt1-wt2}) + + if( n_call < 3 or n_call == 20 or (MPIrank==0 and n_call % 200 == 0) ): + print("#get_derivMatrices:$%02d:n_call%d:elapsed:%f "%(MPIrank,n_call,wt1-wt00)+str(timing)) + return DerivMatrices + + +#calcForce::decomposition:de_hc: [-0.6048776445325672, 8.792403894534924e-12, -3.1558318916535685e-12, 0.604877644536944, -9.06252851525815e-12, 2.7832008400214535e-12] +#calcForce::decomposition:de_ve: [0.18940722064785215, -1.223575882398597e-12, 8.077654110514213e-13, -0.1894072206479185, 1.2673528294682205e-12, -7.751768152964514e-13] +#calcForce::decomposition:de_s1: [-0.00641148674594829, -7.764954972129708e-12, 2.1050545810436393e-12, 0.006411486745948649, 7.763403923918255e-12, -2.1037317874404715e-12] +#calcForce::decomposition:de_nc: [0.661007834315346, -1.582067810090848e-15, 2.42861286636753e-17, -0.6610078343153459, 1.6930901125533637e-15, 8.673617379884035e-17] +#calcForce::decomposition:de_sum: [0.23912592368468272, -1.9770902780347243e-13, -2.429876134298442e-13, -0.2391259236803718, -3.007867175912176e-14, -9.562102654167053e-14] +#---------------- +# -6.04877645e-01 + 0.189407220647904 -6.41148675e-03 +#get_derivMatrices_FFTDF:decomposition:de: [[ 2.39125924e-01 -1.97974644e-13 -2.43014473e-13][-2.39125924e-01 -2.98949839e-14 -9.55658494e-14]] +#get_derivMatrices_FFTDF:decomposition:de_hc: [array([-6.04877645e-01, 8.78584213e-12, -3.15464950e-12]), array([ 6.04877645e-01, -9.05599012e-12, 2.78204792e-12])] +#get_derivMatrices_FFTDF:decomposition:de_ve: [[(0.189407220647904+6.060717360941057e-14j), (-1.2194162514183814e-12-8.900234007133403e-12j), (8.043008872629098e-13-1.1939335589588766e-13j)], [(-0.1894072206479706-6.177722945483058e-14j), (1.2631207411529085e-12-1.6996542016366935e-15j), (-7.717209523184741e-13+2.2768259554397516e-15j)]] +#get_derivMatrices_FFTDF:decomposition:de_s1: [array([-6.41148675e-03, -7.76282649e-12, 2.10729056e-12]), array([ 6.41148675e-03, 7.76127545e-12, -2.10597145e-12])] +#get_derivMatrices_FFTDF:decomposition:de_SUM: [(-0.4218819106306605+6.060717360941057e-14j), (-1.9640061461054911e-13-8.900234007133403e-12j), (-2.4305804815260727e-13-1.1939335589588766e-13j), (0.4218819106349726-6.177722945483058e-14j), (-3.159393465172485e-14-1.6996542016366935e-15j), (-9.564448447206493e-14+2.2768259554397516e-15j)] +#get_derivMatrices_FFTDF:decomposition:de: [[ 2.39125924e-01 -1.97740343e-13 -2.42813838e-13][-2.39125924e-01 -2.96294247e-14 -9.57975145e-14]] +#get_derivMatrices_FFTDF:decomposition:de_hc: [array([-6.04877645e-01, 8.77734037e-12, -3.16133005e-12]), array([ 6.04877645e-01, -9.04744418e-12, 2.78871370e-12])] +#get_derivMatrices_FFTDF:decomposition:de_ve: [[(0.18940722064782067+6.063017054759368e-14j), (-1.2187964451932518e-12-8.90022237725848e-12j), (8.073021354744291e-13-1.1951131488111554e-13j)], [(-0.18940722064788743-6.176721904863186e-14j), (1.2629824019592143e-12-1.698066185035282e-15j), (-7.74733394092281e-13+2.2804314402416723e-15j)]] +#get_derivMatrices_FFTDF:decomposition:de_s1: [array([-6.41148675e-03, -7.75469846e-12, 2.11118352e-12]), array([ 6.41148675e-03, 7.75314676e-12, -2.10986267e-12])] +#get_derivMatrices_FFTDF:decomposition:de_SUM: [(-0.4218819106306605+6.063017054759368e-14j), (-1.9615453588342445e-13-8.90022237725848e-12j), (-2.4284439387733383e-13-1.1951131488111554e-13j), (0.421881910634975-6.176721904863186e-14j), (-3.131502240630195e-14-1.698066185035282e-15j), (-9.588236984042695e-14+2.2804314402416723e-15j)] + +# print("#get_derivMatrices_FFTDF:decomposition:de:",de) +# print("#get_derivMatrices_FFTDF:decomposition:de_hc:",de_hc) # [ 4.83902116e+00 -7.25173118e-11 2.23130409e-11] +# print("#get_derivMatrices_FFTDF:decomposition:de_ve:",de_ve) +# [ [(0.1894072206477209+6.063126496833584e-14j), (-1.2281381848999787e-12-8.900200137431778e-12j), (8.080897407252345e-13-1.1946683087308191e-13j)], +# [(-0.18940722064778714-6.17692666198519e-14j), (1.2719304961047628e-12-1.7058857014271801e-15j), (-7.754284352342526e-13+2.2895488658148303e-15j)]] +# get_derivMatrices_FFTDF:decomposition:de_s1: [array([-6.41148675e-03, -7.76284290e-12, 2.11073496e-12]), array([ 6.41148675e-03, 7.76129120e-12, -2.10940827e-12])] +# print("#get_derivMatrices_FFTDF:decomposition:de_s1:",de_s1) + +def assertf(bool,msg,loglv=0,level=-1): + if( loglv > 0 or (not bool) ): + fd=open("assertf.log","a") + strbuf=("#assertf:log:" if(bool) else "#python assertion failed:")+str(msg)+" \t "+str(datetime.datetime.now())\ + +( " \t\t "+str(rttddft_common.get_job(True)) if(rttddft_common.get_job(True) is not None) else "") + print(strbuf,file=fd); + fd.close() + if(bool): + return 0 + if(level >=0 ): + print(strbuf);return 1 + assert False,strbuf diff --git a/pyscf/rttddft/calc_OAS.py b/pyscf/rttddft/calc_OAS.py new file mode 100644 index 000000000..1bb04f87f --- /dev/null +++ b/pyscf/rttddft/calc_OAS.py @@ -0,0 +1,345 @@ +import sys +import numpy as np +import os +import os.path +import time +from scipy import linalg + +from pyscf.pbc.gto import intor_cross +from pyscf.pbc.dft import KRKS +import pyscf.gto as molgto +from pyscf.gto import Mole +from pyscf.pbc.gto import Cell +from pyscf.gto import Mole +from pyscf.pbc import gto, scf, dft, df +from pyscf.pbc.scf.khf import get_occ as khf_get_occ +from pyscf.pbc.scf.khf import make_rdm1 as khf_make_rdm1 + +from .pyscf_common import pyscf_common + +from .MPIutils01 import MPIutils01 + +from .physicalconstants import physicalconstants +from .utils import read_inpf,read_xyzf,dump_zNarray,distinct_set,get_strPolarization,parse_doubles,parse_ints +from .laserfield import * + +from .diis01 import DIIS01 +#from rttddft01 import load_Aind_over_c,rttddftPBC, rttddftMOL,serialize_rttddft,get_dipole +from .rttddft01 import load_Aind_over_c,rttddftPBC, rttddftMOL,get_dipole +from .eldyn import calc_OAS +from .Moldyn import Moldyn,calc_mo_energies,get_FockMat +from .serialize import serialize,serialize_CDIIS +from .bandstructure import calc_bandstructure,plot_dispersion_kLine,calc_ldos +from .GEAR import initz_rGEARvec +from .with_fftdf_get_pp import dbg_fftdf_get_pp + +#PhysicalConstants_=get_constants(); +aut_in_femtosec= physicalconstants.aut_in_femtosec; #PhysicalConstants_['_aut']*1.0e+15 ## i.e. .00241888 femtosec never use ['AUT'] +HARTREEinEV = physicalconstants.HARTREEinEV; #PhysicalConstants_['Hartree'] +KelvinINeV=8.6173324e-5 + + +params_inp=None + +argv=sys.argv +narg=len(argv) +iarg=0 # start from argv[1] (not 0) +help=False +while(iarg1) else \ + ("%eK"%(Temperature_Kelvin)).strip()) + +restart=None +if( params["restart"] is not None ): + restart=int( params["restart"] ) +if( restart is not None ): + job=job+"_%02d"%(restart) + +pyscf_common.set_params(params,job) +MPIutils01.setup() + +cell_dimension=None +if( params["dimension"] is not None): + params["dimension"]=int(params["dimension"]) + cell_dimension=params["dimension"] +if( params["spin"] is not None): + params["spin"]=int(params["spin"]) +if( params["charge"] is not None): + params["charge"]=float(params["charge"]) +if( params["cell_precision"] is not None): + params["cell_precision"]=float(params["cell_precision"]) +if( params["exp_to_discard"] is not None): + params["exp_to_discard"] = float( params["exp_to_discard"] ) +if( params["mesh"] is not None): + params["mesh"]=parse_ints( params["mesh"] ) +if( params["rcut"] is not None): + params["rcut"]=float( params["rcut"] ) +if( params["Nstep_calcEng"] is not None): + params["Nstep_calcEng"]=int( params["Nstep_calcEng"] ) +if( params["calc_Aind"] is not None): + params["calc_Aind"]=int( params["calc_Aind"] ) +dt_as=float(params["timestep_as"]) +dt_AU=(dt_as*1.0e-3)/physicalconstants.aut_in_femtosec + + +spinrestriction=params["spinrestriction"];DFT=None +if( params["spinrestriction"] is None ): + assert ( (params["spin"] is None) or (params["spin"]==0) ),"please set spinrestriction" + spinrestriction='R';DFT="RKS" +else: + DFT=('RKS' if(spinrestriction=='R') else ('UKS' if(spinrestriction=='U') else ('ROKS' if(spinrestriction=='O') else None))) + +assert DFT is not None,"wrong spinrestriction:"+spinrestriction + + +moldyn=None; tm_fs_offset=None; dmfilepath=None +if( params["restart"] is not None): + assert ( params["moldyn_pscf"] is not None),"" + assert ( params["tm_fs_offset"] is not None),"" + assert ( params["dmfilepath"] is not None),"" + + assert os.path.exists(params["moldyn_pscf"]),"" + moldyn=Moldyn.load(params["moldyn_pscf"]) + print("#tdMO:af_Moldyn.load:%s .."%( str(moldyn.tdMO[0][0]) )) + # dump_zNarray(moldyn.tdMO, fpath=params["moldyn_pscf"]+"_load_tdMO.dmp") + tm_fs_offset=float( params["tm_fs_offset"] ) + tm_au_offset=tm_fs_offset/aut_in_femtosec + assert (abs(moldyn.time_AU-tm_au_offset)<1.0e-5),"%16.8f / %16.8f"%(moldyn.time_AU,tm_au_offset) + dmfilepath=params["dmfilepath"] + +else: + assert ( params["moldyn_pscf"] is None),"" + assert params["tm_fs_offset"] is None,"" + + ## + ## moldyn.gauge_LorV is set None at this point + ## in velocity gauge calculation, it will later be set 'V' inside -calc_OAS- subroutine... + ## + if( not PBC ): + moldyn=Moldyn( pbc=PBC, xyzf=params["xyzf"], basis=params["basis"],pseudo=params["pseudo"], + exp_to_discard=params["exp_to_discard"],spin=params["spin"], charge=params["charge"],mesh=params["mesh"], + rcut=params["rcut"],gauge_LorV=None,df=params["df"],DFT=DFT, + fixednucleiapprox=params["fixednucleiapprox"], + Temperature_Kelvin=Temperature_Kelvin, + xc=params["xc"], calc_Aind=None, dt_AU=dt_AU) + else: + assert (params["nKpoints"] is not None),"nKpoints" + nKpoints = parse_ints( params["nKpoints"] ) + dict={"a":None};R,Sy=read_xyzf(params["xyzf"],dict=dict) + moldyn=Moldyn( pbc=PBC, xyzf=params["xyzf"], basis=params["basis"], pseudo=params["pseudo"], + exp_to_discard=params["exp_to_discard"],spin=params["spin"], charge=params["charge"],mesh=params["mesh"], + rcut=params["rcut"],gauge_LorV=None,df=params["df"], DFT=DFT, + a=dict["a"],nKpoints=nKpoints, cell_dimension=cell_dimension, + check_timing=params["check_timing"],cell_precision=params["cell_precision"], + fixednucleiapprox=params["fixednucleiapprox"], + Temperature_Kelvin=Temperature_Kelvin, + xc=params["xc"], calc_Aind=params["calc_Aind"], dt_AU=dt_AU,alpha_Aind_over_c=params["alpha_Aind_over_c"] ) + dmfilepath=params["dmfilepath"] # most likely to be None + +set_occ=( None if( params["restart"] is None ) else True ) +rttddft = moldyn.gen_rttddft(set_occ=set_occ) + +if( PBC ): + if( gauge_DorV == 'V' ): + rttddft.set_constantfield(True) + +if( params["restart"] is not None ): + ## 2021.08.25 --- it looks that rttddft thus constructed causes error if we invoke get_fermi for example + ## since mo_energy_kpts field is None ( it works perfectly for calc_OAS but print_TDeorbs fails ) + ## here we copy from restart step in eldyn_main.py ... + if( params["Nstep_calcEng"] is not None ): + if( rttddft.mo_occ is None ): + rttddft.mo_occ = rttddft._mo_occ + calc_mo_energies(moldyn,rttddft,update_rttddft=True) + + +if( params["levelshift"] is not None ): + rttddft.level_shift=float(params["levelshift"]) + +if( params["load_Aind_over_c"] is not None ): + print("#load int Aind_over_c :"+str(params["load_Aind_over_c"]),flush=True) + time_AU=moldyn.time_AU + Aind_over_c=load_Aind_over_c( rttddft, time_AU, rttddft._dt_AU, params["load_Aind_over_c"] ) + rttddft._Aind_tmAU = time_AU + assert rttddft._dt_AU>1.0e-8 and rttddft._Aind_tmAU>1.0e-6,"" + rttddft._Aind_Gearvc_C, rttddft._Aind_Gearvc_P = initz_rGEARvec( rttddft._dt_AU, np.array(Aind_over_c), np.zeros([3]) ,np.zeros([3]) ,3) + print("#load_Aind_over_c done",flush=True) + +observables=[] +if( params["observables"] is not None ): + observables=( params["observables"].strip() ).split(','); + No=len(observables); + for Io in range(No): + observables[Io]=observables[Io].strip() + +if( params["testrun"] is not None ): + assert False,"testrun" + +if( params["restart"] is None ): + moldyn.calc_gs(rttddft) + + if( "bandstructure" in params ): + bs=params[ "bandstructure" ] + if( bs is not None ): + ## for dimer dispersion, set "dimerization":2,2,2 in params.inp ... + lattice=bs.strip() + dmat= rttddft.make_rdm1() + plot_dispersion_kLine(str(pyscf_common.job)+"_gs_dispersion.dat",rttddft,dmat,moldyn.BravaisVectors_au, + lattice=lattice) + if( "calc_gsDOS" in params ): + if( params["calc_gsDOS"] is not None ): + if( eval(params["calc_gsDOS"]) ): + FockMat=get_FockMat(moldyn,rttddft) + calc_ldos(rttddft, job+"_gsDOS.dat", moldyn._canonicalMOs, FockMat, de_eV=0.01, + moldyn=moldyn, widths_eV=[0.2123, 0.02123] ) + + R,Sy=read_xyzf(params["xyzf"]);distinctAtms=distinct_set(Sy); + moldip=[] + dict_dipoles= get_dipole( rttddft, moldyn.tdDM,'B',filepath=None,header=None,molecular_dipole=moldip,caller="calc_OAS.L247") + + strdipoles="";legend_dipoles="" + if( moldyn.spinrestriction !='U' ): + strdipoles="%16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %18.8f %18.8f %18.8f"%( + dict_dipoles['dipole'][0], dict_dipoles['dipole'][1], dict_dipoles['dipole'][2], + dict_dipoles['dipole_velocity'][0], dict_dipoles['dipole_velocity'][1], dict_dipoles['dipole_velocity'][2], + moldip[0][0], moldip[0][1], moldip[0][2]) + legend_dipoles="%16s %16s %16s %16s %16s %16s %18s %18s %18s"%( + "dipole_x","dipole_y","dipole_z","dipvel_x","dipvel_y","dipvel_z","moldip_x","moldip_y","moldip_z"); + Nat=len(Sy) + +if( params["restart"] is not None): + dump_zNarray(rttddft.mo_coeff, fpath=params["moldyn_pscf"]+"_load_tdMO_rttddft.dmp") + print("#tdMO:af_Moldyn.load:%s .."%( str(moldyn.tdMO[0][0]) )) + +check_timing=(False if(params["check_timing"] is None) else params["check_timing"]) + +if( dmfilepath is None ): + dmfilepath = job+"_dm.dat" +tm_fs_end=float( params["tm_fs_end"] ) +timestep_as = float( params["timestep_as"]) +tm_fs_step = (1.0e-3)*timestep_as +tmKick_AU= None if(params["tmKick_AU"] is None) else float(params["tmKick_AU"]) +Nstep_Kick = int( params["Nstep_Kick"]) + +# Propagator : +# The default propagator is the Crank-Nicolson propagator ("CN") +# We have optionally implemented the 2nd order Magnus propagator but it did not improve performance +# +propagator=default_propagator +if( "propagator" in params ): + if( params["propagator"] is not None): + propagator=params["propagator"] + +# Dump file options: +# You can specify the point you output the dump file (file needed for restarting). +# (i) Every N steps +# (ii) N hour after starting calculation +# +Nstep_dump=(None if(params["Nstep_dump"] is None) else int(params["Nstep_dump"])) +tmsecond_dump=None; +if( params["tm_hour_to_dump"] is not None ): + hr=float( params["tm_hour_to_dump"] ) + tsecond_dump=hr*60*60 + +calc_OAS(moldyn, rttddft, Evector, gauge_DorV, dmfilepath, + tm_fs_end=tm_fs_end, tm_fs_step=tm_fs_step, tm_fs_offset=tm_fs_offset, + tmKick_AU=tmKick_AU, Nstep_Kick=Nstep_Kick,logfile="OAS_"+job+".log", + propagator=propagator, Nstep_dump=Nstep_dump, tsecond_dump=tsecond_dump, WCt00=WCt00, + dumpfilename="OAS_"+job, Nstep_calcEng=params["Nstep_calcEng"], + Nstep_calcDOS=params["Nstep_calcDOS"],check_timing=check_timing, params=params ) diff --git a/pyscf/rttddft/diis.py b/pyscf/rttddft/diis.py new file mode 100644 index 000000000..828c5589a --- /dev/null +++ b/pyscf/rttddft/diis.py @@ -0,0 +1,438 @@ +#!/usr/bin/env python +# Copyright 2014-2018 The PySCF Developers. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Author: Qiming Sun +# + +""" +DIIS +""" + +from functools import reduce +import numpy +import scipy.linalg +import scipy.optimize +from pyscf import lib +from pyscf.lib import logger + +DEBUG = False + +# J. Mol. Struct. 114, 31-34 (1984); DOI:10.1016/S0022-2860(84)87198-7 +# PCCP, 4, 11 (2002); DOI:10.1039/B108658H +# GEDIIS, JCTC, 2, 835 (2006); DOI:10.1021/ct050275a +# C2DIIS, IJQC, 45, 31 (1993); DOI:10.1002/qua.560450106 +# SCF-EDIIS, JCP 116, 8255 (2002); DOI:10.1063/1.1470195 + +# error vector = SDF-FDS +# error vector = F_ai ~ (S-SDS)*S^{-1}FDS = FDS - SDFDS ~ FDS-SDF in converge +class CDIIS(lib.diis.DIIS): + def __init__(self, mf=None, filename=None): + lib.diis.DIIS.__init__(self, mf, filename) + self.rollback = False + self.space = 8 + + def update(self, s, d, f, *args, **kwargs): + errvec = get_err_vec(s, d, f) + logger.debug1(self, 'diis-norm(errvec)=%g', numpy.linalg.norm(errvec)) + xnew = lib.diis.DIIS.update(self, f, xerr=errvec) + if self.rollback > 0 and len(self._bookkeep) == self.space: + self._bookkeep = self._bookkeep[-self.rollback:] + return xnew + + def get_num_vec(self): + if self.rollback: + return self._head + else: + return len(self._bookkeep) + +SCFDIIS = SCF_DIIS = DIIS = CDIIS + +def get_err_vec(s, d, f): + '''error vector = SDF - FDS''' + if isinstance(f, numpy.ndarray) and f.ndim == 2: + sdf = reduce(numpy.dot, (s,d,f)) + errvec = sdf.T.conj() - sdf + + elif isinstance(f, numpy.ndarray) and f.ndim == 3 and s.ndim == 3: + errvec = [] + for i in range(f.shape[0]): + sdf = reduce(numpy.dot, (s[i], d[i], f[i])) + errvec.append((sdf.T.conj() - sdf)) + errvec = numpy.vstack(errvec) + + elif f.ndim == s.ndim+1 and f.shape[0] == 2: # for UHF + nao = s.shape[-1] + s = lib.asarray((s,s)).reshape(-1,nao,nao) + return get_err_vec(s, d.reshape(s.shape), f.reshape(s.shape)) + else: + raise RuntimeError('Unknown SCF DIIS type') + return errvec + + +class EDIIS(lib.diis.DIIS): + '''SCF-EDIIS + Ref: JCP 116, 8255 (2002); DOI:10.1063/1.1470195 + ''' + def update(self, s, d, f, mf, h1e, vhf): + if self._head >= self.space: + self._head = 0 + if not self._buffer: + shape = (self.space,) + f.shape + self._buffer['dm' ] = numpy.zeros(shape, dtype=f.dtype) + self._buffer['fock'] = numpy.zeros(shape, dtype=f.dtype) + self._buffer['etot'] = numpy.zeros(self.space) + self._buffer['dm' ][self._head] = d + self._buffer['fock'][self._head] = f + self._buffer['etot'][self._head] = mf.energy_elec(d, h1e, vhf)[0] + self._head += 1 + + ds = self._buffer['dm' ] + fs = self._buffer['fock'] + es = self._buffer['etot'] + etot, c = ediis_minimize(es, ds, fs) + logger.debug1(self, 'E %s diis-c %s', etot, c) + fock = numpy.einsum('i,i...pq->...pq', c, fs) + return fock + +def ediis_minimize(es, ds, fs): + nx = es.size + nao = ds.shape[-1] + ds = ds.reshape(nx,-1,nao,nao) + fs = fs.reshape(nx,-1,nao,nao) + df = numpy.einsum('inpq,jnqp->ij', ds, fs).real + diag = df.diagonal() + df = diag[:,None] + diag - df - df.T + + def costf(x): + c = x**2 / (x**2).sum() + return numpy.einsum('i,i', c, es) - numpy.einsum('i,ij,j', c, df, c) + + def grad(x): + x2sum = (x**2).sum() + c = x**2 / x2sum + fc = es - 2*numpy.einsum('i,ik->k', c, df) + cx = numpy.diag(x*x2sum) - numpy.einsum('k,n->kn', x**2, x) + cx *= 2/x2sum**2 + return numpy.einsum('k,kn->n', fc, cx) + + if DEBUG: + x0 = numpy.random.random(nx) + dfx0 = numpy.zeros_like(x0) + for i in range(nx): + x1 = x0.copy() + x1[i] += 1e-4 + dfx0[i] = (costf(x1) - costf(x0))*1e4 + print((dfx0 - grad(x0)) / dfx0) + + res = scipy.optimize.minimize(costf, numpy.ones(nx), method='BFGS', + jac=grad, tol=1e-9) + return res.fun, (res.x**2)/(res.x**2).sum() + + +class ADIIS(lib.diis.DIIS): + ''' + Ref: JCP 132, 054109 (2010); DOI:10.1063/1.3304922 + ''' + def update(self, s, d, f, mf, h1e, vhf): + if self._head >= self.space: + self._head = 0 + if not self._buffer: + shape = (self.space,) + f.shape + self._buffer['dm' ] = numpy.zeros(shape, dtype=f.dtype) + self._buffer['fock'] = numpy.zeros(shape, dtype=f.dtype) + self._buffer['dm' ][self._head] = d + self._buffer['fock'][self._head] = f + + ds = self._buffer['dm' ] + fs = self._buffer['fock'] + fun, c = adiis_minimize(ds, fs, self._head) + if self.verbose >= logger.DEBUG1: + etot = mf.energy_elec(d, h1e, vhf)[0] + fun + logger.debug1(self, 'E %s diis-c %s ', etot, c) + fock = numpy.einsum('i,i...pq->...pq', c, fs) + self._head += 1 + return fock + +def adiis_minimize(ds, fs, idnewest): + nx = ds.shape[0] + nao = ds.shape[-1] + ds = ds.reshape(nx,-1,nao,nao) + fs = fs.reshape(nx,-1,nao,nao) + df = numpy.einsum('inpq,jnqp->ij', ds, fs).real + d_fn = df[:,idnewest] + dn_f = df[idnewest] + dn_fn = df[idnewest,idnewest] + dd_fn = d_fn - dn_fn + df = df - d_fn[:,None] - dn_f + dn_fn + + def costf(x): + c = x**2 / (x**2).sum() + return (numpy.einsum('i,i', c, dd_fn) * 2 + + numpy.einsum('i,ij,j', c, df, c)) + + def grad(x): + x2sum = (x**2).sum() + c = x**2 / x2sum + fc = 2*dd_fn + fc+= numpy.einsum('j,kj->k', c, df) + fc+= numpy.einsum('i,ik->k', c, df) + cx = numpy.diag(x*x2sum) - numpy.einsum('k,n->kn', x**2, x) + cx *= 2/x2sum**2 + return numpy.einsum('k,kn->n', fc, cx) + + if DEBUG: + x0 = numpy.random.random(nx) + dfx0 = numpy.zeros_like(x0) + for i in range(nx): + x1 = x0.copy() + x1[i] += 1e-4 + dfx0[i] = (costf(x1) - costf(x0))*1e4 + print((dfx0 - grad(x0)) / dfx0) + + res = scipy.optimize.minimize(costf, numpy.ones(nx), method='BFGS', + jac=grad, tol=1e-9) + return res.fun, (res.x**2)/(res.x**2).sum() + +class DIIS_dmat: + def __init__(self,size,pbc,scheme="SDFFDS",istep_start_DIIS=6): + self.size=size; + self.nbuf=0 + self.scheme=scheme + self.vecbuf=[ None for j in range(self.nbuf) ] + self.erbuf= [ None for j in range(self.nbuf) ] + self.pbc=pbc + self.minimum_buflen = 4 + self.status=0 + self.step=-1 + self.thr_start_DIIS = 1.0e-3 + self.nstep_start_DIIS = 6 + self.Ndim_dmat=None + self.Ld_dmat=None + self.dtype=None + self.mixing_ratio=0.50 ## 1 means full update + self.S1e=None;self.nKpoints=None + self.mat=None + self.istep_start_DIIS= istep_start_DIIS + self.rollback=None;self.space=size ## we formally define these parameters +## DM[nKpoints][nAO][nAO] + def inner_product(self,lhs1D,rhs1D): + if( self.S1e is None ): + return numpy.vdot( lhs1D,rhs1D) + else: + Lhs=numpy.reshape(lhs1D,self.Ndim_dmat) + Rhs=numpy.reshape(rhs1D,self.Ndim_dmat) + nKpoints=(1 if(not self.pbc) else self.Ndim_dmat[0]) + cum=0.0 + for kp in range(nKpoints): + lh=( Lhs if(not self.pbc) else Lhs[kp] ) + rh=( Rhs if(not self.pbc) else Rhs[kp] ) + s1=( self.S1e if(not self.pbc) else self.S1e[kp] ) + dum = numpy.matmul( lh, numpy.matmul( s1, numpy.matmul( rh, s1))) + ld=len(dum) + for j in range(ld): + cum+=dum[j][j] + if(self.pbc): + cum=cum/nKpoints + return cum + + def get_damped_dmat(self, ibuf, Dmat1D): + if( ibuf == 0 ): + print("#DIIS_dmat:damped_dmat:%d 1*New"%(self.step)) + return numpy.reshape( Dmat1D, self.Ndim_dmat ) + else: + last=(ibuf-1)%self.size + print("#DIIS_dmat:damped_dmat:%d %f*New + (1-r)*Old[%d] "%(self.step,self.mixing_ratio,last )) + return numpy.reshape( self.mixing_ratio * Dmat1D + ( 1 - self.mixing_ratio )* self.vecbuf[last], \ + self.Ndim_dmat ) + def clear_buffers(self): + print("#DIIS_dmat.clear..:"); + self.Ndim_dmat=None;self.Ld_dmat=None;self.dtype=None + self.vecbuf.clear();self.erbuf.clear();self.mat=None;self.nbuf=0 + self.status=0;self.step=-1 + + def update(self, istep, Dmat, ervec=None, S1e=None,Fock=None, ervec_norm=None): + print("#DIIS_dmat.update:istep,nbuf:",istep,self.nbuf) + self.step=istep + if( self.Ndim_dmat is None ): + self.Ndim_dmat = numpy.shape(Dmat) + rank=len(self.Ndim_dmat) + Ld=self.Ndim_dmat[0] + for j in range(1,rank): + Ld=Ld*self.Ndim_dmat[j] + self.Ld_dmat=Ld + + dtype=( Dmat.dtype if(isinstance(Dmat,numpy.ndarray)) else \ + numpy.array( Dmat[0] ).dtype ) + self.dtype=dtype + print("#DIIS_dmat.update:Ndim,Ld,dtype:",self.Ndim_dmat,Ld,self.dtype ) + dtype=( Dmat.dtype if(isinstance(Dmat,numpy.ndarray)) else \ + numpy.array( Dmat[0] ).dtype ) + if( self.dtype != dtype ): + print("#DIIS.dtype:",self.dtype,dtype) + self.dtype=dtype + + Dm1D=numpy.ravel(Dmat) + + if( ervec is None ): + ervec= self.calc_errorvec( Dmat,S1e=S1e,Fock=Fock) + if( self.status == 0 ): + ## DIIS is not yet started + if( ervec is not None ): + ermax= max(ervec) + skip_diis =(ermax > self.thr_start_DIIS and istep < self.istep_start_DIIS) + print("#DIIS_dmat.update:ermax:%6d %14.6e %r"%(istep,ermax,skip_diis)) + if( skip_diis ): + return self.get_damped_dmat( self.nbuf, Dm1D) + + loc= self.nbuf%self.size + print("#DIIS_dmat.update:nbuf/loc/bfsz:",self.nbuf,loc,self.size) + if( len(self.vecbuf)<=loc ): + self.vecbuf.append( arrayclone( Dm1D ) ) + else: + if( self.vecbuf[loc] is None ): + self.vecbuf[loc] = arrayclone( Dm1D ) + else: + le=len(Dm1D) + for j in range(le): + self.vecbuf[loc][j]=Dm1D[j] + + if( ervec is None ): + self.status=1 + ## only at the 1st item + assert self.nbuf==0,"" + return Dmat + else: + if( len(self.erbuf)<=loc): + self.erbuf.append( arrayclone( ervec ) ) + else: + if( self.erbuf[loc] is None ): + self.erbuf[loc] = arrayclone( ervec ) + else: + le=len( ervec ) + for j in range(le): + self.erbuf[loc][j]=ervec[j] + self.status=2 + ibuf=self.nbuf + self.nbuf+=1 + if( self.mat is None ): + self.mat = numpy.zeros([self.size,self.size],dtype=self.dtype) + if( ibuf < self.size ): + for j in range(ibuf+1): + self.mat[ibuf][j]= self.inner_product( self.erbuf[loc], self.erbuf[j] ) + else: + for j in range(loc+1): + self.mat[ loc][j]= self.inner_product( self.erbuf[loc], self.erbuf[j] ) + for j in range(loc+1,self.size): + self.mat[ j][loc]= self.inner_product( self.erbuf[j], self.erbuf[loc] ) + + if( self.nbuf < self.minimum_buflen ): + return self.get_damped_dmat(ibuf, Dm1D) + Nv=min(self.size, self.nbuf) + Ld=Nv+1 + wks=numpy.zeros( [Ld,Ld],dtype= self.dtype) + for i in range(Nv): + for j in range(i+1): + wks[i][j]=self.mat[i][j] + if(i!=j): + wks[j][i]=numpy.conj( self.mat[i][j] ) + for j in range(Ld-1): + wks[Ld-1][j]=1.0 + wks[j][Ld-1]=1.0 + wks[Ld-1][Ld-1]=0.0 + + w=numpy.zeros([Ld],dtype=self.dtype ) + for j in range(Ld-1): + w[j]=0.0 + w[Ld-1]=1.0 + coef,res,rank,sv=numpy.linalg.lstsq(wks,w,rcond=None) ## this is equivalent to svdsolv + + retv_1d=numpy.zeros([self.Ld_dmat],dtype=self.dtype) + retv_1d[:]=coef[0]*self.vecbuf[0][:] + for J in range(1,Nv): + retv_1d[:]+=coef[J]*self.vecbuf[J][:] + return numpy.reshape( retv_1d, self.Ndim_dmat ) +# eg. nbuf==2 ----------- +# 0 1 2 3 +# 0 +# 1 +# 2 * * * +# eg. nbuf==2 ----------- +# 0 1 2 +# 0 * +# 1 * +# 2 * + def calc_errorvec(self,Dmat,S1e=None,Fock=None): + if( self.scheme == "SDFFDS" ): + return self.calc_SDFFDS( Dmat, S1e, Fock) + else: + if( self.vecbuf[0] is None ): + return None +## +## nbuf==0 but we have 0-th item +## + if( self.nbuf == 0 ): + last=0 + else: + last=(self.nbuf-1)%self.size + Dm1D=numpy.ravel(Dmat) + print("dbgng:DM1D:",numpy.shape(Dm1D)) + return Dm1D-self.vecbuf[last] + + + def calc_SDFFDS(self, Dmat,S1e,Fock): + Ndim=numpy.shape(Dmat);rank=len(Ndim) + # RHF UHF + # MOL [nAO][nAO] [2][nAO][nAO] + # PBC [nkp][nAO][nAO] + assert (self.pbc and rank==3) or ( (not self.pbc) and rank==2),"" + nKpt=(1 if(not self.pbc) else Ndim[0]) + nAO =(Ndim[0] if(not self.pbc) else Ndim[1]) + ret =(None if(not self.pbc) else [] ) + for kp in range(nKpt): + s1 =( S1e if(not self.pbc) else S1e[kp]) + fo =( Fock if(not self.pbc) else Fock[kp]) + dm =( Dmat if(not self.pbc) else Dmat[kp]) + sdffds= numpy.matmul( s1, numpy.matmul( dm, fo)) \ + - numpy.matmul( fo, numpy.matmul( dm, s1)) + if( not self.pbc ): + ret=numpy.ravel( sdffds );break + else: + ret.append( numpy.ravel( sdffds ));break + return (ret if( not self.pbc ) else numpy.ravel(ret)) + +def arrayclone(src): + dtype=None + if( isinstance(src,numpy.ndarray) ): + dtype=src.dtype + else: + dtype=( numpy.array(src[0]) ).dtype + + ndim=numpy.shape(src);rank=len(ndim) + ret=numpy.zeros( ndim, dtype ) + for i in range(ndim[0]): + if(rank==1): + ret[i]=src[i];continue + for j in range(ndim[1]): + if(rank==2): + ret[i][j]=src[i][j];continue + for k in range(ndim[2]): + if(rank==3): + ret[i][j][k]=src[i][j][k];continue + for l in range(ndim[3]): + if(rank==4): + ret[i][j][k][l]=src[i][j][k][l];continue + for m in range(ndim[4]): + ret[i][j][k][l][m]=src[i][j][k][l][m];continue + return ret diff --git a/pyscf/rttddft/diis01.py b/pyscf/rttddft/diis01.py new file mode 100644 index 000000000..6f4fe9bf1 --- /dev/null +++ b/pyscf/rttddft/diis01.py @@ -0,0 +1,1196 @@ +import os +import sys +import numpy as np +from numpy import random +from .utils import i1eqb,i1toa,toString,a1maxdiff,d1toa,z1toa,d2toa,parse_ints +from .serialize import load_fromlist,parse_slist,read_strtype,serialize +from .Logger import Logger +from .rttddft_common import rttddft_common +import math +from mpi4py import MPI ### XXX idbgng_threadsync + +# DM 'R' [nkpt,nAO,nAO] / [nAO,nAO] +# else [2,nkpt,nAO,nAO]/[2,nAO,nAO] +# Fck 'U' [2,nkpt,nAO,nAO]/[2,nAO,nAO] +# else +# S [nkpt,nAO,nAO] / [nAO,nAO] +def dot_AOmatrices(a,b,Smat,spinrestriction,DorF,title=None): + + assert DorF=='D' or DorF=='F',"" + nmult=( (1 if(spinrestriction=='R') else 2) if(DorF=='D') else \ + (2 if(spinrestriction=='U') else 1) ) + Ndim_S=np.shape(Smat);le_Ndim_S=len(Ndim_S) + pbc=(le_Ndim_S==3) + nAO=Ndim_S[1] + assert (pbc and Ndim_S[1]==Ndim_S[2]) or ((not pbc) and Ndim_S[0]==Ndim_S[1]), "" + nkpt=(1 if(not pbc) else Ndim_S[0]) + Ndim_DorF=( ( [nkpt,nAO,nAO] if(pbc) else [nAO,nAO]) if(nmult==1) else \ + ( [2,nkpt,nAO,nAO] if(pbc) else [2,nAO,nAO]) ) + A=np.reshape(a,Ndim_DorF);B=np.reshape(b,Ndim_DorF) + cum=0.0;buf=[] + for sp in range(nmult): + As=(A if(nmult==1) else A[sp]) + Bs=(B if(nmult==1) else B[sp]) + dum=0.0 + for kp in range(nkpt): + Ask=(As if(not pbc) else As[kp]) + Bsk=(Bs if(not pbc) else Bs[kp]) + Sk= (Smat if(not pbc) else Smat[kp]) + ASBS=np.matmul(Ask,np.matmul(Sk,np.matmul(Bsk,Sk))) + tr=0.0 + for I in range(nAO): + tr+=ASBS[I][I].real + dum+=tr;buf.append(tr) + if(pbc): + dum=dum/float(nkpt) + cum+=dum + if(title is not None): + print("dot_AOmatrices:%s "%(title)+str(Ndim_DorF)) + print("dot_AOmatrices:A:%f+j%f %f+j%f ..."%(A[0][0][0].real,A[0][0][0].imag,A[0][0][1].real,A[0][0][1].imag)) + print("dot_AOmatrices:B:%f+j%f %f+j%f ..."%(B[0][0][0].real,B[0][0][0].imag,B[0][0][1].real,B[0][0][1].imag)) + print("dot_AOmatrices:Smat:"+str(Ndim_S)) + print("dot_AOmatrices:Smat:%f %f %f ..."%( Smat[0][0][0].real, Smat[0][0][1].real, Smat[0][0][2].real)) + print("dot_AOmatrices:Retv:%f+j%f sqrt:%f ..."%(cum.real,cum.imag,np.sqrt(abs(cum.real))) + str(buf)) + return cum + + +def a1maxdiff(a,b): + Ld=len(a) + ret=abs( a[0]-b[0] );at=0 + for I in range(1,Ld): + dum=abs(a[I]-b[I]) + if( ret=J are filled + self.ervec_thr=ervec_thr + self.nstep_thr=nstep_thr + self.dtype=dtype + self.started=False + self.mixing_factor=mixing_factor + self.nvect_thr = nvect_thr + self.nSleep=0 + self.seqno=0 + self.writer=None ##::Logger must implement .append(text) and Logger.info( .writer, ...) + self.iter=0 + self.check_linear_dependency=False + self.AOparams_=None; + self.dbgbuffer=[]; + self.retv_last=None + def update_AOparams(self,dic,clear=True): + if( self.AOparams_ is None ): + self.AOparams_ = {} + elif(clear): + self.AOparams_.clear() + for key in dic: + self.AOparams_.update({key:dic[key]}) + string=""; + for key in self.AOparams_: + if(key != 'SAO'): + string+="%s:%s "%( str(key), str( self.AOparams_[key] )) + rttddft_common.Write_once('DIIS.update_AOparams',"#DIIS_params set:"+string) + + def get_recent_sqrerrors(self, Nwant, nstepbefore): + Iv0=self.nbuf-1-nstepbefore + if( Iv0<0 ): + return None + nupl=min( Nwant, Iv0+1) + ret=[] + for J in range(nupl): + Iv=Iv0-J + Imod=Iv%self.bfsz + ret.append( self.matrix[Imod][Imod] ) + return ret + + def check_buffer_02(self,Nkeep,order='E',nSleep=6): + if( self.nbuf<2 ): + print("#DIIS:check_buffer too few vecs:%d"%(self.nbuf)); + return 0 + nvect=(self.nbuf if( self.nbuf< self.bfsz) else self.bfsz) + Nremov=nvect-Nkeep + if( Nremov<=0 ): + return 0 + removed=[];N=0 + if( order == 'E' ): + erveclen =np.zeros( [nvect]) + for I in range(nvect): + erveclen[I]=self.matrix[I][I] + jthTOiv=np.argsort(erveclen) + for jth in range(nvect): + Iv=jthTOiv[nvect-jth-1] + removed.append(Iv); + N+=1 + if(N>=Nremov): + break + else: + nk=0 + Iv=(self.nbuf-1) % self.bfsz + for I in range(nvect): + if(nk>=Nkeep): + removed.append(Iv); + else: + nk+=1 + Iv=( Iv - 1 + self.bfsz )%self.bfsz + self.remove_vectors( removed, nSleep=nSleep, update_attributes=True) + return len(removed) + + ## default=0,1,2.. : force apply Ith + ## -1,-2, Nbranch+default th + def check_buffer(self,dicts,N_recent=10,N_latest=4,logger=None,default=None): + + nvect=(self.nbuf if( self.nbuf< self.bfsz) else self.bfsz) + ## DEFAULT : N_recent=10; N_latest=4 + if( nvect < N_recent+N_latest ): + return 0 + Iv=(self.bfsz + self.nbuf-1) % self.bfsz + recent_min=self.matrix[Iv][Iv] + for K in range(1,N_latest): + Iv=(self.bfsz + self.nbuf-1-K)%self.bfsz + recent_min= min( recent_min, self.matrix[Iv][Iv] ) + + Iv=(self.bfsz + self.nbuf-1-N_recent) % self.bfsz + old_min=self.matrix[Iv][Iv] + for K in range(1,N_latest): ## nbuf - 1-(N_latest-1) - N_recent = nbuf-(N_recent+N_latest) + Iv=(self.bfsz + self.nbuf-1-K-N_recent)%self.bfsz + old_min= min( old_min, self.matrix[Iv][Iv] ) + recent_min=np.sqrt(recent_min);old_min=np.sqrt(old_min) + + Nbranch=len(dicts);branch=None + for I in range(Nbranch-1): + if( dicts[I]["condition"]( recent_min, old_min ) ): + branch=I;break + if( branch is None ): + if( default is None ): + return None + Ith=(default if(default>=0) else Nbranch+default) + if( Ith<0 or Ith>=Nbranch ): + return None + branch=Ith ## last one + Nkeep=dicts[branch]["Nkeep"];nSleep=dicts[branch]["nSleep"];order=dicts[branch]["order"]; + ratio=recent_min/old_min + Logger.write(logger,"#DIIS:check_buffer:step=%d:%d recent_min/old_min:%e (%e/%e) >> keep %d sleep %d ordering:%s"%( + self.iter,branch,ratio,recent_min,old_min,Nkeep,nSleep,order)) + Nremov=self.check_buffer_02(Nkeep,order=order,nSleep=nSleep) + if( logger is not None): + nvect=min( self.nbuf, self.bfsz) + logger.info("#DIIS.%d nbuf=%d"%(self.iter, nvect)) + strbuf="" + for jv in range(nvect): + vsqr=self.matrix[jv][jv] + vsqr2=np.vdot( self.erbuf[jv], self.erbuf[jv] ) + strbuf+="#%d: %e %e %d\n"%( jv, np.sqrt(vsqr.real), np.sqrt(vsqr2.real),self.ibuf[jv] ) + assert (abs(vsqr-vsqr2)<1.0e-6),"check vsqr:"+str( [vsqr,vsqr2]) + strbuf+="\n\n" + logger.info(strbuf) + return Nremov + + def check_buffer_old(self,vnorm_abs_thr=1.0e-5,vnorm_relt_thr=1.0e-3,verbose=False,dicts=None, + nSleep=6,N_keep=None,N_remov=None,N_recent=10,N_latest=4, logger=None): + ## check if error is decreasing + ## n=4 N=10 + ## [min. of --N_latest-- errors] - [ the same quant. N steps before ] + ## (i) decreasing by ratio > R_1 (:2) >>> keep going on.. but we want to reduce IRRELEVANT ones if nvect is too large + ## (ii) < R_1 (:2) >>> reduce # of vectors + ## + nvect=(self.nbuf if( self.nbuf< self.bfsz) else self.bfsz) + ## DEFAULT : N_recent=10; N_latest=4 + if( nvect < N_recent+N_latest ): + return 0 + Iv=(self.bfsz + self.nbuf-1) % self.bfsz + recent_min=self.matrix[Iv][Iv] + for K in range(1,N_latest): + Iv=(self.bfsz + self.nbuf-1-K)%self.bfsz + recent_min= min( recent_min, self.matrix[Iv][Iv] ) + + Iv=(self.bfsz + self.nbuf-1-N_recent) % self.bfsz + old_min=self.matrix[Iv][Iv] + for K in range(1,N_latest): ## nbuf - 1-(N_latest-1) - N_recent = nbuf-(N_recent+N_latest) + Iv=(self.bfsz + self.nbuf-1-K-N_recent)%self.bfsz + old_min= min( old_min, self.matrix[Iv][Iv] ) + recent_min=np.sqrt(recent_min);old_min=np.sqrt(old_min) +#12.08.001 diff_small=1.0e-3; diff_fair=1.0e-2; + diff_small=3.0e-3; diff_fair=1.0e-2; + order='E';Scheme_02=True + ratio = recent_min / old_min + Nremov=0 + + if( Scheme_02 ): + if( (ratio < 0.50 and recent_min> keep %d by %s"%(self.nbuf,ratio,recent_min,old_min,Nkeep,order)) + Nremov=self.check_buffer_02(Nkeep,order=order,nSleep=nSleep) +#12.08.001 elif( ratio<0.50 or recent_min> keep %d by %s"%(self.nbuf,ratio,recent_min,old_min,Nkeep,order)) + Nremov=self.check_buffer_02(Nkeep,order=order,nSleep=nSleep) + elif( ratio < 1.0 or recent_min> keep %d by %s"%(self.nbuf,ratio,recent_min,old_min,Nkeep,order)) + Nremov=self.check_buffer_02(Nkeep,order=order,nSleep=nSleep) + else: + Nkeep=5;nSleep=8 + Logger.write(logger,"#DIIS:check_buffer:step=%d recent_min/old_min:%e (%e/%e) >> keep %d by %s"%(self.nbuf,ratio,recent_min,old_min,Nkeep,order)) + Nremov=self.check_buffer_02(Nkeep,order=order,nSleep=nSleep) + else: + if( ratio < 0.50 or (recent_min> keep %d latest"%(self.nbuf,ratio,recent_min,old_min,N_recent)) + Nremov=self.check_buffer_01(vnorm_abs_thr=vnorm_abs_thr, vnorm_relt_thr=vnorm_relt_thr, verbose=verbose,\ + nSleep=nSleep,latestN_excluded=N_recent,N_keep=N_keep,N_remov=N_remov) + elif( ratio < 1.0 or (recent_min> keep %d latest"%(self.nbuf,ratio,recent_min,old_min,3)) + Nremov=self.check_buffer_01(vnorm_abs_thr=vnorm_abs_thr, vnorm_relt_thr=vnorm_relt_thr, verbose=verbose,\ + nSleep=nSleep,latestN_excluded=3,N_keep=N_keep,N_remov=N_remov) + else: + ## We'd better restart ?? + Logger.write(logger,"#DIIS:check_buffer:step=%d recent_min/old_min:%e (%e/%e) >> restart.."%(self.nbuf,ratio,recent_min,old_min)) + + Nremov=self.check_buffer_01(vnorm_abs_thr=vnorm_abs_thr,vnorm_relt_thr=vnorm_relt_thr, verbose=verbose,\ + nSleep=nSleep,latestN_excluded=0,N_keep=N_latest,N_remov=None,err_upl=0.10,err_lwl=1.0e-3,Nkeep_upl=15) +## Nremov=self.check_buffer_01(vnorm_abs_thr=vnorm_abs_thr,vnorm_relt_thr=vnorm_relt_thr, verbose=verbose,\ +## nSleep=nSleep,latestN_excluded=0,N_keep=N_latest,N_remov=None) + if( logger is not None): + nvect=min( self.nbuf, self.bfsz) + logger.info("#DIIS.%d nbuf=%d"%(self.iter, nvect)) + strbuf="" + for jv in range(nvect): + vsqr=self.matrix[jv][jv] + vsqr2=np.vdot( self.erbuf[jv], self.erbuf[jv] ) + strbuf+="#%d: %e %e %d\n"%( jv, np.sqrt(vsqr.real), np.sqrt(vsqr2.real),self.ibuf[jv] ) + assert (abs(vsqr-vsqr2)<1.0e-6),"check vsqr:"+str( [vsqr,vsqr2]) + strbuf+="\n\n" + logger.info(strbuf) + return Nremov + + def check_linear_independency1(self,vect,vnorm_abs_thr=-1,vnorm_relt_thr=1.0e-3,logger=None): + nvect=(self.nbuf if( self.nbuf< self.bfsz) else self.bfsz) + vc1=np.ravel(vect).copy() + vnorm_org= np.sqrt( np.vdot(vc1,vc1).real ) + cofs=[] + for ivect in range(nvect): + ref=self.vcbuf[ivect] + prd = np.vdot( ref, vc1); cofs.append(prd) + vsqr = np.vdot(ref,ref) + vnorm= math.sqrt( vsqr.real ) + vc1 = vc1 - (prd/vnorm)*ref + vsqr=np.vdot(vc1,vc1) + vnorm=math.sqrt( vsqr.real ); + vnratio=vnorm/vnorm_org + if( ( vnorm_abs_thr>=0 and vnorm=0 and vnratioerr_upl): + n_tooLarge+=1;jth_removed.append(jth);continue + cofs=[] + for ref in vcs: + prd = np.vdot( ref, vc1); cofs.append(prd) + vsqr = np.vdot(ref,ref) + vnorm= math.sqrt( vsqr.real ) + vc1 = vc1 - (prd/vnorm)*ref + vsqr=np.vdot(vc1,vc1) + vnorm=math.sqrt( vsqr.real ); + vnratio=vnorm/vnorm_org + if( ( vnorm_abs_thr>=0 and vnorm=0 and vnratioself.matrix[Iv][Iv].real): + ermin=self.matrix[Iv][Iv].real; Iv_at=Iv + ermin=np.sqrt(ermin) + + Iv =(self.nbuf-1 -pms4["nstep_back"] + self.bfsz) % self.bfsz + ermax_2=self.matrix[Iv][Iv].real; ermin_2=self.matrix[Iv][Iv].real;Iv2_at=Iv; + for I in range(1, pms4["width"] ): + ## index (bf. modulo) runs up to nbuf-pms4["width"]-pms4["nstep_back"], which must be >=0 ... + Iv=(self.nbuf-1-I-pms4["nstep_back"] + self.bfsz) % self.bfsz + ermax_2=max(ermax_2,self.matrix[Iv][Iv].real); + if( ermin_2>self.matrix[Iv][Iv].real): + ermin_2=self.matrix[Iv][Iv].real; Iv2_at=Iv + ermin_2=np.sqrt(ermin_2) + + if( "relative_diff_thr" in pms4 ): + test = (ermin_2 - ermin)/ 0.50*(ermin + ermin_2) ## >0:improving + + string="#check_if_stuck4:"+("!W STUCK" if(test< pms4[ "relative_diff_thr" ]) else "")\ + +("" if(text is None) else text+":")\ + +" recent_min:[%d]%e / %d steps before:[%d]%e"%( Iv_at, ermin, pms4["nstep_back"], Iv2_at, ermin_2 ) + if( strbuf is not None ): + strbuf.append(string) + if( test< pms4[ "relative_diff_thr" ] ): + istuck=Ipms; + print(string); + break + if(text is not None): + print(string); + return istuck; + + def check_if_stuck( self, pmset1=[ {"nstep_thr":6,"relative_diff_thr":1.0e-2} ],\ + pmset2=[ {"nstep_avg":4, "nstep_back":10, "relative_diff_thr":1.0e-2} ],\ + pmset3=[ {"nstep_thr":50,"diff_thr":5.0e-5} ]): + nvect=(self.nbuf if( self.nbuf< self.bfsz) else self.bfsz) + ## {"nstep_thr":6,"relative_diff_thr":1.0e-2} + istuck=0 + Ipms1=0 + for pms1 in pmset1: + Ipms1+=1 + Iv=(self.nbuf-1 + self.bfsz) % self.bfsz + ermax=self.matrix[Iv][Iv].real; ermin=self.matrix[Iv][Iv].real + for I in range(1, pms1["nstep_thr"] ): + Iv=(self.nbuf-1-I + self.bfsz) % self.bfsz + ##for J in range(I): + ## Jv = (self.nbuf-1-J + self.bfsz) % self.bfsz + ermax=max( ermax, self.matrix[Iv][Iv].real ) + ermin=min( ermin, self.matrix[Iv][Iv].real ) + ermax=np.sqrt(ermax); ermin=np.sqrt(ermin) + relative_diff = (ermax-ermin)/ 0.50*(ermax + ermin) + if( relative_diff < pms1["relative_diff_thr"] ): + istuck = Ipms1; break + if( istuck > 0 ): + return istuck + ## Test of avg-err : {"nstep_avg":4, "nstep_back":10, "relative_diff_thr":1.0e-2 } + Ipms2=0 + for pms2 in pmset2: + Ipms2+=1 + if( nvect < pms2["nstep_avg"] + pms2["nstep_back"]): + continue + else: + avgC=0.0;navgC=0 + for I in range(1, pms2["nstep_avg"] ): + Iv=(self.nbuf-1-I + self.bfsz) % self.bfsz + avgC+=self.matrix[Iv][Iv];navgC+=1 + avgC=avgC/float(navgC) + + avgP=0.0;navgP=0 + for I in range(1, pms2["nstep_avg"] ): + Iv=(self.nbuf-1-I -pms2["nstep_back"] + self.bfsz) % self.bfsz + avgP+=self.matrix[Iv][Iv];navgP+=1 + avgP=avgP/float(navgP) + relative_diff = abs(avgC-avgP)/ 0.50*(abs(avgC) + abs(avgP)) + if( relative_diff < pms2["relative_diff_thr"] ): + istuck = (pms2+1)*10; break + logger.info("#check_2:%d_avg_err current:%e %d steps ago:%e relative diff:%e < thr:%e"%(\ + pms2["nstep_avg"],avgC,pms2["nstep_back"],avgP,relative_diff,pms2["relative_diff_thr"])) + istuck = Ipms2*100; break + if( istuck > 0 ): + return istuck + ## check if you've reached almost converging result long ago but are still iterating + ## {"nstep_thr":50,"diff_thr":5.0e-5} + Ipms3=0 + for pms3 in pmset3: + Ipms3+=1 + if( (self.bfsz < pms3["nstep_thr"]) or (nvect < pms3["nstep_thr"]) ): + continue + else: + Istep1st=None;IstepLast=None;Ibuf=[] + err1st=None;errLast=None + sqrTHR=pms3["diff_thr"]**2 + for I in range(nvect): + J=nvect-I-1 + Jv=(self.nbuf-1-J + self.bfsz) % self.bfsz + errSQR=self.matrix[Iv][Iv]; + if( errSQR < sqrTHR): + if(Istep1st is None): + Istep1st=I; err1st=errSQR + IstepLast=I;errLast=errSQR; Ibuf.append(I) + if( Istep1st is not None): + if( IstepLast-Istep1st >= pms3["nstep_thr"]): + logger.info("#check_3:iteration first reaches %e at %d:(%d):%e but is still %e at %d:(%d) and for %d more steps..."%(\ + pms3["diff_thr"],Istep1st,np.sqrt(err1st),np.sqrt(errLast),IstepLast,len(Ibuf)-2)) + istuck = Ipms3*100; break + return istuck + ## scheme-01b: removes those with error > err_upl (~0.05) + ## keep all vecs with error < err_lwl (~2e-3) up to N_keep + ## Scheme-01: (i) removes linearly dependent ones TAKING ACCOUNT of smallness of error + ## (ii) if(N_remov is not None): removes further up to N from those with largest errors + def check_buffer_01(self,vnorm_abs_thr=1.0e-5,vnorm_relt_thr=1.0e-3,verbose=False,nSleep=6,N_keep=20,Nkeep_upl=None,\ + latestN_excluded=0,N_remov=None, err_upl=None, err_lwl=None): + nvect=(self.nbuf if( self.nbuf< self.bfsz) else self.bfsz) + + excl=[] + Iv=(self.nbuf-1) % self.bfsz + for I in range(latestN_excluded): + excl.append(Iv); + Iv=( Iv - 1 + self.bfsz )%self.bfsz + #for I in range(nvect): + # if( self.matrix[I][I].real < err_lwl ) + if( self.nbuf<2 ): + print("#DIIS:check_buffer too few vecs:%d"%(self.nbuf));return 0 + erveclen =np.zeros( [nvect]) + for I in range(nvect): + erveclen[I]=self.matrix[I][I] + jthTOiv=np.argsort(erveclen) + + Nexcl_MAX=nvect + if( N_remov is not None ): + Nexcl_MAX=nvect - N_remov + elif( Nkeep_upl is not None ): + Nexcl_MAX=Nkeep_upl + Nexcl_MAX-=len(excl) + + if( err_lwl is not None): + sqr_lwl=err_lwl**2 + nlwr=0;nadd=0 + for jth in range(nvect): + iv=jthTOiv[jth] + vsqr = erveclen[ iv ] + if( vsqr >sqr_lwl ): + break + if( iv in excl ): + continue + nlwr+=1 + if( nlwr<= Nexcl_MAX): + excl.append(iv);nadd+=1 + Logger.write(self.writer,"#err_lwl:%e nlwr:%d add:%d"%(err_lwl,nlwr,nadd)) + + vNORM_min=-1.0;vRELT_min=-1.0 + removed=[];vnorms=[] + vcs=[]; ## Schmidt orth + jth=0; Iv=jthTOiv[jth]; vcs.append( self.vcbuf[Iv] ) + n_tooLarge=0 + while(jtherr_upl): + n_tooLarge+=1;removed.append(jth);continue + cofs=[] + for ref in vcs: + prd = np.vdot( ref, vc1); cofs.append(prd) + vsqr = np.vdot(ref,ref) + vnorm= math.sqrt( vsqr.real ) + vc1 = vc1 - (prd/vnorm)*ref + vsqr=np.vdot(vc1,vc1) + vnorm=math.sqrt( vsqr.real );vnorms.append(vnorm) + vnratio=vnorm/vnorm_org + assert (vnratio<=1.0),"vnratio" + if( ( vnorm_abs_thr>=0 and vnorm=0 and vnratio0): + Logger.write(self.writer,"#err_upl:%e nExcl:%d"%(err_upl,n_tooLarge)) + + Ndel=len(removed) + Ndel_lnDP=Ndel + if( N_keep is not None ): + assert ( (N_remov is None) or (N_remov<0) ),"" + N_remov = nvect - N_keep + Ndel_2=0 + if( N_remov is not None): + if( Ndel < N_remov ): + for kth in range(nvect): + jth=nvect-1-kth + if( jth in removed ): + continue + Iv=jthTOiv[jth] + if( Iv in excl ): + continue + removed.append(jth);Ndel=Ndel+1;Ndel_2+=1 + if( Ndel>=N_remov ): + break + if( Ndel>0 ): + text="#DIIS_check_buffer:removing:%d(lnDP:%d add:%d) vectors:jth:"%(Ndel,Ndel_lnDP,Ndel_2)+i1toa(removed) + print(text) + if( self.writer is not None): + self.writer.append(text) + Iv_removed=[] + for jth in removed: + Iv_removed.append( jthTOiv[jth] ) + self.remove_vectors(Iv_removed) + return Ndel + else: + text="#DIIS_check_buffer:removing:0 vectors:vNORM_min:%e vRELT_min:%e:"%(vNORM_min,vRELT_min) + print(text) + if( self.writer is not None): + self.writer.append(text) + return 0 + def remove_vectors(self,removed,nSleep=6,update_attributes=True): + if( len(removed)<=0 ): + return 0 + vcbuf=np.zeros([self.bfsz,self.Ldvec],dtype=self.dtype) + erbuf=np.zeros([self.bfsz,self.Ldvec],dtype=self.dtype) + ibuf=np.zeros([self.bfsz],dtype=int) + nINDP=0 + nvect=(self.nbuf if( self.nbuf< self.bfsz) else self.bfsz) + for I in range(nvect): + if( I in removed ): + ## print("removing vec:%d .."%(I)) + continue + for K in range(self.Ldvec): + vcbuf[nINDP][K]=self.vcbuf[I][K] + erbuf[nINDP][K]=self.erbuf[I][K] + ibuf[nINDP]=self.ibuf[I] + ## print("Keeping vec:%d as %d th"%(I,nINDP)) + nINDP+=1 + print("#check_buffer:checked:%d removed:%d Nremaining:%d:"%(nvect,len(removed),nINDP)+i1toa(ibuf,N=nINDP)) + self.vcbuf=vcbuf + self.erbuf=erbuf + self.ibuf =ibuf + self.nbuf=nINDP + for I in range(nINDP): + for j in range(I+1): + self.matrix[I][j]=dot_product(self,'ervecs',self.erbuf[I], self.erbuf[j]) + ## print("#AF:"+sd2toa( self.matrix, Ld=nINDP, format="%8.2e ",)) + if( update_attributes ): + self.started=False;self.nSleep=nSleep + return len(removed) + ## Here we remove linearly dependent vectors.. + def check_buffer_00(self,vnorm_thr=1.0e-5,debug=False,vnorm_relt_thr=1.0e-3,verbose=False,nSleep=6): + print("#DIIS:check_buffer nBuf:%d / size:%d"%(self.nbuf,self.bfsz)) + if( self.nbuf<2 ): + print("#DIIS:check_buffer too few vecs:%d"%(self.nbuf));return 0 + nvect=(self.nbuf if( self.nbuf< self.bfsz) else self.bfsz) + removed=[];vnorms=[] + vcs=[]; + jth=0;Iv=nvect-jth-1;Iv=jth; vcs.append( self.vcbuf[Iv] ) ## zero-th + while (jth3 ): + ### removed.append(3); + ### print("#BF:"+sd2toa( self.matrix, Ld=nvect)) + if( len(removed)==0 ): + print("#check_buffer:checked %d vnorm_min:%e"%(nvect,min(vnorms)) );return 0 + else: + self.remove_vectors(removed,nSleep=nSleep) + return len(removed) + +# USAGE : +# H(dm0)->dm1 : dm1' = update(dm0, dm1-dm0) ... this returns dm0 + (1-mixing)*(dm1-dm0) +# + def update(self,vect,ervec,dict=None,Iter=-1,ervec_mixing=None,oldvec_mixing=None,verbose=False,strbuf=None,ervec_norm=None): + + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + idbgng_threadsync=0 ## 2021.05.21 fixed.. ## idbgng_threadsync=2 + if( MPIsize < 2 ): + idbgng_threadsync=0 + + self.iter=Iter + #if( self.iter>50 ): + # verbose=True + self.seqno+=1 + #if( self.seqno>15): + # print("#DIIS.update:%d + + assert (i1eqb(self.Ndim_vec,np.shape(vect))),"" + if(ervec is not None): + assert (i1eqb(self.Ndim_vec,np.shape(ervec))),"" + + if( self.nSleep > 0 ): + if( self.check_linear_dependency ): + if( self.check_linear_independency1(vect)): + Logger.write(self.writer,"linearly INdependent reducing nSleep:%d"%(self.nSleep-1)) + self.nSleep=self.nSleep-1 + else: + Logger.write(self.writer,"linearly dependent vector..") + else: + self.nSleep=self.nSleep-1 + print("#DIIS:nSleep:%d"%(self.nSleep)) + start_diis=False + if( self.nbuf == 0 ): + assert (ervec is not None),"set ervec explicitly at the 1st step" + nprev=(self.nbuf-1)%self.bfsz + if( ervec is None ): + ervec_1d = np.reshape( vect.copy(), [self.Ldvec]) ## you need to copy this + ervec_1d[:]=ervec_1d[:]-self.vcbuf[nprev][:] + else: + ervec_1d = np.reshape( ervec, [self.Ldvec] ) ## you do not have to copy this + dict1={"at":-1,"dev":-1} + ermax=a1maxval(ervec_1d,dict=dict1) + # print("#diis:ermax:%d %e"%(dict1["at"],dict1["dev"])); + if( not self.started and self.nbuf>0 and self.nSleep<=0 ): + if( ermax= self.nvect_thr ): + ### print("start DIIS:%d/%d %e"%(self.nbuf,self.nvect_thr,ermax)); + self.started=True + elif( self.nstep_thr>0 and self.nbuf>self.nstep_thr and self.nbuf>= self.nvect_thr): + print("force start DIIS:%d/%d %d %e nvthr:%d"%(self.nbuf,self.nstep_thr,self.nvect_thr,ermax,self.nvect_thr)); self.started=True + # fd1=open("DIIS_forcestart.log","a"); + # print("%05d %d %d %r %d/%d"%( self.seqno, Iter, self.bfsz, self.started,self.nbuf,self.nvect_thr),file=fd1) + # fd1.close() + ncur=self.nbuf%self.bfsz + + ## --- a. store error vectors + self.erbuf[ncur][:]=ervec_1d[:] ## substitution into existing buffer + self.vcbuf[ncur][:]=np.reshape( vect, [self.Ldvec]) ## substitution into existing buffer + self.ibuf[ncur]=Iter + ## --- b. update matrix [I][j] (only the LOWER triangle, I>=j are filled) + if( self.nbuf>=self.bfsz ): + # update all [ncur][*] [*][ncur].. note we fill [I]>=[j] + for J in range(ncur): + self.matrix[ncur][J]=dot_product(self,'ervecs',ervec_1d, self.erbuf[J]) + for I in range(ncur,self.bfsz): + self.matrix[I][ncur]=dot_product(self,'ervecs',self.erbuf[I], ervec_1d) + else: + for J in range(ncur+1): + self.matrix[ncur][J]=dot_product(self,'ervecs',ervec_1d, self.erbuf[J]) + ### print("#diis:filling into %d,%d:%f+j%f"%(ncur,J,self.matrix[ncur][J].real,self.matrix[ncur][J].imag)) + + ### print(self.AOparams_['AOrep']) + ### print(self.AOparams_['spinrestriction']);print(self.AOparams_['DorF']) + if( ervec_norm is not None and self.AOparams_ is not None ): + ervcSQREnrm=dot_AOmatrices(ervec_1d,ervec_1d,self.AOparams_['SAO'], + self.AOparams_['spinrestriction'],self.AOparams_['DorF'],title="ervecnorm") + ervcnrm=np.sqrt( abs(ervcSQREnrm) ) + print( "#ervecnorm:"+str(ervcnrm) +"/"+str( np.sqrt( abs(self.matrix[ncur][ncur].real) ) )) + assert abs(ervec_norm-np.sqrt(abs(self.matrix[ncur][ncur])))<1e-8,"%e / %e"%( ervec_norm, np.sqrt( abs(self.matrix[ncur][ncur]) ) ) + + self.nbuf+=1 ## --- c. finally we increment nbuf ---- + if( not self.started ): + if( ervec_mixing is not None): + if(verbose): + print("#diis_retv:vect:mixed:%d:%d:"%(ncur,self.ibuf[ncur])+toString(vect,Nmax=6) ) + print("#diis_retv:ervec:%d:%d:"%(ncur,self.ibuf[ncur])+toString(ervec,Nmax=6) ) + return vect[:] - ervec_mixing * ervec[:] ### new - 0.5*(new-old) + elif( oldvec_mixing is not None): + if( self.nbuf < 2 ): + if(verbose): + print("#diis_retv:vect:default:%d:%d:"%(ncur,self.ibuf[ncur])+toString(vect,Nmax=6) ) + return vect[:] ## nbuf==1 at first time + else: + ndim_vect=np.shape(vect) + Iold=( self.nbuf - 2 )%self.bfsz + if(verbose): + print("#diis_retv:vect:mixed:%d:%d:"%(ncur,self.ibuf[ncur])+toString(vect,Nmax=6) ) + print("#diis_retv:prev_vect:%d:%d:"%(Iold,self.ibuf[Iold])+toString(self.vcbuf[Iold],Nmax=6) ) + return vect[:]*(1.0-oldvec_mixing) + oldvec_mixing * np.reshape( self.vcbuf[Iold][:], ndim_vect) + else: + return vect; + else: + Neff= self.nbuf if(self.nbuf0): + sqrediff_IN,maxabsdiff_IN,At_IN,vals_IN = mpi_aNdiff(submatr,"DIIS01%06d.%03d_submatr"%(self.seqno,self.iter)) + strdiff_sync="submatr:"+ mpidiffs_tostring_(sqrediff_IN,maxabsdiff_IN,At_IN,vals_IN,Datf=False) + + DEBUG_matrix=False + if( DEBUG_matrix ): + dev=-1;at=[-1,-1];vals=[0,0] + for I in range(LdMat-1): + for J in range(LdMat-1): + cdum=dot_product(self,'ervecs',self.erbuf[I],self.erbuf[J]) + diff=abs(cdum-submatr[I][J]); + if(diff>dev): + dev=diff;at=[I,J];vals=[submatr[I][J],cdum] + if( dev>1.0e-6 ): + print("wrong mat:%f+j%f / %f+j%f"%( vals[0].real,vals[0].imag, vals[1].real,vals[1].imag )) + for I in range(LdMat-1): + ref="";string="" + for J in range(LdMat-1): + cdum=dot_product(self,'ervecs',self.vcbuf[I],self.vcbuf[J]) + ref=ref+"%10.3f %10.3f "%(cdum.real,cdum.imag) + string=string+"%10.3f %10.3f "%(submatr[I][J].real, submatr[I][J].imag) + print("#matr:%d:"%(I)+string) + print("#refr:%d:"%(I)+ref) + + assert False,"wrong mat" + ### coef1,res1,rank1,sv1=np.linalg.lstsq(submatr,w,rcond=None) + coef,res,rank,sv=np.linalg.lstsq(submatr,w,rcond=None) ## this is equivalent to svdsolv + ### coef,res,rank,sv=np.linalg.lstsq(submatr,w,rcond=-1) + + #svdsolv: List_err=[] + #svdsolv: coef,res = svdsolv(submatr,w,List_errors=List_err) + #if( coef is None ): + # printout("DIIS:svdsolve failed:"+List_err[0],warning=-1) + # coef=coef1;res=res1 + + if(idbgng_threadsync>0 and MPIsize>1 ): + sqrediff_OU1,maxabsdiff_OU1,At_OU1,vals_OU1 = mpi_aNdiff(coef,"DIIS01%06d.%03d_cof1"%(self.seqno,self.iter)) + sqrediff_OUT,maxabsdiff_OUT,At_OUT,vals_OUT = mpi_aNdiff(coef,"DIIS01%06d.%03d_coef"%(self.seqno,self.iter)) + strdiff_sync+="coef:"+ mpidiffs_tostring_(sqrediff_OUT,maxabsdiff_OUT,At_OUT,vals_OUT,Datf=False) + strADD="#np.linalg.lstsq: %16.6e with res="%(maxabsdiff_OU1)+str(res) + ### +" \t svdsolv: %16.6e with res="%(maxabsdiff_OUT)+str(res) + if( dict is not None ): + if("coef" in dict): + dict["coef"]=coef + if("ibuf" in dict): + dict["ibuf"]=self.ibuf + DEBUG_soln=False + if(DEBUG_soln): + wrk=np.zeros([LdMat],dtype=self.dtype) + wrk=np.matmul( submatr,coef) + print("#diis:AxSOLN:"+z1toa(wrk)) + print("#diis:w:"+z1toa(w)) + + lcERR=np.zeros([self.Ldvec],dtype=self.dtype) + lcERR[:]=coef[0]*self.erbuf[0][:] + for J in range(1,Neff): + lcERR[:]+=coef[J]*self.erbuf[J][:] + cdum=dot_product(self,'ervecs', lcERR, lcERR) + lcNORM=( cdum.real if (type(cdum) is complex) else cdum) + print("#LC norm:%f / ervcs:"+diag_tostring(self.matrix)) + + retv_1d=np.zeros([self.Ldvec],dtype=self.dtype) + retv_1d[:]=coef[0]*self.vcbuf[0][:] + for J in range(1,Neff): + retv_1d[:]+=coef[J]*self.vcbuf[J][:] + + if(idbgng_threadsync>0): + sqrediff_IN2,maxabsdiff_IN2,At_IN2,vals_IN2 = mpi_aNdiff(self.vcbuf[0:Neff],"DIIS01%06d.%03d_vcbuf"%(self.seqno,self.iter)) + strdiff_sync+=" vecs:"+ mpidiffs_tostring_(sqrediff_IN2,maxabsdiff_IN2,At_IN2,vals_IN2,Datf=False) + sqrediff_OUT2,maxabsdiff_OUT2,At_OUT2,vals_OUT2 = mpi_aNdiff(retv_1d,"DIIS01%06d.%03d_retv"%(self.seqno,self.iter)) + strdiff_sync+=" retv_1d:"+ mpidiffs_tostring_(sqrediff_OUT2,maxabsdiff_OUT2,At_OUT2,vals_OUT2,Datf=False) + + fd01=open("diis_DBGsynchthreads_%02d.log"%(MPIrank),'a') + print("# DIIS%06d.%03d: retv:%16.4e submatr:%16.4e vecs:%16.4e coefs:%16.4e"%(\ + self.seqno, self.iter, maxabsdiff_OUT2, maxabsdiff_IN, maxabsdiff_IN2, maxabsdiff_OUT),file=fd01); + print("## DIIS%06d.%03d: "%(self.seqno,self.iter) + strdiff_sync, file=fd01); + print(strADD, file=fd01);fd01.close() +## ------------------------------------------------------------------------------------- + dbgng_DIIScoefs=False + if( dbgng_DIIScoefs and self.AOparams_ is not None): + diff_to_prev=None + if( self.retv_last is not None ): + cdum= dot_AOmatrices( retv_1d-self.retv_last, retv_1d-self.retv_last, self.AOparams_['SAO'], + self.AOparams_['spinrestriction'], self.AOparams_['DorF']) + diff_to_prev = np.sqrt( abs(cdum.real) ) + self.retv_last=retv_1d.copy() + err=np.vdot( coef[0:LdMat-1], np.matmul(submatr[0:LdMat-1,0:LdMat-1],coef[0:LdMat-1]) ) + err=np.sqrt( abs(err.real) ) + self.dbgbuffer.append({'ncur':ncur, 'cofs':coef.copy(), 'err':err, 'diff_to_prev':diff_to_prev}) + lebf=len(self.dbgbuffer) + if( lebf>= 6 ): + fpath1="DIIS_coefs.log" + fd1=open(fpath1,"a"); + print("#DIIS:iter=%d nbuf=%d/%d ncur=%d"%(Iter,self.nbuf,self.bfsz,ncur),file=fd1) + + for k in range(Neff): + I=ncur-Neff+1+k + Imod=(I+self.bfsz)%self.bfsz; err=np.sqrt( abs(self.matrix[Imod][Imod].real)) + string=""; + for j in range(lebf): + arr=self.dbgbuffer[j]['cofs'] + if( len(arr)>k ): + string+="%10.4f %10.4f "%(arr[k].real,arr[k].imag) + else: + string+=(' '*26) + print(" %5d %3d %14.4e "%(I,self.ibuf[Imod],err) +string,file=fd1) + string=""; + for j in range(lebf): + err_est=self.dbgbuffer[j]['err'] + jnxt =self.dbgbuffer[j]['ncur']+1 + if( jnxt < self.nbuf ): + jmod=(jnxt+self.bfsz)%self.bfsz + err_true=np.sqrt( abs(self.matrix[jmod][jmod].real) ) + string+="%10.4e %10.4e "%(err_est,err_true) + else: + string+="%10.4e "%(err_est)+(' '*15) + print("#%5s %3s %14s "%("err","","")+string,file=fd1) + string=""; + for j in range(lebf): + diff=self.dbgbuffer[j]['diff_to_prev'] + if( diff is None ): + string+=(' '*26) + else: + string+="%14.4e "%(diff)+' '*11 + print("#%5s %3s %14s "%("diff","","")+string,file=fd1) + fd1.close() + self.dbgbuffer.clear(); + os.system("fopen "+fpath1); +##------------------------------------------------------------------------------------ + if(verbose): + for J in range(Neff): + Logger.write(self.writer,"#diis_retv:%d:LC:%d(%d) %f+%fj"%(self.iter, J, self.ibuf[J],coef[J].real,coef[J].imag)) +# if(self.iter>80): +# assert False,"" +###+toString(retv_1d,Nmax=6) + return np.reshape(retv_1d, self.Ndim_vec) + +def z1rand(N): + ret=np.zeros([N],dtype=complex) + foo=random.rand(N) + boo=random.rand(N) + for I in range(N): + ret[I]=complex( foo[I],boo[I]) + return ret; + +def d1toa(vect,N_upl=None,format="%5.2f "): + ret="" + N=len(vect); + if(N_upl is not None): + N=min( N_upl, N) + for j in range(N): + ret=ret+ format%vect[j] + return ret; +def dbgwrited1(vect): + ret="" + Ndim=np.shape(vect) + dim=len(Ndim) + if(dim==1): + return d1toa(vect,N_upl=20) + else: + Ld=Ndim[0]; + for k in range(1,dim): + Ld=Ld*Ndim[k] + return d1toa(np.reshape(vect,[Ld]),N_upl=20) + +#Ldvec=10;bfsz=10; +#diis=DIIS01(Ldvec,bfsz,dtype=complex,ervec_thr=1.0e-3,nstep_thr=2,mixing_factor=0.50) +#v0=z1rand(Ldvec) +#v1=z1rand(Ldvec) +#diis.update(v1,v1[:]-v0[:]) +#v2=z1rand(Ldvec) +#diis.update(v2) +#v3=z1rand(Ldvec) +#diis.update(v3) +#v4=z1rand(Ldvec) +#diis.update(v4) + +def aNdiff(A,B): + from .utils import ixj_to_IandJ + a=np.ravel( np.array(A) ) + b=np.ravel( np.array(B) ) + d=a-b + sqrediff=( np.vdot( d, d) ).real + + maxabsdiff=abs(a[0]-b[0]);at=0;vals=[a[0],b[0]]; + N=len(a) + for I in range(1,N): + dum=abs(a[I]-b[I]) + if( dum>maxabsdiff ): + maxabsdiff=dum; at=I; vals=[a[I],b[I]] + Ndim_A=np.shape(A) + At=ixj_to_IandJ(at,Ndim_A) + return sqrediff,maxabsdiff,At,vals + +def mpidiffs_tostring_(sqrediff,maxabsdiff,At,vals,Datf=False,Legend=False): + retv=None;legend="" + if( not Datf ): + retv="%16.8f %16.6e %10.4f+j%10.4f / %10.4f+j%10.4f at "%(\ + np.sqrt(sqrediff), maxabsdiff,vals[0].real,vals[0].imag,vals[1].real,vals[1].imag)\ + + str(At) + else: + retv="%16.8f %16.6e %10.4f %10.4f %10.4f %10.4f"%(\ + np.sqrt(sqrediff), maxabsdiff,vals[0].real,vals[0].imag,vals[1].real,vals[1].imag) + if( not Legend ): + return retv + else: + legend=( "%16s %16s %21s %21s"%('dist','maxabsdiff','lhs','rhs') if(Datf) else + "%16s %16s %22s / %22s at %s"%('dist','maxabsdiff','lhs','rhs','ijk') ) + return retv,legend +# sqrediff,maxabsdiff,At,vals = mpi_aNdiff(md.tdMO,"tdMO_eldyn%03d.%03d"%(I_step,iter)) +def mpi_aNdiff(buf,key,compto=0,sync=False): + from .utils import arrayclone + from mpi4py import MPI + from .mpiutils import mpi_Bcast + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if( MPIsize < 2 ): + return + assert compto>=0,"" ## (-1) may mean comp to MPIrank-1 (mod size) th thread but.. + assert comptodiff_THR ): + Ndim=np.shape(buf);leNdim=len(Ndim) + if(leNdim==1): + for I in range(Ndim[0]): + buf[I]=wks[I] + elif(leNdim==2): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + buf[I][J]=wks[I][J] + elif(leNdim==3): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + buf[I][J][K]=wks[I][J][K] + elif(leNdim==4): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + for L in range(Ndim[3]): + buf[I][J][K][L]=wks[I][J][K][L] + elif(leNdim==5): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + for L in range(Ndim[3]): + for M in range(Ndim[4]): + buf[I][J][K][L][M]=wks[I][J][K][L][M] + else: + assert False,"" + return sqrediff,maxabsdiff,At,vals + +def svdsolv(A,b,eps=None,rcond=None,List_errors=None,Dict_logs=None): + from scipy import linalg as scipy_linalg + from .utils import arrayclone + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + dbgng_sync=True # XXX XXX + if( MPIsize < 2 ): + dbgng_sync= False + dbgng=True # XXX XXX + if( eps is None ):eps=np.finfo(float).eps + Ndim=np.shape(A) + + if(dbgng_sync): + sqrediff_IN,maxabsdiff_IN,At_IN,vals_IN = mpi_aNdiff(A,"svdsolv_INPUT") + sqrediff_b,maxabsdiff_b,At_b,vals_b = mpi_aNdiff(b,"svdsolv_INPUTb") + + U,w,Vh=scipy_linalg.svd(A) + if(dbgng_sync): + sqrediff_U,maxabsdiff_U,At_U,vals_U = mpi_aNdiff(U,"svdsolv_Umat") + sqrediff_w,maxabsdiff_w,At_w,vals_w = mpi_aNdiff(w,"svdsolv_w") + sqrediff_Vh,maxabsdiff_Vh,At_Vh,vals_Vh = mpi_aNdiff(Vh,"svdsolv_Vh") + + N=len(w) + absmXw=max( abs(w) ) + absmNw=min( abs(w) ) + if( absmXw < eps ): + string="svdsolv:!E:all max|singular value|(=%e) < eps(:=%e)"%(absmXw,eps) + if( List_errors is not None): + List_errors.append(string); + return None,None + else: + assert False,"" + condition_number=absmNw/absmXw + if( Dict_logs is not None): + warn=( condition_number < 1.0e-12 ) + key=('warning' if(warn) else 'info') + string="svdsolv:%s condition number %e"%( ('!W' if(warn) else ''),condition_number ) + if( key not in Dict_logs ): + Dict_logs.update({key:[]}) + Dict_logs[key].append(string) + + thr=eps + if( rcond is None ): + thr=eps*absmXw +## A = U w Vh +## [M,N] [M,N][N,N][N,N] +## here, Vh[i][:] is the Ith vector + cofs=(np.zeros([N],dtype=(np.array(A)).dtype) if(dbgng_sync) else None) + bcpy=arrayclone(b) + ret=np.zeros(Ndim[1]);Nskip=0 + for I in range(N): + if( abs(w[I])> start afresh +# tm_fs >> restart from tm_fs ... md.time_AU must be consistent with tm_fs ... +def calc_OAS(md, rttddft, Evector, gauge_LorV, dmfilepath, + tm_fs_end=24.0, tm_fs_step=0.008, tm_fs_offset=None, + tmStart_AU = 0.0, tmKick_AU =None, Nstep_Kick=20, logger=None, logfile=None, propagator="CN", + Nstep_dump=None, tsecond_dump=None, WCt00=None, dumpfilename=None, Nstep_calcEng=None, + Nstep_calcDOS=None, check_timing=False, params=None, job=None ): +## GPAW recommends Nstep_Kick = kick_ampd / 1.0e-4 +## Here default values are kick_ampd = 1.0e-3 so Nstep_Kick=20 is large enough + + calc_MOprojection=False + + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + check_sync=1 + if(job is not None): + rttddft_common.set_job(job) + else: + rttddft_common.set_job("_".join( ["OAS", gauge_LorV+'G', "dt%3.1f"%(tm_fs_step*1e+3)+"as"])) + + + verbose=0 + if( tsecond_dump is not None ): + assert WCt00 is not None,"" + restart=(tm_fs_offset is not None) + if(tm_fs_offset is not None): + assert (tm_fs_offset > tm_fs_step),"" + wct_00=time.time() + + assert (propagator=="CN" or propagator=="Magnus"),"wrong propagator:"+propagator + use_Magnus=(propagator=="Magnus") + fnme1="calc_OAS.log";tm00=time.time() + printout("#calc_OAS:"+rttddft_common.get_job(True) + +":"+propagator+":%7.3fas tend:%8.3ffs"%(tm_fs_step*1000,tm_fs_end),fpath=fnme1,Append=True,Threads=[0]); + if( logger is None ): + assert (logfile is not None),"logfile" + logger=Logger(logfile) + md.logger=logger + aut_in_femtosec=PhysicalConstants.aut_in_femtosec(); + pbc = md.pbc + assert (gauge_LorV=='L' or gauge_LorV=='V'),"wrong gauge:"+gauge_LorV + if(tmKick_AU is None): + tmKick_AU = 1.0 # By definition this must be unity + + if( MPIsize>1 ): + sqrediff,maxabsdiff,At,vals = mpi_aNdiff(md.tdMO,"calc_OAS.initial_tdMO",sync=True) + printout("#tdMO: %6d %04d %16.8f %16.6e %10.4f+j%10.4f/%10.4f+j%10.4f at "%(0,0,\ + np.sqrt(sqrediff),maxabsdiff,vals[0].real,vals[0].imag,vals[1].real,vals[1].imag)\ + +str(At), fnme_format="calc_OAS_sync%02d.log",Append=False) + + F=None;nAO=None;nkpt=None + rttddft.update_Sinv() + + # if MPIsize>1, we synchronize Sinv ( you may not need such operation ) + # + if( (MPIsize>1) and (check_sync>1) ): + sqrediff,maxabsdiff,At,vals = mpi_aNdiff( rttddft._Sinvrt,"calc_OAS.initial_Sinvrt",sync=True) + printout("### Ssqrt: %6d %04d %16.8f %16.6e %10.4f+j%10.4f/%10.4f+j%10.4f at "%(0,0,\ + np.sqrt(sqrediff),maxabsdiff,vals[0].real,vals[0].imag,vals[1].real,vals[1].imag)\ + +str(At), fnme_format="calc_OAS_sync%02d.log",Append=True) + + rttddft_common.Dict_setv("rtTDDFT_Istep",0) + if( gauge_LorV == 'L' and (not restart) ): + printout("#calc_OAS: applying delta-like pulse.."); + logfile="calc_OAS.log"; + printout("#calc_OAS:DIPOLE GAUGE:%f %f %f"%(Evector[0],Evector[1],Evector[2]),fpath=logfile,Append=True,Threads=[0]); + rttddft.dipolegauge=True; rttddft.velocitygauge=False + # apply H= - (-e r : E) + if( not pbc ): + dipole_matr = rttddft.mol.intor('int1e_r',comp=3, hermi=1) # 3,nAO,nAO + + if( F is None ): + Ndim_dp = np.shape(dipole_matr) + nAO=Ndim_dp[1]; assert (Ndim_dp[0]==3 and Ndim_dp[2]==nAO),"" + F=np.zeros([nAO,nAO],np.complex128) + for I in range(nAO): + for J in range(nAO): + F[I][J]= Evector[0] * dipole_matr[0][I][J] + for dir in range(1,3): + F[I][J]+= Evector[dir] * dipole_matr[dir][I][J] + + S1e_1=rttddft.get_ovlp() + if( calc_MOprojection ): + md.calc_MOprojection(rttddft,"",fpath="calcOAS_checkMO.dat",append=False) + + if(use_Magnus): + tdMO_AF = Magnus_AOrep(rttddft._Ssqrt,rttddft._Sinvrt,nAO,F,F, tmKick_AU, md.tdMO) + else: + tdMO_AF = CNlnr_AOrep (rttddft._Ssqrt,rttddft._Sinvrt,F,F, tmKick_AU, Nstep_Kick, md.tdMO, + check_vecnorms=True, check_projection="CheckMO_CNlnrAOrep.dat", rttddft=rttddft ) + for I in range(len(tdMO_AF)): + for J in range(len(tdMO_AF[0])): + md.tdMO[I][J]=tdMO_AF[I][J] + dict={"excitedstate_populations":None} + if( calc_MOprojection ): + md.calc_MOprojection(rttddft,"",fpath="calcOAS_checkMO.dat",dict=dict) + logger.Info("#excitedstate_populations:"+d1toa(dict["excitedstate_populations"])) + else: + # + # Usually LG does not make sense in the periodic direction. + # But it does make sense if it is perpendicular to the periodic direction + # (e.g. 2D system in the x,y plane + electric field in z direction ) + # + kvectors = np.reshape( rttddft.kpts, (-1,3)) + dipole_matr = rttddft.cell.pbc_intor('int1e_r', comp=3, hermi=1, kpts=kvectors) + if( F is None ): + Ndim_dp = np.shape(dipole_matr) # nkp,3,nAO,nAO + nAO =Ndim_dp[2]; nkp=Ndim_dp[0]; + assert (Ndim_dp[1]==3 and Ndim_dp[2]==Ndim_dp[3]),"--" + F= np.zeros([nAO,nAO], dtype=np.complex128) + + for kp in range(nkp): + S1e_k =rttddft.get_ovlp(rttddft.cell,kvectors[kp]) + for I in range(nAO): + for J in range(nAO): + F[I][J]= Evector[0] * dipole_matr[kp][0][I][J] + for dir in range(1,3): + F[I][J]+= Evector[dir] * dipole_matr[kp][dir][I][J] + + if(use_Magnus): + tdMO_AF = Magnus_AOrep(rttddft._Ssqrt[kp],rttddft._Sinvrt[kp],nAO,F,F, tmKick_AU, md.tdMO[kp]) + else: + tdMO_AF = CNlnr_AOrep (rttddft._Ssqrt[kp],rttddft._Sinvrt[kp],F,F,tmKick_AU,Nstep_Kick,md.tdMO[kp],kp=kp, + check_vecnorms=True, rttddft=rttddft) + + for I in range(len(tdMO_AF)): + for J in range(len(tdMO_AF[0])): + md.tdMO[kp][I][J]=tdMO_AF[I][J] + + if( MPIsize>1 ): + sqrediff,maxabsdiff,At,vals = mpi_aNdiff(md.tdMO,"calc_OAS.0th_tdMO",sync=True) + printout("calc_OAS.initial_tdMO: %16.8f %16.6e %10.4f+j%10.4f/%10.4f+j%10.4f at "%(\ + np.sqrt(sqrediff),maxabsdiff,vals[0].real,vals[0].imag,vals[1].real,vals[1].imag)\ + +str(At), fnme_format="calc_OAS_sync%02d.log",Append=False) + elif( gauge_LorV == 'L' and restart ): + rttddft.dipolegauge=True; rttddft.velocitygauge=False + logfile="calc_OAS.log"; + printout("#calc_OAS:restart:tm_fs_offset=%f:DIPOLE GAUGE:%f %f %f"%(tm_fs_offset,Evector[0],Evector[1],Evector[2]), + fpath=logfile,Append=True,Threads=[0]); + elif( gauge_LorV == 'V' ): + logfile="calc_OAS.log"; + if( restart ): + printout("#calc_OAS:restart:tm_fs_offset=%f:VELOCITY GAUGE:%f %f %f"%(tm_fs_offset,Evector[0],Evector[1],Evector[2]), + fpath=logfile,Append=True,Threads=[0]); + else: + printout("#calc_OAS:VELOCITY GAUGE:%f %f %f"%(Evector[0],Evector[1],Evector[2]), + fpath=logfile,Append=True,Threads=[0]); + + rttddft.dipolegauge=False; rttddft.velocitygauge=True + field=None + + fd01=open(rttddft_common.get_job(True)+"_tdfield.log","a");print("tdField:kickfield",file=fd01);fd01.close() + field=kickfield(Evector,tmStart_AU=tmStart_AU) + + logger.Info("#calc_OAS:velocity gauge... kickField:"+str(Evector)+" tmStart:%f"%(tmStart_AU)); + md.td_field=field + md.gauge_LorV='V' + rttddft._td_field=field + + if( check_timing ): + rttddft.print_log("calc_OAS:zero_th-kick-step:",timing=True); + + logger.Info("#calc_OAS: starting normal time propagation....:dt=%f T=%f"%(tm_fs_step,tm_fs_end)); + + calc_OAS_propagate( md, rttddft, dmfilepath, Evector, tmKick_AU, + tm_fs_end=tm_fs_end,tm_fs_step=tm_fs_step, tm_fs_offset=tm_fs_offset, + propagator=propagator, Nstep_dump=Nstep_dump, tsecond_dump=tsecond_dump, + WCt00=WCt00, dumpfilename=dumpfilename, restart=restart, Nstep_calcEng=Nstep_calcEng, + Nstep_calcDOS=Nstep_calcDOS, check_timing=check_timing, params=params) + + logfile="calc_OAS.log";tm01=time.time(); + printout("## calc_OAS:"+ rttddft_common.get_job(True)+":End:%f sec"%(tm01-tm00), + fpath=logfile,Append=True,Threads=[0]); + + +def calc_OAS_propagate( md, rttddft, dmfilepath, Evector, tmKick_AU, + tm_fs_end=24.0,tm_fs_step=0.008, tm_fs_offset=None, logger=None, propagator="CN", + Nstep_dump=None, tsecond_dump=None, WCt00=None, dumpfilename=None, Nstep_no_save=None, + tsecond_no_save=60*60, verbose=1, restart=False, Nstep_calcEng=None, Nstep_calcDOS=None, + check_timing=False, params=None, nmax_warn=-1, nmax_seq_warn=3): + + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + WCt01=time.time();WCtCUR=WCt01 + if( tsecond_dump is not None ): + assert WCt00 is not None,"" + if( (Nstep_dump is not None) or (tsecond_dump is not None) ): + assert dumpfilename is not None + # by default this starts from this.time_AU and propagates up to tm_fs_end + # + if logger is None:logger=md.get_logger(set=True); + aut_in_femtosec=PhysicalConstants.aut_in_femtosec() + assert (propagator=="CN" or propagator=="Magnus"),"wrong propagator:"+propagator + use_Magnus=(propagator=="Magnus") + job=rttddft_common.get_job(True) + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank() + fno_incf=-1 + checkField=(rttddft._td_field is not None) ## True + + cLIGHT_AU=PhysicalConstants.CLIGHTinAU() + Fallbackschemes=[ [{'type':'best','reltthr':10}] ] ## 'best' fallback should be the last one + N_fallbackschemes=len( Fallbackschemes ) + + n_warn=0;n_seq_warn=0 + + restart=False + tm_AU_step=tm_fs_step/aut_in_femtosec + if( tm_fs_offset is not None ): + tm_AU_offset = tm_fs_offset/aut_in_femtosec + ### rttddft.time_AU = tm_AU_offset; + assert abs(tm_AU_offset-md.time_AU)<1.0e-4,"tm_AU_offset:%f / MD:%f "%(tm_AU_offset,md.time_AU) + md.set_time_AU(tm_AU_offset,step=0,rttddft=rttddft) + restart=True + else: + assert ( abs(md.time_AU)<1.0e-6),"" + calc_current=True + Nstep = int( round( (tm_fs_end - md.time_AU*aut_in_femtosec)/tm_fs_step ) ) + logger.Info("#calc_OAS_propagate:calculating %d steps dt=%f"%(Nstep,tm_fs_step)) + + logfpath="calc_OAS_propagate.log" + if( not restart and (MPIrank==0) ): + fd=futils.fopen(dmfilepath,"w") + print("#Gauge=%s Kick_strength:%f %f %f tmKick=%f (au) %f (fs) Nstep=%d"%( + ("VG" if(rttddft.velocitygauge) else "LG"),Evector[0],Evector[1],Evector[2],tmKick_AU,tmKick_AU*aut_in_femtosec,Nstep), file=fd) + futils.fclose(fd) + os.system("ls -ltrh "+dmfilepath) + elif( MPIrank==0 ): + printout("#restart:%f au %f fs Nstep=%d"%(md.time_AU,md.time_AU*aut_in_femtosec,Nstep),fpath=logfpath,Append=True,Threads=[0]) + Dic={"devsum_max":-1, "dagdev_max":-1,"ofddev_max":-1,"Nfix":0};nlog=0 + + Istep_saved_last=None;dumpfilenumber=1 + dbgng=False;dbgng_dipole=True;dbgng_iter=True + N_elec=get_Nele( rttddft ) + En_tot_t0=None + tdFockMat=None + if(Nstep_calcEng is not None): + fpath= rttddft_common.get_job(True) + "_tdEng.dat";Edict={'ecoul':None,'ekin':None} + printout("#%5s %14s %14s %16s %16s %16s %16s %18s %16s %14s %14s %14s %14s"%( + "step","time_AU","time_fs","Eel", "ncCoul","elCoul","elKE","enField","En_tot","En_tot_dev", + "DAGdev","OFDdev","dev_Nele"),fpath=fpath,Threads=[0],Append=False) + Eel,ncCoul,elCoul,elKE=md.calc_energy_tot(rttddft,dict=Edict) + DAGdev,OFDdev,Nfix=check_orthnorm(md,rttddft,md.tdMO) + trDM=trace_dmat(rttddft, md.tdDM, rttddft._spinrestriction, rttddft._pbc) + + En_tot=Eel;enField=0 + if( rttddft._calc_Aind != 0 ): + enField,enFieldTOT=calc_FieldEng_cell(rttddft) + En_tot=Eel+enField + print("#En_tot:%e %e %e"%(Eel,enField,En_tot)) + En_tot_t0=En_tot + printout("%6d %14.6f %14.6f %16.8f %16.8f %16.8f %16.8f %18.6e %16.8f %14.4e %14.4e %14.4e %14.4e"%( + 0,md.time_AU,md.time_AU*aut_in_femtosec,Eel, ncCoul,elCoul,elKE, enField,En_tot,abs(En_tot-En_tot_t0), + DAGdev,OFDdev,abs(trDM-N_elec)),fpath=fpath,Append=True,Threads=[0]) + + tdFockMat=get_FockMat(md, rttddft) + filenames=print_TDeorbs( md.spinrestriction, md.tdMO, rttddft, md.pbc, md._canonicalMOs, + tdFockMat, md.mo_occ, job=rttddft_common.get_job(True), Append=(restart),step=0,tm_au=md.time_AU) + printout("#calc_OAS_propagate:TDeorbs:"+str(filenames)) + ldosf_nblock=0 + if( Nstep_calcDOS is not None): + if( tdFockMat is None ): + tdFockMat=get_FockMat(md, rttddft) + ldosf_nblock = calc_ldos( rttddft, rttddft_common.get_job(True), md.tdMO, tdFockMat,\ + emin_eV=None, emax_eV=None, de_eV=0.050, Nstep=None, + iappend=ldosf_nblock, header="#%d:t=%14.4f"%(ldosf_nblock, md.time_AU*aut_in_femtosec), + trailer="\n\n\n", spinrestriction=md.spinrestriction, + widths_eV=[0.2123, 0.1], gnuplot=True, N_elec=N_elec ) + wt_001=time.time();wt_1=wt_001 + skip_MOprojections=1 + check_tdmatr=False + Nstep_syncMO=1 + n_buf=0;buf_results=[];logfile=rttddft_common.get_job(True)+"_calcOASpropagate.log";nstep_prtout=20;threads_printlog=[0] + fd1=open(logfile,'w');fd1.close() + + def print_log(text,Threads=threads_printlog): + if( MPIrank not in Threads ): + return + fd1=open(logfile,'a');print(text,file=fd1);fd1.close() + def printout_buf(Threads=threads_printlog): + if( MPIrank not in Threads ): + return + fd1=open(logfile,'a'); + for item in buf_results: + print(str(item),file=fd1); + fd1.close() + + # printout("#calc_OAS_propagate:df:"+str( type(rttddft.with_df) ),fpath="df.log",Append=True) + for Istep in range(Nstep): + if( checkField and (Istep<100 or Istep%200==0) ): + fd11=open("eldyn_tdfield.log","a"); + A_div_c = rttddft._td_field.get_vectorfield(md.time_AU)/cLIGHT_AU + print("%16.8f %16.8f %16.8f %16.8f"%(md.time_AU,A_div_c[0],A_div_c[1],A_div_c[2]), file=fd11);fd11.close() + + if( MPIsize>1 and (Nstep_syncMO>0 and Istep>0 and Istep%Nstep_syncMO==0) ): + fdDBG=open("eldynDBG_%02d.log"%(MPIrank),"a");print("tdMO:",str(np.shape(md.tdMO)),"step:",Istep,file=fdDBG);fdDBG.close() + sqrediff,maxabsdiff,At,vals = mpi_aNdiff(md.tdMO,"tdMO_calc_OAS_propagate%04d"%(Istep),sync=True) + printout("#tdMO: %6d %04d %16.8f %16.6e %10.4f+j%10.4f/%10.4f+j%10.4f at "%(Istep,0,\ + np.sqrt(sqrediff),maxabsdiff,vals[0].real,vals[0].imag,vals[1].real,vals[1].imag)\ + +str(At), fnme_format="calc_OAS_sync%02d.log",Append=False) + if(check_tdmatr): + name1="tdMO_"+str(rttddft_common.get_job(True)) + fpth1,maxdiff1,indxAT1,sqrdiffsum1,strdiff1 = readwritezN( + 'W',name1,md.tdMO,description="calc_OAS_tdMO %05d %14.4f (fs)"%(Istep,md.time_AU*aut_in_femtosec), + logfile=name1+"_compTO.log",iverbose=1) + name2="tdDM_"+str(rttddft_common.get_job(True)) + fpth2,maxdiff2,indxAT2,sqrdiffsum2,strdiff2 = readwritezN( + 'W',name2,md.tdDM,description="calc_OAS_tdDM %05d %14.4f (fs)"%(Istep,md.time_AU*aut_in_femtosec), + logfile=name2+"_compTO.log",iverbose=1) + + + rttddft_common.Dict_setv("rtTDDFT_Istep",Istep) + + avoid_saving=False + dm_kOR1 = md.calc_tdDM(rttddft) ## this also updates md.tdDM ... + mol_dip=[] + current=None + if(calc_current): + current=get_current(rttddft,densitymatrix=dm_kOR1) + dict_dipoles = get_dipole( rttddft, dm_kOR1,"B",filepath=dmfilepath,headline=(not restart and (Istep==0)), + header="%14.6f "%(md.time_AU), current=current, molecular_dipole=mol_dip,caller="eldyn#calc_OAS_propagate") + if( eldyn_.Dipoles_ini_ is None ): + eldyn_.Dipoles_ini_=dict_dipoles + eldyn_.Dipoles_latest_=dict_dipoles + + DIIS_nstep_thr=( eldyn_default_.DIIS_nstep_thr if( dict_getv(params,'DIIS_nstep_thr') is None) else int(params['DIIS_nstep_thr']) ) + dm2diff_TOL=( eldyn_default_.dm2diff_TOL if( dict_getv(params,'dm2diff_TOL') is None) else float(params['dm2diff_TOL']) ) + maxit=eldyn_default_.maxit + + n_fallback=0;poor_cvg=False;nw=0;str_warning=None;cvgd=False;n_iter=-1 + for ith_fallback in range(N_fallbackschemes): + fallbackscheme=Fallbackschemes[ith_fallback] + Dict_warnings={}; + n_iter=eldyn_singlestep(md,rttddft, tm2_AU= md.time_AU + tm_AU_step,propagator=propagator, maxit=maxit, \ + DIIS_nstep_thr=DIIS_nstep_thr, dm2diff_TOL=dm2diff_TOL,Dict_warnings=Dict_warnings, + List_fallbackschemes=fallbackscheme) + + nw=len(Dict_warnings) + str_warning=(None if(nw==0) else "#warning%02d: calc_OAS_propagate.%05d.%02d:"%(n_warn+1,Istep,ith_fallback)+str(Dict_warnings)) + if(n_iter>=0): + cvgd=True; break + else: + if(n_buf>0): + printout_buf();buf_results.clear();n_buf=0 + print_log("#%6d %12.6f %14.4f %d %d "%(Istep,md.time_AU*aut_in_femtosec, md.time_AU, ith_fallback,n_iter)+str_warning) + + buf_results.append(" %6d %12.6f %14.4f %d %d"%(Istep,md.time_AU*aut_in_femtosec, md.time_AU, ith_fallback, n_iter));n_buf+=1 + if( n_buf >= nstep_prtout ): + printout_buf();buf_results.clear();n_buf=0 + if( not cvgd ): + assert False,"" + if(nw>0): + printout(str_warning,fnme_format='calc_OAS_propagate_%02d_warnings.txt',Append=True,dtme=True,warning=-1); + if(n_buf>0): + printout_buf();buf_results.clear();n_buf=0 + print_log(str_warning); + n_warn+=1;n_seq_warn+=1 + strerr=None + if( n_seq_warn > nmax_seq_warn ): + strerr="calc_OAS_propagate.%05d.%02d n_seq_warn=%d > %d"%(Istep,ith_fallback,n_seq_warn,nmax_seq_warn) + if( (nmax_warn>=0) and (n_warn > nmax_warn) ): + strerr="calc_OAS_propagate.%05d.%02d n_warn=%d > %d"%(Istep,ith_fallback,n_warn,nmax_warn) + if(strerr is not None): + printout(strerr,fnme_format='calc_OAS_propagate_%02d_warnings.txt',Append=True,dtme=True,warning=-1); + assert False,""+strerr + else: + if( n_seq_warn > 0 ): + printout("### step %05d converges:by %d iterations at %d th fallback ###"%( + Istep,n_iter,ith_fallback),fnme_format='calc_OAS_propagate_%02d_warnings.txt',Append=True,dtme=True) + n_seq_warn=0 + wt_2=wt_1;wt_1=time.time(); + if(dbgng_iter): printout("#calc_OAS:%05d iter:%6d elapsed:%14.4f %14.4f"%(Istep,n_iter,wt_1-wt_2,wt_1-wt_001)) + ### print("## calc_OAS_propagate:AF-Step%d"%(Istep),flush=True) + dict={"devsum_max":None, "dagdev_max":None,"ofddev_max":None,"Nfix":None} + md.normalize_MOcofs(rttddft,MO_Coeffs=md.tdMO, dict=dict) + Dic["devsum_max"]=max( Dic["devsum_max"],dict["devsum_max"] ) + Dic["dagdev_max"]=max( Dic["dagdev_max"],dict["dagdev_max"] ) + Dic["ofddev_max"]=max( Dic["ofddev_max"],dict["ofddev_max"] ) + Dic["Nfix"]+=dict["Nfix"] +### nfix,maxdev = check_nrmz(md,rttddft,md.tdMO,norm_dev_tol=1.0e-6) + + prtout=( (dict["Nfix"]>0 and nlog<10) or (Istep%200==0) ) + if(prtout): + printout("step:%d Nfix=%d devsum_max=%e dagdev_max=%e ofddev_max=%e / cum: Nfix=%d devsum_max=%e dagdev_max=%e ofddev_max=%e"%( + Istep,dict["Nfix"],dict["devsum_max"],dict["dagdev_max"],dict["ofddev_max"], + Dic["Nfix"],Dic["devsum_max"],Dic["dagdev_max"],Dic["ofddev_max"]), + fpath=logfpath,Append=True,Threads=[0],flush=(Istep%100==0)); nlog=nlog+1 + + md.set_time_AU( md.time_AU+tm_AU_step, md.step+1,rttddft=rttddft) + + if(Nstep_calcEng is not None): + if((Istep+1)%Nstep_calcEng==0): + fdDAF=open( rttddft_common.get_job(True) + "_tdEng.dat","a");dict={'ecoul':None,'ekin':None} + Eel,ncCoul,elCoul,elKE = md.calc_energy_tot(rttddft,dict=dict) + DAGdev,OFDdev,Nfix=check_orthnorm(md,rttddft,md.tdMO) + + En_tot=Eel;enField=0 + if( rttddft._calc_Aind != 0 ): + enField,enFieldSUM=calc_FieldEng_cell(rttddft) + En_tot=Eel+enField + + trDM=trace_dmat(rttddft, md.tdDM, rttddft._spinrestriction, rttddft._pbc) + for fd1 in [fdDAF,sys.stdout]: + print("%6d %14.6f %14.6f %16.8f %16.8f %16.8f %16.8f %18.6e %16.8f %14.4e %14.4e %14.4e %14.4e"%( + Istep+1,md.time_AU,md.time_AU*aut_in_femtosec,Eel, ncCoul,elCoul,elKE, enField,En_tot,abs(En_tot-En_tot_t0), + DAGdev,OFDdev,abs(trDM-N_elec)),file=fd1) + tdFockMat=get_FockMat(md, rttddft) + print_TDeorbs( md.spinrestriction, md.tdMO, rttddft, md.pbc, md._canonicalMOs, + tdFockMat, md.mo_occ, job=rttddft_common.get_job(True), Append=True,step=Istep+1,tm_au=md.time_AU) + fdDAF.close() + + if( Nstep_calcDOS is not None): + if( (Istep+1)%Nstep_calcDOS == 0 ): + ldosf_nblock = calc_ldos( rttddft, rttddft_common.get_job(True), md.tdMO, tdFockMat, emin_eV=0.0, emax_eV=40.0, de_eV=0.050, Nstep=None, + moldyn=md, iappend=ldosf_nblock, header="#%d:t=%14.4f"%(ldosf_nblock, md.time_AU*aut_in_femtosec), + trailer="\n\n\n", spinrestriction=md.spinrestriction, + widths_eV=[0.2123, 0.1], gnuplot=False ) + #if( check_timing ): + # if( (Istep+1)==1 or (Istep+1)==10 or (Istep+1)==20 or (Istep+1)%50==0 ): + # if(isinstance(rttddft,rttddftPBC_timing)): + # rttddft.print_log( "#calc_OAS:step=%05d"%(Istep+1), timing=True) + # rttddft.print_timerecord( header="### calc_OAS:step=%05d"%(Istep+1) ) + if( (Istep+1)==1 or (Istep+1)==10 or (Istep+1)==50 ): + WCtOLD=WCtCUR;WCtCUR=time.time();perstep_tsec=(WCtCUR-WCt01)/float(Istep+1) + if(Nstep_no_save is None): + Nstep_no_save=max(1, int(round(tsecond_no_save/perstep_tsec))) + if(Nstep_dump is not None): + Nstep_no_save = min( Nstep_no_save, Nstep_dump ) + if(verbose>0): + printout("#calc_OAS_propagate:elapsed %f / %d steps avg %f total %f"%( WCtCUR-WCt01,(Istep+1),perstep_tsec, + WCtCUR-WCt01 if(WCt00 is None) else WCtCUR-WCt00) ) + dbgng=False + if( (Nstep_no_save is not None) and (Istep_saved_last is not None) ): + avoid_saving=(Istep < (Istep_saved_last + Nstep_no_save) ) + +## if( MPIsize<2 or MPIrank==0 ): + save_here=False + Force_save=False + for fno in range(fno_incf+1,5): + dum="eldyn_save_%02d.inc"%(fno_incf); + if(os.path.exists(dum)): + Force_save=True;fno_incf=fno;print("saving eldyn:"+dum) + if( (not avoid_saving) and ( (tsecond_dump is not None) or Force_save )): + WCtCUR=time.time(); + if( ( (WCtCUR-WCt00) + perstep_tsec*0.5 > tsecond_dump ) or Force_save ): + save_here=True + if( (not save_here) and (not avoid_saving) and (Nstep_dump is not None) ): + if( (Istep+1)%Nstep_dump == 0 ): + save_here=True + if( save_here ): + dumpfilenumber=1-dumpfilenumber; + md.save(fpath=dumpfilename+"%02d"%(dumpfilenumber)+".pscf",delimiter='\n', + comment="step:%d time=%f(au) of "%(Istep+1,md.time_AU) + rttddft_common.get_job(True), rttddft=rttddft, + caller="eldyn.L1152,calc_OAS_propagate, step%06d"%(Istep+1), Barrier=True); + Istep_saved_last=Istep;avoid_saving=True + if(dbgng): + test_reload(md,dumpfilename+"%02d"%(dumpfilenumber)+".pscf") + assert False,"" + +def eldyn_singlestep(md,rttddft,tm2_AU, mo_coeff_IN=None, + h1e_kOR1=None, DM1_kOR1=None, tm1_AU=None, + DM2_kOR1=None, maxit=eldyn_default_.maxit, Nstep_CN=20, + DIIS_bufsz=eldyn_default_.DIIS_bufsz, DIIS_ervec_thr=eldyn_default_.DIIS_ervec_thr, + DIIS_nstep_thr=eldyn_default_.DIIS_nstep_thr, + dm2_mixing_factor=0.50,DIISscheme={"updated":'D',"errvecs":'D'}, + DIIS_checkbuf_vnorm_thr=1.0e-5, DIIS_checkbuf_vnorm_relt_thr=1.0e-2,DIIS_checkbuf_nSleep=6, + dm2diff_TOL=eldyn_default_.dm2diff_TOL, F2diff_TOL=5.0e-7, difflog = None, append_difflog=False, + update_attribute=True, Dict_warnings=None, List_fallbackschemes=None, + logger=None, logger2=None,Vnuc_au_1D=None, Nacm_rep=None, fallback=0, force_update=False, + step="", params_prtNacm=None, verbose=False, details=None, append_iterationlog=False, + Niter_clear_buffer=None,Niter_check_buffer=None,diffthr_clear_buffer=None, + propagator="CN", synchronize=True, abort_if_failed=True, reuse_DIIS=False ): + + #> MPI + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + # check_sync: 3: Fock1 + check_sync=1 # check_sync: 2: h1e,DM1,DM2,h2e(:) + # check_sync: 1:normal md.hcore_last, md.Fock_last + # check_sync: 0:minimal + syncthr=2;niter_syncthr=4; + + + #> PhysicalConstants : we only need aut_in_femtosec. + aut_in_femtosec=PhysicalConstants.aut_in_femtosec() + + #> fncdepth, walltime etc. for logging + depth=1;fncnme="eldyn_singlestep";fncdepth=1 ## fncdepth ~ SCF:0 vhf:1 get_j:2 + wt_010=rttddft_common.Get_time();wct_01=time.time() + Wctm000=wct_01;Wctm010=Wctm000;N_call=rttddft_common.Countup("eldyn_singlestep");dic1_timing={} + Dic_timing=rttddft_common.Dict_getv('timing_'+fncnme, default=None) + if( Dic_timing is None ): + rttddft_common.Dict_setv('timing_'+fncnme, {}); + Dic_timing=rttddft_common.Dict_getv('timing_'+fncnme, default=None) + + + #> propagator, either CN or Magnus + assert (propagator=="CN" or propagator=="Magnus"),"wrong propagator:"+propagator + use_Magnus=(propagator=="Magnus") + pbc = md.pbc + + + #> Fallback schemes + diffthr_keep_best=-1;diff_best=None;MO_best=None ## by default, (dm2diff < diffthr_keep_best) never occurs + if(List_fallbackschemes is not None): + for fbs in List_fallbackschemes: + if( fbs['type']=='best'): + assert (Dict_warnings is not None),"" + absthr_default=None; reltthr_default=10 + absthr=dict_getv(fbs,'absthr',None) + if( absthr is not None ): + diffthr_keep_best=absthr + else: + reltthr=dict_getv(fbs,'reltthr',reltthr_default) + diffthr_keep_best=dm2diff_TOL*reltthr + + #> DIIS param : Niter_clear_buffer = How frequently you clear DIIS buffer + #> Note, usually you reach convergence in less than 10 iterations. + if(Niter_clear_buffer is None): + Niter_clear_buffer=70; diffthr_clear_buffer=10*dm2diff_TOL;Nskip_clear_buffer=20;Navoid_clrbuf=70; + if( fallback> 0 ): + Niter_clear_buffer=400;diffthr_clear_buffer=20*dm2diff_TOL; ## Niter_check_buffer=200; + + #assert ( RTTDDFT_.is_rttddft(rttddft) ),"rttddft" + assert ( rttddft._fix_occ ),"set fix_occ first" + assert ( tm2_AU is not None),"" + if mo_coeff_IN is None: mo_coeff_IN = md.tdMO + if tm1_AU is None: tm1_AU= md.time_AU; + if DM1_kOR1 is None: DM1_kOR1 = md.calc_tdDM(rttddft ) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"setup2_dm1",Wctm010-Wctm020,depth=fncdepth) + + #> A. Calculate h1e (hcore) + # + if( h1e_kOR1 is None ): + if( md.hcore_last is None ): + h1e_kOR1=md.calc_hcore(rttddft, time_AU=tm1_AU, dm1_kOR1=DM1_kOR1, tmAU_dmat=tm1_AU) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"setup1_h1eA",Wctm010-Wctm020,depth=fncdepth) + else: + h1e_kOR1=arrayclone(md.hcore_last); ## aNcpy(md.hcore_last,h1e_kOR1) + + assert abs(md.tmAU_hcore_last-tm1_AU)<1.0e-6,"%f / %f :%e"%(md.tmAU_hcore_last,\ + tm1_AU, abs(md.tmAU_hcore_last-tm1_AU)) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"setup1_h1eB",Wctm010-Wctm020,depth=fncdepth) + + #> B. Create DM2_kOR1 + #> note that DM1_kOR1: density matr at t=t_1, fixed + #> DM2_kOR1: density matr at t=t_1+\Delta t updated at each iteration + if DM2_kOR1 is None: DM2_kOR1 = arrayclone(DM1_kOR1) + if logger is None: logger=md.get_logger(True) + SIMPLE_DOT_PRODUCT_=0; AO_DOT_PRODUCT_=1; ORTHNORM_AOMATRICES_=2 + + if( Dict_warnings is not None ): + Dict_warnings.clear() + nmod_check_nrmz=1 + + description="#eldyn_singlestep:tm1=%f (%f fs) dt=%f (%f fs) Nstep_CN=%d eps_CN=%f "%(\ + tm1_AU, tm1_AU*aut_in_femtosec, (tm2_AU-tm1_AU), (tm2_AU-tm1_AU)*aut_in_femtosec, Nstep_CN,\ + (tm2_AU-tm1_AU)/float(Nstep_CN)) + I_step=int(round(tm1_AU/(tm2_AU-tm1_AU))) + + loglvl=1; Nmod_iterationlogf=20; + iteration_logfpath="eldyn_singlestep_%03d.log"%(I_step%Nmod_iterationlogf); + threads_iterationlog=[0] + + devs=[ [], [] ];devs_bfsz=50;diis_status=[];iter_strbuf=[]; Niter_printed=0 + + printout("## step:%03d: %14.4f au %14.4f fs "%(I_step,tm1_AU,tm1_AU*aut_in_femtosec), + fpath=iteration_logfpath,Append=False,Threads=threads_iterationlog) + + def prtout_iteration(iter_unitoffset,d2buf,ibuf,sbuf,bfsz,cvgd,wct_INI,niter_printed): + strresult=None + if(cvgd is not None): + wct_END=time.time(); + if(cvgd): + strresult=" converged N_iter:%5d walltime: %14.4f"%(iter_unitoffset,(wct_END-wct_INI)) + else: + strresult=" DID NOT converge N_iter:%5d walltime: %14.4f"%(iter_unitoffset,(wct_END-wct_INI)) + + if(niter_printed==0): + printout("#%5s %14s %14s %4s"%("iter","dm2Diff","FckDiff","DIIS"), + fpath=iteration_logfpath,Append=True,Threads=threads_iterationlog) + for it_0offset in range(niter_printed,iter_unitoffset): ## @20th(019) 0,20 > @50th(049) 20,50 + imod=it_0offset%bfsz + printout(" %5d %14.4e %14.4e %4d "%(it_0offset,d2buf[0][imod],d2buf[1][imod],ibuf[imod])+("" if(sbuf is None) else sbuf[imod]), + fpath=iteration_logfpath,Append=True,Threads=threads_iterationlog) + if( len(d2buf[0])>=bfsz ): + d2buf[0].clear();d2buf[1].clear();ibuf.clear(); + niter_printed=iter_unitoffset + return niter_printed + def append_log(text,stdout=True): + printout(text,fpath=iteration_logfpath,Append=True,Threads=threads_iterationlog,stdout=stdout); + + params={"tm1_AU":tm1_AU,"tm2_AU":tm2_AU,"Nstep_CN":Nstep_CN}; + converger={"DIIS_bufsz":DIIS_bufsz,"DIIS_ervec_thr":DIIS_ervec_thr,"DIIS_nstep_thr":DIIS_nstep_thr,"dm2_mixing_factor":dm2_mixing_factor}; + description+="\n##CONVERGER:"+str(converger); params.update(converger); + thresholds={"maxit":maxit,"dm2diff_TOL":dm2diff_TOL}; + description+="\n##THRESHOLDS:"+str(thresholds); params.update(thresholds); + misc={"update_attribute":update_attribute}; + description+="\n##misc:"+str(misc); params.update(misc) + logger.timing("singlestep_%d"%(md.step),start=True) + + Ndim_DM2_kOR1 = np.shape( DM2_kOR1 ) + rank_DM2_kOR1 = len( Ndim_DM2_kOR1 ) + nAO=md.nAO;nMO=md.nMO + nkpt=(1 if (not md.pbc) else md.nkpt) + kvectors=( None if(not md.pbc) else np.reshape( rttddft.kpts, (-1,3)) ) + Ndim_Fock = [2,md.nkpt,md.nAO,md.nAO] if( md.pbc and md.spinrestriction=='U') else (\ + [2,md.nAO,md.nAO] if(md.spinrestriction=='U') else (\ + [md.nkpt,md.nAO,md.nAO] if(md.pbc) else [md.nAO, md.nAO])) # assume mol:[nAO][nAO] / pbc:[nkpt][nAO][nAO]... + Ndim_hcore =([md.nkpt,md.nAO,md.nAO] if(md.pbc) else [md.nAO, md.nAO]) + dtype_hcore=np.float64 + rank_Fock=len(Ndim_Fock) + Ndim_MOcoeff=np.shape( mo_coeff_IN ); + rank_MOcoeff=len(Ndim_MOcoeff) + + #> set S^{-1}, S^{-1/2}, S^{1/2} + rttddft.update_Sinv() + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"setup3_Sinv",Wctm010-Wctm020,depth=fncdepth) + + #> spin multiplicity + nmult_Fock=(2 if (md.spinrestriction=='U') else 1) + nmult_DM =(1 if (md.spinrestriction=='R') else 2) + nmult_MO = nmult_Fock + + AOmatr_innerproduct=AO_DOT_PRODUCT_ ### SIMPLE_DOT_PRODUCT_ + + diis=None; ## nmin_DIIS=0 + if(DIIS_bufsz>0): + if( reuse_DIIS ): + if(md._DIIS is None ): + md._DIIS=DIIS01(Ndim_DM2_kOR1,DIIS_bufsz,dtype=np.complex128,ervec_thr=DIIS_ervec_thr,nstep_thr=DIIS_nstep_thr,mixing_factor=dm2_mixing_factor) + diis=md._DIIS + else: + diis=DIIS01(Ndim_DM2_kOR1,DIIS_bufsz,dtype=np.complex128,ervec_thr=DIIS_ervec_thr,nstep_thr=DIIS_nstep_thr,mixing_factor=dm2_mixing_factor) + SAO=None + if( AOmatr_innerproduct == AO_DOT_PRODUCT_ ): + kvecs=(None if(not rttddft._pbc) else np.reshape(rttddft.kpts, (-1,3))) + nkpts=( 1 if(not rttddft._pbc) else len(kvecs) ) + SAO=( rttddft.get_ovlp() if(not rttddft._pbc) else \ + [ rttddft.get_ovlp(rttddft.cell,kvecs[k]) for k in range(nkpts) ]) + if( diis is not None ): + diis.update_AOparams({'AOrep':True,'SAO':SAO,'spinrestriction':rttddft._spinrestriction,'DorF':'D'}) + orthnorm_ervecs=( AOmatr_innerproduct == ORTHNORM_AOMATRICES_ ) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"setup4_DIIS",Wctm010-Wctm020,depth=fncdepth) + + #> Choice of DIIS vectors -- in principle you can use either Density_matrix or Fock_matrix for error vec and updated vecs + #> + #> updated vecs : {u_j} + #> error vecs : {e_j} + #> + #> next vector = \sum_j u_j c_j + #> + #> 0 (e_1|e_1) (e_1|e_2) ... (e_1|e_N) 1 c_1 + #> 0 c_2 + #> 0 = x c_3 + #> .. ... + #> 1 1 1 ... 1 0 -\lambda + diis_updated = 0; diis_errvecs = 0 + FOCK_=2; DMAT_=1; ## constant bit flags + diis_ervec_mixing=None; diis_oldvec_mixing=None + if( (diis is not None) and (DIISscheme is not None) ): + diis_updated=( FOCK_ if( DIISscheme["updated"]=='F') else ( DMAT_ if( DIISscheme["updated"]=='D') else -1)) + diis_errvecs=( FOCK_ if( DIISscheme["errvecs"]=='F') else ( DMAT_ if( DIISscheme["errvecs"]=='D') else -1)) + if( diis_updated == diis_errvecs and (AOmatr_innerproduct != ORTHNORM_AOMATRICES_) ): + diis_ervec_mixing=dm2_mixing_factor; diis_oldvec_mixing=None + else: + diis_ervec_mixing=None; diis_oldvec_mixing=dm2_mixing_factor + assert (diis_updated>0 and diis_errvecs>0),"" + description+="\n##DIISscheme:"+str( DIISscheme ) + V_eff=None + + logger.only_once("eldyn_singlestep",description); + idbgng=0 + ## MATRICES --- + ### md.Fock_last=None 20210616 commented out + if( md.Fock_last is not None ): + if( abs(md.tmAU_Fock_last-tm1_AU)>1.0e-6 ): + printout("Fock1A:tm1_AU %14.4f / tmAU_Fock_last %14.4f"%(tm1_AU,md.tmAU_Fock_last), + fpath="eldyn_FockLast.log",Append=True,Threads=[0]); + md.Fock_last=None + + ## Fock1: allocation=ALWAYS calc=IFF md.Fock is None + Fock1_kOR1_eff = np.zeros( Ndim_Fock, dtype=np.complex128 ) + if( md.Fock_last is None ): + + Fock1_kOR1_eff = rttddft.get_fock( h1e=h1e_kOR1,dm=DM1_kOR1,vhf=md.vhf_last ) ## cycle =-1(default) and diis=None + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"setup5_Fock1A",Wctm010-Wctm020,depth=fncdepth) + else: + Fock1_kOR1_eff = aNcpy( md.Fock_last, Fock1_kOR1_eff ) + assert abs(md.tmAU_Fock_last-tm1_AU)<1.0e-6,"" + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"setup5_Fock1B",Wctm010-Wctm020,depth=fncdepth) + + #> calculate hcore at t=tm2_AU and put it in md.hcore_last + #> + if( rttddft._calc_Aind >= 0 ): + md.hcore_last=md.calc_hcore(rttddft, time_AU=tm2_AU, dm1_kOR1=DM1_kOR1, tmAU_dmat=tm1_AU, Dict_hc=None) + else: + md.hcore_last=md.calc_hcore(rttddft, time_AU=tm2_AU, dm1_kOR1=DM2_kOR1, tmAU_dmat=tm2_AU, Dict_hc=None) + + md.tmAU_hcore_last=tm2_AU; printout("#tmAU_hcore_last:%f"%(md.tmAU_hcore_last),fpath="moldyn_upd.log",Append=True,dtme=True) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"setup6_hcore2",Wctm010-Wctm020,depth=fncdepth) + + #> calculate vhf at t=tm2_AU and put it in md.vhf_last + #> Fock at t=tm2_AU and put it in md.Fock_last + + mol_or_cell=( rttddft.mol if(not rttddft._pbc) else rttddft.cell) ## 2021.07.12 cell->mol_or_cell + md.vhf_last = rttddft.get_veff( mol_or_cell, dm=DM2_kOR1 ) ## 2021.07.12 cell->mol_or_cell + md.Fock_last= rttddft.get_fock( h1e=md.hcore_last,dm=DM2_kOR1,vhf=md.vhf_last) + + md.tmAU_Fock_last=tm2_AU; md.tmAU_vhf_last=tm2_AU + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"setup7_Fock2",Wctm010-Wctm020,depth=fncdepth) + + if( MPIsize>1 ): + string="" + if( check_sync > 0 ): + sqrediff0,maxabsdiff0,At0,vals0 = mpi_aNdiff(DM2_kOR1,"DM2_eldyn%04d_PREP"%(I_step),sync=True) + + if( check_sync > 1 ): + sqrediff1,maxabsdiff1,At1,vals1 = mpi_aNdiff(h1e_kOR1,"h1e_eldyn%04d_PREP"%(I_step),sync=True) + sqrediff2,maxabsdiff2,At2,vals2 = mpi_aNdiff(DM1_kOR1,"DM1_eldyn%04d_PREP"%(I_step),sync=True) + sqrediff3,maxabsdiff3,At3,vals3 = mpi_aNdiff(md.hcore_last,"h2e_eldyn%04d_PREP"%(I_step),sync=True) + if( I_step < 3 or I_step==20 ): + string+= "#DM2: %6d %4d "%(I_step,0) + mpidiffs_tostring_(sqrediff0,maxabsdiff0,At0,vals0) \ + +"#h1e: %6d %4d "%(I_step,0) + mpidiffs_tostring_(sqrediff1,maxabsdiff1,At1,vals1) \ + +"#DM1: %6d %4d "%(I_step,0) + mpidiffs_tostring_(sqrediff2,maxabsdiff2,At2,vals2) + if( check_sync > 2): + sqrediff5,maxabsdiff5,At5,vals5 = mpi_aNdiff(Fock1_kOR1_eff,"Fock1_eldyn%04d_PREP"%(I_step),sync=True) + sqrediff6,maxabsdiff6,At6,vals6 = mpi_aNdiff(md.Fock_last,"Fock2_eldyn%04d_PREP"%(I_step),sync=True) + if( I_step < 3 or I_step==20 ): + string+= "#Fock1: %6d %4d "%(I_step,0) + mpidiffs_tostring_(sqrediff5,maxabsdiff5,At5,vals5) \ + +"#Fock2: %6d %4d "%(I_step,0) + mpidiffs_tostring_(sqrediff6,maxabsdiff6,At6,vals6) + if( (I_step < 3 or I_step==20) and len(string)> 0 ): + printout(string, fnme_format="calc_OAS_sync%02d.log",Append=True) + + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"setup8_sync",Wctm010-Wctm020,depth=fncdepth) + + MOcoeff_kOR1 = arrayclone(mo_coeff_IN) ### .copy() + + #> Fock, DM2_kOR1 at the previous iteration step is stored in Fock2_old, DM2_kOR1_old + Fock2_old = np.zeros( Ndim_Fock, dtype=np.complex128) + DM2_kOR1_old = arrayclone( DM2_kOR1 ) ### .copy() + MOcoeff_kOR1org = arrayclone(mo_coeff_IN) ### .copy() + + ## (i) Fock1_kOR1_eff contains possible Nacm + ## (ii) md.Fock_last does NOT contain Nacm.. it is to be treated separately + + if( Vnuc_au_1D is not None ): + ## We simply assume Vnuc does not change over a short period... + Vdot_nacm_eff = calc_Vdot_nacm_eff(rttddft,Vnuc_au_1D, Nacm_rep=Nacm_rep, check_antihermicity=True) + if( params_prtNacm is not None): + Istep=params_prtNacm["Istep"];job=params_prtNacm["job"];logger=params_prtNacm["logger"] + prtNacm( pbc,md.spinrestriction, Vdot_nacm_eff, MOrep=True, refr_MO=md.tdMO, Vnuc_1D=Vnuc_au_1D, job=job, Istep=Istep, tm_au=rttddft._time_AU,\ + logger=md.get_logger(True) ) + Fock1_kOR1_eff = to_complexarray( Fock1_kOR1_eff ) + Ndim_Fock1=np.shape(Fock1_kOR1_eff) + if( not pbc ): ## h1e[nAO][nAO] -= i\hbar Vdot_nacm_eff[nAO][nAO].. + for i in range(Ndim_Fock1[0]): + for j in range(Ndim_Fock1[1]): + Fock1_kOR1_eff[i][j]-= 1j*Vdot_nacm_eff[i][j] + else: + for i in range(Ndim_Fock1[0]): + for j in range(Ndim_Fock1[1]): + for k in range(Ndim_Fock1[2]): + Fock1_kOR1_eff[i][j][k]-= 1j*Vdot_nacm_eff[i][j][k] + + cvgd=False; iter=0; dm2diff=-1.0 + writer=None + iter_startdiis=-1;iter_clrbuf=-1 + if( diis is not None): + diis.writer=writer + dict_DIIS_coefs=None + diis_started=False + diff_min=None;dmOpt=None + DM2_indices=[] + if( details is not None and ("dmOpt" in details) ): + if( details["dmOpt"] is None ): + details["dmOpt"]=np.zeros( Ndim_DM2_kOR1, dtype=np.complex128) + diff_min=details["diff_min"];dmOpt=details["dmOpt"] + + if(True): + Dic1={"devsum_max":None, "dagdev_max":None,"ofddev_max":None,"Nfix":None} + md.normalize_MOcofs(rttddft,MO_Coeffs=md.tdMO, dict=Dic1) + assertf(Dic1['Nfix']==0,"normalize_MOcofs retv:"+str(Dic1),1) + iter_strbuf.append(str(Dic1)) + + dm2diff_min=9.9e+20; dm2diff_at=-1 + + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"setup9_misc",Wctm010-Wctm020,depth=fncdepth) + + Wctm_ITER00=time.time() + while( not cvgd and iter=1 and iter<=10 ): + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"iter%02d"%(iter),Wctm010-Wctm020,depth=fncdepth) + + ## all quantities are derived from + ## (i) md.hcore_last(h2e), h1e_kOR1, DM1_kOR1, Fock1_kOR1_eff ---- already been synchronized + ## (ii) DM2_kOR1 note F2 or md.Fock_last is calculated from h2e and DM2 ... + + wt_020=rttddft_common.Get_time() + if(iter==1 or iter==10 or iter%50==0 ): + logger.timing("iteration_%d"%(iter)) + + iter+=1 ## iter=1,2,3...,maxit + + #> 1. MOcoeff_kOR1 <-- MOcoeff_kOR1org + assert rank_MOcoeff<=4,"" + + for I in range(Ndim_MOcoeff[0]): + for J in range(Ndim_MOcoeff[1]): + if(rank_MOcoeff==2): + MOcoeff_kOR1[I][J]=MOcoeff_kOR1org[I][J] + else: + for K in range(Ndim_MOcoeff[2]): + if( rank_MOcoeff==3): + MOcoeff_kOR1[I][J][K]=MOcoeff_kOR1org[I][J][K] + else: + for L in range(Ndim_MOcoeff[3]): + MOcoeff_kOR1[I][J][K][L]=MOcoeff_kOR1org[I][J][K][L] + + #> 2. Fock2_old <-- Fock2_kOR1 + assert rank_Fock<=4,"" + for I in range(Ndim_Fock[0]): + for J in range(Ndim_Fock[1]): + if(rank_Fock==2): + Fock2_old[I][J]=md.Fock_last[I][J] + else: + for K in range(Ndim_Fock[2]): + if( rank_Fock==3): + Fock2_old[I][J][K]=md.Fock_last[I][J][K] + else: + for L in range(Ndim_Fock[3]): + Fock2_old[I][J][K][L]=md.Fock_last[I][J][K][L] + + #> 3. construct Fock2 + if( iter>1 and (rttddft._calc_Aind < 0) ): ## < calc_Aind > + md.hcore_last=md.calc_hcore(rttddft, time_AU=tm2_AU, dm1_kOR1=DM2_kOR1, tmAU_dmat=tm2_AU) + + if( (V_eff is None) or ((diis_updated & FOCK_) == 0) ): + + mol_or_cell=( rttddft.mol if(not rttddft._pbc) else rttddft.cell) ## 2021.07.12 cell->mol_or_cell + md.vhf_last = rttddft.get_veff( mol_or_cell, dm=DM2_kOR1 ) ## 2021.07.12 cell->mol_or_cell + md.Fock_last = rttddft.get_fock( h1e=md.hcore_last, dm=DM2_kOR1,vhf=md.vhf_last ) + + + sqrediff_IN1=-1;maxabsdiff_IN1=-1;At_IN1=None;vals_IN1=None + #> 4. propagate MOcoeff ... + for sp in range(nmult_MO): + mo_coeff = ( MOcoeff_kOR1 if(nmult_MO==1) else MOcoeff_kOR1[sp]) + f2_kOR1 = ( md.Fock_last if(nmult_MO==1) else md.Fock_last[sp]) + f1_kOR1 = ( Fock1_kOR1_eff if(nmult_MO==1) else Fock1_kOR1_eff[sp]) ## 2021.12.01 : it now contains possible Nacm term + + # Note : f2_kOR1 originally points to (a part of) md.Fock_last [ i.e. possible modifications affect md.Focklast ] + # but if( Vnuc_au_1D is not None ) it is cloned into a local copy [ i.e. modifications do not affect md.Focklast ] + if( Vnuc_au_1D is not None ): + f2_kOR1 = to_complexarray(f2_kOR1,do_clone=True); Nd_f2=np.shape(f2_kOR1) + assert ( (pbc and len(Nd_f2)==3) or ((not pbc) and len(Nd_f2)==2) ),"" + if( pbc ): + for i in range(Nd_f2[0]): + for j in range(Nd_f2[1]): + for k in range(Nd_f2[2]): + f2_kOR1[i][j][k] -= 1j*Vdot_nacm_eff[i][j][k] + else: + for i in range(Nd_f2[0]): + for j in range(Nd_f2[1]): + f2_kOR1[i][j] -= 1j*Vdot_nacm_eff[i][j] + + #print("eldyn_singlestep:",pbc) + if( not pbc ): + ## it seems that the LHS is newly generated here... + if(use_Magnus): + mo_coeff = Magnus_AOrep(rttddft._Ssqrt,rttddft._Sinvrt,nAO,f2_kOR1,f1_kOR1,tm2_AU-tm1_AU,mo_coeff) + else: + mo_coeff = CNlnr_AOrep (rttddft._Ssqrt,rttddft._Sinvrt,f2_kOR1,f1_kOR1,tm2_AU-tm1_AU,Nstep_CN,mo_coeff, + check_vecnorms=(md.step%200==1),rttddft=rttddft,moldyn=md) + if(nmult_MO==1): + MOcoeff_kOR1=mo_coeff + else: + MOcoeff_kOR1[sp]=mo_coeff + else: + if(use_Magnus): + for k in range(nkpt): + assert False,"#2021.08.03 XXX XXX I think this should be : mo_coeff[k]=Magnus_AOrep(...) PLS fix and TEST it..." + mo_coeff = Magnus_AOrep(rttddft._Ssqrt[k],rttddft._Sinvrt[k],nAO,f2_kOR1[k],f1_kOR1[k],tm2_AU-tm1_AU,mo_coeff[k]) + else: + #print("eldyn_singlestep:",nkpt,np.shape(rttddft._Ssqrt[0])) + for k in range(nkpt): + mo_coeff[k] = CNlnr_AOrep (rttddft._Ssqrt[k],rttddft._Sinvrt[k],f2_kOR1[k],f1_kOR1[k],tm2_AU-tm1_AU,Nstep_CN,mo_coeff[k], + kp=k, check_vecnorms=(md.step%200==1),rttddft=rttddft,moldyn=md) + if(nmult_MO==1): + MOcoeff_kOR1[k]=mo_coeff[k] + else: + MOcoeff_kOR1[sp][k]=mo_coeff[k] + + strchecknrmz="" + if( nmod_check_nrmz>0 ): + if( iter%nmod_check_nrmz==0 ): + Dic1={"devsum_max":None, "dagdev_max":None,"ofddev_max":None,"Nfix":None} + md.normalize_MOcofs(rttddft,MO_Coeffs=MOcoeff_kOR1, dict=Dic1) + assertf(Dic1['Nfix']==0,"normalize_MOcofs %04d.%03d retv:"%(I_step,iter)+str(Dic1),1) + strchecknrmz= str(Dic1) + iter_strbuf.append(strchecknrmz) + + #> 5. DM2_kOR1_old <- DM2_kOR1 + for I in range(Ndim_DM2_kOR1[0]): + for J in range(Ndim_DM2_kOR1[1]): + if(rank_DM2_kOR1==2): + DM2_kOR1_old[I][J]=DM2_kOR1[I][J] + else: + for K in range(Ndim_DM2_kOR1[2]): + if( rank_DM2_kOR1==3): + DM2_kOR1_old[I][J][K]=DM2_kOR1[I][J][K] + else: + for L in range(Ndim_DM2_kOR1[3]): + DM2_kOR1_old[I][J][K][L]=DM2_kOR1[I][J][K][L] + + + #> 6. new DM2 from MOcoeff_kOR1 + DM2_kOR1 = rttddft.make_rdm1( MOcoeff_kOR1, md.mo_occ ) ## 2020.11.28 make DM out of tdMO + + fckdiff=( -1.0 if(Fock2_old is None) else aNmaxdiff(Fock2_old,md.Fock_last) ) + + vcdiff1D=np.ravel( DM2_kOR1_old-DM2_kOR1 ); + if( AOmatr_innerproduct == AO_DOT_PRODUCT_ ): + assert SAO is not None,"" + dm2diff=dot_AOmatrices( vcdiff1D, vcdiff1D, SAO, rttddft._spinrestriction,'D') + else: + dm2diff=np.vdot( vcdiff1D, vcdiff1D ) + assert abs(dm2diff.imag)<1.0e-7 and dm2diff.real>=0.0,"dm2diff:"+str(dm2diff) + dm2diff=np.sqrt( abs(dm2diff.real) ) + + if( MPIsize>1 and (niter_syncthr > 0) and (iter)%niter_syncthr==0 ): + ## NOTE: here we do synchronize threads ----- + sqrediff_MOcofs,maxabsdiff_MOcofs,At_MOcofs,vals_MOcofs = mpi_aNdiff(MOcoeff_kOR1,"MOcoeff_kOR1_eldyn%03d.%03d"%(I_step,iter),sync=True) + sqrediff_DM2,maxabsdiff_DM2,At_DM2,vals_DM2 = mpi_aNdiff(DM2_kOR1,"DM2_kOR1_eldyn%03d.%03d"%(I_step,iter),sync=True) + string=" %6d %4d %14.6e %14.6e %10.4f %10.4f %10.4f %10.4f %10.4f %10.4f %10.4f %10.4f"%(\ + I_step,iter,maxabsdiff_MOcofs,maxabsdiff_DM2, + vals_MOcofs[0].real,vals_MOcofs[0].imag, vals_MOcofs[1].real,vals_MOcofs[1].imag, + vals_DM2[0].real,vals_DM2[0].imag, vals_DM2[1].real,vals_DM2[1].imag) + legend="#%6s %4s %14s %14s %21s %21s %21s %21s"%(\ + "Istep","iter","maxabsdiff_MO","maxabsdiff_DM","MO_loc","MO_ref","DM2_loc","DM2_ref") + fd1=open("eldyn_syncthreads_%02d.log"%(MPIrank),'a'); + print(string,file=fd1); + fd1.close() + + if(loglvl>=3): + print_dm2(DM2_kOR1_old,DM2_kOR1,DM2_indices,iter,filepath=iteration_logfpath) + + devs[0].append(dm2diff);devs[1].append(fckdiff);diis_status.append(diis_started) + + if( writer is not None ): + writer.append("%d %e %e %d"%(iter,dm2diff,fckdiff,(1 if(diis_started) else 0))) + if( iter==20 ): + Niter_printed = prtout_iteration(iter,devs,diis_status,iter_strbuf,devs_bfsz,None,wct_01,Niter_printed) + elif( iter>=50 and iter%50==0 ): + Niter_printed = prtout_iteration(iter,devs,diis_status,iter_strbuf,devs_bfsz,None,wct_01,Niter_printed) + + ## ---------------------------------------------------------- + if( (diff_min is None) or diff_min> dm2diff): + diff_min=dm2diff; + if( details is not None and ("dmOpt" in details) ): + #7. details["dmOpt"] <- DM2_kOR1 + for I in range(Ndim_DM2_kOR1[0]): + for J in range(Ndim_DM2_kOR1[1]): + if(rank_DM2_kOR1==2): + details["dmOpt"][I][J]=DM2_kOR1[I][J] + else: + for K in range(Ndim_DM2_kOR1[2]): + if( rank_DM2_kOR1==3): + details["dmOpt"][I][J][K]=DM2_kOR1[I][J][K] + else: + for L in range(Ndim_DM2_kOR1[3]): + details["dmOpt"][I][J][K][L]=DM2_kOR1[I][J][K][L] + ## ----------------------------------------------------------- + if( MPIsize > 1 ): + diffs_local=[dm2diff,fckdiff] + diffs_00=sync_dbuf([dm2diff,fckdiff],"sync_eldyn_diffs_%03d.%03d"%(I_step,iter),root=0) + dm2diff=diffs_00[0];fckdiff=diffs_00[1] + icvgd=(1 if(dm2diffmol_or_cell + md.vhf_last = rttddft.get_veff( mol_or_cell, dm=DM2_kOR1 ) ## 2021.07.12 cell->mol_or_cell + md.Fock_last = rttddft.get_fock( h1e=md.hcore_last,dm=DM2_kOR1,vhf=md.vhf_last ) + ### md._dbg_update_FockLast("eldyn_singlestep.1128",dm=DM2_kOR1,Rnuc=md.Rnuc) + + + if( diis is not None): + + Nremov=None + if( Navoid_clrbuf <=0 or (iter_clrbuf<0 or iter-iter_clrbuf>Navoid_clrbuf)): + iter_eff=(iter if(iter_clrbuf<0) else iter-iter_clrbuf) + if( iter_eff>=Niter_clear_buffer and (iter_eff-Niter_clear_buffer)%Nskip_clear_buffer==0 and dm2diff> diffthr_clear_buffer): + range_m=3; n_stepback=10; relt_thr=0.10; Nkeep=0 + recent_m_sqrerrors=diis.get_recent_sqrerrors(range_m,0); recent_errmin=np.sqrt( min(recent_m_sqrerrors) ) + old_m_sqrerrors =diis.get_recent_sqrerrors(range_m,n_stepback); old_errmin=np.sqrt( min(old_m_sqrerrors) ) + + if( recent_errmin / old_errmin >= relt_thr ): + Nremov=diis.check_buffer_02(Nkeep,order='E',nSleep=6) + append_log("## diis_clear iter:%6d Nremov=%d recent_errmin:%e / old_errmin:%e"%(iter,Nremov,recent_errmin,old_errmin)) + else: + append_log("## skipping diis.clear iter:%6d recent_errmin:%e / old_errmin:%e"%(iter,recent_errmin,old_errmin)) + if( Nremov is not None): + iter_clrbuf=iter + log="#eldyn_singlestep:DIIS removes %d vectors.."%(Nremov) + if( writer is not None ): + writer.append(log) + writer.append("#DIIS_vecs:"+i1toa(diis.ibuf,N=min(diis.nbuf, diis.bfsz))) + + + if( diis is not None ): + # + # dm-update: vec=dm2, err=delta FockMat / delta dm2; F2[ updated_dm2 ] -> CNlnr_and_dm2 [ F2 ] + # Fock-update:vec=H2, err=delta dm2 / delta FockMat; CNlnr_and_dm2 [ updated_F2 ] -> F2[ dm2' ] + # + + dict_DIIS_coefs={"coef":None,"ibuf":None} + started=diis.started + if( started and iter_startdiis<0 ): + iter_startdiis=iter + elif( (not started) and iter_startdiis>=0 ): + iter_startdiis=-1 + + ervec_AOrep = (DM2_kOR1 - DM2_kOR1_old) if( (diis_errvecs & DMAT_)!=0 ) else (md.Fock_last - Fock2_old ) + ervec = ( calc_DIIServec(rttddft, ervec_AOrep, ('D' if( (diis_errvecs & DMAT_)!=0 ) else 'F') ) if(orthnorm_ervecs) else \ + ervec_AOrep ) + + if( (diis_updated & FOCK_)!=0 ): + md.Fock_last= diis.update(md.Fock_last, ervec=ervec,dict=dict_DIIS_coefs,Iter=iter, ervec_mixing=diis_ervec_mixing,oldvec_mixing=diis_oldvec_mixing) + ### md.dbg_update_FockLast("eldyn_singlestep.1199",dm=[],Rnuc=md.Rnuc) + md.vhf_last=None; md.tmAU_vhf_last=None ## 20210616: we discard vhf since it is no longer consistent to FockMat.. + + elif( (diis_updated & DMAT_)!=0 ): + DM2_kOR1=diis.update(DM2_kOR1, ervec=ervec,dict=dict_DIIS_coefs,Iter=iter, + ervec_mixing=diis_ervec_mixing,oldvec_mixing=diis_oldvec_mixing) ### , ervec_norm=ervec_norm) + dic1={} + DM2_kOR1=normalize_DM(rttddft,DM2_kOR1,dev_TOL=1.0e-7,Istep=I_step,Iter=iter,Dict=dic1) + if( dic1['Nfix']>0 ): + printout(str(dic1),fpath=iteration_logfpath,Append=True,Threads=[0],warning=1) + + diis_started = diis.started + + + if( (diis_updated & FOCK_) != 0 and (diis_errvecs & DMAT_) !=0 ): + # 8. calculate Fock iff DIIS is off + if( not diis.started ): + + mol_or_cell=( rttddft.mol if(not rttddft._pbc) else rttddft.cell) ## 2021.07.12 cell->mol_or_cell + md.vhf_last = rttddft.get_veff( mol_or_cell, dm=DM2_kOR1 ) ## 2021.07.12 cell->mol_or_cell + md.Fock_last = rttddft.get_fock( h1e=md.hcore_last,dm=DM2_kOR1,vhf=md.vhf_last ) + ### md.dbg_update_FockLast("eldyn_singlestep.1225",dm=DM2_kOR1,Rnuc=md.Rnuc) + + wt_030=rttddft_common.Get_time() + rttddft_common.Update_timing('single_SCFiter',wt_030-wt_020) + + Niter_printed = prtout_iteration(iter,devs,diis_status,iter_strbuf,devs_bfsz,cvgd,wct_01,Niter_printed) + + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"iterations",Wctm010-Wctm_ITER00,depth=fncdepth) + + if( (not cvgd) and (MO_best is not None)): + ndim_MO=np.shape(MOcoeff_kOR1);le_ndim_MO=len(ndim_MO) + for I in range(ndim_MO[0]): + for J in range(ndim_MO[1]): + if( le_ndim_MO==2 ): + MOcoeff_kOR1[I][J]=MO_best[I][J] + else: + for K in range(ndim_MO[2]): + if( le_ndim_MO==3): + MOcoeff_kOR1[I][J][K]=MO_best[I][J][K] + else: + for L in range(ndim_MO[3]): + if( le_ndim_MO==4): + MOcoeff_kOR1[I][J][K][L]=MO_best[I][J][K][L] + else: + for M in range(ndim_MO[4]): + MOcoeff_kOR1[I][J][K][L][M]=MO_best[I][J][K][L][M] + DM2_kOR1 = rttddft.make_rdm1( MOcoeff_kOR1, md.mo_occ ) + cvgd=True; Dict_warnings.update({'dm2diff':diff_best}) + + if( abort_if_failed ): + assert cvgd," iteration did not converge:best=%e[%d] ... note: set abort_if_failed=False if you have a valid fallback scheme..."%(dm2diff_min, dm2diff_at) + + if( fallback < 0 ): + Logger.write(writer,"#End iteration at:%d dm2diff=%e"%(iter,dm2diff)) + if( details is not None and ("diff_min" in details) ): + details["diff_min"]=diff_min + + rttddft_common.Dict_setv("rtTDDFT_Iter",0) + if( not cvgd ): + if( details is not None and ("dmOpt" in details) ): + + # 9. DM2_kOR1 <- details["dmOpt"] + for I in range( Ndim_DM2_kOR1[0] ): + for J in range( Ndim_DM2_kOR1[1] ): + if(rank_DM2_kOR1==2): + DM2_kOR1[I][J] = details["dmOpt"][I][J] + else: + for K in range( Ndim_DM2_kOR1[2] ): + if(rank_DM2_kOR1==3): + DM2_kOR1[I][J][K] = details["dmOpt"][I][J][K] + else: + for L in range(Ndim_DM2_kOR1[3]): + DM2_kOR1[I][J][K][L] = details["dmOpt"][I][J][K][L] + # 10.update Fock (DM2_kOR1) + mol_or_cell=( rttddft.mol if(not rttddft._pbc) else rttddft.cell) ## 2021.07.12 cell->mol_or_cell + md.vhf_last = rttddft.get_veff( mol_or_cell, dm=DM2_kOR1 ) ## 2021.07.12 cell->mol_or_cell + md.Fock_last = rttddft.get_fock( h1e=md.hcore_last, dm=DM2_kOR1, vhf=md.vhf_last ) + + # 11.propagate MO_coeff + for sp in range(nmult_MO): + mo_coeff = ( MOcoeff_kOR1 if(nmult_MO==1) else MOcoeff_kOR1[sp]) + f2_kOR1 = ( md.Fock_last if(nmult_MO==1) else md.Fock_last[sp]) + f1_kOR1 = ( Fock1_kOR1_eff if(nmult_MO==1) else Fock1_kOR1_eff[sp]) + + if( not pbc ): + mo_coeff = CNlnr_AOrep (rttddft._Ssqrt,rttddft._Sinvrt,f2_kOR1,f1_kOR1,tm2_AU-tm1_AU,Nstep_CN,mo_coeff, + check_vecnorms=(md.step%200==1),rttddft=rttddft,moldyn=md) + if( nmult_MO == 1 ): + MOcoeff_kOR1 = mo_coeff + else: + MOcoeff_kOR1[sp] = mo_coeff + else: + for k in range(nkpt): + mo_coeff[k] = CNlnr_AOrep (rttddft._Ssqrt[k],rttddft._Sinvrt[k],f2_kOR1[k],f1_kOR1[k],tm2_AU-tm1_AU,Nstep_CN,mo_coeff[k], + kp=k, check_vecnorms=(md.step%200==1),rttddft=rttddft,moldyn=md) + if( nmult_MO == 1 ): + MOcoeff_kOR1[k] = mo_coeff[k] + else: + MOcoeff_kOR1[sp][k] = mo_coeff[k] + + DM2_NEW = rttddft.make_rdm1( MOcoeff_kOR1, md.mo_occ ) + dm2diff=dot_AOmatrices( DM2_NEW-DM2_kOR1, DM2_NEW-DM2_kOR1, SAO, rttddft._spinrestriction,'D') + dm2diff=np.sqrt( abs(dm2diff.real) ) + + Logger.write( writer,"#fallback:apply best result:diff_min %e >> final diff %e"%(details["diff_min"],dm2diff)) + + + if( rttddft._calc_Aind != 0 ): + update_Aind_over_c(rttddft) + Aind_overC=rttddft._Aind_Gearvc_C[0];tm_fs=rttddft._Aind_tmAU*physicalconstants.aut_in_femtosec + + result = "Iteration "+("converged" if(cvgd) else "did not converge") + " after %d iterations."%(iter) + if( writer is not None ): + if( len(devs[0])>0 ): + for j in range(len(devs[0])): + writer.append("%d %e %e %d"%(j,devs[0][j],devs[1][j],(1 if(diis_status[j]) else 0))) + writer.append("#"+result) + renameto=None + if( iter >=100 ): + if( not append_iterationlog ): + renameto="eldyn_iteration_%s.log"%(step) + writer.close(renameto) + + if( not cvgd ): + if( details is not None ): + details["dm2diff"]=dm2diff; + + logger.timing(result,end=True) + logger.Info(result) + + if(synchronize): + sync_threads(md,rttddft,MOcoeff_kOR1,DM2_kOR1,I_step) ## sync + + ## md.print_DMO( "#moldyn_main:AF:%s %r %r"%(step,update_attribute,cvgd), dmat=dm2_kOR1 ) + if(update_attribute): + if( cvgd or (force_update and (details is not None and ("dmOpt" in details))) ): + #if(dbgng_tdMO): + # diff3=aNmaxdiff(MOcoeff_kOR1,md.tdMO,comment="finalMO-md.tdMO:%02d"%(I_step),lower_thr=1.0e-6,iverbose=2, + # title="finalMO-md.tdMO:%02d"%(I_step),logfile="finalMO-md.tdMO_diff.log") + + for sp in range(nmult_MO): + mo_coeff=(MOcoeff_kOR1 if(nmult_MO==1) else MOcoeff_kOR1[sp]) + tdMO=(md.tdMO if(nmult_MO==1) else md.tdMO[sp]) + nd_mo=np.shape(mo_coeff) + for I in range( nd_mo[0] ): + for J in range( nd_mo[1] ): + if( not pbc ): + tdMO[I][J] = mo_coeff[I][J] + else: + for K in range( nd_mo[2] ): + tdMO[I][J][K] = mo_coeff[I][J][K] + dm2_kOR1=(DM2_kOR1 if(nmult_MO==1) else DM2_kOR1[sp]) + tddm =(md.tdDM if(nmult_MO==1) else md.tdDM[sp]) + nd_dm=np.shape(dm2_kOR1) + for I in range( nd_dm[0] ): + for J in range( nd_dm[1] ): + if( not pbc ): + tddm[I][J] =dm2_kOR1[I][J] + else: + for K in range( nd_dm[2] ): + tddm[I][J][K] = dm2_kOR1[I][J][K] + md.save_tempFockMat(md.Fock_last,tm2_AU) + else: + logger.warning("#singlestep:iteration did not converge"); + + + wt_100=rttddft_common.Get_time() + rttddft_common.Print_timing("eldyn_singlestep",["setup","Sinv","hcore","fock","CNlnr","rdm2","diis", + "diis_misc","setup2","setup3","setup4","misc1","Fallback1","af-iteration"], + walltime=wt_100-wt_010,depth=depth,N_iter=iter) + def fnprtoutdict2(arg): + return (arg<=10 or arg%10==0) + Wctm010=time.time() + printout_dict(fncnme,dic1_timing,Dic_timing,Wctm010-Wctm000,depth=fncdepth,fnprtout=fnprtoutdict2) + return (iter if cvgd else min([-1,-iter])) + +# CNlnr_AOrep : wrapper of CNlnr. Canonicalizes input +# S^{-0.5} H S^{-0.5} ( S^{0.5} C ) = i\hbar \partial_t (S^{0.5} C) +# @input : c_in[nAO][Nv] +# @input : check_projection : str output filepath +# @return: ret[nAO][Nv] +def CNlnr_AOrep(Ssqrt,Sinvrt,H2,H1,dt,Nstep,c_in,Nv=None,kp=-1, eorbs=None,check_vecnorms=False,check_projection=None,rttddft=None,moldyn=None): + # here c_in is [*][nAO] dimensional input and we want to propagate Nv vectors + # if( "propagator" in rttddft_common.params ): + # assert rttddft_common.params["propagator"]=="CN","" + + if(Nv is None): + Nv=len(c_in[0]) + nAO=len(c_in) + +# if(kp==0): +# jc=0 +# col_j=[ row[jc] for row in c_in ] # c_in[:,jc] +# print("H0xC0:",end="");print( np.matmul(H1,col_j)) +# print("S0xC0*e:",end="");print( np.matmul( np.matmul(Ssqrt,Ssqrt),col_j)*eorbs[jc]) + + # Sinv(:,:) H Sinv(:,:) Sinv is Hermitian.. + H1modif=np.matmul( np.matmul( Sinvrt,H1), Sinvrt) + # + H2modif=np.matmul( np.matmul( Sinvrt,H2), Sinvrt) + #print("CNlnr_AOrep:",np.shape(H1),np.shape(H2),np.shape(Sinvrt),np.shape(H1modif),np.shape(H2modif)) + ret=np.zeros([nAO,Nv],dtype=np.complex128) + # print("check_projection"+check_projection);assert False,"" + def fnCheckMO(step,tme,coefs): + if( (moldyn is None) or (rttddft is None) ): + return + ndim=np.shape(coefs) + WKS=np.zeros([ ndim[0],ndim[1] ],dtype=np.complex128) + WKS=np.matmul(Sinvrt, coefs) ## Canonical MOs + moldyn.calc_MOprojection(rttddft, "%d %f "%(step,tme), + fpath=("CheckMO_CNlnrAOrep.dat" if (check_projection is None) else check_projection),mo_coeff=WKS) + ### calc_MOprojection( self, rttddft, header,fpath=None,mo_coeff=None,kpts=None,append=True,dict=None) + SxC_in=np.matmul( Ssqrt, c_in) # this allocates a new matrix.. + if( check_projection is not None ): + assert (rttddft is not None),"check_projection" + ret=np.matmul( Sinvrt, CNlnr(H2modif,H1modif,dt,Nstep,SxC_in,check_vecnorms=check_vecnorms,fnc=fnCheckMO) ) + else: + ret=np.matmul( Sinvrt, CNlnr(H2modif,H1modif,dt,Nstep,SxC_in,check_vecnorms=check_vecnorms) ) + return ret + + +# CNlnr : linearly interpolated Crank-Nicolson: +# @input: H2[nAO][nAO], H1[nAO][nAO], dt:time in AU +# c_in[nAO][Nv] +# @return: c[nAO][Nv] (newly allocated) +def CNlnr(H2,H1,dt,Nstep,c_in, norm_dev_tol=1.0e-6, check_vecnorms=False, fnc=None): + # H1*(1-u) + H2*u u=j+0.5/Nstep j=0,1,...,Nstep-1 + # H1 + j*D with D=(H2-H1)/N + ## print("#CNlnr:%f"%(dt)) + assert (c_in.dtype == np.complex128),"wrong type of input for c_in:"+str(c_in.dtype) + nAO=len(c_in);Nv=len(c_in[0]) + fac=1.0/float(Nstep) + DH=np.zeros([nAO,nAO],dtype=np.complex128); H=np.zeros([nAO,nAO],dtype=np.complex128) + c=np.zeros([nAO,Nv],dtype=np.complex128) + DH[:][:]=(H2[:][:]-H1[:][:])*fac + H[:][:]=H1[:][:] + 0.50*DH[:][:] + c[:][:]=c_in[:][:] + eps= dt/float(Nstep) + for j in range(Nstep): + c=CNstep1(H,eps,c) + if( fnc is not None ): + fnc(j,eps*(j+1),c) + H[:][:] = H[:][:] + DH[:][:] + # (c^{\dagger} c)_{jj} is the norm of jth vector + wks=np.zeros([Nv,Nv],dtype=np.complex128) + #wks=np.matmul( np.matrix(c_in).getH(), c_in) + wks=np.matmul( np.transpose(np.conj(c_in)), c_in) + sqnorm0=[] + for j in range(Nv): + sqnorm0.append( wks[j][j].real ) + wks=np.matmul( np.transpose(np.conj(c)), c) + #wks=np.matmul( np.matrix(c).getH(), c) + sqnorm1=[] + for j in range(Nv): + sqnorm1.append( wks[j][j].real ) + devmx=-1; at=-1 + nWarn=0 + for j in range(Nv): + ratio=math.sqrt( sqnorm1[j]/sqnorm0[j] ) + dev1=abs(ratio-1.0) + if( devmx< dev1 ): + devmx= dev1; at=j + if( abs( 1.0- ratio)> norm_dev_tol): + nWarn+=1 + fac=math.sqrt( sqnorm0[j]/sqnorm1[j] ) + for k in range(nAO): + c[k][j]=c[k][j]*fac + if( check_vecnorms or nWarn>0 ): + + printout("norm:N=%d:dt=%e:maxdev:%e %f->%f"%(Nstep,eps,devmx,math.sqrt(sqnorm0[at]),math.sqrt(sqnorm1[at]))) + + return c + + +def mpidiffs_tostring_(sqrediff,maxabsdiff,At,vals,Datf=False,Legend=False): + retv=None;legend="" + if( not Datf ): + retv="%16.8f %16.6e %10.4f+j%10.4f / %10.4f+j%10.4f at "%(\ + np.sqrt(sqrediff), maxabsdiff,vals[0].real,vals[0].imag,vals[1].real,vals[1].imag)\ + + str(At) + else: + retv="%16.8f %16.6e %10.4f %10.4f %10.4f %10.4f"%(\ + np.sqrt(sqrediff), maxabsdiff,vals[0].real,vals[0].imag,vals[1].real,vals[1].imag) + if( not Legend ): + return retv + else: + legend=( "%16s %16s %21s %21s"%('dist','maxabsdiff','lhs','rhs') if(Datf) else + "%16s %16s %22s / %22s at %s"%('dist','maxabsdiff','lhs','rhs','ijk') ) + return retv,legend +# sqrediff,maxabsdiff,At,vals = mpi_aNdiff(md.tdMO,"tdMO_eldyn%03d.%03d"%(I_step,iter)) +def mpi_aNdiff(buf,key,compto=0,sync=False,diff_THR=-1.0, details=False): + from mpi4py import MPI + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if( MPIsize < 2 ): + return + assert compto>=0,"" ## (-1) may mean comp to MPIrank-1 (mod size) th thread but.. + assert comptodiff_THR ): + Ndim=np.shape(buf);leNdim=len(Ndim) + if(leNdim==1): + for I in range(Ndim[0]): + buf[I]=wks[I] + elif(leNdim==2): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + buf[I][J]=wks[I][J] + elif(leNdim==3): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + buf[I][J][K]=wks[I][J][K] + elif(leNdim==4): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + for L in range(Ndim[3]): + buf[I][J][K][L]=wks[I][J][K][L] + elif(leNdim==5): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + for L in range(Ndim[3]): + for M in range(Ndim[4]): + buf[I][J][K][L][M]=wks[I][J][K][L][M] + else: + assert False,"" + return sqrediff,maxabsdiff,At,vals + + +def aNdiff(A,B): + a=np.ravel( np.array(A) ) + b=np.ravel( np.array(B) ) + d=a-b + sqrediff=( np.vdot( d, d) ).real + + maxabsdiff=abs(a[0]-b[0]);at=0;vals=[a[0],b[0]]; + N=len(a) + for I in range(1,N): + dum=abs(a[I]-b[I]) + if( dum>maxabsdiff ): + maxabsdiff=dum; at=I; vals=[a[I],b[I]] + Ndim_A=np.shape(A) + At=ixj_to_IandJ(at,Ndim_A) + return sqrediff,maxabsdiff,At,vals + +def normalize_DM(rttddft,dmat,dev_TOL=1.0e-7,Istep=-1,Iter=-1,Dict=None): + dbgng=True + Nfix=0;string="";dev=0 + trDM=trace_dmat(rttddft, dmat, rttddft._spinrestriction, rttddft._pbc) + N_ele=get_Nele(rttddft) + if( rttddft._spinrestriction == 'R' ): + ## N_ele and trDM are both scalar ... + dev=abs( N_ele-trDM );strfac=" fac:" + if( dev > dev_TOL ): + fac=N_ele/trDM;strfac="%14.4e "%(fac) + dmat=np.array(dmat)*fac;Nfix=Nfix+1 + string="#normalize_DM:"+("@%04d.%03d:"%(Istep,Iter) if(Istep>0 and Iter>0) else "")\ + +"dev:%14.4e "%(dev)+strfac + else: + devs=[-1,-1]; + for sp in range(2): + devs[sp]=abs( N_ele[sp]-trDM[sp] );strfac=" fac:" + if( devs[sp] > dev_TOL ): + fac=N_ele[sp]/trDM[sp];strfac="%14.4e "%(fac) + dmat[sp] = np.array(dmat[sp])*fac; Nfix=Nfix+1 + if( sp== 0 ): + string="#normalize_DM:"+("@%04d.%03d:"%(Istep,Iter) if(Istep>0 and Iter>0) else "") + string+=" dev[%s]:%14.4e "%(sp,devs[sp])+strfac + dev=max(devs) + if(Dict is not None): + Dict.update({'Nfix':Nfix,'log':string,'dev':dev}) + + if(Nfix>0 and dbgng): + trDM=trace_dmat(rttddft, dmat, rttddft._spinrestriction, rttddft._pbc) + dev=( abs(N_ele - trDM) if(rttddft._spinrestriction == 'R') else max( [ abs(N_ele[0] - trDM[0]), abs(N_ele[1] - trDM[1]) ] )) + assert dev=ofd_tol or dagdev>=dag_tol): + printout("#check_orthnorm:!W large dev:DAG:%e [%d][%d] %f+j%f / OFD:%e [%d][%d] %f+j%f"%( + dagdev,dag_ref[0],dag_ref[1], Sij[dag_ref[0]][dag_ref[1]].real, Sij[dag_ref[0]][dag_ref[1]].imag, + ofddev,ofd_ref[0],ofd_ref[1], Sij[ofd_ref[0]][ofd_ref[1]].real, Sij[ofd_ref[0]][ofd_ref[1]].imag)) + + Sij_invsqrt = calc_Sroot(Sij,[-1]) + MO_new = np.matmul(MO, Sij_invsqrt) + Dic={'DAGdev':None,'OFDdev':None} + dev_new=a2sqrdiff( np.matmul( np.matrix.getH( MO ), np.matmul( S1e, MO ) ), np.eye(nMO), DAG_OFDdev=Dic) + printout("#check_orthnorm:dev=%e,%e -> %e,%e"%(dagdev,ofddev,Dic['DAGdev'],Dic['OFDdev'])) + assert dev_new<1.0e-7,"" + Nfix+=1 + return DAGdev,OFDdev,Nfix + +def check_nrmz(md,rttddft,tdMO,norm_dev_tol=1.0e-6): + pbc = md.pbc + nmult_MO=( 2 if(md.spinrestriction=='U') else 1) + nkpt=(1 if (not md.pbc) else md.nkpt) + maxdev=-1.0;nfix=0;value_ref=None + for spin in range(nmult_MO): + MO=( tdMO if(nmult_MO==1) else tdMO[spin] ) + for kp in range(nkpt): + MO1=( MO if(not pbc) else MO[kp] ) + ### dtyp =( np.array( MO1 ).dtype ) + ### icmplx=(dtyp == np.complex128 or dtyp==complex ) + ### print(dtyp);print(icmplx) + S1e=( rttddft.get_ovlp() if(not pbc) else rttddft.get_ovlp(rttddft.cell,kvectors[kp]) ) + ndim=np.shape(MO1); + nAO=ndim[0];nMO=ndim[1] + assert ( len(ndim)==2 ),"" + for jmo in range(nMO): + norm= np.vdot( MO1[:,jmo], np.matmul( S1e, MO1[:,jmo] ) ) + norm=norm.real + ### print("norm:",end="");print(norm) + dev=abs(norm-1) + if( dev > maxdev ): + maxdev=dev;value_ref=norm + if( dev >= norm_dev_tol ): + fac=1.0/math.sqrt(norm);nfix+=1 + for kao in range(nAO): + MO1[kao][jmo]=MO1[kao][jmo]*fac + return nfix,maxdev + +def test_reload(moldyn1,dumpfpath): + os.system("ls -ltrh "+dumpfpath) + md2=Moldyn.load(dumpfpath) + Ndiff,Nsame,Nerr= diff_objects(moldyn1,md2,verbose=1,diff_TOL=1.0e-7) + md2.save("moldyn_dbg.pscf",delimiter='\n',comment=" time=%f(au) of "%(md2.time_AU) + rttddft_common.get_job(True)); + os.system("ls -ltrh "+dumpfpath) + os.system("ls -ltrh moldyn_dbg.pscf") + +def print_dm2(cur,prev,Indices,Istep,text="",Istep_upd=[0,4,9,19],N_uplm=[5,10,15,20],TINY=5.0e-6, + filepath=None): + Ndim=np.shape(cur);Ld=i1prod(Ndim) + lhs=np.ravel( np.array(cur) ) + rhs=np.ravel( np.array(prev)) + le=len(lhs);assert (le==Ld),"ravel:"+str(Ndim)+" >> "+str(np.shape(lhs)) + maxdev=a1maxdiff(lhs,rhs) + sort_diff=( len(Indices)==0 or (Istep in Istep_upd) ) + + if( sort_diff ): + Iupd=0 + for k in range(1,len(Istep_upd)): + if(Istep==Istep_upd[k]): + Iupd=k + arr=[ abs( lhs[k]-rhs[k] ) for k in range(le) ] + ithTOk=np.argsort(arr) + Nadd=0 + for j in range(le): + ith=le-j-1 + ks=ithTOk[ith];val=arr[ks] + if( val < TINY ): + break + if( ks in Indices ): + continue + Indices.append(ks);Nadd+=1; + if(len(Indices)>N_uplm[Iupd]): + break + string="%06d:%14.4e:"%(Istep,maxdev);delimiter='\t ' + idcs=Indices + if( len(Indices)==0 ): + Nprt=min(10,le);idcs=[ k for k in range(Nprt) ] + for I in idcs: + string+="%03d:%12.6f+j%12.6f %12.6f+j%12.6f "%( + I,lhs[I].real,lhs[I].imag, rhs[I].real, rhs[I].imag)+delimiter + printout("#prtDM2:"+text+" "+string,fpath=filepath,Append=True,Threads=[0],stdout=True); + + + + +def sync_dbuf(data,key,root=0,check_diff=None): + from mpi4py import MPI + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + Ld=len(data); + + bfsz=30;assert(Ld<=bfsz),""; + buf=np.zeros([bfsz],dtype=np.float64) + for j in range(Ld): + buf[j]=data[j] + + cpy=None + if(check_diff is not None): + cpy=arrayclone(data) + mpi_Bcast( "sync_dbuf."+key,buf,root=root, barrier=True, iverbose=1, Append=False) + if(check_diff is not None): + if(cpy is not None ): + fnme="checksync_"+key+"_%02d-%02d.dat"%(MPIrank,root); + if( "fnme_format" in check_diff ): + if(check_diff["fnme_format"] is not None): + fnme=check_diff["fnme_format"]%(MPIrank,root) + fd1=open(fnme,'a');string="" + if( "description" in check_diff ): + string=str(check_diff["description"])+":" + str1="";str2="";str3=""; + for k in range(Ld): + str1+="%12.6f "%(cpy[k]) + str2+="%12.6f "%(buf[k]) + str3+="%10.3e "%(abs(buf[k]-cpy[k])) + print(string+" \tLHS:"+str1+ " \tRHS:"+str2+ " \tDIFF:"+str3,file=fd1) + fd1.close() + return np.array( [ buf[k] for k in range(Ld) ] ) + + +def mpidiffs_tostring_(sqrediff,maxabsdiff,At,vals,Datf=False,Legend=False): + retv=None;legend="" + if( not Datf ): + retv="%16.8f %16.6e %10.4f+j%10.4f / %10.4f+j%10.4f at "%(\ + np.sqrt(sqrediff), maxabsdiff,vals[0].real,vals[0].imag,vals[1].real,vals[1].imag)\ + + str(At) + else: + retv="%16.8f %16.6e %10.4f %10.4f %10.4f %10.4f"%(\ + np.sqrt(sqrediff), maxabsdiff,vals[0].real,vals[0].imag,vals[1].real,vals[1].imag) + if( not Legend ): + return retv + else: + legend=( "%16s %16s %21s %21s"%('dist','maxabsdiff','lhs','rhs') if(Datf) else + "%16s %16s %22s / %22s at %s"%('dist','maxabsdiff','lhs','rhs','ijk') ) + return retv,legend + +def sync_threads(md,tddft,mo_coeff,dm2_kOR1,Istep=0,flag=15,check_diff=None,subkey="",flag_details=0): + from mpi4py import MPI + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if( MPIsize < 2 ): + if(Istep==0): + print("#sync_tdWF:no sync"); ### iff MPIsize<2 + return + + if((flag & 1)!=0): + do_sync1(mo_coeff,barrier=True,key="eldyn.step%03d"%(Istep)+subkey+".mo_coeff",root=0, + iverbose=(2 if(Istep<2 or Istep==10 or Istep==50) else 1),check_diff=check_diff,details=( (flag_details%1)!=0 ) ) + if((flag & 2)!=0): + do_sync1(dm2_kOR1,barrier=True,key="eldyn.step%03d"%(Istep)+subkey+".dm2_kOR1",root=0, + iverbose=(2 if(Istep<2) else 0),check_diff=check_diff,details=( (flag_details%2)!=0 ) ) + if((flag & 4)!=0): + do_sync1(md.hcore_last,barrier=True,key="eldyn.step%03d"%(Istep)+subkey+".hc_last",root=0, + iverbose=(2 if(Istep<2) else 0)) + if((flag & 8)!=0): + do_sync1(md.Fock_last,barrier=True,key="eldyn.step%03d"%(Istep)+subkey+".Fock_last",root=0, + iverbose=(2 if(Istep<2) else 0)) + key="eldyn.step%03d.sync_end"%(Istep) + comm_Barrier(key) + +def print_aNbuf(buf,fpath=None,fnme_format=None,fpath_threadlocal=None,Threads=None,Append=False,Nd=8, half=False): + Ndim=np.shape(buf);leNdim=len(Ndim) + dt=(np.array(buf)).dtype + iscmplx=( dt == complex or dt == np.complex128 ) + path,fd,Threads=path_fd_Threads_(fpath=fpath,fnme_format=fnme_format,fpath_threadlocal=fpath_threadlocal, + Threads=Threads,Append=Append) + + def print_a2buf(bfr,Nd,fd_out,is_complx,half=False): + ndim=np.shape(bfr) + nx=min(ndim[0],Nd);ny_0=min(ndim[1],Nd) + for ix in range(nx): + string="" + if(is_complx): + ny=( min(ix+1,ny_0) if(half) else ny_0) + for jy in range(ny): + string+="%10.4f %10.4f "%( bfr[ix][jy].real, bfr[ix][jy].imag ) + else: + ny=( min(ix+1,ny_0) if(half) else ny_0) + for jy in range(ny): + string+="%12.6f "%( bfr[ix][jy] ) + print(string,file=fd_out) + + if( leNdim==2 ): + print_a2buf( buf,Nd,fd, iscmplx) + elif( leNdim==3 ): + n1=min(3,Nd,Ndim[0]) + for I in range(n1): + print(('\n\n\n' if(I>0) else '')+"#%03d "%(I)+str(Ndim),file=fd) + print_a2buf( buf[I],Nd,fd, iscmplx,half=half) + elif( leNdim==4 ): + n1=min(2,Nd,Ndim[0]);n2=min(2,Nd,Ndim[1]);IxJ=-1 + for I in range(n1): + for J in range(n2): + IxJ+=1;print( ('\n\n\n' if(IxJ>0) else '')+"#%03d %d,%d"%(IxJ,I,J)+str(Ndim),file=fd) + print_a2buf( buf[I][J],Nd,fd, iscmplx,half=half) + if(path is not None): + fd.close() +def print_aNbufx2(lhs,rhs,fpath=None,fnme_format=None,fpath_threadlocal=None,Threads=None,Append=False, Nd=5, half=False,description=""): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + Ndim=np.shape(lhs);leNdim=len(Ndim) + sqrediff,maxabsdiff,At,vals=aNdiff(lhs,rhs) + dt=(np.array(lhs)).dtype + iscmplx=( dt == complex or dt == np.complex128 ) + path,fd,Threads=path_fd_Threads_(fpath=fpath,fnme_format=fnme_format,fpath_threadlocal=fpath_threadlocal, + Threads=Threads,Append=Append) + if( MPIrank not in Threads ): + return + + print("#"+description+" dist:%e maxdiff:%e %f+j%f/%f+j%f at "%( + np.sqrt(sqrediff),maxabsdiff,vals[0].real,vals[0].imag, + vals[1].real,vals[1].imag)+str(At),file=fd) + + def print_a2bufx2(lbfr,rbfr,Nd,fd_out,is_complx,half=False,diff=False,description=""): + ndim=np.shape(lbfr) + nx=min(ndim[0],Nd);ny_0=min(ndim[1],Nd) + if(diff): + sqrediff1,maxabsdiff1,At1,vals1=aNdiff(lbfr,rbfr) + print("##"+description+" dist:%e maxdiff:%e %f+j%f/%f+j%f at "%( + np.sqrt(sqrediff1),maxabsdiff1,vals1[0].real,vals1[0].imag, + vals1[1].real,vals1[1].imag)+str(At),file=fd_out) + for ix in range(nx): + string="" + if(is_complx): + ny=( min(ix+1,ny_0) if(half) else ny_0) + for jy in range(ny): + string+="%10.4f %10.4f "%( lbfr[ix][jy].real, lbfr[ix][jy].imag ) + string+=' '*((ny_0-ny)*27) + for jy in range(ny): + string+="%10.4f %10.4f "%( rbfr[ix][jy].real, rbfr[ix][jy].imag ) + string+=' '*((ny_0-ny)*27) + for jy in range(ny): + string+="%9.3e "%( abs(lbfr[ix][jy]-rbfr[ix][jy]) ) + else: + ny=( min(ix+1,ny_0) if(half) else ny_0) + for jy in range(ny): + string+="%12.6f "%( lbfr[ix][jy] ) + string+=' '*((ny_0-ny)*18) + for jy in range(ny): + string+="%12.6f "%( rbfr[ix][jy] ) + string+=' '*((ny_0-ny)*18) + for jy in range(ny): + string+="%9.3e "%( abs(lbfr[ix][jy]-rbfr[ix][jy]) ) + print(string,file=fd_out) + + if( leNdim==2 ): + print_a2bufx2( lhs,rhs,Nd,fd, iscmplx, half=half, diff=False,description="") + elif( leNdim==3 ): + n1=min(3,Nd,Ndim[0]) + for I in range(n1): + string=('\n\n\n' if(I>0) else '')+"#%03d "%(I)+str(Ndim) + print_a2bufx2( lhs[I],rhs[I],Nd,fd, iscmplx,half=half, diff=True,description=string ) + elif( leNdim==4 ): + n1=min(2,Nd,Ndim[0]);n2=min(2,Nd,Ndim[1]);IxJ=-1 + for I in range(n1): + for J in range(n2): + IxJ+=1;description= ('\n\n\n' if(IxJ>0) else '')+"#%03d %d,%d"%(IxJ,I,J)+str(Ndim) + print_a2bufx2( lhs[I][J],rhs[I][J], Nd,fd, iscmplx,half=half, diff=True,description=description) + if( path is not None ): + fd.close() +def i1prod(Iarr): + le=len(Iarr) + if(le==0): + return 1 + else: + ret=Iarr[0] + for k in range(1,le): + ret=ret*Iarr[k] + return ret + +def do_sync1(buffer,barrier=True,key="",root=0,iverbose=3, check_diff=None, details=False): + from mpi4py import MPI + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + + if( isinstance(buffer,np.ndarray) ): + bcast_ndarray(buffer,barrier=barrier,key=key,root=root,iverbose=iverbose, check_diff=check_diff,details=details) + else: + le=len(buffer) + if( isinstance( buffer[0],np.ndarray) ): + for I in range(le): + bcast_ndarray( buffer[I],barrier=( barrier and I==0 ),key=key+"[%02d]"%(I), + root=root,iverbose=(iverbose if(I==0) else iverbose-1), check_diff=check_diff,details=details ) + else: + for I in range(le): + buffer[I]=np.array(buffer[I]) + bcast_ndarray( buffer[I],barrier=( barrier and I==0 ),key=key+"[%02d]"%(I), + root=root,iverbose=(iverbose if(I==0) else iverbose-1), check_diff=check_diff,details=details ) +def path_fd_Threads_(fpath=None,fnme_format=None,fpath_threadlocal=None,Threads=None,Append=False): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + fd=None;path=None; + if(fpath is None): + path_threadlocal=None; + if(fpath_threadlocal is not None): + path_threadlocal=fpath_threadlocal; + elif( fnme_format is not None ): + path_threadlocal=fnme_format%(MPIrank) + + if( path_threadlocal is not None ): + if(Threads is None): + Threads=[ j for j in range(MPIsize) ] + fd=open(path_threadlocal,('a' if(Append) else 'w')) + return path_threadlocal,fd,Threads + else: + if(Threads is None): + Threads=[0] + fd=sys.stdout + return None,fd,Threads + else: + if(Threads is None): + Threads=[0] + fd=open(fpath,('a' if(Append) else 'w')) + return fpath,fd,Threads +def np_ravel(src): + return np.ravel(np.array(src)) +def bcast_ndarray(buf,barrier=True,key="",root=0,iverbose=3,check_diff=None,details=False): + from mpi4py import MPI + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + + if( not MPIutils01.Multithreading() ): + MPIutils01.DebugLog("!W:MPI is off:eldyn.bcast_ndarray") + assert False,"" + + string = "#eldyn.comm_Bcast:%02d:"%(MPIrank)+str(key)+"....."+\ + " \t\t"+str(np.shape(buf))+" "+str( (np.array(buf)).dtype ) + fnme_format='mpi_Bcast_%02d.log' + Append = True; flush=True ## XXX XXX + printout(string,fnme_format=fnme_format,Type='mpi',Append=Append,flush=flush, dtme=True, stdout=(iverbose>1) ) + + cpy=None + if( (check_diff is not None) and (MPIrank != root) ): + cpy=arrayclone(buf) + + if( barrier ): + comm_Barrier(key,iverbose=iverbose) + + + ## strlog="#do_sync:%s:%02d:shape:"+str(np.shape(buf)) + ## if( iverbose > 1 ): + ## printout(strlog+" start... \t\t "+str(datetime.datetime.now()),flush=(iverbose>2)) + comm.Bcast(buf,root=root) + + if( (check_diff is not None) and (MPIrank != root) ): + if( cpy is not None ): + sqrediff,maxabsdiff,At,vals=aNdiff(buf,cpy) + fnme="checksync_"+key+"_%02d-%02d.dat"%(MPIrank,root); + if( "fnme_format" in check_diff ): + if(check_diff["fnme_format"] is not None): + fnme=check_diff["fnme_format"]%(MPIrank,root) + + fd1=open(fnme,'a');header="" + if( "description" in check_diff ): + header=check_diff["description"]+":" + print( header+"%16.8f %16.6e (%s/%s) at "%(sqrediff,maxabsdiff,str(vals[0]),str(vals[1]))+str(At),file=fd1) + fd1.close(); + if(details): + fnme2="checksync_"+key+"_%02d-%02d_details.dat"%(MPIrank,root) + print_aNbufx2(cpy,buf,fpath=fnme2, Threads=[MPIrank],Append=False, Nd=5, half=False,description="") + cpy=None + + string="#eldyn.comm_Bcast:%02d:done"%(MPIrank)+str(key)+" done " + printout(string,fnme_format=fnme_format,Type='mpi',Append=Append,flush=flush, dtme=True, stdout=(iverbose>1) ) + + ## if( iverbose > 1 ): + ## printout(strlog+" done \t\t "+str(datetime.datetime.now()),flush=(iverbose>2)) +def comm_Barrier(key="",iverbose=3): + mpi_Barrier(("eldyn_comm_Barrier" if(key=="") else key)) + +def Magnus_AOrep(Ssqrt,Sinvrt,Ld,H2,H1,dt,C_in): + ## Magnus propagator : Heff = 0.5( H(t1) + H(t2) )+ (np.sqrt(3)/12)dt + # if( "propagator" in rttddft_common.params ): + # assert rttddft_common.params["propagator"]=="Magnus","" + + ret= np.matmul( Sinvrt, Magnus_step(Ld, np.matmul( Sinvrt, np.matmul(H2, Sinvrt) ), + np.matmul( Sinvrt, np.matmul(H1, Sinvrt) ),dt, np.matmul(Ssqrt,C_in) ) ) + + return ret +def Magnus_step(Ld,H2,H1,dt,C_in): + sqrt3_over6=0.28867513459481288225457439025098 + sqrt3_over12=0.14433756729740644112728719512549 + DH=H2-H1 + Ndim=np.shape(C_in);nAO=Ndim[0];nMO=Ndim[1] + fac1=0.5 - sqrt3_over6; H_t1=H1 + DH*fac1 + fac2=0.5 + sqrt3_over6; H_t2=H1 + DH*fac2 + Heff=np.zeros( [ Ld, Ld], dtype=np.complex128 ) + fac=0.0 + Heff= 0.50*( H_t1 + H_t2 ) -1j*dt*sqrt3_over12*( np.matmul(H_t2,H_t1) - np.matmul(H_t1,H_t2) ) + + ### print("Magnus_commutator:",end="");print( dt*sqrt3_over12*( np.matmul(H_t2,H_t1) - np.matmul(H_t1,H_t2) ) ) + ### print("Magnus_FULL",end="");print( 0.50*( H_t1 + H_t2 ) -1j*dt*sqrt3_over12*( np.matmul(H_t2,H_t1) - np.matmul(H_t1,H_t2) )) + ### print("Magnus_Heff",end="");print(Heff) + eng,vecs=np.linalg.eig(Heff) + ### print(np.array(eng).dtype);assert False,"" + expfacs=np.zeros([Ld],np.complex128) + for j in range(Ld): + arg=eng[j].real*dt; expfacs[j]=math.cos(arg) - 1j*math.sin(arg) + U=np.zeros( [Ld,Ld], np.complex128 ) + for ia in range(Ld): + for jm in range(Ld): + cum=0.0 + for k in range(Ld): + cum+= vecs[ia][k] * expfacs[k]* np.conj( vecs[jm][k] ) + U[ia][jm]=cum + ### print("Magnus_propagation:%f+j%f ..."%(C_in[0][0].real,C_in[0][0].imag)); + ret=np.matmul( U, C_in ) + ### print("Magnus_propagation:%f+j%f ..."%(ret[0][0].real,ret[0][0].imag)); + return ret diff --git a/pyscf/rttddft/filter_by_exponent.py b/pyscf/rttddft/filter_by_exponent.py new file mode 100644 index 000000000..74a3e99e1 --- /dev/null +++ b/pyscf/rttddft/filter_by_exponent.py @@ -0,0 +1,176 @@ +import numpy as np +import os +import math +#shell_info_A[0] [0, [18.121074109, -0.1275232222, -0.0248047945, 0.0, 0.0], +# [7.37750664, -0.0812376594, -0.0171596817, 0.0, 0.0], +# [2.8817585986, 0.3277442268, 0.0724090847, 0.0, 0.0], +# [1.0990235357, 0.5946658147, 0.1739886836, 0.0, 0.0], +# [0.400738772, 0.2436047977, 0.1404493622, 0.0, 0.0], +# [0.091685942, -0.0017574619, -0.3860533721, 1.0, 0.0], +# [0.0309750158, 0.0016745741, -0.736061992, 0.0, 1.0]] , +# [1] [1, [18.121074109, 0.0729874345, 0.0, 0.0], +# [7.37750664, 0.199671759, 0.0, 0.0], +# [2.8817585986, 0.3527504683, 0.0, 0.0], +# [1.0990235357, 0.3936231447, 0.0, 0.0], +# [0.400738772, 0.2171401481, 0.0, 0.0], [0.091685942, 0.0205070521, 1.0, 0.0], [0.0309750158, -0.0045593404, 0.0, 1.0]], [2, [0.0973, 1.0]]] +# org[A] = shell_info[ 0:nSh[A] ] +# shell_info[jsh] = [ ell_jsh, rows[0:nPGTO[elmt,jsh]] +# rows[kPGTO]=[ alph, cof_0, cof_1, ... ] +def print_bset(org,exp_to_discard=None,comment=""): + TINY=1.0e-30 + if( exp_to_discard is None ): + exp_to_discard=-1.0 + ret="" + for A in org: + shell_info_A=org[A]; + nSh_A = len(shell_info_A) + ret+=A+":nSh_A=%d\n"%(nSh_A) + shell_info_A_nw=[]; nSh_A_removed=0 + for jSh_A in range(nSh_A): + ell=int( shell_info_A[jSh_A][0] ) + alph_cofs = shell_info_A[jSh_A][1:] + ### o.k. print("alph_cofs:"+str(np.shape(alph_cofs))+":"+str(alph_cofs)) + + nPGTO=len(alph_cofs) + row_0=alph_cofs[0]; + ncols=len(row_0)-1; + alph=[ alph_cofs[kpgto][0] for kpgto in range(nPGTO) ] + ncols_nw=0;jcol_remov=[] + for jcol in range(ncols): + cofs=[ alph_cofs[kpgto][1+jcol] for kpgto in range(nPGTO) ] + cofs_nw=[];sqrsum=0.0 + for kpgto in range(nPGTO): + if( alph[kpgto] >= exp_to_discard ): + cofs_nw.append(cofs[kpgto]);sqrsum+=cofs[kpgto]**2 + sqrtnorm=np.sqrt(sqrsum); + if(sqrtnorm>TINY): + ncols_nw+=1 + else: + jcol_remov.append(jcol) + + strbuf=[" %2d %11.4e %2s "%( kpgto,alph_cofs[kpgto][0],\ + ("" if(alph_cofs[kpgto][0]>=exp_to_discard) else "***") ) for kpgto in range(nPGTO)] + + for kpgto in range(nPGTO): + for jcol in range(ncols): + strbuf[kpgto]+="%12.6f%1s "%(alph_cofs[kpgto][1+jcol],("x" if(jcol in jcol_remov) else "")) + for line in strbuf: + ret+="\n"+line + ret+="\n"; + print("#print_bset:"+comment) + print("#print_bset:"+ret) + +def filter_by_exponent(org,exp_to_discard): + TINY=1.0e-30 + ret={} + for A in org: + shell_info_A=org[A]; + ### print("#shell_info_%s:"%(A)+str(shell_info_A)) + ### print("#shell_info_%s:"%(A)+str(np.shape(shell_info_A))) + nSh_A = len(shell_info_A) + shell_info_A_nw=[]; nSh_A_removed=0 + for jSh_A in range(nSh_A): + ell=int( shell_info_A[jSh_A][0] ) + alph_cofs = shell_info_A[jSh_A][1:] + ### print("alph_cofs:"+str(np.shape(alph_cofs))+":"+str(alph_cofs)) + nPGTO=len(alph_cofs) + row_0=alph_cofs[0]; + ncols=len(row_0)-1; + alph_cofs_nw=[]; ncols_nw=0 + # i. find cols to discard ... + alph=[ alph_cofs[kpgto][0] for kpgto in range(nPGTO) ] + #if( min(alph)>=exp_to_discard ): + # ncols_nw=ncols; + # alph_cofs_nw=[] + # for kpgto in range(nPGTO): + # alph_cofs_nw.append([ alph_cofs[kpgto][0], + # [ alph_cofs[kpgto][1+jcol] for jcol in range(ncols) ]]) + #else: + jcol_remov=[] + for jcol in range(ncols): + cofs=[ alph_cofs[kpgto][1+jcol] for kpgto in range(nPGTO) ] + cofs_nw=[];sqrsum=0.0 + for kpgto in range(nPGTO): + if( alph[kpgto] >= exp_to_discard ): + cofs_nw.append(cofs[kpgto]);sqrsum+=cofs[kpgto]**2 + sqrtnorm=np.sqrt(sqrsum); + if(sqrtnorm>TINY): + ncols_nw+=1 + else: + jcol_remov.append(jcol) + if(ncols_nw<1): + print("#filter_by_exponent:dropping block %s.%d:"%(A,jSh_A) +str(alph)) + assert max(alph)=TOL): + print("#a1eqb:%f/%f %e"%(lhs,rhs,abs(lhs-rhs))); + return False + elif( isinstance(lhs,int) ): + if( lhs!=rhs ): + return False + elif( isinstance(lhs,list) ): + if( not a1eqb(lhs,rhs,TOL=TOL) ): + return False + return True + else: + print("#shape differs:%d/%d"%(lea,len(b)));return False + else: + print("#Shape differs:"+str(np.shape(A))+" / "+str(np.shape(B)));return False diff --git a/pyscf/rttddft/futils.py b/pyscf/rttddft/futils.py new file mode 100644 index 000000000..1de5b150b --- /dev/null +++ b/pyscf/rttddft/futils.py @@ -0,0 +1,51 @@ +import os +import sys +from mpi4py import MPI + +class futils: + _Buffer=[] + @staticmethod + def fopen_00(file,mode='r',buffering=-1,encoding=None,errors=None,newline=None,closefd=True,opener=None,default=None): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if(MPIrank!=0): + if(default is None): + return None + elif(isinstance(default,str) and default == "dummy"): + return open("dummy.log",mode) + else: + return default; + return futils.fopen(file,mode=mode,buffering=buffering,encoding=encoding,errors=errors,newline=newline,closefd=closefd,opener=opener) + @staticmethod + def fclose_00(fd): + if( fd is None ): + return + elif( fd == sys.stdout ): + return + else: + fd.close();return + + @staticmethod + def fopen(file,mode='r',buffering=-1,encoding=None,errors=None,newline=None,closefd=True,opener=None): + fd=open(file,mode=mode,buffering=buffering,encoding=encoding,errors=errors,newline=newline,closefd=closefd,opener=opener); + futils._Buffer.append(file); + futils.prtoutifnecs() + return fd + @staticmethod + def prtoutifnecs(): + if( os.path.exists("futils.in") ): + print("#prtoutifncs:%d"%( len(futils._Buffer) )+str(futils._Buffer)) + + @staticmethod + def fclose(fd): + n=len(futils._Buffer) + ok=False + for j in range(n): + if( fd.name==futils._Buffer[j] ): + futils._Buffer.pop(j);ok=True;break + if( not ok ): + print("!E missing file:"+fd.name+" in list:"+str(futils._Buffer)); + n=len(futils._Buffer) + ## if( n>2 ): + ## print("check Buffer:len=%d "%(n)+ str(futils._Buffer)) + fd.close() + futils.prtoutifnecs() diff --git a/pyscf/rttddft/gto_ps_pp_int01.py b/pyscf/rttddft/gto_ps_pp_int01.py new file mode 100644 index 000000000..298e96a1e --- /dev/null +++ b/pyscf/rttddft/gto_ps_pp_int01.py @@ -0,0 +1,2200 @@ +#!/usr/bin/env python +# revision of pbc/gto/pseudo/pp_int.py +# +# Copyright 2014-2018 The PySCF Developers. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Author: Qiming Sun +# + +'''Analytic PP integrals. See also pyscf/pbc/gto/pesudo/pp.py + +For GTH/HGH PPs, see: + Goedecker, Teter, Hutter, PRB 54, 1703 (1996) + Hartwigsen, Goedecker, and Hutter, PRB 58, 3641 (1998) +''' + +import ctypes +import pathlib +import copy +import numpy +import os +import sys +import math +import scipy.special +from pyscf import lib +from pyscf import gto +import pathlib +from .filter_by_exponent import filter_by_exponent +from .futils import futils +from pyscf.pbc.gto.pseudo.pp_int import fake_cell_vnl, _int_vnl +from pyscf.pbc.df.aft import _get_pp_loc_part1 as get_pp_loc_part1 +from .utils import write_filex,update_dict,printout_dict,readwrite_xbuf,arrayclone,print_a2maxdiff,aNmaxdiff,print_Hmatrices,atomicsymbol_to_atomicnumber,parse_xyzstring,write_file,i1eqb,list_to_a1,gamma_hfint,atomicnumber_to_atomicsymbol +from pyscf.gto.mole import format_basis +import ctypes +from .rttddft_common import rttddft_common +from pyscf.pbc.gto.pseudo.pp_int import get_pp_nl +from pyscf.pbc.gto import pseudo +from numpy.ctypeslib import ndpointer +from .Logger import Logger +from .physicalconstants import physicalconstants +from .Loglv import printout +from mpi4py import MPI +from .mpiutils import mpi_Bcast +from .heapcheck import heapcheck +from .MPIutils01 import MPIutils01 +import datetime +libpbc = lib.load_library('libpbc') + +def suppress_prtout(): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); + return ( MPIrank!=0 ) + + +def fprintf(fpath,text,Append=False,Threads=[0],flush=False,stdout=False,dtme=True): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank();MPIsize=comm.Get_size() + if( MPIsize>1 and (MPIrank not in Threads) ): + return + fd=open(fpath,('a' if(Append) else 'w')) + if( dtme ): + text=text+" \t\t"+str(datetime.datetime.now()) + print(text,file=fd);fd.close() + if(stdout): + printout(text) +def print_kvectors(kvectors,BravaisVectors,fpath=None,Append=False): + PIx2=6.283185307179586476925286766559; + if( suppress_prtout() ): + return + fd=sys.stdout; + if(fpath is not None ): + fd=open(fpath,('a' if(Append) else 'w')) + ## B=numpy.transpose( numpy.linalg.inv(BravaisVectors) )*PIx2 + ## for I in range(3): + ## print("#check_BdotA:"+str( [ numpy.vdot(B[I],BravaisVectors[J]) for J in range(3) ] )) + Nv=len(kvectors) + print("#print_kvectors: Kx,Ky,Kz projection_to_Gvectors",file=fd); ## rank=0 only + for I in range(Nv): + print(" %03d: %9.4f %9.4f %9.4f %9.4f %9.4f %9.4f"%(I, kvectors[I][0],kvectors[I][1],kvectors[I][2], + numpy.vdot(kvectors[I],BravaisVectors[0])/PIx2, numpy.vdot(kvectors[I],BravaisVectors[1])/PIx2, + numpy.vdot(kvectors[I],BravaisVectors[2])/PIx2),file=fd ) ## rank=0 only + if( fpath is not None ): + fd.close() +def absmax_imaginary_part(zbuf): + buf=numpy.ravel( numpy.array(zbuf) ) + le=len(buf) + if(le<1): + return 0 + I=0; maxv=abs( buf[I].imag );at=I + for I in range(1,le): + dum=abs( buf[I].imag ) + if(dum>maxv): + maxv=dum;at=I + return maxv +def modify_normalization(zbuf,nCGTO_2A,nKpoints,nCGTO_1,n_cols, IZnuc_B,distinct_IZnuc,ell_B,alpha_B,Nsh): + # Input: zbuf[3][nKpoints][nCGTO_2A[:]][nCGTO_1] + # fix normalization + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); + Nat=len(IZnuc_B) + nDa=len(distinct_IZnuc) + info=[] + norb_AL=[0,0,0] + nAO=0 + for Iat in range(Nat): + IZ=IZnuc_B[Iat] + for iDa in range(nDa): + if(distinct_IZnuc[iDa]==IZ): + break + assert (distinct_IZnuc[iDa]==IZ),"" + offset=0 + for jda in range(iDa): + offset+=Nsh[jda] + for ksh in range(Nsh[iDa]): + el=ell_B[offset+ksh] + alph=alpha_B[offset+ksh] + rLsqr=0.5/alph + norb=2*el+1 + + for m in range(-el,el+1): + info.append({"indx":"%d.%d.%d"%(Iat,iDa,ksh),"alph":alph,"l":el,"m":m,"n_cols":n_cols[offset+ksh]}) + ## + ## we now fix normalization... + ## + norb_AL[0]+=norb + for Icol in range(1,3): + if( nCGTO_2A[Icol]<1 ): + continue ## skip as if there is no input +# +# I normalized p^{l}_n by 1.0/[ sqrt(0.5 Gamma( (2l+4I+3)/2 )) * rL**(l+(4I+3)/2) ] +# but here pySCF expects it to be normalized by I=0 value +# so I multiply with sqrt( Gamma( (2l+4I+3)/2 )/Gamma( (2l+3)/2 ) )* rL**2I + if( Icol< n_cols[offset+ksh]): ## 1 < 2 etc. + fac=math.sqrt( gamma_hfint( 2*el+4*Icol+3 )/gamma_hfint( 2*el + 3) )*(rLsqr**Icol) + printout("#zbuf_%d:"%(Icol)+str(numpy.shape(zbuf[Icol]))) + printout("#iorb [%d:%d+%d) / %d:"%(norb_AL[Icol], norb_AL[Icol], norb, nCGTO_2A[Icol])) + for kp in range(nKpoints): + for kAO in range(norb): + for mu1 in range(nCGTO_1): + ### printout("%d %d %d %d"%(Icol,kp,norb_AL[Icol]+kAO,mu1),flush=True) + zbuf[Icol][kp][ norb_AL[Icol]+kAO ][mu1]*=fac + norb_AL[Icol] +=norb + ### fd=futils.fopen("modify_nrmz.log","w") ## fd.close @line 96 + fpath1="modify_nrmz.log"; ## fd.close @line 96 + printout(info,fpath=fpath1,Threads=[0],Append=False);### futils.fclose(fd); + + ### print("norb_AL_%02d:"%(MPIrank)+str(norb_AL)) + ### print("nCGTO_2A_%02d:"%(MPIrank)+str(nCGTO_2A)) + assert ( norb_AL[0]==nCGTO_2A[0] and norb_AL[1]==nCGTO_2A[1] and + ( norb_AL[2]==0 or norb_AL[2]==nCGTO_2A[2])),"norb_AL:"+str(norb_AL) + return zbuf + +def count_nCGTO(IZnuc,distinct_IZnuc,Nsh,ell,n_cols=None,title=None,verbose=0): + # Nshell[iDa] + # Ell[iDa][jsh] + if( verbose > 0 ): + printout("#count_nCGTO:INPUT:Nsh="+str(Nsh)+" for distinct_IZnuc:"+str(distinct_IZnuc)) + retv=0 + nDa=len(distinct_IZnuc) + Ell=[] + ixj=0 + ## Ell[ nDA ][ Nsh[*] ] + for iDa in range(nDa): + el_1=numpy.zeros([Nsh[iDa]],dtype=int) + for ksh in range(Nsh[iDa]): + el_1[ksh]=ell[ ixj + ksh ] + ixj+=Nsh[iDa] + + Ell.append( el_1 ) + + ret_Array=None + info=[]; + NshSUM=0 + Nat=len(IZnuc) + for iat in range(Nat): + IZ=IZnuc[iat] + for iDa in range(nDa): + if(IZ==distinct_IZnuc[iDa]): + break + assert (iDa1 ... + if(nco[kk]>Ico): + ret_Array[Ico]+=(2*Ell[iDa][kk]+1) + + NshSUM+=Nsh[iDa] + retv+=nOrb + ### printout("#Count_nCGTO:iat=%d iDa=%d nOrb=%d %d"%(iat,iDa,nOrb,retv)); + if( title is not None): + printout("#Count_nCGTO:shell_info:"+str(title)+":"+str(info)) + ### if( n_cols is not None): + ### le=len(n_cols) + ### assert (le==NshSUM),"len:%d / NshSUM:%d"%(le,NshSUM) + if(ret_Array is not None): + assert retv==ret_Array[0],"%d/%d"%(retv,ret_Array[0]) + if(n_cols is None): + return retv + else: + return ret_Array +def print_bset(IZnuc,distinct_IZnuc,Nsh,ell): + Nat=len(IZnuc) + Nsh_sum=sum(Nsh) + printout("#IZnuc:%d"%(len(IZnuc))) + +def gen_bset_info(cell,IZnuc): + ## generalization of format_basis({'Ti':'sto-3g','O':'sto-3g'}) .. + Nat=len(IZnuc) + if( isinstance(cell.basis,str) ): + dict={} + for iat in range(Nat): + Z=IZnuc[iat] + Sy=atomicnumber_to_atomicsymbol(Z) + dict.update({Sy:cell.basis}) + ### printout("gen_bset_info:INPUT:",end="");printout(dict) + ret=format_basis(dict) + ### printout("gen_bset_info:OUTPUT:",end="");printout(ret) + return ret + elif( isinstance(cell.basis,dict) ): + ### print("gen_bset_info:INPUT:",end="");print(cell.basis) + ret=format_basis(cell.basis) + ### print("gen_bset_info:OUTPUT:",end="");print(ret) + return ret + else: + assert False,"check cell.basis and its type.."+str(type(cell.basis))+" "+str(cell.basis) + return None + +# alph,cofs,Ell,distinct_IZnuc,Nsh,Npgto,Npgto_sum,Nsh_sum=reorg_bset_infox(cell,Sy) +def reorg_bset_infox(cell,Sy): + Nat=len(Sy) + IZnuc=[]; + for i in range(Nat): + IZnuc.append( atomicsymbol_to_atomicnumber( Sy[i] ) ) + bset_info=gen_bset_info(cell,IZnuc) + + if( cell.exp_to_discard is not None ): + filtered =filter_by_exponent(bset_info, cell.exp_to_discard ) + bset_info=filtered + + return reorg_bset_info(bset_info) +# alph,cofs,Ell,distinct_IZnuc,Nsh,Npgto,Npgto_sum,Nsh_sum=reorg_bset_info(bset_info) +# nDa:=len(distinct_IZnuc) +# Nsh [ nDa ] # of shell for each atom +# Ell [ sum(Nsh[:]) ] +# Npgto[ sum(Nsh[:]) ] +def reorg_bset_info(bset_info): + distinct_IZnuc=[] + nDa=len(bset_info) + alph=[];cofs=[]; + Nsh=[]; Npgto_sum=0 + Npgto=[] + Ell=[] + for A in bset_info: + infoA=bset_info[A]; + nsh1=len(infoA) + + distinct_IZnuc.append( atomicsymbol_to_atomicnumber(A) ) + for jsh in range(nsh1): + shell=infoA[jsh] + el=shell[0]; Ell.append(el); + npgto=0; alpha_col2=None; cofs_col2=None; alpha_col3=None; cofs_col3=None + alpha_col4=None; cofs_col4=None; alpha_col5=None; cofs_col5=None; alpha_col6=None; cofs_col6=None + alpha_col7=None; cofs_col7=None; alpha_col8=None; cofs_col8=None + for j in range(1,len(shell)): + row=shell[j] + alph.append(row[0]);cofs.append(row[1]);npgto+=1 + if(len(row)>2): + if(len(row)>=3): + if( alpha_col2 is None): + alpha_col2=[]; cofs_col2=[] + alpha_col2.append(row[0]);cofs_col2.append(row[2]); + if(len(row)>=4): + if( alpha_col3 is None): + alpha_col3=[]; cofs_col3=[] + alpha_col3.append(row[0]);cofs_col3.append(row[3]); + if(len(row)>=5): + if( alpha_col4 is None): + alpha_col4=[]; cofs_col4=[] + alpha_col4.append(row[0]);cofs_col4.append(row[4]); + if(len(row)>=6): + if( alpha_col5 is None): + alpha_col5=[]; cofs_col5=[] + alpha_col5.append(row[0]);cofs_col5.append(row[5]); + if(len(row)>=7): + if( alpha_col6 is None): + alpha_col6=[]; cofs_col6=[] + alpha_col6.append(row[0]);cofs_col6.append(row[6]); + if(len(row)>=8): + if( alpha_col7 is None): + alpha_col7=[]; cofs_col7=[] + alpha_col7.append(row[0]);cofs_col7.append(row[7]); + if(len(row)>=9): + if( alpha_col8 is None): + alpha_col8=[]; cofs_col8=[] + alpha_col8.append(row[0]);cofs_col8.append(row[8]); + if(len(row)>=10): + assert False,"unimplemnted" + + Npgto.append(npgto); Npgto_sum+=npgto + if( alpha_col2 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_2=len(alpha_col2) + Npgto.append(npgto_2) + for k in range(npgto_2): + ### print("#adding to alph:%d %f"%(k,alpha_col2[k])) + alph.append( alpha_col2[k] ) + cofs.append( cofs_col2[k] ) + nsh1+=1; Npgto_sum+=npgto_2 + if( alpha_col3 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_3=len(alpha_col3) + Npgto.append(npgto_3) + for k in range(npgto_3): + alph.append( alpha_col3[k] ) + cofs.append( cofs_col3[k] ) + nsh1+=1; Npgto_sum+=npgto_3 + + if( alpha_col4 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_4=len(alpha_col4) + Npgto.append(npgto_4) + for k in range(npgto_4): + alph.append( alpha_col4[k] ) + cofs.append( cofs_col4[k] ) + nsh1+=1; Npgto_sum+=npgto_4 + if( alpha_col5 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_5=len(alpha_col5) + Npgto.append(npgto_5) + for k in range(npgto_5): + alph.append( alpha_col5[k] ) + cofs.append( cofs_col5[k] ) + nsh1+=1; Npgto_sum+=npgto_5 + if( alpha_col6 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_6=len(alpha_col6) + Npgto.append(npgto_6) + for k in range(npgto_6): + alph.append( alpha_col6[k] ) + cofs.append( cofs_col6[k] ) + nsh1+=1; Npgto_sum+=npgto_6 + if( alpha_col7 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_7=len(alpha_col7) + Npgto.append(npgto_7) + for k in range(npgto_7): + alph.append( alpha_col7[k] ) + cofs.append( cofs_col7[k] ) + nsh1+=1; Npgto_sum+=npgto_7 + if( alpha_col8 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_8=len(alpha_col8) + Npgto.append(npgto_8) + for k in range(npgto_8): + alph.append( alpha_col8[k] ) + cofs.append( cofs_col8[k] ) + nsh1+=1; Npgto_sum+=npgto_8 + Nsh.append(nsh1); + Nsh_sum=sum(Nsh) + return alph,cofs,Ell,distinct_IZnuc,Nsh,Npgto,Npgto_sum,Nsh_sum + +# retv[0] [ nKpoints ][ nCGTO_2A[0] ][ nCGTO_1 ] +# retv[1] [ nKpoints ][ nCGTO_2A[1] ][ nCGTO_1 ] *** truncated if nCGTO_2A[1]==0 *** +# retv[2] [ nKpoints ][ nCGTO_2A[1] ][ nCGTO_1 ] +def calc_pp_overlaps(cell,A_over_c,kpts, singlethread=None,dbgng=False,Zbuf_Refr=None): + import math + import time + comm=MPI.COMM_WORLD + kvectors=numpy.reshape(kpts,(-1,3)) + nKpoints=len(kvectors) + MPIrank=comm.Get_rank();MPIsize=comm.Get_size() + Rnuc_au,Sy=parse_xyzstring(cell.atom,unit_BorA='B') + Nat_too_small=3 + Nat=len(Sy) + dbgng_mpi=False + if( singlethread is None ): + singlethread = ( MPIsize < 2 or Nat <= Nat_too_small ) + if( MPIsize < 2 ): + singlethread = True + + if( not MPIutils01.Multithreading() ): + MPIutils01.DebugTrace("calc_pp_overlaps","#calc_pp_overlaps:singlethread"); + singlethread = True + + fncnme="calc_pp_overlaps";fncdepth=4 ## XXX XXX fncdepth ~ SCF:0 vhf:1 get_j:2 + Wctm000=time.perf_counter();Wctm010=Wctm000;N_call=rttddft_common.Countup(fncnme);dic1_timing={} ## XXX XXX + Dic_timing=rttddft_common.Dict_getv('timing_'+fncnme, default=None) ## XXX XXX + if( Dic_timing is None ): + rttddft_common.Dict_setv('timing_'+fncnme, {}); + Dic_timing=rttddft_common.Dict_getv('timing_'+fncnme, default=None) + f_write("calc_pp_overlaps_DBGNG.log",Append=True,msg="calc_pp_overlaps Nat:%d "%(len(Sy))+str(Sy)) + if( singlethread ): + ### printout("calling calc_pp_overlaps1... %r"%(dbgng),fpath="gto_ps_pp_int01_py.log",Threads=[0],Append=True) + retv=calc_pp_overlaps1(cell, A_over_c, kpts, Rnuc_au, Sy, Rnuc_au, Sy, dbgng=dbgng, Zbuf_Refr=Zbuf_Refr) + ### printout("calling calc_pp_overlaps1... returns",fpath="gto_ps_pp_int01_py.log",Threads=[0],Append=True) + Wctm020=Wctm010;Wctm010=time.perf_counter() # XXX XXX + update_dict(fncnme,dic1_timing,Dic_timing,"singlethread",Wctm010-Wctm020,depth=fncdepth) # XXX XXX + Wctm010=time.perf_counter() # XXX XXX + printout_dict(fncnme,dic1_timing,Dic_timing,Wctm010-Wctm000,depth=fncdepth) # XXX XXX + return retv + + ## divide task over threads... + ## Here I take the SIMPLEST strategy, which is not necessarily optimal + ## better choice is to evenly distribute task taking account of N_shells/N_pgtos of each atom.. + ## but in such case you have to broadcast matrix dimension etc. + ## NOTE we here assume (i) numpy.shape( ppnl_half_sub ) [0] and [1] are the same + ## (ii) numpy.shape( ppnl_half_sub ) [2] is largest + Nat_per_thread=int( math.ceil( Nat / float(MPIsize) ) ) + iatSTT= min( MPIrank*Nat_per_thread, Nat) + iatUPL= min( (MPIrank+1)*Nat_per_thread, Nat) + + f_write("calc_pp_overlaps_DBGNG.log",Append=True,msg="calc_pp_overlaps iatSTT:%d %d "%(iatSTT,iatUPL),Threads=None) + ppnl_half_sub=None; le_ppnl_half_sub=0 + if( iatSTT < iatUPL ): + Rnuc_sub=Rnuc_au[iatSTT:iatUPL] + Sy_sub=Sy[iatSTT:iatUPL] + ## [3][ nKpoints ][ n + ppnl_half_sub=calc_pp_overlaps1(cell, A_over_c, kpts, Rnuc_sub, Sy_sub, Rnuc_au, Sy, dbgng=dbgng ) + le_ppnl_half_sub = len( ppnl_half_sub ) + ### if( dbgng_mpi ): + ### mpi_prtout_zbuf("ppnl_half_sub%02d.dat",ppnl_half_sub, + ### description="Nat:%d:%d"%(iatSTT,iatUPL)+str(Rnuc_sub),Append=False) + Wctm020=Wctm010;Wctm010=time.perf_counter() # XXX XXX + update_dict(fncnme,dic1_timing,Dic_timing,"multithread_ppnl",Wctm010-Wctm020,depth=fncdepth) # XXX XXX + + IZnuc=[ atomicsymbol_to_atomicnumber( Sy[i] ) for i in range(Nat) ] + alph,cofs,Ell,distinct_IZnuc,Nsh,Npgto,Npgto_sum,Nsh_sum=reorg_bset_infox(cell,Sy) + + ## METADATA : nCGTO1 + nCGTO1_A=[] + for r in range(MPIsize): + iatSTT= min( r*Nat_per_thread, Nat) + iatUPL= min( (r+1)*Nat_per_thread, Nat) + if( iatSTT < iatUPL ): + IZnuc_sub=IZnuc[iatSTT:iatUPL] + ## this applies IZnuc_sub + ncgto=count_nCGTO(IZnuc_sub,distinct_IZnuc,Nsh,Ell) + nCGTO1_A.append(ncgto) + else: + nCGTO1_A.append(0) + + nCGTO1_sum=sum(nCGTO1_A) + + ## METADATA : nCGTO2 + nCGTO2_A=numpy.zeros([3], dtype='i') + + for Icol in range(3): + if( (ppnl_half_sub is None) or (Icol >=le_ppnl_half_sub) ): + nCGTO2_A[Icol]=0 + else: + ndim=numpy.shape( ppnl_half_sub[Icol] ) + nCGTO2_A[Icol]=ndim[1] ## [0]:nKpoints [1]:nCGTO2 [2]:nCGTO1 + if( MPIrank == 0 ): + for Icol in range(len(ppnl_half_sub)): + print("#00:numpy.shape(ppnl_half_sub[Icol=%d])"%(Icol)\ + +str(numpy.shape(ppnl_half_sub[Icol])) ) + print("#%02d:nCGTO2_A:"%(MPIrank)+str(nCGTO2_A)) + print("#%02d:nCGTO1_A:"%(MPIrank)+str(nCGTO1_A)) + mpi_Bcast("calc_pp_overlaps.nCGTO2",nCGTO2_A,root=0) + + ## final buffer + ppnl_half=[] + for Icol in range(3): + if( nCGTO2_A[Icol] < 1 ): + continue + zbuf1=numpy.zeros( [ nKpoints, nCGTO2_A[Icol],nCGTO1_sum ],dtype=numpy.complex128) + ioff=0 + for r in range(MPIsize): + if( nCGTO1_A[r] < 1 ): + continue + iupl=ioff + nCGTO1_A[r] + if(r==0): + if(MPIrank==0): + zbuf1[:,:, ioff:iupl]=ppnl_half_sub[Icol][:,:,0:nCGTO1_A[r]] + ### mpi_prtout_zbuf("zbuf1_%d_0"%(Icol)+"_%02d",zbuf1[:,:, ioff:iupl],description="[%d:%d)"%(ioff,iupl),Append=False) + ### mpi_prtout_zbuf("ppnl_half_sub_%d"%(Icol)+"_%02d",ppnl_half_sub[Icol],description="",Append=False) + else: + cwks=numpy.zeros([nKpoints, nCGTO2_A[Icol],nCGTO1_A[r]], dtype=numpy.complex128) + if( MPIrank==0 ): + comm.Recv(cwks, source=r, tag=( MPIsize*Icol + r )) + zbuf1[:,:,ioff:iupl] = cwks + ### mpi_prtout_zbuf("zbuf1_%d_%d"%(Icol,r)+"_%02d",zbuf1[:,:, ioff:iupl],description="[%d:%d)"%(ioff,iupl),Append=False) + + elif( MPIrank == r ): + comm.Send( numpy.array(ppnl_half_sub[Icol]), dest=0, tag=( MPIsize*Icol + r )) + ### mpi_prtout_zbuf("ppnl_half_sub_%d_%d"%(Icol,r)+"_%02d",ppnl_half_sub[Icol],description="",Append=False) + + + ioff=iupl ## <<< never remove this >>> + ppnl_half.append( zbuf1 ) + + Wctm020=Wctm010;Wctm010=time.perf_counter() # XXX XXX + update_dict(fncnme,dic1_timing,Dic_timing,"mpi_send-recv",Wctm010-Wctm020,depth=fncdepth) # XXX XXX + + ### mpi_prtout_zbuf("ppnl_half_retv0a_%02d",ppnl_half[0],description="singlethread:%r"%(singlethread),Append=True) + ## then broadcast the result.. + le_ppnl_half=len(ppnl_half) + for Icol in range(le_ppnl_half): + if( nCGTO2_A[Icol] < 1 ): + continue + mpi_Bcast("calc_pp_overlaps.ppnl_half", ppnl_half[Icol], root=0) + Wctm020=Wctm010;Wctm010=time.perf_counter() # XXX XXX + update_dict(fncnme,dic1_timing,Dic_timing,"mpi_Bcast",Wctm010-Wctm020,depth=fncdepth) # XXX XXX + Wctm010=time.perf_counter() # XXX XXX + printout_dict(fncnme,dic1_timing,Dic_timing,Wctm010-Wctm000,depth=fncdepth) # XXX XXX + ### mpi_prtout_zbuf("ppnl_half_retv0b_%02d",ppnl_half[0],description="singlethread:%r"%(singlethread),Append=True) + + if( MPIrank==0 and get_pp_nl01_static.prtout_calc_pbc_overlaps_retv_ ): + get_pp_nl01_static.fnme_prtout_calc_pbc_overlaps_retv_="calc_pbc_overlaps_pyretv.dat" + get_pp_nl01_static.AoverC_prtout_calc_pbc_overlaps_retv_=numpy.array( [ A_over_c[0], A_over_c[1], A_over_c[2] ] ) + fd=futils.fopen( get_pp_nl01_static.fnme_prtout_calc_pbc_overlaps_retv_, "w");# OK; + for Icol in range(3): + nCGTO_i=nCGTOb_Array[Icol] + if( nCGTO_i < 1 ): + continue + print("###%d %d %d"%(nKpoints,nCGTOb_Array[Icol],nCGTO_1),file=fd) + for kp in range(nKpoints): + for j2 in range(nCGTOb_Array[Icol]): + print("#%d,%d,%d:\t "%(Icol,kp,j2),file=fd) + for k1 in range(nCGTO_1): + print("%16.8f j%16.8f "%( zbuf[Icol][kp][j2][k1].real, zbuf[Icol][kp][j2][k1].imag ),file=fd) + futils.fclose(fd); + + return ppnl_half + +def f_write(path,Append,msg,Threads=[0]): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); + if(Threads is not None): + if(MPIrank not in Threads): + return + fd=open(path,("a" if(Append) else "w")) + print(msg,file=fd);fd.close() + +def calc_pp_overlaps1(cell, A_over_c, kpts, RnucAU_sub, Sy_sub, RnucAU_full, Sy_full, dbgng=False, Zbuf_Refr=None): + #libname=pathlib.Path().absolute() / "libpp01.so" + #c_lib = ctypes.CDLL(libname) + c_lib = lib.load_library("libpp01") + + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); + + kvectors=numpy.reshape( kpts, (-1,3)) + nKpoints=len(kvectors) + kvecs=[] + for v in numpy.ravel(kvectors): + kvecs.append(v) + kvectors_1=( ctypes.c_double*(nKpoints*3) )(*kvecs) + + Nat_sub=len(Sy_sub) + IZnuc_sub=[]; + for i in range(Nat_sub): + IZnuc_sub.append( atomicsymbol_to_atomicnumber( Sy_sub[i] ) ) + Nat_full=len(Sy_full) + IZnuc_full=[]; + for i in range(Nat_full): + IZnuc_full.append( atomicsymbol_to_atomicnumber( Sy_full[i] ) ) + + bset_info=gen_bset_info(cell,IZnuc_sub) + + if( cell.exp_to_discard is not None ): + filtered =filter_by_exponent(bset_info, cell.exp_to_discard ) + bset_info=filtered + + ## + alph,cofs,Ell,distinctIZnuc_sub,Nsh,Npgto,Npgto_sum,Nsh_sum=reorg_bset_info(bset_info) + nDa_sub=len(bset_info) + + IZnuc_B=IZnuc_full.copy(); Nat_B=len(IZnuc_full) + alph_B=[];cofs_B=[];Nsh_B=[];NpGTO_B=[];ell_B=[] + distinct_IZnuc_B=[];N_cols=[];n_cum=0 + for symb in cell._pseudo: + n_th=0;n_cum=0 + distinct_IZnuc_B.append( atomicsymbol_to_atomicnumber(symb) ) + pp = cell._pseudo[symb] + nproj_types = pp[4] + nsh=0 + for l, (rl, nl, hl) in enumerate(pp[5:]): + n_th+=1;n_cum+=(2*l+1) + ### print("#ppshell_"+symb+":%d l=%d n_cum=%d"%(n_th,l,n_cum)) + if nl > 0: + alpha = .5 / rl**2 + alph_B.append(alpha); cofs_B.append(1.0); # for each pGTO + ell_B.append(l); NpGTO_B.append(1); nsh+=1; # for each shell + Nsh_B.append(nsh) # for each nDa_sub +# + n_call=Logger.Countup("pp_ncols"); + verbose_pp=(0 if(n_call!=1) else 2) + n_cols=get_ncols(cell,IZnuc_full,distinct_IZnuc_B,Nsh_B,title="pp_ncols",verbose=verbose_pp ) + n_cols=list_to_a1(n_cols) + BravisVectors= numpy.array( cell.a )/physicalconstants.BOHRinANGS +## note: cell.a this is given in ANGS unit... +## + ### print("#BravisVectors","");print(BravisVectors);### assert False,"" + spdm=3; + BravisVectors_1=( ctypes.c_double*(spdm*3) )( *numpy.ravel(BravisVectors) ) + Vectorfield_1=( ctypes.c_double*(3) )( *A_over_c ) + nKpoints=len(kpts);### print(kpts);print(nKpoints);### assert False,"" + + Npgto_sum_B=len(alph_B) + Nsh_sum_B=sum(Nsh_B) + nDa_B=len(distinct_IZnuc_B) + le=len(n_cols) + ncols_2=( ctypes.c_int*(le))(*n_cols) + RnucAU_sub =list(numpy.ravel(RnucAU_sub)) + Rnuc_1 =( ctypes.c_double*(3*Nat_sub) )(*RnucAU_sub) + IZnuc_1=( ctypes.c_int*(Nat_sub) )( *IZnuc_sub ) + Nsh_1 =( ctypes.c_int*(nDa_sub) )( *Nsh ) + Ell_1 =( ctypes.c_int*(Nsh_sum) )( *Ell ) + Npgto_1=( ctypes.c_int*(Nsh_sum) )(*Npgto) + distinct_IZnuc_1=( ctypes.c_int*(nDa_sub) )( *distinctIZnuc_sub ) + alph_1=( ctypes.c_double*(Npgto_sum) )(*alph) + cofs_1=( ctypes.c_double*(Npgto_sum) )(*cofs) + + nCGTO_1=count_nCGTO(IZnuc_sub,distinctIZnuc_sub,Nsh,Ell); nCGTO_1=int(nCGTO_1) + nCGTOb_Array=count_nCGTO(IZnuc_B,distinct_IZnuc_B,Nsh_B,ell_B,n_cols=n_cols,verbose=verbose_pp); + nCGTO_2=nCGTOb_Array[0] + ### print(nCGTO_1,end="");print(nCGTO_1) + ### print(nCGTO_1,end="");print(type(nCGTO_1)) + + ### print(nCGTO_2,end="");print(nCGTO_2) + ### print(nCGTO_2,end="");print(type(nCGTO_2)) + nCGTO_2=int(nCGTO_2) +### nCGTO_2=count_nCGTO(IZnuc_B,distinct_IZnuc_B,Nsh_B,ell_B,n_cols=n_cols,title="pseudo");nCGTO_2=int(nCGTO_2) + + IZnuc_2=( ctypes.c_int*(Nat_B) )( *IZnuc_B ) + RnucAU_full =list(numpy.ravel(RnucAU_full)) + Rnuc_2 =( ctypes.c_double*(3*Nat_full) )(*RnucAU_full) + + Nsh_2 =( ctypes.c_int*(nDa_B) )( *Nsh_B ) + Ell_2 =( ctypes.c_int*(Nsh_sum_B) )( *ell_B ) + Npgto_2=( ctypes.c_int*(Nsh_sum_B) )(*NpGTO_B) + distinct_IZnuc_2=( ctypes.c_int*(nDa_B) )( *distinct_IZnuc_B ) + alph_2=( ctypes.c_double*(Npgto_sum_B) )(*alph_B) + cofs_2=( ctypes.c_double*(Npgto_sum_B) )(*cofs_B) + Ndim_retv=[3,nKpoints,nCGTO_2,nCGTO_1,2] + + if( nKpoints*nCGTO_2*nCGTO_1 <=0 ): + printout("zero dimension of PSP:"+str( [nKpoints,nCGTO_2,nCGTO_1] ),warning=1) + kpts_lst = ( numpy.zeros((1,3)) if(kpts is None) else numpy.reshape(kpts, (-1,3)) ) + fakecell, hl_blocks = fake_cell_vnl(cell) + ppnl_half_o = _int_vnl(cell, fakecell, hl_blocks, kpts_lst) + printout("ppnl_half_o:SHAPE:"+str(numpy.shape(ppnl_half_o))+" /"+str( Ndim_retv ),flush=True) + printout("ppnl_half_o:VALS:"+str( ppnl_half_o ) ); + ### print("ppnl_half_o:SHAPE:"+str(numpy.shape(ppnl_half_o))+" /"+str( Ndim_retv ),flush=True) + ### print("ppnl_half_o:VALS:"+str( ppnl_half_o ) ); + ### assert False,"PLS check result" + return ppnl_half_o + assert (nKpoints*nCGTO_2*nCGTO_1>0),"%d %d %d"%(nKpoints,nCGTO_2,nCGTO_1) + Lx=20;Ly=20;Lz=20 + Lx=8;Ly=8;Lz=8 + piX2=6.283185307179586476925286766559 + Lj=[-1,-1,-1]; + dbgng_Lx=True; dbgfpath="Lx_for_FT.log" + if( dbgng_Lx ): + print_kvectors(kvectors,BravisVectors,fpath=dbgfpath) + for dir in range(3): + abs_aDOTk=[ abs(numpy.vdot(BravisVectors[dir],kvectors[j])) for j in range(nKpoints) ] + ceil_2pi_over_aDOTk=[ ( 1 if(abs_aDOTk[j]<1e-6) else int(math.ceil( piX2/abs_aDOTk[j])) ) for j in range(nKpoints) ] + Lj[dir]=max( ceil_2pi_over_aDOTk ) + fprintf(dbgfpath,"%02d:"%(dir)+str(abs_aDOTk)+" > "+str(ceil_2pi_over_aDOTk),Append=True) + Lx=Lj[0];Ly=Lj[1];Lz=Lj[2] + + fileIO=False;both=False + key='calc_pbc_overlaps_output' + if( rttddft_common.Params_get(key) is not None ): + dum=rttddft_common.Params_get(key) + if( dum is not None): + if( dum == 'F' or dum=='f'): + fileIO=True;both=False + elif( dum=='B' or dum=='b'): + fileIO=True;both=True + elif( dum=='D' or dum=='d'): + fileIO=False;both=False + else: + assert False, key+":"+str(dum) + zbuf=None;zbuf_refr=None; + + ### nc=get_pp_nl01_static.Countup(fnme) + prtout_retv1=False; ## ( nc==1 ) + prtout_retv2=False; ## ( nc==1 ) + + if(dbgng): ## XXX XXX + both=True;fileIO=True;prtout_retv1=True ## XXX XXX + ### printout("dbgng:%r both:%r"%(dbgng,both),fpath="gto_ps_pp_int01_py.log",Threads=[0],Append=True) + + N_call_dbgclib = rttddft_common.Countup("Call_calc_pbc_overlaps_dbg") + dbgng_clib=False + if(dbgng_clib): + if( N_call_dbgclib==1 or N_call_dbgclib==5 ): + flag=1+2; N_test=8000;I_skip=400 + for I_test in range(N_test): + c_lib.calc_pbc_overlaps_dbg( Nat_sub, Rnuc_1, IZnuc_1, nDa_sub, distinct_IZnuc_1, + Nsh_1, Ell_1, Npgto_1, alph_1, cofs_1, + Nat_full, Rnuc_2, IZnuc_2, nDa_B, distinct_IZnuc_2, + Nsh_2, Ell_2, ncols_2, Npgto_2, alph_2, + cofs_2,spdm, BravisVectors_1, Vectorfield_1, nKpoints, + kvectors_1, Lx, Ly, Lz, nCGTO_2, nCGTO_1, MPIrank, flag); + if( I_test==0 or I_test==5 or (I_test+1)%I_skip==0 ): + if( MPIrank==0 ): + fprintf("calc_pbc_overlaps_dbg_python.log","#c_lib.calc_pbc_overlaps_dbg test%4d END"%(I_test+1),Append=True) + print("#c_lib.calc_pbc_overlaps_dbg.1 END",flush=True) + flag=1+2+4+8+16+32; N_test=200; I_skip=20 + if( N_call_dbgclib==1 ): + N_test=20;I_skip=5 + elif( N_call_dbgclib==3 or N_call_dbgclib==4): + N_test=4000;I_skip=400 + else: + N_test=0;I_skip=1 + for I_test in range(N_test): + c_lib.calc_pbc_overlaps_dbg( Nat_sub, Rnuc_1, IZnuc_1, nDa_sub, distinct_IZnuc_1, + Nsh_1, Ell_1, Npgto_1, alph_1, cofs_1, + Nat_full, Rnuc_2, IZnuc_2, nDa_B, distinct_IZnuc_2, + Nsh_2, Ell_2, ncols_2, Npgto_2, alph_2, + cofs_2,spdm, BravisVectors_1, Vectorfield_1, nKpoints, + kvectors_1, Lx, Ly, Lz, nCGTO_2, nCGTO_1, MPIrank, flag); + if( I_test==0 or I_test==5 or (I_test+1)%I_skip==0 ): + if( MPIrank==0 ): + fprintf("calc_pbc_overlaps_dbg_python.log","#c_lib.calc_pbc_overlaps_dbg FULL test%4d / %4d"%(I_test+1,N_test),Append=True) + print("#c_lib.calc_pbc_overlaps_dbg.2 END",flush=True) + + n_call=rttddft_common.Countup("calc_pp_overlaps"); + dbgng_libf01o=( n_call==1 or n_call==5) ## XXX XXX PLS. remove this in the expanse cluster ... + ### printout("dbgng_libf01o:%r n_call:%d"%(dbgng_libf01o,n_call),fpath="gto_ps_pp_int01_py.log",Threads=[0],Append=True) + if( fileIO ): +#int calc_pbc_overlaps_f(int nAtm, double *Rnuc, int *IZnuc, int nDa, int *distinctIZnuc, +# const int *Nsh, const int *ell, const int *npGTO, const double *alph, const double *cofs, +# int nAtmB, double *RnucB, int *IZnucB, int nDb, int *distinctIZnucB, +# const int *NshB, const int *ellB, const int *n_cols, const int *npGTOB, const double *alphB, +# const double *cofsB, int spdm, double *BravaisVectors, double *Vectorfield,int nKpoints, +# double *kvectors, int Lx,int Ly,int Lz, const int nCGTO_2, const int nCGTO_1, const int MPIrank, const int filenumber) + filenumber=MPIrank + heapcheck("calc_pbc_overlaps-BF") + c_lib.calc_pbc_overlaps_f01( Nat_sub, Rnuc_1, IZnuc_1, nDa_sub, distinct_IZnuc_1, + Nsh_1, Ell_1, Npgto_1, alph_1, cofs_1, + Nat_full, Rnuc_2, IZnuc_2, nDa_B, distinct_IZnuc_2, + Nsh_2, Ell_2, ncols_2, Npgto_2, alph_2, + cofs_2,spdm, BravisVectors_1, Vectorfield_1, nKpoints, + kvectors_1, Lx, Ly, Lz, nCGTO_2, nCGTO_1, MPIrank, filenumber); + heapcheck("calc_pbc_overlaps-AF") + retf="calc_pbc_overlaps_%03d.retf"%(filenumber) + ### printout("FILE:%s"%(retf),fpath="gto_ps_pp_int01_py.log",Threads=[0],Append=True) + retv=numpy.reshape( readwrite_xbuf('R',retf), [3,nKpoints,nCGTO_2,nCGTO_1]) + zbuf=[] + for Icol in range(3): + nCGTO_i=nCGTOb_Array[Icol] + if( nCGTO_i<1 ): + continue + array=numpy.zeros([nKpoints,nCGTO_i,nCGTO_1],dtype=numpy.complex128) + for kp in range(nKpoints): + for j2 in range(nCGTOb_Array[Icol]): + for k1 in range(nCGTO_1): + array[kp][j2][k1] = retv[Icol][kp][j2][k1] + zbuf.append(array) + if( dbgng_libf01o ): + filenumber=MPIrank+400 + c_lib.calc_pbc_overlaps_f( Nat_sub, Rnuc_1, IZnuc_1, nDa_sub, distinct_IZnuc_1, + Nsh_1, Ell_1, Npgto_1, alph_1, cofs_1, + Nat_full, Rnuc_2, IZnuc_2, nDa_B, distinct_IZnuc_2, + Nsh_2, Ell_2, ncols_2, Npgto_2, alph_2, + cofs_2,spdm, BravisVectors_1, Vectorfield_1, nKpoints, + kvectors_1, Lx, Ly, Lz, nCGTO_2, nCGTO_1, MPIrank, filenumber); + retf="calc_pbc_overlaps_%03d.retf"%(filenumber) + printout("flib01o:%s"%(retf),fpath="gto_ps_pp_int01_py.log",Threads=[0],Append=True) + retv_ref=numpy.reshape( readwrite_xbuf('R',retf), [3,nKpoints,nCGTO_2,nCGTO_1]) + zbuf_ref=[] + for Icol in range(3): + nCGTO_i=nCGTOb_Array[Icol] + if( nCGTO_i<1 ): + continue + array=numpy.zeros([nKpoints,nCGTO_i,nCGTO_1],dtype=numpy.complex128) + for kp in range(nKpoints): + for j2 in range(nCGTOb_Array[Icol]): + for k1 in range(nCGTO_1): + array[kp][j2][k1] = retv_ref[Icol][kp][j2][k1] + zbuf_ref.append(array) + zbuf_diff.append( aNmaxdiff( zbuf[Icol], zbuf_ref[Icol]) ) + if(MPIrank==0): + fdDBG=open("dbgng_libf01o.log","a") + print(zbuf_diff,file=fdDBG);fdDBG.close() + verbose_DBG=False + if(verbose_DBG): + fd=futils.fopen("dbgng_libf01o_zbuf.log","a") ## OK + print("#A_over_c:%f,%f,%f"%(A_over_c[0],A_over_c[1],A_over_c[2]),file=fd); + for kp in range(nKpoints): + print("#%03d:K=%d\n"%(kp,kp),file=fd); + for j2 in range(nCGTO_2): + string="";strng2="" + for k1 in range(nCGTO_1): + string+="%16.8f %16.8f "%(zbuf[Icol][kp][j2][k1][0].real,zbuf[Icol][kp][j2][k1][1].imag) + strng2+="%16.8f %16.8f "%(zbuf_ref[Icol][kp][j2][k1][0].real,zbuf_ref[Icol][kp][j2][k1][1].imag) + print(string,file=fd); + print(strng2,file=fd); + ### print("%d %d %d %d %f %f"%(Icol,kp,j2,k1,dbuf[Icol][kp][j2][k1][0],dbuf[Icol][kp][j2][k1][1]),file=fd) + futils.fclose(fd); + + dev=max( zbuf_diff );devTOL=1.0e-7 + if( dev >= devTOL or MPIrank==0 ): + print("#dbgng_libf01o:diff:%e"%(dev)+ str(zbuf_diff)) + assert dev 0) and (n_call==1 or n_call==20 or n_call==200) ): + vpp_org = pseudo.pp_int.get_pp_nl(cell, kpts_lst) + fakecell, hl_blocks = fake_cell_vnl(cell) + ppnl_half_o = _int_vnl(cell, fakecell, hl_blocks, kpts_lst) + Wctm020=Wctm010;Wctm010=time.perf_counter() # XXX XXX + update_dict(fncnme,dic1_timing,Dic_timing,"DBG_get_pp_nl_org",Wctm010-Wctm020,depth=fncdepth) # XXX XXX + + zerovec=[ 0.0, 0.0, 0.0] + get_ppnl_half=[] + vpp_ZF= get_pp_nl01(cell, zerovec, kpts_lst, comp_to_singlethread=True, get_ppnl_half=get_ppnl_half) + ppnl_half_ZF= get_ppnl_half[0] + diff_vpp = max( abs( numpy.ravel( vpp_org ) - numpy.ravel( vpp_ZF ) )) + + diff_ppnl_half = -1; le=len(ppnl_half_ZF) + for I in range(le): + if( len(ppnl_half_ZF[I])==0 or len(ppnl_half_o[I]) ): + fdOU=open("ppnl_half.log","a"); + print("#skipping %d %s %s"%(I,str(numpy.shape(ppnl_half_ZF[I])),str(numpy.shape(ppnl_half_o))),file=fdOU) + fdOU.close();continue + diff1 = max( abs( numpy.ravel( ppnl_half_ZF[I] ) - numpy.ravel( ppnl_half_o[I] ) ) ) + diff_ppnl_half = max( diff_ppnl_half, diff1 ) + fdOU=open("ppnl_half.log","a"); + for fd in [ fdOU, sys.stdout ]: + print("#diff_ppnl_half:%e"%(diff_ppnl_half), file=fd) + print("#diff_vpp :%e"%(diff_vpp), file=fd) + fdOU.close() + Wctm020=Wctm010;Wctm010=time.perf_counter() # XXX XXX + update_dict(fncnme,dic1_timing,Dic_timing,"DBG_get_pp_nl_ZF",Wctm010-Wctm020,depth=fncdepth) # XXX XXX + if(idbgng>1): + dev=-1 + for kp in range(nkpts): + diff=print_a2maxdiff(vpp_org[kp],vpp_ZF[kp], + "validate_get_pp_nl01_"+str(rttddft_common.get_job(True))+".rcd", + Append=(kp>0 or n_call>1), + description="ZF pp (lhs:mine,rhs:pySCForg) n_call=%d kp=%02d/%2d"%(n_call,kp,nkpts)) + dev=max(diff,dev) + else: + dev=aNmaxdiff(vpp_org,vpp_ZF,comment="vpp",verbose=True,title="vpp_ZF") + assert (dev<1.0e-6),"diff:||vpp_org-vpp_ZF||=%e"%(dev) + ### print("vloc1;",end="");print( numpy.shape(vloc1)) ## vloc1;(8, 56, 56) + ### print("vloc2;",end="");print( numpy.shape(vloc2)) ## vloc1;(8, 56, 56) + ### print("vpp_org;",end="");print( numpy.shape(vpp_org)) ## (8, 56, 56) + + vpp = get_pp_nl01(cell, A_over_c, kpts_lst) + Wctm020=Wctm010;Wctm010=time.perf_counter() # XXX XXX + update_dict(fncnme,dic1_timing,Dic_timing,"get_pp_nl01",Wctm010-Wctm020,depth=fncdepth) # XXX XXX + + if( details is not None ): + details.update({"vloc1":arrayclone(vloc1),"vloc2":arrayclone(vloc2), + "vpp":arrayclone(vpp)}) + + if( diff_ZF_to_fF and (vpp_org is not None) ): + abs_AoverC=numpy.sqrt( A_over_c[0]**2 + A_over_c[1]**2 + A_over_c[2]**2 ) + if(abs_AoverC>1.0e-6): + n1=rttddft_common.Countup("with_df_get_pp.diff_ZF_to_fF") + if(n1==1): + diff=aNmaxdiff(vpp,vpp_org,comment="vpp/vpp_org",verbose=True,title="vpp") + print_Hmatrices("vpp",vpp,vpp_org,fpath="vpp_and_vppZF.dat") + + for k in range(nkpts): + vpp[k] += vloc1[k] + vloc2[k] + + if kpts is None or numpy.shape(kpts) == (3,): + vpp = vpp[0] + Wctm010=time.perf_counter() # XXX XXX + printout_dict(fncnme,dic1_timing,Dic_timing,Wctm010-Wctm000,depth=fncdepth) # XXX XXX + + return vpp + +class get_pp_nl01_static: + count=0 + Dict_={} + prtout_calc_pbc_overlaps_retv_=False ## XXX XXX + AoverC_prtout_calc_pbc_overlaps_retv_=None ## XXX XXX + fnme_prtout_calc_pbc_overlaps_retv_=None ## XXX XXX + @staticmethod + def Countup(key,inc=True): + if( key not in get_pp_nl01_static.Dict_ ): + get_pp_nl01_static.Dict_.update({key:0}); + if( inc ): + get_pp_nl01_static.Dict_[key]+=1 + return get_pp_nl01_static.Dict_[key] + +def get_pp_nl01(cell, A_over_c, kpts=None, comp_to_singlethread=False, get_ppnl_half=None): + ### fd01=open("get_pp_nl01_dbg.log","w");print("start:"+str( datetime.datetime.now() ),file=fd01);fd01.close() + ### test_zalloc(5,3,4,1,prtout=True) + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); + + Logger.write_once(None,"get_pp_nl01:calc_pp_overlaps","calculate pp for A="+str(A_over_c)) + if kpts is None: + assert False,"please set kpts explicitly.."; + kpts_lst = numpy.zeros((1,3)) + else: + kpts_lst = numpy.reshape(kpts, (-1,3)) + nkpts = len(kpts_lst) + + fakecell, hl_blocks = fake_cell_vnl(cell) ## pyscf.pbc.gto.pseudo.pp_int + + #if( hasattr(fakecell,"atom") ): + # pyscf_common.Check_cellRnuc(fakecell,"get_pp_nl01.fakecell") + + force_singlethread=None ## default ... + if( not MPIutils01.Multithreading() ): + ## MPIutils01.DebugLog("#calc_pp_overlaps:singlethread"); + comp_to_singlethread = False + force_singlethread = True + MPIutils01.DebugTrace("get_pp_nl01","get_pp_nl01:SINGLETHREAD") + dbgng=1;strict=1; + if(dbgng>0): + get_pp_nl01_static.count=get_pp_nl01_static.count+1 + if( get_pp_nl01_static.count==1 or get_pp_nl01_static.count==20 or comp_to_singlethread): + ppnl_half_o = _int_vnl(cell, fakecell, hl_blocks, kpts_lst) +### fd001=open("ppnl_half_o_01.log","w"); +### print("#ppnl_half_o:"+str(datetime.datetime.now()),file=fd001); +### ### print(ppnl_half_o,file=fd001);### fd001.close() +### print( len(ppnl_half_o),file=fd001 ); +### for I in range( len(ppnl_half_o) ): +### print(numpy.shape(ppnl_half_o[I]),file=fd001) +### ## (1, 72, 180), (1, 16, 180), (1, 4, 180) ... so this cannot be treated as ndarray +### ## whereas A[0],A[1],A[2] are ndarrays +### fd001.close() + +### datf01="ppnl_half.dat" +### if( not suppress_prtout() ): +### fd=futils.fopen(datf01,("w" if(get_pp_nl01_static.count==1) else "a")) ## OK +### for col in ppnl_half_o: +### line="" +### print("#"+str(numpy.shape(col)),file=fd) +### for y in numpy.ravel(col): +### line+=str(y) +### print(line,file=fd) +### futils.fclose(fd); + + ppnl_half_ZF = calc_pp_overlaps(cell,[0,0,0],kpts_lst,dbgng=True,Zbuf_Refr=ppnl_half_o) ## New subroutine + comp_datf="ppnl_half_comp_n%06d.dat"%(get_pp_nl01_static.count); maxdev=-1;Ndev=0 + if( not suppress_prtout() ): + fd=futils.fopen(comp_datf,"w") ## OK + maxdev=-1;vals=[];Ndev=0 + for Icol in range(3): + Ndim2=numpy.shape(ppnl_half_o[Icol]); ### print("#%d:shape:"%(Icol),end="");print(Ndim2) + if(Ndim2[0]<1): + continue + Ndim1=numpy.shape(ppnl_half_ZF[Icol]);### print("#%d:shape:"%(Icol),end="");print(Ndim1) + Ndim=[ min( Ndim1[0], Ndim2[0]), min( Ndim1[1], Ndim2[1]), min( Ndim1[2], Ndim2[2]) ] + for Kp in range( Ndim[0] ): + for j2 in range(Ndim[1]): + for k1 in range(Ndim[2]): + dev=abs( ppnl_half_ZF[Icol][Kp][j2][k1] - ppnl_half_o[Icol][Kp][j2][k1] ) + if(dev>maxdev): + maxdev=dev; vals=[ ppnl_half_ZF[Icol][Kp][j2][k1], ppnl_half_o[Icol][Kp][j2][k1] ]; + if(dev<1.0e-6): + print("## ",end="",file=fd) + else: + Ndev+=1 + ratio=ppnl_half_ZF[Icol][Kp][j2][k1]/(1.0 if( abs(ppnl_half_o[Icol][Kp][j2][k1])<1.0e-20 ) else ppnl_half_o[Icol][Kp][j2][k1]); + print("%d %d %d %d %f+j%f %f+j%f %e val/ref=%14.8f + j%14.8f"%(Icol,Kp,j2,k1, + ppnl_half_ZF[Icol][Kp][j2][k1].real, ppnl_half_ZF[Icol][Kp][j2][k1].imag, + ppnl_half_o[Icol][Kp][j2][k1].real, ppnl_half_o[Icol][Kp][j2][k1].imag, dev, + ratio.real, ratio.imag),file=fd) + fd2=futils.fopen("comp_vals.dat",("w" if(Kp==0 and Icol==0) else "a")) + print("%d %d %e %f+j%f / %f+j%f"%(Icol,Kp,maxdev, vals[0].real,vals[0].imag, vals[1].real,vals[1].imag),file=fd2) + futils.fclose(fd2); + + futils.fclose(fd); + if( maxdev > 1.0e-6 or Ndev > 0 ): + assert False,"Check results %02d %e %d:check:"%(MPIrank,maxdev,Ndev) +comp_datf + if( maxdev > 1.0e-7 or Ndev > 0 ): + if(strict>1): + assert False,"Check results %02d %e %d:check:"%(MPIrank,maxdev,Ndev)+comp_datf + else: + Logger.Warning("ppnl_half_ZF","ppnl_half_ZF:maxdev=%e:"%(maxdev)+str(vals)) + assert (maxdev<1.0e-6),"check"+comp_datf + if(get_pp_nl01_static.count%20==1): + printout("#calculating ppnl_half with Field:%f"%(math.sqrt(A_over_c[0]*A_over_c[0] + A_over_c[1]*A_over_c[1] + A_over_c[2]*A_over_c[2]))) + + abs_A_over_c= numpy.sqrt( A_over_c[0]**2 + A_over_c[1]**2 + A_over_c[2]**2 ) + + dbgng_mpi=False; ppnl_half_refr=None ## 20210609MPIvalidation: we compare final results to those of with_df_get_pp_bf20210608 .. + if( dbgng_mpi or comp_to_singlethread ): + n_count = rttddft_common.Countup("get_pp_nl01_testMPI") + if(n_count==1 or comp_to_singlethread): + ppnl_half_refr=calc_pp_overlaps(cell,A_over_c,kpts_lst,singlethread=True) + ### printout("calling calc_pp_overlaps... to get ppnl_half (main)",fpath="gto_ps_pp_int01_py.log",Threads=[0],Append=True) + ppnl_half = calc_pp_overlaps(cell,A_over_c,kpts_lst, singlethread=force_singlethread) + if( force_singlethread ): + print("#multithreading:$%02d:ppnl_half:SINGLETHREAD"%(MPIrank) ) + else: + print("#multithreading:$%02d:ppnl_half:MULTITHREAD"%(MPIrank) ) + + if( ppnl_half_refr is not None ): + Ld=len(ppnl_half);dev=-1;diffs=[] + for I in range(Ld): + diffs.append( aNmaxdiff(ppnl_half_refr[I], ppnl_half[I]) ) + printout("ppnl_half:maxdiff:%e"%( max(diffs) ),fpath="ppnl_half.log",Append=True,Threads=[0]) + print("ppnl_half:maxdiff:%e"%( max(diffs) ) ) + assert max(diffs)<1.0e-7,"$%02d:|ppnl_half - ppnl_half_SINGLETHREAD|=%e"(MPIrank,diffs) + + + if( get_ppnl_half is not None ): + print("#cloning ppnl_half:",[ numpy.shape( buf ) for buf in ppnl_half ]) + get_ppnl_half.append( [ arrayclone(buf) for buf in ppnl_half ]) +##ppnl_half:(8, 22, 56) +##ppnl_half:(8, 8, 56) +##ppnl_half:(0,) +#nao:56 + + nao = cell.nao_nr() # 56 + ### print("nao:",end="");print(nao) + buf = numpy.empty((3*9*nao), dtype=numpy.complex128) + + # We set this equal to zeros in case hl_blocks loop is skipped + # and ppnl is returned + n_cum=0 + ppnl = numpy.zeros((nkpts,nao,nao), dtype=numpy.complex128) + for k, kpt in enumerate(kpts_lst): + offset = [0] * 3 + for ib, hl in enumerate(hl_blocks): + l = fakecell.bas_angular(ib) + if(k==0): + n_cum+=(2*l+1) + ### print("#ppShell:%d el=%d nmult=%d %d"%(ib,l,2*l+1,n_cum)) #ppShell:0 el=0 nmult=1 1 + nd = 2 * l + 1 + hl_dim = hl.shape[0] + ### print("hl_dim;",end="");print(hl_dim) ## 2 or 1 + ilp = numpy.ndarray((hl_dim,nd,nao), dtype=numpy.complex128, buffer=buf) + for i in range(hl_dim): + p0 = offset[i] + ilp[i] = ppnl_half[i][k][p0:p0+nd] + + ### print("ilp_%d:"%(i),end="");print(ppnl_half[i][k][p0:p0+nd]) + ### print("ilp_%d:"%(i),end="");print(ilp[i]); + + offset[i] = p0 + nd + ppnl[k] += numpy.einsum('ilp,ij,jlq->pq', ilp.conj(), hl, ilp) + ### if(k==0): + ### print("offset_sum:%d %d %d"%(offset[0],offset[1],offset[2])) (8,0,0) + if abs(kpts_lst).sum() < 1e-9: # gamma_point: + if( abs_A_over_c < 1e-10 ): + ppnl = ppnl.real + else: + # dum=absmax_imaginary_part(ppnl) + printout("#finite A_over_c.. keep as a complex array: imag:%e"%(absmax_imaginary_part(ppnl))) + # assert (dum<1.0e-10),"" + if kpts is None or numpy.shape(kpts) == (3,): + ppnl = ppnl[0] + return ppnl + +def get_ncols(cell,IZnuc, distinct_IZnuc, Nsh_B=None,verbose=0,title=""): + + fakecell, hl_blocks = fake_cell_vnl(cell) + if(verbose>1): + printout("#get_ncols:"+title+":cell:"+str(cell)) + printout("#get_ncols:"+title+":fakecell:"+str(fakecell)) + printout("#get_ncols:"+title+":hl_blocks:"+str(hl_blocks)) + pre=[] + for hl in hl_blocks: + if(verbose>1): + printout("#get_ncols:"+title+":hl_blocks:"+str(hl)) + nd=len(hl) + pre.append(nd) + ### print("#n_cols_pre:",end="");print(pre) + nDa=len(distinct_IZnuc) + assert nDa>0,"wrong nDa:"+str(distinct_IZnuc) + ret=[] + for iDa in range(nDa): + ret.append(None) + + + Nat=len(IZnuc) + ksh_to_Iat=[] + for Iat in range(Nat): + IZ=IZnuc[Iat] + for iDa in range(nDa): + if(IZ==distinct_IZnuc[iDa]): + break + assert(distinct_IZnuc[iDa]==IZ),"" + nsh1=Nsh_B[iDa] + for k in range(nsh1): + ksh_to_Iat.append(Iat) + + if(verbose>0): + printout("#get_ncols:"+title+":ksh_to_Iat:"+str(ksh_to_Iat)); + if(verbose>0): + printout("#get_ncols:"+title+":pre:"+str(pre)); +# +# 20210608: Nat is not necs. full size... +# assert len(ksh_to_Iat)==len(pre),"" +# + le=len(ksh_to_Iat) + append_to_logfile=False + for Iat in range(Nat): + IZ=IZnuc[Iat] + for iDa in range(nDa): + if(IZ==distinct_IZnuc[iDa]): + break + assert(distinct_IZnuc[iDa]==IZ),"" + if( ret[iDa] is None): + ret[iDa]=[];kA=[]; + for k in range(le): + if( ksh_to_Iat[k] != Iat ): + continue + else: + ret[iDa].append( pre[k] );kA.append(k) + #if(verbose>1): + # print("#get_ncols:"+title+":ret:"+str(pre[k])); + if( not suppress_prtout() ): + fd=futils.fopen("gen_ncols.log",("a" if(append_to_logfile) else "w"));append_to_logfile=True ## OK + print("#%d: %d k={"%(Iat,iDa)+str(kA)+"} ret:"+str(ret[iDa]),file=fd); + futils.fclose(fd); + else: + refr=[];kA=[]; + for k in range(le): + if( ksh_to_Iat[k] != Iat ): + continue + else: + refr.append( pre[k] );kA.append(k) + assert i1eqb(refr, ret[iDa], verbose=False,title="gen_ncols.001"),"" + ### print("#n_cols_ret:",end="");print(ret) + # NshSUM=sum(Nsh_B) + # leRET=len(ret) + # assert leRET==NshSUM,"len:%d / NshSUM:%d ("%(leRET,NshSUM) + str(Nsh_B) + return ret; +def test_pp(cell): + fakecell, hl_blocks = fake_cell_vnl(cell) + printout("#fakecell:"+str(fakecell)) + + n=0 + for x in vars(fakecell): + y=getattr(fakecell,x,None) + printout("#fakecell_%s"%(str(x))+str(y)) + n+=1 + n=0 + for hl in hl_blocks: + printout("#hl_blocks_%d:"%(n)+str(hl)) + n+=1 +#fakecell_ke_cutoff None +#fakecell_pseudo gth-pade +#fakecell_dimension 3 +#fakecell_low_dim_ft_type None +#fakecell__mesh [969 969 625] +#fakecell__mesh_from_build True +#fakecell__ew_eta 2.7513252105444863 +#fakecell__ew_from_build True +#fakecell__ew_cut 2.5435279375048974 +#fakecell__rcut 20.291655858262136 +#fakecell__rcut_from_build True +#fakecell_0:[[ 6.9257397 5.62514728] +# [ 5.62514728 -67.13819583]] +#fakecell_1:[[ 5.0790865 15.27691303] +# [ 15.27691303 -207.97142959]] +#fakecell_2:[[-9.12589591]] +#fakecell_3:[[ 6.9257397 5.62514728] +# [ 5.62514728 -67.13819583]] +#fakecell_4:[[ 5.0790865 15.27691303] +# [ 15.27691303 -207.97142959]] +#fakecell_5:[[-9.12589591]] +#fakecell_6:[[18.26691718]] +#fakecell_7:[[18.26691718]] +#fakecell_8:[[18.26691718]] +#fakecell_9:[[18.26691718]] +def mpi_prtout_zbuf(fnme_format,zbuf,description="",Append=False): + comm=MPI.COMM_WORLD;MPIrank=comm.Get_rank();MPIsize=comm.Get_size() + fnme=fnme_format%(MPIrank) + fd=open(fnme,('a' if(Append) else 'w')) + Ld=len(zbuf) + print("##"+description,file=fd); + for I in range(Ld): + cbuf=zbuf[I];ndim=numpy.shape(cbuf) + print("#%03d:"%(I) +str(ndim)) + if(len(ndim)==2): + for J in range(ndim[0]): + string="" + for K in range(ndim[1]): + string+="%14.6f %14.6f "%(cbuf[J][K].real, cbuf[J][K].imag) + print(string,file=fd) + elif( len(ndim)==3 ): + for J in range(ndim[0]): + print("#%02d"%(J),file=fd) + for K in range(ndim[1]): + string="" + for L in range(ndim[2]): + string+="%14.6f %14.6f "%(cbuf[J][K][L].real, cbuf[J][K][L].imag) + print(string,file=fd) + print("\n\n",file=fd) + else: + cbuf=numpy.ravel(cbuf);le=len(cbuf) + string="" + for K in range(le): + string+="%14.6f %14.6f "%(cbuf[K].real, cbuf[K].imag) + print(string,file=fd) + fd.close() + +def uniquify_i1a(org): + le=len(org) + ret=[] + for I in range(le): + if( org[I] in ret ): + continue + ret.append( org[I] ) + return ret + + +def prtout_bsetx(rttddft,filename=None): + kpts=( None if(not rttddft._pbc) else rttddft.kpts) + mol_or_cell = (rttddft.mol if(not rttddft._pbc) else rttddft.cell) + Rnuc_au,Sy=parse_xyzstring( mol_or_cell.atom, unit_BorA='B') + A_over_c=[0.0, 0.0, 0.0] + prtout_bset1(rttddft, mol_or_cell, A_over_c, kpts, Rnuc_au, Sy, filename=filename) + +def prtout_bset1(rttddft, mol_or_cell, A_over_c, kpts, RnucAU_sub, Sy_sub, filename=None): + #libnme=pathlib.Path().absolute() / "libpp01.so" + #testlib=ctypes.CDLL(libnme) + testlib = lib.load_library("libpp01") + + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); + + if( kpts is None ): + kpts=[ 0.0, 0.0, 0.0] + + kvectors=numpy.reshape( kpts, (-1,3)) + nKpoints=len(kvectors) + kvecs=[] + for v in numpy.ravel(kvectors): + kvecs.append(v) + kvectors_1=( ctypes.c_double*(nKpoints*3) )(*kvecs) + + Nat_sub=len(Sy_sub) + IZnuc_sub=[]; + for i in range(Nat_sub): + IZnuc_sub.append( atomicsymbol_to_atomicnumber( Sy_sub[i] ) ) + + bset_info=gen_bset_info(mol_or_cell,IZnuc_sub) + + strbset=None + if( isinstance(mol_or_cell.basis,str) ): + strbset=(mol_or_cell.basis).replace('(','_').replace(')','').replace(',','') + elif( isinstance(mol_or_cell.basis, dict) ): + delimiter="" + for elmt in mol_or_cell.basis: + strbset+=delimiter+elmt+ str( mol_or_cell.basis[elmt] ).replace('(','_').replace(')','').replace(',','') + delimiter="_" + + if( hasattr(mol_or_cell,"exp_to_discard")): + if( mol_or_cell.exp_to_discard is not None ): + filtered =filter_by_exponent(bset_info, mol_or_cell.exp_to_discard ) + bset_info=filtered + + ## + spdm=3 + alph,cofs,Ell,distinctIZnuc_sub,Nsh,Npgto,Npgto_sum,Nsh_sum=reorg_bset_info(bset_info) + nDa_sub=len(bset_info) + BravisVectors= ( numpy.array([0.0 for k in range(9)]) if( not rttddft._pbc ) else \ + numpy.array( mol_or_cell.a )/physicalconstants.BOHRinANGS ) + BravisVectors_1=( ctypes.c_double*(spdm*3) )( *numpy.ravel(BravisVectors) ) + Vectorfield_1=( ctypes.c_double*(3) )( *A_over_c ) + nKpoints=len(kpts);### print(kpts);print(nKpoints);### assert False,"" + + RnucAU_sub =list(numpy.ravel(RnucAU_sub)) + Rnuc_1 =( ctypes.c_double*(3*Nat_sub) )(*RnucAU_sub) + IZnuc_1=( ctypes.c_int*(Nat_sub) )( *IZnuc_sub ) + Nsh_1 =( ctypes.c_int*(nDa_sub) )( *Nsh ) + Ell_1 =( ctypes.c_int*(Nsh_sum) )( *Ell ) + Npgto_1=( ctypes.c_int*(Nsh_sum) )(*Npgto) + distinct_IZnuc_1=( ctypes.c_int*(nDa_sub) )( *distinctIZnuc_sub ) + alph_1=( ctypes.c_double*(Npgto_sum) )(*alph) + cofs_1=( ctypes.c_double*(Npgto_sum) )(*cofs) + nCGTO_1=count_nCGTO(IZnuc_sub,distinctIZnuc_sub,Nsh,Ell); nCGTO_1=int(nCGTO_1) + Nsh_sum=sum( Nsh ); nPGTO_sum=sum(Npgto) + + fnme=filename + if( fnme is None ): + fnme=str(rttddft_common.get_job(True))+"_basisset.dat" + if( strbset is not None ): + if( rttddft_common.Params_get("name") is not None ): + fnme=rttddft_common.Params_get("name")+strbset+"_basisset.dat" + write_filex(fnme, + Natm=Nat_sub, Rnuc=RnucAU_sub, IZnuc=IZnuc_sub, nDa=nDa_sub, distinctIZnuc=distinctIZnuc_sub, + Nsh=Nsh, Nsh_sum=Nsh_sum, ell=Ell, nPGTO=Npgto, + nPGTO_sum=nPGTO_sum, alph=alph, cofs=cofs, spdm=3, + BravisVectors=BravisVectors, Vectorfield=A_over_c, nKpoints=nKpoints, + kvectors=kvectors, nCGTO=nCGTO_1); + testlib.test001( Nat_sub, Rnuc_1, IZnuc_1, nDa_sub, distinct_IZnuc_1, + Nsh_1, Ell_1, Npgto_1, alph_1, cofs_1, + spdm, BravisVectors_1, Vectorfield_1, nKpoints, + kvectors_1, nCGTO_1); + +## returns Complex [spdm][nKpoints][nAO][nAO] matrix +## corresponding to < \mu | x V_NL(x,x') - V_NL(x,x') x'| \nu > +## +def with_df_get_ppxx(mydf,A_over_c,kpts=None,rttddft=None): + import time + from .update_dict import printout_dict,update_dict + + fncnme="with_df_get_ppxx";fncdepth=3 ## fncdepth ~ SCF:0 vhf:1 get_j:2 XXX XXX + Wctm000=time.perf_counter();Wctm010=Wctm000;dic1_timing={} # XXX XXX + Dic_timing=rttddft_common.Dict_getv('timing_'+fncnme, default=None) # XXX XXX + if( Dic_timing is None ): + rttddft_common.Dict_setv('timing_'+fncnme, {}); # XXX XXX + Dic_timing=rttddft_common.Dict_getv('timing_'+fncnme, default=None) # XXX XXX + N_call=rttddft_common.Countup("with_df_get_ppxx"); + cell = mydf.cell + if kpts is None: + assert False,"please set kpts explicitly.."; + kpts_lst = numpy.zeros((1,3)) + else: + kpts_lst = numpy.reshape(kpts, (-1,3)) + nkpts = len(kpts_lst) + + ## in any sense this is <\mu | xV(x,x') - V(x,x')x' |\nu> + ## [3][nAO][nAO] + vpp = get_pp_nl01xx(cell, A_over_c, kpts_lst) + ### Dbgtrace("#with_df_get_ppxx:get_pp_nl01xx returns"); + Wctm020=Wctm010;Wctm010=time.perf_counter() # XXX XXX + update_dict(fncnme,dic1_timing,Dic_timing,"get_pp_nl01xx",Wctm010-Wctm020,depth=fncdepth) # XXX XXX + printout_dict(fncnme,dic1_timing,Dic_timing,Wctm010-Wctm000,depth=fncdepth) # XXX XXX + ### Dbgtrace("#with_df_get_ppxx:END"); + return vpp +def Dbgtrace(msg,flush=None): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + msg+=" \t\t "+str( datetime.datetime.now() ) + print("#gto_ps_pp_int01.Dbgtrace:#$%02d/%d:"%(MPIrank,MPIsize)+str(msg),flush=True); + fd1=open("gto_ps_pp_int01_Dbgtrace%02d.log"%(MPIrank),"a");print(msg,file=fd1);fd1.close() + +def test_zalloc(N1,N2,N3,N4,prtout=True): + ### XXX XXX TODO: this stupid test takes very very long time + ### it looks that the memory allocated in c library is not fully released by python -del- method + ### + #libname=pathlib.Path().absolute() / "libpp01.so" + #c_lib = ctypes.CDLL(libname) + c_lib = lib.load_library("libpp01") + + Ndim_retv=[N1,N2,N3,2] + zbuf=None + for I in range(N4): + c_lib.test_alloc.restype= ndpointer(dtype=ctypes.c_double,shape=Ndim_retv ) + dbuf=c_lib.test_alloc(N1,N2,N3) + ### print(numpy.shape(dbuf)) + zbuf=numpy.zeros([N1,N2,N3],dtype=numpy.complex128) + for i in range(N1): + for j in range(N2): + for k in range(N3): + zbuf[i][j][k]= dbuf[i][j][k][0] + 1j*dbuf[i][j][k][1] + ##if(I%2==0): + ## c_lib.free_zbuf(dbuf); ## ctypes.ArgumentError: argument 1: : Don't know how to convert parameter 1 + ##else: + ## c_lib.free_buf(dbuf); ## ctypes.ArgumentError: argument 1: : Don't know how to convert parameter 1 + ### dbuf=None + if(I<20 or (I<1000 and I%20==0) or (I<10000 and I%200==0) or I%2000==0 ): + print("#test_alloc:%d.."%(I)) + ### del zbuf;zbuf=None + if(prtout): + fd1=open("test_zalloc.log","w") + for i in range(N1): + print("#%02d"%(i),file=fd1) + for j in range(N2): + strbuf="" + for k in range(N3): + strbuf+="%12.6f %12.6f "%(zbuf[i][j][k].real,zbuf[i][j][k].imag) + print(strbuf,file=fd1) + fd1.close() + + print("#test_alloc:DONE:%d %d,%d,%d"%(N4, N1,N2,N3)) + +def get_pp_nl01xx(cell, A_over_c, kpts=None): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); + if kpts is None: + assert False,"please set kpts explicitly.."; + kpts_lst = numpy.zeros((1,3)) + else: + kpts_lst = numpy.reshape(kpts, (-1,3)) + nkpts = len(kpts_lst) + fakecell, hl_blocks = fake_cell_vnl(cell) ## pyscf.pbc.gto.pseudo.pp_int + ## this invokes lib.calc_pbc_overlapsx and possiblly collects distributed results + ## [spdm+1,3,nKpoints,nCGTO_2,nCGTO_1,2] + ### Dbgtrace("#get_pp_nl01xx:calc_pp_overlapsxx start"); + ppnl_half = calc_pp_overlapsxx(cell,A_over_c,kpts_lst) # [1+3][N_col][nkpt][nBS2][nBS1] + + ### for dir in range(4): ## xxx xxx xxx + ### readwrite_xbuf('W',"calc_pp_overlapsxx_ppnl_half%02d.dat"%(dir), data=ppnl_half[dir])## xxx xxx xxx + + nao = cell.nao_nr() + buf1 = numpy.empty((3*9*nao), dtype=numpy.complex128) + buf2 = numpy.empty((3*9*nao), dtype=numpy.complex128) + + dbgng=False; ppnl_DBG=None + if(dbgng): + ppnl_DBG=numpy.zeros((3,nkpts,nao,nao), dtype=numpy.complex128) + Dbgng2=1 + ppnl = numpy.zeros((3,nkpts,nao,nao), dtype=numpy.complex128) + for dir in range(3): + ### Dbgtrace("#get_pp_nl01xx:calc_pp_overlapsxx dir:%d"%(dir)); + for k, kpt in enumerate(kpts_lst): + offset = [0] * 3 + for ib, hl in enumerate(hl_blocks): + ### Dbgtrace("#get_pp_nl01xx:calc_pp_overlapsxx dir,ib:%d,%d"%(dir,ib)); + l = fakecell.bas_angular(ib) + nd = 2 * l + 1 + hl_dim = hl.shape[0] + ilpO = numpy.ndarray((hl_dim,nd,nao), dtype=numpy.complex128, buffer=buf1) + ilpX = numpy.ndarray((hl_dim,nd,nao), dtype=numpy.complex128, buffer=buf2) + for i in range(hl_dim): + p0 = offset[i] + ilpO[i] = ppnl_half[0][i][k][p0:p0+nd] # [1+3][N_col][nkpt][nBS2][nBS1] -> [nd \in nBS2][nBS1] + ilpX[i] = ppnl_half[1+dir][i][k][p0:p0+nd] + offset[i] = p0 + nd + XhO=None;OhX=None + if(Dbgng2>1 or (Dbgng2==1 and k==0) ): + XhO= numpy.einsum('ilp,ij,jlq->pq', ilpX.conj(), hl, ilpO) + OhX= numpy.einsum('ilp,ij,jlq->pq', ilpO.conj(), hl, ilpX) + ## originally they are ppnlxx.log + printout_zmatrices(rttddft_common.get_job(True)+"_xVandVx.log",XhO,OhX,index=[dir,k],fopen=False) ## (dir==0 and ib==0 and i==0)) + ppnl[dir][k] += numpy.einsum('ilp,ij,jlq->pq', ilpX.conj(), hl, ilpO)\ + - numpy.einsum('ilp,ij,jlq->pq', ilpO.conj(), hl, ilpX) +### this is anti-Hermitian Array + +#DbgCode: see gto_ps_pp_int01_20220214DBG.py +# results : DBG_einsum.log ppnlx_%d_%03d_DIAG/OFD.log +# results show XhO or OhX summations are both non-zero but difference is ZERO.. ilpX[i][l][0] ilpO[i][l][4] +#000 004: 0 0 0 -0.000000 0.000000 -0.000000 0.000000 -0.000000 0.000000 0.000000 -0.000000 -14.277462 0.000000 0.000000 +#000 004: 0 0 1 -0.000000 -0.000000 -0.000000 0.000000 -0.000000 0.000000 0.000000 -0.000000 -14.277462 0.000000 0.000000 +#000 004: 0 0 2 0.000000 0.000005 0.000000 0.000005 0.000000 0.000005 0.029784 -0.000000 -14.277462 -0.000000 -0.000013 +# +# ilpX[i][l][4] ilpO[i][l][0] +#004 000: 0 0 0 -0.000000 -0.000000 -0.000000 -0.000000 -0.000000 -0.000000 0.000000 -0.000000 -14.277462 0.000000 0.000000 +#004 000: 0 0 1 -0.000000 0.000000 -0.000000 -0.000000 -0.000000 -0.000000 0.000000 -0.000000 -14.277462 0.000000 0.000000 +#004 000: 0 0 2 0.000000 -0.000005 0.000000 -0.000005 0.000000 -0.000005 -0.000000 0.000013 -14.277462 0.029784 0.000000 + + + if kpts is None or numpy.shape(kpts) == (3,): + ppnl = ppnl[0] + + if(dbgng): + n_call=rttddft_common.Countup("get_pp_nl01xx") + for dir in range(3): + fnm1="get_pp_nl01xx_%02d_ppnl.log"%(dir) + fd1=open(fnm1,('w' if(n_call==1) else 'a')) + fd2=open("get_pp_nl01xx_%02d_ilp.log"%(dir+1),('w' if(n_call==1) else 'a')) + for k, kpt in enumerate(kpts_lst): + print("#%06d %03d "%(n_call,k)+str(datetime.datetime.now()),file=fd1) + print("#%06d %03d "%(n_call,k)+str(datetime.datetime.now()),file=fd2) + for jj in range(nao): + strbuf=""; + for kk in range(nao): + strbuf+="%14.8f %14.8f "%( ppnl_DBG[dir][k][jj][kk].real, ppnl_DBG[dir][k][jj][kk].imag ) + print(strbuf,file=fd1) + print("\n\n",file=fd1) + + offset = [0] * 3 + for ib, hl in enumerate(hl_blocks): + str2="";str3="" + l = fakecell.bas_angular(ib) + nd = 2 * l + 1 + hl_dim = hl.shape[0] + for i in range(hl_dim): + p0 = offset[i] + str2+= str( ppnl_half[0][i][k][p0:p0+nd] )+" \t\t " + str3+= str( ppnl_half[1+dir][i][k][p0:p0+nd] )+" \t\t " + offset[i] = p0 + nd + print(str2,file=fd2); + print(str3+"\n",file=fd2); + fd1.close();fd2.close() + ### os.system("fopen "+fnm1); + ### Dbgtrace("#get_pp_nl01xx:calc_pp_overlapsxx dir:%d"%(dir)); + return ppnl + +def calc_pp_overlapsxx(cell,A_over_c,kpts, singlethread=None): + import math + import time + comm=MPI.COMM_WORLD + kvectors=numpy.reshape(kpts,(-1,3)) + nKpoints=len(kvectors) + MPIrank=comm.Get_rank();MPIsize=comm.Get_size() + Rnuc_au,Sy=parse_xyzstring(cell.atom,unit_BorA='B') + Nat_too_small=3 + Nat=len(Sy) + if( singlethread is None ): + singlethread = ( MPIsize < 2 or Nat <= Nat_too_small ) + if( MPIsize < 2 ): + singlethread = True + fncnme="calc_pp_overlapsxx";fncdepth=4 ## XXX XXX fncdepth ~ SCF:0 vhf:1 get_j:2 + Wctm000=time.perf_counter();Wctm010=Wctm000;N_call=rttddft_common.Countup(fncnme);dic1_timing={} ## XXX XXX + Dic_timing=rttddft_common.Dict_getv('timing_'+fncnme, default=None) ## XXX XXX + if( Dic_timing is None ): + rttddft_common.Dict_setv('timing_'+fncnme, {}); + Dic_timing=rttddft_common.Dict_getv('timing_'+fncnme, default=None) + if( singlethread ): + retv=calc_pp_overlapsxx1(cell, A_over_c, kpts, Rnuc_au, Sy, Rnuc_au, Sy) + ### Dbgtrace(".calc_pp_overlapsxx:singlethread returns.... ",flush=True); + Wctm020=Wctm010;Wctm010=time.perf_counter() # XXX XXX + update_dict(fncnme,dic1_timing,Dic_timing,"singlethread",Wctm010-Wctm020,depth=fncdepth) # XXX XXX + Wctm010=time.perf_counter() # XXX XXX + printout_dict(fncnme,dic1_timing,Dic_timing,Wctm010-Wctm000,depth=fncdepth) # XXX XXX + ### Dbgtrace(".calc_pp_overlapsxx:singlethread END",flush=True); + return retv + Nat_per_thread=int( math.ceil( Nat / float(MPIsize) ) ) + iatSTT= min( MPIrank*Nat_per_thread, Nat) + iatUPL= min( (MPIrank+1)*Nat_per_thread, Nat) + ppnl_half_sub=None; ncol_ppnl_half_sub=0 + if( iatSTT < iatUPL ): + Rnuc_sub=Rnuc_au[iatSTT:iatUPL] + Sy_sub=Sy[iatSTT:iatUPL] + ppnl_half_sub=calc_pp_overlapsxx1(cell, A_over_c, kpts, Rnuc_sub, Sy_sub, Rnuc_au, Sy ) + ### Dbgtrace(".calc_pp_overlapsxx:thread %d returns.... "%(MPIrank),flush=True); + ncol_ppnl_half_sub = len( ppnl_half_sub[0] ) + Wctm020=Wctm010;Wctm010=time.perf_counter() # XXX XXX + update_dict(fncnme,dic1_timing,Dic_timing,"multithread_ppnl",Wctm010-Wctm020,depth=fncdepth) # XXX XXX + + ## We have to recalculate matrix size(s) here + IZnuc=[ atomicsymbol_to_atomicnumber( Sy[i] ) for i in range(Nat) ] + alph,cofs,Ell,distinct_IZnuc,Nsh,Npgto,Npgto_sum,Nsh_sum=reorg_bset_infox(cell,Sy) + + ## nCGTO sizes + nCGTO1_A=[] + for r in range(MPIsize): + iatSTT= min( r*Nat_per_thread, Nat) + iatUPL= min( (r+1)*Nat_per_thread, Nat) + if( iatSTT < iatUPL ): + IZnuc_sub=IZnuc[iatSTT:iatUPL] + ## this applies IZnuc_sub + ncgto=count_nCGTO(IZnuc_sub,distinct_IZnuc,Nsh,Ell) + nCGTO1_A.append(ncgto) + else: + nCGTO1_A.append(0) + nCGTO1_sum=sum(nCGTO1_A) + nCGTO2_A=numpy.zeros([3], dtype='i') + ### Dbgtrace(".calc_pp_overlapsxx:collecting.... "+str(nCGTO1_A),flush=True); + for Icol in range(3): + if( (ppnl_half_sub is None) or (Icol >=ncol_ppnl_half_sub) ): + nCGTO2_A[Icol]=0 + else: + ndim=numpy.shape( ppnl_half_sub[0][Icol] ) + nCGTO2_A[Icol]=ndim[1] ## [0]:nKpoints [1]:nCGTO2 [2]:nCGTO1 + mpi_Bcast("calc_pp_overlapsxx.nCGTO2",nCGTO2_A,root=0) + + ## make ppnl_half [spdm+1,3,nKpoints,nCGTO_2,nCGTO_1] + ## out of chunks [spdm+1,3,nKpoints,nCGTO_2,nCGTO1_A[r]] + ppnl_half=[ [], [], [], [] ] + for dir in range(4): + for Icol in range(3): + if( nCGTO2_A[Icol] < 1 ): + continue + zbuf1=numpy.zeros( [ nKpoints, nCGTO2_A[Icol],nCGTO1_sum ],dtype=numpy.complex128) + ioff=0 + for r in range(MPIsize): + if( nCGTO1_A[r] < 1 ): + continue + iupl=ioff + nCGTO1_A[r] + if(r==0): + if(MPIrank==0): + zbuf1[:,:, ioff:iupl]=ppnl_half_sub[dir][Icol][:,:,0:nCGTO1_A[r]] + ### mpi_prtout_zbuf("zbuf1_%d_0"%(Icol)+"_%02d",zbuf1[:,:, ioff:iupl],description="[%d:%d)"%(ioff,iupl),Append=False) + ### mpi_prtout_zbuf("ppnl_half_sub_%d"%(Icol)+"_%02d",ppnl_half_sub[Icol],description="",Append=False) + else: + cwks=numpy.zeros([nKpoints, nCGTO2_A[Icol],nCGTO1_A[r]], dtype=numpy.complex128) + if( MPIrank==0 ): + comm.Recv(cwks, source=r, tag=( MPIsize*Icol + r )) + zbuf1[:,:,ioff:iupl] = cwks + ### mpi_prtout_zbuf("zbuf1_%d_%d"%(Icol,r)+"_%02d",zbuf1[:,:, ioff:iupl],description="[%d:%d)"%(ioff,iupl),Append=False) + + elif( MPIrank == r ): + comm.Send( numpy.array(ppnl_half_sub[dir][Icol]), dest=0, tag=( MPIsize*Icol + r )) + ### mpi_prtout_zbuf("ppnl_half_sub_%d_%d"%(Icol,r)+"_%02d",ppnl_half_sub[Icol],description="",Append=False) + + + ioff=iupl ## <<< never remove this >>> + ppnl_half[dir].append( zbuf1 ) ## up to 3 collection of [ nKpoints, nCGTO2_A[Icol],nCGTO1_sum ] + +## if( gto_ps_pp_int01_static.prtout_calc_pbc_overlaps_retv_ ): +## z1a=[] +## fdIN=open(gto_ps_pp_int01_static.fnme_prtout_calc_pbc_overlaps_retv_,"r") +## for line in fdIN: +## line=line.strip();le=len(line); +## if(le<1): +## continue +## if(line[0]=='#'): +## continue +## sA=line.split();nA=len(sA);assert nA%2==0,"";nZ=nA//2 +## for j in range(nZ): +## z1a.append( float(sA[2*j]) + 1j*float(sA[2*j+1]) ) +## fclose(fdIN) +## z1b=[] +## for Icol in range(3): +## nCGTO_i=nCGTOb_Array[Icol] +## if( nCGTO_i < 1 ): +## continue +## for kp in range(nKpoints): +## for j2 in range(nCGTOb_Array[Icol]): +## for k1 in range(nCGTO_1): +## z1b.append( zbuf[0][Icol][kp][j2][k1] ) +## dev=z1diff( z1a, z1b, "calc_pbc_overlapsxx") +## assert dev<1.0e-7,"" + return ppnl_half + +def calc_pp_overlapsxx1(cell, A_over_c, kpts, RnucAU_sub, Sy_sub, RnucAU_full, Sy_full): + #libname=pathlib.Path().absolute() / "libpp01.so" + #c_lib = ctypes.CDLL(libname) + c_lib = lib.load_library("libpp01") + + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); + + kvectors=numpy.reshape( kpts, (-1,3)) + nKpoints=len(kvectors) + kvecs=[] + for v in numpy.ravel(kvectors): + kvecs.append(v) + kvectors_1=( ctypes.c_double*(nKpoints*3) )(*kvecs) + + Nat_sub=len(Sy_sub) + IZnuc_sub=[]; + for i in range(Nat_sub): + IZnuc_sub.append( atomicsymbol_to_atomicnumber( Sy_sub[i] ) ) + Nat_full=len(Sy_full) + IZnuc_full=[]; + for i in range(Nat_full): + IZnuc_full.append( atomicsymbol_to_atomicnumber( Sy_full[i] ) ) + + bset_info=gen_bset_info(cell,IZnuc_sub) + + if( cell.exp_to_discard is not None ): + filtered =filter_by_exponent(bset_info, cell.exp_to_discard ) + bset_info=filtered + + ## + alph,cofs,Ell,distinctIZnuc_sub,Nsh,Npgto,Npgto_sum,Nsh_sum=reorg_bset_info(bset_info) + nDa_sub=len(bset_info) + + IZnuc_B=IZnuc_full.copy(); Nat_B=len(IZnuc_full) + alph_B=[];cofs_B=[];Nsh_B=[];NpGTO_B=[];ell_B=[] + distinct_IZnuc_B=[];N_cols=[];n_cum=0 + for symb in cell._pseudo: + n_th=0;n_cum=0 + distinct_IZnuc_B.append( atomicsymbol_to_atomicnumber(symb) ) + pp = cell._pseudo[symb] + nproj_types = pp[4] + nsh=0 + for l, (rl, nl, hl) in enumerate(pp[5:]): + n_th+=1;n_cum+=(2*l+1) + ### print("#ppshell_"+symb+":%d l=%d n_cum=%d"%(n_th,l,n_cum)) + if nl > 0: + alpha = .5 / rl**2 + alph_B.append(alpha); cofs_B.append(1.0); # for each pGTO + ell_B.append(l); NpGTO_B.append(1); nsh+=1; # for each shell + Nsh_B.append(nsh) # for each nDa_sub +# + n_call=Logger.Countup("pp_ncols"); + verbose_pp=(0 if(n_call!=1) else 2); verbose_pp=3; + print({"IZnuc_full":IZnuc_full, "distinct_IZnuc_B":distinct_IZnuc_B,"Nsh_B":Nsh_B}) + n_cols=get_ncols(cell,IZnuc_full,distinct_IZnuc_B,Nsh_B,title="pp_ncols",verbose=verbose_pp ) + n_cols=list_to_a1(n_cols) + BravisVectors= numpy.array( cell.a )/physicalconstants.BOHRinANGS +## note: cell.a this is given in ANGS unit... +## + ### print("#BravisVectors","");print(BravisVectors);### assert False,"" + spdm=3; + BravisVectors_1=( ctypes.c_double*(spdm*3) )( *numpy.ravel(BravisVectors) ) + Vectorfield_1=( ctypes.c_double*(3) )( *A_over_c ) + nKpoints=len(kpts);### print(kpts);print(nKpoints);### assert False,"" + + Npgto_sum_B=len(alph_B) + Nsh_sum_B=sum(Nsh_B) + nDa_B=len(distinct_IZnuc_B) + le=len(n_cols) + ncols_2=( ctypes.c_int*(le))(*n_cols) + RnucAU_sub =list(numpy.ravel(RnucAU_sub)) + Rnuc_1 =( ctypes.c_double*(3*Nat_sub) )(*RnucAU_sub) + IZnuc_1=( ctypes.c_int*(Nat_sub) )( *IZnuc_sub ) + Nsh_1 =( ctypes.c_int*(nDa_sub) )( *Nsh ) + Ell_1 =( ctypes.c_int*(Nsh_sum) )( *Ell ) + Npgto_1=( ctypes.c_int*(Nsh_sum) )(*Npgto) + distinct_IZnuc_1=( ctypes.c_int*(nDa_sub) )( *distinctIZnuc_sub ) + alph_1=( ctypes.c_double*(Npgto_sum) )(*alph) + cofs_1=( ctypes.c_double*(Npgto_sum) )(*cofs) + + nCGTO_1=count_nCGTO(IZnuc_sub,distinctIZnuc_sub,Nsh,Ell); nCGTO_1=int(nCGTO_1) + nCGTOb_Array=count_nCGTO(IZnuc_B,distinct_IZnuc_B,Nsh_B,ell_B,n_cols=n_cols,verbose=verbose_pp); + nCGTO_2=nCGTOb_Array[0] + nCGTO_2=int(nCGTO_2) + + IZnuc_2=( ctypes.c_int*(Nat_B) )( *IZnuc_B ) + RnucAU_full =list(numpy.ravel(RnucAU_full)) + Rnuc_2 =( ctypes.c_double*(3*Nat_full) )(*RnucAU_full) + + Nsh_2 =( ctypes.c_int*(nDa_B) )( *Nsh_B ) + Ell_2 =( ctypes.c_int*(Nsh_sum_B) )( *ell_B ) + Npgto_2=( ctypes.c_int*(Nsh_sum_B) )(*NpGTO_B) + distinct_IZnuc_2=( ctypes.c_int*(nDa_B) )( *distinct_IZnuc_B ) + alph_2=( ctypes.c_double*(Npgto_sum_B) )(*alph_B) + cofs_2=( ctypes.c_double*(Npgto_sum_B) )(*cofs_B) + Ndim_retv=[4,3,nKpoints,nCGTO_2,nCGTO_1,2] + + if( nKpoints*nCGTO_2*nCGTO_1 <=0 ): + assert nCGTO_2==0,"" + printout("zero dimension of PSP:"+str( [nKpoints,nCGTO_2,nCGTO_1] ),warning=1) + return [ [],[],[],[] ]; +# assert False,"%d %d %d"%(nKpoints,nCGTO_2,nCGTO_1) + ### kpts_lst = ( numpy.zeros((1,3)) if(kpts is None) else numpy.reshape(kpts, (-1,3)) ) + ### fakecell, hl_blocks = fake_cell_vnl(cell) + ### ppnl_half_o = _int_vnl(cell, fakecell, hl_blocks, kpts_lst) + ### printout("ppnl_half_o:SHAPE:"+str(numpy.shape(ppnl_half_o))+" /"+str( Ndim_retv ),flush=True) + ### printout("ppnl_half_o:VALS:"+str( ppnl_half_o ) ); + ### return ppnl_half_o + assert (nKpoints*nCGTO_2*nCGTO_1>0),"%d %d %d"%(nKpoints,nCGTO_2,nCGTO_1) + Lx=8;Ly=8;Lz=8 + piX2=6.283185307179586476925286766559 + Lj=[-1,-1,-1]; + for dir in range(3): + abs_aDOTk=[ abs(numpy.vdot(BravisVectors[dir],kvectors[j])) for j in range(nKpoints) ] + ceil_2pi_over_aDOTk=[ ( 1 if(abs_aDOTk[j]<1e-6) else int(math.ceil( piX2/abs_aDOTk[j])) ) for j in range(nKpoints) ] + Lj[dir]=max( ceil_2pi_over_aDOTk ) + ### fprintf(dbgfpath,"%02d:"%(dir)+str(abs_aDOTk)+" > "+str(ceil_2pi_over_aDOTk),Append=True) + Lx=Lj[0];Ly=Lj[1];Lz=Lj[2] + + fileIO=False;both=False + + key='calc_pbc_overlaps_output' + if( rttddft_common.Params_get(key) is not None ): + dum=rttddft_common.Params_get(key) + if( dum is not None): + if( dum == 'F' or dum=='f'): + fileIO=True;both=False + elif( dum=='B' or dum=='b'): + fileIO=True;both=True + elif( dum=='D' or dum=='d'): + fileIO=False;both=False + else: + assert False, key+":"+str(dum) + zbuf=None;zbuf_refr=None; + + n_call=rttddft_common.Countup("calc_pp_overlapsxx1"); + dbgng_libf01x=( n_call==1 or n_call==5) ## XXX XXX PLS. remove this in the expanse cluster ... + prtout_retv1=False; ## ( nc==1 ) + prtout_retv2=False; ## ( nc==1 ) + if( fileIO ): + filenumber=MPIrank + c_lib.calc_pbc_overlaps02x_f01( Nat_sub, Rnuc_1, IZnuc_1, nDa_sub, distinct_IZnuc_1, + Nsh_1, Ell_1, Npgto_1, alph_1, cofs_1, + Nat_full, Rnuc_2, IZnuc_2, nDa_B, distinct_IZnuc_2, + Nsh_2, Ell_2, ncols_2, Npgto_2, alph_2, + cofs_2,spdm, BravisVectors_1, Vectorfield_1, nKpoints, + kvectors_1, Lx, Ly, Lz, nCGTO_2, nCGTO_1, MPIrank, filenumber); + retf="calc_pbc_overlapsx_%03d.retf"%(filenumber) + retv=numpy.reshape( readwrite_xbuf('R',retf), [4,3,nKpoints,nCGTO_2,nCGTO_1]) + zbuf=[ [], [], [], [] ] + for dir in range(4): + for Icol in range(3): + nCGTO_i=nCGTOb_Array[Icol] + if( nCGTO_i<1 ): + continue + array=numpy.zeros([nKpoints,nCGTO_i,nCGTO_1],dtype=numpy.complex128) + for kp in range(nKpoints): + for j2 in range(nCGTOb_Array[Icol]): + for k1 in range(nCGTO_1): + array[kp][j2][k1] = retv[dir][Icol][kp][j2][k1] + zbuf[dir].append(array) + ### print_zbufs("calc_pp_overlapx",False,zbuf) ## TODO + if( dbgng_libf01x ): + filenumber=MPIrank+300; + c_lib.calc_pbc_overlaps02x_f( Nat_sub, Rnuc_1, IZnuc_1, nDa_sub, distinct_IZnuc_1, + Nsh_1, Ell_1, Npgto_1, alph_1, cofs_1, + Nat_full, Rnuc_2, IZnuc_2, nDa_B, distinct_IZnuc_2, + Nsh_2, Ell_2, ncols_2, Npgto_2, alph_2, + cofs_2,spdm, BravisVectors_1, Vectorfield_1, nKpoints, + kvectors_1, Lx, Ly, Lz, nCGTO_2, nCGTO_1, MPIrank, filenumber); + retf="calc_pbc_overlapsx_%03d.retf"%(filenumber) + retv_ref=numpy.reshape( readwrite_xbuf('R',retf), [4,3,nKpoints,nCGTO_2,nCGTO_1]) + zbuf_ref=[ [], [], [], [] ]; zbuf_diff=[] + for dir in range(4): + for Icol in range(3): + nCGTO_i=nCGTOb_Array[Icol] + if( nCGTO_i<1 ): + continue + array=numpy.zeros([nKpoints,nCGTO_i,nCGTO_1],dtype=numpy.complex128) + for kp in range(nKpoints): + for j2 in range(nCGTOb_Array[Icol]): + for k1 in range(nCGTO_1): + array[kp][j2][k1] = retv_ref[dir][Icol][kp][j2][k1] + zbuf_ref[dir].append(array) + zbuf_diff.append( aNmaxdiff( zbuf[dir][Icol], zbuf_ref[dir][Icol] ) ) + dev=max( zbuf_diff ); devTOL=1.0e-7 + if( dev >= devTOL or MPIrank==0 ): + print("#dbgng_libf01x:diff %e"%(dev)+str(zbuf_diff)) + assert dev absmax): + absmax=dum;at=[K,L];val=ppnl[I][J][K][L] + if( dum > TINY ): + nonzero+=1 + if( absmax > Absmax ): + Absmax=absmax;At=[I,J,at[0],at[1]];Val=val;Nonzero+=nonzero + if( maxdev > TINY ): + fnme=rttddft_common.get_job(True) + "_ppnlx.log"; fd1=open(fnme,"a"); + print("#check_ppnlx:nonzero matrix elmt:dir=%d,k=%03d: [%d][%d] %16.8f,%16.8f Nnonzero=%d"%(\ + At[0],At[1],At[2],At[3], Val.real,Val.imag, Nonzero),file=fd1); fd1.close() + fd1.close(); os.system("fopen "+fnme); +def check_xV(xV,dir,k,TINY=1e-7): + ## Hermicity of xV... part of ppnl[dir][k] [nAO][nAO] + Ndim=numpy.shape(xV);rank=len(Ndim); + if(rank!=2): + fd=open("pySCFwarning.log","w");print("check_xV:rank is not 2.. "+str(Ndim),file=fd);fd.close() + os.system("fopen pySCFwarning.log"); return + if(Ndim[0]!=Ndim[1]): + fd=open("pySCFwarning.log","w");print("check_xV:is not SQUARE.. "+str(Ndim),file=fd);fd.close() + os.system("fopen pySCFwarning.log"); return + maxdev=-1;at=None;vals=None + for I in range(Ndim[0]): + for J in range(I,Ndim[1]): + lhs=xV[I][J];rhs=xV[J][I].conj() + dev=abs(lhs-rhs) + if( dev > maxdev ): + maxdev=dev;at=[I,J]; vals=[lhs,rhs] + if( maxdev > TINY ): + fnme=rttddft_common.get_job(True) + "_xVVx.log"; fd1=open(fnme,"a"); + print("#check_xV:antiHermicity:dir=%d,k=%03d: %18.6e [%d][%d] %16.8f,%16.8f %16.8f,%16.8f"%(\ + dir,k,maxdev,at[0],at[1],vals[0].real,vals[0].imag, vals[1].real, vals[1].imag),file=fd1); fd1.close() + fd1.close(); os.system("fopen "+fnme); ## only in exceptional case (xVVx!=0) + return maxdev + +def printout_zmatrices(path,Mat1,Mat2,index,Append=False,fopen=False, Ndim_uplm=None): + def fnformat(arg1,arg2): + return "%14.8f,%14.8f %14.8f,%14.8f %16.6e"%(arg1.real,arg1.imag, arg2.real,arg2.imag, abs(arg1-arg2)) + + N_call=rttddft_common.Countup(path) + fd=open(path,("a" if(Append or N_call>1) else "w")) + Ndim=numpy.shape(Mat1);rank=len(Ndim) + Ia=numpy.zeros([rank],dtype=int) + strNdim_o=str(Ndim) + + if( Ndim_uplm is not None ): + rank_uplm=len(Ndim_uplm) + for j in range(rank_uplm): + Ndim[j]=min( Ndim[j], Ndim_uplm[j] ) + print("%s#%04d:%s Ndim:%s / %s"%( ("" if(N_call==1) else "\n\n\n"), (N_call-1), str(index), str(Ndim), strNdim_o ),file=fd) + else: + print("%s#%04d:%s Ndim:%s"%( ("" if(N_call==1) else "\n\n\n"), (N_call-1), str(index), strNdim_o ),file=fd) + + for Ia[0] in range(Ndim[0]): + if(rank==1): + print(" %3d:"%(Ia[0])+fnformat(Mat1[Ia[0]],Mat2[Ia[0]]),file=fd);continue + for Ia[1] in range(Ndim[1]): + if(rank==2): + print(" %3d,%3d:"%(Ia[0],Ia[1])+fnformat( Mat1[Ia[0]][Ia[1]],Mat2[Ia[0]][Ia[1]] ),file=fd);continue + for Ia[2] in range(Ndim[2]): + if(rank==3): + print(" %3d,%3d,%3d:"%(Ia[0],Ia[1],Ia[2])+fnformat( Mat1[Ia[0]][Ia[1]][Ia[2]],Mat2[Ia[0]][Ia[1]][Ia[2]] ),file=fd);continue + for Ia[3] in range(Ndim[3]): + if(rank==4): + print(" %3d,%3d,%3d,%3d:"%(Ia[0],Ia[1],Ia[2],Ia[3])+fnformat( Mat1[Ia[0]][Ia[1]][Ia[2]][Ia[3]],Mat2[Ia[0]][Ia[1]][Ia[2]][Ia[3]] ),file=fd);continue + for Ia[4] in range(Ndim[3]): + if(rank==5): + print(" %3d,%3d,%3d,%3d,%3d:"%(Ia[0],Ia[1],Ia[2],Ia[3],Ia[4])+fnformat( Mat1[Ia[0]][Ia[1]][Ia[2]][Ia[3]][Ia[4]],Mat2[Ia[0]][Ia[1]][Ia[2]][Ia[3]][Ia[4]] ),file=fd);continue + else: + assert False,"%d"%(rank)+str(Ndim) + fd.close() + if(fopen): + os.system("fopen "+path) + +def print_zbufs(name,Append,zbuf,fopen=False): + # zbuf[dir][Icol][kp][j2][k1] => FILE_Icol,kp: j2,k1,[0][1][2][3] ... + zbuf_0=zbuf[0]; + N_col=len(zbuf_0) + Ndim=numpy.shape(zbuf_0[0]); + nkpt=Ndim[0];nBS2=Ndim[1];nBS1=Ndim[2]; + fnmes=[] + for Icol in range(N_col): + for kp in range(nkpt): + fnme="%s_%d_%03d.dat"%(name,Icol,kp);fd=open(fnme,("a" if(Append) else "w")) + fnmes.append(fnme) + for j2 in range(nBS2): + for k1 in range(nBS1): + print(" %3d,%3d %16.8f,%16.8f %16.8f,%16.8f %16.8f,%16.8f %16.8f,%16.8f"%(\ + j2,k1, zbuf[0][Icol][kp][j2][k1].real,zbuf[0][Icol][kp][j2][k1].imag,\ + zbuf[1][Icol][kp][j2][k1].real,zbuf[1][Icol][kp][j2][k1].imag,\ + zbuf[2][Icol][kp][j2][k1].real,zbuf[2][Icol][kp][j2][k1].imag,\ + zbuf[3][Icol][kp][j2][k1].real,zbuf[3][Icol][kp][j2][k1].imag),file=fd) + fd.close() + if(fopen): + os.system("fopen "+fnmes[0]); + for F in fnmes: + os.system("ls -ltrh "+F) + + + + diff --git a/pyscf/rttddft/gto_ps_pp_int01_bf20210608.py b/pyscf/rttddft/gto_ps_pp_int01_bf20210608.py new file mode 100644 index 000000000..f98cf4039 --- /dev/null +++ b/pyscf/rttddft/gto_ps_pp_int01_bf20210608.py @@ -0,0 +1,945 @@ +#!/usr/bin/env python +# revision of pbc/gto/pseudo/pp_int.py +# +# Copyright 2014-2018 The PySCF Developers. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Author: Qiming Sun +# + +'''Analytic PP integrals. See also pyscf/pbc/gto/pesudo/pp.py + +For GTH/HGH PPs, see: + Goedecker, Teter, Hutter, PRB 54, 1703 (1996) + Hartwigsen, Goedecker, and Hutter, PRB 58, 3641 (1998) +''' + +import ctypes +import pathlib +import copy +import numpy +import os +import sys +import math +import scipy.special +from pyscf import lib +from pyscf import gto +import pathlib +from .filter_by_exponent import filter_by_exponent +from .futils import futils +from pyscf.pbc.gto.pseudo.pp_int import fake_cell_vnl, _int_vnl +from pyscf.pbc.df.aft import _get_pp_loc_part1 as get_pp_loc_part1 +from .utils import comp_zbufs,readwrite_xbuf,arrayclone,print_a2maxdiff,print_aNmatr,aNmaxdiff,print_Hmatrices,prtaNx2,atomicsymbol_to_atomicnumber,parse_xyzstring,write_file,read_zbuf,i1eqb,list_to_a1,gamma_hfint,atomicnumber_to_atomicsymbol +from pyscf.gto.mole import format_basis +import ctypes +from pyscf.pbc.gto.pseudo.pp_int import get_pp_nl +from pyscf.pbc.gto import pseudo +from numpy.ctypeslib import ndpointer +from .Logger import Logger +from .physicalconstants import physicalconstants +from .rttddft_common import rttddft_common +from .Loglv import printout +from mpi4py import MPI +import datetime +libpbc = lib.load_library('libpbc') + +def suppress_prtout(): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); + return ( MPIrank!=0 ) + + +def fprintf(fpath,text,Append=False,stdout=True): + if( suppress_prtout() ): + return + fd=open(fpath,('a' if(Append) else 'w')) + print(text,file=fd);fd.close() + if(stdout): + printout(text) +def print_kvectors(kvectors,BravaisVectors,fpath=None,Append=False): + PIx2=6.283185307179586476925286766559; + if( suppress_prtout() ): + return + fd=sys.stdout; + if(fpath is not None ): + fd=open(fpath,('a' if(Append) else 'w')) + ## B=numpy.transpose( numpy.linalg.inv(BravaisVectors) )*PIx2 + ## for I in range(3): + ## print("#check_BdotA:"+str( [ numpy.vdot(B[I],BravaisVectors[J]) for J in range(3) ] )) + Nv=len(kvectors) + print("#print_kvectors: Kx,Ky,Kz projection_to_Gvectors",file=fd); ## rank=0 only + for I in range(Nv): + print(" %03d: %9.4f %9.4f %9.4f %9.4f %9.4f %9.4f"%(I, kvectors[I][0],kvectors[I][1],kvectors[I][2], + numpy.vdot(kvectors[I],BravaisVectors[0])/PIx2, numpy.vdot(kvectors[I],BravaisVectors[1])/PIx2, + numpy.vdot(kvectors[I],BravaisVectors[2])/PIx2),file=fd ) ## rank=0 only + if( fpath is not None ): + fd.close() +def absmax_imaginary_part(zbuf): + buf=numpy.ravel( numpy.array(zbuf) ) + le=len(buf) + if(le<1): + return 0 + I=0; maxv=abs( buf[I].imag );at=I + for I in range(1,le): + dum=abs( buf[I].imag ) + if(dum>maxv): + maxv=dum;at=I + return maxv +def modify_normalization(zbuf,nCGTO_2A,nKpoints,nCGTO_1,n_cols, IZnuc_B,distinct_IZnuc,ell_B,alpha_B,Nsh): + # Input: zbuf[3][nKpoints][nCGTO_2A[:]][nCGTO_1] + # fix normalization + Nat=len(IZnuc_B) + nDa=len(distinct_IZnuc) + info=[] + norb_AL=[0,0,0] + nAO=0 + for Iat in range(Nat): + IZ=IZnuc_B[Iat] + for iDa in range(nDa): + if(distinct_IZnuc[iDa]==IZ): + break + assert (distinct_IZnuc[iDa]==IZ),"" + offset=0 + for jda in range(iDa): + offset+=Nsh[jda] + for ksh in range(Nsh[iDa]): + el=ell_B[offset+ksh] + alph=alpha_B[offset+ksh] + rLsqr=0.5/alph + norb=2*el+1 + + for m in range(-el,el+1): + info.append({"indx":"%d.%d.%d"%(Iat,iDa,ksh),"alph":alph,"l":el,"m":m,"n_cols":n_cols[offset+ksh]}) + ## + ## we now fix normalization... + ## + norb_AL[0]+=norb + for Icol in range(1,3): + if( nCGTO_2A[Icol]<1 ): + continue ## skip as if there is no input +# +# I normalized p^{l}_n by 1.0/[ sqrt(0.5 Gamma( (2l+4I+3)/2 )) * rL**(l+(4I+3)/2) ] +# but here pySCF expects it to be normalized by I=0 value +# so I multiply with sqrt( Gamma( (2l+4I+3)/2 )/Gamma( (2l+3)/2 ) )* rL**2I + if( Icol< n_cols[offset+ksh]): ## 1 < 2 etc. + fac=math.sqrt( gamma_hfint( 2*el+4*Icol+3 )/gamma_hfint( 2*el + 3) )*(rLsqr**Icol) + printout("#zbuf_%d:"%(Icol)+str(numpy.shape(zbuf[Icol]))) + printout("#iorb [%d:%d+%d) / %d:"%(norb_AL[Icol], norb_AL[Icol], norb, nCGTO_2A[Icol])) + for kp in range(nKpoints): + for kAO in range(norb): + for mu1 in range(nCGTO_1): + ### printout("%d %d %d %d"%(Icol,kp,norb_AL[Icol]+kAO,mu1),flush=True) + zbuf[Icol][kp][ norb_AL[Icol]+kAO ][mu1]*=fac + norb_AL[Icol] +=norb + ### fd=futils.fopen("modify_nrmz.log","w") ## fd.close @line 96 + fpath1="modify_nrmz.log"; ## fd.close @line 96 + printout(info,fpath=fpath1,Threads=[0],Append=False);### futils.fclose(fd); + + ### print("#check norb:"+str(norb_AL)+"/"+str(nCGTO_2A)) + assert ( norb_AL[0]==nCGTO_2A[0] and norb_AL[1]==nCGTO_2A[1] and + ( norb_AL[2]==0 or norb_AL[2]==nCGTO_2A[2])),"norb_AL:"+str(norb_AL) + return zbuf + +def count_nCGTO(IZnuc,distinct_IZnuc,Nsh,ell,n_cols=None,title=None,verbose=0): + # Nshell[iDa] + # Ell[iDa][jsh] + if( verbose > 0 ): + printout("#count_nCGTO:INPUT:Nsh="+str(Nsh)+" for distinct_IZnuc:"+str(distinct_IZnuc)) + retv=0 + nDa=len(distinct_IZnuc) + Ell=[] + ixj=0 + for iDa in range(nDa): + el_1=numpy.zeros([Nsh[iDa]],dtype=int) + for ksh in range(Nsh[iDa]): + el_1[ksh]=ell[ ixj + ksh ] + ixj+=Nsh[iDa] + + Ell.append( el_1 ) + + ret_Array=None + info=[]; + NshSUM=0 + Nat=len(IZnuc) + for iat in range(Nat): + IZ=IZnuc[iat] + for iDa in range(nDa): + if(IZ==distinct_IZnuc[iDa]): + break + assert (iDa1 ... + if(nco[kk]>Ico): + ret_Array[Ico]+=(2*Ell[iDa][kk]+1) + + NshSUM+=Nsh[iDa] + retv+=nOrb + ### printout("#Count_nCGTO:iat=%d iDa=%d nOrb=%d %d"%(iat,iDa,nOrb,retv)); + if( title is not None): + printout("#Count_nCGTO:shell_info:"+str(title)+":"+str(info)) + ### if( n_cols is not None): + ### le=len(n_cols) + ### assert (le==NshSUM),"len:%d / NshSUM:%d"%(le,NshSUM) + if(ret_Array is not None): + assert retv==ret_Array[0],"%d/%d"%(retv,ret_Array[0]) + if(n_cols is None): + return retv + else: + return ret_Array +def print_bset(IZnuc,distinct_IZnuc,Nsh,ell): + Nat=len(IZnuc) + Nsh_sum=sum(Nsh) + printout("#IZnuc:%d"%(len(IZnuc))) + +def gen_bset_info(cell,IZnuc): + ## generalization of format_basis({'Ti':'sto-3g','O':'sto-3g'}) .. + Nat=len(IZnuc) + if( isinstance(cell.basis,str) ): + dict={} + for iat in range(Nat): + Z=IZnuc[iat] + Sy=atomicnumber_to_atomicsymbol(Z) + dict.update({Sy:cell.basis}) + ### printout("gen_bset_info:INPUT:",end="");printout(dict) + ret=format_basis(dict) + ### printout("gen_bset_info:OUTPUT:",end="");printout(ret) + return ret + elif( isinstance(cell.basis,dict) ): + ### print("gen_bset_info:INPUT:",end="");print(cell.basis) + ret=format_basis(cell.basis) + ### print("gen_bset_info:OUTPUT:",end="");print(ret) + return ret + else: + assert False,"check cell.basis and its type.."+str(type(cell.basis))+" "+str(cell.basis) + return None + +def calc_pp_overlaps(cell,A_over_c,kpts): + #libname=pathlib.Path().absolute() / "libpp01.so" + #c_lib = ctypes.CDLL(libname) + c_lib = lib.load_library("libpp01") + + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); + + kvectors=numpy.reshape( kpts, (-1,3)) + nKpoints=len(kvectors) + kvecs=[] + for v in numpy.ravel(kvectors): + kvecs.append(v) + kvectors_1=( ctypes.c_double*(nKpoints*3) )(*kvecs) + ### print(kvectors_1) + IZnuc=[]; + Rnuc_au,Sy=parse_xyzstring(cell.atom,unit_BorA='B') + Nat=len(Sy) + IZnuc=[]; + for i in range(Nat): + IZnuc.append( atomicsymbol_to_atomicnumber( Sy[i] ) ) + bset_info=gen_bset_info(cell,IZnuc) + + if( cell.exp_to_discard is not None ): + filtered =filter_by_exponent(bset_info, cell.exp_to_discard ) + bset_info=filtered + + ### bset_info=format_basis({'Ti':'sto-3g','O':'sto-3g'}) + distinct_IZnuc=[] + nDa=len(bset_info) + alph=[];cofs=[]; + Nsh=[]; Npgto_sum=0 + Npgto=[] + Ell=[] + for A in bset_info: + infoA=bset_info[A]; + nsh1=len(infoA) + + distinct_IZnuc.append( atomicsymbol_to_atomicnumber(A) ) + for jsh in range(nsh1): + shell=infoA[jsh] + el=shell[0]; Ell.append(el); + npgto=0; alpha_col2=None; cofs_col2=None; alpha_col3=None; cofs_col3=None + alpha_col4=None; cofs_col4=None; alpha_col5=None; cofs_col5=None; alpha_col6=None; cofs_col6=None + alpha_col7=None; cofs_col7=None; alpha_col8=None; cofs_col8=None + for j in range(1,len(shell)): + row=shell[j] + alph.append(row[0]);cofs.append(row[1]);npgto+=1 + if(len(row)>2): + if(len(row)>=3): + if( alpha_col2 is None): + alpha_col2=[]; cofs_col2=[] + alpha_col2.append(row[0]);cofs_col2.append(row[2]); + if(len(row)>=4): + if( alpha_col3 is None): + alpha_col3=[]; cofs_col3=[] + alpha_col3.append(row[0]);cofs_col3.append(row[3]); + if(len(row)>=5): + if( alpha_col4 is None): + alpha_col4=[]; cofs_col4=[] + alpha_col4.append(row[0]);cofs_col4.append(row[4]); + if(len(row)>=6): + if( alpha_col5 is None): + alpha_col5=[]; cofs_col5=[] + alpha_col5.append(row[0]);cofs_col5.append(row[5]); + if(len(row)>=7): + if( alpha_col6 is None): + alpha_col6=[]; cofs_col6=[] + alpha_col6.append(row[0]);cofs_col6.append(row[6]); + if(len(row)>=8): + if( alpha_col7 is None): + alpha_col7=[]; cofs_col7=[] + alpha_col7.append(row[0]);cofs_col7.append(row[7]); + if(len(row)>=9): + if( alpha_col8 is None): + alpha_col8=[]; cofs_col8=[] + alpha_col8.append(row[0]);cofs_col8.append(row[8]); + if(len(row)>=10): + assert False,"unimplemnted" + + Npgto.append(npgto); Npgto_sum+=npgto + if( alpha_col2 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_2=len(alpha_col2) + Npgto.append(npgto_2) + for k in range(npgto_2): + ### print("#adding to alph:%d %f"%(k,alpha_col2[k])) + alph.append( alpha_col2[k] ) + cofs.append( cofs_col2[k] ) + nsh1+=1; Npgto_sum+=npgto_2 + if( alpha_col3 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_3=len(alpha_col3) + Npgto.append(npgto_3) + for k in range(npgto_3): + alph.append( alpha_col3[k] ) + cofs.append( cofs_col3[k] ) + nsh1+=1; Npgto_sum+=npgto_3 + + if( alpha_col4 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_4=len(alpha_col4) + Npgto.append(npgto_4) + for k in range(npgto_4): + alph.append( alpha_col4[k] ) + cofs.append( cofs_col4[k] ) + nsh1+=1; Npgto_sum+=npgto_4 + if( alpha_col5 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_5=len(alpha_col5) + Npgto.append(npgto_5) + for k in range(npgto_5): + alph.append( alpha_col5[k] ) + cofs.append( cofs_col5[k] ) + nsh1+=1; Npgto_sum+=npgto_5 + if( alpha_col6 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_6=len(alpha_col6) + Npgto.append(npgto_6) + for k in range(npgto_6): + alph.append( alpha_col6[k] ) + cofs.append( cofs_col6[k] ) + nsh1+=1; Npgto_sum+=npgto_6 + if( alpha_col7 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_7=len(alpha_col7) + Npgto.append(npgto_7) + for k in range(npgto_7): + alph.append( alpha_col7[k] ) + cofs.append( cofs_col7[k] ) + nsh1+=1; Npgto_sum+=npgto_7 + if( alpha_col8 is not None): + Ell.append(el); ## Ell[\sum Nsh[:]] + npgto_8=len(alpha_col8) + Npgto.append(npgto_8) + for k in range(npgto_8): + alph.append( alpha_col8[k] ) + cofs.append( cofs_col8[k] ) + nsh1+=1; Npgto_sum+=npgto_8 + Nsh.append(nsh1); + Nsh_sum=sum(Nsh) + + IZnuc_B=IZnuc.copy(); Nat_B=len(IZnuc_B) + alph_B=[];cofs_B=[];Nsh_B=[];NpGTO_B=[];ell_B=[] + distinct_IZnuc_B=[];N_cols=[];n_cum=0 + for symb in cell._pseudo: + n_th=0;n_cum=0 + distinct_IZnuc_B.append( atomicsymbol_to_atomicnumber(symb) ) + pp = cell._pseudo[symb] + nproj_types = pp[4] + nsh=0 + for l, (rl, nl, hl) in enumerate(pp[5:]): + n_th+=1;n_cum+=(2*l+1) + ### print("#ppshell_"+symb+":%d l=%d n_cum=%d"%(n_th,l,n_cum)) + if nl > 0: + alpha = .5 / rl**2 + alph_B.append(alpha); cofs_B.append(1.0); # for each pGTO + ell_B.append(l); NpGTO_B.append(1); nsh+=1; # for each shell + Nsh_B.append(nsh) # for each nDa +#ppshell_Ti:1 l=0 n_cum=1 +#ppshell_Ti:2 l=1 n_cum=4 +#ppshell_Ti:3 l=2 n_cum=9 +#ppshell_O:1 l=0 n_cum=1 +#ppshell_O:2 l=1 n_cum=4 +# + n_call=Logger.Countup("pp_ncols"); + verbose_pp=(0 if(n_call!=1) else 2) + n_cols=get_ncols(cell,IZnuc,distinct_IZnuc_B,Nsh_B,title="pp_ncols",verbose=verbose_pp ) + n_cols=list_to_a1(n_cols) + BravisVectors= numpy.array( cell.a )/physicalconstants.BOHRinANGS +## note: cell.a this is given in ANGS unit... +## + ### print("#BravisVectors","");print(BravisVectors);### assert False,"" + spdm=3; + BravisVectors_1=( ctypes.c_double*(spdm*3) )( *numpy.ravel(BravisVectors) ) + Vectorfield_1=( ctypes.c_double*(3) )( *A_over_c ) + nKpoints=len(kpts);### print(kpts);print(nKpoints);### assert False,"" + + Npgto_sum_B=len(alph_B) + Nsh_sum_B=sum(Nsh_B) + nDa_B=len(distinct_IZnuc_B) + le=len(n_cols) + ncols_2=( ctypes.c_int*(le))(*n_cols) + Rnuc_au =list(numpy.ravel(Rnuc_au)) + Rnuc_1 =( ctypes.c_double*(3*Nat) )(*Rnuc_au) + IZnuc_1=( ctypes.c_int*(Nat) )( *IZnuc ) + Nsh_1 =( ctypes.c_int*(nDa) )( *Nsh ) + Ell_1 =( ctypes.c_int*(Nsh_sum) )( *Ell ) + Npgto_1=( ctypes.c_int*(Nsh_sum) )(*Npgto) + distinct_IZnuc_1=( ctypes.c_int*(nDa) )( *distinct_IZnuc ) + alph_1=( ctypes.c_double*(Npgto_sum) )(*alph) + cofs_1=( ctypes.c_double*(Npgto_sum) )(*cofs) + + nCGTO_1=count_nCGTO(IZnuc,distinct_IZnuc,Nsh,Ell); nCGTO_1=int(nCGTO_1) + nCGTOb_Array=count_nCGTO(IZnuc_B,distinct_IZnuc_B,Nsh_B,ell_B,n_cols=n_cols,verbose=verbose_pp); + nCGTO_2=nCGTOb_Array[0] + ### print(nCGTO_1,end="");print(nCGTO_1) + ### print(nCGTO_1,end="");print(type(nCGTO_1)) + + ### print(nCGTO_2,end="");print(nCGTO_2) + ### print(nCGTO_2,end="");print(type(nCGTO_2)) + nCGTO_2=int(nCGTO_2) +### nCGTO_2=count_nCGTO(IZnuc_B,distinct_IZnuc_B,Nsh_B,ell_B,n_cols=n_cols,title="pseudo");nCGTO_2=int(nCGTO_2) + + IZnuc_2=( ctypes.c_int*(Nat_B) )( *IZnuc_B ) + Nsh_2 =( ctypes.c_int*(nDa_B) )( *Nsh_B ) + Ell_2 =( ctypes.c_int*(Nsh_sum_B) )( *ell_B ) + Npgto_2=( ctypes.c_int*(Nsh_sum_B) )(*NpGTO_B) + distinct_IZnuc_2=( ctypes.c_int*(nDa_B) )( *distinct_IZnuc_B ) + alph_2=( ctypes.c_double*(Npgto_sum_B) )(*alph_B) + cofs_2=( ctypes.c_double*(Npgto_sum_B) )(*cofs_B) + Ndim_retv=[3,nKpoints,nCGTO_2,nCGTO_1,2] + + if( nKpoints*nCGTO_2*nCGTO_1 <=0 ): + printout("zero dimension of PSP:"+str( [nKpoints,nCGTO_2,nCGTO_1] ),warning=1) + kpts_lst = ( numpy.zeros((1,3)) if(kpts is None) else numpy.reshape(kpts, (-1,3)) ) + fakecell, hl_blocks = fake_cell_vnl(cell) + ppnl_half_o = _int_vnl(cell, fakecell, hl_blocks, kpts_lst) + printout("ppnl_half_o:SHAPE:"+str(numpy.shape(ppnl_half_o))+" /"+str( Ndim_retv ),flush=True) + printout("ppnl_half_o:VALS:"+str( ppnl_half_o ) ); + return ppnl_half_o + assert (nKpoints*nCGTO_2*nCGTO_1>0),"%d %d %d"%(nKpoints,nCGTO_2,nCGTO_1) + Lx=20;Ly=20;Lz=20 + Lx=8;Ly=8;Lz=8 + piX2=6.283185307179586476925286766559 + Lj=[-1,-1,-1]; + dbgng_Lx=True; dbgfpath="Lx_for_FT.log" + if( dbgng_Lx ): + print_kvectors(kvectors,BravisVectors,fpath=dbgfpath) + for dir in range(3): + abs_aDOTk=[ abs(numpy.vdot(BravisVectors[dir],kvectors[j])) for j in range(nKpoints) ] + ceil_2pi_over_aDOTk=[ ( 1 if(abs_aDOTk[j]<1e-6) else int(math.ceil( piX2/abs_aDOTk[j])) ) for j in range(nKpoints) ] + Lj[dir]=max( ceil_2pi_over_aDOTk ) + fprintf(dbgfpath,"%02d:"%(dir)+str(abs_aDOTk)+" > "+str(ceil_2pi_over_aDOTk),Append=True) + Lx=Lj[0];Ly=Lj[1];Lz=Lj[2] + + fileIO=False;both=False + key='calc_pbc_overlaps_output' + dum=rttddft_common.Params_get(key) + if( dum is not None): + if( dum == 'F' or dum=='f'): + fileIO=True;both=False + elif( dum=='B' or dum=='b'): + fileIO=True;both=True + elif( dum=='D' or dum=='d'): + fileIO=False;both=False + else: + assert False, key+":"+str(dum) + zbuf=None;zbuf_refr=None; + + ### nc=get_pp_nl01_static.Countup(fnme) + prtout_retv1=False; ## ( nc==1 ) + prtout_retv2=False; ## ( nc==1 ) + if( fileIO ): + filenumber=MPIrank+100 + c_lib.calc_pbc_overlaps_f( Nat, Rnuc_1, IZnuc_1, nDa, distinct_IZnuc_1, + Nsh_1, Ell_1, Npgto_1, alph_1, cofs_1, + Nat, Rnuc_1, IZnuc_2, nDa_B, distinct_IZnuc_2, + Nsh_2, Ell_2, ncols_2, Npgto_2, alph_2, + cofs_2,spdm, BravisVectors_1, Vectorfield_1, nKpoints, + kvectors_1, Lx, Ly, Lz, nCGTO_2, nCGTO_1, MPIrank,filenumber); + retf="calc_pbc_overlaps_%03d.retf"%(filenumber) + retv=numpy.reshape( readwrite_xbuf('R',retf), [3,nKpoints,nCGTO_2,nCGTO_1]) + zbuf=[] + for Icol in range(3): + nCGTO_i=nCGTOb_Array[Icol] + if( nCGTO_i<1 ): + continue + array=numpy.zeros([nKpoints,nCGTO_i,nCGTO_1],dtype=numpy.complex128) + for kp in range(nKpoints): + for j2 in range(nCGTOb_Array[Icol]): + for k1 in range(nCGTO_1): + array[kp][j2][k1] = retv[Icol][kp][j2][k1] + zbuf.append(array) + + if(both): + zbuf_refr=[ arrayclone(zbuf[J]) for J in range( len(zbuf) ) ] + + if(not fileIO or both): + c_lib.calc_pbc_overlaps02.restype= ndpointer(dtype=ctypes.c_double,shape=Ndim_retv ) + print("#clib:restype:Ndim_retv:"+str(Ndim_retv)); + ### Here is alternative choice: parameters are handed over files + write_file("calc_pbc_overlaps01.in", Nat,Rnuc_au,IZnuc,nDa,distinct_IZnuc, + Nsh, numpy.ravel(Ell), numpy.ravel(Npgto) ,numpy.ravel(alph),numpy.ravel(cofs), + Nat, numpy.ravel(Rnuc_au),numpy.ravel(IZnuc_B),nDa_B, + numpy.ravel(distinct_IZnuc_B), Nsh_B, numpy.ravel(ell_B), n_cols, NpGTO_B, + alph_B, cofs_B, spdm, numpy.ravel(BravisVectors), A_over_c, + nKpoints, kvecs, Lx, Ly, Lz, + nCGTO_2, nCGTO_1) + ### os.system("./testread.x"); + ### zbuf=read_zbuf("calc_pbc_overlaps.dat") + + dbuf=c_lib.calc_pbc_overlaps02( Nat, Rnuc_1, IZnuc_1, nDa, distinct_IZnuc_1, + Nsh_1, Ell_1, Npgto_1, alph_1, cofs_1, + Nat, Rnuc_1, IZnuc_2, nDa_B, distinct_IZnuc_2, + Nsh_2, Ell_2, ncols_2, Npgto_2, alph_2, + cofs_2,spdm, BravisVectors_1, Vectorfield_1, nKpoints, + kvectors_1, Lx, Ly, Lz, nCGTO_2, nCGTO_1, MPIrank) + + if(prtout_retv1): # xxx xxx remove after debugging xxx xxx + for Icol in range(3): + #str_AoverC=("0" if( abs(A_over_c[0])<1.0e-7) else ("%6.3f"%(A_over_c[0])).strip() )+"_"+\ + # ("0" if( abs(A_over_c[1])<1.0e-7) else ("%6.3f"%(A_over_c[1])).strip() )+"_"+\ + # ("0" if( abs(A_over_c[2])<1.0e-7) else ("%6.3f"%(A_over_c[2])).strip() ) + fnme="calc_pbc_overlaps_bf20210608"; ##+str_AoverC + fpath01=fnme+"I%d.dat"%(Icol); + fd=futils.fopen(fpath01,"w") ## OK + print("#A_over_c:%f,%f,%f"%(A_over_c[0],A_over_c[1],A_over_c[2]),file=fd); + for kp in range(nKpoints): + print("#%03d:K=%d\n"%(kp,kp),file=fd); + for j2 in range(nCGTO_2): + string="" + for k1 in range(nCGTO_1): + string+="%12.6f %12.6f "%(dbuf[Icol][kp][j2][k1][0],dbuf[Icol][kp][j2][k1][1]) + print(string,file=fd); + ### print("%d %d %d %d %f %f"%(Icol,kp,j2,k1,dbuf[Icol][kp][j2][k1][0],dbuf[Icol][kp][j2][k1][1]),file=fd) + futils.fclose(fd); + ### os.system("fopen "+fpath01); + zbuf=[] + for Icol in range(3): + nCGTO_i=nCGTOb_Array[Icol] + if( nCGTO_i<1 ): + continue + array=numpy.zeros([nKpoints,nCGTO_i,nCGTO_1],dtype=numpy.complex128) + for kp in range(nKpoints): + for j2 in range(nCGTOb_Array[Icol]): + for k1 in range(nCGTO_1): + array[kp][j2][k1] = dbuf[Icol][kp][j2][k1][0] + 1j*dbuf[Icol][kp][j2][k1][1] + zbuf.append(array) + ## print("calc_pbc_overlaps:direct IO:"+str(zbuf[0][0][0][0])) + + if(both): + leL=len(zbuf);leR=len(zbuf_refr);le=min(leL,leR) + devs=[];maxdev=-1; + for J in range(le): + dev1=aNmaxdiff(zbuf[J],zbuf_refr[J]); + devs.append(dev1);maxdev=max(maxdev,dev1) + + if(maxdev>=1.0e-6): + comp_zbufs(zbuf,zbuf_refr,"comp_pbc_overlaps.diff",Append=False,description="zbuf,zbuf_refr") + + assert maxdev<1.0e-6,"maxdev=%e"%(maxdev) + + # fdDBG=open("comp_pbc_overlaps.dat","a") + # print("maxdev:%e "%(maxdev)+str(devs),file=fdDBG) + # fdDBG.close(); + # readwrite_xbuf('W',"comp_pbc_overlaps_LHS.dat",data=zbuf) + # readwrite_xbuf('W',"comp_pbc_overlaps_RHS.dat",data=zbuf_refr) + + zbuf=modify_normalization(zbuf,nCGTOb_Array,nKpoints,nCGTO_1,n_cols, IZnuc,distinct_IZnuc_B,ell_B,alph_B,Nsh_B) + if(prtout_retv2): + fd=futils.fopen("calc_pbc_overlaps_pyretv.dat","w")#OK + for Icol in range(3): + nCGTO_i=nCGTOb_Array[Icol] + if( nCGTO_i < 1 ): + continue + print("###%d %d %d"%(nKpoints,nCGTOb_Array[Icol],nCGTO_1),file=fd) + for kp in range(nKpoints): + for j2 in range(nCGTOb_Array[Icol]): + print("#%d,%d,%d:\t "%(Icol,kp,j2),file=fd) + for k1 in range(nCGTO_1): + print("%16.8f j%16.8f "%( zbuf[Icol][kp][j2][k1].real, zbuf[Icol][kp][j2][k1].imag ),file=fd) + futils.fclose(fd); + return zbuf + +def with_df_get_pp(mydf,A_over_c,kpts=None): + import time + from .update_dict import printout_dict,update_dict + + ## Copy of pyscf.pbc.df.aft.py --- + '''Get the periodic pseudotential nuc-el AO matrix, with G=0 removed. + ''' + idbgng=0 # XXX XXX + diff_ZF_to_fF=False + + # fncnme|fncdepth|Wctm000|Wctm010|N_call|Dic_timing|dic1_timing + fncnme="with_df_get_pp";fncdepth=3 ## fncdepth ~ SCF:0 vhf:1 get_j:2 XXX XXX + Wctm000=time.time();Wctm010=Wctm000;dic1_timing={} # XXX XXX + Dic_timing=rttddft_common.Dict_getv('timing_'+fncnme, default=None) # XXX XXX + if( Dic_timing is None ): + rttddft_common.Dict_setv('timing_'+fncnme, {}); # XXX XXX + Dic_timing=rttddft_common.Dict_getv('timing_'+fncnme, default=None) # XXX XXX + + N_call=rttddft_common.Countup("with_df_get_pp"); + n_call=N_call +### n_call=rttddft_common.Countup("with_df_get_pp") + cell = mydf.cell + if kpts is None: + assert False,"please set kpts explicitly.."; + kpts_lst = numpy.zeros((1,3)) + else: + kpts_lst = numpy.reshape(kpts, (-1,3)) + nkpts = len(kpts_lst) + + vloc1 = get_pp_loc_part1(mydf, kpts_lst) + Wctm020=Wctm010;Wctm010=time.time() # XXX XXX + update_dict(fncnme,dic1_timing,Dic_timing,"get_pp_loc_part1",Wctm010-Wctm020,depth=fncdepth) # XXX XXX + + vloc2 = pseudo.pp_int.get_pp_loc_part2(cell, kpts_lst) + Wctm020=Wctm010;Wctm010=time.time() # XXX XXX + update_dict(fncnme,dic1_timing,Dic_timing,"get_pp_loc_part2",Wctm010-Wctm020,depth=fncdepth) # XXX XXX + + vpp_org=None;vpp_ZF=None + if( (idbgng > 0) and (n_call==1 or n_call==20 or n_call==200) ): + vpp_org = pseudo.pp_int.get_pp_nl(cell, kpts_lst) + + zerovec=[ 0.0, 0.0, 0.0] + vpp_ZF= get_pp_nl01(cell, zerovec, kpts_lst) + if(idbgng>1): + dev=-1 + for kp in range(nkpts): + diff=print_a2maxdiff(vpp_org[kp],vpp_ZF[kp], + "validate_get_pp_nl01_"+str(rttddft_common.get_job(True))+".rcd", + Append=(kp>0 or n_call>1), + description="ZF pp (lhs:mine,rhs:pySCForg) n_call=%d kp=%02d/%2d"%(n_call,kp,nkpts)) + dev=max(diff,dev) + else: + dev=aNmaxdiff(vpp_org,vpp_ZF,comment="vpp",verbose=True,title="vpp_ZF") + assert (dev<1.0e-6),"diff=%e"%(dev) + ### print("vloc1;",end="");print( numpy.shape(vloc1)) ## vloc1;(8, 56, 56) + ### print("vloc2;",end="");print( numpy.shape(vloc2)) ## vloc1;(8, 56, 56) + ### print("vpp_org;",end="");print( numpy.shape(vpp_org)) ## (8, 56, 56) + + vpp = get_pp_nl01(cell, A_over_c, kpts_lst) + Wctm020=Wctm010;Wctm010=time.time() # XXX XXX + update_dict(fncnme,dic1_timing,Dic_timing,"get_pp_nl01",Wctm010-Wctm020,depth=fncdepth) # XXX XXX + if( diff_ZF_to_fF and (vpp_org is not None) ): + abs_AoverC=numpy.sqrt( A_over_c[0]**2 + A_over_c[1]**2 + A_over_c[2]**2 ) + if(abs_AoverC>1.0e-6): + n1=rttddft_common.Countup("with_df_get_pp.diff_ZF_to_fF") + if(n1==1): + diff=aNmaxdiff(vpp,vpp_org,comment="vpp/vpp_org",verbose=True,title="vpp") + print_Hmatrices("vpp",vpp,vpp_org,fpath="vpp_and_vppZF.dat") + + for k in range(nkpts): + vpp[k] += vloc1[k] + vloc2[k] + + if kpts is None or numpy.shape(kpts) == (3,): + vpp = vpp[0] + Wctm010=time.time() # XXX XXX + printout_dict(fncnme,dic1_timing,Dic_timing,Wctm010-Wctm000,depth=fncdepth) # XXX XXX + + return vpp + +class get_pp_nl01_static: + count=0 + Dict_={} + @staticmethod + def Countup(key,inc=True): + if( key not in get_pp_nl01_static.Dict_ ): + get_pp_nl01_static.Dict_.update({key:0}); + if( inc ): + get_pp_nl01_static.Dict_[key]+=1 + return get_pp_nl01_static.Dict_[key] + +def get_pp_nl01(cell, A_over_c, kpts=None): + ### fd01=open("get_pp_nl01_dbg.log","w");print("start:"+str( datetime.datetime.now() ),file=fd01);fd01.close() + + Logger.write_once(None,"get_pp_nl01:calc_pp_overlaps","calculate pp for A="+str(A_over_c)) + if kpts is None: + assert False,"please set kpts explicitly.."; + kpts_lst = numpy.zeros((1,3)) + else: + kpts_lst = numpy.reshape(kpts, (-1,3)) + nkpts = len(kpts_lst) + + fakecell, hl_blocks = fake_cell_vnl(cell) ## pyscf.pbc.gto.pseudo.pp_int + dbgng=1;strict=1; + if(dbgng>0): + get_pp_nl01_static.count=get_pp_nl01_static.count+1 + if( get_pp_nl01_static.count==1 or get_pp_nl01_static.count==20): + ppnl_half_o = _int_vnl(cell, fakecell, hl_blocks, kpts_lst) + fd001=open("ppnl_half_o_01.log","w"); + print("#ppnl_half_o:"+str(datetime.datetime.now()),file=fd001); + ### print(ppnl_half_o,file=fd001);### fd001.close() + print( len(ppnl_half_o),file=fd001 ); + for I in range( len(ppnl_half_o) ): + print(numpy.shape(ppnl_half_o[I]),file=fd001) + ## (1, 72, 180), (1, 16, 180), (1, 4, 180) ... so this cannot be treated as ndarray + ## whereas A[0],A[1],A[2] are ndarrays + fd001.close() + ### xxx 20210531 printout("#ppnl_half:"+str(numpy.shape(ppnl_half_o))) never use shape or ravel + ### xxx 20210531 ppnl_half_o = numpy.ravel(ppnl_half_o) + datf01="ppnl_half.dat" + if( not suppress_prtout() ): + fd=futils.fopen(datf01,("w" if(get_pp_nl01_static.count==1) else "a")) ## OK + for col in ppnl_half_o: + line="" + print("#"+str(numpy.shape(col)),file=fd) + for y in numpy.ravel(col): + line+=str(y) + print(line,file=fd) + futils.fclose(fd); + #print("#ppnl_half_ZF:",end=""); print(numpy.shape(ppnl_half_o)) xxx never apply np.shape to ppnl_half + #for X in ppnl_half_o: + # print("#ppnl_half_ZF:",end="");print(numpy.shape(X)) + ppnl_half_ZF = calc_pp_overlaps(cell,[0,0,0],kpts_lst) ## New subroutine + comp_datf="ppnl_half_comp_%02d.dat"%(get_pp_nl01_static.count) + if( not suppress_prtout() ): + fd=futils.fopen(comp_datf,"w") ## OK + maxdev=-1;vals=[];Ndev=0 + for Icol in range(3): + Ndim2=numpy.shape(ppnl_half_o[Icol]); ### print("#%d:shape:"%(Icol),end="");print(Ndim2) + if(Ndim2[0]<1): + continue + Ndim1=numpy.shape(ppnl_half_ZF[Icol]);### print("#%d:shape:"%(Icol),end="");print(Ndim1) + Ndim=[ min( Ndim1[0], Ndim2[0]), min( Ndim1[1], Ndim2[1]), min( Ndim1[2], Ndim2[2]) ] + for Kp in range( Ndim[0] ): + for j2 in range(Ndim[1]): + for k1 in range(Ndim[2]): + dev=abs( ppnl_half_ZF[Icol][Kp][j2][k1] - ppnl_half_o[Icol][Kp][j2][k1] ) + if(dev>maxdev): + maxdev=dev; vals=[ ppnl_half_ZF[Icol][Kp][j2][k1], ppnl_half_o[Icol][Kp][j2][k1] ]; + if(dev<1.0e-6): + print("## ",end="",file=fd) + else: + Ndev+=1 + ratio=ppnl_half_ZF[Icol][Kp][j2][k1]/(1.0 if( abs(ppnl_half_o[Icol][Kp][j2][k1])<1.0e-20 ) else ppnl_half_o[Icol][Kp][j2][k1]); + print("%d %d %d %d %f+j%f %f+j%f %e val/ref=%14.8f + j%14.8f"%(Icol,Kp,j2,k1, + ppnl_half_ZF[Icol][Kp][j2][k1].real, ppnl_half_ZF[Icol][Kp][j2][k1].imag, + ppnl_half_o[Icol][Kp][j2][k1].real, ppnl_half_o[Icol][Kp][j2][k1].imag, dev, + ratio.real, ratio.imag),file=fd) + fd2=futils.fopen("comp_vals.dat",("w" if(Kp==0 and Icol==0) else "a")) + print("%d %d %e %f+j%f / %f+j%f"%(Icol,Kp,maxdev, vals[0].real,vals[0].imag, vals[1].real,vals[1].imag),file=fd2) + futils.fclose(fd2); + + futils.fclose(fd); + if( maxdev > 1.0e-6 or Ndev > 0 ): + assert False,"Check results:check:"+comp_datf + if( maxdev > 1.0e-7 or Ndev > 0 ): + if(strict>1): + assert False,"Check results:check:"+comp_datf + else: + Logger.Warning("ppnl_half_ZF","ppnl_half_ZF:maxdev=%e:"%(maxdev)+str(vals)) + if(get_pp_nl01_static.count%20==1): + printout("#calculating ppnl_half with Field:%f"%(math.sqrt(A_over_c[0]*A_over_c[0] + A_over_c[1]*A_over_c[1] + A_over_c[2]*A_over_c[2]))) + + abs_A_over_c= numpy.sqrt( A_over_c[0]**2 + A_over_c[1]**2 + A_over_c[2]**2 ) + ppnl_half = calc_pp_overlaps(cell,A_over_c,kpts_lst) + ### DBG if( abs_A_over_c > 1.0e-7 ): + ### DBG print_aNmatr("ppnl_half.dat",ppnl_half,Append=True,comment="AoverC="+str(A_over_c)) +##ppnl_half:(8, 22, 56) +##ppnl_half:(8, 8, 56) +##ppnl_half:(0,) +#nao:56 + + nao = cell.nao_nr() # 56 + ### print("nao:",end="");print(nao) + buf = numpy.empty((3*9*nao), dtype=numpy.complex128) + + # We set this equal to zeros in case hl_blocks loop is skipped + # and ppnl is returned + n_cum=0 + ppnl = numpy.zeros((nkpts,nao,nao), dtype=numpy.complex128) + for k, kpt in enumerate(kpts_lst): + offset = [0] * 3 + for ib, hl in enumerate(hl_blocks): + l = fakecell.bas_angular(ib) + if(k==0): + n_cum+=(2*l+1) + ### print("#ppShell:%d el=%d nmult=%d %d"%(ib,l,2*l+1,n_cum)) #ppShell:0 el=0 nmult=1 1 + nd = 2 * l + 1 + hl_dim = hl.shape[0] + ### print("hl_dim;",end="");print(hl_dim) ## 2 or 1 + ilp = numpy.ndarray((hl_dim,nd,nao), dtype=numpy.complex128, buffer=buf) + for i in range(hl_dim): + p0 = offset[i] + ilp[i] = ppnl_half[i][k][p0:p0+nd] + + ### print("ilp_%d:"%(i),end="");print(ppnl_half[i][k][p0:p0+nd]) + ### print("ilp_%d:"%(i),end="");print(ilp[i]); + + offset[i] = p0 + nd + ppnl[k] += numpy.einsum('ilp,ij,jlq->pq', ilp.conj(), hl, ilp) + ### if(k==0): + ### print("offset_sum:%d %d %d"%(offset[0],offset[1],offset[2])) (8,0,0) + if abs(kpts_lst).sum() < 1e-9: # gamma_point: + if( abs_A_over_c < 1e-10 ): + ppnl = ppnl.real + else: + # dum=absmax_imaginary_part(ppnl) + printout("#finite A_over_c.. keep as a complex array: imag:%e"%(absmax_imaginary_part(ppnl))) + # assert (dum<1.0e-10),"" + if kpts is None or numpy.shape(kpts) == (3,): + ppnl = ppnl[0] + return ppnl + +def get_ncols(cell,IZnuc, distinct_IZnuc, Nsh_B=None,verbose=0,title=""): + + fakecell, hl_blocks = fake_cell_vnl(cell) + if(verbose>1): + printout("#get_ncols:"+title+":cell:"+str(cell)) + printout("#get_ncols:"+title+":fakecell:"+str(fakecell)) + printout("#get_ncols:"+title+":hl_blocks:"+str(hl_blocks)) + pre=[] + for hl in hl_blocks: + if(verbose>1): + printout("#get_ncols:"+title+":hl_blocks:"+str(hl)) + nd=len(hl) + pre.append(nd) + ### print("#n_cols_pre:",end="");print(pre) + nDa=len(distinct_IZnuc) + + ret=[] + for iDa in range(nDa): + ret.append(None) + + + Nat=len(IZnuc) + ksh_to_Iat=[] + for Iat in range(Nat): + IZ=IZnuc[Iat] + for iDa in range(nDa): + if(IZ==distinct_IZnuc[iDa]): + break + assert(distinct_IZnuc[iDa]==IZ),"" + nsh1=Nsh_B[iDa] + for k in range(nsh1): + ksh_to_Iat.append(Iat) + + if(verbose>0): + printout("#get_ncols:"+title+":ksh_to_Iat:"+str(ksh_to_Iat)); + if(verbose>0): + printout("#get_ncols:"+title+":pre:"+str(pre)); + assert len(ksh_to_Iat)==len(pre),"" + le=len(ksh_to_Iat) + append_to_logfile=False + for Iat in range(Nat): + IZ=IZnuc[Iat] + for iDa in range(nDa): + if(IZ==distinct_IZnuc[iDa]): + break + assert(distinct_IZnuc[iDa]==IZ),"" + if( ret[iDa] is None): + ret[iDa]=[];kA=[]; + for k in range(le): + if( ksh_to_Iat[k] != Iat ): + continue + else: + ret[iDa].append( pre[k] );kA.append(k) + #if(verbose>1): + # print("#get_ncols:"+title+":ret:"+str(pre[k])); + if( not suppress_prtout() ): + fd=futils.fopen("gen_ncols.log",("a" if(append_to_logfile) else "w"));append_to_logfile=True ## OK + print("#%d: %d k={"%(Iat,iDa)+str(kA)+"} ret:"+str(ret[iDa]),file=fd); + futils.fclose(fd); + else: + refr=[];kA=[]; + for k in range(le): + if( ksh_to_Iat[k] != Iat ): + continue + else: + refr.append( pre[k] );kA.append(k) + assert i1eqb(refr, ret[iDa], verbose=False,title="gen_ncols.001"),"" + ### print("#n_cols_ret:",end="");print(ret) + # NshSUM=sum(Nsh_B) + # leRET=len(ret) + # assert leRET==NshSUM,"len:%d / NshSUM:%d ("%(leRET,NshSUM) + str(Nsh_B) + return ret; +def test_pp(cell): + fakecell, hl_blocks = fake_cell_vnl(cell) + printout("#fakecell:"+str(fakecell)) + + n=0 + for x in vars(fakecell): + y=getattr(fakecell,x,None) + printout("#fakecell_%s"%(str(x))+str(y)) + n+=1 + n=0 + for hl in hl_blocks: + printout("#hl_blocks_%d:"%(n)+str(hl)) + n+=1 +#fakecell_ke_cutoff None +#fakecell_pseudo gth-pade +#fakecell_dimension 3 +#fakecell_low_dim_ft_type None +#fakecell__mesh [969 969 625] +#fakecell__mesh_from_build True +#fakecell__ew_eta 2.7513252105444863 +#fakecell__ew_from_build True +#fakecell__ew_cut 2.5435279375048974 +#fakecell__rcut 20.291655858262136 +#fakecell__rcut_from_build True +#fakecell_0:[[ 6.9257397 5.62514728] +# [ 5.62514728 -67.13819583]] +#fakecell_1:[[ 5.0790865 15.27691303] +# [ 15.27691303 -207.97142959]] +#fakecell_2:[[-9.12589591]] +#fakecell_3:[[ 6.9257397 5.62514728] +# [ 5.62514728 -67.13819583]] +#fakecell_4:[[ 5.0790865 15.27691303] +# [ 15.27691303 -207.97142959]] +#fakecell_5:[[-9.12589591]] +#fakecell_6:[[18.26691718]] +#fakecell_7:[[18.26691718]] +#fakecell_8:[[18.26691718]] +#fakecell_9:[[18.26691718]] diff --git a/pyscf/rttddft/heapcheck.py b/pyscf/rttddft/heapcheck.py new file mode 100644 index 000000000..0e149c1df --- /dev/null +++ b/pyscf/rttddft/heapcheck.py @@ -0,0 +1,9 @@ +import os +import numpy as np +from mpi4py import MPI +import datetime +from .Loglv import printout +from .pyscf_common import pyscf_common + +def heapcheck(tag,text="",only_once=False,dtme=False): + pass diff --git a/pyscf/rttddft/laserfield.py b/pyscf/rttddft/laserfield.py new file mode 100644 index 000000000..4920f9cda --- /dev/null +++ b/pyscf/rttddft/laserfield.py @@ -0,0 +1,536 @@ +from .physicalconstants import physicalconstants +import numpy as np +import math +from mpi4py import MPI +# PhysicalConstants_=get_constants(); + +# PhysicalConstants_['_c'] >> physicalconstants.CLIGHTinMPS +# PhysicalConstants_["_aut"] >> ((physicalconstants.aut_in_femtosec)*(1e-15)) +# PhysicalConstants_['Bohr'] >> physicalconstants.BOHRinANGS +# PhysicalConstants_['Hartree'] >> physicalconstants.HARTREEinEV +def vcdiff(A,B): + D=np.array(A)-np.array(B) + return np.sqrt( np.vdot(D, D) ) +def printout_tdfields(laser, t0_fs,t1_fs,dt_fs,fpath,Append=False,Threads=[0], h=None): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + ## PhysicalConstants_=get_constants(); + aut_in_fs= physicalconstants.aut_in_femtosec; ## PhysicalConstants_['_aut']*1.0e+15 + t0_au=t0_fs/aut_in_fs; t1_au=t1_fs/aut_in_fs; dt_au=dt_fs/aut_in_fs + cLIGHT_AU = physicalconstants.CLIGHTinAU; ## PhysicalConstants_['_c'] * PhysicalConstants_["_aut"] / ( PhysicalConstants_['Bohr']*(1.0e-10) ) + + print_Evecs=( hasattr(laser,"get_electricfield")) + print_Avecs=( hasattr(laser,"get_vectorfield")) + N=int(round( (t1_au-t0_au)/dt_au )) + t=t0_au-dt_au + fd1=open(fpath,('a' if(Append) else 'w')) + + string = "#%14s %14s"%("t_au","t_fs"); + if( print_Evecs ): + string += " %14s %14s %14s"%("Ex","Ey","Ez") + if( print_Avecs ): + string += " %14s %14s %14s"%("Ax/c","Ay/c","Az/c") + print(string,file=fd1) + + + for I in range(N): + t+=dt_au + string=" %14.4f %14.4f"%(t,t*aut_in_fs) + E=None + if( print_Evecs ): + E=laser.get_electricfield(t) + string+=" %14.6f %14.6f %14.6f"%(E[0],E[1],E[2]) + if( print_Avecs ): + A_over_c=laser.get_vectorfield(t)/cLIGHT_AU + string+=" %14.6f %14.6f %14.6f"%(A_over_c[0],A_over_c[1],A_over_c[2]) + if( print_Evecs and print_Avecs and (h is not None) ): + b2 = laser.get_vectorfield(t-2*h)/cLIGHT_AU + b1 = laser.get_vectorfield(t-h)/cLIGHT_AU + f1 = laser.get_vectorfield(t+h)/cLIGHT_AU + f2 = laser.get_vectorfield(t+2*h)/cLIGHT_AU + d3p = (f1-b1)/(2*h) + d5p = ( 8*(f1-b1) - (f2-b2) )/(12*h) + nmrerr = vcdiff( d5p, d3p) + diff = vcdiff( -d5p, E) + string+=" %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f %12.4e (nmerr~%10.2e) %r"%(\ + -d5p[0],-d5p[1],-d5p[2], -d3p[0],-d3p[1],-d3p[2], diff, nmrerr, diff w=%14.6f; I:%16.3f => F_0=%14.6f; sigma=%14.6f; tc=%f %f(fs)"%( + freq_eV, self.omega, peakIntensity_WpeCM2, self.Fpeak, self.sigma, self.tc, self.tc*aut_in_fs), file=fd) + elif( isinstance(self,CWField01) ): + print("freq:%12.4f eV => w=%14.6f; I:%16.3f => F_0=%14.6f; ts=%f %f(fs)"%( + freq_eV, self.omega, peakIntensity_WpeCM2, Fpeak_au, self.ts, self.ts*aut_in_fs ), file=fd) + + print("#%6s %14s %16s %16s %16s %16s %16s %16s %16s"%("step","time_au","Esqr", "A_x","A_y","A_z","E_x","E_y","E_z"),file=fd) + + if( dt is None ): + dtref = 0.1 * 2*(np.pi)/self.omega + if( Nstep is None ): + dt = dtref; Nstep=int( math.ceil( (t1-t0)/dt ) ) + else: + dt = (t1-t0)/float(Nstep) + else: + if( Nstep is None ): + Nstep=int( math.ceil( (t1-t0)/dt ) ) + t=t0-dt + for j in range(Nstep): + t+=dt + A=self.get_vectorfield(t) + E=self.get_electricfield(t) + Esqr=np.dot(E,E) + print(" %6d %14.4f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f"%(j,t,Esqr, A[0],A[1],A[2],E[0],E[1],E[2]),file=fd) + fd.close() + +class kickfield: + def __init__(self,ElectricfieldVector,tmKick_AU=None,tmStart_AU=0.0): + # PhysicalConstants_=get_constants(); + self.tmKick_AU = tmKick_AU + self.tmStart_AU= tmStart_AU + print(ElectricfieldVector) + if( isinstance(ElectricfieldVector,tuple) ): + self.ElectricfieldVector = list(ElectricfieldVector).copy() + else: + self.ElectricfieldVector = ElectricfieldVector.copy() + cLIGHT_AU = physicalconstants.CLIGHTinAU; ## physicalconstants.CLIGHTinMPS * ((physicalconstants.aut_in_femtosec)*(1e-15)) / ( PhysicalConstants_['Bohr']*(1.0e-10) ) + self.Avec1 = np.array( [ -cLIGHT_AU*ElectricfieldVector[0], -cLIGHT_AU*ElectricfieldVector[1], -cLIGHT_AU*ElectricfieldVector[2] ]) + + def tostring(self,delimiter='\n'): + ## PhysicalConstants_=get_constants(); + aut_in_attosec= physicalconstants.aut_in_femtosec*(1.0e+3); ##PhysicalConstants_['_aut']*1.0e+18 + retv="#laserfield.kickfield:E:"+ str(self.ElectricfieldVector) + return retv + printout_tdfields=printout_tdfields + + def printout(self,file,t0,t1,dt=None, Nstep=None): + print("kickfield") + + def get_vectorfield(self,tm_AU): + if(tm_AU> get_hcore(self,cell=None,kpts=None,tm_AU=None) +# get_occ(mf, mo_energy_kpts=None, mo_coeff_kpts=None)>> get_occ( ...) +# get_fock(mf, h1e=None, s1e=None, vhf=None, dm=None, cycle=-1, diis=None, +# diis_start_cycle=None, level_shift_factor=None, damp_factor=None) +# eig(self, h_kpts, s_kpts) @khf.py +# foreach k: self._eigh(h_kpts[k], s_kpts[k]) and stacks the results + +class kickfield01: + def __init__(self,ElectricfieldVector,hfWidth_AU,tmKick_AU=None,tmStart_AU=0.0): + # PhysicalConstants_=get_constants(); + self.tmKick_AU = tmKick_AU + self.tmStart_AU= tmStart_AU + self.hfWidth_AU= hfWidth_AU + + print(ElectricfieldVector) + self.ElectricfieldVector = ElectricfieldVector.copy() + cLIGHT_AU = physicalconstants.CLIGHTinAU; ## physicalconstants.CLIGHTinMPS * ((physicalconstants.aut_in_femtosec)*(1e-15)) / ( PhysicalConstants_['Bohr']*(1.0e-10) ) + self.Avec1 = np.array( [ -cLIGHT_AU*ElectricfieldVector[0], -cLIGHT_AU*ElectricfieldVector[1], -cLIGHT_AU*ElectricfieldVector[2] ]) + + def tostring(self,delimiter='\n'): + # PhysicalConstants_=get_constants(); + aut_in_attosec= physicalconstants.aut_in_femtosec*(1.0e+3); ##= PhysicalConstants_['_aut']*1.0e+18 + retv="#laserfield.kickfield:E:"+ str(self.ElectricfieldVector) + return retv + printout_tdfields=printout_tdfields + + def printout(self,file,t0,t1,dt=None, Nstep=None): + print("kickfield") + + def get_vectorfield(self,tm_AU): + if(tm_AU< self.tmStart_AU - self.hfWidth_AU ): + return np.array([0.0, 0.0, 0.0]) + elif( tm_AU < self.tmStart_AU + self.hfWidth_AU ): + fac=0.50*(1 + (tm_AU-self.tmStart_AU)/self.hfWidth_AU) + return np.array( [ fac*self.Avec1[0], fac*self.Avec1[1], fac*self.Avec1[2] ] ) + else: + return np.array( [ self.Avec1[0], self.Avec1[1], self.Avec1[2] ] ) +class CWField01(laserfield): + """ + Continuously oscillating laser field which switches on linearly. + + Parameters: + e0 electric field strength (in atomic units) + w field frequency (in atomic units) + ts switch on time (in atomic units) + """ + def __init__(self, e0, omega, ts, polarization=[0.0,0.0,1.0], toffset=None): + if(toffset is None): + toffset=ts + # PhysicalConstants_=get_constants(); + cLIGHT_AU = physicalconstants.CLIGHTinAU; ## = physicalconstants.CLIGHTinMPS * ((physicalconstants.aut_in_femtosec)*(1e-15)) / ( PhysicalConstants_['Bohr']*(1.0e-10) ) + assert ( abs( cLIGHT_AU - 137.035999)<2.0e-6),"check cLIGHT_AU:%f"%(cLIGHT_AU) + self.e0 = e0 + self.omega = omega + self.a0 = - e0*cLIGHT_AU/self.omega + self.ts = ts + self.toffset = toffset ### 20210607 we set this explicitly.. + assert abs(ts-toffset)<1e-8,"PLS make sure if this is what you really want." + ### print(ts);print(toffset);print([ts==0,ts==0.0,toffset==0,toffset==0.0]) + # assert ts==0.0 and toffset==0.0,"consider Trapezoidal pulse" + #self.time = -9999.99 + self.polarization=np.array(polarization) + + printout_tdfields=printout_tdfields + + def tostring(self,delimiter='\n'): + # PhysicalConstants_=get_constants(); + aut_in_attosec= physicalconstants.aut_in_femtosec*(1.0e+3); ##= PhysicalConstants_['_aut']*1.0e+18 + retv="#laserfield.CWField01:" + retv+= delimiter+"#omega,Fpeak,Apeak:"+str( [self.omega,self.e0,self.a0] ) + retv+= delimiter+"#freq_eV:%f wavelength:%f"%(self.omega*physicalconstants.HARTREEinEV,omega_to_wavelength(self.omega)) + retv+= delimiter+"#ts:%f au/ %f fs"%( self.ts, self.ts*aut_in_attosec*(1.0e-3)) + retv+= delimiter+"#polarization:"+str( self.polarization ) + return retv; + + def get_vectorfield(self,tm_AU): + if(tm_AU < self.toffset): + ampd=0.0 + elif( tm_AU < self.ts): + ampd = self.a0 * ((tm_AU-self.toffset)/ self.ts) * np.sin(self.omega * tm_AU) + else: + ampd = self.a0 * np.sin(self.omega * (tm_AU-self.toffset) ) + print("VectorField:",ampd,tm_AU>self.ts,self.a0 );## assert False,""+str(ampd) + return np.array([ ampd*self.polarization[0], ampd*self.polarization[1], ampd*self.polarization[2] ]) + def get_electricfield(self,tm_AU): + if(tm_AU < self.ts): + ampd = self.e0 * (tm_AU / self.ts) * np.cos(self.omega * tm_AU)\ + + self.e0 * (1.0/ (self.omega * self.ts) )* np.sin( self.omega * tm_AU) + else: + ampd = self.e0 * np.cos(self.omega * tm_AU) + return np.array([ ampd*self.polarization[0], ampd*self.polarization[1], ampd*self.polarization[2] ]) + +class Trapezoidalpulse(laserfield): + def __init__(self, freq_eV, peakIntensity_WpeCM2, + polarization=[0,0,1], tAsc_fs=None, tFlat_fs=None, tDsc_fs=None, tc_fs=None, tOffset_fs=0.0, + fwhm_as=-1.0, phase=0.0, sincos=None): + # PhysicalConstants_=get_constants(); + cLIGHT_AU = physicalconstants.CLIGHTinAU; ## = physicalconstants.CLIGHTinMPS * ((physicalconstants.aut_in_femtosec)*(1e-15)) / ( PhysicalConstants_['Bohr']*(1.0e-10) ) + aut_in_fs= physicalconstants.aut_in_femtosec ## i.e. 24.1888 attosec + + self.omega= freq_eV/physicalconstants.HARTREEinEV + self.Fpeak= intensity_to_FieldStrength(peakIntensity_WpeCM2,"au") + self.Apeak= (cLIGHT_AU/self.omega)* self.Fpeak ## (\omega/c )A = E + norm = math.sqrt( polarization[0]**2 + polarization[1]**2 + polarization[2]**2 ) + assert norm>0.01 and norm<=100, "wrong polarization vector" + if(abs(norm-1)>1.0e-8): + self.polarization=np.array(polarization)*(1.0/norm) + else: + self.polarization=np.array(polarization) + if( tc_fs is None ): + tc_fs = tAsc_fs + tFlat_fs*0.50 + + self.tc = tc_fs / aut_in_fs + self.tAsc = tAsc_fs / aut_in_fs + self.tFlat= tFlat_fs / aut_in_fs + self.tDsc = tDsc_fs / aut_in_fs + + self.A1 = None + self.A2 = None + self.A3 = None + + self.t0 = tOffset_fs / aut_in_fs + self.t1 = self.t0 + self.tAsc + self.t2 = self.t1 + self.tFlat + self.t3 = self.t2 + self.tDsc + + self.phi0=phase + self.nstep=0; self.time=-999.9; + if sincos is not None: + if( sincos == 'sin' ): + self.phi0=self.phi0-math.pi*0.50 + + def get_electricfield(self,tm_AU): + if( (tm_AU > self.t3) or (tm_AU < self.t0) ): + return np.array([ 0.0, 0.0, 0.0 ]) + phase=(tm_AU-self.tc)*self.omega + self.phi0 + if( tm_AU < self.t1 ): + ampd = ( self.Fpeak * (tm_AU - self.t0)/self.tAsc )*math.cos(phase) + return ampd*self.polarization + elif( tm_AU < self.t2 ): + ampd = self.Fpeak * math.cos(phase) + return ampd*self.polarization + else: + ampd = ( self.Fpeak * ( 1.0 - (tm_AU-self.t2)/self.tAsc ) )*math.cos(phase) + return ampd*self.polarization + + def get_vectorfield(self,tm_AU): + if( tm_AU < self.t0 ): + return np.array([ 0.0, 0.0, 0.0 ]) + elif( tm_AU < self.t1 ): + return self.get_vectorfield_(1,tm_AU) + elif( tm_AU < self.t2 ): + if( self.A1 is None ): + self.A1 = self.get_vectorfield_(1,self.t1) + return self.get_vectorfield_(2,tm_AU) + elif( tm_AU < self.t3 ): + if( self.A2 is None ): + self.A2 = self.get_vectorfield_(2,self.t2) + return self.get_vectorfield_(3,tm_AU) + elif( tm_AU > self.t3 ): + if( self.A3 is None ): + self.A3 = self.get_vectorfield_(3,self.t3) + return self.A3 + + def get_vectorfield_(self,step,tm_AU): + phase=(tm_AU-self.tc)*self.omega + self.phi0 + if( step == 1 ): + phase_0=(self.t0-self.tc)*self.omega + self.phi0 + ampd = (-self.Apeak) * ( ((tm_AU-self.t0)/self.tAsc)*math.sin(phase) \ + + (1.0/(self.omega * self.tAsc))*( math.cos(phase)-math.cos(phase_0) ) ) + return ampd * self.polarization + elif( step == 2 ): + phase_1=(self.t1-self.tc)*self.omega + self.phi0 + ampd = (-self.Apeak) * ( math.sin(phase) - math.sin(phase_1) ) + return self.A1 + ampd*self.polarization + elif( step == 3 ): + phase_2=(self.t2-self.tc)*self.omega + self.phi0 + ampd = (-self.Apeak) * ( ( 1.0 - (tm_AU-self.t2)/self.tDsc )*math.sin(phase) - math.sin(phase_2) \ + - (1.0/(self.omega * self.tDsc))*( math.cos(phase)-math.cos(phase_2) ) ) + return self.A2 + ampd*self.polarization + else: + assert False,"" + return None + def printout_tdfields(laser, t0_fs,t1_fs,dt_fs,fpath,Append=False,Threads=[0]): + + printout_tdfields(laser, t0_fs,t1_fs,dt_fs,fpath,Append=False,Threads=[0],h=0.02) + + def tostring(self,delimiter='\n'): + #PhysicalConstants_=get_constants(); + aut_in_fs= physicalconstants.aut_in_femtosec; ## PhysicalConstants_['_aut']*1.0e+15 + retv="#laserfield.Trapezoidalpulse:" + retv+= delimiter+"#omega,Fpeak,Apeak:"+str( [self.omega,self.Fpeak,self.Apeak] ) + retv+= delimiter+"#freq_eV,wavelength,Intensity:%f,%f,%7.2e"%(self.omega*physicalconstants.HARTREEinEV, + omega_to_wavelength(self.omega), FieldStrength_to_intensity(self.Fpeak)) + retv+= delimiter+"#tAsc-tFlat-tDsc:%5.1f-%5.1f-%5.1f tc:%5.1f"%(\ + self.tAsc*aut_in_fs, self.tFlat*aut_in_fs, self.tDsc*aut_in_fs, self.tc*aut_in_fs) + retv+= delimiter+"#polarization:"+str( self.polarization ) + return retv; + +# laser=gaussianpulse01 +class gaussianpulse01(laserfield): + """ Gaussian Pulse + """ + def __init__(self, freq_eV, peakIntensity_WpeCM2, + polarization=[0,0,1], tc_as=0.0, sigma_as=-1.0, + fwhm_as=-1.0, phase=0.0, sincos=None): + assert sigma_as>0 or fwhm_as>0, "either sigma or fwhm should be >0" + peakIntensity_SI=peakIntensity_WpeCM2*(1.0e+4) ## 0.5* eps * (E**2) * c + """ + This function is invoked as add_linear_field( strength(time) ...) + take AU input and return AU output + """ + #PhysicalConstants_=get_constants(); + cLIGHT_AU = physicalconstants.CLIGHTinAU; ## = physicalconstants.CLIGHTinMPS * ((physicalconstants.aut_in_femtosec)*(1e-15)) / ( PhysicalConstants_['Bohr']*(1.0e-10) ) + + self.omega= freq_eV/physicalconstants.HARTREEinEV + self.Fpeak= intensity_to_FieldStrength(peakIntensity_WpeCM2,"au") + self.Apeak= (cLIGHT_AU/self.omega)* self.Fpeak ## (\omega/c )A = E + + aut_in_attosec= physicalconstants.aut_in_femtosec*(1.0e+3); ##= PhysicalConstants_['_aut']*1.0e+18 ## i.e. 24.1888 attosec + if(sigma_as<0): + self.sigma= (0.5*fwhm_as) * math.sqrt( 1.00/math.sqrt(math.log(2.0)) ) / aut_in_attosec + ## 2020.09.19 11.34 JST: intensity-FWHM + ## -0.5(0.5fwhm/sigma)**2 = -0.5( ln(2) ) + norm = math.sqrt( polarization[0]**2 + polarization[1]**2 + polarization[2]**2 ) + assert norm>0.01 and norm<=100, "wrong polarization vector" + if(abs(norm-1)>1.0e-8): + self.polarization=np.array(polarization)*(1.0/norm) + else: + self.polarization=np.array(polarization) + +# A = - Apeak * polarization[:] * sin(\omega*(t-tc)) * exp(...) +# E = Fpeak * polarization[:] * cos(\omega*(t-tc)) * exp(...) + ...terms arising from deriv. of exp.. +# Fpeak:= Apeak * \omega / c + + self.tc=tc_as / aut_in_attosec + self.phi0=phase + self.nstep=0; self.time=-999.9; + if sincos is not None: + if( sincos == 'sin' ): + self.phi0=self.phi0-math.pi*0.50 + printout_tdfields=printout_tdfields + + def tostring(self,delimiter='\n'): + #PhysicalConstants_=get_constants(); + aut_in_attosec= physicalconstants.aut_in_femtosec*(1.0e+3); ##= PhysicalConstants_['_aut']*1.0e+18 + retv="#laserfield.gaussianpulse01:" + retv+= delimiter+"#omega,Fpeak,Apeak:"+str( [self.omega,self.Fpeak,self.Apeak] ) + retv+= delimiter+"#freq_eV,wavelength,Intensity:%f,%f,%7.2e"%(self.omega*physicalconstants.HARTREEinEV, + omega_to_wavelength(self.omega), FieldStrength_to_intensity(self.Fpeak)) + retv+= delimiter+"#tc:%f au %f fs"%( self.tc, self.tc*aut_in_attosec*(1.0e-3)) + retv+= delimiter+"#polarization:"+str( self.polarization ) + return retv; + def get_vectorfield(self,tm_AU): + arg=(tm_AU-self.tc)/self.sigma + phase=(tm_AU-self.tc)*self.omega + self.phi0 ## cosine wave means max ampd at t=tc. + ampd= - self.Apeak*math.sin(phase)*math.exp(0.0-0.5*arg*arg) + return np.array([ ampd*self.polarization[0], ampd*self.polarization[1], ampd*self.polarization[2] ]) + def get_electricfield(self,tm_AU): + #PhysicalConstants_=get_constants(); + cLIGHT_AU = physicalconstants.CLIGHTinAU; ## = physicalconstants.CLIGHTinMPS * ((physicalconstants.aut_in_femtosec)*(1e-15)) / ( PhysicalConstants_['Bohr']*(1.0e-10) ) + arg=(tm_AU-self.tc)/self.sigma + phase=(tm_AU-self.tc)*self.omega + self.phi0 + ampd = self.Apeak * ( (self.omega/cLIGHT_AU)*math.cos(phase) \ + - ( (tm_AU-self.tc)/(cLIGHT_AU* (self.sigma**2)) )*math.sin(phase)) * math.exp(-0.5*arg*arg) + return np.array([ ampd*self.polarization[0], ampd*self.polarization[1], ampd*self.polarization[2] ]) + +class sinsquarepulse(laserfield): + def __init__(self, freq_eV, peakIntensity_WpeCM2, width_as, + polarization=[0,0,1], tc_as=0.0, phase=0.0, sincos=None): + assert width_as>0, "width_as should be >0" + """ + This function is invoked as add_linear_field( strength(time) ...) + take AU input and return AU output + """ + #PhysicalConstants_=get_constants(); + cLIGHT_AU = physicalconstants.CLIGHTinAU; ## = physicalconstants.CLIGHTinMPS * ((physicalconstants.aut_in_femtosec)*(1e-15)) / ( PhysicalConstants_['Bohr']*(1.0e-10) ) + aut_in_attosec= physicalconstants.aut_in_femtosec*(1.0e+3); ##= PhysicalConstants_['_aut']*1.0e+18 ## i.e. 24.1888 attosec + + PI=3.1415926535897932384626433832795 + self.omega= freq_eV/physicalconstants.HARTREEinEV + self.Fpeak= intensity_to_FieldStrength(peakIntensity_WpeCM2,"au") + self.Apeak= (cLIGHT_AU/self.omega)* self.Fpeak ## (\omega/c )A = E + wid_AU = width_as/aut_in_attosec + self.kappa= PI/wid_AU + self.width_AU=wid_AU + norm = math.sqrt( polarization[0]**2 + polarization[1]**2 + polarization[2]**2 ) + assert norm>0.01 and norm<=100, "wrong polarization vector" + if(abs(norm-1)>1.0e-8): + self.polarization=np.array(polarization)*(1.0/norm) + else: + self.polarization=np.array(polarization) + +# A = - Apeak * polarization[:] * sin(\omega*(t-tc)) * exp(...) +# E = Fpeak * polarization[:] * cos(\omega*(t-tc)) * exp(...) + ...terms arising from deriv. of exp.. +# Fpeak:= Apeak * \omega / c + + self.tc=tc_as / aut_in_attosec + + self.toff=self.tc-self.width_AU*0.50 + + self.phi0=phase + self.nstep=0; self.time=-999.9; + if sincos is not None: + if( sincos == 'sin' ): + self.phi0=self.phi0-math.pi*0.50 + printout_tdfields=printout_tdfields + def get_vectorfield(self,tm_AU): + PI=3.1415926535897932384626433832795 + arg= self.kappa*(tm_AU-self.toff) + if( arg < 0 or arg>PI ): + return np.zeros([3],dtype=np.float64); + phase=(tm_AU-self.tc)*self.omega + self.phi0 ## cosine wave means max ampd at t=tc. + ampd= - self.Apeak*math.sin(phase)*( math.sin(arg)**2 ) + return np.array([ ampd*self.polarization[0], ampd*self.polarization[1], ampd*self.polarization[2] ]) + def get_electricfield(self,tm_AU): + #PhysicalConstants_=get_constants(); + cLIGHT_AU = physicalconstants.CLIGHTinAU; ## = physicalconstants.CLIGHTinMPS * ((physicalconstants.aut_in_femtosec)*(1e-15)) / ( PhysicalConstants_['Bohr']*(1.0e-10) ) + arg= self.kappa*(tm_AU-self.toff) ### ampd arg + PI=3.1415926535897932384626433832795 + if( arg < 0 or arg>PI ): + return np.zeros([3],dtype=np.float64); + phase=(tm_AU-self.tc)*self.omega + self.phi0 ## cosine wave means max ampd at t=tc. + si=math.sin(arg);co=math.cos(arg); + ampd= self.Apeak *( (self.omega/cLIGHT_AU)*math.cos(phase)*(si**2) \ + + (2.0*self.kappa/cLIGHT_AU) * si*co * math.sin(phase) ) + return np.array([ ampd*self.polarization[0], ampd*self.polarization[1], ampd*self.polarization[2] ]) + def tostring(self,delimiter='\n'): + #PhysicalConstants_=get_constants(); + aut_in_attosec= physicalconstants.aut_in_femtosec*(1.0e+3); ##= PhysicalConstants_['_aut']*1.0e+18 + retv="#laserfield.sinsquarepulse:" + retv+= delimiter+"#omega,Fpeak,Apeak:"+str( [self.omega,self.Fpeak,self.Apeak] ) + retv+= delimiter+"#freq_eV,wavelength,Intensity:%f,%f,%7.2e"%(self.omega*physicalconstants.HARTREEinEV, + omega_to_wavelength(self.omega), FieldStrength_to_intensity(self.Fpeak)) + retv+= delimiter+"#tc:%f au %f fs"%( self.tc, self.tc*aut_in_attosec*(1.0e-3)) + retv+= delimiter+"#polarization:"+str( self.polarization ) + return retv; diff --git a/pyscf/rttddft/mpiutils.py b/pyscf/rttddft/mpiutils.py new file mode 100644 index 000000000..d60990e33 --- /dev/null +++ b/pyscf/rttddft/mpiutils.py @@ -0,0 +1,167 @@ +import numpy +import datetime +import sys +import math +from mpi4py import MPI +from .Loglv import Loglv,printout + +class mpi_utils_: + Counter={} + @staticmethod + def Countup(key,inc=True): ## by default 1,2,3,... + if( key not in mpi_utils_.Counter ): + if( not inc ): + return 0 + else: + mpi_utils_.Counter.update({key:0}) + if(inc): + mpi_utils_.Counter[key]+=1 + return mpi_utils_.Counter[key] + +# def mpi_print :: see Loglv.py#printout +# +def mpi_Barrier(key,logfile=None,stdout=False,Append=True): ## False XXX XXX + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank() + MPIsize=comm.Get_size() + if( MPIsize<2 ): + return + stdout = (stdout and (MPIrank==0) ) + string="#mpi_Barrier:"+str(key)+":%02d ..."%(MPIrank)+str(datetime.datetime.now()); + fnme_format='mpi_Bcast_%02d.log';fpath=None + printout(string,fnme_format=fnme_format,fpath=fpath,Type='mpi',dtme=True, stdout=stdout ) + # if( logfile is not None ): + # fdOU=open(logfile+"_%02d"%(MPIrank),('a' if(Append) else 'w')) + # print(string,file=fdOU);fdOU.close() ### mth-adapted + # dbgng_Barrier=True + # logfiles=[ 'mpi_Bcast_%02d.log'%(MPIrank) ] ### , 'mpi_Bcast.log'] + # for f in logfiles: + # fdOU=open(f,('a' if(Append) else 'w')) + # print(string,file=fdOU);fdOU.close() + # if( stdout and MPIrank==0 ): + # print(string,flush=True) + + comm.Barrier() + + string="#mpi_Barrier:"+str(key)+":%02d leaving "%(MPIrank)+str(datetime.datetime.now()); + printout(string,fnme_format=fnme_format,fpath=fpath,Type='mpi',dtme=True, stdout=stdout ) + # if( logfile is not None ): + # fdOU=open(logfile+"_%02d"%(MPIrank),'w') + # print(string,file=fdOU);fdOU.close() + # for f in logfiles: + # fdOU=open(f,('a' if(Append) else 'w')) + # print(string,file=fdOU);fdOU.close() + # if( stdout and MPIrank==0 ): + # print(string,flush=True) + +def mpi_Bcast(key,buf,root=None, barrier=True, iverbose=1, Append=False): + from mpi4py import MPI + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank() + MPIsize=comm.Get_size() + N_call= mpi_utils_.Countup("Bcast."+key) + string = "#comm_Bcast:%02d:"%(MPIrank)+str(key)+"....."+\ + " \t\t"+str(numpy.shape(buf))+" "+str( (numpy.array(buf)).dtype ) + fnme_format='mpi_Bcast_%02d.log' + printout(string,fnme_format=fnme_format,Type='mpi',Append=Append, dtme=True, stdout=(iverbose>1) ) + if( barrier ): + comm.Barrier() + + if( root is not None ): + comm.Bcast(buf,root=root) + else: + comm.Bcast(buf) + string="#comm_Bcast:%02d:done"%(MPIrank)+str(key)+" done " + printout(string,fnme_format=fnme_format,Type='mpi',Append=Append, dtme=True, stdout=(iverbose>1) ) + +def mpi_Bcast_old(key,buf,root=None, barrier=True, iverbose=1, Append=False): + from mpi4py import MPI + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank() + MPIsize=comm.Get_size() + N_call= mpi_utils_.Countup(key) + # print("#%02d:mpiutils.mpi_Bcast:%s:Ncall=%d"%(MPIrank,str(key),N_call)) + # if( N_call<3 or N_call==10 or N_call==100): + # iverbose+=1 + # prtout = ( iverbose > 1 ) + + loglv=Loglv.loglv('mpi') + redundancy=1 + fdA=[];fdOU=None;### fdOU2=None + if( redundancy <= loglv ): + fdOU=open('mpi_Bcast_%02d.log'%(MPIrank), ('a' if(Append) else 'w') );fdA.append(fdOU); + ### fdOU2=open('mpi_Bcast.log', ('a' if(Append) else 'w') );fdA.append(fdOU2); + if( MPIrank==0 ): + fdA.append(sys.stdout) + for fd in fdA: + if( (root is None) or (root != MPIrank) ): + print("#comm_Bcast:%02d:"%(MPIrank)+str(key)+"....."+ str(datetime.datetime.now()),file=fd) + else: + print("#comm_Bcast:root:%02d:"%(MPIrank)+str(key)+"....."+\ + " \t\t"+str(numpy.shape(buf))+" "+str( (numpy.array(buf)).dtype ) + + str(datetime.datetime.now()),file=fd) + if(fdOU is not None): + fdOU.close() + ### if(fdOU2 is not None): + ### fdOU2.close() + + if( barrier ): + comm.Barrier() + + if( root is not None ): + comm.Bcast(buf,root=root) + else: + comm.Bcast(buf) + + fdA=[];fdOU=None;### fdOU2=None + if( redundancy <= loglv ): + fdOU=open('mpi_Bcast_%02d.log'%(MPIrank),('a' if(Append) else 'w') );fdA.append(fdOU); + ### fdOU2=open('mpi_Bcast.log', ('a' if(Append) else 'w') );fdA.append(fdOU2); + if( MPIrank==0 ): + fdA.append(sys.stdout) + for fd in fdA: + if( (root is None) or (root != MPIrank) ): + print("#comm_Bcast:%02d:done"%(MPIrank)+str(key)+" done "+ str(datetime.datetime.now()) ,file=fd) + else: + print("#comm_Bcast:root:%02d:done"%(MPIrank)+str(key)+" done"+ + " \t\t"+str(numpy.shape(buf))+" "+str( (numpy.array(buf)).dtype ) + + str(datetime.datetime.now()),file=fd ) + if( fdOU is not None ): + fdOU.close() + ### if(fdOU2 is not None): + ### fdOU2.close() +def mpi_dbgtrace(text,buf=None,redundancy=1,iverbose=1): + printout(text, dtme=True,stdout=True, + Type='mpi',redundancy=redundancy-(iverbose-1), warning=(1 if(redundancy<0) else 0) ) + +def mpi_dbgtrace_old(text,buf=None,redundancy=1,iverbose=1): + from mpi4py import MPI + comm = MPI.COMM_WORLD + MPIsize = comm.Get_size() + MPIrank = comm.Get_rank() + + loglv=Loglv.loglv('mpi') + if( redundancy >= loglv+(iverbose-1) ): + return + + string="#mpi_dbgtrace:%03d:"%(MPIrank)+text + if( buf is not None): + string+=" buf:"+str(type(buf))+" "+str(buf.dtype)+" "+str(numpy.shape(buf)) + bf=numpy.ravel(buf);le=len(bf);str1="" + nprt=min(le,10) + if( bf.dtype==float or bf.dtype==numpy.float64 ): + for j in range(nprt): + str1+="%14.6f "%(bf[j]) + if(le>nprt): + str1+=" ... [%d-1]:"%(le)+"%14.6f"%(bf[le-1]) + else: + for j in range(nprt): + str1+=str(bf[j])+" " + if(le>nprt): + str1+=" ... [%d-1]:"%(le)+str(bf[le-1]) + string+=str1 + + fdO=open("mpi_dbgtrace_%02d.log"%(MPIrank),"a"); + for fd in [fdO,sys.stdout]: + print(string,file=fd,flush=True); + fdO.close() diff --git a/pyscf/rttddft/physicalconstants.py b/pyscf/rttddft/physicalconstants.py new file mode 100644 index 000000000..3f9bf00f9 --- /dev/null +++ b/pyscf/rttddft/physicalconstants.py @@ -0,0 +1,116 @@ +class PhysicalConstants: + def __setattr__(self,name,value): + if( name in self.__dict__ ): + assert False,"do not change const:"+name + self.__dict__[name]=value + def __init__(self): + print("__init__ PhysicalConstants",flush=True) + self.CLIGHTinMPS=299792458.0; self.AUTinFEMTOSEC=2.418884326058678e-2; + self.BOHRinANGS=0.5291772105638411;self.HARTREEinEV=27.211386024367243 + self.PLANCKinJOULSEC=6.62607004e-34; + self.ECHARGEinCOULOMB=1.6021766208e-19; + self.EMASSinKG=9.10938356e-31 + self.EPS0inSI=8.85418781762039e-12 + self.aut_in_femtosec=self.AUTinFEMTOSEC + self.CLIGHTinAU=self.CLIGHTinMPS * (self.AUTinFEMTOSEC*1e-15) \ + / ( self.BOHRinANGS*(1.0e-10) ) + self.LAMBDA1EVinNM=( self.PLANCKinJOULSEC * self.CLIGHTinMPS/self.ECHARGEinCOULOMB )*(1e+9); + + +# o to add more constants, you set them in __init__ method +# o you can access to immutable constants as shown below... +# print(PhysicalConstants.Getv().BOHRinANGS) +# print(PhysicalConstants.Getv("AUTinFEMTOSEC")) +# print(PhysicalConstants.Getv("AUTinFEMTOSEC","BOHRinANGS")) +# print(PhysicalConstants.CLIGHTinAU()) +# + Instance_=None + @staticmethod + def Getv(*args): + if( PhysicalConstants.Instance_ is None ): + PhysicalConstants.Instance_=PhysicalConstants() + le=len(args) + if(le==0): + return PhysicalConstants.Instance_; + ret=[] + for name in args: + dum=getattr( PhysicalConstants.Instance_, name) + if(le==1): + return dum + ret.append(dum) + return ret + @staticmethod + def CLIGHTinAU(): + if( PhysicalConstants.Instance_ is None ): + PhysicalConstants.Instance_=PhysicalConstants() + cLIGHT_AU = PhysicalConstants.Instance_.CLIGHTinMPS \ + * (PhysicalConstants.Instance_.AUTinFEMTOSEC*1e-15) \ + / ( PhysicalConstants.Instance_.BOHRinANGS*(1.0e-10)) + return cLIGHT_AU + + @staticmethod + def BOHRinANGS(): + if( PhysicalConstants.Instance_ is None ): + PhysicalConstants.Instance_=PhysicalConstants() + val=PhysicalConstants.Instance_.BOHRinANGS + return val + + @staticmethod + def aut_in_femtosec(): + if( PhysicalConstants.Instance_ is None ): + PhysicalConstants.Instance_=PhysicalConstants() + val=PhysicalConstants.Instance_.AUTinFEMTOSEC + return val + + @staticmethod + def HARTREEinEV(): + if( PhysicalConstants.Instance_ is None ): + PhysicalConstants.Instance_=PhysicalConstants() + val=PhysicalConstants.Instance_.HARTREEinEV + return val + + +physicalconstants=PhysicalConstants.Getv() + + +## def get_constants(): +## print("\n\n#!W get_constants:this subroutine is to be removed in the near future\n\n") +## dic={"_c":299792458.0, "_mu0":1.2566370614359173e-06, "_Grav":6.67408e-11, "_hplanck":6.62607004e-34,\ +## "_e":1.6021766208e-19, "_me":9.10938356e-31, "_mp":1.672621898e-27, "_Nav":6.022140857e+23,\ +## "_k":1.38064852e-23, "_amu":1.66053904e-27, "_eps0":8.85418781762039e-12, "_hbar":1.0545718001391127e-34,\ +## "Ang":1.0, "Angstrom":1.0, "nm":10.0, "Bohr":0.5291772105638411,\ +## "eV":1.0, "Hartree":27.211386024367243, "kJ":6.241509125883258e+21, "kcal":2.611447418269555e+22,\ +## "mol":6.022140857e+23, "Rydberg":13.605693012183622, "Ry":13.605693012183622, "Ha":27.211386024367243,\ +## "second":98226947884640.62, "fs":0.09822694788464063, "kB":8.617330337217213e-05, "Pascal":6.241509125883258e-12,\ +## "GPa":0.006241509125883258, "Debye":0.20819433442462576, "alpha":0.007297352566206496, "invcm":0.0001239841973964072,\ +## "_aut":2.418884326058678e-17, "_auv":2187691.262715653, "_auf":8.238723368557715e-08, "_aup":29421015271080.86,\ +## "AUT":0.0023759962463473982, "m":10000000000.0, "kg":6.0221408585491615e+26, "s":98226947884640.62,\ +## "A":63541.719052630964, "J":6.241509125883258e+18, "C":6.241509125883258e+18}; +## return dic + +if(__name__ == "__main__"): + dic={"_c":299792458.0, "_mu0":1.2566370614359173e-06, "_Grav":6.67408e-11, "_hplanck":6.62607004e-34,\ + "_e":1.6021766208e-19, "_me":9.10938356e-31, "_mp":1.672621898e-27, "_Nav":6.022140857e+23,\ + "_k":1.38064852e-23, "_amu":1.66053904e-27, "_eps0":8.85418781762039e-12, "_hbar":1.0545718001391127e-34,\ + "Ang":1.0, "Angstrom":1.0, "nm":10.0, "Bohr":0.5291772105638411,\ + "eV":1.0, "Hartree":27.211386024367243, "kJ":6.241509125883258e+21, "kcal":2.611447418269555e+22,\ + "mol":6.022140857e+23, "Rydberg":13.605693012183622, "Ry":13.605693012183622, "Ha":27.211386024367243,\ + "second":98226947884640.62, "fs":0.09822694788464063, "kB":8.617330337217213e-05, "Pascal":6.241509125883258e-12,\ + "GPa":0.006241509125883258, "Debye":0.20819433442462576, "alpha":0.007297352566206496, "invcm":0.0001239841973964072,\ + "_aut":2.418884326058678e-17, "_auv":2187691.262715653, "_auf":8.238723368557715e-08, "_aup":29421015271080.86,\ + "AUT":0.0023759962463473982, "m":10000000000.0, "kg":6.0221408585491615e+26, "s":98226947884640.62,\ + "A":63541.719052630964, "J":6.241509125883258e+18, "C":6.241509125883258e+18}; + + aut_in_femtosec= dic['_aut']*1.0e+15 + BOHRinANGS=dic['Bohr'] + HARTREEinEV=dic['Hartree'] + + dum=PhysicalConstants.HARTREEinEV(); diff=abs(dum-HARTREEinEV); assert diff<1e-7,""; print(dum,diff) + dum=PhysicalConstants.BOHRinANGS(); diff=abs(dum-BOHRinANGS); assert diff<1e-7,""; print(dum,diff) + dum=PhysicalConstants.aut_in_femtosec(); diff=abs(dum-aut_in_femtosec); assert diff<1e-7,""; print(dum,diff) + + + + dum=physicalconstants.HARTREEinEV; diff=abs(dum-HARTREEinEV); assert diff<1e-7,""; print(dum,diff) + dum=physicalconstants.BOHRinANGS; diff=abs(dum-BOHRinANGS); assert diff<1e-7,""; print(dum,diff) + dum=physicalconstants.aut_in_femtosec; diff=abs(dum-aut_in_femtosec); assert diff<1e-7,""; print(dum,diff) diff --git a/pyscf/rttddft/print_00.py b/pyscf/rttddft/print_00.py new file mode 100644 index 000000000..1d8367910 --- /dev/null +++ b/pyscf/rttddft/print_00.py @@ -0,0 +1,37 @@ +import sys +from mpi4py import MPI +import datetime + +## see also utils.py +def print_00(text,flush=False,file=sys.stdout,end='\n',dtme=False,warning=0,Threads=[0]): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if( isinstance(Threads,str) ): + if( Threads.strip()=='all' ): + Threads= range(MPIsize) + if((MPIrank not in Threads) and (warning >=0) ): + return + if(dtme): + text+=' \t\t'+str(datetime.datetime.now()) + if( file is None ): + file=sys.stdout + print(text,flush=flush,file=file,end=end) + +def open_00(fpath,mode,default=None): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if(MPIrank!=0): + if(default is None): + return None + elif(isinstance(default,str) and default == "dummy"): + return open("dummy.log",mode) + else: + return default; + return open(fpath,mode) + +def close_00(fd): + if( fd is None ): + return + elif( fd == sys.stdout ): + return + else: + fd.close();return + diff --git a/pyscf/rttddft/pyscf_common.py b/pyscf/rttddft/pyscf_common.py new file mode 100644 index 000000000..5acf90e57 --- /dev/null +++ b/pyscf/rttddft/pyscf_common.py @@ -0,0 +1,749 @@ +import numpy as np +import sys +import os +import math +import os.path +import time +import datetime +from mpi4py import MPI + +class Stack: + def __init__(self,bfsz): + self.buf=[] + self.bfsz=bfsz + self.o=0 + self.len=0 + def contains(self,item): + return (item in self.buf) + def append(self,item): + if(self.len>=self.bfsz): + self.buf[ self.o ]=item; + self.o=(self.o+1)%self.bfsz + else: + self.buf.append(item); self.len+=1 + return self + def toarray(self): + return [ self.buf[(self.o+k)%self.bfsz] for k in range(self.len) ] + def clear(self): + self.buf.clear();self.o=0;self.len=0 + def last(ith=0): ## here we define ith=0: last item ith=1:last-1 ... + ## o+0 + ## [ 0, 1 ... le-1 ] + ## le-1 0th + if( ith >= self.len ): + print("#Stack.last %d / %d"%(ith,self.len)) + return None + else: + indx= ( self.o+(self.len-1-ith) )%self.bfsz + return self.buf[indx] +class Filewriter: + def __init__(self,fpath, bfsz=10): + self.fpath=fpath + self._append=False + self.strbuf=[];self.nbuf=0 + self.bfsz=bfsz + def prtout(self): + ### print("Logwriter:%s nbuf=%d printing out..."%(self.fpath,self.nbuf)) + fd=open(self.fpath,('a' if(self._append) else 'w')) + retv=0 + for item in self.strbuf: + print(item,file=fd);retv+=1 + fd.close(); self._append=True + return retv + + def append(self,text,timing=False): + self.strbuf.append(text); self.nbuf+=1 + ### print("Logwriter:%s nbuf=%d"%(self.fpath,self.nbuf)) + if( self.nbuf >=self.bfsz ): + self.prtout() + self.nbuf=0;self.strbuf.clear() +class pyscf_common: + SCF_buf=[]; SCF_bfsz=5; n_SCF=0; + SCF_warnings={} # key:{'count':0,'i_SCF':[ 5 most recent occurrence ] } + dic={} + params=None + job=None + _Time_000=None;wt_010={} + Key=None;KeyHistory=None;Logwriter=None;Timing={} + _iVerbose=2 + _Counter={} + _Dict={} + _Keys_Write_once=[] + _Warning_logfile=None + _Filenames=[] + + time_AU_=None + step_=None + # 2021.12.31 --------------------- + Rnuc_=None + Dict_Print_warning_={} + + Dict_Clipboard={} + @staticmethod + def Clipboard(key,value=None,default=None,clear=None,set_value=False): + if(value is not None or set_value ): + pyscf_common.Dict_Clipboard.update({key:value}) + else: + if(key in pyscf_common.Dict_Clipboard ): + if( clear is not None): + if(clear): + return pyscf_common.Dict_Clipboard.pop(key) + return pyscf_common.Dict_Clipboard[key] + else: + print("!W key:%s is not in pyscf_common.Dict_Clipboard"%( str(key) )) + return default + + @staticmethod + def Printout_warning(key,content,level=-1, nth_call=[1], dtme=True, Threads=[0], fpath=None, Append=None): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + + isempty=( len(pyscf_common.Dict_Print_warning_)==0 ) + MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if( key not in pyscf_common.Dict_Print_warning_ ): + pyscf_common.Dict_Print_warning_.update({key:0}); + pyscf_common.Dict_Print_warning_[key]+=1 + if( dtme ): + content+=" \t\t "+str(datetime.datetime.now()) + nth=pyscf_common.Dict_Print_warning_[key] + + logfpath0=pyscf_common.job + "_Print_warning.log" + Fpaths=[ logfpath0 ];Flags=[ ("w" if(isempty) else "a") ] + if(fpath is not None): + if( Append is None ): + Append=True + Fpaths.append(fpath);Flags.append("a" if(Append) else "w") + + if( MPIsize < 2 or MPIrank in Threads ): + Nf=len(Fpaths) + if( nth in nth_call ): + for I in range(Nf): + fdOU=open( Fpaths[I], Flags[I] ) + print("#%s:"%(key)+content,file=fdOU) + fdOU.close() + print("#%s:"%(key)+content) + + if( isempty and abs(level)>1 ): + os.system("fopen "+logfpath0) + @staticmethod + def Check_cellRnuc(cell, caller=""): + Rnuc_au,Sy=parse_xyzstring(cell.atom,unit_BorA='B') + return pyscf_common.Check_Rnuc(Rnuc_au, caller) + @staticmethod + def Check_Rnuc(testee, caller=""): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if( pyscf_common.Rnuc_ is None ): + return None + dev = max( np.ravel( pyscf_common.Rnuc_ ) - np.ravel( testee ) ) + dbgng=True ## XXX XXX + prtout=( dbgng or dev>1.0e-6 ) + if( prtout ): + + path="Set_Rnuc_%02d.log"%(MPIrank) + fdOU=open(path,"a") + if( dev < 1e-6 ): + print("###Check:%s:$%02d: %e"%(caller,MPIrank,dev),file=fdOU) + else: + + Nat=len( testee ) + diffs=[ np.sqrt( (testee[I][0]-pyscf_common.Rnuc_[I][0])**2 + + (testee[I][1]-pyscf_common.Rnuc_[I][1])**2 + + (testee[I][2]-pyscf_common.Rnuc_[I][2])**2 ) for I in range(Nat) ] + strbuf="" + for I in range(Nat): + strbuf+=" %12.6f %12.6f %12.6f / %12.6f %12.6f %12.6f %e \n"%( + testee[I][0],testee[I][1],testee[I][2], + pyscf_common.Rnuc_[I][0],pyscf_common.Rnuc_[I][1],pyscf_common.Rnuc_[I][2], diffs[I]) + + strbuf+=" \t\t "+str(datetime.datetime.now()) + print("#Check:%s:$%02d:!W: %s"%(caller,MPIrank,strbuf),file=fdOU) + fdOU.close() + return dev + @staticmethod + def Set_Rnuc(Rnuc,step=None,time_AU=None,Logging=[0],sync=False ): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + AUinFS=2.418884326058678e-2 + + strRnuc="" + Nat=len(Rnuc) + for I in range(Nat): + strRnuc+=("" if(I==0) else ";")+"%12.6f,%12.6f,%12.6f"%(Rnuc[I][0],Rnuc[I][1],Rnuc[I][2]) + logfpath = "Set_Rnuc_%02d.log"%(MPIrank) + if( sync ): + print("#Set_Rnuc:Bcast..") + comm.Bcast(Rnuc,root=0) + fd1=open(logfpath,"a"); + strlog="#Bcast:" + strlog+=strRnuc + if( step is not None ): strlog+=" step=%d"%(step); + if( time_AU is not None ): strlog+=" time=%14.5f,%12.4f"%(time_AU,time_AU*AUinFS) + strlog+=" \t\t "+str( datetime.datetime.now() ) + print(strlog,file=fd1) + fd1.close() + + diffs=None + if( pyscf_common.Rnuc_ is not None ): + Nat=len( pyscf_common.Rnuc_ ) + diffs=[ np.sqrt( (Rnuc[I][0]-pyscf_common.Rnuc_[I][0])**2 + + (Rnuc[I][1]-pyscf_common.Rnuc_[I][1])**2 + + (Rnuc[I][2]-pyscf_common.Rnuc_[I][2])**2 ) for I in range(Nat) ] + dev=max( diffs ) + + if( Logging is not None ): + if( MPIrank in Logging ): + path="Set_Rnuc_%02d.log"%(MPIrank) + fdOU=open(path,"a") + strbuf="" + strbuf +=strRnuc + if( step is not None ): strbuf+=" step=%d"%(step); + if( time_AU is not None ): strbuf+=" time=%14.5f,%12.4f"%(time_AU,time_AU*AUinFS) + strbuf+=" \t\t "+str( datetime.datetime.now() ) + print(strbuf,file=fdOU);fdOU.close() + print("#Set_Rnuc:"+strbuf, diffs) + + + Ndim=np.shape(Rnuc) + if( step is not None ): + pyscf_common.step_=step + if( time_AU is not None ): + pyscf_common.time_AU_=time_AU + print("#pyscf_common.Rnuc:$%02d:set:"%(MPIrank),Rnuc,step,time_AU) + rank=len(Ndim);assert rank==1 or rank==2,"" + pyscf_common.Rnuc_=np.zeros(Ndim,dtype=np.float64) + if(rank==2): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + pyscf_common.Rnuc_[I][J]=Rnuc[I][J] + else: + for I in range(Ndim[0]): + pyscf_common.Rnuc_[I]=Rnuc[I] + + @staticmethod + def Get_Rnuc(clone=False): + if(not clone): + return pyscf_common.Rnuc_ + + Ndim=np.shape(pyscf_common.Rnuc_) + rank=len(Ndim);assert rank==1 or rank==2,"" + ret=np.zeros(Ndim,dtype=np.float64) + if(rank==2): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + ret[I][J]=pyscf_common.Rnuc_[I][J] + else: + for I in range(Ndim[0]): + ret[I]=pyscf_common.Rnuc_[I] + return ret + + @staticmethod + def Assert(bool,text,severity): + if(bool): + return 0 + pyscf_common.Print_warning(text,severity=severity) + if( severity<0 ): + assert False,""+text + @staticmethod + def Print_warning(text,severity=1): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if( severity>=0 and MPIrank>0 ): + return + Append=True + if( pyscf_common._Warning_logfile is None ): + pyscf_common._Warning_logfile=("pyscf_" if(pyscf_common.job is None) else pyscf_common.job)\ + +"_warning.log" + Append=False + fd=open( pyscf_common._Warning_logfile,('a' if(Append) else 'w')) + print(text+" \t\t"+str(datetime.datetime.now()),file=fd) + fd.close() + + @staticmethod + def Write_once(key,text,fpath=None,filename=None,Append=False,stdout=True): + if( key in pyscf_common._Keys_Write_once ): + return + else: + pyscf_common._Keys_Write_once.append(key) + fdA=[];fdOU=None + if(stdout or (fpath is None)): + fdA.append(sys.stdout) + + if(fpath is not None): + fdOU=open(fpath,('a' if(Append) else 'w')) + fdA.append(fdOU) + else: + if(filename is not None): + append_file=True + if( filename not in pyscf_common._Filenames ): + pyscf_common._Filenames.append( filename );append_file=False + fpath=pyscf_common.job+"_"+filename+".log" + ## print("Write_once:%s %r"%(fpath,append_file)) + fdOU=open(fpath,('a' if(append_file) else 'w')) + fdA.append(fdOU) + for fd in fdA: + print(key+":"+text,file=fd) + if(fdOU is not None): + fdOU.close() + + @staticmethod + def Dict_setv(key,val): + ### print("#pyscf_common:Dict_setv:%s:%s"%(str(key),str(val))) + pyscf_common._Dict.update({key:val}) + @staticmethod + def Dict_popv(key,default=None): + print("#pyscf_common:Dict_popv:%s:%s..."%( + str(key),("none" if(key not in pyscf_common._Dict) else str(pyscf_common._Dict[key])) )) + if( key in pyscf_common._Dict ): + return pyscf_common._Dict.pop(key) + else: + return default + @staticmethod + def Dict_getv(key,default=None): + ### print("#pyscf_common:Dict_getv:%s:%s..."%( + ### str(key),("none" if(key not in pyscf_common._Dict) else str(pyscf_common._Dict[key])) )) + if( key in pyscf_common._Dict ): + return pyscf_common._Dict[key] + else: + return default + + ### Nat=None;nAO=None;nMO=None;nKpoints=None + @staticmethod + def Set_iVerbose(level): + pyscf_common._iVerbose=level + + @staticmethod + def Setup(bfsz=5): + if( pyscf_common._Time_000 is None ): + pyscf_common._Time_000=time.time() + if( pyscf_common.KeyHistory is None ): + pyscf_common.KeyHistory=Stack(bfsz) + if( pyscf_common.Logwriter is None ): + pyscf_common.Logwriter=Filewriter(\ + ("pyscf_common" if (pyscf_common.job is None) else pyscf_common.job)\ + + "_logger.log" ) + @staticmethod + def Clock000(set_if_none=True): + if( pyscf_common._Time_000 is not None ): + return pyscf_common._Time_000 + else: + if( not set_if_none ): + return None + else: + pyscf_common._Time_000=time.time() + return pyscf_common._Time_000 + + @staticmethod + def set_params(dict,job=None): + def get1(dic,key,default=None): + if(key in dic): + return dic[key] + else: + return default; + if( job is None): + job= get1(dict, "name","pySCF_job") + "_" + get1(dict,"xc","") + get1(dict, "basis","") + get1(dict,"branch","") + pyscf_common.job=job + pyscf_common.params=dict + pyscf_common.Setup() + + @staticmethod + def Get_time(): + return time.time()-pyscf_common._Time_000 +## def somefunc(...) +## depth=1 # 1 : SCF,eldyn_singlestep etc. +## wt_010= pyscf_common.Start_timer("",depth=depth) +## -- step1 -- +## pyscf_common.Switch_timer("","",depth=depth) +## -- step2 -- +## pyscf_common.Stop_timer("",depth=depth) +## pyscf_common.Start_timer("",depth=depth) +## wt_100=pyscf_common.Get_time() +## pyscf_common.Print_timing("", ["",'','',''], +## walltime=wt_100-wt_010,depth=depth) + @staticmethod + def get_MPIrank(format=None): + comm = MPI.COMM_WORLD + size = comm.Get_size() + rank = comm.Get_rank() + if( format is not None ): + return format%(rank) + return rank + + @staticmethod + def get_MPIsize(format=None): + comm = MPI.COMM_WORLD + size = comm.Get_size() + if( format is not None ): + return format%(size) + return size + + + @staticmethod + def Start_timer(key,flush=False,depth=1): + if( pyscf_common._Time_000 is None ): + pyscf_common.Setup() + pyscf_common.wt_010.update({key: time.time() - pyscf_common._Time_000}) + oldky=pyscf_common.Key + if( oldky is not None ): + pyscf_common.KeyHistory.append(oldky); + pyscf_common.Key=key + + ### print("#Start_timer:"+str(oldky)+" >> current:"+str(pyscf_common.Key)) + if( flush or pyscf_common._iVerbose>1): + header='#'*(2*depth) + pyscf_common.Logwriter.append( header + "start:%24s %14.4f "%(key, pyscf_common.wt_010[key]) + +" \t\t\t "+("" if(pyscf_common.job is None) else pyscf_common.job) + + " "+str(datetime.datetime.now())) + return pyscf_common.wt_010[key] + @staticmethod + def Switch_timer(key1,key2,flush=False,depth=1): + ### print("#Switch_timer:BF:"+str(key1)+" /current:"+str(pyscf_common.Key)) + ret= pyscf_common.Stop_timer(key1,key2=key2,flush=flush,depth=depth) + ### print("#Switch_timer:AF:"+str(key2)+" /current:"+str(pyscf_common.Key)) + return ret + @staticmethod + def Stop_timer(key,key2=None,flush=False,depth=1,subkey=""): + ### print("#stop_timer:"+key+" current:"+str(pyscf_common.Key)) + wctNow=time.time() - pyscf_common._Time_000 +# if( key == pyscf_common.Key ): + if( key in pyscf_common.wt_010 ): + if( key in [ 'get_veff', 'get_j'] ): + key1=key+"_1st" + if( key1 not in pyscf_common.Timing): + pyscf_common.Update_timing( key1, wctNow-pyscf_common.wt_010[key], flush=flush) + else: + key2=key+"_2nd";tCUR=wctNow-pyscf_common.wt_010[key] + key_to_upd=key2 + if( key2 in pyscf_common.Timing): + av = pyscf_common.Timing[key2]['sum']/pyscf_common.Timing[key2]['count'] + stdv = np.sqrt( abs( pyscf_common.Timing[key2]['sqrsum']/pyscf_common.Timing[key2]['count'] - av**2 ) ) + av_1 = pyscf_common.Timing[key1]['sum']/pyscf_common.Timing[key1]['count'] + stdv_1 = np.sqrt( abs( pyscf_common.Timing[key1]['sqrsum']/pyscf_common.Timing[key1]['count'] - av_1**2 ) ) + if( abs(av - tCUR)> max(1.0, stdv)*3 ): + if( abs(av_1-tCUR)1): + header='#'*(2*depth) + pyscf_common.Logwriter.append( header + "END:%24s %14.4f %14.4f"%(key, wctNow-pyscf_common.wt_010[key], wctNow) + +" \t\t\t "+("" if(pyscf_common.job is None) else pyscf_common.job) + + " "+str(datetime.datetime.now())) + + pyscf_common.Key=None; pyscf_common.wt_010.pop(key,None) + else: + pyscf_common.Logwriter.append("## key:%s did not end tmNow:%f"%(key,wctNow)) + ### pyscf_common.Key=None; pyscf_common.wt_010=None + if( flush or pyscf_common._iVerbose>1): + header='#'*(2*depth) + pyscf_common.Logwriter.append( header + "END:%24s %14s %14.4f"%(key, "--", wctNow) + +" \t\t\t "+("" if(pyscf_common.job is None) else pyscf_common.job) + + " "+str(datetime.datetime.now())) + if( key2 is None ): + return wctNow + else: + ### print("#Switching to:"+str(key2)) + return pyscf_common.Start_timer(key2) + @staticmethod + def Update_timing(key,walltime,flush=False,doNotPrtOut=False): + if( key not in pyscf_common.Timing ): + pyscf_common.Timing.update({key:{'count':0,'sum':0.0,'sqrsum':0.0}}) + pyscf_common.Timing[key]['count']+=1 + pyscf_common.Timing[key]['sum']+=walltime + pyscf_common.Timing[key]['sqrsum']+=walltime**2 + ncount=pyscf_common.Timing[key]['count'] + ### print("#pyscf_common.Update_timing:%s:%d"%(key,ncount)) + if( not doNotPrtOut ): + if( ncount == 1 or ncount==10 or ncount==20 or ncount == 100 or ncount== 200 or ncount==1000 ): + avg= pyscf_common.Timing[key]['sum'] / pyscf_common.Timing[key]['count'] + stdv=np.sqrt( abs( pyscf_common.Timing[key]['sqrsum'] / pyscf_common.Timing[key]['count'] - avg**2 ) ) + pyscf_common.Logwriter.append("#AvgTime:%24s %14.4f %14.4e %d %14.4f avg/stdv/count/sum"%(key,avg,stdv, + pyscf_common.Timing[key]['count'], pyscf_common.Timing[key]['sum'])) + return pyscf_common.Timing[key]['count'] + @staticmethod + def Print_timing(name,keys,walltime=None,flush=False,depth=1,N_iter=None,subkey=""): + ### print("#pyscf_common.print_timing.."); + if( N_iter is not None ): + ky1=name+"_N_iter" + pyscf_common.Update_timing(ky1,N_iter,flush=False,doNotPrtOut=False) + if(ky1 not in keys): + keys.append(ky1) + if( name in [ 'get_veff', 'get_j', 'Get_Veff'] ): + name1=name+"_1st" + if( name1 not in pyscf_common.Timing): + pyscf_common._Print_timing( name1, keys, walltime=walltime, flush=flush, depth=depth) + else: + name2=name+"_2nd" + name_upd=name2 + if( name2 in pyscf_common.Timing ): + av = pyscf_common.Timing[name2]['sum']/pyscf_common.Timing[name2]['count'] + stdv = np.sqrt( abs( pyscf_common.Timing[name2]['sqrsum']/pyscf_common.Timing[name2]['count'] - av**2 ) ) + av_1 = pyscf_common.Timing[name1]['sum']/pyscf_common.Timing[name1]['count'] + stdv_1 = np.sqrt( abs( pyscf_common.Timing[name1]['sqrsum']/pyscf_common.Timing[name1]['count'] - av_1**2 ) ) + if( abs(av - walltime)> max(1.0, stdv)*3 ): + ### ??? XXX XXX if( abs(av_1-walltime)1): + header='#'*(2*depth) + strtm=("--" if(walltime is None) else "%14.4f"%(walltime)) + pyscf_common.Logwriter.append( header + "END:%24s %14s %14.4f"%(name, strtm, wctNow) + +" \t\t\t "+("" if(pyscf_common.job is None) else pyscf_common.job) + + " "+str(datetime.datetime.now())) + + if( ncount == 1 or ncount==10 or ncount==20 or ncount == 100 or ncount== 200 or ncount==1000 ): + string="";legend="";ncol=0 + for key in keyAL: + if( key not in pyscf_common.Timing ): + keyset=[ ky for ky in pyscf_common.Timing ] + print("#!W %s not in Timing:"%(key)+str(keyset));continue + avg= pyscf_common.Timing[key]['sum'] / pyscf_common.Timing[key]['count'] + stdv=np.sqrt( abs( pyscf_common.Timing[key]['sqrsum'] / pyscf_common.Timing[key]['count'] - avg**2 ) ) + string+=" %18.4f %18.4e %8d %18.4f "%(avg,stdv, + pyscf_common.Timing[key]['count'], pyscf_common.Timing[key]['sum']) + legend+=" %4d:%24s_%24s_av,stdv,cnt,sum "%(ncol+1,key,name) + ncol+=4 + fdOu=open( fpath,('w' if(ncount==1) else 'a')) + if( ncount==1 ): + print(legend,file=fdOu); + print(string,file=fdOu); + fdOu.close() + return ncount + @staticmethod + def Log(text,fnme=None,stdout=True,flush=False): + if(fnme is not None): + fd1=open(fnme,"a");print(text,file=fd1);fd1.close() + if(stdout): + print(text); + + @staticmethod + def Countup(key,inc=True): ## by default 1,2,3,... + if( key not in pyscf_common._Counter ): + if( not inc ): + return 0 + else: + pyscf_common._Counter.update({key:0}) + if(inc): + pyscf_common._Counter[key]+=1 + return pyscf_common._Counter[key] + + @staticmethod + def count(key,inc=False): + + if(key in pyscf_common.dic): + if(inc): + pyscf_common.dic[key]=pyscf_common.dic[key]+1 + return pyscf_common.dic[key] + else: + ret=0 + if(inc): + ret+=1 + pyscf_common.dic.update( {key:ret} ) + return ret; + @staticmethod + def Append_SCFwarning(item,i_SCF=None): + if( i_SCF is None ): + i_SCF = pyscf_common.n_SCF + if( item not in pyscf_common.SCF_warnings ): + pyscf_common.SCF_warnings.update({item:{'count':0,'i_SCF':Stack(5)}}) + pyscf_common.SCF_warnings[item]['count']+=1 + if( not pyscf_common.SCF_warnings[item]['i_SCF'].contains(i_SCF) ): + pyscf_common.SCF_warnings[item]['i_SCF'].append(i_SCF) + + @staticmethod + def Setup_SCFbuf(): + if( len(pyscf_common.SCF_buf)==0 ): + for I in range(pyscf_common.SCF_bfsz): + pyscf_common.SCF_buf.append({'iter':0, 'time':0, 'cvgd':None}) + pyscf_common.SCF_buf.append({'iter':{'sum':0.0,'sqrsum':0.0}, 'time':{'sum':0.0,'sqrsum':0.0} }) + @staticmethod + def Get_SCFresult(nth=0): + if( nth >= pyscf_common.SCF_bfsz): + return None + i_SCF= pyscf_common.n_SCF-1 - nth + if( i_SCF < 0 ): + return None + iMOD=i_SCF%pyscf_common.SCF_bfsz + return pyscf_common.SCF_buf[iMOD] + + @staticmethod + def Set_SCFresult(cvgd, iter, Egnd, time, warnings=None,dbuf=None): + import sys + import datetime + if( len(pyscf_common.SCF_buf)==0 ): + pyscf_common.Setup_SCFbuf() + pyscf_common.n_SCF+=1 + i_SCF= pyscf_common.n_SCF-1 + iMOD=i_SCF%pyscf_common.SCF_bfsz + pyscf_common.SCF_buf[iMOD]['cvgd']=cvgd + pyscf_common.SCF_buf[iMOD]['iter']=iter + pyscf_common.SCF_buf[iMOD]['time']=time + ### pyscf_common.SCF_buf[iMOD]['warnings'].clear() + pyscf_common.SCF_buf[pyscf_common.SCF_bfsz]['iter']['sum']+=iter + pyscf_common.SCF_buf[pyscf_common.SCF_bfsz]['iter']['sqrsum']+=iter**2 + + pyscf_common.SCF_buf[pyscf_common.SCF_bfsz]['time']['sum']+=time + pyscf_common.SCF_buf[pyscf_common.SCF_bfsz]['time']['sqrsum']+=time**2 + if( not cvgd ): + fdOU=open('SCF_failure_%05d.log'%(i_SCF),'a') + string="#SCF:%05d failed after %d iterations"%(i_SCF,iter)+" \t\t\t "+str(datetime.datetime.now()) + if( warnings is not None ): + for item in warnings: + string+='\n##!W: '+str(item) + for fd in [fdOU,sys.stdout]: + print(string,file=fd) + if( dbuf is not None ): + le=len(dbuf); + print("#%4s %16s %14s %14s"%('iter','Etot','|g|','ddm'),file=fdOU) + for I in range(le): + print(" %4d %16.8f %14.6e %14.6e"%(I,dbuf[I][0],dbuf[I][1],dbuf[I][2]),file=fdOU) + fdOU.close() + + if( warnings is not None ): + for item in warnings: + pyscf_common.Append_SCFwarning(item,i_SCF=i_SCF) + if( pyscf_common.n_SCF == 1 or pyscf_common.n_SCF==5 or pyscf_common.n_SCF==10 or pyscf_common.n_SCF == 20 or + pyscf_common.n_SCF %100==0 ): + fpath=("" if(pyscf_common.job is None) else pyscf_common.job)+"_SCF.log" + pyscf_common.Print_SCFresults( fpath,Append=( pyscf_common.n_SCF>1 )) + @staticmethod + def Print_SCFresults(fpath=None,Append=False): + fdA=[ sys.stdout ] + fdout=(None if(fpath is None) else open(fpath,('a' if(Append) else 'w'))) + if(fdout is not None): + fdA.append(fdout) + Dic=pyscf_common.SCF_buf[pyscf_common.SCF_bfsz] + strWarning="" + for key in pyscf_common.SCF_warnings: + wdict= pyscf_common.SCF_warnings[key] + strWarning +=key+":%3d / %4d"%( pyscf_common.SCF_warnings[key]['count'],pyscf_common.n_SCF ) \ + +str( pyscf_common.SCF_warnings[key]['i_SCF'].toarray() ) + if( len(strWarning.strip())>0 ): + strWarning=" Warning:"+strWarning + for fd in fdA: + is_stdout=(fd==sys.stdout) + av_iter=Dic['iter']['sum']/float(pyscf_common.n_SCF) + stdv_iter=np.sqrt( abs( Dic['iter']['sqrsum']/float(pyscf_common.n_SCF) -av_iter**2 ) ) + + av_time=Dic['time']['sum']/float(pyscf_common.n_SCF) + stdv_time=np.sqrt( abs( Dic['time']['sqrsum']/float(pyscf_common.n_SCF) -av_iter**2 ) ) + if( (not Append) and (fdout is not None) and fd==fdout ): + print("#%6s %6s %14s %14s %14s %14s %14s %14s "%("n_SCF", + "sum_iter","avg_iter","stdv_iter", + "sum_time","avg_time","stdv_time","per-iter-time"),file=fd) + + # ITER TIME + # n_SCF sum av stdv sum av stdv PER-ITER-time + print("%s %6d %6d %14.6f %14.4e %14.6f %14.6f %14.4e %14.6f "%( + ("#SCFresults:" if(is_stdout) else ""), pyscf_common.n_SCF, + Dic['iter']['sum'], av_iter, stdv_iter, + Dic['time']['sum'], av_time, stdv_time, Dic['time']['sum']/float(Dic['iter']['sum'])) + +strWarning,file=fd) + if(fdout is not None): + fdout.close() + + +def parse_xyzstring(str,unit_BorA): + assert (unit_BorA=='B' or unit_BorA=='A'),"" + fac=1.0 + if( unit_BorA=='B' ): + BOHRinANGS=0.5291772105638411 + fac=1.0/BOHRinANGS ## converts from ANGS to BOHR + arr=str.split('\n') + nl=0;Nat=-1 + R=[];Sy=[]; + for line in arr: + ## print("#parse_xyzstring:"+line) + line=line.strip() + Cols=line.split(';') + for col in Cols: + col=col.strip(); + if(col==""): + continue + arr=col.split() + if(len(arr)==0): + continue + Sy.append(arr[0].strip()) + R.append([ float(arr[1])*fac,float(arr[2])*fac,float(arr[3])*fac]) + ## print("#parse_xyzstring:returns:",R) + return R,Sy +def write_xyzstring(R,Sy,input_unit,output_unit='A'): + if( output_unit==input_unit ): + str=""; + Nat=len(Sy) + for Iat in range(Nat): + str+="%s %f %f %f\n"%(Sy[Iat],R[Iat][0],R[Iat][1],R[Iat][2]); + return str; + + assert output_unit=='A',"" + assert input_unit=='B',"" + fac=1.0 + if( input_unit=='B' and output_unit=='A'): + BOHRinANGS=0.5291772105638411 + fac=BOHRinANGS ## 0.5291... + str=""; + Nat=len(Sy) + for Iat in range(Nat): + str+="%s %f %f %f\n"%(Sy[Iat],R[Iat][0]*fac,R[Iat][1]*fac,R[Iat][2]*fac); + return str; + + +def sync_Rnuc(cell,who_am_I=""): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + Rnuc_au,Sy=parse_xyzstring(cell.atom,unit_BorA='B') + Rnuc_refr=pyscf_common.Get_Rnuc();step=pyscf_common.step_;time_AU=pyscf_common.time_AU_ + if( step is None ):step=-1 + if( time_AU is None ):time_AU=0.0 + if( Rnuc_refr is not None ): + Rdiff = max( np.ravel(Rnuc_au)- np.ravel( Rnuc_refr ) ) + print("#dbgng_20211229:aft.py.625:Rdiff:@%s %e %d,%f:"%(who_am_I,Rdiff,step,time_AU)+str(Rnuc_au)+"/"+str( Rnuc_refr )) + assert Rdiff<1.0e-6,"" + if(MPIsize > 1 ): + Rnuc_1D=np.ravel(Rnuc_au);le=len(Rnuc_1D) + Rnuc_1D_sync=np.zeros([le]) + for j in range(le): + Rnuc_1D_sync[j]=Rnuc_1D[j] + comm.Bcast(Rnuc_1D_sync,root=0) + dev=max( abs(Rnuc_1D_sync-Rnuc_1D) ) + step=pyscf_common.step_ + step=( -1 if(step is None) else step ) + fd=open("sync_Rnuc_%02d.log"%(MPIrank),"a") + print("#sync_Rnuc:%06d:%02d: %e"%(step,MPIrank,dev)+str(datetime.datetime.now()),file=fd) + if( dev >= 1e-6 ): + print("#sync_Rnuc:",[ "%14.6f"%(Rnuc_1D_sync[k]) for k in range(le) ], + [ "%14.6f"%(Rnuc_1D[k]) for k in range(le) ] ,file=fd) + Nat=le//3 + Rnuc_sync = np.reshape( Rnuc_1D_sync, [Nat,3] ) + cell.atom=write_xyzstring( Rnuc_sync, Sy,input_unit='B',output_unit='A') + fd.close() + ## assert dev<1.0e-6,"sync:%e"%(dev) diff --git a/pyscf/rttddft/rttddft01.py b/pyscf/rttddft/rttddft01.py new file mode 100644 index 000000000..9dbe8165a --- /dev/null +++ b/pyscf/rttddft/rttddft01.py @@ -0,0 +1,2502 @@ +import numpy as np +import os +import time +import sys +import math +import cmath +import datetime +from scipy import linalg +from mpi4py import MPI + +from pyscf.pbc.gto import intor_cross +from pyscf.pbc.dft.krks import KRKS +### from krks01 import KRKS01 +from pyscf.dft.rks import RKS +from scipy import linalg +from pyscf.lib import logger as pyscflib_logger +from .rttddft_common import rttddft_common +from pyscf.lib import logger as pyscflib_logger +from pyscf import lib +import pyscf.gto as molgto +from pyscf.pbc.gto import Cell +from pyscf.pbc import gto, scf, dft +from pyscf.pbc.scf.khf import get_occ as khf_get_occ +from pyscf.pbc.scf.kuhf import get_occ as kuhf_get_occ +from pyscf.pbc.scf.khf import make_rdm1 as khf_make_rdm1 +from pyscf.pbc.dft import multigrid +from pyscf.pbc.dft import gen_grid +from pyscf.gto.mole import nao_cart +from pyscf import __config__ +from pyscf.pbc.dft import rks +from pyscf.pbc import df +from pyscf.lib import logger as pyscf_logger + +from pyscf.dft.rks import _dft_common_init_ + +from .Loglv import printout +from .heapcheck import heapcheck + +from .futils import futils +from .laserfield import * +from .Dbglogger import Dbglogger +from .diis01 import DIIS01 +from .Logger import Logger +from .GEAR import initz_rGEARvec, rGEAR2ndOne +from .serialize import is_method_or_function,serialize_listedfields,serialize_tdfield,svld_aNbuf + +# tostring,save_zbuf,write_aNbuf,fwrite_zNbuf,aNdiff,d3diff,read_matr,a1maxdiff,d2toa,z2toa,parse_xyzstring,write_xyzstring, +from .utils import parse_doubles,parse_dict,check_Hermicity_xKaa,calc_3Dvolume,update_dict,printout_dict,print_Hmatrices,\ +d1dist,i1eqb,z2diff,dNtoa,d1toa,z1toa,arrayclone,d1x2toa,aNmaxdiff,toComplexArray,write_once,print_z2array,iNtoa,d1diff,sNtoa,zNtoa,dist3D,\ +check_equivalence +from .Constants import Constants +from .physicalconstants import PhysicalConstants +from .gto_ps_pp_int01 import with_df_get_pp,with_df_get_ppxx +from .gto_ps_pp_int01_bf20210608 import with_df_get_pp as with_df_get_pp_bf20210608 +from .with_fftdf_get_pp import with_fftdf_get_pp + +def obj_to_string(val): + ## this is taken from my serialize.py ... + typ='';strval="" + if( val is None ): + typ='o';strval="None" + elif( isinstance(val,str) ): + Stdlogger.printout(2,key+":str",verbose=verbose) + typ='s';strval=str(val) + elif( isinstance(val,bool) ): ## << check bool first: isinstance( BOOLEAN, int ) returns -True- .. + Stdlogger.printout(2,key+":bool",verbose=verbose) + typ='b';strval=str(val) + elif( isinstance(val,int) ): + Stdlogger.printout(2,key+":int",verbose=verbose) + typ='i';strval="%d"%(val) + elif( isinstance(val,float) or isinstance(val,np.float64) ): + Stdlogger.printout(2,key+":float",verbose=verbose) + typ='d';strval="%24.12e"%(val) + elif( isinstance(val,complex) or isinstance(val,np.complex128) ): + Stdlogger.printout(2,key+":complex",verbose=verbose) + typ='z';strval="%24.12e %24.12e"%(val.real, val.imag) + elif( isinstance(val,list) or isinstance(val,np.ndarray) ): + Stdlogger.printout(2,key+":list_or_ndarray:"+str(val),verbose=verbose) + Ndim=np.shape(val) + a1D =np.ravel( np.array(val) );dty=a1D.dtype + if( len(a1D) == 0 ): + if( isinstance(val,list) ): + typ='I0';strval="" + else: + typ=('I0' if(val.dtype==int) else ('D0' if(val.dtype==float or val.dtype==np.float64) else + ('Z0' if(val.dtype==complex or val.dtype==np.complex128) else 'S0')));strval="" + else: + if( type(a1D[0])==str or type(a1D[0])==np.str_ ): + typ='S'+iNtoa(Ndim,delimiter=',');strval=sNtoa(val,delimiter=" ") + else: + if( dty==int ): + typ='I'+iNtoa(Ndim,delimiter=',');strval=iNtoa(val,delimiter=" ") + elif( dty==float or dty==np.float64 ): + typ='D'+iNtoa(Ndim,delimiter=',');strval=dNtoa(val,format="%24.12e",delimiter=" ") + elif( dty==complex or dty==np.complex128 ): + typ='Z'+iNtoa(Ndim,delimiter=',');strval=zNtoa(val,format="%24.12e %24.12e", delimiter=" ") + ### elif( dty==str ): + ### typ='S'+iNtoa(Ndim,delimiter=',');strval=sNtoa(val,delimiter=" ") + else: + strval=str(val); + print("#serialize:"+"dty:"+str(dty)+" KEY:"+str(key)+" type:"+str(type(val))) + print("#serialize:"+str(val)) + Stdlogger.printout(1,"#Serialize:"+header+str(type(obj))+":"+str(obj),verbose=verbose) + Stdlogger.printout(1,"key:"+str(key)+" type:"+str(type(val))+" dtype:"+str(np.array(val).dtype)+" val:"+str(val),verbose=verbose) + ### assert False,"dty:"+str(dty)+" KEY:"+str(key)+" type:"+str(type(val)) + elif( isinstance(val,dict) ): + if( len(val) == 0 ): + typ='dict';strval="{}" + else: + typ='dict';strval=None + for ky in val: + if(strval is None): + strval="{"+ str(ky).strip() + ","+ str( val[ky] ).strip() + else: + strval+=","+ str(ky).strip() + ","+ str( val[ky] ).strip() + strval+="}" + return strval +def get_Ssqrt_invsqrt_sINV(S): + Ssqrt,Invrt,sINV = get_Ssqrt_invsqrt_sINV_1(S) + N=len(S) + dum=np.zeros([N,N],dtype=np.complex128) + dum=np.matmul( Ssqrt, Ssqrt) + dev1=z2diff( S, dum);### , title="|Ssqrt**2-S|"); + Logger.write_maxv(None,"Ssqrt_dev",dev1); + dum=np.matmul( Invrt, Ssqrt ) + dev2=z2diff( dum, np.eye(N,dtype=np.complex128));###,title="|Invrt*Ssqrt-1|") + Logger.write_maxv(None,"invSsqrt_dev",dev2); +## + dum=np.matmul( Invrt, np.matmul( S, Invrt) ) + dev3=z2diff( dum, np.eye(N,dtype=np.complex128)); + Logger.write_maxv(None,"invSsqrt_dev3",dev3); ### print("#invSsqrt_dev3:",dev3) + return Ssqrt,Invrt,sINV + +# S V = V \Lambda so S = V \Lambda V^{\dagger} +# S[I][:] = V[I][k] Lambda[k] conjg( V[:][k] ) +def get_Ssqrt_invsqrt_sINV_1(S): + N=len(S) + dtype=np.array(S).dtype + ### print("get_Ssqrt_invsqrt:",end="");print(dtype) + iscomplex=False + if( dtype == complex ): + iscomplex=True + eigvals,vecs,info=linalg.lapack.zheev(S) + else: + eigvals,vecs,info=linalg.lapack.dsyev(S) + assert (info==0),"dsyev/zheev failed" + # print("S_eigvals:",end="");print(eigvals) + Ssqrt=np.zeros([N,N],dtype=dtype) + InvSqrt=np.zeros([N,N],dtype=dtype) + sINV=np.zeros([N,N],dtype=dtype) + for I in range(N): + for J in range(N): + cdum=( np.complex128(0.0) if(iscomplex) else 0.0) + for k in range(N): + cdum+= vecs[I][k]*math.sqrt(eigvals[k])*np.conj( vecs[J][k]) + Ssqrt[I][J]=cdum + + cdum=( np.complex128(0.0) if(iscomplex) else 0.0) + for k in range(N): + cdum+= vecs[I][k]*(1.0/math.sqrt(eigvals[k]))*np.conj( vecs[J][k]) + InvSqrt[I][J]=cdum + + cdum=( np.complex128(0.0) if(iscomplex) else 0.0) + for k in range(N): + cdum+= vecs[I][k]*(1.0/eigvals[k])*np.conj( vecs[J][k]) + sINV[I][J]=cdum + + return Ssqrt,InvSqrt,sINV; + +def suppress_prtout(): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); + return ( MPIrank!=0 ) + +def list_to_array(src): + dbgng=True;dbglog="" + if( dbgng ): + dbglog+="#list_to_array:INPUT:"+str(type(src))+str(np.shape(src))+"\n" + retv=np.array(src) + if( dbgng ): + dbglog+="#list_to_array:OUTPUT:"+str(type(retv))+str(np.shape(retv))+"\n" + Ndim=np.shape(retv);rank=len(Ndim) + if( rank > 1 ): + for I in range(Ndim[0]): + dbglog+="#list_to_array:OUTPUT:[%d]:"%(I)+str(type(retv[I]))+str(np.shape(retv[I]))+"\n" + printout(dbglog,fpath="list_to_array_DBG.log",Append=True) + return retv + +class Dipoles_static: + Diff_moldip_eldip_=None + + +def dmtrace_xKaa(matr,comp,dmat,pbc,spinrestriction,dict=None): + if( spinrestriction == 'R' ): + return dmtrace_xKaa1(matr,comp,dmat,pbc,dict=dict) + else: + return dmtrace_xKaa1(matr,comp,dmat[0],pbc,dict=dict),dmtrace1(matr,comp,dmat[1],pbc,dict=dict) +def dmtrace_xKaa1(matr,comp,dmat,pbc,dict=None): + ndim=np.shape(dmat) + nkpt=1;nAO=ndim[0]; # dmat[nAO][nAO] + if( pbc ): # dmat[nKpt][nAO][nAO] + nkpt=ndim[0];nAO=ndim[1] + wks=np.zeros([nAO,nAO],dtype=np.complex128) + + ndim_matr=np.shape(matr) + if( not pbc ): ## non-pbc [comp][nAO][nAO] + assert( ndim_matr[0]==comp and ndim_matr[1]==nAO),""+str(ndim_matr) + else: ## pbc [comp][nKpt][nAO][nAO] + assert( ndim_matr[0]==comp and ndim_matr[1]==nkpt and ndim_matr[2]==nAO),""+str(ndim_matr) + + if( not pbc ): + ret=[] + for dir in range(comp): + wks=np.matmul( matr[dir],dmat) + cum=wks[0][0] + for I in range(1,nAO): + cum+=wks[I][I] + ret.append(cum) + return np.array(ret) + else: + ## print("#dmtrace:DMshape",end="");print(np.shape(dmat)) + ## print("#dmtrace:MATshape",end="");print(np.shape(matr)) + ret=[] + for dir in range(comp): + buf=[] + for kp in range(nkpt): + wks=np.matmul( matr[dir][kp],dmat[kp]) + cum=wks[0][0] + for I in range(1,nAO): + cum+=wks[I][I] + buf.append(cum) + tot=sum(buf) + avg=tot/float(nkpt) + ## print("#dipole_%d:"%(dir)+z1toa(buf)+" avg(/%d):%f+j%f"%(nkpt,avg.real, avg.imag)) + ret.append(avg) + return np.array(ret) + +def dmtrace(matr,comp,dmat,pbc,spinrestriction,dict=None): + # spin-sym: + # non-pbc : matr[comp][nAO][nAO] dmat[nAO][nAO] >> ret[comp] + # pbc : matr[nkpt][comp][nAO][nAO] dmat[nkpt][nAO][nAO] >> ret[comp] ## avgd over kpts + # spin-pol + # non-pbc : matr[comp][nAO][nAO] dmat[2][nAO][nAO] >> ret[spin][comp] + # pbc : matr[nkpt][comp][nAO][nAO] dmat[2][nkpt][nAO][nAO]>> ret[spin][comp] + if( spinrestriction == 'R' ): + return dmtrace1(matr,comp,dmat,pbc,dict=dict) + else: + return dmtrace1(matr,comp,dmat[0],pbc,dict=dict),dmtrace1(matr,comp,dmat[1],pbc,dict=dict) + +def dmtrace1(matr,comp,dmat,pbc,dict=None): + ndim=np.shape(dmat) + nkpt=1;nAO=ndim[0]; + if( pbc ): + nkpt=ndim[0];nAO=ndim[1] + wks=np.zeros([nAO,nAO],dtype=np.complex128) + + ndim_matr=np.shape(matr) + if( not pbc ): + assert( ndim_matr[0]==comp and ndim_matr[1]==nAO),""+str(ndim_matr) + else: + assert( ndim_matr[0]==nkpt and ndim_matr[1]==comp and ndim_matr[2]==nAO),""+str(ndim_matr) + + if( not pbc ): + ret=[] + for dir in range(comp): + wks=np.matmul( matr[dir],dmat) + cum=wks[0][0] + for I in range(1,nAO): + cum+=wks[I][I] + ret.append(cum) + return np.array(ret) + else: + ## print("#dmtrace:DMshape",end="");print(np.shape(dmat)) + ## print("#dmtrace:MATshape",end="");print(np.shape(matr)) + ret=[] + for dir in range(comp): + buf=[] + for kp in range(nkpt): + wks=np.matmul( matr[kp][dir],dmat[kp]) + cum=wks[0][0] + for I in range(1,nAO): + cum+=wks[I][I] + buf.append(cum) + tot=sum(buf) + avg=tot/float(nkpt) + ## print("#dipole_%d:"%(dir)+z1toa(buf)+" avg(/%d):%f+j%f"%(nkpt,avg.real, avg.imag)) + ret.append(avg) + return np.array(ret) + +def check_hermicity_dm(this, densitymatrix, sqrSums=None, DAGthr=-1.0, OFDthr=-1.0, title="", verbose=0): + + spinrestriction=this._spinrestriction + pbc=this._pbc + nspin=(1 if(spinrestriction=='R') else 2) + OFDdev=-1;OFDvals=None;OFDindcs=None;sqrsum=0.0 + DAGdev=-1;DAGval=None; DAGindex=None + max_Im=-1;val=None;index=None + sqrsum_Re=0.0; sqrsum_Im=0.0 + S1e=None + if( not pbc ): + S1e=this.get_ovlp() + for spin in range(nspin): + dmat = ( densitymatrix if(nspin==1) else densitymatrix[spin] ) + Ndim=np.shape(dmat) + nKpt=(1 if(not pbc) else Ndim[0]) + nAO=(Ndim[0] if(not pbc) else Ndim[1]) + kvectors=(None if(not this._pbc) else np.reshape( this.kpts, (-1,3)) ) + + for kp in range(nKpt): + if(pbc): + S1e =this.get_ovlp( this.cell, kvectors[kp]) + dm=( dmat if(not pbc) else dmat[kp]) + for mu in range(nAO): + for nu in range(mu): + dum=abs( dm[mu][nu] - np.conj( dm[nu][mu] )) + if( dum > OFDdev): + OFDdev=dum;OFDvals=[ dm[mu][nu], dm[nu][mu] ];OFDindcs=[mu,nu] + if( max_Im < abs(dm[mu][nu].imag) ): + max_Im = abs(dm[mu][nu].imag); val=dm[mu][nu]; index=[mu,nu] + sqrsum_Re+=0.50* (dm[mu][nu].real + dm[nu][mu].real)*S1e[mu][nu] + sqrsum_Im+=0.50* (dm[mu][nu].imag - dm[nu][mu].imag)*S1e[mu][nu] + dum=abs( dm[mu][mu].imag ) + if(dum>DAGdev): + DAGdev=dum; DAGval= dm[mu][mu];DAGindex=mu + sqrsum_Re+= dm[mu][mu].real * S1e[mu][mu] + sqrsum_Im+= dm[mu][mu].imag * S1e[mu][mu] + # sqrsum_Re+= dm[mu][mu].real**2 + # sqrsum_Im+= dm[mu][mu].imag**2 + if(sqrSums is not None): + sqrSums.clear() + sqrSums.update({'real':sqrsum_Re,'imag':sqrsum_Im}) + prtout=(verbose>1);warn="" + if( DAGdev>1.0e-4 or OFDdev>1.0e-4 or (DAGthr>0 and DAGdev>0.1*DAGthr) or (OFDthr>0 and OFDdev>0.1*OFDthr) ): + prtout=True;warn="W!:" + if(prtout): + mu=OFDindcs[0];nu=OFDindcs[1] + printout("#check_hermicity_DM:"+warn+title+" dagdev=%16.6e [%d][%d]:%14.6f+j%14.6f ofddev=%16.6e [%d][%d]:%14.6f+j%14.6f / %14.6f+j%14.6f"%( + DAGdev,DAGindex,DAGindex,DAGval.real,DAGval.imag, + OFDdev,mu,nu, dm[mu][nu].real,dm[mu][nu].imag, dm[nu][mu].real,dm[nu][mu].imag)) + printout("#check_hermicity_DM:"+warn+title+" max_Im:%16.6e [%d][%d]:%14.6f+j%14.6f sqrSUM:%14.6f, %14.6f"%( + max_Im,index[0],index[1], dm[index[0]][index[1]].real, dm[index[0]][index[1]].imag,sqrsum_Re, sqrsum_Im)) + if(DAGthr > 0): + assert DAGdev 0): + assert OFDdev0 and dev>=dev_abort_thr): + assert False,"too large deviation from Nele:"+str(ret)+"/"+str(N_ele) + return ret; + +def get_HOMO(this,nth=0): + return get_LHomo(this,-1-nth) +def get_SOMO(this): + return get_LHomo(this,0) +def get_LUMO(this,nth=0): + return get_LHomo(this,1+nth) + +def krks_get_veff(ks, cell=None, dm=None, dm_last=0, vhf_last=0, hermi=1, + kpts=None, kpts_band=None): + ''' + modification of KRKS.get_veff + somehow we need a type cast onto complex + ''' + import time + from .utils import printout_dict,update_dict + + if( ks.nkpt is not None ): + assert ks.nkpt == len(ks.kpts),"%d/%s"%(ks.nkpt,str(np.shape(ks.kpts))); + fncnme='get_veff';fncdepth=1 ## fncdepth ~ SCF:0 vhf:1 get_j:2 + Wctm000=time.time();Wctm010=Wctm000;dic1={} + Dic=rttddft_common.Dict_getv('timing_'+fncnme, default=None) + if( Dic is None ): + rttddft_common.Dict_setv('timing_'+fncnme, {}); + Dic=rttddft_common.Dict_getv('timing_'+fncnme, default=None) + + if cell is None: cell = ks.cell + if dm is None: dm = ks.make_rdm1() + if kpts is None: kpts = ks.kpts + N_call=rttddft_common.Countup("krks_get_veff"); + check_timing_veff=(N_call<3 or N_call==20) # xxx xxx + t0 = (time.process_time(), time.perf_counter()) + AUinFS=2.418884326058678e-2 + rtTDDFT_Istep=rttddft_common.Dict_getv("rtTDDFT_Istep",0);rtTDDFT_Iter=rttddft_common.Dict_getv("rtTDDFT_Iter",0) + time_AU=(0.0 if(not hasattr(ks,"_time_AU")) else ks._time_AU); time_FS=time_AU*AUinFS + wt_010= rttddft_common.Start_timer("setup");wt_000=wt_010;timing={"misc":0.0} + omega, alpha, hyb = ks._numint.rsh_and_hybrid_coeff(ks.xc, spin=cell.spin) + hybrid = abs(hyb) > 1e-10 or abs(alpha) > 1e-10 + wt_020=wt_010;wt_010=rttddft_common.Stop_timer("setup");timing.update({"setup":wt_010-wt_020}) + ### wt_020=wt_010; wt_010=time.time(); Logger.UpdTiming('setup',wt_010-wt_020) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1,Dic,"setup",Wctm010-Wctm020,depth=fncdepth) + + if not hybrid and isinstance(ks.with_df, multigrid.MultiGridFFTDF): + n, exc, vxc = multigrid.nr_rks(ks.with_df, ks.xc, dm, hermi=hermi, + kpts=kpts, kpts_band=kpts_band, + with_j=True, return_j=False) + pyscflib_logger.debug(ks, 'nelec by numeric integration = %s', n) + t0 = pyscflib_logger.timer(ks, 'vxc', *t0) + return vxc + + # ndim = 3 : dm.shape = (nkpts, nao, nao) + ground_state = (isinstance(dm, np.ndarray) and dm.ndim == 3 and + kpts_band is None) +# For UniformGrids, grids.coords does not indicate whehter grids are initialized + if ks.grids.non0tab is None: + wt_020=wt_010;wt_010=rttddft_common.Start_timer("setup_grids");timing['misc']+=wt_010-wt_020 + ks.grids.build(with_non0tab=True) + if (isinstance(ks.grids, gen_grid.BeckeGrids) and + ks.small_rho_cutoff > 1e-20 and ground_state): + ks.grids = rks.prune_small_rho_grids_(ks, cell, dm, ks.grids, kpts) + ### wt_020=wt_010; wt_010=time.time(); Logger.UpdTiming('setup_grids',wt_010-wt_020) + wt_020=wt_010;wt_010=rttddft_common.Stop_timer("setup_grids");timing.update({"setup_grids":wt_010-wt_020}) + t0 = pyscflib_logger.timer(ks, 'setting up grids', *t0) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1,Dic,"setup_grids",Wctm010-Wctm020,depth=fncdepth) + + if hermi == 2: # because rho = 0 + n, exc, vxc = 0, 0, 0 + else: + ### print("#KRKS.veff:hermi(%d)/=2"%(hermi)) # 1 + wt_020=wt_010;wt_010=rttddft_common.Start_timer("nr_rks");timing['misc']+=wt_010-wt_020 + N_nr_rks=rttddft_common.Countup("krks_get_veff.nr_rks") + wt_x0=time.time(); + n, exc, vxc = ks._numint.nr_rks(cell, ks.grids, ks.xc, dm, hermi=0, + kpts=kpts, kpts_band=kpts_band) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1,Dic,"nr_rks",Wctm010-Wctm020,depth=fncdepth) + wt_020=wt_010;wt_010=rttddft_common.Stop_timer("nr_rks");timing.update({"nr_rks":wt_010-wt_020}) + wt_x1=time.time();wt_cur=wt_x1-wt_x0 + pyscflib_logger.debug(ks, 'nelec by numeric integration = %s', n) + t0 = pyscflib_logger.timer(ks, 'vxc', *t0) + + weight = 1./len(kpts) + if not hybrid: + wt_020=wt_010;wt_010=rttddft_common.Start_timer("get_j");timing['misc']+=wt_010-wt_020 + + vj = ks.get_j(cell, dm, hermi, kpts, kpts_band) + wt_020=wt_010;wt_010=rttddft_common.Stop_timer("get_j");timing.update({"get_j":wt_010-wt_020}) + + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1,Dic,"get_j",Wctm010-Wctm020,depth=fncdepth) + + if( (np.array(vxc).dtype == np.float64 or np.array(vxc).dtype == float) and + (np.array(vj).dtype == np.complex128 or np.array(vj).dtype == complex) ): + vxc=tocomplex(vxc) + vxc += vj + else: + ### print("#KRKS.veff:Hybrid") + if getattr(ks.with_df, '_j_only', False): # for GDF and MDF + ks.with_df._j_only = False + vj, vk = ks.get_jk(cell, dm, hermi, kpts, kpts_band) + vk *= hyb + if abs(omega) > 1e-10: + vklr = ks.get_k(cell, dm, hermi, kpts, kpts_band, omega=omega) + vklr *= (alpha - hyb) + vk += vklr + vxc += vj - vk * .5 + + if ground_state: + exc -= np.einsum('Kij,Kji', dm, vk).real * .5 * .5 * weight + + if ground_state: + wt_020=wt_010;wt_010=rttddft_common.Start_timer("ecoul");timing['misc']+=wt_010-wt_020 + + ecoul = np.einsum('Kij,Kji', dm, vj).real * .5 * weight + wt_020=wt_010;wt_010=rttddft_common.Stop_timer("ecoul");timing.update({"ecoul":wt_010-wt_020}) + ## wt_020=wt_010; wt_010=time.time(); Logger.UpdTiming('ecoul',wt_010-wt_020) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1,Dic,"ecoul",Wctm010-Wctm020,depth=fncdepth) + + else: + ecoul = None + + wt_020=wt_010; wt_010=rttddft_common.Get_time(); + + wt_100=rttddft_common.Get_time() + if( check_timing_veff ): + fpath1="rttddft_get_veff_timing.log" + legend="#%06s %6s %4s %14s \t\t %14s "%("N_call", "Istep", "Iter", "time_FS", "walltime") + text=" %06d %6d %4d %14.4f \t\t %14.4f "%(N_call, rtTDDFT_Istep, rtTDDFT_Iter, time_FS,wt_100-wt_000)\ + +str(timing) + printout("#rttddft.krks_get_veff:elapsed:%14.4f "%(wt_010-wt_000)+text) + if(N_call==1): + printout(legend,fpath=fpath1,Append=True,Threads=[0]) + printout(text,fpath=fpath1,Append=True,Threads=[0]) + ### fdOUT.close() + rttddft_common.Print_timing('Get_Veff',['setup',"setup_grids", "nr_rks","get_j_1st","get_j_2nd", "ecoul"], + walltime=wt_100-wt_000);timing.update({"Get_Veff":wt_100-wt_000}) + Wctm010=time.time() + printout_dict(fncnme,dic1,Dic,Wctm010-Wctm000,depth=fncdepth) + + vxc = lib.tag_array(vxc, ecoul=ecoul, exc=exc, vj=None, vk=None) + return vxc + +def get_Nele(this,Occ=None): + # Occ:[spin][nKpt][nMO] + if( Occ is None ): + Occ=this._mo_occ + + #print("#get_Nele:Occ:"+str(np.shape(Occ))) + #print("#get_Nele:Occ:"+str(Occ)) + + nspin=1; nKpt=1 +## 2021.05.24 fix if( this._spinrestriction == 'U'): + if( this._spinrestriction != 'R'): + assert len(Occ)==2,"";nspin=2 + Ndim1=np.shape(Occ[0]); + if( this._pbc ): ## [nKpt][nMO] + assert len(Ndim1)==2,""; nKpt=Ndim1[0]; + else: + Ndim1=np.shape(Occ); + if( this._pbc ): + assert len(Ndim1)==2,""; nKpt=Ndim1[0]; + + ret=[] + for spin in range(nspin): + occ1=( Occ if(nspin==1) else Occ[spin]) + tot=0.0 + for kp in range(nKpt): + occ11=( occ1 if(not this._pbc) else occ1[kp]); + cum=sum(occ11); + tot+=cum + if(this._pbc): + tot=tot/float(nKpt) + ret.append(tot) + if(nspin==1): + ret=ret[0]; + return ret + +def set_nOrbs(this,nkpt=None,nAO=None,nMO=None): + if( nkpt is not None ): + this.nkpt=nkpt + if( nAO is not None ): + this.nAO=nAO + if( nMO is not None ): + this.nMO=nMO + +def update_nOrbs(this,force=False): + ## non-PBC PBC + ## O,R nAO,nMO nKPT,nAO,nMO + ## U 2,nAO,nMO 2,nKPT,nAO,nMO + if( not force ): + if( (this.nAO is not None) and (this.nkpt is not None) and (this.nMO is not None) ): + return 0 + if( this.mo_coeff is None ): + assert False,"" + Logger.info(this._logger,"get_len but mo_coeff is None"); + return -1 + Ndim=np.shape(this.mo_coeff) + if( this._spinrestriction=='U'): + + if( this._pbc ): + assert Ndim[0]==2,""; this.nkpt=Ndim[1]; this.nAO=Ndim[2]; this.nMO=Ndim[3] + else: + assert Ndim[0]==2,""; this.nkpt=1; this.nAO=Ndim[1]; this.nMO=Ndim[2] + printout("#UKS %d %d %d mo_coeff:"%(this.nkpt,this.nAO,this.nMO)+str(Ndim)) + else: + if( this._pbc ): + this.nkpt=Ndim[0]; this.nAO=Ndim[1]; this.nMO=Ndim[2]; + else: + this.nkpt=1; this.nAO=Ndim[0]; this.nMO=Ndim[1]; + return 1 + + +def get_LHomo(this,nth): + occ=this._mo_occ + if( occ is None ): + printout("#get_LHOMO:recalculating occ..") + occ=this.get_occ() + occ_a=(occ if(this._spinrestriction != 'U') else occ[0]) + occ_a0=(occ_a if(not this._pbc) else occ_a[0]) + this.update_nOrbs() + nMO=this.nMO + thr=1.0;LUMO=-1 + for i in range(nMO): + if( occ_a0[i]0.5): + ## this is SOMO.. + SOMO=LUMO + if( nth==0 ): + retv= SOMO + else: + retv= SOMO+nth + if( retv<0 or retv>nMO ): + printout("!W get_LHomo:nth=%d >> retv=%d (SOMO=%d nMO=%d)"%(nth,retv,SOMO,nMO) ) + return retv + else: + ## this is LUMO.. + retv= LUMO+nth-1 # 1=LUMO 2=LUMO+1 + + if( retv<0 or retv>nMO ): + printout("!W get_LHomo:nth=%d >> retv=%d (LUMO=%d nMO=%d)"%(nth,retv,LUMO,nMO) ) + return retv + +def print_calc_gs(this,Egnd,CPUtime=None,Niter=None,legend=False,fname=None,appendtofile=False): + if(suppress_prtout()): + return + + string=" ";strlegend="#" + if(this.nAO is not None): + string+=" %5d "%(this.nAO);strlegend+=" %5s "%("Nao") + if(this._pbc): + if( getattr(this.cell,"mesh",None) is not None ): + mesh=getattr(this.cell,"mesh",None); + meshsz=mesh[0]*mesh[1]*mesh[2]; + string+=" %8d %4d %4d %4d "%(meshsz,mesh[0],mesh[1],mesh[2]) + strlegend+=" %8s %4s %4s %4s "%("meshsz","mesh","mesh","mesh") + string+=" %16.8f "%(Egnd);strlegend+=" %16s "%("Egnd") + if( CPUtime is not None): + string+=" %14.4f "%(CPUtime);strlegend+=" %14s "%("CPUtime") + if( Niter is not None and Niter>0 ): + string+=" %5d %14.4f "%(Niter,CPUtime/Niter);strlegend+=" %5s %14s "%("Niter","time_per_Iter") + if( rttddft_common.get_job(False) is not None ): + string+=rttddft_common.get_job(False) + string+=" "+str(datetime.datetime.now()) + + fdlist=[sys.stdout];fdout=None + if( fname is not None ): + fdout=open(fname,("a" if(appendtofile) else "w")) + fdlist.append(fdout ) + for fd1 in fdlist: + if(legend): + print(strlegend,file=fd1); + print(string,file=fd1) + if(fdout is not None): + fdout.close() + +def calc_gs(this,update_Matrices=True,verbose=False,dm0=None): + assert (not this._fix_occ),"" + t0=time.time() + En=this.kernel(dm0=dm0) + t1=time.time() + + check_time=True + if(check_time): + print_calc_gs(this,En,CPUtime=t1-t0,Niter=None,legend=True,fname="calc_gs.log",appendtofile=True) + + this._Egnd=En + print("#rttddft:calc_gs:%16.8f N_ele:%f"%(En,get_Nele(this,Occ=this.mo_occ))) + if( update_Matrices ): + this.update_Sinv(refresh=True) + return En + +def set_mo_occ(this,mo_occ,fix_occ,clone=False): + if( not clone ): + this._mo_occ=mo_occ + else: + this._mo_occ=arrayclone(mo_occ) + this._fix_occ=fix_occ + this.get_logger(True).Info("set_mo_occ:"+d1toa(np.ravel(np.array(mo_occ)))) + +def update_Sinv(this,refresh=False): + need_update=refresh + if( not need_update ): + if( this._sINV is not None): + return False + pbc=this._pbc + if( not pbc ): + S1e_1=this.get_ovlp() + this._Ssqrt,this._Sinvrt,this._sINV=get_Ssqrt_invsqrt_sINV(S1e_1) + else: + kvectors=np.reshape( this.kpts, (-1,3)) + nkpt=len(kvectors) + this._Ssqrt=[];this._Sinvrt=[];this._sINV=[] + for k in range(nkpt): + S1e_k=this.get_ovlp(this.cell,kvectors[k]) + Ssqrt,Sinvrt,sINV = get_Ssqrt_invsqrt_sINV(S1e_k) + this._Ssqrt.append(Ssqrt);this._Sinvrt.append(Sinvrt);this._sINV.append(sINV); + return True + +def energy_tot(mf, dm=None, h1e=None, vhf=None,verbose=False): + nuc = mf.energy_nuc() + e_tot = mf.energy_elec(dm, h1e, vhf)[0] + nuc + mf.scf_summary['nuc'] = nuc.real + return e_tot + +def energy_elec_krks(this, dm_kpts=None, h1e_kpts=None, vhf=None,verbose=False): + logger=this.get_logger(set=True) + if(verbose): + logger.info("#rttddftPBC:energy_elec_krks ---") + if( dm_kpts is None ): + if( verbose ): + logger.info("#rttddftPBC:MOcofs:calculating dm_kpts from Cofs..") + moCofs=this.mo_coeff[0] + HOMO=get_HOMO(this) + logger.info("#MO_0:"+z1toa(moCofs[:,0])) + logger.info("#MO_%d(HOMO):"%(HOMO)+z1toa(moCofs[:,HOMO])) + dm_kpts = this.make_rdm1() + if(verbose): + logger.info("#dm_00:%f _01:%f+j%f _11 %f ..."%( + dm_kpts[0][0][0].real,dm_kpts[0][0][1].real,dm_kpts[0][0][1].imag,dm_kpts[0][1][1].real) ) + retv = this.get_super().energy_elec(dm_kpts=dm_kpts,h1e_kpts=h1e_kpts,vhf=vhf) + if(verbose): + Enuc=this.energy_nuc().real + Etot = retv + Enuc + logger.info("#E_el:%f / E_tot:%f / E_GS:%f..."%(retv,Etot,this._Egnd) ) + return retv + +def energy_elec_rks(this, dm=None, h1e=None, vhf=None, verbose=False): + logger=this.get_logger(set=True) + if(verbose): + logger.info("#rttddftMOL:energy_elec_rks ---") + if( dm is None ): + if( verbose ): + logger.info("#rttddftMOL:MOcofs:calculating dm from Cofs..") + moCofs=this.mo_coeff + HOMO=get_HOMO(this) + logger.info("#MO_0:"+z1toa(moCofs[:,0])) + logger.info("#MO_%d(HOMO):"%(HOMO)+z1toa(moCofs[:,HOMO])) + dm = this.make_rdm1() + if(verbose): + logger.info("#dm_00:%f _01:%f+j%f _11 %f ..."%(dm[0][0].real,dm[0][1].real,dm[0][1].imag,dm[1][1].real) ) + retv = this.get_super().energy_elec(dm=dm,h1e=h1e,vhf=vhf) + if(verbose): + Enuc=this.energy_nuc().real + Etot = retv + Enuc + logger.info("#E_el:%f / E_tot:%f / E_GS:%f..."%(retv,Etot,this.Egnd) ) + return retv + +def get_Rnuc(this,unit): + fac=1.0 + assert (unit=='A' or unit=='ANGS' or unit=='B' or unit=='BOHR'),"unit:"+unit + if( unit=='A' or unit=='ANGS'): + fac=physicalconstants.BOHRinANGS + pbc=this._pbc + if( not pbc ): + return np.array( this.mol.atom_coords() )*fac + else: + return np.array( this.cell.atom_coords() )*fac + + +def get_logger(self,set=False): + if( (self._logger is None) and set ): + printout("get_logger:self._logger is None..."+str(id(self))); + self.set_logger(filename="rttddft_dbg.log"); + return self._logger; + +def set_logger(mf,logger=None,filename=None,replace=True): + if( not replace ): + if( mf._logger is not None): + printout("#rttddftPBC already has a logger"); + return False + if( logger is None ): + assert (filename is not None),"" + printout("set_logger:setting Logger..."+str(id(mf)) ); + mf._logger = Logger(filename) + else: + mf._logger = logger + return True + +def get_populations(this,dm_kpts, title="", kpts=None): + ## pop[\mu] = D_{\mu,k'} S_{k',\mu} + ## non-pbc pbc + ## RKS [nAO] [nkpt][nAO] + ## UKS,ROKS [2][nAO] [2][nkpt][nAO] + if( this._spinrestriction == 'R'): + return get_populations_1(this,dm_kpts, title=title, kpts=kpts) + else: + return get_populations_1(this,dm_kpts[0], title=title, kpts=kpts),\ + get_populations_1(this,dm_kpts[1], title=title, kpts=kpts) + +def get_populations_1(this,dm_kpts, title="", kpts=None): + pbc=this._pbc + + nkpt=(1 if (not pbc) else len(dm_kpts)) + + nAO=( len(dm_kpts) if (not pbc) else len(dm_kpts[0]) ) + + kvectors=(None if (not pbc) else np.reshape( this.kpts, (-1,3))) + + wks=None; ## np.zeros([nAO,nAO],dtype=np.complex128 ) + + ret=[] + for kp in range(nkpt): + if( not pbc ): + S1e_k=this.get_ovlp() + wks=np.matmul( S1e_k, dm_kpts) + else: + if( kpts is not None ): + if( not (kp in kpts) ): + continue + S1e_k=this.get_ovlp(this.cell,kvectors[kp]) + wks=np.matmul( S1e_k, dm_kpts[kp]) + pop=[] + for ao in range(nAO): + pop.append( wks[ao][ao].real ) + popsum=sum(pop) + printout("#AOpop_%d:%f "%(kp,popsum)+ title +":"+d1toa(pop,format="%5.2f ")) + if( not pbc ): + return np.array(pop) + ret.append( pop.copy() ) + if(pbc): + return np.array( ret ) + +def calc_phases(mf,time_AU,mocoefs,mocoefs_REF,eorbs_REF,fpath_format,append=False): #,gnuplot=False): + if( suppress_prtout() ): + return + + assert (this._spinrestriction=='R'),"otherwise unimplemented" + pbc=mf._pbc + eorbs=( eorbs_REF if(eorbs_REF is not None) else mf.mo_energy ) + ndim=np.shape(mocoefs) + + kvectors=None; + if( pbc ): + nkp=ndim[0];nAO=ndim[1];nMO=ndim[2]; + kvectors=(None if (not pbc) else np.reshape( mf.kpts, (-1,3))) + else: + nkp=1;nAO=ndim[0];nMO=ndim[1] + + SxC=np.zeros([nAO,nMO],dtype=np.complex128) + pop=np.zeros([nMO],dtype=float) + angl=np.zeros([nMO],dtype=float) + col=np.zeros([nAO],dtype=np.complex128) + ref=np.zeros([nAO],dtype=np.complex128) + + for kp in range(nkp): + fd=futils.fopen( fpath_format%(kp),("a" if append else "w")) ## OK + if( not pbc ): + S1e=mf.get_ovlp() + else: + S1e=mf.get_ovlp(mf.cell,kvectors[kp]) + + SxC=np.matmul( S1e, mocoefs[kp] ) + print("%f "%(time_AU),end="",file=fd) + for mo in range(nMO): + for kao in range(nAO): + col[kao]=SxC[kao][mo] + if( not pbc ): + for kao in range(nMO): + ref[kao]=mocoefs_REF[kao][mo] + else: + for kao in range(nMO): + ref[kao]=mocoefs_REF[kp][kao][mo] + + cdum = np.vdot(ref,col) + pop[mo]= (cdum.real)**2 + (cdum.imag)**2 + angl[mo]=math.atan2( cdum.imag, cdum.real ) + print("%f %f %f %f "%(angl[mo],eorbs[kp][mo],angl[mo]/eorbs[kp][mo],pop[mo]),end="",file=fd) + print("",file=fd); + futils.fclose(fd) + +def print_eorbocc(this,title="",file=None): + if( this._spinrestriction =='U'): + this.print_eorbocc1(this._mo_occ[0], this.mo_energy[0], title=title,file=file, end="") + this.print_eorbocc1(this._mo_occ[1], this.mo_energy[1], title=title,file=file) + else: + this.print_eorbocc1(this._mo_occ, this.mo_energy, title=title,file=file) + +def print_eorbocc1(this,occ,eorbs,title="",file=None,end="\n"): + if( suppress_prtout() ): + return + fd=(sys.stdout if (file is None) else file) + pbc=this._pbc + + if( not pbc ): + print("#print_eorbocc_"+title+":"+d1x2toa(this._mo_occ,this.mo_energy,format="%3.1f %10.4f "),end=end,file=fd ) + else: + nkpt=len(this.kpts) + mo_energy_kpts=this.mo_energy + for kp in range(nkpt): + print("#K%d:%10.4f %10.4f %10.4f :"%( \ + kp, this.kpts[kp][0],this.kpts[kp][1],this.kpts[kp][2]) \ + +d1x2toa(this._mo_occ_kpts[kp],this.mo_energy[kp],format="%3.1f %10.4f "),end=end, file=fd) + + +def get_hcore(this,cell_or_mol=None,kpts=None,tm_AU=None, dm_kOR1=None, tmAU_dmat=None, Dict_hc=None): + idbgng=0 + diff_ZF_and_fF=False + ncall=rttddft_common.count("get_hcore",inc=True) + pbc=this._pbc + + if(pbc and (this.nkpt is not None) ): + assert this.nkpt == len(this.kpts),"%d/%s"%(this.nkpt,str(np.shape(this.kpts))); + + dbgng_constantfield=True ## TODO + if(this._fixednucleiapprox): + if( this._constantfield and (this._td_field is not None) ): + ncall_cf =rttddft_common.count("get_hcore.cf",inc=True) + do_calc_hc=( this._hcore is None ) + print("#get_hcore.constantfield:%05d:start:%r"%(ncall,do_calc_hc)) + if( this._hcore is None ): + print("#get_hcore.constantfield:%05d:get_hcore new"%(ncall_cf) ) + if( dbgng_constantfield ): + # we assume 1st:CALC 2nd:cpy, ... + if(ncall_cf==3 or ncall_cf==20 or ncall_cf==100 or ncall_cf==3000): + print("#get_hcore.constantfield:%05d:get_hcore for DBG.."%(ncall_cf)) + do_calc_hc=True + if( (not do_calc_hc) and (this._hcore is not None) ): + return arrayclone( this._hcore ) + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); + fncnme="get_hcore";fncdepth=1 ## fncdepth ~ SCF:0 vhf:1 get_j:2 + Wctm000=time.time();Wctm010=Wctm000;N_call=rttddft_common.Countup("get_hcore");dic1_timing={} + Dic_timing=rttddft_common.Dict_getv('timing_'+fncnme, default=None) + if( Dic_timing is None ): + rttddft_common.Dict_setv('timing_'+fncnme, {}); + Dic_timing=rttddft_common.Dict_getv('timing_'+fncnme, default=None) + AUinFS=PhysicalConstants.aut_in_femtosec() + cLIGHT_AU=PhysicalConstants.CLIGHTinAU() + assert ( abs( cLIGHT_AU - 137.035999)<2.0e-6),"check cLIGHT_AU:%f"%(cLIGHT_AU) + + A_over_c=None + if( this._calc_Aind !=0 ): + assert this._dt_AU is not None,"PLS set dt_AU ..." + assert dm_kOR1 is not None,"PLS set dm_kOR1 ...:%d"%(this._calc_Aind) + Aind_over_c = calc_Aind_over_c( this, (tm_AU if(tm_AU is not None) else this._time_AU), this._dt_AU, + dm_kOR1, tm_dmat=tmAU_dmat,caller="get_hcore") + Aext_over_c = this._td_field.get_vectorfield(tm_AU)/cLIGHT_AU + A_over_c = Aext_over_c + Aind_over_c + else: + tmAU_refr=( tm_AU if(tm_AU is not None) else this._time_AU) + Aext_over_c = (np.zeros([3],dtype=np.float64) if(this._td_field is None) else this._td_field.get_vectorfield(tmAU_refr)/cLIGHT_AU); + A_over_c=Aext_over_c + + if( this._iflag_prtout_field!=0 ): + headline="" + if( this._iflag_prtout_field < 0 ): + headline=" %6s %14s %16s %16s %16s\n"%("step","tm_AU","A-over-c_x","A-over-c_y","A-over-c_z") + printout( headline+" %6d %14.6f %16.8f %16.8f %16.8f"%(abs(this._iflag_prtout_field),tm_AU, A_over_c[0], A_over_c[1], A_over_c[2]),\ + fpath=rttddft_common.get_job(True)+"_hcore_AoverC.log",Append=(this._iflag_prtout_field>0)); + this._iflag_prtout_field=0; + + + if( Dict_hc is not None ): + Dict_hc.update({"A_over_c":arrayclone(A_over_c)}) + nkpt=1;kvectors=None + if(pbc): + nkpt=len(this.kpts) + kvectors=np.reshape( this.kpts, (-1,3)) + + if( tm_AU is None ): + tm_AU = this._time_AU + + ## hcore ([nkpt])[nAO][nAO] for all types of spin restriction + pseudo=False + if( pbc and this.cell.pseudo): + pseudo=True + calc_hcZF=0;calc_hcA0=0;calc_hcSF=0; hcZF=None;hcA0=None; hcSF=None; tdF=this._td_field; + if( this._td_field is not None ): + if( pseudo ): + if(pbc): + Dic1={} + hcore= krhf_get_hcore_pp(this, cell_or_mol, kpts=kpts,tm_AU=tm_AU,Dict_DBG=Dic1, A_over_c=A_over_c) + #A_over_c is automatically calculated (as a purely external field) even if it is None + if( Dict_hc is not None ): + Dict_hc.update({"hcore_00":arrayclone(hcore)}) + + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"get_hcore_pp",Wctm010-Wctm020,depth=fncdepth) + assert Dic1['get_pp']=='new',"" + else: + assert False,"" + else: + if( not pbc ): + hcore = this.get_super().get_hcore(cell_or_mol) + + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"super.get_hcore",Wctm010-Wctm020,depth=fncdepth) + else: + hcore= this.get_super().get_hcore(cell_or_mol,kpts); ## wrong:(cell=this.cell, kpts=kvectors) 2020.11.12 fixed + assert nkpt==len(hcore),"nkpt:%s / len(hcore):%d hcore:"%(str(nkpt),len(hcore))+str(np.shape(hcore)) + + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"super.get_hcore_PBC",Wctm010-Wctm020,depth=fncdepth) + if( Dict_hc is not None ): + Dict_hc.update({"hcore_00":arrayclone(hcore)}) + + if( this.dipolegauge ): + ## - q_e r:E = +|e| r:E + Efield = this._td_field.get_electricfield(tm_AU) + if( not pbc ): + dipole_kpt = this.mol.intor('int1e_r', comp=3) + for dir in range(3): + hcore[:][:] = hcore[:][:] + Efield[dir] * dipole_kpt[dir][:][:] + if( Dict_hc is not None ): + Dict_hc.update({"hcore_field":arrayclone( Efield[0]*dipole_kpt[0][:][:] \ + + Efield[1]*dipole_kpt[1][:][:] + Efield[2]*dipole_kpt[2][:][:] )}) + else: + dipole_kpt = this.cell.pbc_intor('int1e_r', comp=3, hermi=1, kpts=kvectors) + assert (len(elgrad_kpt)==nkpt),"shape:" + for kp in range(nkpt): + for dir in range(3): + hcore[kp][:][:] = hcore[kp][:][:] + Efield[dir] * dipole_kpt[kp][dir][:][:] + if( Dict_hc is not None ): + Dict_hc.update({"hcore_field":arrayclone( hcore - Dict_hc["hcore_00"] )}) + + return hcore + elif( this.velocitygauge ): + ## print("#get_hcore.constantfield:velocitygauge...") + hcore=toComplexArray(hcore) + ## - p: q_e A/c = p|e|A/c = -i (nabla) A/c (a.u.) + if( A_over_c is None ): + A_over_c = this._td_field.get_vectorfield(tm_AU)/cLIGHT_AU + + if( (tm_AU < 0.10/AUinFS) or int( round( (tm_AU/AUinFS)/0.008 ) )%100==0 ): + if( MPIrank == 0 ): + fd01=open(rttddft_common.get_job(True)+"_tdfield.log","a"); + print("%14.6f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f"%(tm_AU,A_over_c[0],A_over_c[1],A_over_c[2], + Aext_over_c[0],Aext_over_c[1],Aext_over_c[2]),file=fd01);fd01.close() + + if( not pbc ): + elgrad_kpt = this.mol.intor('int1e_ipovlp',comp=3, hermi=2) + # comp : Components of the integrals, e.g. int1e_ipovlp_sph has 3 components + # hermi: Hermitian:1 anti-Hermitian:2 + else: + elgrad_kpt = this.cell.pbc_intor('int1e_ipovlp',comp=3, hermi=2, kpts=kvectors) + assert (len(elgrad_kpt)==nkpt),"shape:" + + if( not pbc ): + for dir in range(3): + hcore[:][:] = hcore[:][:] - 1j * Constants.sgn_int1e_ipovlp * A_over_c[dir] * elgrad_kpt[dir][:][:] + + S1e_1=this.get_ovlp() + quiver_energy = 0.50 * np.dot( A_over_c, A_over_c ) + hcore[:][:] = hcore[:][:] + quiver_energy * S1e_1[:][:] + + if( Dict_hc is not None ): + Dict_hc.update({"hcore_field":arrayclone( - 1j * Constants.sgn_int1e_ipovlp * ( A_over_c[0]*elgrad_kpt[0][:][:] \ + + A_over_c[1]*elgrad_kpt[1][:][:] + A_over_c[2]*elgrad_kpt[2][:][:] ) \ + + quiver_energy * S1e_1[:][:])}) + + else: + # - p:(e/mc)A = + (\hbar/i) p:A/c + + for kp in range(nkpt): + for dir in range(3): + hcore[kp][:][:] = hcore[kp][:][:] - 1j * Constants.sgn_int1e_ipovlp * A_over_c[dir] * elgrad_kpt[kp][dir][:][:] + for kp in range(nkpt): + S1e_k=this.get_ovlp( this.cell, kvectors[kp]) + quiver_energy = 0.50 * np.dot( A_over_c, A_over_c ) + hcore[kp][:][:] = hcore[kp][:][:] + quiver_energy * S1e_k[:][:] + + if( (hcZF is not None) and diff_ZF_and_fF and (np.sqrt(2*quiver_energy)>1.0e-8) ): + ttl1="rttddft01_get_hcore_hcZF_and_hcfF_K%d"%(kp) + print_Hmatrices(ttl1,hcore[kp],hcZF[kp],Nref=7,fpath=ttl1+".dat") + + if( Dict_hc is not None ): + Dict_hc.update({"hcore_field":arrayclone( hcore - Dict_hc["hcore_00"] )}) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1_timing,Dic_timing,"dipvel",Wctm010-Wctm020,depth=fncdepth) + # Wctm010=time.time() + # printout_dict(fncnme,dic1_timing,Dic_timing,Wctm010-Wctm000,depth=fncdepth) + + if(this._fixednucleiapprox): + if(this._constantfield): + if( this._hcore is not None ): + diff=aNmaxdiff( this._hcore, hcore ) + if(MPIrank==0): + fd1=open("constantfield.log","a"); + print("#get_hcore.%05d diff:%e elapsed:%f"%(ncall_cf,diff,Wctm010-Wctm000),file=fd1) + fd1.close() + assert diff<1e-7,"diff:%e"%(diff) + else: + if(MPIrank==0): + fd1=open("constantfield.log","a"); + print("#get_hcore.%05d set afresh:%s elapsed:%f"%(ncall_cf, str(np.shape(hcore)),Wctm010-Wctm000),file=fd1) + fd1.close() + this._hcore=arrayclone( hcore ) + print("#get_hcore.constantfield:set hcore:",np.shape(this._hcore)) + return hcore + else: + assert False,"wrong gauge %r,%r"%(this.dipolegauge,this.velocitygauge) + else: + if( not pbc ): + return this.get_super().get_hcore(cell_or_mol) + else: + return this.get_super().get_hcore(cell_or_mol,kpts); ## wrong:(cell=this.cell, kpts=this.kpts) + +def rttddft_sget_Aind_args_(SorG,this,Dic,errorlogfnme=None,verbose=False): + #keys_Aind_over_c= ["_Aind_over_c_ini:D3", "_calc_Aind:i","_dt_AU:d", "BravaisVectors_au:D3,3","cell_volume:d", + # "_d2Aind_over_c_dt2:d","_d2Aind_over_c_dt2_tmAU:d", "_Aind_tmAU:d","_Aind_Gearvc_C:D5,3","_Aind_Gearvc_P:D5,3", + # "_Aind_Gearvc_C_nxt:D5,3","_Aind_Gearvc_P_nxt:D5,3","_Aind_tmNxt:d"] + assert this._pbc,"are you going to set Aind_over_c for system without pbc ??" + Threads=[0];comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank();MPIsize=comm.Get_size() + if(errorlogfnme is None): + errorlogfnme="rttddft_%set_Aind_args_error.log"%(SorG); + + dbglogfnme="rttddft_%set_Aind_args.log"%(SorG); + def append_log1(ith,k,t,v): + if( MPIsize<2 or (MPIrank in Threads) ): + fdL=open(dbglogfnme,('a' if(ith>0) else 'w')) + print("%03d:"%(ith)+ k+":"+str(t)+":"+obj_to_string(v));fdL.close() + + def print_error1(msg): + if( MPIsize<2 or (MPIrank in Threads) ): + msg+=" \t\t\t"+str(datetime.datetime.now()) + fdE=open(errorlogfnme,"a");print(msg,file=fdE);print(msg);fdE.close() + assert SorG=='S' or SorG=='G',"" + set_args=(SorG=='S' or SorG=='s') + nerror=0;ith=0 + for item in rttddftPBC.Keys_Aind_over_c_: + sA=item.split(':');nA=len(sA);assert nA==2,"wrong format:"+str(item) + ky=sA[0].strip(); ty=sA[1]; + if(set_args): + if(ky not in Dic): + print_error1(ky+" not in Dic");nerror+=1;continue + setattr(this,ky,Dic[ky]); + if(verbose): + append_log1(ith,ky,ty,Dic[ky]) + else: + val=getattr(this,ky,None) + if(val is None): + if( ky in rttddftPBC.Keys_Aind_over_c_allow_None_ ): + printout("#rttddft_sget_Aind_args:%s allows None"%(ky)); ## go down and set {ky:None} ... + else: + print_error1(ky+" does not exist in this rttddft instance");nerror+=1;continue + Dic.update({ky:val}) + if(verbose): + append_log1(ith,ky,ty,val) + ith+=1 + + if(nerror>0): + print("%set args failed:"%(SorG),Dic); + + return nerror + +def printout_matrix(path,Matrix,Append=False,fopen=False,job=True,dtme=True,step=None,time_AU=None): + def fnformat_Z(arg): + return "%12.6f,%12.6f"%(arg.real,arg.imag) + def fnformat_R(arg): + return "%14.6f"%(arg) + def fprtD2(mat,fd,format="%10.5f",delimiter=" ",end="\n\n"): + ndim=np.shape(mat) + for i in range(ndim[0]): + print(delimiter.join( [ format%(mat[i][j]) for j in range(ndim[1]) ]),file=fd) + print(end,file=fd) + def fprtZ2(mat,fd,format="%9.4f,%9.4f",delimiter=" ",end="\n\n"): + ndim=np.shape(mat) + for i in range(ndim[0]): + print(delimiter.join( [ format%(mat[i][j].real,mat[i][j].imag) for j in range(ndim[1]) ]),file=fd) + print(end,file=fd) + + AUinFS=physicalconstants.aut_in_femtosec + fd=open(path,("a" if(Append) else "w")) + Ndim=np.shape(Matrix);rank=len(Ndim) + dtype=( np.array( Matrix[0]).dtype if( (not isinstance(Matrix,np.ndarray)) and rank>1) else np.array(Matrix).dtype ) + fnformat=( fnformat_Z if(dtype==np.complex128 or dtype==complex) else fnformat_R ) + fprtA2 =( fprtZ2 if(dtype==np.complex128 or dtype==complex) else fprtD2 ) + + print("# xVVx matrix %s %s dim:%s job:%s %s"%(\ + ("at step %04d"%(step) if(step is not None) else ""),\ + ("t= %12.6f fs"%(time_AU*AUinFS) if(time_AU is not None) else ""),\ + str(Ndim), ( rttddft_common.get_job(True) if(job) else ""), (str(datetime.datetime.now()) if(dtme) else "")),file=fd) + + ia=np.zeros([rank],dtype=int) + for ia[0] in range(Ndim[0]): + if(rank==1): + print(" %3d:"%(ia[0])+fnformat(Matrix[ ia[0] ]),file=fd);continue + if(rank==3): + print("#%3d:"%(ia[0]),file=fd);fprtA2(Matrix[ia[0]],fd);continue + + for ia[1] in range(Ndim[1]): + if(rank==2): + print(" %3d,%3d:"%(ia[0],ia[1])+fnformat(Matrix[ ia[0] ][ ia[1] ]),file=fd);continue + if(rank==4): + print("#%3d,%3d:"%(ia[0],ia[1]),file=fd); fprtA2(Matrix[ ia[0] ][ ia[1] ],fd);continue + + for ia[2] in range(Ndim[2]): + if(rank==3): + print(" %3d,%3d,%3d:"%(ia[0],ia[1],ia[2])+fnformat(Matrix[ ia[0] ][ ia[1] ][ ia[2] ]),file=fd);continue + if(rank==5): + print("#%3d,%3d,%3d:"%(ia[0],ia[1],ia[2]),file=fd); fprtA2(Matrix[ ia[0] ][ ia[1] ][ ia[2] ],fd);continue + + for ia[3] in range(Ndim[3]): + if(rank==4): + print(" %3d,%3d,%3d,%3d:"%(ia[0],ia[1],ia[2],ia[3])+fnformat(Matrix[ ia[0] ][ ia[1] ][ ia[2] ][ ia[3] ]),file=fd);continue + for ia[4] in range(Ndim[3]): + if(rank==5): + print(" %3d,%3d,%3d,%3d,%3d:"%(ia[0],ia[1],ia[2],ia[3],ia[4])+fnformat(Matrix[ ia[0] ][ ia[1] ][ ia[2] ][ ia[3] ][ ia[4] ]),file=fd);continue + else: + assert False,"%d"%(rank)+str(Ndim) + fd.close() + if(fopen): + os.system("fopen "+path) + +def load_Aind_over_c(this,tm_AU,dt_AU,fpath): + def d1diff(lhs,rhs): + le=len(lhs) + if(len(rhs)!=le): + return -1 + ret=0.0 + for j in range(le): + ret=max( ret, abs(lhs[j]-rhs[j])) + return ret + IpK=0; Indcsrtn=[2,3,4] + dtTINY=dt_AU*0.01;diff_TINY=1.0e-7 + fd=open(fpath,"r") + Dic={};pKmaxv=-1;spKmax=None;erbuf=[] + spKwant=None;N_dupl=0 + for line in fd: + line=line.strip();le=len(line) + if(le<1): + continue + sA=line.split();nA=len(sA); + spK=sA[IpK] + arr=np.array( [ float(sA[k]) for k in range(nA) ] ) + pK=arr[IpK] + if( pKmaxv<0 or pK>= pKmaxv + dt_AU - dtTINY): + Dic.update({spK:arr}) + else: + if(spK in Dic): + old=Dic[spK]; + dff=d1diff(old,arr); + if(dff < diff_TINY ): + N_dupl+=1 + else: + strwrn="#Conflicting data:#diff=%16.6e\n#Conflicting data:%s_1:%s\n#Conflicting data:%s_2:%s"%( + dff,spK,str(old),spK,str(arr)) + erbuf.append(strwrn) + else: + strwrn="#check pK is correct: pKlast=%f / pKnew=%f but %s is not in Dic.."%(pKlast,pK,spK) + erbuf.append(strwrn) + Dic.update({spK:arr}) + if(pKmaxv 0 ): + fd=open("load_Aind_over_c_err.log","w") + for item in erbuf: + print(item,file=fd); + fd.close() + if(spKwant is not None): + arr=Dic[spKwant] + fd=open("load_Aind_over_c.log","a") + print( [ arr[I] for I in Indcsrtn ],file=fd);fd.close() + return np.array( [ arr[I] for I in Indcsrtn ] ); + return None + +def get_current(this,densitymatrix=None): + if( densitymatrix is None ): + densitymatrix = this.make_rdm1() + ## \sum_{mu>nu} Im(DM_{\mu\nu}) * [ mu GRAD nu - nu GRAD mu ] + ## + ## + dbgng=True + if(dbgng): + if( rttddft_common.count("rttddft01.get_current",inc=True)%10==1 ): + sqrSums={}; + dagDEV,ofdDEV=check_hermicity_dm(this, densitymatrix, sqrSums=sqrSums,title="DM"); + matrix=None + kvectors=(None if(not this._pbc) else np.reshape( this.kpts, (-1,3)) ) + if( not this._pbc ): + matrix = this.mol.intor('int1e_ipovlp',comp=3, hermi=2) + else: + matrix = this.cell.pbc_intor('int1e_ipovlp',comp=3, hermi=2, kpts=kvectors) + Ndim_matrix=np.shape(matrix) + ### print("Ndim_matrix:",end="");print(Ndim_matrix) + ### print("should_be:",end="");print([3,this.nAO,this.nAO] if(not this._pbc) else [this.nkpt,3,this.nAO,this.nAO]) + if( not this._pbc ): + assert i1eqb(Ndim_matrix,[3,this.nAO,this.nAO],verbose=True),""+str(Ndim_matrix) + else: + assert i1eqb(Ndim_matrix,[this.nkpt,3,this.nAO,this.nAO],verbose=True),""+str(Ndim_matrix) + + nspin=(1 if(this._spinrestriction=='R') else 2) + for spin in range(nspin): + dmat = ( densitymatrix if(nspin==1) else densitymatrix[spin] ) + Ndim=np.shape(dmat) + nKpt=(1 if(not this._pbc) else Ndim[0]) + nAO=(Ndim[0] if(not this._pbc) else Ndim[1]) + ret=[0.0, 0.0, 0.0] + for kp in range(nKpt): + dm=( dmat if(not this._pbc) else dmat[kp]) + mat=( matrix if(not this._pbc) else matrix[kp]) ## [3,nAO,nAO] + cum=[ 0.0, 0.0, 0.0 ] + for mu in range(1,nAO): + for nu in range(mu): + for dir in range(3): + cum[dir] += dm[mu][nu].imag * Constants.sgn_int1e_ipovlp*(mat[dir][mu][nu]-mat[dir][nu][mu]) + for dir in range(3): + ret[dir]+=cum[dir] + if(this._pbc): + for dir in range(3): + ret[dir]=ret[dir]/float(nKpt) + return ret; + +def get_dipole(this,dm_kpts,mode,filepath=None,header=None,trailer="", molecular_dipole=None, + headline=False,current=None,Aind_over_c=None, Aext_over_c=None, caller="", tmrefAU_Aind=None, + xVVx_A_over_c_diff_TOL=1.0e-6): + # dict_retv={'dipole':None, 'dipole_velocity':None} + # Note your dm[\mu\nu] = C^{^mu}_n w_n { C^{\nu}_n }^{\ast} + # .. so TR( matmul(O,dm) ) gives the expectation value. + # the dipole velocity : TR(...) should give pure-imaginary and -i * value is to be stored.. + AUinFS=0.02418884326058678 + if( tmrefAU_Aind is None ): + tmrefAU_Aind = this._time_AU + tmAU_TINY=1.0e-7 + STRwalltime=" \t\t walltime: %12.4f"%( time.time()-this._wt000 ) + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); + dbgng_calcAind=False ## True; + pbc=this._pbc + check_DMtrace=True + if(check_DMtrace): + trDM=trace_dmat(this, dm_kpts, this._spinrestriction, this._pbc) + N_ele=get_Nele(this) + if( this._spinrestriction == 'R' ): + assert abs(trDM-N_ele)<1.0e-7,"" + else: + assert ( abs(trDM[0]-N_ele[0])<1.0e-7 and abs(trDM[1]-N_ele[1])<1.0e-7),"" + + if(Aind_over_c is None): + if( this._calc_Aind != 0 ): + Aind_over_c=get_Aind_over_c(this,this._time_AU) + + kvectors = (None if (not pbc) else np.reshape( this.kpts, (-1,3))) + nkpt= (None if (not pbc) else len(kvectors) ) + + cLIGHT_AU = PhysicalConstants.CLIGHTinAU() + this.update_nOrbs() + + assert ( mode == 'R' or mode=='B' or mode=='V'),"" + ret_RandV=[None, None] + nmult_DM=(1 if(this._spinrestriction == 'R') else 2) + + dipvel_0=None; dipvel_1=None; dipvel_2=None; dipvel_3=None; dipvel_x0=None + for RorV in ["R","V"]: + matrix = None + if( RorV=='R' and (mode == 'B' or mode==RorV) ): + if( not pbc ): + matrix = this.mol.intor('int1e_r',comp=3, hermi=1) + else: + matrix = this.cell.pbc_intor('int1e_r', comp=3, hermi=1, kpts=kvectors) + + ndim_matrix=np.shape(matrix) + if( not pbc ): + # this should be [3, nAO, nAO] + assert ( ndim_matrix[1]==this.nAO and ndim_matrix[2]==this.nAO ),"matrix dimension"+str(ndim_matrix) + else: + # this should be [nKpoints, 3, nAO, nAO] + assert ( ndim_matrix[0]==this.nkpt and ndim_matrix[2]==this.nAO and ndim_matrix[3]==this.nAO ),"matrix dimension:"+str(ndim_matrix) + + if( nmult_DM==1 ): + cdum = dmtrace(matrix,3,dm_kpts,pbc,this._spinrestriction) + ret_RandV[0] = [ cdum[0].real, cdum[1].real, cdum[2].real ] + else: + cdumA,cdumB = dmtrace(matrix,3,dm_kpts,pbc,this._spinrestriction) + ret_RandV[0]=[ cdumA[0].real+cdumB[0].real, cdumA[1].real+cdumB[1].real, cdumA[2].real+cdumB[2].real ] + elif( RorV=='V' and (mode == 'B' or mode==RorV) ): + if( not pbc ): + matrix = this.mol.intor('int1e_ipovlp',comp=3, hermi=2) + else: + matrix = this.cell.pbc_intor('int1e_ipovlp',comp=3, hermi=2, kpts=kvectors) + + if( Constants.sgn_int1e_ipovlp<0 ): + matrix = - np.array( matrix ) + + if( this._spinrestriction == 'R'): + cdum = dmtrace(matrix,3,dm_kpts,pbc,this._spinrestriction,dict=None) + ret_RandV[1] = [ cdum[0].imag, cdum[1].imag, cdum[2].imag ] + else: + cdumA,cdumB = dmtrace(matrix,3,dm_kpts,pbc,this._spinrestriction,dict=None) + ret_RandV[1] = [ cdumA[k].imag + cdumB[k].imag for k in range(3) ] + + dipvel_0 =[ ret_RandV[1][0], ret_RandV[1][1], ret_RandV[1][2] ] ## dipvel_0 : < \hat{v} > + + if( this.velocitygauge and this._td_field is not None ): + if( Aext_over_c is not None ): + A_over_c=np.array( [ Aext_over_c[kk] for kk in range(3) ] ) + else: + A_over_c=this._td_field.get_vectorfield(this._time_AU)/cLIGHT_AU + + if( this._spinrestriction == 'R'): + for kk in range(3): + ret_RandV[1][kk]+=A_over_c[kk]*N_ele ### electronic charge being -1 ... + ### print("#adding Gauge term*N_ele(%f): %f %f %f"%(N_ele, A_over_c[0]*N_ele, A_over_c[1]*N_ele, A_over_c[2]*N_ele)) + else: + for kk in range(3): + ret_RandV[1][kk]+=A_over_c[kk]*( N_ele[0]+N_ele[1] ) ### electronic charge being -1 ... + else: + A_over_c=np.zeros([3]) ## external field + + dipvel_1=[ ret_RandV[1][0], ret_RandV[1][1], ret_RandV[1][2] ] ## dipvel_1 : < \hat{v} - q_e/c A_ext > + if( Aind_over_c is not None ): ## always true if calc_Aind!=0 (see above) + for kk in range(3): + ret_RandV[1][kk]+=Aind_over_c[kk]*( N_ele if(this._spinrestriction == 'R') else (N_ele[0]+N_ele[1]) ) + A_over_c[kk]+=Aind_over_c[kk] + dipvel_2=[ ret_RandV[1][0], ret_RandV[1][1], ret_RandV[1][2] ] ## dipvel_1 : < \hat{v} - q_e/c (A_ext + A_ind) > + + A_over_c_diff=-1 + N_ele_sum=( N_ele if(this._spinrestriction == 'R') else (N_ele[0]+N_ele[1]) ) + ## recall that we are calculating electronic --velocity-- i.e. [ r,H]/ih + ## we therefore calculate DMtrace of and divide by ih and ADD to velocity +## 2022.02.08 XXX XXX we always include xVVx --> if( this._calc_Aind and this.cell.pseudo): + calc_xVVx=(this._pbc and this.cell.pseudo) + if( calc_xVVx ): + Dbgng_xVVx=False ## TODO + Ncall_xVVx=rttddft_common.Countup("xVVx") + reCalc_xVVx=( Dbgng_xVVx and (Ncall_xVVx==5 or Ncall_xVVx==20 or Ncall_xVVx==200 or\ + Ncall_xVVx%1000==0 ) ) + reuse_xVVx=True + if( rttddft_common.Params_get("reuse_xVVx") is not None ): + reuse_xVVx = rttddft_common.Params_get("reuse_xVVx"); ## pyscf_common.params["reuse_xVVx"] + + is_fixednucleiapprox=False + if( hasattr(this,"_fixednucleiapprox") ): + if( this._fixednucleiapprox is not None ): + is_fixednucleiapprox=this._fixednucleiapprox + if( not is_fixednucleiapprox ): + reuse_xVVx=False; + rttddft_common.Write_once("reuse_xVVx","reuse_xVVx set False job:"+str(rttddft_common.get_job(True)), + fpath="reuse_xVVx.log",Append=True) + else: + rttddft_common.Write_once("reuse_xVVx","reuse_xVVx set default, %r job:"%(reuse_xVVx)+str(rttddft_common.get_job(True)), + fpath="reuse_xVVx.log",Append=True) + + istep=int( round(this._time_AU/this._dt_AU) ) + wct_010=time.time() + xVVx_matr=None;wct_xVVx=0 + if( reuse_xVVx and (this._xVVx is not None) ): + A_over_c_diff=max( [ abs(A_over_c[0]-this._Aeff_over_c_xVVx[0]), + abs(A_over_c[1]-this._Aeff_over_c_xVVx[1]), + abs(A_over_c[2]-this._Aeff_over_c_xVVx[2]) ] ) + if( A_over_c_diff < xVVx_A_over_c_diff_TOL ): + xVVx_matr=this._xVVx; + fd01=open("xVVx.log","a");print("#xVVx:%05d:"%(Ncall_xVVx),reuse_xVVx,reCalc_xVVx,file=fd01);fd01.close() + + if( xVVx_matr is None or reCalc_xVVx ): + xVVx_matr= with_df_get_ppxx(this.with_df,A_over_c,kpts=this.kpts,rttddft=this) + printout_matrix("xVVx_matr.dat",xVVx_matr,step=this._step,time_AU=this._time_AU) + wct_020=time.time(); wct_xVVx=wct_020-wct_010 + if( A_over_c_diff > 0 and this._xVVx is not None): + xVVx_diff=aNmaxdiff(xVVx_matr,this._xVVx) + printout("#get_dipole:RECALC xVVx:%f %f %f / %f %f %f Adiff=%e tmAU=%f/%f xVVx diff:%e /walltime:%f"%(\ + A_over_c[0], A_over_c[1], A_over_c[2], + this._Aeff_over_c_xVVx[0], this._Aeff_over_c_xVVx[1], this._Aeff_over_c_xVVx[2], + A_over_c_diff,tmrefAU_Aind, this._tmrefAU_xVVx, xVVx_diff, wct_xVVx),fpath="xVVx.log",Append=True) + this._xVVx = arrayclone( xVVx_matr);this._tmrefAU_xVVx = tmrefAU_Aind; + this._Aeff_over_c_xVVx = [ A_over_c[0], A_over_c[1], A_over_c[2] ] + Dic001={}; + n_dev = check_Hermicity_xKaa('A',xVVx_matr,3,len(this.kpts),Dic=Dic001,title="xVVx_matr") + absmaxv= max( abs( np.ravel(xVVx_matr) ) ) + fd_xVVxlog =open("xVVx_consistency.log","a"); + print(" step %d, time %f (fs), absmax:%e anti Hermicity:%s job:%s time:%s"%(\ + (-1 if(this._step is None) else this._step),\ + (-1.0 if(this._time_AU is None) else this._time_AU*AUinFS),\ + absmaxv, str(Dic001),str(rttddft_common.get_job(True)),\ + str(datetime.datetime.now())),file=fd_xVVxlog) + ### 2021.08.24 :: fwrite_zNbuf(xVVx_matr,"xVVx_matr_%04d.dat"%(istep),Append=False,description="xVVx",format="%16.8f %16.8f",delimiter=" ",Threads=[0]) + ### print("#rttddft01:check_Hermicity_xKaa returns:%d"%(n_dev),flush=True); + v_add = -1j*dmtrace_xKaa( xVVx_matr,3,dm_kpts,pbc,this._spinrestriction) + + # v_add := [x, V]/(i\hbar) the real part is to be added to the electronic velocity + # the imaginary part should be zero in principle because of the Hermicity of xVVx/i\hbar . + + dum=np.sqrt( v_add[0].imag**2 + v_add[1].imag**2 + v_add[2].imag**2 ) + print("xVVx:v_add imag:%e"%(dum)) + print("#v_add: %15.5e %15.5e %15.5e %15.5e %15.5e %15.5e"%(\ + v_add[0].real,v_add[0].imag, v_add[1].real,v_add[1].imag, v_add[2].real,v_add[2].imag),file=fd_xVVxlog) + fd_xVVxlog.close() + assert dum<1e-4, "check anti hermicity or dmtrace" + + for kk in range(3): + ret_RandV[1][kk]+= v_add[kk].real + dipvel_3 = [ ret_RandV[1][0], ret_RandV[1][1], ret_RandV[1][2] ] + + dirZ=[0.0, 0.0, 1.0 ] + if( rttddft_common.Params_get("polarization") is not None ): + ## dirZ= np.array( parse_doubles(pyscf_common.params["polarization"],delimiter=',') ); + dirZ= np.array( parse_doubles(rttddft_common.Params_get("polarization"),delimiter=',') ); + if( Ncall_xVVx == 1 ): + dum=np.sqrt( np.vdot( dirZ,dirZ ) );assert abs(dum-1)<1e-5,"polarization vector" + if( Ncall_xVVx == 1 ): + printout("#%14s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %s"%( + "time_AU", "xVVx_x","xVVx_y","xVVx_z","xVVx_n", "dipvel3_x","dipvel3_y","dipvel3_z","dipvel3_n", + "dipvel0_x","dipvel0_y","dipvel0_z","dipvel0_n", "Aext_x","Aext_y","Aext_z","Aext_n", + "Aind_x","Aind_y","Aind_z","Aind_n", "xVVx_x","xVVx_y","xVVx_z","xVVx_n", "walltime"), + dtme=True,fpath=rttddft_common.get_job(True)+"_dipvel.dat",Append=False ); + + printout(" %14.6f %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %16.6e %f"%( + this._time_AU,\ + v_add[0].real, v_add[1].real, v_add[2].real, np.vdot(dirZ, np.array([ v_add[0].real, v_add[1].real, v_add[2].real ])),\ + dipvel_3[0], dipvel_3[1], dipvel_3[2], np.vdot(dirZ, dipvel_3),\ + dipvel_0[0], dipvel_0[1], dipvel_0[2], np.vdot(dirZ, dipvel_0),\ + dipvel_1[0]-dipvel_0[0], dipvel_1[1]-dipvel_0[1], dipvel_1[2]-dipvel_0[2], np.vdot(dirZ, np.array(dipvel_1)-np.array(dipvel_0)),\ + dipvel_2[0]-dipvel_1[0], dipvel_2[1]-dipvel_1[1], dipvel_2[2]-dipvel_1[2], np.vdot(dirZ, np.array(dipvel_2)-np.array(dipvel_1)),\ + dipvel_3[0]-dipvel_2[0], dipvel_3[1]-dipvel_2[1], dipvel_3[2]-dipvel_2[2], np.vdot(dirZ, np.array(dipvel_3)-np.array(dipvel_2)),\ + wct_xVVx),dtme=True,fpath=rttddft_common.get_job(True)+"_dipvel.dat",Append=True ); + dipvel_x0 =[ dipvel_0[0]+v_add[0].real, dipvel_0[1]+v_add[1].real, dipvel_0[2]+v_add[2].real ] + + ### print("#rttddft01:dmtrace_xKaa returns",flush=True); + if( dbgng_calcAind and MPIrank==0 ): + tm_fs=this._time_AU*( physicalconstants.aut_in_femtosec );n_rcd=rttddft_common.Countup("calc_Aind_dipvel.dat") + fd01a=open("calc_Aind_dipvel.dat",("a" if(n_rcd>1) else "w")); + if(n_rcd==1): + print("#%14s %14s %50s %50s %50s %50s %50s %50s"%(\ + "time_au","time_fs","dipvel_0","dipvel-Aext","dipvel-Aeff","dipvel-Aeff_corrected","Aind_over_c","v_add"),file=fd01a) + strWRN="" + Aind_REF=( Aind_over_c if(Aind_over_c is not None) else [ 0,0,0] );strWRN+=(" Aind_over_c_is_None" if(Aind_over_c is None) else ""); + vadd_REF=( v_add if(v_add is not None) else [0.0+1j*0.0, 0.0+1j*0.0, 0.0+1j*0.0]);strWRN+=(" v_add_is_None" if(v_add is None) else ""); + Aeff_REF=[ A_over_c[0] + Aind_REF[0] + vadd_REF[0], A_over_c[1] + Aind_REF[1] + vadd_REF[1], A_over_c[2] + Aind_REF[2] + vadd_REF[2] ] + print(" %14.6f %14.6f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.6e %16.6e %16.6e %16.8f %16.8f %16.8f"%(\ + this._time_AU, tm_fs, dipvel_0[0], dipvel_0[1], dipvel_0[2], dipvel_1[0], dipvel_1[1], dipvel_1[2],\ + dipvel_2[0], dipvel_2[1], dipvel_2[2], ret_RandV[1][0], ret_RandV[1][1], ret_RandV[1][2], + Aind_REF[0], Aind_REF[1], Aind_REF[2], vadd_REF[0].real, vadd_REF[1].real, vadd_REF[2].real, + Aeff_REF[0], Aeff_REF[1], Aeff_REF[2] )+strWRN ) + print(" %14.6f %14.6f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.6e %16.6e %16.6e %16.8f %16.8f %16.8f"%(\ + this._time_AU, tm_fs, dipvel_0[0], dipvel_0[1], dipvel_0[2], dipvel_1[0], dipvel_1[1], dipvel_1[2],\ + dipvel_2[0], dipvel_2[1], dipvel_2[2], ret_RandV[1][0], ret_RandV[1][1], ret_RandV[1][2], + Aind_REF[0], Aind_REF[1], Aind_REF[2], vadd_REF[0].real, vadd_REF[1].real, vadd_REF[2].real, + Aeff_REF[0], Aeff_REF[1], Aeff_REF[2] )+strWRN,file=fd01a) + fd01a.close() + if(n_rcd==1): + ### os.system("gnuf.sh calc_Aind_dipvel"); + fd01a=open("calc_Aind_dipvel.plt","w"); + print("set term postscript color\nset output \"calc_Aind_dipvel.ps\"\n",file=fd01a); + print("plot \"calc_Aind_dipvel.dat\" using 2:5 title \"v_0\" with lines ls 2,\\\n" \ + +"\"\" using 2:8 title \"v-Aext\" with lines ls 4,\\\n" \ + +"\"\" using 2:11 title \"v-Aeff\" with lines ls 6,\\\n" \ + +"\"\" using 2:14 title \"v-Aeff-fix\" with lines ls 8",file=fd01a); + print("plot \"calc_Aind_dipvel.dat\" using 2:17 title \"A_{ind}\" with lines ls 102,\\\n" \ + +"\"\" using 2:20 title \"v-add\" with lines ls 4",file=fd01a);fd01a.close() + + + else: + continue + + dict_retv={'dipole':ret_RandV[0], 'dipole_velocity':ret_RandV[1]};strdiff="" + if( dipvel_0 is not None ): + dict_retv.update( {'dipvel_0':dipvel_0} ) + if( dipvel_x0 is not None ): + dict_retv.update( {'dipvel_x0':dipvel_x0} ) + if( dipvel_1 is not None ): + dict_retv.update( {'dipvel_1':dipvel_1, 'dipvel_2':dipvel_2} ) + if( dipvel_3 is not None ): + dict_retv.update( {'dipvel_3':dipvel_3} ) + check_dip_ref=(molecular_dipole is not None) + calc_MOLdip=( (molecular_dipole is not None) and (not this._pbc) ) + if(calc_MOLdip): + dip_ref=None + if(this._pbc): + dip_ref= this.dip_moment( this.cell, dm_kpts, unit='au', verbose=pyscflib_logger.WARN) + else: + dip_ref= this.dip_moment( this.mol, dm_kpts, unit='au', verbose=pyscflib_logger.WARN) + ## takes summation over spin + dict_retv.update({'molecular_dipole':dip_ref}) + dip_dist=d1dist( dip_ref, ret_RandV[0]) + dip_dist1=dip_dist + charge_center = None + if(this._pbc): + charges = this.cell.atom_charges() + coords = this.cell.atom_coords() + charge_center = np.einsum('i,ix->x', charges, coords) / charges.sum() + else: + charges = this.mol.atom_charges() + coords = this.mol.atom_coords() + charge_center = np.einsum('z,zr->r', charges, coords)/charges.sum() + + if( molecular_dipole is not None ): + molecular_dipole.clear() + molecular_dipole.append( dip_ref ) + else: + assert dip_dist1<1.0e-7,"check dipoles.." + + strdiff="" + diff_moldip_eldip=[ ret_RandV[0][kk]-dip_ref[kk] for kk in range(3) ];Ddiff=[0.0, 0.0, 0.0] + if( Dipoles_static.Diff_moldip_eldip_ is None): + Dipoles_static.Diff_moldip_eldip_ = diff_moldip_eldip + strdiff=" %14.6f %14.6f %14.6f "%( + diff_moldip_eldip[0],diff_moldip_eldip[1],diff_moldip_eldip[2]) + ### Ddiff[0],Ddiff[1],Ddiff[2]) + else: + for k in range(3): + Ddiff[k]= diff_moldip_eldip[k] - Dipoles_static.Diff_moldip_eldip_[k] + strdiff=" %14.6f %14.6f %14.6f %14.6f %14.6f %14.6f"%( + diff_moldip_eldip[0],diff_moldip_eldip[1],diff_moldip_eldip[2], + Ddiff[0],Ddiff[1],Ddiff[2]) + elif( molecular_dipole is not None ): + molecular_dipole.append( [0.0, 0.0, 0.0]) + + if( (filepath is not None) and (not suppress_prtout()) ): + nmult_dipole=1 ### (1 if(this._spinrestriction == 'R') else 2) + fd=futils.fopen(filepath,"a");## OK + if(headline): + strbuf="#1:%11s 2:%16s 3:%16s 4:%16s 5:%16s 6:%16s 7:%16s"%("tm_AU","x","y","z","Vx","Vy","Vz") + ncol=7 + if( dipvel_0 is not None ): + strbuf+=" %2d:%15s %2d:%15s %2d:%15s"%( ncol+1,"v^{0}_x", ncol+2,"v^{0}_y", ncol+3,"v^{0}_z");ncol+=3 + if( dipvel_1 is not None ): + strbuf+=" %2d:%15s %2d:%15s %2d:%15s"%( ncol+1,"p-qA^{ext}_x", ncol+2,"p-qA^{ext}_y", ncol+3,"p-qA^{ext}_z"); + strbuf+=" %2d:%15s %2d:%15s %2d:%15s"%( ncol+4,"p-qA^{tot}_x", ncol+5,"p-qA^{tot}_y", ncol+6,"p-qA^{tot}_z");ncol+=6 + if( current is not None): + strbuf+=" %2d:%15s %2d:%15s %2d:%15s"%( ncol+1,"Jx", ncol+2,"Jy", ncol+3,"Jz"); ncol+=3 + + if( this._calc_Aind < 0 ): + strbuf+=" %2d:%15s %2d:%15s %2d:%15s"%( ncol+1,"C-dAdt/c.x",ncol+2,"C-dAdt/c.y", ncol+3,"C-dAdt/c.z");ncol+=3 + strbuf+=" %2d:%15s %2d:%15s %2d:%15s"%( ncol+1,"Aind/c.x",ncol+2,"Aind/c.y", ncol+3,"Aind/c.z");ncol+=3 + elif( this._calc_Aind > 0 ): + strbuf+=" %2d:%15s %2d:%15s %2d:%15s"%( ncol+1,"P-dAdt/c.x",ncol+2,"P-dAdt/c.y", ncol+3,"P-dAdt/c.z");ncol+=3 + strbuf+=" %2d:%15s %2d:%15s %2d:%15s"%( ncol+1,"Aind/c.x",ncol+2,"Aind/c.y", ncol+3,"Aind/c.z");ncol+=3 + + if( molecular_dipole is not None): + strbuf+=" %2d:%15s %2d:%15s %2d:%15s"%( ncol+1,"Moldip.x", ncol+2,"Moldip.y", ncol+3,"Moldip.z"); ncol+=3 + + print(strbuf,file=fd) + + print(header,end="",file=fd) + if(mode == 'B' or mode=='R'): + for m in range(nmult_dipole): + ref=( ret_RandV[0] if(nmult_dipole==1) else ret_RandV[0][m] ) + print(" %18.10f %18.10f %18.10f "%( ref[0], ref[1], ref[2]), end="", file=fd) + if(mode == 'B' or mode=='V'): + for m in range(nmult_dipole): + ref=( ret_RandV[1] if(nmult_dipole==1) else ret_RandV[1][m] ) + print(" %18.10f %18.10f %18.10f "%( ref[0], ref[1], ref[2]), end="", file=fd) + if( dipvel_0 is not None ): + print(" %18.10f %18.10f %18.10f "%( dipvel_0[0], dipvel_0[1], dipvel_0[2]), end="", file=fd) + if( dipvel_1 is not None ): + print(" %18.10f %18.10f %18.10f "%( dipvel_1[0], dipvel_1[1], dipvel_1[2]), end="", file=fd) + print(" %18.10f %18.10f %18.10f "%( dipvel_2[0], dipvel_2[1], dipvel_2[2]), end="", file=fd) + + if(current is not None): + print(" %18.10f %18.10f %18.10f "%( current[0], current[1], current[2]), end="", file=fd) + + if( this._calc_Aind <0 ): + if( this._Aind_Gearvc_C is None ): + print(" %18.10f %18.10f %18.10f "%( 0.0, 0.0, 0.0),end="",file=fd) + print(" %18.10f %18.10f %18.10f "%( 0.0, 0.0, 0.0),end="",file=fd) + else: + print(" %18.10f %18.10f %18.10f "%( this._Aind_Gearvc_C[1][0]/this._dt_AU, this._Aind_Gearvc_C[1][1]/this._dt_AU, this._Aind_Gearvc_C[1][2]/this._dt_AU),end="",file=fd) + print(" %18.10f %18.10f %18.10f "%( this._Aind_Gearvc_C[0][0], this._Aind_Gearvc_C[0][1], this._Aind_Gearvc_C[0][2]/this._dt_AU),end="",file=fd) + elif( this._calc_Aind >0 ): + if( this._Aind_Gearvc_P is None ): + print(" %18.10f %18.10f %18.10f "%( 0.0, 0.0, 0.0),end="",file=fd) + print(" %18.10f %18.10f %18.10f "%( 0.0, 0.0, 0.0),end="",file=fd) + else: + print(" %18.10f %18.10f %18.10f "%( this._Aind_Gearvc_P[1][0]/this._dt_AU, this._Aind_Gearvc_P[1][1]/this._dt_AU, this._Aind_Gearvc_P[1][2]/this._dt_AU),end="",file=fd) + print(" %18.10f %18.10f %18.10f "%( this._Aind_Gearvc_P[0][0], this._Aind_Gearvc_P[0][1], this._Aind_Gearvc_P[0][2]/this._dt_AU),end="",file=fd) + + if(molecular_dipole is not None): + ndim1=np.shape( molecular_dipole[0] );rank1=len(ndim1); + ## [3] or [2][3] + nmult_moldip=1 ### (1 if(this._spinrestriction == 'R' or rank1==1) else 2) + for m in range(nmult_moldip): + ref=( molecular_dipole[0] if(nmult_moldip==1) else molecular_dipole[0][m] ) + print(" %18.10f %18.10f %18.10f %s"%( molecular_dipole[0][0], + molecular_dipole[0][1],molecular_dipole[0][2],strdiff),end="",file=fd) + print(STRwalltime,end="",file=fd) + print(trailer,file=fd) + futils.fclose(fd) + return dict_retv; + +def update_Aind_over_c(this): + n_call=rttddft_common.Countup("update_Aind_over_c") + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); + assert this._Aind_tmNxt is not None,"" + assert this._Aind_Gearvc_C_nxt is not None,"" + + if( this._Aind_over_c_Nintpl is not None ): + assert this._veff_latest is not None,"this._veff_latest is None tm:%f"%(this._Aind_tmNxt) + this._veff_LAST=np.array( [ this._veff_latest[kk] for kk in range(3) ] ) + this._veff_tmAU=this._tmAU_veff_latest + this._veff_latest=None; this._tmAU_veff_latest=None + + AUinFS=0.02418884326058678 + this._Aind_tmAU=this._Aind_tmNxt + for ii in range(5): + for jj in range(3): + this._Aind_Gearvc_C[ii][jj]=this._Aind_Gearvc_C_nxt[ii][jj] + this._Aind_Gearvc_P[ii][jj]=this._Aind_Gearvc_P_nxt[ii][jj] + this._Aind_Gearvc_C_nxt=None; this._Aind_Gearvc_P_nxt=None; this._Aind_tmNxt=None + +def rttddft_set_Aind_args(this,Dic,errorlogfnme=None,verbose=False): + nerror=rttddft_sget_Aind_args_('S',this,Dic,errorlogfnme=errorlogfnme,verbose=verbose); + assert nerror==0,"" + +def rttddft_get_Aind_args(this,Dic,errorlogfnme=None,verbose=False): + nerror=rttddft_sget_Aind_args_('G',this,Dic,errorlogfnme=errorlogfnme,verbose=verbose); + assert nerror==0,"" + +def check_nao_nr(mol, cart=None): + ANG_OF = 1 + NCTR_OF = 3 + '''Total number of contracted GTOs for the given :class:`Mole` object''' + if cart is None: + cart = mol.cart + if cart: + ### print("#nao_nr:cart...",flush=True) + return nao_cart(mol) + else: + ### print("#nao_nr:_ANG:",end="");print(mol._bas[:,ANG_OF]) + ### print("#nao_nr:NCTR:",end="");print(mol._bas[:,NCTR_OF]) + return ((mol._bas[:,ANG_OF]*2+1) * mol._bas[:,NCTR_OF]).sum() + +def update_timing(this,label,cputime,Nskip_prtout=20,logfpath=None,logfappend=True,logtext=""): + if(this.timing is None): + this.timing={} + if( not (label in this.timing)): + dic1={"count":0,"time":0.0} + this.timing.update({label:dic1}) + dic1=this.timing[label] + dic1["count"]+=1;dic1["time"]+=(cputime) + prtou=(dic1["count"]==1) + if(Nskip_prtout>0): + if( dic1["count"]%Nskip_prtout==0): + prtou=True + if(prtou and (not suppress_prtout()) ): + fdA=[ sys.stdout ];fdOUTF=None + if( logfpath is not None ): + fdOUTF =futils.fopen(logfpath,("a" if(logfappend) else "w")); + fdA.append(fdOUTF) + for fdx in fdA: + print("#"+label+":%f %s: %s sum:%f(%d) avg:%f"%( + cputime, str(label),str(logtext), dic1["time"], dic1["count"], dic1["time"]/dic1["count"]),file=fdx) + if(fdOUTF is not None): + futils.fclose(fdOUTF) + +def tocomplex(src): + ndim=np.shape(src) + ### print("#toComplex:",end="");print(ndim) + rank=len(ndim) + if( rank<5): + ret=np.zeros(ndim,dtype=np.complex128) + for i in range(ndim[0]): + if(rank<2): + ret[i]=src[i];continue + for j in range(ndim[1]): + if(rank<3): + ret[i][j]=src[i][j];continue + for k in range(ndim[2]): + if(rank<4): + ret[i][j][k]=src[i][j][k];continue + for l in range(ndim[3]): + ret[i][j][k][l]=src[i][j][k][l]; + return ret; + else: + Ld=1; + for j in range(rank): + Ld=Ld*ndim[j] + s1d=np.ravel(src) + r1d=np.zeros([Ld],dtype=np.complex128) + for k in range(Ld): + r1d[k]=s1d[k] + return np.reshape(r1d,ndim) + +def calc_FieldEng_cell(this,tmAU=None,Dict=None): + if(tmAU is None ): + tmAU=this._time_AU + + if( this.cell_volume is None ): + assert this.BravaisVectors_au is not None,"" + this.cell_volume=calc_3Dvolume( this.BravaisVectors_au ) + PIx8=25.132741228718345907701147066236 + fac=this.cell_volume/PIx8 + + E_tot=[ 0.0, 0.0, 0.0 ] + E_ext=[ 0.0, 0.0, 0.0 ] + if( this._td_field is not None ): + if( not isinstance( this._td_field, kickfield ) ): + E_ext=this._td_field.get_electricfield( tmAU ) + if( this._calc_Aind == 0 ): + Esqr= E_ext[0]**2 + E_ext[1]**2 + E_ext[2]**2 + return 0.0, Esqr*fac + if( Dict is not None ): + Dict.update({"E_ext":[ E_ext[0],E_ext[1],E_ext[2] ] }) +### 2021.08.25 assert False,"" +### 2021.08.25 return 0 + if( this._Aind_Gearvc_C is None ): + assert False,"_Aind_Gearvc_C" + return 0 + Implicit=(this._calc_Aind < 0 ) + Adot_over_c=( this._Aind_Gearvc_C[1]/this._dt_AU if(Implicit) else this._Aind_Gearvc_P[1]/this._dt_AU ) + ret0= ( Adot_over_c[0]**2 + Adot_over_c[1]**2 + Adot_over_c[2]**2 )*fac + ### printout("#cell_volume:",this.cell_volume,fac,this._Aind_Gearvc_C[1]) + ### printout("#Adot_over_c:%e %e %e"%(Adot_over_c[0],Adot_over_c[1],Adot_over_c[2])) + E_tot=[ E_ext[k] - Adot_over_c[k] for k in range(3) ] + Esqr= E_tot[0]**2 + E_tot[1]**2 + E_tot[2]**2 + ret1=Esqr*fac + if( Dict is not None ): + Dict.update({"E_ind":[ -Adot_over_c[0],-Adot_over_c[1],-Adot_over_c[2] ] }) + Dict.update({"E_tot":[ E_tot[0],E_tot[1],E_tot[2] ]}) + return ret0,ret1 + +def krhf_get_hcore_pp(this, cell=None, kpts=None,tm_AU=None,Dict_DBG=None, A_over_c=None): + import time + from .utils import aNmaxdiff,print_z2array + from .update_dict import printout_dict,update_dict + + ''' Copy of khf.py#get_hcore + Get the core Hamiltonian AO matrices at sampled k-points. + + Args: + kpts : (nkpts, 3) ndarray + + Returns: + hcore : (nkpts, nao, nao) ndarray + ''' + assert (this._pbc),"never come here otherwise" + cLIGHT_AU=PhysicalConstants.CLIGHTinAU() + if tm_AU is None: tm_AU=this._time_AU + if cell is None: cell = this.cell + if kpts is None: kpts = this.kpts + + n_call=rttddft_common.Countup("krhf_get_hcore_pp") + fncnme='krhf_get_hcore_pp';fncdepth=2 ## fncdepth ~ SCF:0 vhf:1 get_j:2 + Wctm000=time.time();Wctm010=Wctm000;dic1={} + Dic=rttddft_common.Dict_getv('timing_'+fncnme, default=None) + if( Dic is None ): + rttddft_common.Dict_setv('timing_'+fncnme, {}); + Dic=rttddft_common.Dict_getv('timing_'+fncnme, default=None) + + dbgng=False + ## see UT/with_fftdf_get_pp + ## dbgng_pp=True;pp_dbgfnme=str(rttddft_common.get_job(True))+"_pp.dat" + + if( this._td_field is not None ): + A_div_c = (A_over_c if(A_over_c is not None) else this._td_field.get_vectorfield(tm_AU)/cLIGHT_AU ) + Logger.write_once(logger=None,title="get_hcore_AoverC",content="AoverC:%f,%f,%f"%(A_div_c[0],A_div_c[1],A_div_c[2]),fnme="get_hcore.log") + if cell.pseudo: + details=None + if( ( n_call == 1 or n_call == 5 or n_call == 20 or n_call == 50 or n_call == 200 ) and + isinstance( this.with_df, df.GDF ) ): + details={} + if( Dict_DBG is not None ): + Dict_DBG.update({'get_pp':'new'}) + if( isinstance( this.with_df, df.FFTDF ) ): + nuc=lib.asarray( with_fftdf_get_pp(this.with_df, A_div_c, kpts=kpts) ) + #if( dbgng_pp ): + # svld_aNbuf("S",pp_dbgfnme,buf=nuc, + # comment="A_over_c:"+str(A_over_c)+"Rnuc:"+tostring(this.get_Rnuc(unit='ANGS'))) + else: + nuc=lib.asarray( with_df_get_pp( this.with_df,A_div_c,kpts,rttddft=this, details=details ) ) ### this.with_df.get_pp01(kpts,A_div_c)) + #if( dbgng_pp ): + # svld_aNbuf("S",pp_dbgfnme,buf=nuc, + # comment="A_over_c:"+str(A_over_c)+"Rnuc:"+tostring(this.get_Rnuc(unit='ANGS'))) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1,Dic,"get_pp_A",Wctm010-Wctm020,depth=fncdepth) + Wctm_par=Wctm010-Wctm020 + + ## n_call = rttddft_common.Countup("krhf_get_hcore_pp") + if( ( n_call == 1 or n_call == 5 or n_call == 20 or n_call == 50 or n_call == 200 ) and + isinstance( this.with_df, df.GDF ) ): + ## + ## 20210609MPIvalidation: When you remove this validation, you might want to comment-in dbgng_mpi in gto_ps_pp_int01.py line 955 .. + ## + details_bf20210608={} + nuc_refr=lib.asarray( with_df_get_pp_bf20210608( this.with_df,A_div_c,kpts,details=details_bf20210608 ) ) + + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1,Dic,"get_pp_singlethread",Wctm010-Wctm020,depth=fncdepth) + diff=aNmaxdiff( nuc, nuc_refr ) + diffs={}; + for ky in details: + diffs.update({ky:aNmaxdiff( details[ky],details_bf20210608[ky])}) + printout("with_df_get_pp %d:%e %s walltime par:%f / ser:%f"%(n_call,diff, str(diffs),Wctm_par, Wctm010-Wctm020), + fpath="ppnl_half.log",Append=True,Threads=[0]) + + if(diff>=1.0e-7): + zerovec=np.zeros([3],dtype=np.float64) + ppZF_new=with_df_get_pp( this.with_df,zerovec,kpts,rttddft=this ) + ppZF_old=with_df_get_pp_bf20210608( this.with_df,zerovec,kpts) + ppZF_refr=this.with_df.get_pp(kpts) + dev_r_n=aNmaxdiff( ppZF_refr, ppZF_new) + dev_r_o=aNmaxdiff( ppZF_refr, ppZF_old) + dev_n_o=aNmaxdiff( ppZF_new, ppZF_old) + printout("#ppZF:%e %e %e"%(dev_r_n,dev_r_o,dev_n_o),fpath="ppZF_comp.log",Append=False,dtme=True) + assert diff<1.0e-7,"new/old deviates" + ### print("#with_df_get_pp returns",flush=True) + else: + assert False,"" + else: + if cell.pseudo: + if( Dict_DBG is not None ): + Dict_DBG.update({'get_pp':'old'}) + nuc = lib.asarray(this.with_df.get_pp(kpts)) + + #if( dbgng_pp ): + # svld_aNbuf("S",pp_dbgfnme, + # buf=nuc,comment=tostring(this.get_Rnuc(unit='ANGS'))) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1,Dic,"get_pp",Wctm010-Wctm020,depth=fncdepth) + else: + nuc = lib.asarray(this.with_df.get_nuc(kpts)) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1,Dic,"get_nuc",Wctm010-Wctm020,depth=fncdepth) + if len(cell._ecpbas) > 0: + nuc += lib.asarray(ecp.ecp_int(cell, kpts)) + #if(dbgng_pp): + # os.system("fopen "+pp_dbgfnme) + # assert False,"dbgng_pp" + t=None + if( hasattr(this,"_fixednucleiapprox") ): + if( this._fixednucleiapprox is not None ): + if( this._fixednucleiapprox ): + if( this.int1e_kin_ is None ): + this.int1e_kin_=lib.asarray(cell.pbc_intor('int1e_kin', 1, 1, kpts)) + Wctm020=Wctm010;Wctm010=time.time() ## XXX XXX + update_dict(fncnme,dic1,Dic,"int1e_kin",Wctm010-Wctm020,depth=fncdepth) ## XXX XXX + t=arrayclone( this.int1e_kin_) + if( n_call == 2 or n_call == 10 or n_call == 50 ): + t_ref=lib.asarray(cell.pbc_intor('int1e_kin', 1, 1, kpts)) + Wctm020=Wctm010;Wctm010=time.time() ## XXX XXX + update_dict(fncnme,dic1,Dic,"int1e_kin_DBG",Wctm010-Wctm020,depth=fncdepth) ## XXX XXX + diff=aNmaxdiff(t,t_ref) + printout("int1e_kin:diff=%e time=%f"%(diff,Wctm010-Wctm020), + fnme_format="Save_vloc_%02d.log",Append=True) + assert (diff<1.0e-10),"t deviates" + t = lib.asarray(cell.pbc_intor('int1e_kin', 1, 1, kpts)) + Wctm020=Wctm010;Wctm010=time.time() + update_dict(fncnme,dic1,Dic,"int1e_kin",Wctm010-Wctm020,depth=fncdepth) + printout_dict(fncnme,dic1,Dic,Wctm010-Wctm000,depth=fncdepth) + return nuc + t + + + + + +def get_Aind_over_c(this,tm_AU,errlv=-1): + ### test_Aind_over_c(this) ## XXX XXX + tmAU_TINY=1.0e-8 + if( this._calc_Aind == 0 ): + return None + Implicit_scheme=( this._calc_Aind < 0 ) + if( this._Aind_Gearvc_C is None ): + if( abs(tm_AU) Matrix Calculators --------------------------------------------------------- + get_hcore = get_hcore + + def get_veff(self, cell=None, dm=None, dm_last=0, vhf_last=0, hermi=1, kpts=None, kpts_band=None): + cput0=time.time(); + retv= krks_get_veff(self,cell=cell,dm=dm,dm_last=dm_last,vhf_last=vhf_last,hermi=hermi,kpts=kpts,kpts_band=kpts_band) + cput1=time.time(); + if(self.timing is None): + self.timing={} + if( not ("get_veff" in self.timing)): + Dic={"count":0,"time":0.0} + self.timing.update({"get_veff":Dic}) + self.timing["get_veff"]["count"]+=1;self.timing["get_veff"]["time"]+=(cput1-cput0) + dic=self.timing["get_veff"] + if( (dic["count"]==1 or dic["count"]%20==0) and (not suppress_prtout()) ): + fdlog=futils.fopen("get_veff.log","a");Ndim=np.shape(retv); ## OK + for fd in [fdlog,sys.stdout]: + print("#get_veff:%f step %s sum:%f(%d) avg:%f "%( + cput1-cput0, str(Ndim), dic["time"], dic["count"], dic["time"]/dic["count"]) + +" \t\t" + rttddft_common.get_job(True)+ " \t\t" + str(datetime.datetime.now()), file=fd ) + futils.fclose(fdlog) + return retv + + def energy_nuc(self,Rnuc_au=None): + if(Rnuc_au is not None): + ref_1d=np.ravel( self.mol.atom_coords() ) + inp_1d=np.ravel( Rnuc_au ) + dev=max( abs(ref_1d-inp_1d) ) + assert dev<1e-6,"dev:%e:"%(dev)+str(inp_1d)+"/"+str(ref_1d) + + retv=super().energy_nuc() + return retv + + def get_occ(self, mo_energy_kpts=None, mo_coeff_kpts=None): + if( self._fix_occ ): + assert (self._mo_occ is not None),"" + return self._mo_occ + else: + ret = khf_get_occ(self,mo_energy_kpts,mo_coeff_kpts) + return ret; + + +class rttddftMOL(RKS): + seqno_=0 + def __init__(self, mol, xc='LDA,VWN',td_field=None,dipolegauge=False,logger=None): + self._pbc=False + self._spinrestriction='R' + rttddftMOL.seqno_+=1 + Logger.write_once( None, "rttddft_xc:"+xc, + content="rttddftMOL:"+xc+" \t\t "+str(datetime.datetime.now()), + fnme="rttddft_xc.log", append=True ) + self._td_field=td_field + self._time_AU=0.0 + self._fix_occ=False + self._logger=logger + self._step=None + self._mo_occ=None + self._iflag_prtout_field=0 + if( dipolegauge ): + assert (td_field is not None),"field is missing" + self.dipolegauge=(td_field is not None); + self.velocitygauge=False + else: + self.velocitygauge=(td_field is not None); + self.dipolegauge=False; + + self._calc_Aind=0 + self._constantfield=False; + self._wt000=time.time() + self._sINV=None + self._Sinvrt=None + self._Ssqrt=None + self.nkpt=None; self.nAO=None; self.nMO=None; + self._fixednucleiapprox=None ## 20210610:fixednucleiapprox + RKS.__init__(self,mol,xc) + + get_HOMO = get_HOMO + get_SOMO = get_SOMO + get_LUMO = get_LUMO + + update_nOrbs = update_nOrbs + set_nOrbs = set_nOrbs + + calc_gs = calc_gs + + set_mo_occ = set_mo_occ + + update_Sinv = update_Sinv + + energy_tot = energy_tot + + energy_elec = energy_elec_rks + + get_Rnuc = get_Rnuc + + get_logger = get_logger + set_logger = set_logger + + get_populations = get_populations + + calc_phases = calc_phases + + print_eorbocc = print_eorbocc + + def get_super(self): + return super() + + #> Matrix Calculators --------------------------------------------------------- + get_hcore = get_hcore + + def energy_nuc(self,Rnuc_au=None): + if(Rnuc_au is not None): + ref_1d=np.ravel( self.mol.atom_coords() ) + inp_1d=np.ravel( Rnuc_au ) + dev=max( abs(ref_1d-inp_1d) ) + assert dev<1e-6,"dev:%e:"%(dev)+str(inp_1d)+"/"+str(ref_1d) + + retv=super().energy_nuc() + return retv + + def get_occ(self, mo_energy=None, mo_coeff=None): + if( self._fix_occ ): + assert (self._mo_occ is not None),"" + return self._mo_occ + else: + return super().get_occ(mo_energy,mo_coeff) + +def construct_Aind_args(strIN): + ### print("## construct_Aind_args:"+strIN,flush=True) + Dic=parse_dict(strIN) + ### print("## construct_Aind_args:Dic:"+str(Dic),flush=True) + Ret={} + for item in rttddftPBC.Keys_Aind_over_c_: + sA=item.split(':');nA=len(sA);assert nA==2,"wrong format:"+str(item) + ky=sA[0].strip(); ty=sA[1]; + if( ky not in Dic ): + errorstring="#construct_Aind_args:ky:%s missing in Dic"%(ky); + printout(errorstring,fpath=rttddft_common.get_job(True)+"_Aind_over_c_setting.log",Append=True,dtme=True,warning=1);continue + val=Dic[ky] + if( val is not None and val=='None' ): + val=None + printout("#construct_Aind_args:"+ky+":"+ty+":"+str(val),fpath=rttddft_common.get_job(True)+"_Aind_over_c_setting.log",Append=True,dtme=True) + print("#construct_Aind_args:%s "%(ky),val,type(val)); + if( ky in rttddftPBC.Keys_Aind_over_c_allow_None_): + if( val is None ): + print("#construct_Aind_args:%s:skipping None... "%(ky),val); + Ret.update({ky:val}); continue ## never forget to set None + elif( val is None ): + print("%s is not in allow_None"%(ky),val) + if(ty[0]=='D'): + if( ky in rttddftPBC.Keys_Aind_over_c_list_not_ndarray_ ): + assert isinstance(val,list),"" ### or convert ndarray to list + else: + if( not isinstance(val,np.ndarray) ): + val=list_to_array(val) + assert isinstance(val,np.ndarray),"" + else: + if(ty[0]=='d'): + if( val is not None ): + val=float(val); + elif(ty[0]=='i'): + if( val is not None ): + val=int(val) + else: + assert False,"key:"+ky+" type:"+ty + Ret.update({ky:val}) + return Ret; + +# if( pyscf_common.params["Aind_over_c_Nintpl"] is not None ): +# assuming +## tm_AU tm_dmat this._Aind_tmAU ._dt_AU and GEARvecs _Aind_tmNxt and _Aind_Gearvc_C_nxt +## DEFAULT : None +## 1st call : 0.0 0.0 None->0.0 -> initialized +# h/Nintpl +# 2h/Nintpl +# ... +# (Nintpl-1)h/Nintpl +## 2nd call : h h -- h rGEAR2ndOne(GEARvecs) +## 3rd call : h h -- h rGEAR2ndOne(GEARvecs) +## AF-eldyn : h _Aind_Gearvc_C_nxt +## ... here C is at this._Aind_tmAU, P is at this._Aind_tmAU+dt_AU +def propagate_Aind_over_c_interpol(this,tm_AU,dt_AU, dm_kOR1, tm_dmat=None, Aind_over_c_ini=None,caller=""): + dbgng_Aind_over_c_interpol=True;fdDBG=None + flag_Aind=abs(this._calc_Aind) + if( dbgng_Aind_over_c_interpol ): + Istep= int( round(tm_AU/dt_AU) );Imod=Istep%2; + if( Istep == 1 ): + os.system("cat propagate_Aind_over_c_interpol_%d.wks > propagate_Aind_over_c_interpol_DBG.log"%(1-Imod) ) + elif( Istep > 0 ): + idum=os.system("cat propagate_Aind_over_c_interpol_%d.wks >> propagate_Aind_over_c_interpol_DBG.log"%(1-Imod) ) + ### print("cat propagate_Aind_over_c_interpol_%d.wks >> propagate_Aind_over_c_interpol_DBG.log %d"%(1-Imod,idum) ) + ### os.system("cat propagate_Aind_over_c_interpol_%d.wks"%(1-Imod)) + ### os.system("fopen propagate_Aind_over_c_interpol_DBG.log") + fdDBG= open("propagate_Aind_over_c_interpol_%d.wks"%(Imod),"w") + + def SQRdist3D(a,b): + return ( (a[0]-b[0])**2 + (a[1]-b[1])**2 + (a[2]-b[2])**2 ) + def get_dipvel0_eff(this,dmat,tmAU_dmat,caller=""): ## dmat-dependent part of dip-vel + dbgng=1 + flag=abs(this._calc_Aind) + PIx4=12.566370614359172953850573533118;tmAU_TINY=1.0e-8 + if( this.cell_volume is None ): + assert this.BravaisVectors_au is not None,"" + this.cell_volume=calc_3Dvolume( this.BravaisVectors_au ) + # ------ + # Strictly speaking, v^{0} (or paramagnetic current times cell_volume) depends on A through xVVx term + # We however assume dependence of xVVx term on A (as well as ampd of xVVx term) to be small and use + # A_{ext+ind}(t) and DM^{guess}(t+h) to calculate v^{0}(t+h) + # v^{phys} or v^{0}(t+h)+A(t+h)/c on the other hand uses A carefully propagated in this subroutine + # ------ + cLIGHT_AU=PhysicalConstants.CLIGHTinAU() + tmAU_refr=this._time_AU + assert (abs(tmAU_dmat) 0 ): + # v1 = v0 + Aext * N_ele_sum + assert SQRdist3D( dic['dipvel_0'] + Aext_over_c_t1 * N_ele_sum, dic['dipvel_1'] ) < 1.0e-8,"" + assert SQRdist3D( dic['dipvel_0'] + Atot_over_c_t1 * N_ele_sum, dic['dipvel_2'] ) < 1.0e-8,"" + if(flag==4): + assert SQRdist3D( dic['dipvel_3'] - Atot_over_c_t1 * N_ele_sum, dic['dipvel_x0'] ) < 1.0e-8,"" + if( flag != 4 ): + return dic['dipvel_0'] + else: + return dic['dipvel_x0'] + def make_d2Aind_over_c_dt2_(this, flag, time_au, veff0, Aind_over_c=None): + N_ele=get_Nele(this) + PIx4=12.566370614359172953850573533118; + cLIGHT_AU=PhysicalConstants.CLIGHTinAU() + + if( this.cell_volume is None ): + assert this.BravaisVectors_au is not None,"" + this.cell_volume=calc_3Dvolume( this.BravaisVectors_au ) + fac= PIx4/this.cell_volume; q_e=-1 + if( this._alpha_Aind_over_c is not None ): + fac=fac*this._alpha_Aind_over_c + if( flag == 1 ): + return np.array([ q_e*veff0[kk]*fac for kk in range(3) ]) + A_over_c = this._td_field.get_vectorfield(time_au)/cLIGHT_AU + if( flag == 2 ): + return np.array([ q_e*(veff0[kk]-q_e*A_over_c[kk]*N_ele)*fac for kk in range(3) ]) + assert Aind_over_c is not None,"" + return np.array([ q_e*(veff0[kk]-q_e*( A_over_c[kk] + Aind_over_c[kk])*N_ele )*fac for kk in range(3) ]) + + assert this._calc_Aind < 0,"" + tmAU_TINY=1.0e-8; AUinFS=0.02418884326058678; Ld=3; Implicit_Scheme=True; PIx4=12.566370614359172953850573533118; + + if( this._dt_AU is None ): + this._dt_AU = ( dt_AU if(dt_AU is not None) else tm_AU-this._Aind_tmAU) + else: + assert abs( this._dt_AU - dt_AU ) 1e-10 + + if not hybrid and isinstance(ks.with_df, multigrid.MultiGridFFTDF): + n, exc, vxc = multigrid.nr_uks(ks.with_df, ks.xc, dm, hermi, + kpts, kpts_band, + with_j=True, return_j=False) + pyscf_logger.debug(ks, 'nelec by numeric integration = %s', n) + t0 = pyscf_logger.timer(ks, 'vxc', *t0) + return vxc + + # ndim = 4 : dm.shape = ([alpha,beta], nkpts, nao, nao) + ground_state = (dm.ndim == 4 and dm.shape[0] == 2 and kpts_band is None) + + if ks.grids.non0tab is None: + ks.grids.build(with_non0tab=True) + if (isinstance(ks.grids, gen_grid.BeckeGrids) and + ks.small_rho_cutoff > 1e-20 and ground_state): + ks.grids = rks.prune_small_rho_grids_(ks, cell, dm, ks.grids, kpts) + t0 = pyscf_logger.timer(ks, 'setting up grids', *t0) + + if hermi == 2: # because rho = 0 + n, exc, vxc = (0,0), 0, 0 + else: + n, exc, vxc = ks._numint.nr_uks(cell, ks.grids, ks.xc, dm, 0, + kpts, kpts_band) + pyscf_logger.debug(ks, 'nelec by numeric integration = %s', n) + t0 = pyscf_logger.timer(ks, 'vxc', *t0) + + weight = 1./len(kpts) + + if not hybrid: + vj = ks.get_j(cell, dm[0]+dm[1], hermi, kpts, kpts_band) + ## XXX XXX + if( (np.array(vxc).dtype == np.float64 or np.array(vxc).dtype == float) and + (np.array(vj).dtype == np.complex128 or np.array(vj).dtype == complex) ): + ### print("#kuks_get_veff:complex conversion ...",flush=True) + Ndim_vxc=np.shape(vxc) # [2][nKpt][nAO][nAO] + ### print("#vxc:"+str(Ndim_vxc));#vxc:(2, 1, 16, 16) + if( len(Ndim_vxc) < 4 ): + Ndim_vxc=[ np.shape(vxc[sp]) for sp in range(2) ] + print(Ndim_vxc);assert False,"" + vxc=tocomplex(vxc) + + vxc += vj + else: + if getattr(ks.with_df, '_j_only', False): # for GDF and MDF + ks.with_df._j_only = False + vj, vk = ks.get_jk(cell, dm, hermi, kpts, kpts_band) + vj = vj[0] + vj[1] + vk *= hyb + if abs(omega) > 1e-10: + vklr = ks.get_k(cell, dm, hermi, kpts, kpts_band, omega=omega) + vklr *= (alpha - hyb) + vk += vklr + vxc += vj - vk + + if ground_state: + exc -= (np.einsum('Kij,Kji', dm[0], vk[0]) + + np.einsum('Kij,Kji', dm[1], vk[1])).real * .5 * weight + + if ground_state: + ecoul = np.einsum('Kij,Kji', dm[0]+dm[1], vj).real * .5 * weight + else: + ecoul = None + + vxc = pyscf_lib.tag_array(vxc, ecoul=ecoul, exc=exc, vj=None, vk=None) + return vxc + +class rttddftPBC_ROKS(KROKS): + def __init__(self, cell, kpts=np.zeros((1,3)), xc='LDA,VWN',td_field=None, dipolegauge=False, logger=None, + exxdiv=getattr(__config__, 'pbc_scf_SCF_exxdiv', 'ewald'), calc_Aind=False): + self._pbc=True + self._spinrestriction='O' + self._td_field=td_field + self._time_AU=0.0 + self._fix_occ=False + self._logger=logger + self._step=None + self._mo_occ=None + if( dipolegauge ): + assert (td_field is not None),"field is missing" + self.dipolegauge=(td_field is not None); + self.velocitygauge=False + else: + self.velocitygauge=(td_field is not None); + self.dipolegauge=False; + self._sINV=None + self._Sinvrt=None + self._Ssqrt=None + self.nkpt=None; self.nAO=None; self.nMO=None; + self._calc_Aind=calc_Aind + KROKS.__init__(self,cell, kpts=kpts, xc=xc,exxdiv=exxdiv) +# def __init__(self, cell, kpts=np.zeros((1,3)), xc='LDA,VWN', +# exxdiv=getattr(__config__, 'pbc_scf_SCF_exxdiv', 'ewald')): + + get_HOMO = get_HOMO + get_SOMO = get_SOMO + get_LUMO = get_LUMO + + update_nOrbs = update_nOrbs + set_nOrbs = set_nOrbs + + calc_gs = calc_gs + set_mo_occ = set_mo_occ + def get_super(self): + return super() + update_Sinv = update_Sinv + + energy_tot = energy_tot + + energy_elec = energy_elec_super + + get_Rnuc = get_Rnuc + + get_hcore = get_hcore + + get_logger = get_logger + + set_logger = set_logger + + get_populations = get_populations + + calc_phases = calc_phases + + print_eorbocc = print_eorbocc + +class RTTDDFT_: + @staticmethod + def is_rttddft(item): + return ( isinstance(item,rttddftMOL) or isinstance(item,rttddftPBC) or \ + isinstance(item,rttddftMOL_ROKS) or isinstance(item,rttddftPBC_ROKS) or \ + isinstance(item,rttddftMOL_UKS) or isinstance(item,rttddftPBC_UKS) ) diff --git a/pyscf/rttddft/rttddft_common.py b/pyscf/rttddft/rttddft_common.py new file mode 100644 index 000000000..f97aa4850 --- /dev/null +++ b/pyscf/rttddft/rttddft_common.py @@ -0,0 +1,665 @@ +import numpy as np +import sys +import os +import math +import os.path +import time +import datetime +from mpi4py import MPI + +class Stack: + def __init__(self,bfsz): + self.buf=[] + self.bfsz=bfsz + self.o=0 + self.len=0 + def contains(self,item): + return (item in self.buf) + def append(self,item): + if(self.len>=self.bfsz): + self.buf[ self.o ]=item; + self.o=(self.o+1)%self.bfsz + else: + self.buf.append(item); self.len+=1 + return self + def toarray(self): + return [ self.buf[(self.o+k)%self.bfsz] for k in range(self.len) ] + def clear(self): + self.buf.clear();self.o=0;self.len=0 + def last(ith=0): ## here we define ith=0: last item ith=1:last-1 ... + ## o+0 + ## [ 0, 1 ... le-1 ] + ## le-1 0th + if( ith >= self.len ): + print("#Stack.last %d / %d"%(ith,self.len)) + return None + else: + indx= ( self.o+(self.len-1-ith) )%self.bfsz + return self.buf[indx] +class Filewriter: + def __init__(self,fpath, bfsz=10): + self.fpath=fpath + self._append=False + self.strbuf=[];self.nbuf=0 + self.bfsz=bfsz + def prtout(self): + ### print("Logwriter:%s nbuf=%d printing out..."%(self.fpath,self.nbuf)) + fd=open(self.fpath,('a' if(self._append) else 'w')) + retv=0 + for item in self.strbuf: + print(item,file=fd);retv+=1 + fd.close(); self._append=True + return retv + + def append(self,text,timing=False): + self.strbuf.append(text); self.nbuf+=1 + ### print("Logwriter:%s nbuf=%d"%(self.fpath,self.nbuf)) + if( self.nbuf >=self.bfsz ): + self.prtout() + self.nbuf=0;self.strbuf.clear() + +class rttddft_common: + # Note we have removed: mf_SCF_|Dict_Clipboard|params + + SCF_buf=[]; SCF_bfsz=5; n_SCF=0; + SCF_warnings={} # key:{'count':0,'i_SCF':[ 5 most recent occurrence ] } + + _Keys_Write_once=[];_Filenames_Write_once=[] + + job=None + Rnuc_=None + time_AU_=None + step_=None + + _Counter={} + _Dict={} + + Dict_Print_warning_={} + + _Time_000=None; + wt_010={}; Key=None; KeyHistory=None;Timing={} + + _iVerbose=1;Logwriter=None;Logfpath_=None;_Warning_logfile=None + + Dict_Clipboard={} + _Params={} + @staticmethod + def Params_update(dic): + if( rttddft_common._Params is None ): + rttddft_common._Params={} + rttddft_common._Params.update(dic) + + @staticmethod + def Params_get(key,default=None): + if( rttddft_common._Params is None ): + return default + if( key not in rttddft_common._Params ): + return default + return rttddft_common._Params[key]; + + @staticmethod + def set_params(dict,job=None): + def get1(dic,key,default=None): + if(key in dic): + return dic[key] + else: + return default; + if( job is None): + job= get1(dict, "name","pySCF_job") + "_" + get1(dict,"xc","") + get1(dict, "basis","") + get1(dict,"branch","") + rttddft_common.job=job + rttddft_common._Params=dict + rttddft_common.Setup() + + @staticmethod + def Clipboard(key,value=None,default=None,clear=None,set_value=False): + if(value is not None or set_value ): + rttddft_common.Dict_Clipboard.update({key:value}) + ### print("#Clipboard:SET:%s:"%(key),value) + else: + if(key in rttddft_common.Dict_Clipboard ): + if( clear is not None): + if(clear): + item = rttddft_common.Dict_Clipboard.pop(key) + print("#Clipboard:CLEAR:%s:"%(key),item) + return item + return rttddft_common.Dict_Clipboard[key] + else: + # keyset=[ ky for ky in rttddft_common.Dict_Clipboard ] + # print("!W key:%s is not in rttddft_common.Dict_Clipboard"%( str(key) ),keyset) + return default + + @staticmethod + def Setup(bfsz=5): + if( rttddft_common._Time_000 is None ): + rttddft_common._Time_000=time.time() + if( rttddft_common.KeyHistory is None ): + rttddft_common.KeyHistory=Stack(bfsz) + if( rttddft_common.Logwriter is None ): + rttddft_common.Logwriter=Filewriter(\ + ("rttddft_common" if (rttddft_common.job is None) else rttddft_common.job)\ + + "_logger.log" ) + + @staticmethod + def Get_time(): + if( rttddft_common._Time_000 is None ): + rttddft_common.Setup() + + return time.time()-rttddft_common._Time_000 + + @staticmethod + def Dict_setv(key,val): + rttddft_common._Dict.update({key:val}) + + @staticmethod + def Dict_getv(key,default=None): + if( key in rttddft_common._Dict ): + return rttddft_common._Dict[key] + else: + return default + + @staticmethod + def set_job(job,override=False): + if( rttddft_common.job is not None ): + if( not override ): + return + rttddft_common.job=job + + @staticmethod + def get_job(safe=False): + if( safe ): + if( rttddft_common.job is None ): + return "" + return rttddft_common.job + + @staticmethod + def DebugWrite(key="",content="",array=None,buf=None,Threads=[0],open=True,dtme=True): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if( Threads is not None ): + if( MPIsize>1 and (MPIrank not in Threads) ): + return 0 + fd=None;isNew=False + if( rttddft_common.Logfpath_ is None ): + today=datetime.date.today() + fnme="pyscfdbg_%04d%02d%02d.log"%(today.year,today.month,today.day) + if( os.path.exists(fnme) ): + fd=open(fnme,"a");print("\n\n\n### %s %s --------"%(str(rttddft_common.job,datetime.datetime.now())),file=fd) + else: + fd=open(fnme,"w");print("### %s %s --------"%(str(rttddft_common.job,datetime.datetime.now())),file=fd) + rttddft_common.Logfpath_=fnme; + isNew=True + else: + fd=open( rttddft_common.Logfpath_,"a"); + if( array is not None ): + content+=" "+str(array) + if( dtme ): + content+=" \t\t"+str(datetime.datetime.now()) + print("#%s:%s"%(key,content),file=fd); + if( buf is not None ): + print("#%s:buf:%s"%(key,str(buf)),file=fd) + fd.close() + if( isNew ): + os.system("ls -ltrh "+rttddft_common.Logfpath_) + @staticmethod + def Printout_warning(key,content,level=-1, nth_call=[1], dtme=True, Threads=[0], fpath=None, Append=None): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + + isempty=( len(rttddft_common.Dict_Print_warning_)==0 ) + MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if( key not in rttddft_common.Dict_Print_warning_ ): + rttddft_common.Dict_Print_warning_.update({key:0}); + rttddft_common.Dict_Print_warning_[key]+=1 + if( dtme ): + content+=" \t\t "+str(datetime.datetime.now()) + nth=rttddft_common.Dict_Print_warning_[key] + + logfpath0=rttddft_common.get_job(True) + "_Print_warning.log" + Fpaths=[ logfpath0 ];Flags=[ ("w" if(isempty) else "a") ] + if(fpath is not None): + if( Append is None ): + Append=True + Fpaths.append(fpath);Flags.append("a" if(Append) else "w") + + if( MPIsize < 2 or MPIrank in Threads ): + Nf=len(Fpaths) + if( nth in nth_call ): + for I in range(Nf): + fdOU=open( Fpaths[I], Flags[I] ) + print("#%s:"%(key)+content,file=fdOU) + fdOU.close() + print("#%s:"%(key)+content) + + if( isempty and abs(level)>1 ): + os.system("ls -ltrh "+logfpath0) + @staticmethod + def Set_Rnuc(Rnuc,step=None,time_AU=None,Logging=[0],sync=False ): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + AUinFS=2.418884326058678e-2 + + strRnuc="" + Nat=len(Rnuc) + for I in range(Nat): + strRnuc+=("" if(I==0) else ";")+"%12.6f,%12.6f,%12.6f"%(Rnuc[I][0],Rnuc[I][1],Rnuc[I][2]) + logfpath = "Set_Rnuc_%02d.log"%(MPIrank) + if( sync ): + print("#Set_Rnuc:Bcast..") + comm.Bcast(Rnuc,root=0) + fd1=open(logfpath,"a"); + strlog="#Bcast:" + strlog+=strRnuc + if( step is not None ): strlog+=" step=%d"%(step); + if( time_AU is not None ): strlog+=" time=%14.5f,%12.4f"%(time_AU,time_AU*AUinFS) + strlog+=" \t\t "+str( datetime.datetime.now() ) + print(strlog,file=fd1) + fd1.close() + + diffs=None + if( rttddft_common.Rnuc_ is not None ): + Nat=len( rttddft_common.Rnuc_ ) + diffs=[ np.sqrt( (Rnuc[I][0]-rttddft_common.Rnuc_[I][0])**2 + + (Rnuc[I][1]-rttddft_common.Rnuc_[I][1])**2 + + (Rnuc[I][2]-rttddft_common.Rnuc_[I][2])**2 ) for I in range(Nat) ] + dev=max( diffs ) + + if( Logging is not None ): + if( MPIrank in Logging ): + path="Set_Rnuc_%02d.log"%(MPIrank) + fdOU=open(path,"a") + strbuf="" + strbuf +=strRnuc + if( step is not None ): strbuf+=" step=%d"%(step); + if( time_AU is not None ): strbuf+=" time=%14.5f,%12.4f"%(time_AU,time_AU*AUinFS) + strbuf+=" \t\t "+str( datetime.datetime.now() ) + print(strbuf,file=fdOU);fdOU.close() + print("#Set_Rnuc:"+strbuf, diffs) + + + Ndim=np.shape(Rnuc) + if( step is not None ): + rttddft_common.step_=step + if( time_AU is not None ): + rttddft_common.time_AU_=time_AU + print("#rttddft_common.Rnuc:$%02d:set:"%(MPIrank),Rnuc,step,time_AU) + rank=len(Ndim);assert rank==1 or rank==2,"" + rttddft_common.Rnuc_=np.zeros(Ndim,dtype=np.float64) + if(rank==2): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + rttddft_common.Rnuc_[I][J]=Rnuc[I][J] + else: + for I in range(Ndim[0]): + rttddft_common.Rnuc_[I]=Rnuc[I] + + @staticmethod + def Get_Rnuc(clone=False): + if(not clone): + return rttddft_common.Rnuc_ + + Ndim=np.shape(rttddft_common.Rnuc_) + rank=len(Ndim);assert rank==1 or rank==2,"" + ret=np.zeros(Ndim,dtype=np.float64) + if(rank==2): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + ret[I][J]=rttddft_common.Rnuc_[I][J] + else: + for I in range(Ndim[0]): + ret[I]=rttddft_common.Rnuc_[I] + return ret + + @staticmethod + def Assert(bool,text,severity): + if(bool): + return 0 + rttddft_common.Print_warning(text,severity=severity) + if( severity<0 ): + assert False,""+text + @staticmethod + def Print_warning(text,severity=1): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if( severity>=0 and MPIrank>0 ): + return + Append=True + if( rttddft_common._Warning_logfile is None ): + rttddft_common._Warning_logfile=("pyscf_" if(rttddft_common.job is None) else rttddft_common.job)\ + +"_warning.log" + Append=False + fd=open( rttddft_common._Warning_logfile,('a' if(Append) else 'w')) + print(text+" \t\t"+str(datetime.datetime.now()),file=fd) + fd.close() + + @staticmethod + def Write_once(key,text,fpath=None,filename=None,Append=False,stdout=True): + if( key in rttddft_common._Keys_Write_once ): + return + else: + rttddft_common._Keys_Write_once.append(key) + fdA=[];fdOU=None + if(stdout or (fpath is None)): + fdA.append(sys.stdout) + + if(fpath is not None): + fdOU=open(fpath,('a' if(Append) else 'w')) + fdA.append(fdOU) + else: + if(filename is not None): + append_file=True + if( filename not in rttddft_common._Filenames_Write_once ): + rttddft_common._Filenames_Write_once.append( filename );append_file=False + fpath=rttddft_common.get_job(True)+"_"+filename+".log" + ## print("Write_once:%s %r"%(fpath,append_file)) + fdOU=open(fpath,('a' if(append_file) else 'w')) + fdA.append(fdOU) + for fd in fdA: + print(key+":"+text,file=fd) + if(fdOU is not None): + fdOU.close() + + @staticmethod + def Append_SCFwarning(item,i_SCF=None): + if( i_SCF is None ): + i_SCF = rttddft_common.n_SCF + if( item not in rttddft_common.SCF_warnings ): + rttddft_common.SCF_warnings.update({item:{'count':0,'i_SCF':Stack(5)}}) + rttddft_common.SCF_warnings[item]['count']+=1 + if( not rttddft_common.SCF_warnings[item]['i_SCF'].contains(i_SCF) ): + rttddft_common.SCF_warnings[item]['i_SCF'].append(i_SCF) + + @staticmethod + def Setup_SCFbuf(): + if( len(rttddft_common.SCF_buf)==0 ): + for I in range(rttddft_common.SCF_bfsz): + rttddft_common.SCF_buf.append({'iter':0, 'time':0, 'cvgd':None}) + rttddft_common.SCF_buf.append({'iter':{'sum':0.0,'sqrsum':0.0}, 'time':{'sum':0.0,'sqrsum':0.0} }) + @staticmethod + def Get_SCFresult(nth=0): + if( nth >= rttddft_common.SCF_bfsz): + return None + i_SCF= rttddft_common.n_SCF-1 - nth + if( i_SCF < 0 ): + return None + iMOD=i_SCF%rttddft_common.SCF_bfsz + return rttddft_common.SCF_buf[iMOD] + + @staticmethod + def Set_SCFresult(cvgd, iter, Egnd, time, warnings=None,dbuf=None): + import sys + import datetime + if( len(rttddft_common.SCF_buf)==0 ): + rttddft_common.Setup_SCFbuf() + rttddft_common.n_SCF+=1 + i_SCF= rttddft_common.n_SCF-1 + iMOD=i_SCF%rttddft_common.SCF_bfsz + rttddft_common.SCF_buf[iMOD]['cvgd']=cvgd + rttddft_common.SCF_buf[iMOD]['iter']=iter + rttddft_common.SCF_buf[iMOD]['time']=time + ### rttddft_common.SCF_buf[iMOD]['warnings'].clear() + rttddft_common.SCF_buf[rttddft_common.SCF_bfsz]['iter']['sum']+=iter + rttddft_common.SCF_buf[rttddft_common.SCF_bfsz]['iter']['sqrsum']+=iter**2 + + rttddft_common.SCF_buf[rttddft_common.SCF_bfsz]['time']['sum']+=time + rttddft_common.SCF_buf[rttddft_common.SCF_bfsz]['time']['sqrsum']+=time**2 + if( not cvgd ): + fdOU=open('SCF_failure_%05d.log'%(i_SCF),'a') + string="#SCF:%05d failed after %d iterations"%(i_SCF,iter)+" \t\t\t "+str(datetime.datetime.now()) + if( warnings is not None ): + for item in warnings: + string+='\n##!W: '+str(item) + for fd in [fdOU,sys.stdout]: + print(string,file=fd) + if( dbuf is not None ): + le=len(dbuf); + print("#%4s %16s %14s %14s"%('iter','Etot','|g|','ddm'),file=fdOU) + for I in range(le): + print(" %4d %16.8f %14.6e %14.6e"%(I,dbuf[I][0],dbuf[I][1],dbuf[I][2]),file=fdOU) + fdOU.close() + + if( warnings is not None ): + for item in warnings: + rttddft_common.Append_SCFwarning(item,i_SCF=i_SCF) + if( rttddft_common.n_SCF == 1 or rttddft_common.n_SCF==5 or rttddft_common.n_SCF==10 or rttddft_common.n_SCF == 20 or + rttddft_common.n_SCF %100==0 ): + fpath=("" if(rttddft_common.job is None) else rttddft_common.job)+"_SCF.log" + rttddft_common.Print_SCFresults( fpath,Append=( rttddft_common.n_SCF>1 )) + + @staticmethod + def Print_SCFresults(fpath=None,Append=False): + fdA=[ sys.stdout ] + fdout=(None if(fpath is None) else open(fpath,('a' if(Append) else 'w'))) + if(fdout is not None): + fdA.append(fdout) + if( len(rttddft_common.SCF_buf) <= rttddft_common.SCF_bfsz ): + print("#Print_SCFresults:len:%d / bfsz:%d"%( len(rttddft_common.SCF_buf), rttddft_common.SCF_bfsz )) + return + + Dic=rttddft_common.SCF_buf[rttddft_common.SCF_bfsz] + strWarning="" + for key in rttddft_common.SCF_warnings: + wdict= rttddft_common.SCF_warnings[key] + strWarning +=key+":%3d / %4d"%( rttddft_common.SCF_warnings[key]['count'],rttddft_common.n_SCF ) \ + +str( rttddft_common.SCF_warnings[key]['i_SCF'].toarray() ) + if( len(strWarning.strip())>0 ): + strWarning=" Warning:"+strWarning + for fd in fdA: + is_stdout=(fd==sys.stdout) + av_iter=Dic['iter']['sum']/float(rttddft_common.n_SCF) + stdv_iter=np.sqrt( abs( Dic['iter']['sqrsum']/float(rttddft_common.n_SCF) -av_iter**2 ) ) + + av_time=Dic['time']['sum']/float(rttddft_common.n_SCF) + stdv_time=np.sqrt( abs( Dic['time']['sqrsum']/float(rttddft_common.n_SCF) -av_iter**2 ) ) + if( (not Append) and (fdout is not None) and fd==fdout ): + print("#%6s %6s %14s %14s %14s %14s %14s %14s "%("n_SCF", + "sum_iter","avg_iter","stdv_iter", + "sum_time","avg_time","stdv_time","per-iter-time"),file=fd) + + # ITER TIME + # n_SCF sum av stdv sum av stdv PER-ITER-time + print("%s %6d %6d %14.6f %14.4e %14.6f %14.6f %14.4e %14.6f "%( + ("#SCFresults:" if(is_stdout) else ""), rttddft_common.n_SCF, + Dic['iter']['sum'], av_iter, stdv_iter, + Dic['time']['sum'], av_time, stdv_time, Dic['time']['sum']/float(Dic['iter']['sum'])) + +strWarning,file=fd) + if(fdout is not None): + fdout.close() + + @staticmethod + def Countup(key,inc=True): ## by default 1,2,3,... + if( key not in rttddft_common._Counter ): + if( not inc ): + return 0 + else: + rttddft_common._Counter.update({key:0}) + if(inc): + rttddft_common._Counter[key]+=1 + return rttddft_common._Counter[key] + @staticmethod + def count(key,inc=False): + return rttddft_common.Countup(key,inc=inc) + + @staticmethod + def Update_timing(key,walltime,flush=False,doNotPrtOut=False): + if( key not in rttddft_common.Timing ): + rttddft_common.Timing.update({key:{'count':0,'sum':0.0,'sqrsum':0.0}}) + rttddft_common.Timing[key]['count']+=1 + rttddft_common.Timing[key]['sum']+=walltime + rttddft_common.Timing[key]['sqrsum']+=walltime**2 + ncount=rttddft_common.Timing[key]['count'] + ### print("#rttddft_common.Update_timing:%s:%d"%(key,ncount)) + if( not doNotPrtOut ): + if( ncount == 1 or ncount==10 or ncount==20 or ncount == 100 or ncount== 200 or ncount==1000 ): + avg= rttddft_common.Timing[key]['sum'] / rttddft_common.Timing[key]['count'] + stdv=np.sqrt( abs( rttddft_common.Timing[key]['sqrsum'] / rttddft_common.Timing[key]['count'] - avg**2 ) ) + print("#AvgTime:%24s %14.4f %14.4e %d %14.4f avg/stdv/count/sum"%(key,avg,stdv, + rttddft_common.Timing[key]['count'], rttddft_common.Timing[key]['sum'])) + return rttddft_common.Timing[key]['count'] + @staticmethod + def Print_timing(name,keys,walltime=None,flush=False,depth=1,N_iter=None,subkey=""): + ### print("#rttddft_common.print_timing.."); + if( N_iter is not None ): + ky1=name+"_N_iter" + rttddft_common.Update_timing(ky1,N_iter,flush=False,doNotPrtOut=False) + if(ky1 not in keys): + keys.append(ky1) + if( name in [ 'get_veff', 'get_j', 'Get_Veff'] ): + name1=name+"_1st" + if( name1 not in rttddft_common.Timing): + rttddft_common._Print_timing( name1, keys, walltime=walltime, flush=flush, depth=depth) + else: + name2=name+"_2nd" + name_upd=name2 + if( name2 in rttddft_common.Timing ): + av = rttddft_common.Timing[name2]['sum']/rttddft_common.Timing[name2]['count'] + stdv = np.sqrt( abs( rttddft_common.Timing[name2]['sqrsum']/rttddft_common.Timing[name2]['count'] - av**2 ) ) + av_1 = rttddft_common.Timing[name1]['sum']/rttddft_common.Timing[name1]['count'] + stdv_1 = np.sqrt( abs( rttddft_common.Timing[name1]['sqrsum']/rttddft_common.Timing[name1]['count'] - av_1**2 ) ) + if( abs(av - walltime)> max(1.0, stdv)*3 ): + print("#get_Veff:%s:time %f / get_Veff_2nd av=%f(%f) av1=%f(%f) ... %s"%(subkey,walltime,av,stdv,av_1,stdv_1,name_upd)) + rttddft_common._Print_timing( name_upd, keys, walltime=walltime, flush=flush, depth=depth) + else: + rttddft_common._Print_timing( name, keys, walltime=walltime, flush=flush, depth=depth) + @staticmethod + def _Print_timing(name, keys, walltime=None, flush=False, depth=1): + fpath=("rttddft_common" if(rttddft_common.job is None) else rttddft_common.job)+"_"+name+"_walltime.log" + wctNow=time.time() - rttddft_common._Time_000 + ### print("#rttddft_common._Print_timing..%f"%(wctNow) +fpath); + + ncount=None;keyAL=None + if(walltime is not None): + ncount=rttddft_common.Update_timing( name,walltime,doNotPrtOut=True) + keyAL=[name] + for ky in keys: + keyAL.append(ky) + ### print("#rttddft_common._Print_timing.1: %s %d"%(name,ncount)) + else: + ncount=99999 + for ky in keys: + if( ky in rttddft_common.Timing): + ncount=min(ncount,rttddft_common.Timing[key]['count']) + keyAL=[] + for ky in keys: + keyAL.append(ky) + ### print("#rttddft_common._Print_timing.2: %s %d"%(name,ncount)) + + if( flush ): + header='#'*(2*depth) + strtm=("--" if(walltime is None) else "%14.4f"%(walltime)) + print( header + "END:%24s %14s %14.4f"%(name, strtm, wctNow) + +" \t\t\t "+("" if(rttddft_common.job is None) else rttddft_common.job) + + " "+str(datetime.datetime.now())) + + if( ncount == 1 or ncount==10 or ncount==20 or ncount == 100 or ncount== 200 or ncount==1000 ): + string="";legend="";ncol=0 + for key in keyAL: + if( key not in rttddft_common.Timing ): + keyset=[ ky for ky in rttddft_common.Timing ] + print("#!W %s not in Timing:"%(key)+str(keyset));continue + avg= rttddft_common.Timing[key]['sum'] / rttddft_common.Timing[key]['count'] + stdv=np.sqrt( abs( rttddft_common.Timing[key]['sqrsum'] / rttddft_common.Timing[key]['count'] - avg**2 ) ) + string+=" %18.4f %18.4e %8d %18.4f "%(avg,stdv, + rttddft_common.Timing[key]['count'], rttddft_common.Timing[key]['sum']) + legend+=" %4d:%24s_%24s_av,stdv,cnt,sum "%(ncol+1,key,name) + ncol+=4 + fdOu=open( fpath,('w' if(ncount==1) else 'a')) + if( ncount==1 ): + print(legend,file=fdOu); + print(string,file=fdOu); + fdOu.close() + return ncount + + @staticmethod + def Assert(bool,text,severity): + if(bool): + return 0 + rttddft_common.Print_warning(text,severity=severity) + if( severity<0 ): + assert False,""+text + @staticmethod + def Print_warning(text,severity=1): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if( severity>=0 and MPIrank>0 ): + return + Append=True + if( rttddft_common._Warning_logfile is None ): + rttddft_common._Warning_logfile=("pyscf_" if( rttddft_common.job is None) else rttddft_common.job)\ + +"_warning.log" + Append=False + fd=open( rttddft_common._Warning_logfile,('a' if(Append) else 'w')) + print(text+" \t\t"+str(datetime.datetime.now()),file=fd) + fd.close() + + + + + @staticmethod + def Start_timer(key,flush=False,depth=1): + if( rttddft_common._Time_000 is None ): + rttddft_common.Setup() + rttddft_common.wt_010.update({key: time.time() - rttddft_common._Time_000}) + oldky=rttddft_common.Key + if( oldky is not None ): + rttddft_common.KeyHistory.append(oldky); + rttddft_common.Key=key + + ### print("#Start_timer:"+str(oldky)+" >> current:"+str(rttddft_common.Key)) + if( flush or rttddft_common._iVerbose>1): + header='#'*(2*depth) + rttddft_common.Logwriter.append( header + "start:%24s %14.4f "%(key, rttddft_common.wt_010[key]) + +" \t\t\t "+("" if(rttddft_common.job is None) else rttddft_common.job) + + " "+str(datetime.datetime.now())) + return rttddft_common.wt_010[key] + @staticmethod + def Switch_timer(key1,key2,flush=False,depth=1): + ret= rttddft_common.Stop_timer(key1,key2=key2,flush=flush,depth=depth) + return ret + @staticmethod + def Stop_timer(key,key2=None,flush=False,depth=1,subkey=""): + if( rttddft_common._Time_000 is None): + rttddft_common.Setup(); + wctNow=time.time() - rttddft_common._Time_000 +# if( key == rttddft_common.Key ): + if( key in rttddft_common.wt_010 ): + if( key in [ 'get_veff', 'get_j'] ): + key1=key+"_1st" + if( key1 not in rttddft_common.Timing): + rttddft_common.Update_timing( key1, wctNow-rttddft_common.wt_010[key], flush=flush) + else: + key2=key+"_2nd";tCUR=wctNow-rttddft_common.wt_010[key] + key_to_upd=key2 + if( key2 in rttddft_common.Timing): + av = rttddft_common.Timing[key2]['sum']/rttddft_common.Timing[key2]['count'] + stdv = np.sqrt( abs( rttddft_common.Timing[key2]['sqrsum']/rttddft_common.Timing[key2]['count'] - av**2 ) ) + av_1 = rttddft_common.Timing[key1]['sum']/rttddft_common.Timing[key1]['count'] + stdv_1 = np.sqrt( abs( rttddft_common.Timing[key1]['sqrsum']/rttddft_common.Timing[key1]['count'] - av_1**2 ) ) + if( abs(av - tCUR)> max(1.0, stdv)*3 ): + if( abs(av_1-tCUR)1): + header='#'*(2*depth) + rttddft_common.Logwriter.append( header + "END:%24s %14.4f %14.4f"%(key, wctNow-rttddft_common.wt_010[key], wctNow) + +" \t\t\t "+("" if(rttddft_common.job is None) else rttddft_common.job) + + " "+str(datetime.datetime.now())) + + rttddft_common.Key=None; rttddft_common.wt_010.pop(key,None) + else: + rttddft_common.Logwriter.append("## key:%s did not end tmNow:%f"%(key,wctNow)) + ### rttddft_common.Key=None; rttddft_common.wt_010=None + if( flush or rttddft_common._iVerbose>1): + header='#'*(2*depth) + rttddft_common.Logwriter.append( header + "END:%24s %14s %14.4f"%(key, "--", wctNow) + +" \t\t\t "+("" if(rttddft_common.job is None) else rttddft_common.job) + + " "+str(datetime.datetime.now())) + if( key2 is None ): + return wctNow + else: + ### print("#Switching to:"+str(key2)) + return rttddft_common.Start_timer(key2) diff --git a/pyscf/rttddft/serialize.py b/pyscf/rttddft/serialize.py new file mode 100644 index 000000000..895204f68 --- /dev/null +++ b/pyscf/rttddft/serialize.py @@ -0,0 +1,1004 @@ +import datetime +import numpy as np +import sys +import os +import time +from .utils import i1toa,d1toa,z1toa,iNtoa,dNtoa,zNtoa,sNtoa,aNmaxdiff,i1eqb +from .Stdlogger import Stdlogger +from .laserfield import kickfield, CWField01, gaussianpulse01, Trapezoidalpulse +from mpi4py import MPI +from .Loglv import printout +from .rttddft_common import rttddft_common + +def serialize_CDIIS(this,delimiter=';'): + return serialize(this,delimiter=delimiter) +def construct_CDIIS(string,delimiter=';'): + if( string=="None" ): + return None + retv=None + sbuf=string.split(delimiter) + col0=sbuf.pop(0); + sA=col0.split(':'); key=sA[0].strip();strtype=read_strtype( sA[1].strip() ); + assert (key=="type"),"" + assert (strtype=="CDIIS"),"strtype:"+strtype + types,values=parse_slist(sbuf) + retv=CDIIS() + return load_fromlist(retv,sbuf) + +def diff_dict(lh,rh,verbose=0): + Ndiff=0; Nsame=0; Nerr=0; strErr=""; strDiff="" + for ky in lh: + if(not(ky in rh)): + Nerr+=1; strErr+="#%d:%s lh:%s rh:missing"%(Nerr,str(ky),str(lh))+";" + else: + nd,ns,ne=diff_objects( lh[ky], rh[ky] ) + if(ne>0): + Nerr+=1; strErr+="#%d:%s lh:%s rh:%s diff:%d,%d,%d"%(Nerr,str(ky),str(lh),str(rh),nd,ns,ne)+";" + elif(nd>0): + Ndiff+=1;strDiff+="#%d:%s lh:%s rh:%s diff:%d,%d,%d"%(Ndiff,str(ky),str(lh),str(rh),nd,ns,ne)+";" + elif(ns>0): + Nsame+=1; + else: + strErr+="###:%s lh:%s rh:%s diff:%d,%d,%d"%(str(ky),str(lh),str(rh),nd,ns,ne)+";" + strLog=""; + if(len(strDiff)>0): + if(len(strLog)>0): + strLog="ERR:%d:"%(Nerr)+strErr+";\t DIFF:%d:"%(Ndiff)+strDiff + else: + strLog="DIFF:%d:"%(Ndiff)+strDiff + else: + if(len(strErr)>0): + strLog="ERR:%d:"%(Nerr)+strErr + return Ndiff,Nsame,Nerr,strLog +def load_fromfile( proto, fpath, constructors=None, excluding=None, logfile=None): + sbuf=[];n=0 + fdIN=open(fpath,"r") + for line in fdIN: + line=line.strip();le=len(line) + if( le==0 ): + continue + sbuf.append(line); + ## print("#load_fromfile:%03d:"%(n)+line);n+=1 + fdIN.close() + return load_fromlist( proto, sbuf, constructors=constructors, excluding=excluding,logfile=logfile ) + +def load_fromstring( proto, string, delimiter=';', constructors=None): + if( string=="None" ): + return None + + sbuf=( string.split() if( delimiter is None ) else string.split(delimiter) ); + return load_fromlist( proto, sbuf,constructors=constructors) + +def load_fromlist( proto, sBuf, constructors=None, excluding=None, logfile=None, append=False ): + ### print("#load_fromlist:%s:"%(str(type(proto)))+str(sBuf)) + loglevel=1; logfd=sys.stdout + if(logfile is not None): + logfd=open(logfile,('a' if(append) else 'w') );loglevel=2 + Nbuf=len(sBuf) + seqno=1 + for ibuf in range(Nbuf): + line=sBuf[ibuf].strip();le=len(line) + if(le<1): + continue + if( line.startswith('#') ): + Stdlogger.printout(1,"#skipping:"+line);continue + + if(22): + colonAT=[];nC=0;le=len(line) + for j in range(le): + if(line[j]==':'): + colonAT.append(j);nC+=1; + if(nC==2): + break + assert nC==2,"" + strval=line[colonAT[1]+1:] + assert strval.startswith(sarr[2]),"" + + Ty=sarr[1];val=None + if( strval.startswith("!") ): + typ=Ty[0]; + fpath1=strval[1:];get_comments=[] + if(typ=='I' or typ=='D' or typ=='Z'): + val=svld_aNbuf('L',fpath1,get_comments=get_comments); + nd=np.shape(val); + if( len(Ty)>1 ): + sdum=Ty[1:].split(',');n=len(sdum) + Ndim=[ int(sdum[kk]) for kk in range(n) ] + if(not i1eqb(nd,Ndim) ): + val=np.reshape(val,Ndim) + setattr(proto,key,val) + if(10 or nExpo>0): + v1=float(v1) + else: + v1=int(v1) + val.update({ky1:v1}) + setattr(proto,key,val) + if(11 ): + sdum=Ty[1:].split(',');n=len(sdum) + Ndim=[ int(sdum[kk]) for kk in range(n) ] + + if(typ=='i'): + val=int( strval ) + elif(typ=='d'): + val=float( strval ) + elif(typ=='z'): + sdum=strval.split(); + val=float(sdum[0]) + 1j*float(sdum[1]) + elif(typ=='s'): + val=strval; + elif(typ=='b'): + val=eval(strval); + elif(typ=='I'): + sA=strval.split();nA=len(sA) + val=np.reshape( [ int(sA[k]) for k in range(nA) ], Ndim) + elif(typ=='D'): + sA=strval.split();nA=len(sA) + val=np.reshape( [ float(sA[k]) for k in range(nA) ], Ndim) + elif(typ=='Z'): + sA=strval.split();nA1=len(sA);nA=nA1//2; assert (nA1%2==0),"" + val=np.reshape( [ float(sA[2*k]) + 1j*float(sA[2*k+1]) for k in range(nA) ], Ndim) + elif(typ=='S'): + sA=strval.split(); + val=np.reshape(sA, Ndim) + elif(typ=='o'): + if( strval == "None" ): + val=None + else: + assert constructors is not None,"don't know how to create:"+key+":"+typ + assert key in constructors,"no valid constructor for "+key + Stdlogger.printout(1,"#creating:"+key+" from:"+strval) + val=constructors[key](strval) + else: + assert False,"wrong typ:"+typ + + setattr(proto,key,val) + if(11),"slist#%d:%s"%(ith,item) + key=arr[0].strip() + typ=arr[1].strip(); types.update({key:typ}) + if( len(arr)>2 ): + val=arr[2].strip(); values.update({key:val}); + else: + values.update({key:None}); + return types,values +def is_method_or_function(tgt,verbose=False): + if(tgt is None): + if( verbose ): + print("!W is_method:None input.."); + return -1 + strtype=str( type(tgt) ) + + if( "method" in strtype ): + if( strtype.endswith("\'method\'>") ): + return 2 + if( strtype.endswith("\'builtin_function_or_method\'>")): + return 2 + print("check:"+strtype); + print("tgt:"+str(tgt)); + if( strtype.endswith("\'method_descriptor\'>") ): + return 2 + + assert False,"" + return 1 + + if( "function" in strtype ): + if( strtype.endswith("\'function\'>") ): + return 2 + print("Check:"+strtype);assert False,"" + return 1 + return 0 + +def check_serialization(fpath=None,string=None,delimiter=';',Dict=None,check_type=True): + assert (fpath is not None) or (strins is not None),"" + assert (fpath is None) or (strins is None),"" + assert (Dict is not None),"" + types,values=( parse_file(fpath) if (fpath is not None) else + parse_slist(string.split(delimiter))) + + if( check_type ): + assert "type" in types,"" + strtype=types.pop("type") ## str(type) + dum=values.pop("type") ## None + + Ndiff=0;Nsame=0;Nerr=0;strLOG="" + for key in Dict: + if( key in types ): + lhs=Dict[key].split('|') + rhs=types[key]; + if(rhs in lhs): + Nsame+=1 + else: + Ndiff+=1; strLOG+=key+":"+ str(rhs)+ "/"+str(lhs)+";" + else: + Nerr+=1; strLOG+=key+":not in string;" + for key in types: + if( key in Dict ): + continue + else: + Nerr+=1; strLOG+=key+":not in given types;" + return Ndiff,Nsame,Nerr,strLOG + +def read_strtype(string): + string=string.strip(); + if(string.startswith("") ): + string=string.replace("",""); + return string + else: + return None + +def serialize_listedfields(obj,keylist,delimiter="\n"): + ret="";n=0 +# primitive_types=[str,int,float,complex,np.complex128 + str_or_int=[str,int] + floats=[float,np.float64] + complexes=[complex,np.complex128] + for key in keylist: + val=getattr(obj,key,None) + if( val is None ): + ret+=("" if(n==0) else delimiter) +key+":o:None";n+=1 + elif( isinstance(val,bool) ): + ret+=("" if(n==0) else delimiter) +key+":b:%r"%(val);n+=1 + elif( isinstance(val,str) ): + ret+=("" if(n==0) else delimiter) +key+":s:%s"%(val);n+=1 + elif( isinstance(val,int) ): + ret+=("" if(n==0) else delimiter) +key+":i:%d"%(val);n+=1 + elif( isinstance(val,float) or isinstance(val,np.float64) ): + ret+=("" if(n==0) else delimiter) +key+":d:%24.12e"%(val);n+=1 + elif( isinstance(val,float) or isinstance(val,np.complex128) ): + ret+=("" if(n==0) else delimiter) +key+":z:%24.12e %24.12e"%(val.real,val.imag);n+=1 + elif( isinstance(val,dict) ): + if( len(val) == 0 ): + typ='dict';strval="{}" + else: + typ='dict';strval=None + for ky1 in val: + if(strval is None): + strval="{"+ str(ky1).strip() + ","+ str( val[ky1] ).strip() + else: + strval+=","+ str(ky1).strip() + ","+ str( val[ky1] ).strip() + strval+="}" + ret+=("" if(n==0) else delimiter) +key+":dict:%s"%(strval);n+=1 + elif( isinstance(val,list) or isinstance(val,np.ndarray) ): + Ndim=np.shape(val);v1D=np.ravel(val) + le=len(v1D) + if(le==0): + typ="I"+i1toa(Ndim,delimiter=',') + if(isinstance(v1D[0],int)): + typ="I"+i1toa(Ndim,delimiter=',') + strval=iNtoa(v1D,delimiter=" ") + elif(isinstance(v1D[0],str)): + typ="S"+i1toa(Ndim,delimiter=',') + strval=sNtoa(v1D,delimiter=" ") + elif( isinstance(v1D[0],float) or isinstance(v1D[0],np.float64) ): + typ="D"+i1toa(Ndim,delimiter=',') + strval=d1toa(v1D,format="%24.12e",delimiter=" ") + elif( isinstance(v1D[0],complex) or isinstance(v1D[0],np.complex128)): + typ="Z"+i1toa(Ndim,delimiter=',') + strval=z1toa(v1D,format="%24.12e %24.12e",delimiter=" ") + else: + print("OBJ:"+str(type(obj))+" "+str(obj)) + print("KEY:"+str(key)+" "+str(type(val))+" "+str(val)) + print("TYP:"+str(type(v1D[0]))+" "+str(v1D[0])) + typ="o";strval="" + for j in range(le): + strval+=("" if(j==0) else " ") +str(v1D[j]) + ret+=("" if(n==0) else delimiter) +key+":%s:%s"%(typ,strval);n+=1 + return ret +# usually additional_fields[key] looks like i:3776 D3,3:1.192 1.333 1.467 ... +def serialize(obj,fpath=None,delimiter='\n',comment=None,serializers=None,depth=1, + additional_fields=None, fields_excluded=None,verbose=0, strict=True, Threads=[0], return_None=False, Dict=None ): + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + Ld_uplm=100 ## TODO + keys_written_on_file=[] + wt0=time.time() + if( return_None ): + if(fpath is not None): + printout("#serialize:return_None is True but no fpath input...",warning=1) + return_None=False + + if( (MPIsize > 1) and (MPIrank not in Threads) ): + return None + assert obj is not None,"" + header="#%d"%(depth); + for J in range(1,depth): + header+=" " + print("##serialize:main:depth=%d:"%(depth) +str(obj)+":"+str(type(obj)),flush=True) + primitive_types=[ str,int,float,np.float64,complex,np.complex128] + collection_types=[ list,dict,np.ndarray ] + for T in primitive_types: + if( isinstance(obj,T) ): + print("#!W primitive type in serialize method:"+str(obj));return str(obj) + for T in collection_types: + if( isinstance(obj,T) ): + print("#!W collection type in serialize method:"+str(obj));return str(obj) + + + Stdlogger.printout(1,"#Serialize:"+header+str(type(obj))+":"+str(obj) ,verbose=verbose, wt0=wt0,dtme=True) + keylist=dir(obj) + nkey=len(keylist) + Stdlogger.printout(1,"keylist:%d:"%(nkey) +str(keylist), wt0=wt0,dtme=True) + fd=( None if(fpath is None) else open(fpath,"w")) + if(fd is not None): + print("#"+str(datetime.datetime.now()),file=fd) ## FPRINT + if( comment is not None): + print("#"+comment,file=fd) ## FPRINT + ret=None + if( additional_fields is not None): + for key in additional_fields: + sdum=str(key)+":"+str( additional_fields[key]) + if( not return_None): + if( ret is None ): + ret=sdum; ### print("#RET:"+ret) + else: + ret += delimiter+sdum; ### print("#ret:"+ret) + if( fd is not None): + print(sdum, file=fd) ## FPRINT + Nerr=0; + for Iky in range(nkey): + if(verbose>2): + print("#%d:%s"%(Iky,str(ret)),flush=True) + key=keylist[Iky].strip();le=len(key);### print("#Top of the loop:%d:"%(Iky)+key) + + if( fields_excluded is not None): + if(key in fields_excluded): + continue + ###if(Iky==0): + ### Stdlogger.printout(1,"#serialize:"+header+":skipping:0th:"+ key,verbose=verbose); continue + if(key[0]=='_' and key[le-1]=='_'): + Stdlogger.printout(1,"#serialize:"+header+":SKipping:_xxx_"+ key,verbose=verbose, wt0=wt0,dtme=True); continue + if(le>1): + if( key[le-1]=='_' and key[le-2]=='_'): + Stdlogger.printout(1,"#serialize:"+header+":SKipping:Xxx__"+ key,verbose=verbose, wt0=wt0,dtme=True); continue + if(key.startswith("staticfield_")): + Stdlogger.printout(1,"#serialize:"+header+":SKipping:staticfield"+ key,verbose=verbose, wt0=wt0,dtme=True); continue + + val=getattr(obj,key);strval=None + if( val is None ): + ### print("#!W "+key+" val is None"); + if( not return_None): +### ret+=delimiter+key+":o:None"; + if( ret is None): + ret= key+":o:None"; + else: + ret+=delimiter+key+":o:None"; + continue + if( serializers is not None ): + if( key in serializers ): + print("#serializing:key=%s"%(key),flush=True) + typ='o' + strval=serializers[key](val) + if( (strval is None) and is_method_or_function(val)>0 ): + Stdlogger.printout(1," skip method.. KEY=%s VAL=%s"%( str(key),str(val)),verbose=verbose) + continue; + if( strval is None ): + Stdlogger.printout(1,"#serialize:"+header+" key:"+key,verbose=verbose);types=[str,bool,int,float,complex] + if( val is None ): + typ='o';strval="None" + elif( isinstance(val,str) ): + Stdlogger.printout(2,key+":str",verbose=verbose, wt0=wt0,dtme=True) + typ='s';strval=str(val) + elif( isinstance(val,bool) ): ## << check bool first: isinstance( BOOLEAN, int ) returns -True- .. + Stdlogger.printout(2,key+":bool",verbose=verbose, wt0=wt0,dtme=True) + typ='b';strval=str(val) + elif( isinstance(val,int) ): + Stdlogger.printout(2,key+":int",verbose=verbose, wt0=wt0,dtme=True) + typ='i';strval="%d"%(val) + elif( isinstance(val,float) or isinstance(val,np.float64) ): + Stdlogger.printout(2,key+":float",verbose=verbose, wt0=wt0,dtme=True) + typ='d';strval="%24.12e"%(val) + elif( isinstance(val,complex) or isinstance(val,np.complex128) ): + Stdlogger.printout(2,key+":complex",verbose=verbose, wt0=wt0,dtme=True) + typ='z';strval="%24.12e %24.12e"%(val.real, val.imag) + elif( isinstance(val,list) or isinstance(val,np.ndarray) ): + Stdlogger.printout(2,key+":list_or_ndarray:"+str( np.shape(val) ),verbose=verbose) + Ndim=np.shape(val) + a1D =np.ravel( np.array(val) );dty=a1D.dtype + Ld_tot=len(a1D) + if( (Ld_tot > Ld_uplm) and (fpath is not None) ): + fnme=( fpath if(not fpath.endswith(".pscf")) else fpath.replace(".pscf","")) + fpath2=fnme+"_"+str(key)+".xpscf" + if( type(a1D[0])==str or type(a1D[0])==np.str_ ): + typ='S'+iNtoa(Ndim,delimiter=',');strval=sNtoa(val,delimiter=" ") + else: + assert key not in keys_written_on_file,"key:"+key+" is not unique.."+str(keys_written_on_file) + keys_written_on_file.append(key); + if( dty==int ): + typ='I'+iNtoa(Ndim,delimiter=',');strval="!"+fpath2;svld_aNbuf("S",fpath2,buf=val,comment=fpath) + elif( dty==float or dty==np.float64 ): + typ='D'+iNtoa(Ndim,delimiter=',');strval="!"+fpath2;svld_aNbuf("S",fpath2,buf=val,comment=fpath) + elif( dty==complex or dty==np.complex128 ): + typ='Z'+iNtoa(Ndim,delimiter=',');strval="!"+fpath2;svld_aNbuf("S",fpath2,buf=val,comment=fpath) + else: + strval=str(val); + print("#serialize:"+"dty:"+str(dty)+" KEY:"+str(key)+" type:"+str(type(val))) + print("#serialize:"+str(val)) + Stdlogger.printout(1,"#Serialize:"+header+str(type(obj))+":"+str(obj),verbose=verbose) + Stdlogger.printout(1,"key:"+str(key)+" type:"+str(type(val))+" dtype:"+str(np.array(val).dtype)+" val:"+str(val),verbose=verbose) + assert False,"" + elif( len(a1D) == 0 ): + if( isinstance(val,list) ): + typ='I0';strval="" + else: + typ=('I0' if(val.dtype==int) else ('D0' if(val.dtype==float or val.dtype==np.float64) else + ('Z0' if(val.dtype==complex or val.dtype==np.complex128) else 'S0')));strval="" + else: + if( type(a1D[0])==str or type(a1D[0])==np.str_ ): + typ='S'+iNtoa(Ndim,delimiter=',');strval=sNtoa(val,delimiter=" ") + else: + if( dty==int ): + typ='I'+iNtoa(Ndim,delimiter=',');strval=iNtoa(val,delimiter=" ") + elif( dty==float or dty==np.float64 ): + typ='D'+iNtoa(Ndim,delimiter=',');strval=dNtoa(val,format="%24.12e",delimiter=" ") + elif( dty==complex or dty==np.complex128 ): + typ='Z'+iNtoa(Ndim,delimiter=',');strval=zNtoa(val,format="%24.12e %24.12e", delimiter=" ") + ### elif( dty==str ): + ### typ='S'+iNtoa(Ndim,delimiter=',');strval=sNtoa(val,delimiter=" ") + else: + strval=str(val); + print("#serialize:"+"dty:"+str(dty)+" KEY:"+str(key)+" type:"+str(type(val))) + print("#serialize:"+str(val)) + Stdlogger.printout(1,"#Serialize:"+header+str(type(obj))+":"+str(obj),verbose=verbose) + Stdlogger.printout(1,"key:"+str(key)+" type:"+str(type(val))+" dtype:"+str(np.array(val).dtype)+" val:"+str(val),verbose=verbose) + ### assert False,"dty:"+str(dty)+" KEY:"+str(key)+" type:"+str(type(val)) + elif( isinstance(val,dict) ): + if( len(val) == 0 ): + typ='dict';strval="{}" + else: + typ='dict';strval=None + for ky in val: + if(strval is None): + strval="{"+ str(ky).strip() + ","+ str( val[ky] ).strip() + else: + strval+=","+ str(ky).strip() + ","+ str( val[ky] ).strip() + strval+="}" + else: + assert key is not None,"key" + assert val is not None,"val" + Stdlogger.printout(1,"Key:"+key+":o:"+str(val)+ "...serializing object..",verbose=verbose) + if(verbose>1): + print("###serialize:main:depth=%d:invoking serialize:Key=%s val=%s type=%s"%(depth,str(key),str(val),str(type(val))),flush=True) + typ='o';strval=serialize(val, delimiter=';', depth=depth+1); + if( strval is None ): + strval=""; print("!W serialize:"+key+":"+str(val)+" returns None") + ##if(not strict): + ## Nerr=Nerr+1 + ##else: + ## assert strval is not None,"serialize:"+str(val)+" Key:"+str(key) + strval=strval.strip() + if( len(strval)==0 ): + strval="type:"+str(type(val)) + else: + strval="type:"+str(type(val))+";"+strval + + sdum=key+":"+typ+":"+strval + if( fd is not None): + print(sdum, file=fd) + if( not return_None): + if( ret is None): + ret= sdum; ### print("#Ret:"+ret) + else: + ret += delimiter + sdum; ### print("#ret:"+ret) + print("#serialize:those written on external file:"+str(keys_written_on_file)) + assert Nerr==0,"Nerr:%d"%(Nerr) + return ret + +## Ndiff,Nsame,Nerr +def diff_objects(lhs,rhs,verbose=0,diff_TOL=1.0e-7,dict_logs=None,keylist=None): ## returns Ndiff,Nsame,Nerr + if( isinstance(lhs,bool) or isinstance(lhs,int) or isinstance(lhs,str) ): + if( lhs==rhs ): + return 0,1,0; + else: + return 1,0,0; + if( isinstance(lhs,float) or isinstance(lhs,np.float64) + or isinstance(lhs,np.complex128) or isinstance(lhs,complex) ): + if( abs(lhs-rhs) 1 and abs(lhs-rhs)/scale < diff_TOL ): + Stdlogger.printout(1, "#OK: %s / %s diff:%f/%f= %e < TOL"%(str(lhs),str(rhs),abs(lhs-rhs),scale,abs(lhs-rhs)/scale)) + return 0,1,0 + Stdlogger.printout(1, "#DIFF: %s / %s diff:%f/%f= %e > TOL"%(str(lhs),str(rhs),abs(lhs-rhs),scale,abs(lhs-rhs)/scale)) + return 1,0,0; + if(keylist is None): + keylist=set_intersection( dir(lhs), dir(rhs),verbose=1) + keylistR=dir(rhs) + nkey=len(keylist) + if( dict_logs is None ): + dict_logs={} + Nsame=0;Ndiff=0;Nerr=0; + dict_logs.update({"diff":"","err":"","warning":""}) + nWarn=0 + for Iky in range(nkey): + + key=keylist[Iky].strip();le=len(key) + ## if(Iky==0): + ## if(verbose>0): + ## print("#compare_objects:skipping_0th:"+ key); + ## continue + if(key[0]=='_' and key[le-1]=='_'): + Stdlogger.printout(2,"#compare_objects:skipping:"+ key,verbose=verbose); + continue + lh=getattr(lhs,key,None);rh=getattr(rhs,key,None) + if( (lh is None) or (rh is None) ): + if( (lh is None) and (rh is None) ): + Nsame+=1;continue + else: + Nerr+=1;continue + + ismL=is_method_or_function(lh);ismR=is_method_or_function(rh) + if( ismL or ismR ): + if( ismL and ismR ): + continue + else: + Nerr+=1;continue + if( key in keylistR ): + if( key == "bit_length" ): + print(str(type(lhs))+" has field:"+key+":"+str(getattr(lhs,key))) ## ERROR + print(str(type(rhs))+" has field:"+key+":"+str(getattr(rhs,key))) ## ERROR + assert False,"" + if( isinstance(lh,dict) ): + if( not isinstance(rh,dict)): + Nerr+=1;dict_logs["err"]+="#%d:%s lh:%s rh:%s"%(Nerr,key,str(type(lh)),str(type(rh))) + else: + nd1,ns1,ne1,strlog1=diff_dict(lh,rh,verbose=0) + if( ne1>0 ): + Nerr+=1; dict_logs["err"]+="#%d:%s lh:%s rh:%s diff:%d,%d,%s"%(Nerr,key,str(lh),str(rh),nd1,ns1,ne1,strlog1) + elif(nd1>0): + Ndiff+=1; dict_logs["diff"]+="#%d:%s lh:%s rh:%s diff:%d,%d,%s"%(Nerr,key,str(lh),str(rh),nd1,ns1,ne1,strlog1) + elif(ns1>0): + Nsame+=1 + else: + dict_logs["err"]+="###:%s lh:%s rh:%s diff fails:%d,%d,%d,%s"%(key,str(lh),str(rh),nd1,ns1,ne1,strlog1) + continue + elif( isinstance(lh,str)): + if( isinstance(rh,str)): + if(lh == rh ): + Nsame+=1 + else: + Ndiff+=1; dict_logs["diff"]+="#%d:%s: %s / %s"%(Ndiff,key,str(lh),str(rh)) + else: + Nerr+=1; dict_logs["err"]+="#%d:%s: %s / %s"%(Nerr,key,str(lh),str(rh)) + elif( isinstance(lh,float) or isinstance(lh, np.float64) or + isinstance(lh,complex) or isinstance(lh, np.complex128) ): + if( abs(lh-rh)< diff_TOL ): + Nsame+=1 + else: + scale=0.50*( abs(lh) + abs(rh) ) + if( scale>1 and abs(lh-rh)/scale < diff_TOL ): + Nsame+=1 + else: + Ndiff+=1; dict_logs["diff"]+="#%d:%s: %s / %s"%(Ndiff,key,str(lh),str(rh)) + elif( isinstance(lh,list) or isinstance(lh,np.ndarray) ): + lh=np.ravel(lh);rh=np.ravel(rh) + nlh=len(lh);nrh=len(rh); + if(nlh==nrh): + jdiff=None + for j in range(nlh): + if( isinstance(lh[j],str) or isinstance(lh[j],int) ): + if( lh[j]==rh[j] ): + continue + else: + jdiff=j;break + elif( isinstance(lh[j],float) or isinstance(lh[j],np.float64) or + isinstance(lh[j],complex) or isinstance(lh[j],np.complex128) ): + df=abs( lh[j]-rh[j] ); + if( df< diff_TOL ): + continue; + else: + scale=0.50*( abs(lh[j]) + abs(rh[j]) ) + if( scale > 1.0 and abs(lh[j]-rh[j])/scale < diff_TOL): + continue + else: + jdiff=j;break + else: + if(nWarn<5): + strWarn="#!W diff_objects:lh:%s %s rh:%s %s"%( str(type(lh)),str(lh),str(type(rh)),str(rh) ) + Stdlogger.printout(0,strWarn); + dict_logs["warning"]+=strWarn; nWarn+=1 + + nd2,ns2,ne2=diff_objects(lh,rh,verbose=0) + if(ne2>0 or nd2>0): + jdiff=j;break + if(jdiff is None): + Nsame+=1 + else: + Ndiff+=1; dict_logs["diff"]+="#%d:%s[%d]: %s / %s"%( Ndiff,key,jdiff,str(lh[jdiff]),str(rh[jdiff]) ) + else: + Nerr+=1; dict_logs["err"]+="#%d:%s: len %d / %d"%(Nerr,key,nlh,nrh) + else: + # --- comp btw. objects --- + ### print("#check:%s:"%(key),end="");print(type(lh),end=" ");print(type(rh)) + ### print("#check:%s:"%(key),end="");print(lh,end=" ");print(rh) + if( lh is None or rh is None): + if( (rh is None) and (lh is None)): + Nsame+=1 + else: + Ndiff+=1; dict_logs["diff"]+="#%d:%s: %s / %s"%( Ndiff,key,str(lh),str(rh) ) + else: + nD,nS,nE=diff_objects(lh,rh,verbose=verbose,diff_TOL=diff_TOL) + if(nE>0): + Nerr+=1; err+="#%d:%s: %s / %s Ndiff:%d Nsame:%d Nerr:%d"%(Nerr,key,str(lh),str(rh),nD,nS,nE); + else: + if(nD>0): + Ndiff+=1; dict_logs["diff"]+="#%d:%s: %s / %s %d %d %d"%( Ndiff,key,str(lh),str(rh),nD,nS,nE ) + else: + Stdlogger.printout(1,"#diff:%s:"%(str(type(lhs))) + key+":"+str(lh)+"/"+str(rh)+" returns:%d,%d,%d"%(nD,nS,nE)) + Nsame+=1; assert nS>0,"" + return Ndiff,Nsame,Nerr + +## BELOW WE DEFINE CONSTRUCTORS ... +## +## constructors have to create objects from string input. +## usually you need to create default object and --load-- properties on it.. +## +def construct_tdfield(string, delimiter=';'): + if( string=="None" ): + return None + retv=None + sbuf=string.split(delimiter) + col0=sbuf.pop(0) + sarr=col0.split(':'); + key=sarr[0].strip() + assert (key=="type"),"" + strtype=sarr[1].strip(); + dum=read_strtype(strtype) + if( dum is not None): + strtype=dum + if( "CWField01" in strtype ): + e0=0.0; omega=1.0; ts=0.0 # 2021.06.07 dummy_omega = 1.0 + retv=CWField01(e0, omega, ts); ### CWfield(e0, omega, ts) + elif( "gaussianpulse01" in strtype ): + freq_eV=1.0e-5; peakIntensity_WpeCM2=0.0 + retv=gaussianpulse01(freq_eV, peakIntensity_WpeCM2,fwhm_as=1.0) + elif( "kickfield" in strtype ): + ElectricfieldVector=[0.0, 0.0, 0.0]; tmKick_AU=0.0; + retv=kickfield( ElectricfieldVector,tmKick_AU=tmKick_AU) + elif( "Trapezoidalpulse" in strtype ): + freq_eV=1.0e-5; peakIntensity_WpeCM2=0.0 + retv=Trapezoidalpulse( freq_eV, peakIntensity_WpeCM2,tAsc_fs=1.0,tFlat_fs=1.0,tDsc_fs=1.0,tc_fs=1.5) + else: + assert False,"strtype:"+strtype + + retv = load_fromlist(retv, sbuf) + comm=MPI.COMM_WORLD; MPIrank=comm.Get_rank(); MPIsize=comm.Get_size() + if( MPIsize<2 or MPIrank==0 ): + logf="serialize_py_construct_tdfield.log" + fd1=open(logf,"a"); + print("#construct_tdfield:"+str(rttddft_common.get_job(True))+" \t\t"+str( datetime.datetime.now() ),file=fd1) + print(retv.tostring(),file=fd1) + retv.printout_tdfields( 0.0, 24.0, 0.008, logf,Append=True,Threads=[0]) + ### print("Field:"+retv.tostring()); + ### assert False,"" + return retv; +def serialize_tdfield(this,delimiter=';'): + if( this is None ): + return "None" + ret="type:"+str(type(this))+delimiter+serialize(this,delimiter=delimiter) + return ret + #if( isinstance(this,CWField01) ): + # ret += delimiter+"e0:%24.12e"%(this.e0) +delimiter+"omega:%24.12e"%(this.omega) + # + delimiter+"ts:%24.12e"%(this.ts) + #elif( isinstance(this, gaussianpulse01) ): + # + # ret += delimiter+"omega:%24.12e"%(this.omega) +delimiter+" + +def i1prod(ibuf): + buf=np.ravel(ibuf) + le=len(buf) + if(le<1): + return 0; + ret=buf[0]; + for j in range(1,le): + ret*=buf[j] + return ret; + +def a1_to_a(buf,delimiter=","): + if( isinstance(buf,np.ndarray) ): + dtype=buf.dtype; + elif( isinstance(buf,list) and len(buf)>0 ): + dtype=np.array( buf[0] ).dtype + else: + dtype=np.complex128 + + if(dtype==int or dtype==np.int64): + return i1_to_a(buf,delimiter=delimiter) + elif(dtype==float or dtype==np.float64): + return d1_to_a(buf,delimiter=delimiter) + elif(dtype==complex or dtype==np.complex128): + return z1_to_a(buf,delimiter=delimiter) + else: + assert False,""+str(dtype) +def i1_to_a(ibuf,format="%d",delimiter=","): + buf=np.ravel(ibuf) + le=len(buf) + sbuf=[ format%(buf[j]) for j in range(le) ] + return delimiter.join(sbuf) +# ret="";dlmt="" +# for j in range(le): +# ret+=dlmt+format%(buf[j]);dlmt=delimiter +# return ret +def d1_to_a(dbuf,format="%24.8e",delimiter=","): + buf=np.ravel(dbuf) + le=len(buf) + sbuf=[ format%(buf[j]) for j in range(le) ] + return delimiter.join(sbuf) +# ret="";dlmt="" +# for j in range(le): +# ret+=dlmt+format%(buf[j]);dlmt=delimiter +# return ret + +def z1_to_a(zbuf,format="%24.8e,%24.8e",delimiter=", "): + buf=np.ravel(zbuf) + le=len(buf) + sbuf=[ format%(buf[j].real, buf[j].imag) for j in range(le) ] + return delimiter.join(sbuf) +# ret="";dlmt="" +# for j in range(le): +# ret+=dlmt+format%( buf[j].real, buf[j].imag );dlmt=delimiter +# return ret + +def prtI1(fd,ibuf,format="%d",delimiter=",",ncol=6): + buf=np.ravel(ibuf) + le=len(buf) + ret="";dlmt="" + nrow=(le+ncol-1)//ncol; + ixj=0 + for i in range(nrow): + ret="";dlmt="" + nc=min(ncol,(le-ixj)) + sbuf=[ format%( buf[ixj+k] ) for k in range(nc)] + print( delimiter.join(sbuf),file=fd ) + ixj+=nc + ## for j in range(nc): + ## ret+=dlmt+format%(buf[ixj]); ixj+=1; dlmt=delimiter + ## print(ret,file=fd); + assert ixj==le,"" + +def prtD1(fd,dbuf,format="%24.8e",delimiter=",",ncol=6): + buf=np.ravel(dbuf) + le=len(buf) + ret="";dlmt="" + nrow=(le+ncol-1)//ncol; + ixj=0 + for i in range(nrow): + ret="";dlmt="" + nc=min(ncol,(le-ixj)) + sbuf=[ format%( buf[ixj+k] ) for k in range(nc)] + print( delimiter.join(sbuf),file=fd ) + ixj+=nc + assert ixj==le,"" +## for j in range(nc): +## ret+=dlmt+format%(buf[ixj]); ixj+=1; dlmt=delimiter +## print(ret,file=fd); + +def prtZ1(fd,zbuf,format="%24.8e,%24.8e",delimiter=", ",ncol=4): + # print(np.shape(zbuf)) + buf=np.ravel(zbuf) + le=len(buf) + # print(np.shape(buf),le) + ret="";dlmt="" + nrow=(le+ncol-1)//ncol; + ixj=0 + for i in range(nrow): + ret="";dlmt="" + nc=min(ncol,(le-ixj)) + sbuf=[ format%( buf[ixj+k].real, buf[ixj+k].imag ) for k in range(nc) ] + print( delimiter.join(sbuf),file=fd ) + ixj+=nc + assert ixj==le,"" +## for j in range(nc): +## ret+=dlmt+format%( buf[ixj].real, buf[ixj].imag ); ixj+=1; dlmt=delimiter +## print(ret,file=fd); + +def svld_aNbuf(SorL,path,buf=None,comment=None,get_comments=None): + STRdtype=None;dtype=None + if(SorL=='S'): + if( isinstance(buf,np.ndarray) ): + dtype=buf.dtype; + elif( isinstance(buf,list) and len(buf)>0 ): + dtype=np.array( buf[0] ).dtype + else: + dtype=np.complex128 + + STRdtype=( "I" if(dtype==int or dtype==np.int64) else \ + ( "D" if(dtype==float or dtype==np.float64) else \ + ( "Z" if(dtype==complex or dtype==np.complex128) else None ))) + assert STRdtype is not None,"dtype:"+str(dtype) + + Ndim=np.shape(buf) + fd=open(path,'w') + if( comment is not None ): + print("#%s"%(comment),file=fd); + print("%s:%s"%(STRdtype,i1_to_a(Ndim)),file=fd) + if(dtype==int or dtype==np.int64): + prtI1(fd,buf) + elif(dtype==float or dtype==np.float64): + prtD1(fd,buf) + elif(dtype==complex or dtype==np.complex128): + prtZ1(fd,buf) + fd.close() + else: + fd=open(path,'r') + STRdtype=None;ret=None + Ngot=0; + for line in fd: + if( line[0]=='#'): + if( get_comments is not None ): + get_comments.append(line) + print("reading off:"+line);continue + if( STRdtype is None ): + sA=line.split(":") + STRdtype=sA[0]; + dtype=(np.int64 if(STRdtype=='I') else \ + (np.float64 if(STRdtype=='D') else \ + (np.complex128 if(STRdtype=='Z') else None))); assert dtype is not None,""+STRdtype + + sub=sA[1].split(',');n1=len(sub) + Ndim=[ int(sub[j]) for j in range(n1) ] + Ldim=i1prod(Ndim) + if( STRdtype == 'Z' ): + ret=np.zeros([2*Ldim],dtype=np.float64) + else: + ret=np.zeros([Ldim],dtype=dtype) + continue + sA=line.split(',');nA=len(sA) + if(STRdtype=='I'): + for j in range(nA): + ret[Ngot+j]=int(sA[j]) + Ngot+=nA; + elif(STRdtype=='D'): + for j in range(nA): + ret[Ngot+j]=np.float64(sA[j]) + Ngot+=nA; + elif(STRdtype=='Z'): + for j in range(nA): + ret[Ngot+j]=np.float64(sA[j]) + Ngot+=nA; + fd.close() + if( STRdtype=='Z' ): + assert Ngot==2*Ldim,"read:%d/2*Ldim:%d"%(Ngot,2*Ldim) + wks=np.zeros([Ldim],dtype=dtype) + for j in range(Ldim): + wks[j]= ret[2*j] + 1j*ret[2*j+1] + ret=wks + else: + assert Ngot==Ldim,"read:%d/Ldim:%d"%(Ngot,Ldim) + + return np.reshape(ret,Ndim) + +def i1eqb(lhs,rhs): + if(len(lhs)!=len(rhs)): + return False + le=len(lhs) + for j in range(le): + if(lhs[j]!=rhs[j]): + return False + return True +def diff_aNbuf(lhs,rhs,diff_thr=1.0e-6,label=None,fpath=None): + Ndim=np.shape(lhs) + Ndim_R=np.shape(rhs) + lh=lhs;rh=rhs + if( not i1eqb(Ndim,Ndim_R) ): + rh=np.reshape(rhs,Ndim) + rank=len(Ndim) + if(rank>4): + Ndim_2=[-1,Ndim[rank-3],Ndim[rank-2],Ndim[rank-1]] + lh=np.reshape(lhs,Ndim_2) + rh=np.reshape(rhs,Ndim_2) + Ndim=Ndim_2 + fd=sys.stdout + if(fpath is not None): + fd=open(fpath,"w") + + diff=aNmaxdiff(lhs,rhs) + if( label is not None ): + print("#diff_aNbuf:%s:diff=%e"%(label,diff), file=fd); + if( diff < diff_thr ): + return diff + if(rank<2): + print("#: %e\n<%s\n>%s"%(I, a1_to_a(lhs),a1_to_a(rhs)), file=fd) + return diff + for I in range(Ndim[0]): + if(rank<3): + dum=aNmaxdiff(lhs[I],rhs[I]) + if(dum>diff_thr): + print("#%d: %e\n<%s\n>%s"%(I,dum, a1_to_a(lhs[I]),a1_to_a(rhs[I])), file=fd) + continue + for J in range(Ndim[1]): + if(rank<4): + dum=aNmaxdiff(lhs[I][J],rhs[I][J]) + if(dum>diff_thr): + print("#%d,%d: %e\n<%s\n>%s"%(I,J,dum, a1_to_a(lhs[I][J]),a1_to_a(rhs[I][J])), file=fd) + continue + + for K in range(Ndim[2]): + dum=aNmaxdiff(lhs[I][J][K],rhs[I][J][K]) + if(dum>diff_thr): + print("#%d,%d,%d: %e\n<%s\n>%s"%(I,J,K,dum, a1_to_a(lhs[I][J][K]),a1_to_a(rhs[I][J][K])), file=fd) + if(fpath is not None): + fd.close() + os.system("ls -ltrh "+fpath) + return diff diff --git a/pyscf/rttddft/test_mol_or_cell.py b/pyscf/rttddft/test_mol_or_cell.py new file mode 100644 index 000000000..ffa3c464a --- /dev/null +++ b/pyscf/rttddft/test_mol_or_cell.py @@ -0,0 +1,157 @@ +import numpy as np +from pyscf import gto +from pyscf.gto import Mole +from pyscf.pbc import gto as pbc_gto +from pyscf.pbc.gto import Cell +from .physicalconstants import PhysicalConstants +# Alternative for read_xyzf +# +# !! in read_xyzf, -outputunit- was implicit (defaulted to ANGS, since xyzf is in ANGS unit) +# !! whereas in this subroutine, you MUST explicitly specify A or B. +# +# !! outputunit (A or B) also applies to lattice vectors +# +def read_mol_or_cell(mol_or_cell,dict=None,outputunit=None): + assert (outputunit=='A' or outputunit=='B'), "PLS specify outputunit" + spdm=3 + natm=mol_or_cell.natm + BOHRinANGS=PhysicalConstants.BOHRinANGS() + if(isinstance(mol_or_cell,Cell)): + # + latticevectors_BOHR = np.array( mol_or_cell.lattice_vectors() ) + # print("latticevectors_BOHR",latticevectors_BOHR) + if( outputunit == 'A' ): + dict.update({'a':latticevectors_BOHR*BOHRinANGS}) + else: + dict.update({'a':latticevectors_BOHR}) +# We assume that _atom = [ row_1, row_2, ... ,row_nAtm ] + assert len(mol_or_cell._atom)==natm,"unexpected size of mol_or_cell._atom" + Sy=[];Rnuc_BOHR=[] + for ia in range(natm): + row=mol_or_cell._atom[ia] + s=row[0]; + assert isinstance(s,str),"" + Sy.append(s) + xyz=row[1] + assert len(xyz)==spdm,"" + assert isinstance(xyz[0],float) or isinstance(xyz[0],np.float64),"" + Rnuc_BOHR.append(xyz) + if(outputunit=='A'): + Rnuc_ANGS=np.array(Rnuc_BOHR)*BOHRinANGS + return Rnuc_ANGS,Sy + else: + return Rnuc_BOHR,Sy + +mol_H2O = gto.Mole() +mol_H2O.atom = '''O 0 0 0; H 0 1 0; H 0 0 1''' +mol_H2O.basis = 'sto-3g' +mol_H2O.build() + +mol_CH4 = gto.M(atom = 'C -0.00002631 0.00024432 0.00007638;'\ ++'H 1.09719302 -0.00099542 -0.00067323;'\ ++'H -0.36460184 1.03512412 0.00149901;'\ ++'H -0.36573517 -0.51759524 0.89561804;'\ ++'H -0.36696120 -0.51556008 -0.89613718', basis="aug-ccpvTz") + + +cell_C2 = pbc_gto.M( + atom = '''C 0.0000 0.0000 0.0000 + C 0.8917 0.8917 0.8917''', + a = '''0.0000 1.7834 1.7834 + 1.7834 0.0000 1.7834 + 1.7834 1.7834 0.0000''', + pseudo = 'gth-pade', + basis = 'gth-szv' +) +cell_C8 = pbc_gto.M( + verbose = 4, + a = np.eye(3)*3.5668, + atom = '''C 0. 0. 0. + C 0.8917 0.8917 0.8917 + C 1.7834 1.7834 0. + C 2.6751 2.6751 0.8917 + C 1.7834 0. 1.7834 + C 2.6751 0.8917 2.6751 + C 0. 1.7834 1.7834 + C 0.8917 2.6751 2.6751''', + basis = 'sto3g', +) + +for m_or_c in [mol_H2O, mol_CH4, cell_C2, cell_C8]: + Dic={} + #R,Sy=read_mol_or_cell(m_or_c,dict=Dic,outputunit='B') + R,Sy=read_mol_or_cell(m_or_c,dict=Dic,outputunit='A') + print(m_or_c.atom_symbol(0)) + print("Rnuc:",str(R)) + print("Sy:",str(Sy)) + gbs=m_or_c.basis + print("gbs:",str(gbs)) + if( isinstance(m_or_c,Cell) ): + print("a:",str(Dic['a'])) + psp=m_or_c.pseudo + print("psp:",str(psp)) + +# O +# Rnuc: [[0.0, 0.0, 0.0], [0.0, 1.8897261245650618, 0.0], [0.0, 0.0, 1.8897261245650618]] +# Sy: ['O', 'H', 'H'] +# gbs: sto-3g +# C +# Rnuc: [[-4.971869433730678e-05, 0.00046169788675373593, 0.00014433728139427943], [2.073394313584436, -0.0018810711789145537, -0.0012722203188409366], [-0.6889976221124907, 1.95610109173142, 0.0028327183579842734], [-0.691139305421244, -0.9781132469785231, 1.6924728078197566], [-0.6934561663417446, -0.9742673519588532, -1.6934538402400632]] +# Sy: ['C', 'H', 'H', 'H', 'H'] +# gbs: aug-ccpvTz +# C +# Rnuc: [[0.0, 0.0, 0.0], [1.6850687852746657, 1.6850687852746657, 1.6850687852746657]] +# Sy: ['C', 'C'] +# gbs: gth-szv +# a: [[0. 3.37013757 3.37013757] +# [3.37013757 0. 3.37013757] +# [3.37013757 3.37013757 0. ]] +# psp: gth-pade +# C +# Rnuc: [[0.0, 0.0, 0.0], [1.6850687852746657, 1.6850687852746657, 1.6850687852746657], [3.3701375705493315, 3.3701375705493315, 0.0], [5.055206355823997, 5.055206355823997, 1.6850687852746657], [3.3701375705493315, 0.0, 3.3701375705493315], [5.055206355823997, 1.6850687852746657, 5.055206355823997], [0.0, 3.3701375705493315, 3.3701375705493315], [1.6850687852746657, 5.055206355823997, 5.055206355823997]] +# Sy: ['C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'] +# gbs: sto3g +# a: [[6.74027514 0. 0. ] +# [0. 6.74027514 0. ] +# [0. 0. 6.74027514]] +# psp: None + +# +# O +# Rnuc: [[0. 0. 0.] +# [0. 1. 0.] +# [0. 0. 1.]] +# Sy: ['O', 'H', 'H'] +# gbs: sto-3g +# C +# Rnuc: [[-2.63100000e-05 2.44320000e-04 7.63799999e-05] +# [ 1.09719302e+00 -9.95419999e-04 -6.73230000e-04] +# [-3.64601840e-01 1.03512412e+00 1.49901000e-03] +# [-3.65735170e-01 -5.17595240e-01 8.95618039e-01] +# [-3.66961200e-01 -5.15560080e-01 -8.96137179e-01]] +# Sy: ['C', 'H', 'H', 'H', 'H'] +# gbs: aug-ccpvTz +# C +# Rnuc: [[0. 0. 0. ] +# [0.8917 0.8917 0.8917]] +# Sy: ['C', 'C'] +# gbs: gth-szv +# a: [[0. 1.7834 1.7834] +# [1.7834 0. 1.7834] +# [1.7834 1.7834 0. ]] +# psp: gth-pade +# C +# Rnuc: [[0. 0. 0. ] +# [0.8917 0.8917 0.8917] +# [1.7834 1.7834 0. ] +# [2.6751 2.6751 0.8917] +# [1.7834 0. 1.7834] +# [2.6751 0.8917 2.6751] +# [0. 1.7834 1.7834] +# [0.8917 2.6751 2.6751]] +# Sy: ['C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'] +# gbs: sto3g +# a: [[3.5668 0. 0. ] +# [0. 3.5668 0. ] +# [0. 0. 3.5668]] +# psp: None diff --git a/pyscf/rttddft/update_dict.py b/pyscf/rttddft/update_dict.py new file mode 100644 index 000000000..3a503b411 --- /dev/null +++ b/pyscf/rttddft/update_dict.py @@ -0,0 +1,119 @@ +import numpy as np +import math +import os +import os.path +import sys +import time +import datetime +from .Loglv import Loglv,printout +from mpi4py import MPI +''' +from .update_dict import printout_dict,update_dict +from .pyscf_common import pyscf_common + +fncnme='get_j_kpts';depth=2 ## depth ~ SCF:0 vhf:1 get_j:2 +wct000=time.time();wct010=wct000;dic1={} +Dic=pyscf_common.Dict_getv('timing_'+fncnme, default=None) +if( Dic is None ): + pyscf_common.Dict_setv('timing_'+fncnme, {}); + Dic=pyscf_common.Dict_getv('timing_'+fncnme, default=None) + +wct020=wct010;wct010=time.time() +update_dict(fncnme,dic1,Dic,"setup",wct010-wct020,depth=depth) +... +printout_dict(fncnme,dic1,Dic,wct010-wct000,depth=depth) + + +''' +def update_dict_(dic1,Dic,key,val,append=False,iverbose=1,depth=0): + + if(not append): + dic1.update({key:{'sum':val,'sqrsum':val**2,'count':1}}) + else: + if( key not in dic1 ): + dic1.update({key:{'sum':val,'sqrsum':val**2,'count':1}}) + else: + dic1[key]['sum']+=val + dic1[key]['sqrsum']+=val**2 + dic1[key]['sum']+=val + + if( key not in Dic ): + Dic.update({key:{"sum":0.0,"sqrsum":0.0,"count":0}}) + + Dic[key]['sum']+=val + Dic[key]['sqrsum']+=val**2 + Dic[key]['count']+=1 + return Dic[key]['count'] + +def avg_dict_(dic,key): + if( key not in dic ): + return 0.0,0.0,0 + ### print("#avg_dict_:"+key+str(dic[key])) + if( dic[key]['count']==0 ): + return 0.0,0.0,0 + else: + av=dic[key]['sum']/dic[key]['count'] + stdv=np.sqrt( abs( dic[key]['sqrsum']/dic[key]['count'] - av**2 )) + return av,stdv,dic[key]['count'] + +def suppress_prtout(): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank(); + return ( MPIrank!=0 ) + +def update_dict(fnc,dic1,Dic,key,val,append=False,iverbose=1,redundancy=None,depth=0): + from mpi4py import MPI + comm = MPI.COMM_WORLD; rank = comm.Get_rank() + Key=fnc+'.'+key + update_dict_(dic1,Dic,Key,val,append=append,iverbose=iverbose,depth=depth) + loglv=Loglv.loglv('timing') + if( redundancy is None ): redundancy=1; + prtout=(redundancy<(loglv+iverbose-1)) + if( Dic[Key]['count'] == 1 ): + prtout=(redundancy<(loglv+iverbose)) + prtout=( prtout and ( not suppress_prtout() ) ) + + if( prtout ): + string=' '*depth + "#%03d:%s.%s:%14.4f"%(rank,fnc,key,val) + fdF=open('walltime_%03d.log'%(rank),'a') + av,stdv,count=avg_dict_(Dic,Key) + string+=" \t\t\t %14.4f %12.2e %3d"%(av,stdv,count) + for fd in [ fdF, sys.stdout ]: + print(string,file=fd) + fdF.close() + return Dic[Key]['count'] + +def printout_dict(fnc,dic1,Dic,val,depth=0,force=False,redundancy=1): + from mpi4py import MPI + comm = MPI.COMM_WORLD; rank = comm.Get_rank() + n=update_dict_(dic1,Dic,fnc,val,iverbose=0,depth=depth) + + loglv=Loglv.loglv('timing') + prtout=(redundancy < loglv ) + if( n==1 or n==2 or n==10): + prtout=(redundancy < loglv+1 ) + + prtout=( prtout and ( not suppress_prtout() ) ) + if(force): + prtout=True + # fd1=open("prtout_dict.log","a") + # print("%s %d %d %d %r %f"%(fnc,n,redundancy,loglv,prtout,val),file=fd1); + # fd1.close() + if( not prtout ): + return n + + nth=Dic[fnc]['count'] + string=' '*depth + "#%03d:%s:%4d %14.4f"%(rank,fnc,nth,val) + cum=0.0 + str1="" + for Ky in dic1: + ky=Ky.replace(fnc+".","") + if(ky==fnc): + continue + str1+="%s:%12.4f "%(ky,dic1[Ky]['sum']) + string+='{'+str1+'}' + fdF=open('walltime_%03d.dat'%(rank),'a') + for fd in [ fdF, sys.stdout ]: + print(string,file=fd) + fdF.close() + return n diff --git a/pyscf/rttddft/utils.py b/pyscf/rttddft/utils.py new file mode 100644 index 000000000..a9fa1c08b --- /dev/null +++ b/pyscf/rttddft/utils.py @@ -0,0 +1,2772 @@ +import numpy as np +import math +import os +import os.path +import sys +import time +from .futils import futils +import scipy +import scipy.linalg +import datetime +from mpi4py import MPI +from .physicalconstants import PhysicalConstants + +class utils_static_: + counter_={} + keys_write_once_=[] + @staticmethod + def Countup(key,inc=True): + if( key not in utils_static_.counter_ ): + utils_static_.counter_.update({key:0}) + if(inc): + utils_static_.counter_[key]+=1 + return utils_static_.counter_[key] + +def write_once(key,text,fnme_format=None,fpath=None,Threads=None,Append=False,stdout=False,dtme=True): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank(); MPIsize=comm.Get_size() + if( Threads is None ): + Threads = ( [0] if(fpath is not None) else \ + ( range(MPIsize) if( fnme_format is not None ) else [0] )) + elif( isinstance(Threads,str) ): + if( Threads.strip()=='all' ): + Threads= range(MPIsize) + if( MPIrank not in Threads ): + return + if( key in utils_static_.keys_write_once_ ): + return + utils_static_.keys_write_once_.append(key) + fdA=[];fdOU=None;path=None + if( fpath is None ): + if( fnme_format is None): + fdA.append(sys.stdout) + else: + path=fnme_format%(MPIrank) + else: + path=fpath + if(path is not None): + fdOU=open(fpath,('a' if(Append) else 'w'));fdA.append(fdOU) + if( stdout ): + fdA.append(sys.stdout) + if(dtme): + text+=' \t\t'+str(datetime.datetime.now()) + + for fd in fdA: + print("#write_once:"+str(key)+":"+text,file=fd); + if( fdOU is not None ): + fdOU.close() + +def i1prod(A): + le=len(A) + ret=1 + for j in range(le): + ret*=A[j] + return ret +def prtout_MOocc(fnme, mf,pbc,spinrestriction,Threads=[0]): +## RKS ROKS UKS +## mo_occ [nMO] [2,nMO] [2,nMO] +## KRKS +## mo_occ [nKPT,nMO] [2,nKPT,nMO] [2,nKPT,nMO] + + from mpi4py import MPI + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank();MPIsize=comm.Get_size() + if( MPIsize>0 and (MPIrank not in Threads) ): + return +# print("prtout_MOocc:"+str(type(mf.mo_occ))) # +# print("prtout_MOocc:"+str(len(mf.mo_occ))) +# print("prtout_MOocc:"+str(np.shape(mf.mo_occ[0]))) + + + MO_occ=np.array( mf.mo_occ ); + Ndim=np.shape(MO_occ);leNdim=len(Ndim) + if(pbc): + assert( (spinrestriction=='R' and leNdim==2) or + (spinrestriction!='R' and leNdim==3) ),""; + else: + assert( (spinrestriction=='R' and leNdim==1) or + (spinrestriction!='R' and leNdim==2) ),""; + + nmult_OCC=(1 if(spinrestriction=='R') else 2) + for sp in range(nmult_OCC): + Occ=( MO_occ if(nmult_OCC==1) else MO_occ[sp]) + fd=open( (fnme if(nmult_OCC==1) else fnme.replace(".dat","")+"_upSpin.dat"),"w") + nKpt=(1 if(not pbc) else (Ndim[0] if(spinrestriction=='R') else Ndim[1]) ); + nMO =( (Ndim[0] if(nmult_OCC==1) else Ndim[1]) if(not pbc) else \ + (Ndim[1] if(spinrestriction=='R') else Ndim[2] ) ) + for kp in range(nKpt): + if(pbc): + print("#%03d"%(kp),file=fd) + occ=( Occ if(not pbc) else Occ[kp] ); + string="" + for jmo in range(nMO): + string+="%16.8f "%(occ[jmo]) + print(string,file=fd); + fd.close() + +def print_00(text,flush=False,file=sys.stdout,end='\n',dtme=False,warning=0,Threads=[0]): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank(); MPIsize=comm.Get_size() + if( isinstance(Threads,str) ): + if( Threads.strip()=='all' ): + Threads= range(MPIsize) + if( (MPIrank not in Threads) and (warning >=0) ): + return + if(dtme): + text+=' \t\t'+str(datetime.datetime.now()) + if( file is None ): + file=sys.stdout + print(text,flush=flush,file=file,end=end) + +def dbglogger(msg,refresh=False,stdout=False): + print_00(msg); + +def read_inpf(dict_ret,fnme,silent=False,check_all_keys=True,abort_if_fail=True): + ngot=0 + if ( os.path.exists(fnme)): + inpf=futils.fopen( fnme,"r");## OK + if( not silent): + dbglogger("##read_inpf:%s"%(fnme),stdout=True); + for line in inpf: + line=line.strip() + if( line=="" ): + continue + if( line.startswith('#') ): + print_00("#read_inpf:reading off:"+line); continue + a=line.split(':') + if( len(a)>=2 ): + ky_in_dict = False + for ky in dict_ret: + if(a[0] == ky): + ky_in_dict=True + a[1]=a[1].rstrip(); + dict_ret[ky]=a[1];ngot=ngot+1 + if( not silent ): + dbglogger("##read_inpf:set_param:%s %s"%(ky,a[1])) + break + if( check_all_keys ): + assert ky_in_dict,"key:"+a[0]+" is not recognized" + if( len(a)!=2 ): + if( not silent ): + dbglogger("##read_inpf:possible parse error:len=%d for"%(len(a))+line); + futils.fclose(inpf) + return ngot + else: + if(abort_if_fail): + assert False,"missing file:"+fnme + if( not silent ): + dbglogger("##read_inpf:no such file:"+fnme) + return 0 +def print_params(job,params): + ##if( world.rank != 0 ): + ## return + fd=futils.fopen(job+"_params.log","w");## OK + for ky in params: + if( params[ky] is None ): + print_00(ky+": none",file=fd); + else: + print_00(ky+":"+str(params[ky]),file=fd) + futils.fclose(fd) + +def i1eqb(a,b,verbose=False,title=""): + ndimA=np.shape(a);ndimB=np.shape(b) + if( not i1eqb1(ndimA,ndimB) ): + if(verbose): + print_00("i1eqb:"+title+":dimension differs:A:",end="");print_00(ndimA,end="");print_00(" B:",end="");print_00(ndimB); + return False + return i1eqb1(a,b,verbose,title) +def i1eqb1(a,b,verbose=False,title=""): + A=np.ravel(a);B=np.ravel(b) + lA=len(A);lB=len(B) + if(lA!=lB): + return False + for I in range(lA): + if(A[I] != B[I]): + if(verbose): + print_00("#i1eqb1:"+title+":[%d] %d / %d"%(I,A[I],B[I])) + return False + return True + +def toString(a,Nmax=None,format=None,polar=False): + A=np.ravel(a) + Ld=len(A); + Nw=(Ld if(Nmax is None) else min([Ld,Nmax])) + dtype=np.array(A).dtype + ret="" + if( (dtype == complex) or (dtype == np.complex128) ): + if( not polar ): + if format is None: format="%14.6f %14.6fj "; + for I in range(Nw): + ret+=format%(A[I].real,A[I].imag) + else: + if format is None: format="%14.4e %6.3fpi "; + for I in range(Nw): + ret+=format%( abs(A[I]), np.atan2(A[I].imag, A[I].real)); + else: + if format is None: format="%14.6f "; + for I in range(Nw): + ret+=format%(A[I]) + return ret; + +def a1maxdiff(A,B): + I=0;dev=abs(A[I]-B[I]);at=I + La=len(A);Lb=len(B) + assert (La==Lb),"a1maxdiff" + for I in range(1,La): + dum=abs(A[I]-B[I]); + if(dum>dev): + dev=dum;at=I + return dev + +def d1maxdiff(A,B): + return a1maxdiff(A,B) + +def d1diff(A,B,length=-1): + return math.sqrt( d1sqrediff(A,B,length=length)) + +def d1dist(A,B,length=-1): + return math.sqrt( d1sqrediff(A,B,length=length)) +def d2dist(A,B,length=-1): + return d1dist(np.ravel(A), np.ravel(B)) + +def d1sqrediff(A,B,length=-1): + La=len(A);Lb=len(B) + L=length + if( L < 0 ): + L=min(La,Lb) + else: + L=min( length, min(La,Lb)) + ret=0.0 + for i in range(L): + ret = ret + (A[i]-B[i])*(A[i]-B[i]); + return ret + +def z1diff(A,B,title=None,err=None): + N=len(A) + dev=abs(A[0]-B[0]);at=0 + for I in range(1,N): + dum=abs(A[I]-B[I]); + if(devtol) ): + print_00("#z2diff:%s:dev=%e @[%d,%d] %10.4f+j%10.4f / %10.4f+j%10.4f"%( + title if(title is not None) else "", dev, at[0],at[1], + A[at[0]][at[1]].real, A[at[0]][at[1]].imag, + B[at[0]][at[1]].real, B[at[0]][at[1]].imag)) + if(err is not None): + assert (dev 1 and (MPIrank not in Threads) ): + return + spdfgh_=[ 's','p','d','f','g','h','i','j'] + fd=open(fnme,('a' if(Append) else 'w')) + for elmt in _basis: + name=None + if( isinstance(cell.basis,str) ): + name=cell.basis + elif( isinstance(cell.basis,dict) ): + if( elmt in cell.basis ): + name=cell.basis[elmt] + if( name is None ): + name=str( cell.basis ) + + bs_A=_basis[elmt] + nblock=len(bs_A) + for iblc in range(nblock): + Buf=bs_A[iblc] + Buflen=len(Buf); NpGTO=Buflen-1 + ell=Buf[0] + string=" %s %3s %s "%(name,elmt,spdfgh_[ell]) + for J in range(1,Buflen): + alph_cofs = Buf[J] + line=" %18.8e "%(alph_cofs[0]) + ncols=len(alph_cofs) + for j in range(1,ncols): + line+="%16.6e "%(alph_cofs[j]) + string+='\n'+line + print(string,file=fd) + ### print(_basis) + ### assert False,"" + fd.close() + +def make_tempfile(head=None,tail=""): + retv=None;iter=0 + if( head is None ): + head="temp" + while(retv is None): + iter+=1 + t_ms=int( round( time.time()*1000 ) ) + pid = os.getpid() + fnme= head + "_%08d"%(int(round(float(t_ms)*float(pid)))) + tail + if(os.path.exists(fnme)): + if(iter>20): + assert False,"" + print_00("!W tempfile:"+fnme+" exists..",warning=-1);continue + else: + retv=fnme; break + return retv + +def dNtoa(buf,format="%14.6f",delimiter=" "): + return d1toa(np.ravel(buf),format=format,delimiter=delimiter) + +def d1toa(arr,format="%14.6f",delimiter=" "): + if( isinstance(arr,float) or isinstance(arr,np.float64) or isinstance(arr,int) ): + return format%(arr) + Dic={};wt0=time.time();wt1=wt0 # XXX XXX + A=np.ravel( np.array(arr) ) + wt2=wt1;wt1=time.time(); Dic.update({"ravel":wt1-wt2}) + nA=len(A) + + sbuf=[ format%(A[j]) for j in range(nA) ] + wt2=wt1;wt1=time.time(); Dic.update({"strjoin":wt1-wt2,"tot":wt1-wt0}) + ## print("d1toa_join,%6d:"%(nA)+str(Dic)) + return delimiter.join(sbuf) + +def d2toa(a,format="%14.6f ",delimiter="\t\t\t "): + ret=""; + for I in range(len(a)): + for J in range(len(a[0])): + ret=ret + format%(a[I][J]) + ret=ret+delimiter + return ret + +def zNtoa(A,format="%10.4f %10.4f",delimiter=" ",Nlimit=None): + a=np.ravel(A) + return z1toa(a,format=format,delimiter=delimiter,Nlimit=Nlimit) + +def z1toa(arr,format="%10.4f %10.4f",delimiter=" ",Nlimit=None): + if( isinstance(arr,complex) or isinstance(arr,np.complex128) ): + return format%(arr.real,arr.imag) + Dic={};wt0=time.time();wt1=wt0 # XXX XXX + A=np.ravel( np.array(arr) ) + wt2=wt1;wt1=time.time(); Dic.update({"ravel":wt1-wt2}) + nA=len(A) + + sbuf=[ format%(A[j].real,A[j].imag) for j in range(nA) ] + wt2=wt1;wt1=time.time(); Dic.update({"strjoin":wt1-wt2,"tot":wt1-wt0}) + print("z1toa_join,%6d:"%(nA)+str(Dic)) + return delimiter.join(sbuf) + +def z1toa_polar(A,format="%8.3e %4.2fpi "): + N=len(A);ret="" + pi=3.1415926535897932384626433832795 + for I in range(N): + r=abs(A[I]);th_pi=math.atan2( A[I].imag, A[I].real)/pi + ret+=format%(r,th_pi) + return ret + +def z2toa(a,format="%8.3f+%8.3fj ",delimiter="\t\t\t "): + if( a.dtype == float ): + return d2toa(a); + ret=""; + for I in range(len(a)): + for J in range(len(a[0])): + ret=ret + format%( a[I][J].real, a[I][J].imag ) + ret=ret+delimiter + return ret + +def write_xyzf(fnme,R,S,description="",Eng=None,ResidualForce=None,LatticeVectors=None,a=None): + Nat=len(S) + fd=futils.fopen(fnme,"w");## OK + ### print("#write_xyzf:",len(R),len(S),fnme) + print_00("%d"%(Nat),file=fd) + secondline="#"+description + if( Eng is not None ): + secondline+="E=%16.8f "%(Eng) + if( ResidualForce is not None ): + secondline+="ResidualForce=%14.4e "%(ResidualForce) + if( a is not None ): + assert LatticeVectors is None,"" + LatticeVectors=a + if( LatticeVectors is not None ): + vec=np.ravel(LatticeVectors); le=len(vec); assert le==9,"" + sdum="%14.6f"%(vec[0]);sdum=sdum.strip(); + for I in range(1,le): + s="%14.6f"%(vec[I]) + sdum=sdum+','+s.strip();sdum=sdum.strip() + secondline+=" a:"+sdum + print_00(secondline,file=fd); + + for I in range(Nat): + print_00("%s %16.8f %16.8f %16.8f"%(S[I],R[I][0],R[I][1],R[I][2]),file=fd) + ### print("%s %16.8f %16.8f %16.8f"%(S[I],R[I][0],R[I][1],R[I][2])) + futils.fclose(fd) + +def check_equivalence(bool,title,values=None): + from .rttddft_common import rttddft_common + jth=rttddft_common.Countup("check_equivalence:"+title.strip()) + if( jth==1 or (not bool) ): + fd=open("check_equivalence.log","a") + nth=rttddft_common.Countup("check_equivalence") + if(nth==1): + print("\n##%s %s"%(rttddft_common.get_job(True),str(datetime.datetime.now())),file=fd) + print("%d %s:%s %s\n"%(nth,title.strip(),str(bool),( str(values) if(values is not None) else "")),file=fd) + fd.close() + +def write_xyzstring(R,Sy,input_unit,output_unit='A'): + if( output_unit==input_unit ): + str=""; + Nat=len(Sy) + for Iat in range(Nat): + str+="%s %f %f %f\n"%(Sy[Iat],R[Iat][0],R[Iat][1],R[Iat][2]); + return str; + + assert output_unit=='A',"" + assert input_unit=='B',"" + fac=1.0 + if( input_unit=='B' and output_unit=='A'): + fac=PhysicalConstants.BOHRinANGS(); + str=""; + Nat=len(Sy) + for Iat in range(Nat): + str+="%s %f %f %f\n"%(Sy[Iat],R[Iat][0]*fac,R[Iat][1]*fac,R[Iat][2]*fac); + return str; + +def get_LatticeVectors(line,ierr=-1,filename=""): + nGot=-1 + keys=["a:","BravaisVectors:","LatticeVectors:"] + dbuf=None + print_00("#get_LatticeVectors:"+line) + for ky in keys: + iat=line.find(ky); + if( iat>=0 ): + lky=len(ky); + dbuf=parse_doublesx( line[iat+lky:], Nwant=9); + print_00("get_LatticeVectors:parsing:"+line[iat+lky:]+str(dbuf)) + nGot=max(nGot,len(dbuf)) + if(len(dbuf)==9): + return np.reshape(dbuf,[3,3]) + if( nGot>=0 ): + if( nGot!=9 ): + warningmsg="!E:"+filename+" wrong length of LatticeVectors:"+str(nGot)+str(dbuf) + if(ierr<0): + assert False,warningmsg + else: + print_00(warningmsg); + else: + dbuf=np.reshape(dbuf,[3,3]) + return dbuf; + else: + return None + return None + +def read_xyzf(fnme,sbuf=None,dict=None,output_unit=None): + BOHRinANGS=None + if( output_unit is not None ): + assert (output_unit=='Bohr' or output_unit=='B'),"unknown output_unit:"+output_unit + BOHRinANGS=PhysicalConstants.BOHRinANGS() + fd=futils.fopen(fnme,"r");## OK + nl=0;Nat=-1 + R=[];Sy=[]; + for line in fd: + nl+=1 + line=line.strip() + if(nl==1): + Nat=int(line);continue + elif(nl==2): + if(sbuf is not None): + sbuf.append(line) + dbuf=get_LatticeVectors(line,filename=fnme) + if(dbuf is not None): + if(dict is not None): + dict.update({'a':dbuf}) + print_00("LatticeVectors:"+str(dbuf) ) + else: + print_00("!W reading off LatticeVectors:"+str(dbuf) ) + else: + print_00("reading off:"+line) + continue + else: + line=line.strip();le=len(line) + if(le<1): + continue + arr=line.split() + Sy.append(arr[0].strip()) + if( output_unit is not None ): + R.append([ float(arr[1])/BOHRinANGS,float(arr[2])/BOHRinANGS,float(arr[3])/BOHRinANGS]) + else: + R.append([ float(arr[1]),float(arr[2]),float(arr[3])]) + + futils.fclose(fd) + return R,Sy + +def dump_zNarray(zNa,fpath,Ncol=6,comment=None): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if(MPIrank!=0): + return + + fd=open(fpath,"w") + a=np.ravel(zNa) + if(comment is not None): + print("#%s"%(comment),file=fd) + le=len(a) + Nrow=le//Ncol + I=0 + for Irow in range(Nrow): + line="" + for J in range(Ncol): + line+="%24.10e %24.10e "%(a[I+J].real,a[I+J].imag) + print(line,file=fd) + I+=6 + while(I=le): + break + J=I; + while(J+1=Nwant): + return ret; + I=J+1 ## NEVER FORGET + return ret; +def parse_intsx(line,Nwant=None): + le=len(line) + ret=[] + I=0;nGot=0 + while(I=le): + break + J=I; + while(J+1=Nwant): + return ret; + I=J+1 ## NEVER FORGET + return ret; + + +def parse_doubles(str,delimiter=','): + darr = []; + sarr=str.split() + for x in sarr: + x=x.strip() + if( len(x)==0 ): + continue + if( delimiter is not None ): + subarr=x.split(delimiter) + for y in subarr: + y=y.strip() + if( len(y)==0 ): + continue + darr.append(float(y)) + else: + darr.append(float(x)) + + return darr + + +def aNmaxdiff(A,B,comment=None,lower_thr=None,verbose=False,iverbose=None,title=None,logfile=None,logf_append=True): + a=np.ravel( np.array(A) ) + b=np.ravel( np.array(B) ) + if(iverbose is None): + iverbose=( 1 if(not verbose) else 2 ) + fdA=[sys.stdout] + fdOU=( None if(logfile is None) else open( logfile,('a' if(logf_append) else 'w') ) );fdA.append(fdOU) + if(iverbose>2): + for fd in fdA: + lea=len(a);leb=len(b) + print_00( "#aNmaxdiff:%sLH:%d:"%( ("" if(comment is None) else comment+':'),lea) +str( np.array(A).dtype )+str(np.shape( np.array(A) )),file=fd) + print_00( "#aNmaxdiff:%sRH:%d:"%( ("" if(comment is None) else comment+':'),leb) +str( np.array(B).dtype )+str(np.shape( np.array(B) )),file=fd) + + ret=abs(a[0]-b[0]);at=0;vals=[a[0],b[0]]; + N=len(a) + for I in range(1,N): + dum=abs(a[I]-b[I]) + if( dum>ret ): + ret=dum; at=I; vals=[a[I],b[I]] + prtout=(iverbose>1) + if(lower_thr is not None): + if(ret> 0.1*lower_thr): + prtout=(iverbose>0) + if(prtout): + for fd in fdA: + print_00("#aNmaxdiff:%e "%(ret)+("" if(comment is None) else comment)\ + +"@"+ixj_to_IandJ(at,np.shape(A),toString=True)+" values:"+str(vals),file=fd) + if(fdOU is not None): + fdOU.close() + return ret + +def print_z3tensor(fpath,Append,T,description=""): + Ndim=np.shape(T);rank=len(Ndim) + if( rank!=3 and rank!=4 ): + print("#print_z3tensor:!W wrong dim:"+str(Ndim));return + nkp=(1 if(rank==3) else Ndim[0]) + strdtm=str(datetime.datetime.now()) + fd1=open(fpath,("a" if(Append) else "w")) + print("###%s \t\t"%(description)+strdtm,file=fd1) + for kp in range(nkp): + M=(T if(rank==3) else T[kp]) + nd=np.shape(M) + for i in range(nd[0]): + if(rank==4): + print("#%d,%d"%(kp,i),file=fd1) + else: + print("#%04d"%(i),file=fd1) + for j in range(nd[1]): + for k in range(nd[2]): + print("%11.5f %11.5f "%(M[i][j][k].real, M[i][j][k].imag),end="",file=fd1) + print("\n",end="",file=fd1) + print("\n\n",end="",file=fd1) + fd1.close() + +# nmrdff: 2n+1 point numerical differentiation n=1,2,3 +# @input: order : 3/5/7 +# @input: arr : [order][ dim ] +# eg. [ f(x-2h), f(x-h), NONE, f(x+h), f(x+2h)] +# each can be an array[dim] (if dim>0) +# of scalar (if dim==0) +# @input: dim : linear dimension of the input arrays (see above) +# @ +def nmrdff( order,arr,dim,dx,dict=None): + if(dim==0): + dtype=np.array( [arr[0]] ).dtype + else: + dtype=np.array( arr[0]).dtype + ## + ## note: arr might contain None + ## e.g.) [ F(x-h), None, F(x+h) ] + ## so for dim>0 np.array( arr ).dtype does not work + ## + assert( dtype==float or dtype==complex),"dtype="+str(dtype) + assert( order==3 or order==5 or order==7),"order" + hf=order//2 # 1,2,3 + ## print_00("hf:%d"%(hf));print_00(dtype) + dxINV=1.0/dx + + df3p=0.0 + if(dim>0): + df3p=np.zeros([dim],dtype=dtype) + df3p=-arr[ -1 + hf]*0.50 + df3p+=arr[ 1 + hf]*0.50 + df3p= df3p*dxINV + if( dict is not None ): + dict.update({"3p":df3p}) +## if( "3p" in dict ): +## dict["3p"]=df3p + + if( order > 3 ): + df5p=0.0 + if(dim>0): + df5p=np.zeros([dim],dtype=dtype) + df5p= arr[ -2 + hf].copy() + else: + df5p= arr[ -2 + hf] + df5p-=arr[ -1 + hf]*8.0 + df5p+=arr[ 1 + hf]*8.0 + df5p-=arr[ 2 + hf] + df5p=df5p*(dxINV/12.0) + if( dict is not None ): + dict.update({"5p":df5p}) +## if( "5p" in dict ): +## dict["5p"]=df5p + + inv3= 1.0/3.0 + if( order > 5 ): + df7p=0.0 + if(dim>0): + df7p=np.zeros([dim],dtype=dtype) + df7p=-arr[ -3 + hf]*inv3; + df7p+=arr[ -2 + hf]*3.0 ; + df7p-=arr[ -1 + hf]*15.0; + df7p+=arr[ 1 + hf]*15.0; + df7p-=arr[ 2 + hf]*3.0 ; + df7p+=arr[ 3 + hf]*inv3; + df7p=df7p*(dxINV/20.0); + + if( dict is not None ): + dict.update({"7p":df7p}) +## if( "7p" in dict ): +## dict["7p"]=df7p + if( order==7 ): + return df7p + elif( order==5): + return df5p + else: + return df3p + +def aNtofile(ope,fpath,dbuf=None): + dtype=np.array(dbuf).dtype + src1D=np.ravel(dbuf);Ld=len(src1D) + if( ope == 'S' ): + print_00("#aNtofile:writing on"+fpath) + fd=futils.fopen(fpath,"w"); ## OK + if(dtype==complex): + print_00("C %d"%(Ld),file=fd) + for I in range(Ld): + print_00("%18.10f %18.10f "%(src1D[I].real,src1D[I].imag),end=("\n" if((I+1)%10==0) else ""),file=fd) + else: + print_00("F %d"%(Ld),file=fd) + for I in range(Ld): + print_00("%18.10f "%(src1D[I]),end=("\n" if((I+1)%20==0) else ""),file=fd) + futils.fclose(fd);return None + elif( ope=='L' or ope=='C'): + print_00("#aNtofile:reading from"+fpath) + fd=futils.fopen(fpath,"r");## OK + nl=0;N=0;buf=None + for line in fd: + nl+=1 + if(nl==1): + a=line.split();dtype=float + if(a[0].strip()=="C"): + dtype=complex + elif(a[0].strip()=="F"): + dtype=float + Ld=int(a[1]); + buf=np.zeros([Ld],dtype=dtype);### print_00("#dim=%d %s /%s file:"%(len(buf),a[1],line)+fpath) + continue + else: + a=line.split();n=len(a); + if( dtype == complex ): + for i in range(n/2): + buf[N]=np.complex128( float(a[2*i]) + 1j*float(a[2*i+1])); N+=1 + else: + for i in range(n): + ## print_00("buf%d/%d a%d/%d"%(N,len(buf),i,len(a))) + buf[N]=float(a[i]); N+=1 + futils.fclose(fd) + assert (N==Ld),"read=%d/%d"%(N,Ld) + if( dbuf is not None ): + dev=abs( src1D[0] - buf[0] );at=0 + for I in range(1,Ld): + dum=abs( src1D[I]-buf[I] ) + if(dum>dev): + dev=dum;at=I + print_00("#maxdiff=%e @[%d]"%(dev,at),end="");print_00(buf[at],end=" / ");print_00(src1D[at]) + + return buf + else: + assert False,"unknown operation:"+ope + +def calc_eorbs(Cofs,FockMatr): + NdimC=np.shape(Cofs) + iscomplex=False + if( (np.array(Cofs).dtype == complex) or (np.array(FockMatr).dtype == complex) ): + iscomplex=True + ret=None + if( len(NdimC)==3 ): + print_00("#calc_eorbs:FockMatr:",end="");print_00(np.shape(FockMatr)); #[nKp][nAO][nAO] + print_00("#calc_eorbs:Cofs:",end="");print_00(np.shape(Cofs));#[nKp][nAO][nMO] + nKP=NdimC[0]; nAO=NdimC[1]; nMO=NdimC[2]; ret=np.zeros([nKP,nMO]) + for KP in range(nKP): + cofK=Cofs[KP];## print_00(np.shape(cofK)) + if( iscomplex ): + for I in range(nMO): + ret[KP][I]=np.vdot( cofK[:,I], np.matmul( FockMatr[KP], cofK[:,I])).real + else: + for I in range(nMO): + ret[KP][I]=np.vdot( cofK[:,I], np.matmul( FockMatr[KP], cofK[:,I])) + + else: + nKP=1; nAO=NdimC[0]; nMO=NdimC[1]; ret=np.zeros([nMO]) + if( iscomplex ): + for I in range(nMO): + ret[I]=np.vdot( Cofs[:,I], np.matmul( FockMatr, Cofs[:,I])).real + else: + for I in range(nMO): + ret[I]=np.vdot( Cofs[:,I], np.matmul( FockMatr, Cofs[:,I])) + return ret; + +def hdiag(matr,check_soln=False,**kwargs): + ## + ## diagonalizes Hermitian matrix via most efficient method ... + ## + Ld=len(matr) + if(Ld>=1024): + E,U = np.linalg.eig(matr) + info=0 ## otherwise throws exception + else: + E,U,info = scipy.linalg.lapack.zheev(matr) + if( check_soln ): + title="hdiag:" + if( "title" in kwargs ): + title=kwargs["title"] + devmx= check_eigvecs(title,matr,U,E); + if( "tol" in kwargs ): + assert (devmx0) else '')+ ky+delimiter+strval; nth=nth+1 + return bra+ret+ket; + + +def parse_xyzstring(str,unit_BorA): + assert (unit_BorA=='B' or unit_BorA=='A'),"" + fac=1.0 + if( unit_BorA=='B' ): + fac=1.0/PhysicalConstants.BOHRinANGS(); + + arr=str.split('\n') + nl=0;Nat=-1 + R=[];Sy=[]; + for line in arr: + ## print("#parse_xyzstring:"+line) + line=line.strip() + Cols=line.split(';') + for col in Cols: + col=col.strip(); + if(col==""): + continue + arr=col.split() + if(len(arr)==0): + continue + Sy.append(arr[0].strip()) + R.append([ float(arr[1])*fac,float(arr[2])*fac,float(arr[3])*fac]) + ## print("#parse_xyzstring:returns:",R) + return R,Sy + +def write_xyzstring(R,Sy,input_unit,output_unit='A'): + if( output_unit==input_unit ): + str=""; + Nat=len(Sy) + for Iat in range(Nat): + str+="%s %f %f %f\n"%(Sy[Iat],R[Iat][0],R[Iat][1],R[Iat][2]); + return str; + + assert output_unit=='A',"" + assert input_unit=='B',"" + fac=1.0 + if( input_unit=='B' and output_unit=='A'): + fac=PhysicalConstants.BOHRinANGS(); + str=""; + Nat=len(Sy) + for Iat in range(Nat): + str+="%s %f %f %f\n"%(Sy[Iat],R[Iat][0]*fac,R[Iat][1]*fac,R[Iat][2]*fac); + return str; + +def update_dict(fnc,dic1,Dic,key,val,append=False,iverbose=1,depth=0): + from mpi4py import MPI + + Key=fnc+'.'+key + update_dict_(dic1,Dic,Key,val,append=append,iverbose=iverbose,depth=depth) + prtout=(iverbose>1) + if( Dic[Key]['count'] == 1 ): + prtout=(iverbose>0) + + if( prtout): + comm=MPI.COMM_WORLD + rank=comm.Get_rank() + + string=' '*depth + "#%03d:%s.%s:%14.4f"%(rank,fnc,key,val) + fdF=open('walltime_%03d.log'%(rank),'a') + av,stdv,count=avg_dict_(Dic,Key) + string+=" \t\t\t %14.4f %12.2e %3d"%(av,stdv,count) + fdA=[ fdF ] + if( rank == 0 ): + fdA.append(sys.stdout) + for fd in fdA: + print(string,file=fd) + fdF.close() + + +def update_dict_(dic1,Dic,key,val,append=False,iverbose=1,depth=0): + if(not append): + dic1.update({key:{'sum':val,'sqrsum':val**2,'count':1}}) + else: + if( key not in dic1 ): + dic1.update({key:{'sum':val,'sqrsum':val**2,'count':1}}) + else: + dic1[key]['sum']+=val + dic1[key]['sqrsum']+=val**2 + dic1[key]['sum']+=val + + if( key not in Dic ): + Dic.update({key:{"sum":0.0,"sqrsum":0.0,"count":0}}) + + Dic[key]['sum']+=val + Dic[key]['sqrsum']+=val**2 + Dic[key]['count']+=1 +def avg_dict_(dic,key): + if( key not in dic ): + return 0.0,0.0,0 + ### print_00("#avg_dict_:"+key+str(dic[key])) + if( dic[key]['count']==0 ): + return 0.0,0.0,0 + else: + av=dic[key]['sum']/dic[key]['count'] + stdv=np.sqrt( abs( dic[key]['sqrsum']/dic[key]['count'] - av**2 )) + return av,stdv,dic[key]['count'] + +def update_dict_(dic1,Dic,key,val,append=False,iverbose=1,depth=0): + if(not append): + dic1.update({key:{'sum':val,'sqrsum':val**2,'count':1}}) + else: + if( key not in dic1 ): + dic1.update({key:{'sum':val,'sqrsum':val**2,'count':1}}) + else: + dic1[key]['sum']+=val + dic1[key]['sqrsum']+=val**2 + dic1[key]['sum']+=val + + if( key not in Dic ): + Dic.update({key:{"sum":0.0,"sqrsum":0.0,"count":0}}) + + Dic[key]['sum']+=val + Dic[key]['sqrsum']+=val**2 + Dic[key]['count']+=1 + +def printout_dict(fnc,dic1,Dic,val,depth=0,force=False,fnprtout=None): + from mpi4py import MPI + comm=MPI.COMM_WORLD + rank=comm.Get_rank() + + update_dict_(dic1,Dic,fnc,val,iverbose=0,depth=depth) + nth=Dic[fnc]['count'] + if( fnprtout is not None ): + prtout=(force or fnprtout(nth) ) + else: + prtout=(force or (nth<4 or nth==10 or nth==100 or (nth>100 and nth%200==0))) + if( not prtout ): + return 0 + string=' '*depth + "#%03d:%s:%4d %14.4f"%(rank,fnc,nth,val) + cum=0.0 + str1="" + for Ky in dic1: + ky=Ky.replace(fnc+".","") + if(ky==fnc): + continue + str1+="%s:%12.4f "%(ky,dic1[Ky]['sum']) + string+='{'+str1+'}' + fdF=open('walltime_%03d.dat'%(rank),'a') + fdA=[ fdF ] + if( rank == 0 ): + fdA.append(sys.stdout) + for fd in fdA: + print(string,file=fd) + fdF.close() + return nth + +def readwritezN(RorW,name,zbuf,Ith=None,Ndim_zbuf=None,format="%s_%04d.dat",compTO=None,description="",logfile=None,iverbose=1): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if( MPIrank > 0 ): + write_once("utils.readwritezN:mpi", + "utils.readwritezN invoked by thread %02d"%(MPIrank)) + + if(Ith is None): + if( RorW=='R'): + Ith=readwritezN_static_.Countup(name,inc=False) + elif( RorW=='W'): + Ith=readwritezN_static_.Countup(name,inc=True) + fpath=format%(name,Ith) + + if( iverbose>(0 if(RorW=='W') else 1) ): + print_00("#readwritezN:"+RorW+" Ith:%d FILE:"%(Ith)+fpath) + + if( compTO is None ): + compTO=Ith-1 + + retv=None + if( RorW=='W' ): + maxdiff=None;indexAT=None;sqrdiffsum=None;strdiff=None + readwritezN_writeone_(fpath,zbuf,header='#'+description, iverbose=iverbose) + if( compTO >=0 ): + maxdiff,indexAT,sqrdiffsum,strdiff = readwritezN_compto(zbuf,Ith, name,compTO,format=format,logfile=logfile,iverbose=iverbose) + return fpath,maxdiff,indexAT,sqrdiffsum,strdiff + elif(RorW=='R'): + sbuf=[] + ret=readwritezN_readone_(fpath,sbuf,Ndim=Ndim_zbuf, iverbose=iverbose) + if( compTO >=0 ): + readwritezN_compto(ret,Ith, name,compTO,format=format,logfile=logfile,iverbose=iverbose) + return ret,sbuf + else: + assert False,""+RorW + return None + + +def to_complexarray(src, do_clone=False): + if( (np.array(src).dtype == complex) or np.array(src).dtype == np.complex128 ): + if( do_clone ): + return arrayclone(src) + return src + else: +#converting to complex from:float64 +### print_00("#converting to complex from:",end="");print_00(np.array(src).dtype) + Ndim=np.shape( np.array(src) ) + srcv=np.ravel( np.array(src) ) + Ld=len(srcv) + ret=np.zeros( [Ld], dtype=np.complex128 ) + for I in range(Ld): + ret[I]=srcv[I] + return np.reshape( ret, Ndim) + +def print_TDeorbs(spinrestriction,TdMO,rttddft,pbc,RefMO, + FockMat,MO_Occ,job="temp",Append=True,step=-1,tm_au=-1,get_eorbs=None,get_pop=None, + md=None,popsum_dev=None,title=""): + assert spinrestriction!='O',"please double check dimensions: nmult_MO=1 nmult_Occ=2 and nmult_Fock=1 ?" + nmult_MO=(2 if(spinrestriction=='U') else 1) + nmult_Fock=nmult_MO + filenamelist=[] + FermiLv_au=(0.0 if(not pbc) else rttddft.get_fermi()) + for sp in range(nmult_MO): + xtn="" if(nmult_MO==1) else ("_upSpin" if(sp==0)else "_dnSpin") + mo= TdMO if(nmult_MO==1) else TdMO[sp]; #[kp][nAO][nMO] + rfmo=RefMO if(nmult_MO==1) else RefMO[sp]; #[kp][nAO][nMO] + fock=FockMat if(nmult_Fock==1) else FockMat[sp]; #[kp][nAO][nAO] + occ= MO_Occ if(nmult_MO==1) else MO_Occ[sp]; #[kp][nMO] + #print_00("TdMO:",end="");print_00(np.shape(mo)) + #print_00("rfmo:",end="");print_00(np.shape(rfmo)) + #print_00("fock:",end="");print_00(np.shape(fock)) + #print_00("occ:",end="");print_00(np.shape(occ)) + get_eorbs1=None;get_pop1=None + if( get_eorbs is not None): + if( nmult_MO == 1 ): + get_eorbs1=get_eorbs; + else: + get_eorbs1=[]; + if( get_pop is not None): + if( nmult_MO == 1 ): + get_pop1=get_pop; + else: + get_pop1=[]; + fermiLv1_au=( 0.0 if(not pbc) else ( FermiLv_au if(spinrestriction!='U') else FermiLv_au[sp] ) ) + flist1 = print_tdeorbs1(mo,rttddft,pbc,rfmo,fock,occ,job=job+xtn,Append=Append,step=step,tm_au=tm_au,\ + get_eorbs=get_eorbs1,get_pop=get_pop1,md=md,popsum_dev=popsum_dev,title=title, + FermiLv_au=fermiLv1_au) + if( get_eorbs is not None): + if( nmult_MO != 1 ): + get_eorbs.append( get_eorbs1 ); + if( get_pop is not None): + if( nmult_MO != 1 ): + get_pop.append( get_pop1 ); + + for fnme in flist1: + filenamelist.append(fnme) + return filenamelist; + +## jobname( name=params["name"], branch=params["branch"], basis=params["basis"], xc=params["xc"], +## timestep_as=params["timestep_as"], strField=None ) + +def jobname(**kwargs): + return format_jobname(kwargs); + +def format_jobname(params,pbc=None): + name=getv_safe(params,"name",default="") + + name=getv_safe(params,"name",default="") + branch_or_ver=( ("" if("ver" not in params) else params["ver"]) if("branch" not in params) else params["branch"]) + basis=getv_safe(params,"basis",default="") + if( "exp_to_discard" in params): + if( params["exp_to_discard"] is not None): + basis +="e%4.2f"%( float(params["exp_to_discard"]) ) + xc =getv_safe(params,"xc",default="").replace(",","-") + strKpoints="" + if( pbc is None or (not pbc) ): + for kw in params: + for ref in ["nKpoints","nkpoints"]: + if(kw==ref): + nKpoints=params[kw]; + if( nKpoints is not None ): + if(isinstance(nKpoints,str)): + sA=nKpoints.split(',');NsA=len(sA) + nKpoints=[ int(sA[j]) for j in range(NsA) ] + assert isinstance(nKpoints[0],int),""; assert len(nKpoints)==3,"" + strKpoints="_Kp%d%d%d"%(nKpoints[0],nKpoints[1],nKpoints[2]) + DFT="" + if( "spinrestriction" in params ): + if( params["spinrestriction"] is not None): + DFT=("" if( params["spinrestriction"] =='R' ) else ( "UKS" if (params["spinrestriction"] =='U') + else ("ROKS" if(params["spinrestriction"] =='O') else None) ) ) + assert DFT is not None,"wrong spinrestriction:"+ params["spinrestriction"] + str_dt=("" if("timestep_as" not in params) else "_dt"+("%5.2f"%(params["timestep_as"])).strip() ) + strField=("" if("strField" not in params) else ("" if( params["strField"] is None ) else "_"+params["strField"] ) ) + return name + branch_or_ver + "_" + DFT + basis + xc + strKpoints + str_dt + strField + +def isScalarNumber(arg): + return (isinstance(arg,int) or isinstance(arg,float) or isinstance(arg,complex) or isinstance(arg,np.int64)\ + or isinstance(arg,np.float64) or isinstance(arg,np.complex128) ) + +def Schmidt_orth(tgt,TINY=1.0e-8): + Ndim=np.shape(tgt) + Nv=Ndim[1] + Ret=[];n=0 + for I in range(Nv): + vdum=tgt[:,I].copy(); + for j in range(n): + cof=np.vdot( Ret[j],vdum ) + vdum = vdum - cof*Ret[j] + le=np.sqrt( np.vdot(vdum, vdum)) + if( le < TINY ): + print("linearly dpd:%03d:%e"%(I,le));continue + else: + Ret.append( vdum/le );n+=1 + return Ret + +def check_matrixrank(tgt,TINY=1.0e-8): + orth=Schmidt_orth(tgt,TINY=TINY) + le=len(orth) + return le + + + +def atomicsymbol_to_atomicnumber(S): + atomicsymbols_=["H", "He",\ + "Li","Be", "B", "C", "N", "O", "F","Ne",\ + "Na","Mg", "Al","Si", "P", "S","Cl","Ar",\ + "K","Ca","Sc","Ti", "V","Cr","Mn","Fe","Co","Ni","Cu","Zn","Ga","Ge","As","Se","Br","Kr",\ + "Rb","Sr", "Y","Zr","Nb","Mo","Tc","Ru","Rh","Pb","Ag","Cd","In","Sn","Sb","Te", "I","Xe"] + + for I in range( len(atomicsymbols_) ): + if( atomicsymbols_[I]==S ): + return I+1 + assert False,"wrong symbol:"+S + +def atomicnumber_to_atomicsymbol(Z): + atomicsymbols_=["H", "He",\ + "Li","Be", "B", "C", "N", "O", "F","Ne",\ + "Na","Mg", "Al","Si", "P", "S","Cl","Ar",\ + "K","Ca","Sc","Ti", "V","Cr","Mn","Fe","Co","Ni","Cu","Zn","Ga","Ge","As","Se","Br","Kr",\ + "Rb","Sr", "Y","Zr","Nb","Mo","Tc","Ru","Rh","Pb","Ag","Cd","In","Sn","Sb","Te", "I","Xe"] + le=len(atomicsymbols_) + assert ((Z-1) 0 ): + write_once("utils.write_file:mpi", + "utils.write_file invoked by thread %02d"%(MPIrank)) + fd=futils.fopen(fpath,"w"); ## OK + for ky in kwargs: + x=kwargs[ky] + if( isinstance(x,np.ndarray) ): + if(len(x)==0): + print(ky+":I",end="\t",file=fd); + elif(x.dtype==float): + print(ky+":D",end="\t",file=fd);print(a1toa(x),file=fd) + elif(x.dtype==np.float64): + print(ky+":D",end="\t",file=fd);print(a1toa(x),file=fd) + elif(x.dtype==complex): + print(ky+":Z",end="\t",file=fd);print(a1toa(x),file=fd) + elif(x.dtype==np.complex128): + print(ky+":Z",end="\t",file=fd);print(a1toa(x),file=fd) + elif(x.dtype==int): + print(ky+":I",end="\t",file=fd);print(a1toa(x),file=fd) + elif( isinstance(x,list)): + if(len(x)==0): + print(ky+":I",end="\t",file=fd); + elif(isinstance(x[0],float) ): + print(ky+":D",end="\t",file=fd);print(a1toa(x),file=fd) + elif(isinstance(x[0],np.float64)): + print(ky+":D",end="\t",file=fd);print(a1toa(x),file=fd) + elif(isinstance(x[0],complex)): + print(ky+":Z",end="\t",file=fd);print(a1toa(x),file=fd) + elif(isinstance(x[0],np.complex128)): + print(ky+":Z",end="\t",file=fd);print(a1toa(x),file=fd) + elif(isinstance(x[0],int)): + print(ky+":I",end="\t",file=fd);print(a1toa(x),file=fd) + elif(isinstance(x,float) ): + print(ky+":d",end="\t",file=fd);print(str(x),file=fd) + elif(isinstance(x,np.float64)): + print(ky+":d",end="\t",file=fd);print(str(x),file=fd) + elif(isinstance(x,complex)): + print(ky+":z",end="\t",file=fd);print(str(x),file=fd) + elif(isinstance(x,np.complex128)): + print(ky+":z",end="\t",file=fd);print(str(x),file=fd) + elif(isinstance(x,int)): + print(ky+":i",end="\t",file=fd);print(str(x),file=fd) + elif(isinstance(x,str)): + print(ky+":s",end="\t",file=fd);print(str(x),file=fd) + else: + print(ky+":unknown type:"+str(type(x)),end="\t",file=fd);print(str(x),file=fd) + futils.fclose(fd) + +def readwrite_xbuf(RorW,fnme,data=None): + if(RorW=='R' or RorW=='r'): + ret=[] + fd=futils.fopen(fnme,"r");## OK + dtype=None + for line in fd: + if(dtype is None): + line=line.strip() + if(line=="d"): + dtype=np.float64 + elif(line=='z'): + dtype=np.complex128 + elif(line=='i'): + dtype=int + else: + assert False,""+line + continue + if( dtype == int ): + arr=parse_ints(line,delimiter=None) + n=len(arr) + for i in range(n): + ret.append(arr[i]) + else: + arr=parse_doubles(line,delimiter=None) + if( dtype == np.complex128 ): + n=len(arr)//2 + for i in range(n): + ret.append( np.complex128( arr[2*i]+1j*arr[2*i+1] )) + else: + n=len(arr) + for i in range(n): + ret.append(arr[i]) + futils.fclose(fd) + return np.array(ret) + else: + assert (data is not None),"fnme:"+fnme + data_1d=np.ravel(data) + fd=futils.fopen(fnme,"w") ## OK + dtype=np.array(data_1d).dtype + if( dtype == int ): + print("i",file=fd); + elif(dtype==float or dtype==np.float64): + print("d",file=fd); + elif(dtype==complex or dtype==np.complex128): + print("z",file=fd); + else: + assert False,""+dtype + ncol=8 + Ld=len(data_1d) + sbuf=""; + for i in range(Ld): + if( dtype==int): + sbuf+="%d "%(data_1d[i]) + elif( dtype==float or dtype==np.float64): + sbuf+="%18.10e "%(data_1d[i]) + elif( dtype==complex or dtype==np.complex128): + sbuf+="%18.10e %18.10e "%(data_1d[i].real,data_1d[i].imag) + + if( (i+1)%ncol==0 ): + print(sbuf,file=fd);sbuf="" + if(sbuf!=""): + print(sbuf,file=fd);sbuf="" + futils.fclose(fd) + +def print_a2maxdiff(A,B,fpath,Append=False,description=""): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if(MPIrank!=0): + return aNmaxdiff(A,B) + + fd=open(fpath,("a" if(Append) else "w")) + Ndim=np.shape(A);assert i1eqb(Ndim,np.shape(B)),""; + assert len(Ndim)==2,"" + + diff=aNmaxdiff(A,B) + if(Append): + print("\n\n",file=fd); + print("##%s maxdiff:%14.6e"%(description,diff),file=fd); + for I in range(Ndim[0]): + for J in range(Ndim[1]): + print("%04d %04d %14.6e %12.6f %12.6f %12.6f %12.6f"%(\ + I,J,abs(A[I][J]-B[I][J]),A[I][J].real,A[I][J].imag,B[I][J].real,B[I][J].imag),file=fd) + fd.close() + return diff + +def print_Hmatrices(title,A,B,Nref=5,fpath=None,Append=False): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if(MPIrank!=0): + return + + Ndim=np.shape(A) + assert i1eqb(Ndim,np.shape(B)),"print_Hmatrices:"+str(Ndim)+"/"+str( np.shape(B) ) + if( len(Ndim)==2 ): + print_Hmatrices_1(title,A,B,Nref,fpath) + return + else: + if(len(Ndim)==3): + for I in range(Ndim[0]): + print_Hmatrices_1(title+"_K%03d"%(I),A[I],B[I],Nref,fpath,Append=(Append if(I==0) else True)) + else: + assert False,""+str(Ndim) + + +def write_file(fpath,*args): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if( MPIrank > 0 ): + write_once("utils.write_file:mpi", + "utils.write_file invoked by thread %02d"%(MPIrank)) + fd=futils.fopen(fpath,"w"); ## OK + for x in args: + if( isinstance(x,np.ndarray) ): + if(len(x)==0): + print("I",end="\t",file=fd); + elif(x.dtype==float): + print("D",end="\t",file=fd);print(a1toa(x),file=fd) + elif(x.dtype==np.float64): + print("D",end="\t",file=fd);print(a1toa(x),file=fd) + elif(x.dtype==complex): + print("Z",end="\t",file=fd);print(a1toa(x),file=fd) + elif(x.dtype==np.complex128): + print("Z",end="\t",file=fd);print(a1toa(x),file=fd) + elif(x.dtype==int): + print("I",end="\t",file=fd);print(a1toa(x),file=fd) + elif( isinstance(x,list)): + if(len(x)==0): + print("I",end="\t",file=fd); + elif(isinstance(x[0],float) ): + print("D",end="\t",file=fd);print(a1toa(x),file=fd) + elif(isinstance(x[0],np.float64)): + print("D",end="\t",file=fd);print(a1toa(x),file=fd) + elif(isinstance(x[0],complex)): + print("Z",end="\t",file=fd);print(a1toa(x),file=fd) + elif(isinstance(x[0],np.complex128)): + print("Z",end="\t",file=fd);print(a1toa(x),file=fd) + elif(isinstance(x[0],int)): + print("I",end="\t",file=fd);print(a1toa(x),file=fd) + elif(isinstance(x,float) ): + print("d",end="\t",file=fd);print(str(x),file=fd) + elif(isinstance(x,np.float64)): + print("d",end="\t",file=fd);print(str(x),file=fd) + elif(isinstance(x,complex)): + print("z",end="\t",file=fd);print(str(x),file=fd) + elif(isinstance(x,np.complex128)): + print("z",end="\t",file=fd);print(str(x),file=fd) + elif(isinstance(x,int)): + print("i",end="\t",file=fd);print(str(x),file=fd) + elif(isinstance(x,str)): + print("s",end="\t",file=fd);print(str(x),file=fd) + else: + print("unknown type:"+str(type(x)),end="\t",file=fd);print(str(x),file=fd) + futils.fclose(fd) + +def list_to_a1(src): + if( isinstance(src,list) or isinstance(src,np.ndarray) ): + ret=[] + for x in src: + if( isinstance(x,list) or isinstance(x,np.ndarray)): + arr=list_to_a1(x) + for y in arr: + ret.append(y) + else: + ### print_00("x is not list or ndarray",end="");print_00(x) + ret.append(x) + return ret; + else: + print_00("!W Neither list or ndarray",end="");print_00(src) + return src + +def gamma_hfint(arg): + if(arg%2==0): ## Gamma(n)=(n-1)! + p=arg/2; + return int_factorial(p-1); + else: + return hfodd_factorial(arg) + +def modify_filename(org,pbc,nmult,spin,kpt): + if(not pbc and (nmult==1) ): + return org + head=None;tail=None + for xtn in [".dat",".log",".out"]: + if(org.endswith(xtn)): + head=org.replace(xtn,"");tail=xtn; break + if(head is None): + head=org;tail="" + if( not pbc ): + return head+("_upSpin" if(spin==0) else "_dnSpin")+tail + if( nmult==1 ): + return head+ "_k%03d"%(kpt) + tail + return head+("_upSpin" if(spin==0) else "_dnSpin")\ + + "_k%03d"%(kpt) + tail +def deviation_from_unitmatrix(A): + N=len(A) + devsum=0.0; dagdev=-1.0; ofddev=-1.0 + for I in range(N): + for J in range(N): + if(I==J): + dev=abs( A[I][J]-1.0); devsum+=dev**2; dagdev=max(dagdev,dev) + else: + dev=abs( A[I][J] ); devsum+=dev**2; ofddev=max(ofddev, dev) + return devsum,dagdev,ofddev + +def comp_zbufs(Lhs,Rhs,fpath,Append=False,description=""): + fd=open(fpath,("a" if(Append) else "w")) + print("## "+description,file=fd) + lhs=np.ravel(Lhs);rhs=np.ravel(Rhs) + leL=len(lhs);leR=len(rhs) + le=min(leL,leR) + sL="< ";sR="> ";sD="# ";n=0 + for I in range(le): + sL+="%15.9f %15.9f "%(lhs[I].real,lhs[I].imag) + sR+="%15.9f %15.9f "%(rhs[I].real,rhs[I].imag) + sD+=(' '*15)+" %15.6e "%(abs(rhs[I]-lhs[I])); n+=1 + if(n%6==0): + print(sL,file=fd);print(sR,file=fd);print(sD,file=fd); + sL="";sR="";sD="";n=0; + if(n>0): + print(sL,file=fd);print(sR,file=fd);print(sD,file=fd); + fd.close() + +def print_aNmatr(fpath,A,Append=False,comment=None): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if(MPIrank!=0): + return + + Ndim=np.shape(A) + fd=open(fpath,('a' if(Append) else 'w')) + if(comment is not None): + print("###"+comment,file=fd) ### you come here iff MPIrank==0 + if(len(Ndim)==3): + for I in range(Ndim[0]): + print("#%04d:"%(I),file=fd) + for J in range(Ndim[1]): + string="" + for K in range(Ndim[2]): + string+="%11.6f %11.6f "%(A[I][J][K].real,A[I][J][K].imag) + print(string,file=fd); + print("\n\n",file=fd) + fd.close() + elif( len(Ndim)==2 ): + for J in range(Ndim[0]): + string="" + for K in range(Ndim[1]): + string+="%11.6f %11.6f "%(A[J][K].real,A[J][K].imag) + print(string,file=fd); + print("\n\n",file=fd) + elif( len(Ndim)==4 ): + IxJ=0 + for I in range(Ndim[0]): + for J in range(Ndim[1]): + print("#%04d:(%03d,%03d)"%(IxJ,I,J),file=fd) + string="" + for K in range(Ndim[2]): + for L in range(Ndim[3]): + string+="%11.6f %11.6f "%(A[I][J][K][L].real,A[I][J][K][L].imag) + print(string,file=fd); + print("\n\n",file=fd) + else: + assert False,""+str(Ndim) + fd.close() + +def prtaNx2(title,A,B): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if(MPIrank!=0): + return + + print("#prtaNx2:"+title+" Ndim:"+str(np.shape(A))+" "+str(np.shape(B)) ) + a=np.ravel(A); + if( not ( isinstance(a[0],np.float64) or isinstance(a[0],float) or + isinstance(a[0],np.complex128) or isinstance(a[0],complex) ) ): + buf=[] + for x in a: + for y in np.ravel(x): + buf.append(y); + if( len(buf)%20==1 ): + print("append:",end="");print(y) + print("a:",end="");print(np.shape(buf)) + a=buf + b=np.ravel(B) + print(np.shape(a));print("a:",end="");print(a) + print(np.shape(b));print("b:",end="");print(b) + la=len(a) + lb=len(b) + N=(lb if(lb>la) else la) + line="" + for i in range(N): + line="#prtaNx2:"+title+":%d:"%(i) + if(i0): + J-=1;ret[J]=n%Ndim[J];n=n//Ndim[J]; + if( toString ): + return i1toa(ret) + else: + return ret + +def IxJ_to_IandJ(IxJ,Ndim): + le=len(Ndim); + ret=[ -1 for k in range(le) ] + cur=IxJ + for i in range(le): + J=le-i-1 + ret[J]=cur%Ndim[J] + cur=(cur-ret[J])//Ndim[J] + return ret + +def popsum(pop, spinrestriction, pbc, nKpt ): + ndim=np.shape(pop);le_ndim=len(ndim);Ld=len(pop) + ret=0.0; + if(pbc): + for I in range(Ld): + ret += sum( np.ravel(pop[I]) ) + ret=ret/float(nKpt) + else: + if( le_ndim == 1 ): + ret=sum(pop) + else: + for I in range(Ld): + ret += sum( np.ravel(pop[I]) ) + return ret + +## +## print_tdeorbs1: receives spin-resolved matrix +## tdMO[kp][nAO][nMO], refmo[kp][nAO][nMO], +## +def print_tdeorbs1(tdMO,rttddft,pbc,refMO,FockMat,mo_occ,job="temp",Append=True,step=-1,tm_au=-1, + get_eorbs=None,get_pop=None,md=None,popsum_dev=None,title="", FermiLv_au=0.0): + ## AUinFS=0.02418884326198665673981200055933 + # mo_occ : UHF,ROHF [sp][nMO] / [sp][nKpt][nMO] + # RHF [nMO] / [nKpt][nMO] + Ndim_MO=np.shape(tdMO) + + TINY=1.0e-20 + AUinFS=2.418884326058678e-2 + Ndim=np.shape(tdMO) + if( not pbc ): + nkpt=1;nAO=Ndim[0];nMO=Ndim[1] + else: + nkpt=Ndim[0];nAO=Ndim[1];nMO=Ndim[2] + + kvectors = np.reshape( rttddft.kpts, (-1,3) ) + ### print("ndim_occ:",end="");print(np.shape(mo_occ)) + ### print("mo_occ:",end="");print(mo_occ) + + ndim_occ=np.shape(mo_occ); + N_ele=0.0 + if( len(ndim_occ)==1 ): + N_ele=sum(mo_occ) + else: + for I in range(len(mo_occ)): + N_ele += sum( np.ravel(mo_occ[I]) ) + + kvectors = (None if(not pbc) else np.reshape( rttddft.kpts, (-1,3))) + + eorbs=np.zeros([nMO]) + pop =np.zeros([nMO]);avg_pop=( np.zeros([nMO]) if(pbc and nkpt>1) else None) + filenames=[ job+('' if(not pbc) else '_*')+"_eorbs.dat", + job+('' if(not pbc) else '_*')+"_tdpop.dat"] + popsum=0.0 + for kp in range(nkpt): + wfn=( tdMO if(not pbc) else tdMO[kp]) + ref_wfn=( refMO if(not pbc) else refMO[kp] ) + if( not pbc ): + S1e= rttddft.get_ovlp(); F = FockMat; Occ=mo_occ + else: + S1e= rttddft.get_ovlp(rttddft.cell,kvectors[kp]); F=FockMat[kp];Occ=mo_occ[kp] + # (i) : C F C + + for al in range(nMO): + eps = np.vdot( wfn[:,al], np.matmul( F, wfn[:,al] ) ).real + eorbs[al]=eps + + if( get_eorbs is not None ): + if( not pbc ): + for al in range(nMO): + get_eorbs.append(eorbs[al]) + else: + get_eorbs.append(eorbs.copy()) + + eorbf = ( job if(not pbc) else job+"_kp%03d"%(kp) )+"_eorbs.dat" + fd=futils.fopen( eorbf, ("a" if Append else "w")) + if( not Append ): + print_00("#%6s %14s %14s %16s %14s"%("step","tm_au","tm_fs","FermiLv_au","eorbs"),file=fd) + print_00("### %03d %12.6f %12.6f %12.6f"%(kp, kvectors[kp][0], kvectors[kp][1], kvectors[kp][2]),file=fd) + print_00(" %6d %14.4f %14.4f %16.8f "%(step,tm_au,tm_au*AUinFS,FermiLv_au) + d1toa(eorbs,format="%14.6f "),file=fd) + futils.fclose(fd) + # (ii) : \sum_a | < C0_n | S | C_a > |^{2} * w_a + + for n in range(nMO): + pop[n]=0.0 + for al in range(nMO): + if( Occ[al]1.0e-5 ): + print_00("#print_tdeorbs1:popsum:%14.6f / N_ele:%14.6f "%(popsum,N_ele)+title,warning=1) + trdm = calc_trDM1( tdMO,mo_occ,pbc,rttddft) + trdmREF = calc_trDM1(refMO,mo_occ,pbc,rttddft) + print_00("#print_tdeorbs1:trDM:%14.6f %14.6f"%(trdm,trdmREF),warning=1) + if( md is not None ): + Dic1={} + md.normalize_MOcofs(rttddft,MO_Coeffs=refMO,dict=Dic1,update_self=False) + print_00("popsum_dev:refMO_dev:"+str(Dic1)) + Dic1={} + md.normalize_MOcofs(rttddft,MO_Coeffs=tdMO,dict=Dic1) + print_00("popsum_dev:%e orth:"%(abs(popsum-N_ele))+str(Dic1)) + if(popsum_dev is not None): + popsum_dev.clear() + popsum_dev.append( abs(popsum-N_ele) ) +# assert abs(popsum-N_ele)<1.0e-3,"popsum deviates" + xassertf( abs(popsum-N_ele)<1.0e-3,"print_tdeorbs1:popsum %f/%f dev %e"%(popsum,N_ele,abs(popsum-N_ele)),1) + return filenames + + +def check_eigvecs(title,A,U,E): + Ndim=np.shape(U) + nMO=Ndim[1];devmx=0.0 + for I in range(nMO): + V=np.matmul( A,U[:,I]) + C=U[:,I]*E[I] + dev=z1diff(C,V) + devmx=max([dev,devmx]) + print_00("check_soln:%s %e"%(title,devmx)) + return devmx; + +def int_factorial(arg): + #0 1 2 3 4 5 6 7 8 9 10 + ref=[1,1,2,6,24,120,720,5040,40320,362880, 3628800] + if(arg<=10): + return ref[arg]; + else: + n=10;ret=float(ref[n]) + for I in range(n+1,arg+1): + ret*=I + return ret + +def hfodd_factorial(odd): + assert (odd%2==1),"hfodd_factorial:%d"%(odd) + sqrt_pi=1.7724538509055160272981674833411; + p=(odd-1)//2;## 1,3,5,... => 0,1,2,... and retv[p]= Gamma((2p+1)/2) = ((2p-1)/2)*Gamma[p-1] + # 0(1/2) 1(3/2) 2 3 4(9/2) + retv=[ sqrt_pi, 0.5*sqrt_pi, 0.75*sqrt_pi, 1.875*sqrt_pi, 6.5625*sqrt_pi] + n_last=4 + if(p<=n_last): + return retv[p] + ret=retv[n_last] + for i in range(n_last+1,p+1): ## eg. Gamma(9/2)*(5-0.5) ... + ret*=(i-0.5) + return ret + +def gamma_hfint(arg): + if(arg%2==0): ## Gamma(n)=(n-1)! + p=arg/2; + return int_factorial(p-1); + else: + return hfodd_factorial(arg) + +def gammln(xx): + cof=[ 76.18009172947146e+00, -86.50532032941677e+00, + 24.01409824083091e+00, -1.231739572450155e+00, + 0.1208650973866179e-02, -0.5395239384953e-05]; + x=xx + y=x; ### y=x=xx; + tmp=x+5.5; tmp=tmp-(x+0.5)*math.log(tmp); + ser=1.000000000190015; + for j in range(6): + y+=1; ser+=cof[j]/float(y) ### for(j=0;j<6;j++)ser+=cof[j]/++y; + return -tmp+math.log(2.5066282746310005*ser/x); + +class readwritezN_static_: + counter={} + + @staticmethod + def Countup(key,inc=True,offset=0): ## by default 1,2,3,... + if( key not in readwritezN_static_.counter ): + readwritezN_static_.counter.update({key:0}) + return 0; + if(inc): + readwritezN_static_.counter[key]+=1 + return readwritezN_static_.counter[key] +# +# @return 'R': (zbuf[nblock][ --ndarray-- ] or zbuf[ --Ndim_zbuf-- ]), list_of_commentlines[nblock] +# 'W': fpath,maxdiff,indexAT,sqrdiffsum,strdiff +# +def readwritezN(RorW,name,zbuf,Ith=None,Ndim_zbuf=None,format="%s_%04d.dat",compTO=None,description="",logfile=None,iverbose=1): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if( MPIrank > 0 ): + write_once("utils.readwritezN:mpi", + "utils.readwritezN invoked by thread %02d"%(MPIrank)) + + if(Ith is None): + if( RorW=='R'): + Ith=readwritezN_static_.Countup(name,inc=False) + elif( RorW=='W'): + Ith=readwritezN_static_.Countup(name,inc=True) + fpath=format%(name,Ith) + + if( iverbose>(0 if(RorW=='W') else 1) ): + print_00("#readwritezN:"+RorW+" Ith:%d FILE:"%(Ith)+fpath) + + if( compTO is None ): + compTO=Ith-1 + + retv=None + if( RorW=='W' ): + maxdiff=None;indexAT=None;sqrdiffsum=None;strdiff=None + readwritezN_writeone_(fpath,zbuf,header='#'+description, iverbose=iverbose) + if( compTO >=0 ): + maxdiff,indexAT,sqrdiffsum,strdiff = readwritezN_compto(zbuf,Ith, name,compTO,format=format,logfile=logfile,iverbose=iverbose) + return fpath,maxdiff,indexAT,sqrdiffsum,strdiff + elif(RorW=='R'): + sbuf=[] + ret=readwritezN_readone_(fpath,sbuf,Ndim=Ndim_zbuf, iverbose=iverbose) + if( compTO >=0 ): + readwritezN_compto(ret,Ith, name,compTO,format=format,logfile=logfile,iverbose=iverbose) + return ret,sbuf + else: + assert False,""+RorW + return None + +# maxdiff,indexAT,sqrdiffsum,strdiff +def readwritezN_compto(zbuf,Ith,name,Jth,format,logfile=None,iverbose=1,diffTOL=1.0e-6): + comm=MPI.COMM_WORLD + MPIrank=comm.Get_rank() + + Ndim=np.shape(zbuf) + fpth2=format%(name,Jth);sbuf=[] + error=False + maxdiff=None; indexAT=None; sqrdiffsum=None; strret=None + if( not os.path.exists(fpth2) ): + strret="!W: %d th of %s : %s does not exist"%(Jth,name,fpth2) + error=True + else: + zbf2=readwritezN_readone_(fpth2,sbuf,Ndim=Ndim) + maxdiff,indexAT,vals,sqrdiffsum = maxdiff_zbufs_(zbuf,zbf2) + fdA=[sys.stdout];fdOU=None + strret="#%s %04d/%04d maxdiff:%e @%s %f,%f / %f,%f dist:%e"%(\ + name,Ith,Jth,maxdiff,str(indexAT),vals[0].real,vals[0].imag, + vals[1].real, vals[1].imag, np.sqrt(sqrdiffsum)) + if( MPIrank == 0 ): + if( error or iverbose>2 or \ + (iverbose>1 and (diffTOL>0 and maxdiff>0.1*diffTOL)) or\ + (iverbose>0 and (diffTOL>0 and maxdiff>diffTOL)) ): + if(logfile is not None): + fdOU=open(logfile,"a");fdA.append(fdOU) + + for fd in fdA: + print(strret,file=fd) + if(fdOU is not None): + fdOU.close() + return maxdiff,indexAT,sqrdiffsum,strret + +def readwritezN_writeblock_(fd,cbuf=None,format="%16.8f %16.8f",delimiter=' \t'): + + assert cbuf is not None,"" + Ndim=np.shape(cbuf);leNdim=len(Ndim) + if(leNdim==2): + for I in range(Ndim[0]): + str=format%(cbuf[I][0].real, cbuf[I][0].imag) + for J in range(1,Ndim[1]): + str+=delimiter+format%(cbuf[I][J].real, cbuf[I][J].imag) + print(str,file=fd) + elif(leNdim==1): + str=format%(cbuf[0].real, cbuf[0].imag) + for I in range(1,Ndim[0]): + str+=delimiter+format%(cbuf[I].real, cbuf[I].imag) + print(str,file=fd) + else: + assert False,"" +def readwritezN_writeone_(fpath,zbuf,Append=False,header=None,iverbose=1): + fd=open(fpath,('a' if(Append) else 'w')) + Ndim=np.shape(zbuf);leNdim=len(Ndim) + if(header is not None): + print_00(header,file=fd); + if(leNdim<=2): + readwritezN_writeblock_(fd,cbuf=zbuf) + elif(leNdim==3): + for I in range(Ndim[0]): + print_00( ('\n\n\n' if(I>0) else '')+'###%05d:%04d'%(I,I),file=fd) + readwritezN_writeblock_(fd,cbuf=zbuf[I]) + elif(leNdim==4): + IxJ=-1 + for I in range(Ndim[0]): + for J in range(Ndim[1]): + IxJ+=1 + print( ('\n\n\n' if(IxJ>0) else '')+'###%05d:%04d,%04d'%(IxJ,I,J),file=fd) + readwritezN_writeblock_(fd,cbuf=zbuf[I][J]) + elif(leNdim==5): + IxJ=-1 + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + IxJ+=1 + print( ('\n\n\n' if(IxJ>0) else '')+'###%05d:%04d,%04d,%04d'%(IxJ,I,J,K),file=fd) + readwritezN_writeblock_(fd,cbuf=zbuf[I][J][K]) + else: + assert False,"Ndim:"+str(Ndim) + +def readwritezN_readone_(fpath,sbuf,Ndim=None,iverbose=1): + ## [ ndArray, ... ] + sbuf.clear() + fd=open(fpath,'r') + Ret=[];nblock=0 + cbuf=None;nblank=0;commentlines="";ncl=0 + for line0 in fd: + line=line0.strip() + le=len(line) + if(le<1): + nblank+=1;continue + if(line.startswith('#')): + commentlines+=("" if(ncl==0) else "\n")+line;continue + else: + if(nblank>1): + if(cbuf is not None): + if(iverbose>1): + print_00( "#read:%05d th block(%s) in file:%s"%(len(Ret),commentlines,fpath) ) + Ret.append(np.array(cbuf));sbuf.append(commentlines); + cbuf=None;nblock+=1 + nblank=0;commentlines="";ncl=0 + carr=parse_complexes(line); + assert carr is not None,"" + if( cbuf is None ): + cbuf= []; + cbuf.append(carr) + fd.close() + if(cbuf is not None): + Ret.append(np.array(cbuf));sbuf.append(commentlines); + if(Ndim is not None): + Ret=np.reshape(Ret,Ndim) + return Ret; + +def dN_to_str(arr,format="%20.12f",delimiter=' ',bra='[',ket=']'): + Ndim=np.shape(arr);leNdim=len(Ndim) + ret="" + if(leNdim==1): + le=Ndim[0]; + for J in range(le): + ret+=("" if(J==0) else delimiter)+format%(arr[J]) + elif(leNdim==2): + for I in range(Ndim[0]): + row="" + for J in range(Ndim[1]): + row+=("" if(J==0) else delimiter)+format%(arr[I][J]) + ret+=bra+row+ket + return bra+ret+ket + + +def xassertf(bool,msg,lvl): + if(bool): + return 0 + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank(); MPIsize=comm.Get_size() + fd=open("assertion_%02d_warning.log"%(MPIrank),"a") + msg+=' \t\t'+str(datetime.datetime.now()) + print(msg,file=fd); + print("#!W py assertion failed:"+msg); + if(lvl<0): + assert False,"" + +def calc_trDM1(MO_coefs,MO_occ,pbc,rttddft): + ## MOcofs[nKpt][nAO][nMO] mo_occ[nKpt][nMO] + wct00=time.time() + Ndim_MOcofs=np.shape(MO_coefs) + Ndim_MOocc =np.shape(MO_occ) + if( pbc ): + assert len(Ndim_MOcofs)==3 and len(Ndim_MOocc)==2,"" + nKpt=Ndim_MOcofs[0];nAO=Ndim_MOcofs[1];nMO=Ndim_MOcofs[2] + else: + assert len(Ndim_MOcofs)==2 and len(Ndim_MOocc)==1,"" + nKpt=1;nAO=Ndim_MOcofs[0];nMO=Ndim_MOcofs[1] + + S1e = (None if(pbc) else rttddft.get_ovlp()) + kvectors = (None if (not pbc) else np.reshape( rttddft.kpts, (-1,3))) + + ret=0.0 + for kp in range(nKpt): + coefs=( MO_coefs if(not pbc) else MO_coefs[kp] ) + occ =( MO_occ if(not pbc) else MO_occ[kp] ) + if( pbc ): + S1e=rttddft.get_ovlp( rttddft.cell, kvectors[kp]) + dm1=np.matmul( coefs, np.matmul( np.diag(occ), np.matrix.getH(coefs))) +# dm1=np.zeros([nAO,nAO],dtype=np.complex128) +# for el in range(nMO): +# for mu in range(nAO): +# for nu in range(nAO): +# dm1[mu][nu] += coefs[mu,el] * occ[el] * np.conj( coefs[nu,el] ) + DxS=np.matmul(dm1,S1e) + trDM1=matrixTrace(DxS) + ret=ret+trDM1.real + if(pbc): + ret=ret/float(nKpt) + wct99=time.time();print("trDM1:elapsed %f"%(wct99-wct00)) + return ret + +def normalize(A): + le=len(A) + cum=0.0 + dtype=np.array(A).dtype + if( dtype == np.float64 or dtype==float ): + for I in range(le): + cum+=A[I]**2 + else: + for I in range(le): + cum+=A[I].real**2 + A[I].imag**2 + norm=np.sqrt(cum);fac=1.0/norm + return np.array( [ A[I]*fac for I in range(le) ] ) + +def maxdiff_zbufs_(Lhs,Rhs,Ndim=None): + if(Ndim is None): + Ndim=np.shape(Lhs); + lh=np.ravel(Lhs);rh=np.ravel(Rhs); + le=len(lh);lerh=len(rh); + if( lerh != le ): + print_00("!E:length differs:%d/%d"%(le,lerh)); + return None,None,None,None + maxdiff=-1;Iat=-1;values=None;sqrdiffsum=0.0 + for I in range(le): + dum=abs(lh[I]-rh[I]);sqrdiffsum+=dum*dum + if(maxdiff devmax ): + devmax=dum; at=[dir,kp,I,J]; vals=[ mat[I][J], mat[J][I] ] + if( dum > tol ): + ndev+=1 + else: + for I in range(ndim[0]): + for J in range(I+1): + dum=abs( np.conj(mat[J][I])+mat[I][J] ) ## for I==J, this is abs(real) .. + devsum+=dum**2 + if( dum > devmax ): + devmax=dum; at=[dir,kp,I,J]; vals=[ mat[I][J], mat[J][I] ] + if( dum > tol ): + ndev+=1 + if(Dic is not None): + Dic.update({"ndev":ndev,"devmax":devmax,"at":at,"devsum":devsum,"values":vals}) + if(ndev>0): + print("#check_Hermicity:failed:%s:Ndev:%d"%(title,ndev)\ + +str({"ndev":ndev,"devmax":devmax,"at":at,"devsum":devsum,"values":vals})) + return ndev; + +def calc_3Dvolume(Vectors): + vecs=np.reshape( Vectors, [3,3] ) + axb= AxB( vecs[0], vecs[1] ) + retv= np.vdot( vecs[2], axb ) + return retv + +def toComplexArray(src): + if( np.array(src).dtype == complex ): + print_00("#toComplexArray:is complex"); + return src + if( np.array(src).dtype == np.complex128 ): + print_00("#toComplexArray:is complex128"); + return src + Ndim=np.shape(src) + ret=np.zeros( Ndim, dtype=np.complex128 ) + rank=len(Ndim) + if( rank==1 ): + for I in range(Ndim[0]): + ret[I]=src[I] + elif(rank==2): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + ret[I][J]=src[I][J] + elif(rank==3): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + ret[I][J][K] = src[I][J][K] + elif(rank==4): + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + for L in range(Ndim[3]): + ret[I][J][K][L] = src[I][J][K][L] + else: + assert False,"unimplemented" + return ret + +def print_z2array_(fpath,A,Append=False,header=None): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if(MPIrank!=0): + return + + fd=open(fpath,('a' if(Append) else 'w')); + if( header is not None ): + print(header,file=fd); + Ndim=np.shape(A) + assert len(Ndim)<=2,"" + if( len(Ndim)==2 ): + for I in range(Ndim[0]): + string="" + for J in range(Ndim[1]): + string+="%12.6f %12.6f "%(A[I][J].real,A[I][J].imag) + print(string,file=fd) + elif( len(Ndim)==1 ): + string="" + for J in range(Ndim[0]): + string+="%12.6f %12.6f "%(A[J].real,A[J].imag) + print(string,file=fd) + fd.close() + +def print_z2array(fpath,A,comment="",Append=False): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if(MPIrank!=0): + return + + Ndim=np.shape(A);header=None + leNdim=len(Ndim) + if( leNdim<=2 ): + if( comment is not None ): + header='#'+str(comment)+" Ndim:"+str(Ndim) + print_z2array_(fpath,A,Append=Append,header=header) + elif( leNdim==3 ): + for I in range(Ndim[0]): + header=( '#'+comment+'\n##%03d '%(I)+comment+" Ndim:"+str(Ndim) if(I==0) else '\n\n\n##%03d '%(I)) + print_z2array_(fpath,A[I],Append=(True if(I>0) else Append),header=header) + elif( leNdim==4 ): + IxJ=-1 + for I in range(Ndim[0]): + for J in range(Ndim[1]): + IxJ+=1 + header=('#'+comment+" Ndim:"+str(Ndim)+'\n##%05d:%02d,%02d '%(IxJ,I,J) if(IxJ==0) else + '\n\n\n##%05d:%02d,%02d '%(IxJ,I,J)) + print_z2array_(fpath,A[I][J],Append=(True if(IxJ>0) else Append),header=header) + elif( leNdim==5 ): + IxJxK=-1 + for I in range(Ndim[0]): + for J in range(Ndim[1]): + for K in range(Ndim[2]): + IxJxK+=1 + header=('#'+comment+" Ndim:"+str(Ndim)+'\n##%05d:%02d,%02d,%02d '%(IxJxK,I,J,K) if(IxJxK==0) else + '\n\n\n##%05d:%02d,%02d,%02d '%(IxJxK,I,J,K)) + print_z2array_(fpath,A[I][J][K],Append=(True if(IxJxK>0) else Append),header=header) + else: + assert False,"" +def dist3D(a,b): + return np.sqrt( (a[0]-b[0])**2 + (a[1]-b[1])**2 + (a[2]-b[2])**2 ) +def AxB(A,B): + return np.array([ A[1]*B[2] - A[2]*B[1], + A[2]*B[0] - A[0]*B[2], + A[0]*B[1] - A[1]*B[0] ]) + +def open_00(fpath,mode,default=None): + comm = MPI.COMM_WORLD; MPIrank = comm.Get_rank() + if(MPIrank!=0): + if(default is None): + return None + elif(isinstance(default,str) and default == "dummy"): + return open("dummy.log",mode) + else: + return default; + return open(fpath,mode) + +def close_00(fd): + if( fd is None ): + return + elif( fd == sys.stdout ): + return + else: + fd.close();return + +def z1maxloc(arr): + N=len(arr) + mxv=-1.0;at=None + for k in range(N): + a=abs(arr[k]) + if( mxv < a ): + mxv=a;at=k + return at + +def check_wfNorm(rttddft,pbc,wfn,AOrep,sqrdevtol_FIX=1.0e-6,title=""): + Ndim=np.shape(wfn) + if( len(Ndim)==2 ): + nkpt=1;nAO=Ndim[0];nMO=Ndim[1]; + elif( len(Ndim)==3 ): + nkpt=Ndim[0];nAO=Ndim[1];nMO=Ndim[2] + else: + assert False,"" + + sqrNorms=np.zeros(nMO) + kvectors = (None if (not pbc) else np.reshape( rttddft.kpts, (-1,3))) + maxdev=-1.0; Nfix=0 + for kp in range(nkpt): + if(AOrep): + if( not pbc ): + tgt=wfn; S1e=rttddft.get_ovlp() + else: + tgt=wfn[kp]; S1e=rttddft.get_ovlp( rttddft.cell, kvectors[kp]) + for I in range(nMO): + sqrNorms[I]=np.vdot( tgt[:,I], np.matmul( S1e, tgt[:,I] ) ).real + dev = abs( sqrNorms[I]-1.0 ) + if( dev > maxdev ): + maxdev = dev + if( sqrdevtol_FIX>=0 and dev > sqrdevtol_FIX ): + fac=1.0/np.sqrt( sqrNorms[I] );Nfix+=1 + for K in range(nAO): + tgt[K][I]=tgt[K][I]*fac + else: + if( not pbc ): + tgt=wfn; + else: + tgt=wfn[kp]; + for I in range(nMO): + sqrNorms[I]=np.vdot( tgt[:,I], tgt[:,I] ).real + dev = abs( sqrNorms[I]-1.0 ) + if( dev > maxdev ): + maxdev = dev + if( sqrdevtol_FIX>=0 and dev > sqrdevtol_FIX ): + fac=1.0/np.sqrt( sqrNorms[I] );Nfix+=1 + for K in range(nAO): + tgt[K][I]=tgt[K][I]*fac + +## logger.Info("#orth_tdMO:%s sqrdevMax:%e Nfix:%d/%d"%(title,maxdev,Nfix,nMO)); + +def a2sqrdiff(lhs,rhs,DAG_OFDdev=None): + Ndim=np.shape(lhs) + Ndim2=np.shape(rhs) + assert i1eqb(Ndim,Ndim2),"" + DAGdev=-1;OFDdev=-1;DAGref=None;OFDref=None + cum=0.0 + for I in range(Ndim[0]): + for J in range(Ndim[1]): + cdum=lhs[I][J]-rhs[I][J] + sqrDiff= cdum.real**2 + cdum.imag**2 + diff= np.sqrt(sqrDiff) + if(I==J): + if(DAGdev1): + w_fac=1.0/float(nkpt) + for ith in range(bfsz): + w_sorted[ith]=w_sorted[ith]*w_fac + eorb_min_eV=e_eV_sorted[0] + eorb_max_eV=e_eV_sorted[bfsz-1] + + daf_eorbs=filename+"_eorbs.dat" + fd=open(daf_eorbs,("a" if(iappend!=0) else "w")) + if( fileheader is not None): + print(fileheader,file=fd); + print("#%19s %20s %5s %5s %5s"%("eorb_eV","weight","sp","kp","mo"),file=fd) + for ith in range(bfsz): + print("%20.10f %20.10f %5d %5d %5d"%(e_eV_sorted[ith],w_sorted[ith], + i_sorted[ith][0],i_sorted[ith][1],i_sorted[ith][2]),file=fd) + if(trailer is not None): + print(trailer,file=fd) + fd.close() + + if( (de_eV is None) and (Nstep is None ) ): + min_w=min(widths_eV) + de_eV=( 0.25*min_w if(min_w<0.1) else 0.1*min_w ) + max_w=max(widths_eV) + if( margin_eV is None ): + margin_eV=max( 2*max_w, (8.0 if de_eV is None else de_eV*20) ) + printout("#calc_ldos:margin_eV:%f %f %f %f"%(margin_eV,2*max_w,8.0,de_eV*20)) + if( emin_eV is None ): + emin_eV= eorb_min_eV - margin_eV + if( emax_eV is None ): + emax_eV= eorb_max_eV + margin_eV + + if( de_eV is not None): + Nstep=int(math.ceil((emax_eV-emin_eV)/de_eV)) + elif( Nstep is not None): + de_eV=(emax_eV-emin_eV)/float(Nstep) + printout("#calc_ldos:Nstep:%d de_eV:%f"%(Nstep,de_eV)) + + sqrt2pi=2.506628274631000502415765284811 + daf_ldos=filename+"_ldos.dat" + fd=open( daf_ldos,("a" if(iappend!=0) else "w")) + if( header is not None): + print(header,file=fd); + e_eV=emin_eV + wgt_ref=(1.0 if(spinrestriction=='U') else 2.0)/(1.0 if(not pbc) else float(nkpt)) + wgsum = sum(w_sorted); + print("#calc_ldos:wgsum:%f"%(wgsum)) + if( N_elec is not None): + assert abs(N_elec-wgsum)<1.0e-3,"" + ## exp(-0.5*((e_eV-ej_eV)/wid)**2) + Nwid=len(widths_eV) + nrmz_factors=[ 1.0/(sqrt2pi*widths_eV[kwid]) for kwid in range(Nwid) ] + fn=[ 0.0 for kwid in range(Nwid) ] + fn_occ=[ 0.0 for kwid in range(Nwid) ] + cum=[ 0.0 for kwid in range(Nwid) ] + cum_occ=[ 0.0 for kwid in range(Nwid) ] + + I0=-1 + for I in range(Nstep): + e_eV=emin_eV + I*de_eV + for kwid in range(Nwid): + fn[kwid]=0.0; fn_occ[kwid]=0.0 + for js in range(bfsz): + arg=-0.5*( ((e_eV-e_eV_sorted[js])/widths_eV[kwid])**2 ) + if(arg0): + print("#original mesh:"+str(fftdf.mesh),file=fdLOG) + for k in range(3): + fftdf.mesh[k]=fftdf.mesh[k]*scale_FFTmesh + print("#revised mesh:"+str(fftdf.mesh),file=fdLOG) + extension="meshszX%d"%(scale_FFTmesh) + if(scale_FFTcutoff>0): + print("#original cutoff:%s mesh:"%(str(cell.ke_cutoff))+str(fftdf.mesh),file=fdLOG) + if( cell.ke_cutoff is not None ): + cell.ke_cutoff=cell.ke_cutoff*scale_FFTcutoff + cell.build() + else: + cell.build() + for k in range(3): + cell.mesh[k]=cell.mesh[k]*scale_FFTcutoff + print("expanding.mesh:",cell.mesh,file=fdLOG) + print("cell.mesh:",cell.mesh,file=fdLOG) + fftdf = df.FFTDF(cell) + print("fftdf.mesh:",fftdf.mesh,file=fdLOG) + print("#revised cutoff:%s mesh:"%(str(cell.ke_cutoff))+str(fftdf.mesh),file=fdLOG) + extension="cutoffX%d"%( scale_FFTcutoff ) + fftdf.kpts= kpts + scf.with_df=fftdf + ### scf.kernel() + for Ia in range(nA): + AoverC=AoverC_al[Ia] + pp=with_fftdf_get_pp(scf.with_df,AoverC,kpts=kpts, calc_vppnl_by_k=False) + ppFFTDFal.append(pp) + for Ia in range(nA): + AoverC=AoverC_al[Ia] + pp=with_fftdf_get_pp(scf.with_df,AoverC,kpts=kpts, calc_vppnl_by_k=True) + ppFFTDFalB.append(pp) + + for Ia in range(nA): + AoverC=AoverC_al[Ia] + diff=aNmaxdiff(ppGDFal[Ia],ppFFTDFal[Ia]) + print(" %3d %14.4e"%(Ia,diff),file=fdLOG) + print_Hmatrices_1("#%03d:"%(Ia)+str(AoverC), ppGDFal[Ia],ppFFTDFal[Ia], Nref=5, + fpath="comp_ppMat%s%03d%s.log"%(ver,Ia,extension), Append=False,TINY=1.0e-8) + for Ia in range(nA): + AoverC=AoverC_al[Ia] + diff=aNmaxdiff(ppFFTDFal[Ia],ppFFTDFalB[Ia]) + print("calc_vppnl_by_k: %3d %14.4e"%(Ia,diff),file=fdLOG) + print_Hmatrices_1("#%03d:"%(Ia)+str(AoverC), ppGDFal[Ia],ppFFTDFal[Ia], Nref=5, + fpath="comp_ppMat%s%03d%s.log"%(ver,Ia,extension), Append=True,TINY=1.0e-8) + + fdLOG.close() + os.system("ls -ltrh comp_ppMat%s*.log"%(ver)) + +def with_fftdf_get_pp(mydf, AoverC, kpts=None, calc_vppnl_by_k=False): + '''Get the periodic pseudotential nuc-el AO matrix, with G=0 removed. + ''' + assert isinstance(AoverC,numpy.ndarray),"AoverC" + from pyscf import gto + cell = mydf.cell + if kpts is None: + kpts_lst = numpy.zeros((1,3)) + else: + kpts_lst = numpy.reshape(kpts, (-1,3)) + + mesh = mydf.mesh + SI = cell.get_SI() + Gv = cell.get_Gv(mesh) + vpplocG = pseudo.get_vlocG(cell, Gv) + vpplocG = -numpy.einsum('ij,ij->j', SI, vpplocG) + ngrids = len(vpplocG) + + # vpploc evaluated in real-space + vpplocR = tools.ifft(vpplocG, mesh).real + vpp = [0] * len(kpts_lst) + for ao_ks_etc, p0, p1 in mydf.aoR_loop(mydf.grids, kpts_lst): + ao_ks = ao_ks_etc[0] + for k, ao in enumerate(ao_ks): + vpp[k] += lib.dot(ao.T.conj()*vpplocR[p0:p1], ao) + ao = ao_ks = None + + # vppnonloc evaluated in reciprocal space + fakemol = gto.Mole() + fakemol._atm = numpy.zeros((1,gto.ATM_SLOTS), dtype=numpy.int32) + fakemol._bas = numpy.zeros((1,gto.BAS_SLOTS), dtype=numpy.int32) + ptr = gto.PTR_ENV_START + fakemol._env = numpy.zeros(ptr+10) + fakemol._bas[0,gto.NPRIM_OF ] = 1 + fakemol._bas[0,gto.NCTR_OF ] = 1 + fakemol._bas[0,gto.PTR_EXP ] = ptr+3 + fakemol._bas[0,gto.PTR_COEFF] = ptr+4 + + # buf for SPG_lmi upto l=0..3 and nl=3 + buf = numpy.empty((48,ngrids), dtype=numpy.complex128) + def vppnl_by_k(kpt,AoverC): +#.0 Gk = Gv + kpt + AoverC +#.0 G_rad = lib.norm(Gk, axis=1) + Gk = Gv + kpt + G_rad = lib.norm(Gk, axis=1) + Gk = Gv + kpt + AoverC + aokG = ft_ao.ft_ao(cell, Gv, kpt=kpt) * (1/cell.vol)**.5 ## .1:with kpt+AoverC >> wrong !! + vppnl = 0 + for ia in range(cell.natm): + symb = cell.atom_symbol(ia) + if symb not in cell._pseudo: + continue + pp = cell._pseudo[symb] + p1 = 0 + for l, proj in enumerate(pp[5:]): + rl, nl, hl = proj + if nl > 0: + fakemol._bas[0,gto.ANG_OF] = l + fakemol._env[ptr+3] = .5*rl**2 + fakemol._env[ptr+4] = rl**(l+1.5)*numpy.pi**1.25 + pYlm_part = fakemol.eval_gto('GTOval', Gk) + + p0, p1 = p1, p1+nl*(l*2+1) + # pYlm is real, SI[ia] is complex + pYlm = numpy.ndarray((nl,l*2+1,ngrids), dtype=numpy.complex128, buffer=buf[p0:p1]) + for k in range(nl): + qkl = pseudo.pp._qli(G_rad*rl, l, k) + pYlm[k] = pYlm_part.T * qkl + #:SPG_lmi = numpy.einsum('g,nmg->nmg', SI[ia].conj(), pYlm) + #:SPG_lm_aoG = numpy.einsum('nmg,gp->nmp', SPG_lmi, aokG) + #:tmp = numpy.einsum('ij,jmp->imp', hl, SPG_lm_aoG) + #:vppnl += numpy.einsum('imp,imq->pq', SPG_lm_aoG.conj(), tmp) + if p1 > 0: + SPG_lmi = buf[:p1] + SPG_lmi *= SI[ia].conj() + SPG_lm_aoGs = lib.zdot(SPG_lmi, aokG) + p1 = 0 + for l, proj in enumerate(pp[5:]): + rl, nl, hl = proj + if nl > 0: + p0, p1 = p1, p1+nl*(l*2+1) + hl = numpy.asarray(hl) + SPG_lm_aoG = SPG_lm_aoGs[p0:p1].reshape(nl,l*2+1,-1) + tmp = numpy.einsum('ij,jmp->imp', hl, SPG_lm_aoG) + vppnl += numpy.einsum('imp,imq->pq', SPG_lm_aoG.conj(), tmp) + return vppnl * (1./cell.vol) + + ABS_AoverC_TINY=1.0e-10 + wt00=time.time();wt01=wt00;wt02=wt01 + + wt_A=0 + vppnl_al=None + if(not calc_vppnl_by_k): + vppnl_al=get_pp_nl01(cell, AoverC, kpts_lst) + wt02=wt01;wt01=time.time(); wt_A=wt01-wt00 + + abs_A_over_c = numpy.sqrt( AoverC[0]**2 + AoverC[1]**2 + AoverC[2]**2 ) + for k, kpt in enumerate(kpts_lst): + if( calc_vppnl_by_k ): + wt01=time.time(); + vppnl = vppnl_by_k(kpt,AoverC) + wt02=wt01;wt01=time.time();wt_A+=(wt01-wt02) + else: + vppnl = vppnl_al[k] + if gamma_point(kpt): + if( abs_A_over_c < ABS_AoverC_TINY ): + vpp[k] = vpp[k].real + vppnl.real + else: + vpp[k] = vpp[k].real + vppnl + else: + vpp[k] += vppnl + + printout("ppnl%s:%f"%( ("_by_k" if(calc_vppnl_by_k) else "_lib"), wt_A),fpath="ppnl_walltime.log",\ + Append=True) + + if kpts is None or numpy.shape(kpts) == (3,): + vpp = vpp[0] + return numpy.asarray(vpp) + +def print_Hmatrices_1(title,A,B,Nref=5,fpath=None,Append=False,TINY=1.0e-8): + + fdOU=(None if(fpath is None) else open(fpath,("a" if(Append) else "w")) ) + fd=( fdOU if(fdOU is not None) else sys.stdout) + if( Append ): + print("\n\n",file=fd) + Ndim=numpy.shape(A) + rank=len(Ndim) + if(rank==2): + print_Hmatrices_1_(fd,title,A,B,Nref=Nref,TINY=TINY) + elif(rank==3): + for kp in range(Ndim[0]): + print_Hmatrices_1_(fd,"kp=%02d "%(kp)+title,A[kp],B[kp],Nref=Nref,TINY=TINY) + print("\n\n",file=fd) + if(fdOU is not None): + fdOU.close() + +def print_Hmatrices_1_(fd,title,A,B,Nref=5,TINY=1.0e-8): + + + maxdiff=aNmaxdiff(A,B) + + max_Im=-1;where=None + Ndim=numpy.shape(A) + assert len(Ndim)==2,"Ndim="+str(Ndim)+" len(Ndim)/=2" + Nrow=Ndim[0];Ncol=Ndim[1] + for I in range(Nrow): + for J in range(Ncol): + if(max_Im Date: Sun, 4 May 2025 23:03:36 -0700 Subject: [PATCH 2/2] add lapack in ci --- .github/workflows/run_ci.sh | 1 + pyscf/lib/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run_ci.sh b/.github/workflows/run_ci.sh index 5531b7103..6f26a2df2 100755 --- a/.github/workflows/run_ci.sh +++ b/.github/workflows/run_ci.sh @@ -5,6 +5,7 @@ set -e sudo apt-get -qq install \ gcc \ libblas-dev \ + liblapack-dev \ cmake \ curl diff --git a/pyscf/lib/CMakeLists.txt b/pyscf/lib/CMakeLists.txt index bdea6a730..d7750ec96 100644 --- a/pyscf/lib/CMakeLists.txt +++ b/pyscf/lib/CMakeLists.txt @@ -68,7 +68,7 @@ endif (MKL) #link_directories ($ENV{LD_LIBRARY_PATH}) find_package(BLAS REQUIRED) -#find_package (LAPACK REQUIRED) +find_package (LAPACK REQUIRED) # OpenMP option(ENABLE_OPENMP "Compiling C extensions with openmp" ON)