Beispiel #1
0
 def CalcHfEnergy(self, Rdm):
     # calculate the RHF energy for a given density matrix.
     Fock, j, k = MakeFockOp(Rdm, self.CoreH, self.Int2e_Frs, self.ORB_OCC,
                             self.Int2e_4ix)
     Energy = 0.5 * (dot2(Fock, Rdm) +
                     dot2(self.CoreH, Rdm)) + self.CoreEnergy
     return Energy
Beispiel #2
0
   def RunFci0(self, Log, SpecialSites = None, CiMethod="FCI"):
      import fci_iface as fi
      from os import remove
      p = Log['EmbCalc']
      #def DeleteFciVectorFile():
         ## remove left-over FCI vector if present
         #try: remove(fi.FileNameFciVec)
         #except OSError,e: pass
      #DeleteFciVectorFile()

      def MakeBasis(Fock):
         # TODO: Move this. This should not be here.
         if self.WfDecl.OrbType == "RHF":
            return eigh(Fock)[1]
         elif self.WfDecl.OrbType == "UHF":
            ESC = ExtractSpinComp
            EwA,OrbsA = eigh(ESC(Fock,0))
            EwB,OrbsB = eigh(ESC(Fock,1))
            Orbs = zeros(Fock.shape)
            Orbs[ ::2, ::2] = OrbsA[:,:]
            Orbs[1::2,1::2] = OrbsB[:,:]
            return Orbs
         else:
            assert(0)

      nSysTrace=None
      if ( SpecialSites is not None ):
         nSysTrace = len(SpecialSites)
         assert((array(SpecialSites) == arange(0, len(SpecialSites))).all())
      HL = fi.FindFciSolution(self.CoreH, U=1., nSys_=self.nOrb, # <- both unused.
         nElec=self.WfDecl.nElec, CiMethod=CiMethod,Int2e_=self.MakeOrGet_Int2e_4ix(),
         nSysTrace=nSysTrace, IntType=self.OrbType, MakeRdm2=False, DiagBasis=MakeBasis(self.FockGuess))
      with Log.Section("ci", "Full CI output"):
         Log(HL["Output"] + "\n")
      Energy, rdm = HL["Energy"], HL["Rdm1"]
      OccNumbers,Orbs = eigh(-rdm); OccNumbers *= -1.
      EmbEnergy = None
      EmbElec = None
      Energy1e = dot2(self.CoreH, rdm)
      Energy2e= Energy - Energy1e
      if p:
         Log("%-32s     %-s" % ("Natural occupation", " ".join(["%7.4f" % o for o in OccNumbers])))
         Log(pResultFmt, "Full-CI energy", Energy)
         Log()
      if ( SpecialSites is not None ):
         EmbElec = trace(rdm[:,SpecialSites][SpecialSites,:])
         FakeSys = self.MakeImpPrjSystem(SpecialSites)
         # 2e energy calculated by FCI program itself.
         EmbEnergy = dot2(rdm, FakeSys.CoreH) + HL["EpTrace"] + FakeSys.CoreEnergy

         if p:
            Log(pResultFmt, "Embedded subsystem energy", EmbEnergy)
            Log(pResultFmt, "Embedded subsystem electrons", EmbElec)
            Log()

      #DeleteFciVectorFile()
      return FCalcResult(Energy, Energy2e, Orbs, OccNumbers, EmbElec=EmbElec, EmbEnergy=EmbEnergy)
