def kernel(self, mo_coeff=None, ci0=None, macro=None, micro=None, callback=None, _kern=None): if mo_coeff is None: mo_coeff = self.mo_coeff else: self.mo_coeff = mo_coeff if macro is None: macro = self.max_cycle_macro if micro is None: micro = self.max_cycle_micro if callback is None: callback = self.callback if _kern is None: _kern = mc1step.kernel if self.verbose > logger.QUIET: pyscf.gto.mole.check_sanity(self, self._keys, self.stdout) self.mol.check_sanity(self) self.dump_flags() casci_symm.label_symmetry_(self, self.mo_coeff) self.converged, self.e_tot, self.e_cas, self.ci, \ self.mo_coeff, self.mo_energy = \ _kern(self, mo_coeff, tol=self.conv_tol, conv_tol_grad=self.conv_tol_grad, macro=macro, micro=micro, ci0=ci0, callback=callback, verbose=self.verbose) logger.note(self, 'CASSCF energy = %.15g', self.e_tot) self._finalize_() return self.e_tot, self.e_cas, self.ci, self.mo_coeff, self.mo_energy
def kernel(self, mo_coeff=None, ci0=None, macro=None, micro=None, callback=None, _kern=kernel): if mo_coeff is None: mo_coeff = self.mo_coeff else: self.mo_coeff = mo_coeff if macro is None: macro = self.max_cycle_macro if micro is None: micro = self.max_cycle_micro if callback is None: callback = self.callback if self.verbose > logger.QUIET: pyscf.gto.mole.check_sanity(self, self._keys, self.stdout) self.mol.check_sanity(self) self.dump_flags() self.converged, self.e_tot, e_cas, self.ci, self.mo_coeff = _kern( self, mo_coeff, tol=self.conv_tol, conv_tol_grad=self.conv_tol_grad, macro=macro, micro=micro, ci0=ci0, callback=callback, verbose=self.verbose, ) logger.note(self, "CASSCF energy = %.15g", self.e_tot) # if self.verbose >= logger.INFO: # self.analyze(mo_coeff, self.ci, verbose=self.verbose) self._finalize_() return self.e_tot, e_cas, self.ci, self.mo_coeff
def kernel(self, mo_coeff=None, ci0=None, macro=None, micro=None, callback=None, _kern=kernel): if mo_coeff is None: mo_coeff = self.mo_coeff else: # overwrite self.mo_coeff because it is needed in many methods of this class self.mo_coeff = mo_coeff if macro is None: macro = self.max_cycle_macro if micro is None: micro = self.max_cycle_micro if callback is None: callback = self.callback if self.verbose > logger.QUIET: pyscf.gto.mole.check_sanity(self, self._keys, self.stdout) self.mol.check_sanity(self) self.dump_flags() self.converged, self.e_tot, self.e_cas, self.ci, \ self.mo_coeff, self.mo_energy = \ _kern(self, mo_coeff, tol=self.conv_tol, conv_tol_grad=self.conv_tol_grad, macro=macro, micro=micro, ci0=ci0, callback=callback, verbose=self.verbose) logger.note(self, 'CASSCF energy = %.15g', self.e_tot) #if self.verbose >= logger.INFO: # self.analyze(mo_coeff, self.ci, verbose=self.verbose) return self.e_tot, self.e_cas, self.ci, self.mo_coeff, self.mo_energy
def makov_payne_correction(mf): '''Makov-Payne correction (Phys. Rev. B, 51, 4014) ''' cell = mf.cell logger.note(mf, 'Makov-Payne correction for charged 3D PBC systems') # PRB 51 (1995), 4014 # PRB 77 (2008), 115139 if cell.dimension != 3: logger.warn(mf, 'Correction for low-dimension PBC systems' 'is not available.') return 0 de_mono, de_dip, de_quad, de = _dip_correction(mf) if mf.verbose >= logger.NOTE: write = mf.stdout.write write('Corrections (AU)\n') write(' Monopole Dipole Quadrupole total\n') write('SC %12.8f %12.8f %12.8f %12.8f\n' % (de_mono[0], de_dip , de_quad , de[0])) write('BCC %12.8f %12.8f %12.8f %12.8f\n' % (de_mono[1], de_dip , de_quad , de[1])) write('FCC %12.8f %12.8f %12.8f %12.8f\n' % (de_mono[2], de_dip , de_quad , de[2])) return de
def ccsd(self, t1=None, t2=None, eris=None, mbpt2=False): '''Ground-state unrestricted (U)CCSD. Kwargs: mbpt2 : bool Use one-shot MBPT2 approximation to CCSD. ''' if eris is None: eris = self.ao2mo(self.mo_coeff) self.eris = eris self.dump_flags() if mbpt2: cctyp = 'MBPT2' self.e_corr, self.t1, self.t2 = self.init_amps(eris) else: cctyp = 'CCSD' self.converged, self.e_corr, self.t1, self.t2 = \ kernel(self, eris, t1, t2, max_cycle=self.max_cycle, tol=self.conv_tol, tolnormt=self.conv_tol_normt, verbose=self.verbose) if self.converged: logger.info(self, 'CCSD converged') else: logger.info(self, 'CCSD not converged') if self._scf.e_tot == 0: logger.note(self, 'E_corr = %.16g', self.e_corr) else: logger.note(self, 'E(%s) = %.16g E_corr = %.16g', cctyp, self.e_tot, self.e_corr) return self.e_corr, self.t1, self.t2
def optimize( self ): r'''Augmented Hessian Newton-Raphson optimization of the localization cost function, using an exact gradient and hessian Returns: The orbital coefficients of the orthonormal localized orbitals, expressed in terms of the AO ''' # To break up symmetrical orbitals flatx = 0.0123 * np.ones( [ self.numVars ], dtype=float ) self.__update_unitary( flatx ) #self.__debug_gradient() #self.__debug_hessian() gradient_norm = 1.0 threshold = 1e-6 iteration = 0 logger.debug(self, "Localizer :: At iteration %d the cost function = %g", iteration, -self.__costfunction()) logger.debug(self, "Localizer :: Linear size of the augmented Hessian = %d", self.numVars+1) while ( gradient_norm > threshold ): iteration += 1 augmented = np.zeros( [ self.numVars+1, self.numVars+1 ], dtype=float ) gradient = self.__gradient() augmented[:-1,:-1] = self.__hessian() augmented[:-1,self.numVars] = gradient augmented[self.numVars,:-1] = gradient if ( self.numVars+1 > 1024 ): ini_guess = np.zeros( [self.numVars+1], dtype=float ) ini_guess[ self.numVars ] = 1.0 for elem in range( self.numVars ): ini_guess[ elem ] = - gradient[ elem ] / max( augmented[ elem, elem ], 1e-6 ) eigenval, eigenvec = scipy.sparse.linalg.eigsh( augmented, k=1, which='SA', v0=ini_guess, ncv=1024, maxiter=(self.numVars+1) ) flatx = eigenvec[:-1] / eigenvec[ self.numVars ] else: eigenvals, eigenvecs = np.linalg.eigh( augmented ) idx = eigenvals.argsort() eigenvals = eigenvals[idx] eigenvecs = eigenvecs[:,idx] flatx = eigenvecs[:-1,0] / eigenvecs[self.numVars,0] gradient_norm = np.linalg.norm( gradient ) update_norm = np.linalg.norm( flatx ) self.__update_unitary( flatx ) logger.debug(self, "Localizer :: gradient norm = %g", gradient_norm) logger.debug(self, "Localizer :: update norm = %g", update_norm) logger.debug(self, "Localizer :: At iteration %d the cost function = %g", iteration, -self.__costfunction()) logger.note(self, "Localization procedure converged in %d iterations.", iteration) self.__reorder_orbitals() converged_coeff = np.dot( self.coeff, self.u ) return converged_coeff
def kernel(self, mo1=None): if len(self.nuc_pair) == 0: return cput0 = (time.clock(), time.time()) self.check_sanity() self.dump_flags() mol = self.mol dm0 = self._scf.make_rdm1() mo_coeff = self._scf.mo_coeff mo_occ = self._scf.mo_occ ssc_dia = self.make_dso(mol, dm0) if mo1 is None: mo1 = self.mo10 = self.solve_mo1()[0] ssc_pso = self.make_pso(mol, mo1, mo_coeff, mo_occ) e11 = ssc_dia + ssc_pso if self.with_fcsd: ssc_fcsd = self.make_fcsd(self.nuc_pair) e11 += ssc_fcsd elif self.with_fc: ssc_fc = self.make_fc(self.nuc_pair) e11 += ssc_fc logger.timer(self, 'spin-spin coupling', *cput0) if self.verbose > logger.QUIET: nuc_mag = .5 * (nist.E_MASS/nist.PROTON_MASS) # e*hbar/2m au2Hz = nist.HARTREE2J / nist.PLANCK #logger.debug('Unit AU -> Hz %s', au2Hz*nuc_mag**2) iso_ssc = au2Hz * nuc_mag ** 2 * numpy.einsum('kii->k', e11) / 3 natm = mol.natm ktensor = numpy.zeros((natm,natm)) for k, (i, j) in enumerate(self.nuc_pair): ktensor[i,j] = ktensor[j,i] = iso_ssc[k] if self.verbose >= logger.DEBUG: _write(self.stdout, ssc_dia[k]+ssc_para[k], '\nSSC E11 between %d %s and %d %s' \ % (i, self.mol.atom_symbol(i), j, self.mol.atom_symbol(j))) # _write(self.stdout, ssc_dia [k], 'dia-magnetism') # _write(self.stdout, ssc_para[k], 'para-magnetism') gyro = rhf_ssc._atom_gyro_list(mol) jtensor = numpy.einsum('ij,i,j->ij', ktensor, gyro, gyro) label = ['%2d %-2s'%(ia, mol.atom_symbol(ia)) for ia in range(natm)] logger.note(self, 'Reduced spin-spin coupling constant K (Hz)') tools.dump_mat.dump_tri(self.stdout, ktensor, label) logger.info(self, '\nNuclear g factor %s', gyro) logger.note(self, 'Spin-spin coupling constant J (Hz)') tools.dump_mat.dump_tri(self.stdout, jtensor, label) return e11
def cisd(self, ci0=None, mo_coeff=None, eris=None): if eris is None: eris = self.ao2mo(mo_coeff) self.converged, self.e_corr, self.ci = \ kernel(self, eris, ci0, max_cycle=self.max_cycle, tol=self.conv_tol, verbose=self.verbose) if self._scf.e_tot == 0: logger.note(self, 'E_corr = %.16g', self.e_corr) else: logger.note(self, 'E(CISD) = %.16g E_corr = %.16g', self.e_tot, self.e_corr) return self.e_corr, self.ci
def grad(self, mo_energy=None, mo_coeff=None, mo_occ=None): cput0 = (time.clock(), time.time()) if mo_energy is None: mo_energy = self._scf.mo_energy if mo_coeff is None: mo_coeff = self._scf.mo_coeff if mo_occ is None: mo_occ = self._scf.mo_occ if self.verbose >= param.VERBOSE_INFO: self.dump_flags() grads = self.grad_elec(mo_energy, mo_coeff, mo_occ) + self.grad_nuc() for ia in range(self.mol.natm): log.note(self, 'atom %d %s, force = (%.14g, %.14g, %.14g)', ia, self.mol.atom_symbol(ia), *grads[ia]) log.timer(self, 'HF gradients', *cput0) return grads
def _finalize(self): '''Hook for dumping results and clearing up the object.''' scf.hf.RHF._finalize(self) # e_heat_formation was generated in SOSCF object. if (getattr(self, '_scf', None) and getattr(self._scf, 'e_heat_formation', None)): self.e_heat_formation = self._scf.e_heat_formation logger.note(self, 'Heat of formation = %.15g kcal/mol, %.15g Eh', self.e_heat_formation, self.e_heat_formation / mopac_param.HARTREE2KCAL) return self
def _finalize(self): citype = self.__class__.__name__ if numpy.all(self.converged): logger.info(self, '%s converged', citype) else: logger.info(self, '%s not converged', citype) if self.nroots > 1: for i, e in enumerate(self.e_tot): logger.note(self, '%s root %d E = %.16g', citype, i, e) else: logger.note(self, 'E(%s) = %.16g E_corr = %.16g', citype, self.e_tot, self.e_corr) return self
def kernel(self, mo_coeff=None, ci0=None, macro=None, micro=None, callback=None, _kern=None): if mo_coeff is None: mo_coeff = self.mo_coeff else: self.mo_coeff = mo_coeff if macro is None: macro = self.max_cycle_macro if micro is None: micro = self.max_cycle_micro if callback is None: callback = self.callback if _kern is None: _kern = mc1step.kernel if self.verbose > logger.QUIET: pyscf.gto.mole.check_sanity(self, self._keys, self.stdout) self.mol.check_sanity(self) self.dump_flags() # irrep_name = self.mol.irrep_name irrep_name = self.mol.irrep_id try: self.orbsym = symm.label_orb_symm(self.mol, irrep_name, self.mol.symm_orb, mo_coeff, s=self._scf.get_ovlp()) except ValueError: logger.warn(self, "mc1step_symm symmetrizes input orbitals") s = self._scf.get_ovlp() mo_coeff = symm.symmetrize_orb(self.mol, mo_coeff, s=s) diag = numpy.einsum("ki,ki->i", mo_coeff, numpy.dot(s, mo_coeff)) mo_coeff = numpy.einsum("ki,i->ki", mo_coeff, 1 / numpy.sqrt(diag)) self.orbsym = symm.label_orb_symm(self.mol, irrep_name, self.mol.symm_orb, mo_coeff, s=s) if not hasattr(self.fcisolver, "orbsym") or not self.fcisolver.orbsym: ncore = self.ncore nocc = self.ncore + self.ncas self.fcisolver.orbsym = self.orbsym[ncore:nocc] logger.debug(self, "Active space irreps %s", str(self.fcisolver.orbsym)) self.converged, self.e_tot, e_cas, self.ci, self.mo_coeff = _kern( self, mo_coeff, tol=self.conv_tol, conv_tol_grad=self.conv_tol_grad, macro=macro, micro=micro, ci0=ci0, callback=callback, verbose=self.verbose, ) logger.note(self, "CASSCF energy = %.15g", self.e_tot) return self.e_tot, e_cas, self.ci, self.mo_coeff
def kernel(self, mo1=None): cput0 = (time.clock(), time.time()) self.check_sanity() self.dump_flags() mol = self.mol dm0 = self._scf.make_rdm1() mo_coeff = self._scf.mo_coeff mo_occ = self._scf.mo_occ ssc_dia = self.make_dso(mol, dm0) if mo1 is None: mo1 = self.mo10 = self.solve_mo1()[0] ssc_pso = self.make_pso(mol, mo1, mo_coeff, mo_occ) e11 = ssc_dia + ssc_pso if self.with_fcsd: ssc_fcsd = self.make_fcsd(self.nuc_pair) e11 += ssc_fcsd elif self.with_fc: ssc_fc = self.make_fc(self.nuc_pair) e11 += ssc_fc logger.timer(self, 'spin-spin coupling', *cput0) if self.verbose > logger.QUIET: nuc_mag = .5 * (nist.E_MASS/nist.PROTON_MASS) # e*hbar/2m au2Hz = nist.HARTREE2J / nist.PLANCK #logger.debug('Unit AU -> Hz %s', au2Hz*nuc_mag**2) iso_ssc = au2Hz * nuc_mag ** 2 * numpy.einsum('kii->k', e11) / 3 natm = mol.natm ktensor = numpy.zeros((natm,natm)) for k, (i, j) in enumerate(self.nuc_pair): ktensor[i,j] = ktensor[j,i] = iso_ssc[k] if self.verbose >= logger.DEBUG: _write(self.stdout, ssc_dia[k]+ssc_para[k], '\nSSC E11 between %d %s and %d %s' \ % (i, self.mol.atom_symbol(i), j, self.mol.atom_symbol(j))) # _write(self.stdout, ssc_dia [k], 'dia-magnetism') # _write(self.stdout, ssc_para[k], 'para-magnetism') gyro = [get_nuc_g_factor(mol.atom_symbol(ia)) for ia in range(natm)] jtensor = numpy.einsum('ij,i,j->ij', ktensor, gyro, gyro) label = ['%2d %-2s'%(ia, mol.atom_symbol(ia)) for ia in range(natm)] logger.note(self, 'Reduced spin-spin coupling constant K (Hz)') tools.dump_mat.dump_tri(self.stdout, ktensor, label) logger.info(self, '\nNuclear g factor %s', gyro) logger.note(self, 'Spin-spin coupling constant J (Hz)') tools.dump_mat.dump_tri(self.stdout, jtensor, label) return e11
def eaagf2(self, nroots=5): e_ea, v_ea, spin = self.get_ea(self.gf, nroots=nroots) for n, en, vn, sn in zip(range(nroots), e_ea, v_ea, spin): qpwt = np.linalg.norm(vn)**2 tag = ['alpha', 'beta'][sn] logger.note( self, 'EA energy level %d E = %.16g QP weight = %0.6g (%s)', n, en, qpwt, tag) if nroots == 1: return e_ea[0], v_ea[0] else: return e_ea, v_ea
def cisd(self, ci0=None, mo_coeff=None, eris=None): if eris is None: eris = self.ao2mo(mo_coeff) self.converged, self.e_corr, self.ci = \ kernel(self, eris, ci0, max_cycle=self.max_cycle, tol=self.conv_tol, verbose=self.verbose) if self.converged: logger.info(self, 'CISD converged') else: logger.info(self, 'CISD not converged') if self._scf.e_tot == 0: logger.note(self, 'E_corr = %.16g', self.e_corr) else: logger.note(self, 'E(CISD) = %.16g E_corr = %.16g', self.e_tot, self.e_corr) return self.e_corr, self.ci
def kernel(self, mo_coeff=None, ci0=None): if mo_coeff is None: mo_coeff = self.mo_coeff if ci0 is None: ci0 = self.ci self.check_sanity() self.dump_flags() self.e_tot, e_cas, self.ci = \ kernel(self, mo_coeff, ci0=ci0, verbose=self.verbose) #if self.verbose >= logger.INFO: # self.analyze(mo_coeff, self.ci, verbose=self.verbose) logger.note(self, 'CASCI E = %.15g', self.e_tot) self._finalize_() return self.e_tot, e_cas, self.ci
def kernel(self, mo_coeff=None, ci0=None): if mo_coeff is None: mo_coeff = self.mo_coeff if ci0 is None: ci0 = self.ci if self.verbose > logger.QUIET: pyscf.gto.mole.check_sanity(self, self._keys, self.stdout) self.dump_flags() self.e_tot, e_cas, self.ci = \ kernel(self, mo_coeff, ci0=ci0, verbose=self.verbose) #if self.verbose >= logger.INFO: # self.analyze(mo_coeff, self.ci, verbose=self.verbose) logger.note(self, 'CASCI E = %.15g', self.e_tot) return self.e_tot, e_cas, self.ci
def kernel(self, ci0=None, mo_coeff=None, eris=None): if eris is None: eris = self.ao2mo(mo_coeff) self.converged, self.e_corr, self.ci = \ kernel(self, eris, ci0, max_cycle=self.max_cycle, tol=self.conv_tol, verbose=self.verbose) if self.converged: logger.info(self, 'CISD converged') else: logger.info(self, 'CISD not converged') if self.nroots > 1: for i, e in enumerate(self.e_tot): logger.note(self, 'CISD root %d E = %.16g', i, e) else: logger.note(self, 'E(CISD) = %.16g E_corr = %.16g', self.e_tot, self.e_corr) return self.e_corr, self.ci
def kernel(self, mo_coeff=None, ci0=None): if mo_coeff is None: mo_coeff = self.mo_coeff if ci0 is None: ci0 = self.ci if self.verbose >= logger.WARN: self.check_sanity() self.dump_flags() self.e_tot, e_cas, self.ci = \ kernel(self, mo_coeff, ci0=ci0, verbose=self.verbose) #if self.verbose >= logger.INFO: # self.analyze(mo_coeff, self.ci, verbose=self.verbose) logger.note(self, 'CASCI E = %.15g', self.e_tot) self._finalize() return self.e_tot, e_cas, self.ci
def kernel(self, dm=None, atmlst=None): if dm is None: dm = grad_method.base.make_rdm1(ao_repr=True) # de_solvent needs to be called first because _finalize method # is called in the grad_method.kernel function. de_solvent is # required by the _finalize method. self.de_solvent = kernel(self.with_solvent, dm) self.de_solute = grad_method_class.kernel(self, atmlst=atmlst) self.de = self.de_solute + self.de_solvent if self.verbose >= logger.NOTE: logger.note(self, '--------------- %s (%s) gradients ---------------', grad_method.base.__class__.__name__, self.with_solvent.__class__.__name__) rhf_grad._write(self, self.mol, self.de, self.atmlst) logger.note(self, '----------------------------------------------') return self.de
def kernel(self, mo1=None): cput0 = (time.clock(), time.time()) self.check_sanity() self.dump_flags() gdia = self.dia() gpara = self.para(mo10=mo1) gshift = gpara + gdia gtensor = gshift + numpy.eye(3) * lib.param.G_ELECTRON logger.timer(self, 'g-tensor', *cput0) if self.verbose > logger.QUIET: logger.note(self, 'free electron g %s', lib.param.G_ELECTRON) _write(gobj, gtensor, 'g-tensor', logger.NOTE) _write(gobj, gdia, 'g-tensor diamagnetic terms', logger.INFO) _write(gobj, gpara, 'g-tensor paramagnetic terms', logger.INFO) _write(gobj, gshift * 1e3, 'g-shift (ppt)', logger.NOTE) return gtensor
def kernel(self, dm=None, atmlst=None): if dm is None: dm = self.base.make_rdm1(ao_repr=True) # de_solvent needs to be called first because _finalize method # is called in the grad_method.kernel function. de_solvent is # required by the _finalize method. self.de_solvent = kernel(self.with_solvent, dm) self.de_solute = grad_method_class.kernel(self, atmlst=atmlst) self.de = self.de_solute + self.de_solvent if self.verbose >= logger.NOTE: logger.note(self, '--------------- %s (%s) gradients ---------------', self.base.__class__.__name__, self.with_solvent.__class__.__name__) rhf_grad._write(self, self.mol, self.de, self.atmlst) logger.note(self, '----------------------------------------------') return self.de
def kernel(self, *args, **kwargs): dm = kwargs.pop('dm', None) if dm is None: dm = self.base.make_rdm1(ao_repr=True) self.de_solvent = kernel(self.base.with_solvent, dm) self.de_solute = grad_method_class.kernel(self, *args, **kwargs) self.de = self.de_solute + self.de_solvent if self.verbose >= logger.NOTE: logger.note( self, '--------------- %s (+%s) gradients ---------------', self.base.__class__.__name__, self.base.with_solvent.__class__.__name__) rhf_grad._write(self, self.mol, self.de, self.atmlst) logger.note(self, '----------------------------------------------') return self.de
def kernel(self, mo_coeff=None, ci0=None, callback=None, _kern=kernel): if mo_coeff is None: mo_coeff = self.mo_coeff else: # overwrite self.mo_coeff because it is needed in many methods of this class self.mo_coeff = mo_coeff if callback is None: callback = self.callback if self.verbose >= logger.WARN: self.check_sanity() self.dump_flags() self.converged, self.e_tot, self.e_cas, self.ci, \ self.mo_coeff, self.mo_energy = \ _kern(self, mo_coeff, tol=self.conv_tol, conv_tol_grad=self.conv_tol_grad, ci0=ci0, callback=callback, verbose=self.verbose) logger.note(self, 'CASSCF energy = %.15g', self.e_tot) self._finalize() return self.e_tot, self.e_cas, self.ci, self.mo_coeff, self.mo_energy
def eaagf2(self, nroots=5): ''' Find the (N+1)-electron charged excitations, corresponding to the smallest :attr:`nroots` poles of the virtual Green's function. Kwargs: See ipagf2() ''' e_ea, v_ea = self.get_ea(self.gf, nroots=nroots) for n, en, vn in zip(range(nroots), e_ea, v_ea): qpwt = np.linalg.norm(vn)**2 logger.note(self, 'EA energy level %d E = %.16g QP weight = %0.6g', n, en, qpwt) if nroots == 1: return e_ea[0], v_ea[0] else: return e_ea, v_ea
def kernel(self, mo_coeff=None, ci0=None, callback=None, _kern=kernel): if mo_coeff is None: mo_coeff = self.mo_coeff else: self.mo_coeff = mo_coeff if callback is None: callback = self.callback self.check_sanity() self.dump_flags() self.converged, self.e_tot, self.e_cas, self.ci, self.mo_coeff = \ _kern(self, mo_coeff, tol=self.conv_tol, conv_tol_grad=self.conv_tol_grad, ci0=ci0, callback=callback, verbose=self.verbose) logger.note(self, 'UCASSCF energy = %.15g', self.e_tot) #if self.verbose >= logger.INFO: # self.analyze(mo_coeff, self.ci, verbose=self.verbose) self._finalize() return self.e_tot, self.e_cas, self.ci, self.mo_coeff
def kernel(self, mo_coeff=None, ci0=None, callback=None, _kern=kernel): if mo_coeff is None: mo_coeff = self.mo_coeff else: self.mo_coeff = mo_coeff if callback is None: callback = self.callback if self.verbose >= logger.WARN: self.check_sanity() self.dump_flags() self.converged, self.e_tot, e_cas, self.ci, self.mo_coeff = \ _kern(self, mo_coeff, tol=self.conv_tol, conv_tol_grad=self.conv_tol_grad, ci0=ci0, callback=callback, verbose=self.verbose) logger.note(self, 'CASSCF energy = %.15g', self.e_tot) #if self.verbose >= logger.INFO: # self.analyze(mo_coeff, self.ci, verbose=self.verbose) self._finalize() return self.e_tot, e_cas, self.ci, self.mo_coeff
def cisd(self, ci0=None, eris=None): if eris is None: eris = self.ao2mo(self.mo_coeff) if self.verbose >= logger.WARN: self.check_sanity() self.dump_flags() self.converged, self.e_corr, self.ci = \ kernel(self, eris, ci0, max_cycle=self.max_cycle, tol=self.conv_tol, verbose=self.verbose) if numpy.all(self.converged): logger.info(self, 'CISD converged') else: logger.info(self, 'CISD not converged') if self.nroots > 1: for i,e in enumerate(self.e_tot): logger.note(self, 'CISD root %d E = %.16g', i, e) else: logger.note(self, 'E(CISD) = %.16g E_corr = %.16g', self.e_tot, self.e_corr) return self.e_corr, self.ci
def ccsd(self, t1=None, t2=None, eris=None): if self.verbose >= logger.WARN: self.check_sanity() self.dump_flags() if eris is None: eris = self.ao2mo(self.mo_coeff) self.converged, self.e_corr, self.t1, self.t2 = \ kernel(self, eris, t1, t2, max_cycle=self.max_cycle, tol=self.conv_tol, tolnormt=self.conv_tol_normt, verbose=self.verbose) if self.converged: logger.info(self, 'CCSD converged') else: logger.info(self, 'CCSD not converged') if self._scf.e_tot == 0: logger.note(self, 'E_corr = %.16g', self.e_corr) else: logger.note(self, 'E(CCSD) = %.16g E_corr = %.16g', self.e_tot, self.e_corr) return self.e_corr, self.t1, self.t2
def _finalize_(self): if self.converged: logger.note(self, 'converged SCF energy = %.15g', self.e_tot) else: logger.note(self, 'SCF not converge.') logger.note(self, 'SCF energy = %.15g after %d cycles', self.e_tot, self.max_cycle)
def ccsd(self, t1=None, t2=None, eris=None, mbpt2=False, cc2=False): '''Ground-state CCSD. Kwargs: mbpt2 : bool Use one-shot MBPT2 approximation to CCSD. cc2 : bool Use CC2 approximation to CCSD. ''' if mbpt2 and cc2: raise RuntimeError( 'MBPT2 and CC2 are mutually exclusive approximations to the CCSD ground state.' ) if eris is None: eris = self.ao2mo(self.mo_coeff) self.eris = eris self.dump_flags() if mbpt2: cctyp = 'MBPT2' self.e_corr, self.t1, self.t2 = self.init_amps(eris) else: if cc2: cctyp = 'CC2' self.cc2 = True else: cctyp = 'CCSD' self.cc2 = False self.converged, self.e_corr, self.t1, self.t2 = \ ccsd.kernel(self, eris, t1, t2, max_cycle=self.max_cycle, tol=self.conv_tol, tolnormt=self.conv_tol_normt, verbose=self.verbose) if self.converged: logger.info(self, '%s converged', cctyp) else: logger.info(self, '%s not converged', cctyp) if self._scf.e_tot == 0: logger.note(self, 'E_corr = %.16g', self.e_corr) else: logger.note(self, 'E(%s) = %.16g E_corr = %.16g', cctyp, self.e_tot, self.e_corr) return self.e_corr, self.t1, self.t2
def _finalize(self): if self.converged: logger.note(self, 'converged SCF energy = %.15g', self.e_tot) else: logger.note(self, 'SCF not converged.') logger.note(self, 'SCF energy = %.15g after %d cycles', self.e_tot, self.max_cycle) return self
def _recalculate_with_xc(ot, chkdata): ''' Recalculate MC-DCFT total energy based on intermediate quantities from a previous MC-DCFT calculation Args: ot : str or an instance of on-top density functional class - see otfnal.py chkdata : chkdata dict generated by previous calculation Returns: Total MC-DCFT energy including nuclear repulsion energy. ''' t0 = (time.clock(), time.time()) omega, alpha, hyb = ot._numint.rsh_and_hybrid_coeff(ot.otxc, spin=chkdata['spin']) hyb_x, hyb_c = hyb Vnn = chkdata['Vnn'] Te_Vne = chkdata['Te_Vne'] E_j = chkdata['E_j'] E_x = chkdata['E_x'] dm1s = chkdata['dm1s'] logger.debug(ot, 'CAS energy decomposition (restored from previous calculation):') logger.debug(ot, 'Vnn = %s', Vnn) logger.debug(ot, 'Te + Vne = %s', Te_Vne) logger.debug(ot, 'E_j = %s', E_j) logger.debug(ot, 'E_x = %s', E_x) if abs(hyb_x) > 1e-10 or abs(hyb_c) > 1e-10: logger.debug(ot, 'Adding %s * %s CAS exchange, %s * %s CAS correlation to E_ot', hyb_x, E_x, hyb_c) if E_x == 0: logger.warn(ot, 'E_x == 0. Hybrid functionals might give wrong results!') t0 = logger.timer(ot, 'Vnn, Te, Vne, E_j, E_x', *t0) E_ot = get_E_ot(ot, dm1s) t0 = logger.timer (ot, 'E_ot', *t0) e_tot = Vnn + Te_Vne + E_j + (hyb_x * E_x) + E_ot logger.note(ot, 'MC-DCFT E = %s, Eot(%s) = %s', e_tot, ot.ot_name, E_ot) return e_tot, E_ot
def ccsd(self, t1=None, t2=None, eris=None, mbpt2=False, cc2=False): '''Ground-state CCSD. Kwargs: mbpt2 : bool Use one-shot MBPT2 approximation to CCSD. cc2 : bool Use CC2 approximation to CCSD. ''' if mbpt2 and cc2: raise RuntimeError('MBPT2 and CC2 are mutually exclusive approximations to the CCSD ground state.') if eris is None: eris = self.ao2mo(self.mo_coeff) self.eris = eris self.dump_flags() if mbpt2: cctyp = 'MBPT2' self.e_corr, self.t1, self.t2 = self.init_amps(eris) else: if cc2: cctyp = 'CC2' self.cc2 = True else: cctyp = 'CCSD' self.cc2 = False self.converged, self.e_corr, self.t1, self.t2 = \ ccsd.kernel(self, eris, t1, t2, max_cycle=self.max_cycle, tol=self.conv_tol, tolnormt=self.conv_tol_normt, verbose=self.verbose) if self.converged: logger.info(self, '%s converged', cctyp) else: logger.info(self, '%s not converged', cctyp) if self._scf.e_tot == 0: logger.note(self, 'E_corr = %.16g', self.e_corr) else: logger.note(self, 'E(%s) = %.16g E_corr = %.16g', cctyp, self.e_tot, self.e_corr) return self.e_corr, self.t1, self.t2
def kernel(self, mo1=None): cput0 = (time.clock(), time.time()) self.check_sanity() self.dump_flags() gdia = self.dia(self._scf.make_rdm1(), self.gauge_orig) gpara = self.para(mo1, self._scf.mo_coeff, self._scf.mo_occ) gshift = gpara + gdia gtensor = gshift + numpy.eye(3) * nist.G_ELECTRON logger.timer(self, 'g-tensor', *cput0) if self.verbose >= logger.NOTE: logger.note(self, 'free electron g %s', nist.G_ELECTRON) gtot, v = self.align(gtensor) gdia = reduce(numpy.dot, (v.T, gdia, v)) gpara = reduce(numpy.dot, (v.T, gpara, v)) gshift = gtot - numpy.eye(3) * nist.G_ELECTRON if self.verbose >= logger.INFO: _write(self, gdia, 'g-tensor diamagnetic terms') _write(self, gpara, 'g-tensor paramagnetic terms') _write(self, gtot, 'g-tensor total') _write(self, gshift*1e3, 'g-shift (ppt)') return gtensor
def ccsd(self, t1=None, t2=None, eris=None, mbpt2=False): if eris is None: eris = self.ao2mo(self.mo_coeff) self.eris = eris self.dump_flags() if mbpt2: cctyp = 'MBPT2' self.e_corr, self.t1, self.t2 = self.init_amps(eris) else: cctyp = 'CCSD' self.converged, self.e_corr, self.t1, self.t2 = \ kernel(self, eris, t1, t2, max_cycle=self.max_cycle, tol=self.conv_tol, tolnormt=self.conv_tol_normt, verbose=self.verbose) if self.converged: logger.info(self, 'CCSD converged') else: logger.info(self, 'CCSD not converged') if self._scf.e_tot == 0: logger.note(self, 'E_corr = %.16g', self.e_corr) else: logger.note(self, 'E(%s) = %.16g E_corr = %.16g', cctyp, self.e_tot, self.e_corr) return self.e_corr, self.t1, self.t2
def calc_optim_veig(dscf, target_dm, target_dec=None, gvx=None, nstep=1, force_factor=1., **optim_args): clfn = gen_coul_loss(dscf, fock=dscf.get_fock(vhf=dscf.get_veff0())) dm = dscf.make_rdm1() if dm.ndim == 3 and isinstance(dscf, scf.uhf.UHF): dm = dm.sum(0) t_dm = torch.from_numpy(dm).requires_grad_() t_eig = t_make_eig(t_dm, dscf._t_ovlp_shells).requires_grad_() t_ec = dscf.net(t_eig.to(dscf.device)) t_veig = torch.autograd.grad(t_ec, t_eig)[0].requires_grad_() t_lde = torch.from_numpy(target_dec) if target_dec is not None else None t_gvx = torch.from_numpy(gvx) if gvx is not None else None # build closure def closure(): [t_vc] = torch.autograd.grad( t_eig, t_dm, t_veig, retain_graph=True, create_graph=True) loss, dldv = clfn(t_vc.detach().numpy(), target_dm) grad = torch.autograd.grad( t_vc, t_veig, torch.from_numpy(dldv), only_inputs=True)[0] # build closure for force loss if t_lde is not None and t_gvx is not None: t_pde = torch.tensordot(t_gvx, t_veig) lossde = force_factor * torch.sum((t_pde - t_lde)**2) grad = grad + torch.autograd.grad(lossde, t_veig, only_inputs=True)[0] loss = loss + lossde t_veig.grad = grad return loss # do the optimization optim = torch.optim.LBFGS([t_veig], **optim_args) tic = (time.process_time(), time.perf_counter()) for _ in range(nstep): optim.step(closure) tic = logger.timer(dscf, 'LBFGS step', *tic) logger.note(dscf, f"optimized loss for veig = {closure()}") return t_veig.detach().numpy()
def kernel(self, xy=None, state=0, singlet=None, atmlst=None): cput0 = (time.clock(), time.time()) if xy is None: xy = self._td.xy[state] if singlet is None: singlet = self._td.singlet if atmlst is None: atmlst = range(self.mol.natm) self.check_sanity() de = self.grad_elec(xy, singlet, atmlst) self.de = de = de + self.grad_nuc(atmlst=atmlst) logger.note(self, '--------------') logger.note(self, ' x y z') for k, ia in enumerate(atmlst): logger.note(self, '%d %s %15.9f %15.9f %15.9f', ia, self.mol.atom_symbol(ia), de[k,0], de[k,1], de[k,2]) logger.note(self, '--------------') logger.timer(self, 'TD gradients', *cput0) return self.de
def kernel(self, xy=None, state=0, singlet=None, atmlst=None): cput0 = (time.clock(), time.time()) if xy is None: xy = self._td.xy[state] if singlet is None: singlet = self._td.singlet if atmlst is None: atmlst = range(self.mol.natm) self.check_sanity() de = self.grad_elec(xy, singlet, atmlst) self.de = de = de + self.grad_nuc(atmlst=atmlst) logger.note(self, '--------------') logger.note(self, ' x y z') for k, ia in enumerate(atmlst): logger.note(self, '%d %s %15.9f %15.9f %15.9f', ia, self.mol.atom_symbol(ia), de[k, 0], de[k, 1], de[k, 2]) logger.note(self, '--------------') logger.timer(self, 'TD gradients', *cput0) return self.de
def uno(self, threshold=1): # added by qingchun 3/18 2018 logger.note(self,'entry uno()') s = self.mol.intor_symmetric('int1e_ovlp') from gvb import dump # nco=dump.ncore(self.mol); nelec_a, nelec_b = self.mol.nelec # nelec_a > nelec_b # if nco>1: # occ_a = self.mo_coeff[0][:, :nco]; occ_b = self.mo_coeff[1][:, :nco] # U, l, Vt = numpy.linalg.svd(reduce(numpy.dot, (occ_a.T, s, occ_b))) # self.mo_coeff[0][:, :nco] = numpy.dot(occ_a, U); self.mo_coeff[1][:, :nco] = numpy.dot(occ_b, Vt.T) # logger.note(self, 'uno svd(core) s =\n%s' %l) nco = 0; nelec_a, nelec_b = self.mol.nelec # nelec_a > nelec_b vir_a = self.mo_coeff[0][:,nelec_a:].copy(); vir_b = self.mo_coeff[1][:,nelec_b:].copy() U, l, Vt = numpy.linalg.svd(reduce(numpy.dot,(vir_a.T, s, vir_b))) # self.mo_coeff[0][:, nelec_a:] = numpy.dot(vir_a, U); self.mo_coeff[1][:,nelec_b:] = numpy.dot(vir_b, Vt.T) vir_a = numpy.dot(vir_a, U); vir_b = numpy.dot(vir_b, Vt.T) logger.note(self,'uno svd(vir) s =\n%s' %l) occ_a = self.mo_coeff[0][:,nco:nelec_a].copy(); occ_b = self.mo_coeff[1][:,nco:nelec_b].copy() U, l, Vt = numpy.linalg.svd(reduce(numpy.dot,(occ_a.T.conj(), s, occ_b))) # self.mo_coeff[0][:, nco:nelec_a] = numpy.dot(occ_a, U); self.mo_coeff[1][:,nco:nelec_b] = numpy.dot(occ_b, Vt.T) occ_a = numpy.dot(occ_a, U); occ_b = numpy.dot(occ_b, Vt.T) logger.note(self,'uno svd(occ) s =\n%s' %l) # from pyscf.gvb import gvb # import os # in_b=os.path.splitext(self.mol.output)[0][:-3] # gvb.dump_mo(self, in_b+'_gvb_halfuno.fchk', in_b+'_uhf.fchk') if threshold<1: npair_u = numpy.count_nonzero((l-threshold) < 0) else: nactocc = nelec_b-dump.ncore(self.mol); nactvir = dump.nrefobt(self.mol, '_'.join(self.mol.output.split('_')[:-2]))-nelec_a npair = min(nactocc, nactvir) npair_u=numpy.count_nonzero((l-0.99999)<0) if npair < threshold: raise RuntimeError('threshold(%d) > min(nactocc,nactvir)(%d)' %(threshold, npair)) else: if npair_u >= npair: npair_u = npair n = -1; a_b=nelec_a-nelec_b while n>-(npair_u+1): o_a = occ_a[:, n-a_b].copy(); v_a = vir_a[:,n].copy() o_b = occ_b[:, n].copy(); v_b = vir_b[:,n-a_b].copy() occ_a[:,n-a_b] = (o_a+o_b)/((2*(1+l[n]))**.5); vir_a[:,n] = (o_a-o_b)/((2*(1-l[n]))**.5) occ_b[:,n] = (v_a-v_b)/((2*(1-l[n]))**.5); vir_b[:,n-a_b] = (v_a+v_b)/((2*(1+l[n]))**.5) # self.mo_occ[0][nelec_a+n] = 1+occ_s[n]; self.mo_occ[0][nelec_a-n-1]=1-occ_s[n] # self.mo_occ[1][nelec_b+n] = 1+occ_s[n]; self.mo_occ[1][nelec_b-n-1]=1-occ_s[n] n-=1 self.mo_coeff[0][:,nco:nelec_a] = occ_a; self.mo_coeff[0][:, nelec_a:] = vir_a[:,::-1] self.mo_coeff[1][:,nco:nelec_b] = occ_b; self.mo_coeff[1][:, nelec_b:] = vir_b[:,::-1] # # check U*D*Vt = s # from gvb.rgvb import dump_ndarr # dump_ndarr(self, reduce(numpy.dot, (self.mo_coeff[0][:,0:nelec_a].T, s, self.mo_coeff[0][:,0:nelec_a])), # 'uno occ orbital S =', fmt='rec', label_row=self.mol.ao_labels()) return npair_u
def dump_energy(self, hf_energy=None, converged=None): if hf_energy is None: hf_energy = self.hf_energy if converged is None: converged = self.converged if converged: logger.note(self, 'converged SCF energy = %.15g', hf_energy) else: logger.note(self, 'SCF not converge.') logger.note(self, 'SCF energy = %.15g after %d cycles', hf_energy, self.max_cycle)
def _finalize(self): ''' Hook for dumping results and clearing up the object. ''' if self.converged: logger.info(self, '%s converged', self.__class__.__name__) else: logger.note(self, '%s not converged', self.__class__.__name__) ip = self.get_ip(self.gf, nroots=1)[0][0] ea = self.get_ea(self.gf, nroots=1)[0][0] logger.note(self, 'E(%s) = %.16g E_corr = %.16g', self.__class__.__name__, self.e_tot, self.e_corr) logger.note(self, 'IP = %.16g EA = %.16g', ip, ea) logger.note(self, 'Quasiparticle gap = %.16g', ip + ea) return self
def _finalize(self): if self.verbose >= logger.NOTE: if self.state is None: logger.note(self, '--------- %s gradients ----------', self.base.__class__.__name__) else: logger.note(self, '--------- %s gradients for state %d ----------', self.base.__class__.__name__, self.state) self._write(self.mol, self.de, self.atmlst) logger.note(self, '----------------------------------------------')
def _finalize(self): ss, s = self.spin_square() if self.converged: logger.note(self, 'converged SCF energy = %.15g ' '<S^2> = %.8g 2S+1 = %.8g', self.e_tot, ss, s) else: logger.note(self, 'SCF not converged.') logger.note(self, 'SCF energy = %.15g after %d cycles ' '<S^2> = %.8g 2S+1 = %.8g', self.e_tot, self.max_cycle, ss, s) return self
def grad(self, mo_energy=None, mo_coeff=None, mo_occ=None, atmlst=None): cput0 = (time.clock(), time.time()) if mo_energy is None: mo_energy = self._scf.mo_energy if mo_coeff is None: mo_coeff = self._scf.mo_coeff if mo_occ is None: mo_occ = self._scf.mo_occ if self.verbose >= logger.INFO: self.dump_flags() de =(self.grad_elec(mo_energy, mo_coeff, mo_occ, atmlst) + self.grad_nuc(atmlst)) logger.note(self, '--------------') logger.note(self, ' x y z') if atmlst is None: atmlst = range(self.mol.natm) for k, ia in enumerate(atmlst): logger.note(self, '%d %s %15.9f %15.9f %15.9f', ia, self.mol.atom_symbol(ia), de[k,0], de[k,1], de[k,2]) logger.note(self, '--------------') logger.timer(self, 'SCF gradients', *cput0) return de
def _finalize(self): mcscfbase_class._finalize(self) # Do not overwrite self.e_tot because .e_tot needs to be used in # geometry optimization. self.e_states can be used to access the # energy of each state #self.e_tot = self.fcisolver.e_states logger.note(self, 'CASCI state-averaged energy = %.15g', self.e_average) logger.note(self, 'CASCI energy for each state') if has_spin_square: ss = self.fcisolver.states_spin_square(self.ci, self.ncas, self.nelecas)[0] for i, ei in enumerate(self.e_states): logger.note(self, ' State %d weight %g E = %.15g S^2 = %.7f', i, self.weights[i], ei, ss[i]) else: for i, ei in enumerate(self.e_states): logger.note(self, ' State %d weight %g E = %.15g', i, self.weights[i], ei) return self
def _finalize(self): '''Hook for dumping results and clearing up the object.''' if self.converged: logger.info(self, 'FNO-%s converged', self.__class__.__name__) else: logger.note(self, 'FNO-%s not converged', self.__class__.__name__) logger.note(self, 'E(FNO-%s) = %.16g E_corr = %.16g', self.__class__.__name__, self.e_tot, self.e_corr) logger.note(self, 'E(FNO-%s+delta-MP2) = %.16g E_corr = %.16g', self.__class__.__name__, self.e_tot+self.delta_emp2, self.e_corr+self.delta_emp2) return self
def _finalize(self): ss, s = self.spin_square() if self.converged: # logger.note(self, 'converged SCF energy = %.15g ' # '<S^2> = %.8g 2S+1 = %.8g', self.e_tot, ss, s) logger.note(self, '%s converged SCF energy = %.15g ' # revised by qingchun 3/16/2018 '<S^2> = %.8g 2S+1 = %.8g', self.__class__.__name__, self.e_tot, ss, s) else: # logger.note(self, 'SCF not converged.') logger.note(self, '%s SCF not converged.', self.__class__.__name__) # revised by qingchun 3/16/2018 logger.note(self, 'SCF energy = %.15g after %d cycles ' '<S^2> = %.8g 2S+1 = %.8g', self.e_tot, self.max_cycle, ss, s) return self
def grad(self, mo_energy=None, mo_coeff=None, mo_occ=None, atmlst=None): cput0 = (time.clock(), time.time()) if mo_energy is None: mo_energy = self._scf.mo_energy if mo_coeff is None: mo_coeff = self._scf.mo_coeff if mo_occ is None: mo_occ = self._scf.mo_occ if atmlst is None: atmlst = range(self.mol.natm) if self.verbose >= logger.WARN: self.check_sanity() if self.verbose >= logger.INFO: self.dump_flags() de = self.grad_elec(mo_energy, mo_coeff, mo_occ, atmlst) self.de = de = de + self.grad_nuc(atmlst=atmlst) logger.note(self, '--------------- SCF gradients ----------------') logger.note(self, ' x y z') for k, ia in enumerate(atmlst): logger.note(self, '%d %s %15.9f %15.9f %15.9f', ia, self.mol.atom_symbol(ia), de[k,0], de[k,1], de[k,2]) logger.note(self, '----------------------------------------------') logger.timer(self, 'SCF gradients', *cput0) return self.de
def _finalize(): old_finalize() casscf.e_tot = e_states[0] logger.note(casscf, 'CASCI energy for each state') if has_spin_square: ncas = casscf.ncas nelecas = casscf.nelecas ss, multip = collect(solver.spin_square(c0, ncas, get_nelec(solver, nelecas)) for solver, c0 in loop_civecs(fcisolvers, casscf.ci)) for i, ei in enumerate(casscf.e_tot): logger.note(casscf, ' State %d weight %g E = %.15g S^2 = %.7f', i, weights[i], ei, ss[i]) else: for i, ei in enumerate(casscf.e_tot): logger.note(casscf, ' State %d weight %g E = %.15g', i, weights[i], ei) return casscf
def _finalize(): old_finalize() casscf.e_tot = e_states[0] logger.note(casscf, 'CASCI energy for each state') if has_spin_square: ncas = casscf.ncas nelecas = casscf.nelecas for i, ei in enumerate(casscf.e_tot): ss = fcibase_class.spin_square(casscf.fcisolver, casscf.ci[i], ncas, nelecas)[0] logger.note(casscf, ' State %d weight %g E = %.15g S^2 = %.7f', i, weights[i], ei, ss) else: for i, ei in enumerate(casscf.e_tot): logger.note(casscf, ' State %d weight %g E = %.15g', i, weights[i], ei) return casscf
def DMRG_MPS_NEVPT(mc, root=0, fcisolver=None, maxm = 500, tol =1e-6, parallel= True): if (isinstance(mc, basestring)): fh5 = h5py.File(mc,'r') mol = eval(fh5['mol'].value) ncas = fh5['mc/ncas'].value ncore = fh5['mc/ncore'].value nvirt = fh5['mc/nvirt'].value nelecas = fh5['mc/nelecas'].value fh5.close() mc_chk = mc else : mol = mc.mol ncas = mc.ncas ncore = mc.ncore nvirt = mc.mo_coeff.shape[1] - mc.ncas-mc.ncore nelecas = mc.nelecas mc_chk = 'mc_chkfile' write_chk(mc,root,mc_chk) if fcisolver is None: fcisolver = DMRGCI(mol, maxm, tol) fcisolver.twopdm = False fcisolver.nroots = mc.fcisolver.nroots scratch = fcisolver.scratchDirectory fcisolver.scratchDirectory = '' #if (not parallel): # ci.extraline.append('restart_mps_nevpt %d %d %d'%(ncas,ncore, nvirt)) fcisolver.extraline.append('fullrestart') fcisolver.extraline.append('nevpt_state_num %d'%root) writeDMRGConfFile(nelecas[0], nelecas[1], False, fcisolver) fcisolver.scratchDirectory = scratch if fcisolver.verbose >= logger.DEBUG1: inFile = fcisolver.configFile #inFile = os.path.join(self.scratchDirectory,self.configFile) logger.debug1(fcisolver, 'Block Input conf') logger.debug1(fcisolver, open(inFile, 'r').read()) t0 = (time.clock(), time.time()) from subprocess import check_call import os full_path = os.path.realpath(__file__) check_call('%s %s/nevpt_mpi.py %s %s %s %s %s'%(fcisolver.mpiprefix, os.path.dirname(full_path), mc_chk, fcisolver.executable, fcisolver.configFile,fcisolver.outputFile, fcisolver.scratchDirectory), shell=True) if fcisolver.verbose >= logger.DEBUG1: logger.debug1(fcisolver, open(os.path.join(fcisolver.scratchDirectory, '0/dmrg.out')).read()) import h5py fh5 = h5py.File('Perturbation_%d'%root,'r') Vi_e = fh5['Vi/energy'].value Vi_n = fh5['Vi/norm'].value Vr_e = fh5['Vr/energy'].value Vr_n = fh5['Vr/norm'].value fh5.close() logger.note(fcisolver,'Nevpt Energy:') logger.note(fcisolver,'Sr Subspace: Norm = %s, E = %s'%(Vr_n, Vr_e)) logger.note(fcisolver,'Si Subspace: Norm = %s, E = %s'%(Vi_n, Vi_e)) logger.timer(fcisolver,'MPS NEVPT calculation time', *t0)
def kernel(self): from pyscf.mcscf.addons import StateAverageFCISolver if isinstance(self.fcisolver, StateAverageFCISolver): raise RuntimeError('State-average FCI solver object cannot be used ' 'in NEVPT2 calculation.\nA separated multi-root ' 'CASCI calculation is required for NEVPT2 method. ' 'See examples/mrpt/41-for_state_average.py.') if getattr(self._mc, 'frozen', None) is not None: raise NotImplementedError if isinstance(self.verbose, logger.Logger): log = self.verbose else: log = logger.Logger(self.stdout, self.verbose) time0 = (time.clock(), time.time()) ncore = self.ncore ncas = self.ncas nocc = ncore + ncas #By defaut, _mc is canonicalized for the first root. #For SC-NEVPT based on compressed MPS perturber functions, the _mc was already canonicalized. if (not self.canonicalized): self.mo_coeff,_, self.mo_energy = self.canonicalize(self.mo_coeff,ci=self.load_ci(),verbose=self.verbose) if getattr(self.fcisolver, 'nevpt_intermediate', None): logger.info(self, 'DMRG-NEVPT') dm1, dm2, dm3 = self.fcisolver._make_dm123(self.load_ci(),ncas,self.nelecas,None) else: dm1, dm2, dm3 = fci.rdm.make_dm123('FCI3pdm_kern_sf', self.load_ci(), self.load_ci(), ncas, self.nelecas) dm4 = None dms = {'1': dm1, '2': dm2, '3': dm3, '4': dm4, #'h1': hdm1, 'h2': hdm2, 'h3': hdm3 } time1 = log.timer('3pdm, 4pdm', *time0) eris = _ERIS(self, self.mo_coeff) time1 = log.timer('integral transformation', *time1) if not getattr(self.fcisolver, 'nevpt_intermediate', None): # regular FCI solver link_indexa = fci.cistring.gen_linkstr_index(range(ncas), self.nelecas[0]) link_indexb = fci.cistring.gen_linkstr_index(range(ncas), self.nelecas[1]) aaaa = eris['ppaa'][ncore:nocc,ncore:nocc].copy() f3ca = _contract4pdm('NEVPTkern_cedf_aedf', aaaa, self.load_ci(), ncas, self.nelecas, (link_indexa,link_indexb)) f3ac = _contract4pdm('NEVPTkern_aedf_ecdf', aaaa, self.load_ci(), ncas, self.nelecas, (link_indexa,link_indexb)) dms['f3ca'] = f3ca dms['f3ac'] = f3ac time1 = log.timer('eri-4pdm contraction', *time1) if self.compressed_mps: from pyscf.dmrgscf.nevpt_mpi import DMRG_COMPRESS_NEVPT if self.stored_integral: #Stored perturbation integral and read them again. For debugging purpose. perturb_file = DMRG_COMPRESS_NEVPT(self, maxM=self.maxM, root=self.root, nevptsolver=self.nevptsolver, tol=self.tol, nevpt_integral='nevpt_perturb_integral') else: perturb_file = DMRG_COMPRESS_NEVPT(self, maxM=self.maxM, root=self.root, nevptsolver=self.nevptsolver, tol=self.tol) fh5 = h5py.File(perturb_file, 'r') e_Si = fh5['Vi/energy'].value #The definition of norm changed. #However, there is no need to print out it. #Only perturbation energy is wanted. norm_Si = fh5['Vi/norm'].value e_Sr = fh5['Vr/energy'].value norm_Sr = fh5['Vr/norm'].value fh5.close() logger.note(self, "Sr (-1)', E = %.14f", e_Sr ) logger.note(self, "Si (+1)', E = %.14f", e_Si ) else: norm_Sr , e_Sr = Sr(self, self.load_ci(), dms, eris) logger.note(self, "Sr (-1)', E = %.14f", e_Sr ) time1 = log.timer("space Sr (-1)'", *time1) norm_Si , e_Si = Si(self, self.load_ci(), dms, eris) logger.note(self, "Si (+1)', E = %.14f", e_Si ) time1 = log.timer("space Si (+1)'", *time1) norm_Sijrs, e_Sijrs = Sijrs(self, eris) logger.note(self, "Sijrs (0) , E = %.14f", e_Sijrs) time1 = log.timer('space Sijrs (0)', *time1) norm_Sijr , e_Sijr = Sijr(self, dms, eris) logger.note(self, "Sijr (+1) , E = %.14f", e_Sijr) time1 = log.timer('space Sijr (+1)', *time1) norm_Srsi , e_Srsi = Srsi(self, dms, eris) logger.note(self, "Srsi (-1) , E = %.14f", e_Srsi) time1 = log.timer('space Srsi (-1)', *time1) norm_Srs , e_Srs = Srs(self, dms, eris) logger.note(self, "Srs (-2) , E = %.14f", e_Srs ) time1 = log.timer('space Srs (-2)', *time1) norm_Sij , e_Sij = Sij(self, dms, eris) logger.note(self, "Sij (+2) , E = %.14f", e_Sij ) time1 = log.timer('space Sij (+2)', *time1) norm_Sir , e_Sir = Sir(self, dms, eris) logger.note(self, "Sir (0)' , E = %.14f", e_Sir ) time1 = log.timer("space Sir (0)'", *time1) nevpt_e = e_Sr + e_Si + e_Sijrs + e_Sijr + e_Srsi + e_Srs + e_Sij + e_Sir logger.note(self, "Nevpt2 Energy = %.15f", nevpt_e) log.timer('SC-NEVPT2', *time0) self.e_corr = nevpt_e return nevpt_e
def solve(myMF, dm_guess=None, safe_guess=True): assert hasattr(myMF, "mol") assert hasattr(myMF, "mo_occ") assert hasattr(myMF, "mo_coeff") assert myMF.mol.nelectron % 2 == 0 # RHF possible S_ao = myMF.get_ovlp(myMF.mol) OEI_ao = myMF.get_hcore(myMF.mol) numPairs = myMF.mol.nelectron // 2 numVirt = OEI_ao.shape[0] - numPairs numVars = numPairs * numVirt if dm_guess is None: if (len(myMF.mo_occ) == 0) or (safe_guess == True): dm_ao = myMF.get_init_guess(key=myMF.init_guess, mol=myMF.mol) else: dm_ao = np.dot(np.dot(myMF.mo_coeff, np.diag(myMF.mo_occ)), myMF.mo_coeff.T) else: dm_ao = np.array(dm_guess, copy=True) myJK_ao = __JKengine(myMF) FOCK_ao = OEI_ao + myJK_ao.getJK_ao(dm_ao) energies, orbitals = scipy.linalg.eigh(a=FOCK_ao, b=S_ao) dm_ao = 2 * np.dot(orbitals[:, :numPairs], orbitals[:, :numPairs].T) FOCK_ao = OEI_ao + myJK_ao.getJK_ao(dm_ao) FOCK_mo = np.dot(orbitals.T, np.dot(FOCK_ao, orbitals)) grdnorm = 4 * np.linalg.norm(FOCK_mo[:numPairs, numPairs:]) energy = myMF.mol.energy_nuc() + 0.5 * np.einsum("ij,ij->", OEI_ao + FOCK_ao, dm_ao) logger.note(myMF, "RHF:NewtonRaphson :: Starting augmented Hessian Newton-Raphson RHF.") iteration = 0 while grdnorm > 1e-7: iteration += 1 tempJK_mo = __JKengine(myMF, orbitals) ini_guess = np.ones([numVars + 1], dtype=float) for occ in range(numPairs): for virt in range(numVirt): ini_guess[occ + numPairs * virt] = -FOCK_mo[occ, numPairs + virt] / max( FOCK_mo[numPairs + virt, numPairs + virt] - FOCK_mo[occ, occ], 1e-6 ) def myprecon(resid, eigval, eigvec): myprecon_cutoff = 1e-10 local_myprecon = np.zeros([numVars + 1], dtype=float) for occ in range(numPairs): for virt in range(numVirt): denominator = FOCK_mo[numPairs + virt, numPairs + virt] - FOCK_mo[occ, occ] - eigval if abs(denominator) < myprecon_cutoff: local_myprecon[occ + numPairs * virt] = eigvec[occ + numPairs * virt] / myprecon_cutoff else: # local_myprecon = eigvec / ( diag(H) - eigval ) = K^{-1} u local_myprecon[occ + numPairs * virt] = eigvec[occ + numPairs * virt] / denominator if abs(eigval) < myprecon_cutoff: local_myprecon[numVars] = eigvec[numVars] / myprecon_cutoff else: local_myprecon[numVars] = -eigvec[numVars] / eigval # alpha_myprecon = - ( r, K^{-1} u ) / ( u, K^{-1} u ) alpha_myprecon = -np.einsum("i,i->", local_myprecon, resid) / np.einsum("i,i->", local_myprecon, eigvec) # local_myprecon = r - ( r, K^{-1} u ) / ( u, K^{-1} u ) * u local_myprecon = resid + alpha_myprecon * eigvec for occ in range(numPairs): for virt in range(numVirt): denominator = FOCK_mo[numPairs + virt, numPairs + virt] - FOCK_mo[occ, occ] - eigval if abs(denominator) < myprecon_cutoff: local_myprecon[occ + numPairs * virt] = -local_myprecon[occ + numPairs * virt] / myprecon_cutoff else: local_myprecon[occ + numPairs * virt] = -local_myprecon[occ + numPairs * virt] / denominator if abs(eigval) < myprecon_cutoff: local_myprecon[numVars] = -local_myprecon[occ + numPairs * virt] / myprecon_cutoff else: local_myprecon[numVars] = local_myprecon[occ + numPairs * virt] / eigval return local_myprecon eigenval, eigenvec = linalg_helper.davidson( aop=__wrapAugmentedHessian(FOCK_mo, numPairs, numVirt, tempJK_mo), x0=ini_guess, precond=myprecon, # tol=1e-14, \ # max_cycle=50, \ max_space=20, # lindep=1e-16, \ # max_memory=2000, \ nroots=1, ) # logger.note(myMF, " RHF:NewtonRaphson :: # JK computs (iteration %d) = %d", iteration, tempJK_mo.iter) eigenvec = eigenvec / eigenvec[numVars] update = np.reshape(eigenvec[:-1], (numPairs, numVirt), order="F") xmat = np.zeros([OEI_ao.shape[0], OEI_ao.shape[0]], dtype=float) xmat[:numPairs, numPairs:] = -update xmat[numPairs:, :numPairs] = update.T unitary = scipy.linalg.expm(xmat) orbitals = np.dot(orbitals, unitary) dm_ao = 2 * np.dot(orbitals[:, :numPairs], orbitals[:, :numPairs].T) FOCK_ao = OEI_ao + myJK_ao.getJK_ao(dm_ao) FOCK_mo = np.dot(orbitals.T, np.dot(FOCK_ao, orbitals)) grdnorm = 4 * np.linalg.norm(FOCK_mo[:numPairs, numPairs:]) energy = myMF.mol.energy_nuc() + 0.5 * np.einsum("ij,ij->", OEI_ao + FOCK_ao, dm_ao) logger.note(myMF, " RHF:NewtonRaphson :: gradient norm (iteration %d) = %1.3g", iteration, grdnorm) logger.note(myMF, " RHF:NewtonRaphson :: RHF energy (iteration %d) = %1.15g", iteration, energy) logger.note(myMF, "RHF:NewtonRaphson :: Convergence reached.") logger.note(myMF, "RHF:NewtonRaphson :: Converged RHF energy = %1.15g", energy) energies, orbitals = scipy.linalg.eigh(a=FOCK_ao, b=S_ao) myMF.mo_coeff = orbitals myMF.mo_occ = np.zeros([OEI_ao.shape[0]], dtype=int) myMF.mo_occ[:numPairs] = 2 myMF.mo_energy = energies myMF.hf_energy = energy myMF.converged = True return myMF
def _finalize(self): if self.verbose >= logger.NOTE: logger.note(self, '--------------- %s gradients ---------------', self.base.__class__.__name__) rhf_grad._write(self, self.mol, self.de, self.atmlst) logger.note(self, '----------------------------------------------')