Пример #1
0
def generic_densitydensity(h0,
                           mf=None,
                           mix=0.1,
                           v=None,
                           nk=8,
                           solver="plain",
                           maxerror=1e-5,
                           filling=None,
                           callback_mf=None,
                           callback_dm=None,
                           load_mf=True,
                           compute_cross=True,
                           compute_dd=True,
                           verbose=1,
                           compute_anomalous=True,
                           compute_normal=True,
                           info=False,
                           callback_h=None,
                           **kwargs):
    """Perform the SCF mean field"""
    if verbose > 1: info = True
    #    if not h0.check_mode("spinless"): raise # sanity check
    mf = obj2mf(mf)
    h1 = h0.copy()  # initial Hamiltonian
    h1.turn_dense()
    h1.nk = nk  # store the number of kpoints
    if mf is None:
        try:
            if load_mf: mf = inout.load(mf_file)  # load the file
            else: raise
        except:
            mf = dict()
            for d in v:
                mf[d] = np.exp(1j * np.random.random(h1.intra.shape))
            mf[(0, 0, 0)] = mf[(0, 0, 0)] + mf[(0, 0, 0)].T.conjugate()
    else:
        pass  # initial guess
    ii = 0
    os.system("rm -f STOP")  # remove stop file
    hop0 = hamiltonian2dict(h1)  # create dictionary

    def f(mf, h=h1):
        """Function to minimize"""
        #      print("Iteration #",ii) # Iteration
        mf0 = deepcopy(mf)  # copy
        h = h1.copy()
        hop = update_hamiltonian(hop0,
                                 mf)  # add the mean field to the Hamiltonian
        set_hoppings(h, hop)  # set the new hoppings in the Hamiltonian
        if callback_h is not None:
            h = callback_h(h)  # callback for the Hamiltonian
        t0 = time.perf_counter()  # time
        dm = get_dm(h, v, nk=nk)  # get the density matrix
        if callback_dm is not None:
            dm = callback_dm(dm)  # callback for the density matrix
        t1 = time.perf_counter()  # time
        # return the mean field
        mf = get_mf(v,
                    dm,
                    compute_cross=compute_cross,
                    compute_dd=compute_dd,
                    has_eh=h0.has_eh,
                    compute_anomalous=compute_anomalous,
                    compute_normal=compute_normal)
        if callback_mf is not None:
            mf = callback_mf(mf)  # callback for the mean field
        t2 = time.perf_counter()  # time
        if info: print("Time in density matrix = ", t1 - t0)  # Difference
        if info: print("Time in the normal term = ", t2 - t1)  # Difference
        scf = SCF()  # create object
        scf.hamiltonian = h  # store
        #      h.check() # check the Hamiltonian
        scf.hamiltonian0 = h0  # store
        scf.mf = mf  # store mean field
        if os.path.exists("STOP"): scf.mf = mf0  # use the guess
        scf.dm = dm  # store density matrix
        scf.v = v  # store interaction
        scf.tol = maxerror  # maximum error
        return scf

    if solver == "plain":
        do_scf = True
        while do_scf:
            scf = f(mf)  # new vector
            mfnew = scf.mf  # new vector
            t0 = time.clock()  # time
            diff = diff_mf(mfnew, mf)  # mix mean field
            mf = mix_mf(mfnew, mf, mix=mix)  # mix mean field
            t1 = time.clock()  # time
            if info: print("Time in mixing", t1 - t0)
            if verbose > 0: print("ERROR in the SCF cycle", diff)
            #print("Mixing",dmix)
            if info: print()
            if diff < maxerror:
                scf = f(mfnew)  # last iteration, with the unmixed mean field
                inout.save(scf.mf, mf_file)  # save the mean field
                #   scf.hamiltonian.check(tol=100*maxerror) # perform some sanity checks
                return scf
    else:  # use different solvers
        scf = f(mf)  # perform one iteration
        fmf2a = get_mf2array(scf)  # convert MF to array
        fa2mf = get_array2mf(scf)  # convert array to MF

        def fsol(x):  # define the function to solve
            mf1 = fa2mf(x)  # convert to a MF
            scf1 = f(mf1)  # compute function
            xn = fmf2a(scf1.mf)  # new vector
            diff = x - xn  # difference vector
            print("ERROR", np.max(np.abs(diff)))
            print()
            return x - xn  # return vector

        x0 = fmf2a(scf.mf)  # initial guess
        # these methods do seem too efficient, but lets have them anyway
        if solver == "krylov":
            from scipy.optimize import newton_krylov
            x = newton_krylov(fsol, x0, rdiff=1e-3)  # use the solver
        elif solver == "anderson":
            from scipy.optimize import anderson
            x = anderson(fsol, x0)  # use the solver
        elif solver == "broyden1":
            from scipy.optimize import broyden1
            x = broyden1(fsol, x0, f_tol=maxerror * 100)  # use the solver
        elif solver == "linear":
            from scipy.optimize import linearmixing
            x = linearmixing(fsol, x0, f_tol=maxerror * 100)  # use the solver
        else:
            raise  # unrecognised solver
        mf = fa2mf(x)  # transform to MF
        scf = f(mf)  # compute the SCF with the solution
        scf.error = maxerror  # store the error
        inout.save(scf.mf, mf_file)  # save the mean field
        return scf  # return the mean field
Пример #2
0
self_ene_dmp_init = np.array(self_ene_init)
for iflavor in range(nflavor):
    for iflavor2 in range(nflavor):
        self_ene_dmp_init[:, iflavor,
                          iflavor2] = self_ene_dmp_init[:, iflavor,
                                                        iflavor2] * dmp_fact

#symmetry
if 'SYMM_MAT' in app_parms:
    nsymm = app_parms['SYMM_MAT'].shape[0]
    nf_sbl = imp_model.get_nflavor() / imp_model.get_nsbl()
    for isymm in xrange(nsymm):
        assert is_unitary(app_parms['SYMM_MAT'][isymm, :, :])
        assert commute(
            imp_model.get_moment(1)[0:nf_sbl, 0:nf_sbl],
            app_parms['SYMM_MAT'][isymm, :, :])

#sciopt.root(calc_diff,self_ene_init,method="anderson",options={'nit' : app_parms["MAX_IT"], 'fatol' : app_parms["CONVERGED"], 'disp': True, 'M': 10})
dmft_result = DMFTResult()
mix = 0.5
if 'mix' in app_parms:
    mix = app_parms['mix']
sciopt.linearmixing(calc_diff,
                    self_ene_dmp_init,
                    alpha=mix,
                    iter=app_parms["MAX_IT"],
                    f_rtol=app_parms["CONVERGED"],
                    line_search=None,
                    verbose=True)
#sciopt.anderson(calc_diff,self_ene_dmp_init,iter=app_parms["MAX_IT"], f_rtol=app_parms["CONVERGED"], verbose=True)