Beispiel #3
0
    def _RunHf(self, Log):
        P = self.P
        sc = self.SuperCell
        Log(pInfoFmt, "Number of sites", sc.nSites)
        Log(pInfoFmt, "Number of sites in unit-cell", sc.nSitesU)
        Log()
        if self.P.MaxIt == 1:
            self.FockT = self.CoreH
            self.GuessType = "CoreH (due to non-SCF)"
        Log(pInfoFmt, "Initial guess", self.GuessType)
        f = 1.0 / (1.0 * sc.nUnitCellsTotal)
        if self.WfDecl.OrbType == "RHF":
            Log(pInfoFmt, "Electrons in unit-cell", f * self.WfDecl.nElec)
        else:
            Log(pInfoFmt, "Electrons in unit-cell", (f * self.WfDecl.nElecA(), f * self.WfDecl.nElecB()))
            # Log(pInfoFmt,"Electrons in unit-cell", self.WfDecl.nElecA()/(1.*sc.nUnitCellsTotal), "(alpha)")
            # Log(pInfoFmt,"Electrons in unit-cell", self.WfDecl.nElecB()/(1.*sc.nUnitCellsTotal), "(beta)")
        Log()

        # at this moment we have self.CoreH and self.Fock (initial guess).
        FockT = self.FockT
        Log("   {:^5s} {:^14s} {:^14s} {:^11s} {:>4s}", "ITER.", "ENERGY", "ENERGY CHANGE", "GRAD", "DIIS")
        EnergyFactor = self._EnergyFactor()
        # ^- calc energy per lattice model unit-cell
        LastRdm = None
        LastEnergy = 0.0
        Converged = False
        dc = FDiisContext(P.DiisDim)
        for it in range(P.MaxIt):
            # transform Fock operator to translational irreps.
            FockK = sc.TransformToK(FockT)

            # make new orbitals and new rdm.
            Ew, Orbs = self.UpdateOrbitals(FockK)

            # Log("Fock spectrum (nSitesU x nGridK):\n{}", Ew.T)
            OccNumbers, RdmK, Mu, Gap = self.MakeRdm(Orbs, Ew)
            RdmT = sc.TransformToT(RdmK)

            # make new Fock matrix
            if P.MaxIt != 1 or True:
                FockT, j, k = self.MakeFock(RdmT, self.CoreH, self.Int2e_U, Orb=Orbs)
                self.HaveFock = True
            else:
                # in this case diagonalize CoreH only, do not incorporate
                # 2e potentials via HF mean-field, only via vcor.
                self.HaveFock = False
            Energy = (0.5 * (dot2(FockT, RdmT) + dot2(self.CoreH, RdmT)) + self.CoreEnergy).real
            Energy *= EnergyFactor

            # FockT = 1.*self.CoreH

            # print "Rdm:\n%s" % sc._ExpandFull(RdmT).real
            # print "Fock:\n%s" % sc._ExpandFull(FockT).real

            # Grd1 = np.dot(sc._ExpandFull(FockT),sc._ExpandFull(RdmT))
            # Grd1 = Grd1 - np.conj(Grd1.T)
            # print "Grd1:\n%s" % Grd1.real
            # raise SystemExit

            # calculate orbital gradient and energy
            FockK = sc.TransformToK(FockT)
            OrbGrad = np.zeros_like(FockK)
            for ik in xrange(FockK.shape[0]):
                OrbGrad[ik] = np.dot(FockK[ik], RdmK[ik])
                OrbGrad[ik] = OrbGrad[ik] - np.conj(OrbGrad[ik].T)
                # ^- fun fact: "OrbGrad -= OrbGrad.T" is an unsafe operation
                #    which, depending on circumstances, might or might not produce
                #    the expected result (well.. kinda obvious in hindsight).
                if self.WfDecl.OrbType == "UHF":
                    OrbGrad[ik, ::2, 1::2] = 0.0
                    OrbGrad[ik, 1::2, ::2] = 0.0

            fOrbGrad = la.norm(OrbGrad.flatten())
            dEnergy = Energy - LastEnergy
            LastEnergy = Energy

            Log(
                " {:5d} {:14.8f} {:+14.8f} {:11.2e} {:>6s}",
                (it + 1 if P.MaxIt != 1 else 0),
                Energy,
                dEnergy,
                fOrbGrad,
                dc,
            )

            if fOrbGrad < P.ThrOrb and abs(dEnergy) < P.ThrDen:
                Converged = True
                break
            if it == P.MaxIt - 1:
                break  # not converged.

            # extrapolate
            # SkipDiis = (fOrbGrad > 1e-2 and it < 1)
            SkipDiis = it < P.DiisStart or fOrbGrad > P.DiisThr
            FockT, OrbGrad, c0 = dc.Apply(FockT, OrbGrad, Skip=SkipDiis)

        if not Converged and P.MaxIt != 1:
            ErrMsg = "%s failed to converge." "  NIT =%4i  GRAD=%8.2e  DEN=%8.2e" % (
                self.WfDecl.OrbType,
                it + 1,
                fOrbGrad,
                dEnergy,
            )
            print "WARNING: %s" % ErrMsg
            if 0:
                print "Failed FSystem object stored to file 'brrrk' for investigation."
                import pickle

                pickle.dump(self, open("brrrk", "w"))
            raise EHfConvergenceFail(ErrMsg)
        else:
            # print
            # PrintMatrix("Diagonal RDM:",diag(Rdm))
            Log()
            Log(pResultFmt, "Chemical potential", Mu)
            # Log(pResultFmt, "H**O-LUMO gap", Gap)
            Log(pResultFmt, "Band gap", Gap)
            if Log["HfDensities"]:
                Log()
                if self.WfDecl.OrbType == "UHF":
                    Log(self.FmtRho, "Charge density", RdmT[0].real, "_")
                    Log(self.FmtRho, "Spin density", RdmT[0].real, "S")
                else:
                    Log(self.FmtRho, "Charge density", RdmT[0].real, "_")
            Log()
            Log(pResultFmt, "1e energy", dot2(RdmT, self.CoreH) * EnergyFactor)
            Log(pResultFmt, "2e energy", 0.5 * dot2(RdmT, FockT - self.CoreH) * EnergyFactor)
            Log(pResultFmt, "Hartree-Fock energy", Energy)

        Log(pResultFmt, "Total potential", FockT[0] - self.CoreH_Unpatched[0], self.WfDecl.OrbType)
        if P.MaxIt == 1:
            FockT = self.CoreH
            self.HaveFock = False
            # ^- other code assumes that .Fock is what we actually diagonalized.
            # Log(Log.WARNING, "Turning off Fock potentials in non-iterative lattice mean-field.")

        self.FockT = FockT
        self.RdmT = RdmT
        self.MeanFieldEnergy = EnergyFactor * Energy
        self.Mu = Mu
        self.Gap = Gap
        self.GuessType = "Fock/Last"
