def get_veff(ks, mol=None, dm=None, dm_last=0, vhf_last=0, hermi=1): if getattr(dm, 'mo_coeff', None) is not None: mo_coeff = dm.mo_coeff mo_occ_a = (dm.mo_occ > 0).astype(numpy.double) mo_occ_b = (dm.mo_occ ==2).astype(numpy.double) dm = lib.tag_array(dm, mo_coeff=(mo_coeff,mo_coeff), mo_occ=(mo_occ_a,mo_occ_b)) return uks.get_veff(ks, mol, dm, dm_last, vhf_last, hermi)
def get_veff(ks, mol=None, dm=None, dm_last=0, vhf_last=0, hermi=1): if getattr(dm, 'mo_coeff', None) is not None: mo_coeff = dm.mo_coeff mo_occ_a = (dm.mo_occ > 0).astype(numpy.double) mo_occ_b = (dm.mo_occ == 2).astype(numpy.double) dm = lib.tag_array(dm, mo_coeff=(mo_coeff, mo_coeff), mo_occ=(mo_occ_a, mo_occ_b)) return uks.get_veff(ks, mol, dm, dm_last, vhf_last, hermi)
def get_flosic_veff(ks, mol=None, dm=None, dm_last=0, vhf_last=0, hermi=1): # pyscf standard call for scf cycle 0. veff = uks.get_veff(ks=ks.calc_uks, mol=ks.mol, dm=dm, dm_last=dm_last, vhf_last=vhf_last, hermi=hermi) if mol is None: mol = ks.mol # Build the hamiltonian to get the KS wave functions. dim = np.shape(ks.calc_uks.mo_coeff) s1e = ks.get_ovlp(mol) h1e = ks.get_hcore(mol) hamil = ks.get_fock(h1e, s1e, vhf_last, dm) # Get the KSO. ks_new = np.zeros((2, dim[1], dim[1]), dtype=np.float64) try: if dm_last == 0: # First SCF cycle: do nothing. pass except: # Every other DFT cycle: Build the KS wavefunctions with the Hamiltonian, then give them to the UKS object that is the input for flosic. trash, ks_new = ks.eig(hamil, s1e) ks_inter = np.array(ks_new) # Update UKS object. ks.calc_uks.mo_coeff = ks_inter.copy() # If ldax is enabled, the xc functional is set to LDA exchange only. if ks.ldax == True: xc_sav = ks.calc_uks.xc ks.calc_uks.xc = 'LDA,' # Call the FLOSIC routine with the UKS object. # This for the fixed Vsic modus. # If Vsic values are present and the Vsic potential should not # be updated use these values. # (THa: the outer if ... clause was added to prevent the # sic potentials to be calculated during initialization) _t0 = time.time() #print('>> ks.fixed_vsic', ks.fixed_vsic) #print('>>', ks.neval_vsic) #sys.exit() if ks.neval_vsic > -1: if ks.fixed_vsic != 0.0 and (ks.num_iter % ks.vsic_every) != 0: if ks.verbose >= 4: print('Use fixed Vsic (cycle = %i)' % ks.num_iter) flo_veff = flosic(ks.mol, ks.calc_uks, ks.fod1, ks.fod2,\ datatype=np.float64,calc_forces=ks.calc_forces,debug=ks.debug,\ nuclei=ks.nuclei,l_ij=ks.l_ij,ods=ks.ods,\ fixed_vsic=ks.fixed_vsic,ham_sic=ks.ham_sic) # If no Vsic values are present or the the Vsic values should be # updated calcualte new Vsic values. # !! THa: Possible BUG # ks.fixed_vsic == 0.0 may never be 'True' because # a float-value is amost never exactly zero # better use: np.isclose(ks.fixed_vsic, 0.0) # !! if ks.fixed_vsic == 0.0 or (ks.num_iter % ks.vsic_every) == 0: if ks.verbose >= 4: print('Calculate new Vsic (cycle = %i)' % ks.num_iter) flo_veff = flosic(ks.mol,ks.calc_uks,ks.fod1,ks.fod2,\ datatype=np.float64,calc_forces=ks.calc_forces,debug=ks.debug,\ nuclei=ks.nuclei,l_ij=ks.l_ij,ods=ks.ods,ham_sic=ks.ham_sic) ks.fixed_vsic = flo_veff['fixed_vsic'] else: flo_veff = veff _t1 = time.time() if mol.verbose > 3: print("FLO-SIC time for SIC potential: {0:0.1f} [s]".format(_t1 - _t0)) # increase a magic counter ks.num_iter = ks.num_iter + 1 # If ldax is enabled, the change to xc is only meant for the FLO-SIC part and # therefore has to be changed back. if ks.ldax == True: ks.calc_uks.xc = xc_sav # Assign the return values. # The total energies of DFT and FLO-SIC if ks.neval_vsic > -1: sic_etot = flo_veff['etot_sic'] dft_etot = flo_veff['etot_dft'] # The FLOs. ks.flo = flo_veff['flo'] # The FOD forces. ks.fforces = flo_veff['fforces'] # The FLO-SIC H**O energy eigenvalue. ks.homo_flosic = flo_veff['homo_sic'] ks.evalues = flo_veff['evalues'] ks.lambda_ij = flo_veff['lambda_ij'] # Developer modus: atomic forces (AF) if ks.debug == True: ks.AF = flo_veff['AF'] else: sic_etot = ks.e_tot dft_etot = ks.e_tot ks.flo = ks.mo_coeff ks.homo_flosic = 0.0 try: # First SCF cycle: veff = veff_dft and the SIC is zero. if dm_last == 0: sic_veff = veff sic_etot = dft_etot except: # Every other DFT cycle: Build veff as sum of the regular veff and the SIC # potential. sic_veff = veff + flo_veff['hamil'] # Update the density matrix. dm_new = dynamic_rdm(ks.flo, ks.calc_uks.mo_occ) dm = dm_new.copy() ks.mo_coeff = ks.flo # Give back the FLO-SIC energy correction and the corrected potential. This libtagarray # formalism is defined by pyscf. sic_back = sic_etot - dft_etot veff_sic = lib.tag_array(sic_veff, ecoul=veff.ecoul, exc=veff.exc, vj=veff.vj, vk=veff.vk, esic=(sic_back)) # Return the exchange-correlation energy and the FLO-SIC energy correction. ks.exc = veff.exc ks.esic = sic_back # increase another magic counter ;-) ks.neval_vsic += 1 return veff_sic