def uhf_external(mf, with_symmetry=True, verbose=None): log = logger.new_logger(mf, verbose) hop1, hdiag1, hop2, hdiag2 = _gen_hop_uhf_external(mf, with_symmetry) def precond(dx, e, x0): hdiagd = hdiag1 - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return dx / hdiagd x0 = numpy.zeros_like(hdiag1) x0[hdiag1 > 1e-5] = 1. / hdiag1[hdiag1 > 1e-5] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag1)] = 1 e1, v = lib.davidson(hop1, x0, precond, tol=1e-4, verbose=log) if e1 < -1e-5: log.note('UHF/UKS wavefunction has a real -> complex instability') else: log.note( 'UHF/UKS wavefunction is stable in the real -> complex stability analysis' ) def precond(dx, e, x0): hdiagd = hdiag2 - e hdiagd[abs(hdiagd) < 1e-8] = 1e-8 return dx / hdiagd x0 = numpy.zeros_like(hdiag2) x0[hdiag2 > 1e-5] = 1. / hdiag2[hdiag2 > 1e-5] if not with_symmetry: # allow to break point group symmetry x0[numpy.argmin(hdiag2)] = 1 e3, v = lib.davidson(hop2, x0, precond, tol=1e-4, verbose=log) log.debug('uhf_external: lowest eigs of H = %s', e3) mo = scipy.linalg.block_diag(*mf.mo_coeff) if e3 < -1e-5: stable_e = False # added by qingchun 3/13 2018 log.note('UHF/UKS wavefunction has an UHF/UKS -> GHF/GKS instability.') occidxa = numpy.where(mf.mo_occ[0] > 0)[0] viridxa = numpy.where(mf.mo_occ[0] == 0)[0] occidxb = numpy.where(mf.mo_occ[1] > 0)[0] viridxb = numpy.where(mf.mo_occ[1] == 0)[0] nocca = len(occidxa) nvira = len(viridxa) noccb = len(occidxb) nvirb = len(viridxb) nmo = nocca + nvira dx = numpy.zeros((nmo * 2, nmo * 2)) dx[viridxa[:, None], nmo + occidxb] = v[:nvira * noccb].reshape(nvira, noccb) dx[nmo + viridxb[:, None], occidxa] = v[nvira * noccb:].reshape(nvirb, nocca) u = newton_ah.expmat(dx - dx.T) mo = numpy.dot(mo, u) else: stable_e = True # added by qingchun 3/13 2018 log.note( 'UHF/UKS wavefunction is stable in the UHF/UKS -> GHF/GKS stability analysis' ) return mo, stable_e
def update_rotate_matrix(self, dx, mo_occ, u0=1): p0 = 0 u = [] for k, occ in enumerate(mo_occ): occidx = occ > 0 viridx = ~occidx nocc = occidx.sum() nvir = viridx.sum() nmo = nocc + nvir dr = numpy.zeros((nmo, nmo), dtype=dx.dtype) dr[viridx[:, None] & occidx] = dx[p0:p0 + nocc * nvir] dr = dr - dr.T.conj() p0 += nocc * nvir u1 = newton_ah.expmat(dr) if isinstance(u0, int) and u0 == 1: u.append(u1) else: u.append(numpy.dot(u0[k], u1)) return lib.asarray(u)
def update_rotate_matrix(self, dx, mo_occ, u0=1): nmo = mo_occ.shape[-1] p0 = 0 u = [] for k, occ in enumerate(mo_occ): occidx = occ > 0 viridx = ~occidx nocc = occidx.sum() nvir = nmo - nocc dr = numpy.zeros((nmo,nmo), dtype=dx.dtype) dr[viridx[:,None]&occidx] = dx[p0:p0+nocc*nvir] dr = dr - dr.T.conj() p0 += nocc * nvir u1 = newton_ah.expmat(dr) if isinstance(u0, int) and u0 == 1: u.append(u1) else: u.append(numpy.dot(u0[k], u1)) return lib.asarray(u)
def update_rotate_matrix(self, dx, mo_occ, u0=1): nkpts = len(mo_occ[0]) nmo = mo_occ[0].shape[-1] p0 = 0 u = [] for occ in mo_occ: ua = [] for k in range(nkpts): occidx = occ[k] > 0 viridx = ~occidx nocc = occidx.sum() nvir = nmo - nocc dr = numpy.zeros((nmo, nmo), dtype=dx.dtype) dr[viridx[:, None] & occidx] = dx[p0:p0 + nocc * nvir] dr = dr - dr.T.conj() p0 += nocc * nvir u1 = newton_ah.expmat(dr) if isinstance(u0, int) and u0 == 1: ua.append(u1) else: ua.append(numpy.dot(u0[k], u1)) u.append(ua) return lib.asarray(u)
def _rotate_mo(mo_coeff, mo_occ, dx): dr = hf.unpack_uniq_var(dx, mo_occ) u = newton_ah.expmat(dr) return numpy.dot(mo_coeff, u)