Beispiel #4
0
    def _RunHf(self, Log):
        P = self.P
        sc = self.SuperCell
        Log(pInfoFmt, "Number of sites", sc.nSites)
        Log(pInfoFmt, "Number of sites in unit-cell", sc.nSitesU)
        Log()
        if self.P.MaxIt == 1:
            self.FockT = self.CoreH
            self.GuessType = "CoreH (due to non-SCF)"
        Log(pInfoFmt, "Initial guess", self.GuessType)
        f = 1. / (1. * sc.nUnitCellsTotal)
        if self.WfDecl.OrbType == "RHF":
            Log(pInfoFmt, "Electrons in unit-cell", f * self.WfDecl.nElec)
        else:
            Log(pInfoFmt, "Electrons in unit-cell",
                (f * self.WfDecl.nElecA(), f * self.WfDecl.nElecB()))
            #Log(pInfoFmt,"Electrons in unit-cell", self.WfDecl.nElecA()/(1.*sc.nUnitCellsTotal), "(alpha)")
            #Log(pInfoFmt,"Electrons in unit-cell", self.WfDecl.nElecB()/(1.*sc.nUnitCellsTotal), "(beta)")
        Log()

        # at this moment we have self.CoreH and self.Fock (initial guess).
        FockT = self.FockT
        Log("   {:^5s} {:^14s} {:^14s} {:^11s} {:>4s}", "ITER.", "ENERGY",
            "ENERGY CHANGE", "GRAD", "DIIS")
        EnergyFactor = self._EnergyFactor()
        # ^- calc energy per lattice model unit-cell
        LastRdm = None
        LastEnergy = 0.
        Converged = False
        dc = FDiisContext(P.DiisDim)
        for it in range(P.MaxIt):
            # transform Fock operator to translational irreps.
            FockK = sc.TransformToK(FockT)

            # make new orbitals and new rdm.
            Ew, Orbs = self.UpdateOrbitals(FockK)

            #Log("Fock spectrum (nSitesU x nGridK):\n{}", Ew.T)
            OccNumbers, RdmK, Mu, Gap = self.MakeRdm(Orbs, Ew)
            RdmT = sc.TransformToT(RdmK)

            # make new Fock matrix
            if P.MaxIt != 1 or True:
                FockT, j, k = self.MakeFock(RdmT,
                                            self.CoreH,
                                            self.Int2e_U,
                                            Orb=Orbs)
                self.HaveFock = True
            else:
                # in this case diagonalize CoreH only, do not incorporate
                # 2e potentials via HF mean-field, only via vcor.
                self.HaveFock = False
            Energy = (0.5 * (dot2(FockT, RdmT) + dot2(self.CoreH, RdmT)) +
                      self.CoreEnergy).real
            Energy *= EnergyFactor

            #FockT = 1.*self.CoreH

            #print "Rdm:\n%s" % sc._ExpandFull(RdmT).real
            #print "Fock:\n%s" % sc._ExpandFull(FockT).real

            #Grd1 = np.dot(sc._ExpandFull(FockT),sc._ExpandFull(RdmT))
            #Grd1 = Grd1 - np.conj(Grd1.T)
            #print "Grd1:\n%s" % Grd1.real
            #raise SystemExit

            # calculate orbital gradient and energy
            FockK = sc.TransformToK(FockT)
            OrbGrad = np.zeros_like(FockK)
            for ik in xrange(FockK.shape[0]):
                OrbGrad[ik] = np.dot(FockK[ik], RdmK[ik])
                OrbGrad[ik] = OrbGrad[ik] - np.conj(OrbGrad[ik].T)
                # ^- fun fact: "OrbGrad -= OrbGrad.T" is an unsafe operation
                #    which, depending on circumstances, might or might not produce
                #    the expected result (well.. kinda obvious in hindsight).
                if self.WfDecl.OrbType == "UHF":
                    OrbGrad[ik, ::2, 1::2] = 0.
                    OrbGrad[ik, 1::2, ::2] = 0.

            fOrbGrad = la.norm(OrbGrad.flatten())
            dEnergy = Energy - LastEnergy
            LastEnergy = Energy

            Log(" {:5d} {:14.8f} {:+14.8f} {:11.2e} {:>6s}",
                (it + 1 if P.MaxIt != 1 else 0), Energy, dEnergy, fOrbGrad, dc)

            if (fOrbGrad < P.ThrOrb and abs(dEnergy) < P.ThrDen):
                Converged = True
                break
            if (it == P.MaxIt - 1):
                break  # not converged.

            # extrapolate
            #SkipDiis = (fOrbGrad > 1e-2 and it < 1)
            SkipDiis = it < P.DiisStart or fOrbGrad > P.DiisThr
            FockT, OrbGrad, c0 = dc.Apply(FockT, OrbGrad, Skip=SkipDiis)

        if (not Converged and P.MaxIt != 1):
            ErrMsg = "%s failed to converge."\
                     "  NIT =%4i  GRAD=%8.2e  DEN=%8.2e" % (self.WfDecl.OrbType, it+1, fOrbGrad, dEnergy)
            print "WARNING: %s" % ErrMsg
            if 0:
                print "Failed FSystem object stored to file 'brrrk' for investigation."
                import pickle
                pickle.dump(self, open('brrrk', 'w'))
            raise EHfConvergenceFail(ErrMsg)
        else:
            #print
            #PrintMatrix("Diagonal RDM:",diag(Rdm))
            Log()
            Log(pResultFmt, "Chemical potential", Mu)
            #Log(pResultFmt, "H**O-LUMO gap", Gap)
            Log(pResultFmt, "Band gap", Gap)
            if Log['HfDensities']:
                Log()
                if self.WfDecl.OrbType == "UHF":
                    Log(self.FmtRho, 'Charge density', RdmT[0].real, '_')
                    Log(self.FmtRho, 'Spin density', RdmT[0].real, 'S')
                else:
                    Log(self.FmtRho, 'Charge density', RdmT[0].real, 'A')
            Log()
            Log(pResultFmt, "1e energy", dot2(RdmT, self.CoreH) * EnergyFactor)
            Log(pResultFmt, "2e energy",
                .5 * dot2(RdmT, FockT - self.CoreH) * EnergyFactor)
            Log(pResultFmt, "Hartree-Fock energy", Energy)

        Log(pResultFmt, "Total potential", FockT[0] - self.CoreH_Unpatched[0],
            self.WfDecl.OrbType)
        if P.MaxIt == 1:
            FockT = self.CoreH
            self.HaveFock = False
            # ^- other code assumes that .Fock is what we actually diagonalized.
            #Log(Log.WARNING, "Turning off Fock potentials in non-iterative lattice mean-field.")

        self.FockT = FockT
        self.RdmT = RdmT
        self.MeanFieldEnergy = EnergyFactor * Energy
        self.Mu = Mu
        self.Gap = Gap
        self.GuessType = 'Fock/Last'
