3
0
mirror of https://github.com/triqs/dft_tools synced 2024-10-31 11:13:46 +01:00
dft_tools/doc/advanced.rst

159 lines
6.5 KiB
ReStructuredText

.. _advanced:
A more advanced example
=======================
Normally, one wants to adjust some more parameters in order to make the calculation more efficient. Here, we
will see a more advanced example, which is also suited for parallel execution.
First, we load the necessary modules::
from pytriqs.applications.dft.sumk_lda import *
from pytriqs.applications.dft.converters.wien2k_converter import *
from pytriqs.applications.dft.solver_multiband import *
from pytriqs.gf.local import *
from pytriqs.archive import *
Then we define some parameters::
lda_filename='srvo3'
U = 2.7
J = 0.65
beta = 40
loops = 10 # Number of DMFT sc-loops
mix = 1.0 # Mixing factor of Sigma after solution of the AIM
Delta_mix = 1.0 # Mixing factor of Delta as input for the AIM
dc_type = 1 # DC type: 0 FLL, 1 Held, 2 AMF
use_blocks = True # use bloc structure from LDA input
use_matrix = False # True: Slater parameters, False: Kanamori parameters U+2J, U, U-J
use_spinflip = False # use the full rotational invariant interaction?
prec_mu = 0.0001
qmc_cycles = 20000
length_cycle = 200
warming_iterations = 2000
Most of these parameters are self-explaining. The first, `lda_filename`, gives the filename of the input files.
The next step, as described in the previous section, is to convert the input files::
Converter = Wien2kConverter(filename=lda_filename, repacking=True)
Converter.convert_dmft_input()
mpi.barrier()
The command ``mpi.barrier()`` ensures that all nodes wait until the conversion of the input is finished on the master
node. After the conversion, we can check in the hdf5 archive, if previous runs are present, or if we have to start
from scratch::
previous_runs = 0
previous_present = False
if mpi.is_master_node():
ar = HDFArchive(lda_filename+'.h5','a')
if 'iterations' in ar:
previous_present = True
previous_runs = ar['iterations']
del ar
previous_runs = mpi.bcast(previous_runs)
previous_present = mpi.bcast(previous_present)
# if previous runs are present, no need for recalculating the bloc structure:
calc_blocs = use_blocks and (not previous_present)
Now we can use all this information to initialise the :class:`SumkLDA` class::
SK=SumkLDA(hdf_file=lda_filename+'.h5',use_lda_blocks=calc_blocs)
If there was a previous run, we know already about the block structure, and therefore `UseLDABlocs` is set to `False`.
The next step is to initialise the Solver::
Norb = SK.corr_shells[0][3]
l = SK.corr_shells[0][2]
S = SolverMultiBand(beta=beta,n_orb=Norb,gf_struct=SK.gf_struct_solver[0],map=SK.map[0])
As we can see, many options of the solver are set by properties of the :class:`SumkLDA` class, so we don't have
to set them manually. We now set the basic parameters of the QMC solver::
S.n_cycles = qmc_cycles
S.length_cycle = length_cycle
S.n_warmup_cycles = warming_iterations
If there are previous runs stored in the hdf5 archive, we can now load the self energy
of the last iteration::
if (previous_present):
if (mpi.is_master_node()):
ar = HDFArchive(lda_filename+'.h5','a')
S.Sigma <<= ar['SigmaF']
del ar
S.Sigma = mpi.bcast(S.Sigma)
The last command is the broadcasting of the self energy from the master node to the slave nodes.
Now we can go to the definition of the self-consistency step. It consists again of the basic steps discussed in the
previous section, with some additional refinement::
for iteration_number in range(1,loops+1) :
SK.symm_deg_gf(S.Sigma,orb=0) # symmetrise Sigma
SK.put_Sigma(Sigma_imp = [ S.Sigma ]) # put Sigma into the SumK class:
chemical_potential = SK.find_mu( precision = prec_mu ) # find the chemical potential
S.G <<= SK.extract_G_loc()[0] # calculation of the local Green function
mpi.report("Total charge of Gloc : %.6f"%S.G.total_density())
if ((iteration_number==1)and(previous_present==False)):
# Init the DC term and the real part of Sigma, if no previous run was found:
dm = S.G.density()
SK.set_dc( dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type)
S.Sigma <<= SK.dc_imp[0]['up'][0,0]
# now calculate new G0:
if (mpi.is_master_node()):
# We can do a mixing of Delta in order to stabilize the DMFT iterations:
S.G0 <<= S.Sigma + inverse(S.G)
ar = HDFArchive(lda_filename+'.h5','a')
if ((iteration_number>1) or (previous_present)):
mpi.report("Mixing input Delta with factor %s"%Delta_mix)
Delta = (Delta_mix * S.G0.delta()) + (1.0-Delta_mix) * ar['DeltaF']
S.G0 <<= S.G0 + S.G0.delta() - Delta
ar['DeltaF'] = S.G0.delta()
S.G0 <<= inverse(S.G0)
del ar
S.G0 = mpi.bcast(S.G0)
# Solve the impurity problem:
S.Solve(U_interact=U,J_hund=J,n_orb=Norb,use_matrix=use_matrix,
T=SK.T[0], gf_struct=SK.gf_struct_solver[0],map=SK.map[0],
l=l, deg_orbs=SK.deg_shells[0], use_spinflip=use_spinflip))
# solution done, do the post-processing:
mpi.report("Total charge of impurity problem : %.6f"%S.G.total_density())
# Now mix Sigma and G with factor Mix, if wanted:
if ((iteratio_number>1) or (previous_present)):
if (mpi.is_master_node()):
ar = HDFArchive(lda_filename+'.h5','a')
mpi.report("Mixing Sigma and G with factor %s"%mix)
S.Sigma <<= mix * S.Sigma + (1.0-mix) * ar['SigmaF']
S.G <<= mix * S.G + (1.0-mix) * ar['GF']
del ar
S.G = mpi.bcast(S.G)
S.Sigma = mpi.bcast(S.Sigma)
# Write the final Sigma and G to the hdf5 archive:
if (mpi.is_master_node()):
ar = HDFArchive(lda_filename+'.h5','a')
ar['iterations'] = previous_runs + iteration_number
ar['SigmaF'] = S.Sigma
ar['GF'] = S.G
del ar
# Now set new double counting:
dm = S.G.density()
SK.set_dc( dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type)
#Save stuff:
SK.save()
This is all we need for the LDA+DMFT calculation. At the end, all results are stored in the hdf5 output file.