Beispiel #5
0
    def RunHf(self, Log, SpecialSites=None):
        MAXIT_HF = 1024
        THRORB = 1e-8
        THRDEN = 1e-8

        nOrb = self.nOrb
        if (self.FockGuess is None):
            # coreH guess
            Fock = self.CoreH
        else:
            Fock = self.FockGuess

        p = Log['EmbCalc']
        with Log.Section(
                "hf", "%sHARTREE-FOCK" %
            (["", "EMBEDDED "][SpecialSites != None] +
             ["", "UNRESTRICTED "][self.OrbType == "UHF"]), 1):
            if p:
                Log("%-35s%5i FUNCTIONS" % ("Orbital basis:", nOrb))
                if self.Int2e_Frs is not None:
                    Log("%-35s%5i FUNCTIONS" %
                        ("Fitting basis:", self.Int2e_Frs.shape[0]))
                Log()

            Converged = False
            RefRdm = None
            LastEnergy = 0.

            dc = FDiisContext(12)
            Log("  {:^5s} {:^14s} {:^14s} {:^11s} {:>4s}", "ITER.", "ENERGY",
                "ENERGY CHANGE", "GRAD", "DIIS")
            LastRdm = None
            for it in range(MAXIT_HF):
                # make new orbitals and new rdm.
                if self.OrbType == "RHF":
                    Ew, Orbs = eigh(Fock)
                    nOcc = self.WfDecl.nElec / 2
                    assert (self.WfDecl.nElec % 2 == 0)
                    Rdm = self.ORB_OCC * dot(Orbs[:, :nOcc], Orbs[:, :nOcc].T)
                else:
                    ESC = ExtractSpinComp
                    EwA, OrbsA = eigh(ESC(Fock, 0), ESC(RefRdm, 0), 0)
                    EwB, OrbsB = eigh(ESC(Fock, 1), ESC(RefRdm, 1), 1)
                    Ew = CombineSpinComps(EwA, EwB)
                    Orbs = zeros((nOrb, nOrb))
                    Orbs[::2, ::2] = OrbsA[:, :]
                    Orbs[1::2, 1::2] = OrbsB[:, :]
                    nOccA, nOccB = self.WfDecl.nElecA(), self.WfDecl.nElecB()
                    nOcc = nOccA + nOccB
                    Rdm = CombineSpinComps(
                        dot(OrbsA[:, :nOccA], OrbsA[:, :nOccA].T),
                        dot(OrbsB[:, :nOccB], OrbsB[:, :nOccB].T))

                # make closed-shell Fock matrix:
                #   f[rs] = h[rs] + j[rs] - .5 k[rs]
                Fock, j, k = MakeFockOp(Rdm,
                                        self.CoreH,
                                        self.Int2e_Frs,
                                        self.ORB_OCC,
                                        Int2e_4ix=self.Int2e_4ix,
                                        Orb=Orbs)
                Energy = 0.5 * (dot2(Fock, Rdm) +
                                dot2(self.CoreH, Rdm)) + self.CoreEnergy

                # calculate orbital gradient and energy
                OrbGrad = dot(Fock, Rdm)
                if self.OrbType == "UHF":
                    OrbGrad[::2, 1::2] = 0
                    OrbGrad[1::2, 0::2] = 0
                OrbGrad = OrbGrad - OrbGrad.T
                # ^- fun fact: "OrbGrad -= OrbGrad.T" is an unsafe operation
                #    which, depending on circumstances, might or might not produce
                #    the expected result (well.. kinda obvious in hindsight).

                fOrbGrad = norm(OrbGrad.flatten())
                dEnergy = Energy - LastEnergy
                LastEnergy = Energy

                Log("{:5d} {:14.8f} {:+14.8f} {:11.2e} {:>6s}", it + 1, Energy,
                    dEnergy, fOrbGrad, dc)

                if (fOrbGrad < THRORB and abs(dEnergy) < THRDEN):
                    Converged = True
                    break
                if (it == MAXIT_HF - 1):
                    break  # not converged.

                SkipDiis = False
                Fock, OrbGrad, c0 = dc.Apply(Fock, OrbGrad, Skip=SkipDiis)

            if (not Converged and MAXIT_HF != 1):
                ErrMsg = "%s failed to converge."\
                         "  NIT =%4i  GRAD=%8.2e  DEN=%8.2e" % (self.OrbType, it+1, fOrbGrad, dEnergy)
                Log(Log.WARNING, ErrMsg)
                if 0:
                    print "Failed FSystem object stored to file 'brrrk' for investigation."
                    import pickle
                    pickle.dump(self, open('brrrk', 'w'))
                raise ERhfConvergenceFail(ErrMsg)
            elif p:
                Log()
                Log(pResultFmt, "1e energy", dot2(Rdm, self.CoreH))
                Log(pResultFmt, "2e energy", .5 * dot2(Rdm, Fock - self.CoreH))
                if (self.CoreEnergy != 0.0):
                    Log()
                    Log(pResultFmt, "Core energy", self.CoreEnergy)
                    Log(pResultFmt, "Electronic energy",
                        Energy - self.CoreEnergy)
                Log(pResultFmt, "Hartree-Fock energy", Energy)
                Log()

            EmbEnergy = None
            EmbElec = None
            if (SpecialSites is not None):
                # calculate number of electrons and energy in the embedded system.
                EmbElec = trace(Rdm[:, SpecialSites][SpecialSites, :])
                FakeSys = self.MakeImpPrjSystem(SpecialSites)
                EmbEnergy = FakeSys.CalcHfEnergy(Rdm)
                if p:
                    Log(pResultFmt, "Embedded subsystem energy", EmbEnergy)
                    Log(pResultFmt, "Embedded subsystem electrons", EmbElec)
                    Log()

        return FHfResult(Energy,
                         Orbs,
                         nOcc,
                         self.ORB_OCC,
                         Fock,
                         EmbElec=EmbElec,
                         EmbEnergy=EmbEnergy,
                         Ews=Ew)
Beispiel #6
0
   def RunHf(self, Log, SpecialSites = None):
      MAXIT_HF = 1024
      THRORB = 1e-8
      THRDEN = 1e-8

      nOrb = self.nOrb
      if ( self.FockGuess is None ):
         # coreH guess
         Fock = self.CoreH
      else:
         Fock = self.FockGuess

      p = Log['EmbCalc']
      with Log.Section("hf","%sHARTREE-FOCK" % (["","EMBEDDED "][SpecialSites!=None] + ["","UNRESTRICTED "][self.OrbType=="UHF"]),1):
         if p:
            Log("%-35s%5i FUNCTIONS" % ("Orbital basis:", nOrb))
            if self.Int2e_Frs is not None:
               Log("%-35s%5i FUNCTIONS" % ("Fitting basis:", self.Int2e_Frs.shape[0]))
            Log()

         Converged = False
         RefRdm = None
         LastEnergy = 0.

         dc = FDiisContext(12)
         Log("  {:^5s} {:^14s} {:^14s} {:^11s} {:>4s}",
            "ITER.","ENERGY","ENERGY CHANGE", "GRAD", "DIIS")
         LastRdm = None
         for it in range(MAXIT_HF):
            # make new orbitals and new rdm.
            if self.OrbType == "RHF":
               Ew,Orbs = eigh(Fock)
               nOcc = self.WfDecl.nElec / 2
               assert(self.WfDecl.nElec % 2 == 0)
               Rdm = self.ORB_OCC * dot(Orbs[:,:nOcc], Orbs[:,:nOcc].T)
            else:
               ESC = ExtractSpinComp
               EwA,OrbsA = eigh(ESC(Fock,0), ESC(RefRdm,0), 0)
               EwB,OrbsB = eigh(ESC(Fock,1), ESC(RefRdm,1), 1)
               Ew = CombineSpinComps(EwA,EwB)
               Orbs = zeros((nOrb,nOrb))
               Orbs[ ::2, ::2] = OrbsA[:,:]
               Orbs[1::2,1::2] = OrbsB[:,:]
               nOccA, nOccB = self.WfDecl.nElecA(), self.WfDecl.nElecB()
               nOcc = nOccA + nOccB
               Rdm = CombineSpinComps(dot(OrbsA[:,:nOccA], OrbsA[:,:nOccA].T),
                                      dot(OrbsB[:,:nOccB], OrbsB[:,:nOccB].T))


            # make closed-shell Fock matrix:
            #   f[rs] = h[rs] + j[rs] - .5 k[rs]
            Fock, j, k = MakeFockOp(Rdm, self.CoreH, self.Int2e_Frs, self.ORB_OCC,
                                    Int2e_4ix=self.Int2e_4ix, Orb=Orbs)
            Energy = 0.5 * (dot2(Fock, Rdm) + dot2(self.CoreH, Rdm)) + self.CoreEnergy

            # calculate orbital gradient and energy
            OrbGrad = dot(Fock,Rdm)
            if self.OrbType == "UHF":
               OrbGrad[ ::2,1::2] = 0
               OrbGrad[1::2,0::2] = 0
            OrbGrad = OrbGrad - OrbGrad.T
            # ^- fun fact: "OrbGrad -= OrbGrad.T" is an unsafe operation
            #    which, depending on circumstances, might or might not produce
            #    the expected result (well.. kinda obvious in hindsight).

            fOrbGrad = norm(OrbGrad.flatten())
            dEnergy = Energy - LastEnergy
            LastEnergy = Energy

            Log("{:5d} {:14.8f} {:+14.8f} {:11.2e} {:>6s}",
               it+1, Energy, dEnergy, fOrbGrad, dc)

            if (fOrbGrad < THRORB and abs(dEnergy) < THRDEN):
               Converged = True
               break
            if (it == MAXIT_HF - 1):
               break # not converged.

            SkipDiis = False
            Fock, OrbGrad, c0 = dc.Apply(Fock, OrbGrad, Skip=SkipDiis)

         if (not Converged and MAXIT_HF != 1):
            ErrMsg = "%s failed to converge."\
                     "  NIT =%4i  GRAD=%8.2e  DEN=%8.2e" % (self.OrbType, it+1, fOrbGrad, dEnergy)
            Log(Log.WARNING, ErrMsg)
            if 0:
               print "Failed FSystem object stored to file 'brrrk' for investigation."
               import pickle
               pickle.dump(self,open('brrrk','w'))
            raise ERhfConvergenceFail(ErrMsg)
         elif p:
            Log()
            Log(pResultFmt, "1e energy", dot2(Rdm, self.CoreH))
            Log(pResultFmt, "2e energy", .5*dot2(Rdm, Fock - self.CoreH))
            if (self.CoreEnergy != 0.0):
               Log()
               Log(pResultFmt, "Core energy", self.CoreEnergy)
               Log(pResultFmt, "Electronic energy", Energy - self.CoreEnergy)
            Log(pResultFmt, "Hartree-Fock energy", Energy)
            Log()

         EmbEnergy = None
         EmbElec = None
         if (SpecialSites is not None):
            # calculate number of electrons and energy in the embedded system.
            EmbElec = trace(Rdm[:,SpecialSites][SpecialSites,:])
            FakeSys = self.MakeImpPrjSystem(SpecialSites)
            EmbEnergy = FakeSys.CalcHfEnergy(Rdm)
            if p:
               Log(pResultFmt, "Embedded subsystem energy", EmbEnergy)
               Log(pResultFmt, "Embedded subsystem electrons", EmbElec)
               Log()

      return FHfResult(Energy, Orbs, nOcc, self.ORB_OCC, Fock, EmbElec=EmbElec, EmbEnergy=EmbEnergy, Ews=Ew)
Beispiel #7
0
 def CalcHfEnergy(self, Rdm):
    # calculate the RHF energy for a given density matrix.
    Fock, j, k = MakeFockOp(Rdm, self.CoreH, self.Int2e_Frs, self.ORB_OCC, self.Int2e_4ix)
    Energy = 0.5 * (dot2(Fock, Rdm) + dot2(self.CoreH, Rdm)) + self.CoreEnergy
    return Energy