Tutorial 9: High-throughput functionality
This tutorial is on the two scripts that are provided for high
throughput type calculations within DFT+eDMFT. The scripts are
"cif2struct.py" and "cif2indmf.py". The first converts cif (or
magnetic mcif) file to proper structure file for wien2k calculation,
while the latter also prepares all necessary input files for eDMFT
calculation (as well as converts cif to structure file).
They require pymatgen
installation. The code has been tested with pymatgen version "2023.11.12" and
"2024.2.8".
The first script is cif2struct.py, which was already mentioned before.
It has several options, which are available through "-h" or "--help"
flag.
Options:
-h, --help show this help message and exit
-w, --writek weather to write case.klist_band high symmetry k-path
(default False)
-N NKP, --Nkp=NKP number of k-points along the high symmetry path
-l LOG, --log=LOG info file
-n, --neigh compute neighbors and evaluate Rmt
-m, --magnet should produce magnetic dft struct that allows broken
symmetry from mcif
-H, --hexagonal switches off hexagonal to rhombohedral conversion
-p NDECIMALS, --ndecimals=NDECIMALS
precision when determining the equivalency of atoms we
take nn distance with precision ndecimals. Compatible
with w2k nn method.
-R NRADIUS, --nradius=NRADIUS
How far in AA should nearest neighbors be checked.
Compatible with w2k nn method.
With "-w" one can produce the k-point list through selective high-symmetry
points in the BZ. These special k-points are tabulated in pymatgen,
and this code just produces integer lists needed in wien2k and
transformes the k-points to conventional unit cell (note that VASP and
most other packages require k-points in primitive BZ).
With "-N" we can increase or reduce the number of k-points. With -l we
can change the log filename, which is cif2struct.log by
default, and is very useful to read.
If the cif file is magnetic mcif file, we can switch on "-m" option to
produce input for magnetic calculation (no SO).
By default we convert hexagonal structures to rhombohedral as wien2k
would do it later in initialization. But we don't want to change
structure later, because in this case we also need to change local
axis again. The "-H" switch allows one to not perform this conversion.
We can also produce nearest neighbor list with "-n" and correctly set
RMT radius in structure file. But this neighbors list is crucial for
the second script, namely,
which produces a complete set of all
input files for dmft calculation, which are a good guess for a best set
of parameters.
The script takes many optional parameters:
Options:
-h, --help show this help message and exit
-w, --writek weather to write case.klist_band high symmetry k-path
(default False)
-s, --so is this with spin-orbit or not (default False)
-r, --real real axis sets matsubara to 0 in indmffile (default
False)
-f, --fix fix the chemical potential for Mott insulators
(default False)
-N NKP, --Nkp=NKP number of k-points along the high symmetry path
(default 300)
-l LOG, --log=LOG info file (default cif2struct.log)
-c COR, --cor=COR which atom types are correlated. all or 3,4 or 3-5 or
6-7 (default all)
-d DC, --dc=DC The type of double-counting: exact, exacty, exactd,
nominal (default exacty)
-U COULOMBU, --U=COULOMBU
Coulomb U if we want to set it through input (default
None, set inside for each type)
-J COULOMBJ, --J=COULOMBJ
Coulomb J if we want to set it through input (default
None, set inside for each type)
-b BETA, --beta=BETA inverse temperature (default 50/eV->232K)
-M QMC_M, --QMC_M=QMC_M
Number of MC steps per core (default = 5M)
-q QSPLIT, --qsplit=QSPLIT
qsplit (default = 2)
-m, --magnet should produce magnetic dft struct that allows broken
symmetry from mcif
-H, --hexagonal switches off hexagonal to rhombohedral conversion
-p NDECIMALS, --ndecimals=NDECIMALS
precision when determining the equivalency of atoms we
take nn distance with precision ndecimals. Compatible
with w2k nn method.
-R NRADIUS, --nradius=NRADIUS
How far in AA should nearest neighbors be checked.
Compatible with w2k nn method.
Here '-w', '-s', '-r', '-f' don't take any arguments, just set that particular
option to true. For example, '-s' sets spin-orbit to True. The rest of
the options require an argument. For example '-c' takes the
set of atoms to be treated as correlated. One can specify to correlate
3d,4d, or 5d ions, which is set by values 3, 4, or 5. We can correlated all at
the same time with 3,4,5 or 3-5. For rare earths we give number 6 and
for actinides 7. By default all those should be correlated, hence -c
3-7 is default. Only a set of elements in each row are actually
treated as correlated, namely,
{3:["V","Cr","Mn","Fe","Co","Ni","Cu"],
4:["Nb","Mo","Tc","Ru","Rh","Pd"],
5:["Ta","W","Re","Os","Ir","Pt"],
6:["Ce","Pr","Nd","Pm","Sm","Eu","Gd","Tb","Dy","Ho","Er","Tm","Yb","Lu"],
7:["Th","Pa","U","Np","Pu","Am","Cm","Bk","Cf","Es","Fm","Md","No","Lr"]
}
By default Coulomb U and J are set to the following values
Us={3: 10., 4: 8.0, 5: 7.0, 6: 6.0, 7: 6.0}
Js={3: 0.8, 4: 0.8, 5: 0.8, 6: 0.7, 7: 0.7}
For now, qsplit=2 by default, and can be set to some other number, but
must be equal for all atoms, which is
probably not optimal. For lanthanides and actinides qsplit should
probably be better to be 1, and for 5d 13, but in both cases we would
than need spin-orbit, which is off by default. To refresh our memory,
qsplit means the following choice of orbitals
0 average GF, non-correlated
1 |j,mj> basis, no symmetry, except time reversal (-jz=jz)
-1 |j,mj> basis, no symmetry, not even time reversal (-jz=jz)
2 real harmonics basis, no symmetry, except spin (up=dn)
-2 real harmonics basis, no symmetry, not even spin (up=dn)
3 t2g orbitals
-3 eg orbitals
4 |j,mj>, only l-1/2 and l+1/2
5 axial symmetry in real harmonics
6 hexagonal symmetry in real harmonics
7 cubic symmetry in real harmonics
8 axial symmetry in real harmonics, up different than down
9 hexagonal symmetry in real harmonics, up different than down
10 cubic symmetry in real harmonics, up different then down
11 |j,mj> basis, non-zero off diagonal elements
12 real harmonics, non-zero off diagonal elements
13 J_eff=1/2 basis for 5d ions, non-magnetic with symmetry
14 J_eff=1/2 basis for 5d ions, no symmetry
The harderst algorithm in this script is choosing the best local
coordinate axis on all correlated atoms, so that the hybridization
function has minimal off-diagonal components.
For that purpose, the script includes
localaxes.py script, which tries to guess the best polyhedra
surrounding the correlated atom, and from the polyhedra it tries to
determine the best local axis. It implements cube(8), octahedra(6),
tetrahedra(4), square-piramid(5), cuboctahedron (12), truncated
tetrahedron (12), peak-of-tetrahedron(3), peak-of-square-piramid(4),
peak-of-hexagonal-piramid(6), trigonal prism(6), planar quadrilateral
(4). In the bracket with quote the number of neighbors needed for each
polyhedra.
The script cif2indmf.py will produce case.struct, case.indmf, case.indmfl,
case.indmfi, params.dat, and with "-w" flag also
case.klist_band. Information is written to
cif2struct.log.
Three things are still needed for dmft run, namely,
- projectorw.dat file for projector=5,
- the band range in the top of case.indmfl, which is for now set to zero.
- nf0 in params.dat is set to number obtained from atomic configuration and
oxidation state guessed from the chemical formula. This is often not
precise enough
All these values can be obtained from converged dft run, hence the
third script
should be run after dft run is complete. It will write real space
projector to projectorw.dat. Next, it will check the band range
written in case.indmf in eV around the Fermi level, and convert
this number to integer band range obtained from case.energy files.
Finally, it will check the dft density matrix and guess the best density
nf0 for dmft double-counting, so that the starting point in
double-counting is excellent. Even when we use exact double
counting, we start with first guess that is proportional to this
nf0 value, because we don't have impurity occupancy yet.
Finally, after init_proj.py has been run, we need to call
to produce a good guess for self-energy (best s_oo and Edc).
The complete list of commands for high-throughput calculation could thus be
$WIEN_DMFT_ROOT/cif2indmf.py -w case.cif >& nohup_init.dat
echo "mpirun -n $NSLOTS" > mpi_prefix.dat
echo "mpirun -n $NSLOTS" > mpi_prefix.dat2
$WIENROOT/init_lapw -b -red 0 -vxc 5 -ecut -7.0 -numk 2000 >> nohup_init.dat
$WIEN_DMFT_ROOT/run_dft.py >> nohup_dft.dat
$WIEN_DMFT_ROOT/init_proj.py -a >> nohup_init.dat
$WIEN_DMFT_ROOT/szero.py >> nohup_init.dat
$WIEN_DMFT_ROOT/run_dmft.py >& nohup_dmft.dat
Of course one could use less k-points to converg dft, and later
increase the number of k-points for dmft. But these details can be
easily added.
One should also check how off diagonal is the hybridization, by running
one dmft1 step with qsplit=12. Namely, qsplit=12 will produce all
off-diagonal hybridizations, which should be checked to be small. If
not, one could possibly run
$WIEN_DMFT_ROOT/findRot.py
to diagonalize hybridization on dft level before executing dmft. More
about this below in the case of RuO2.
Finally, we need to use a uniform choice of parameters for all
calculations. In the following we will select
U=10eV
J=0.8eV
DCs='exact'
qsplit=2
CoulombF='Ising'
This works quite well for 3d correlated compounds which are strongly
correlated. CoulombF='Full' is better, but is expensive.
For metals, like Fe superconductors, U should be somewhat
reduced. exact is a combination of exacty and
exactd double-counting. The first is a combination of yukawa and dielectric
screening that gives prescribed U and J, while the latter is purely
dielectric screening. While exacty is expected to be best in
many materials, it seems to be too short ranged in late TMO's, which
require more dielectric type screening. As a result exact is a
compromise that interpolated between exacty in early TMOs and
exactd in later TMOs.
With this in mind, we rerun a few compounds discussed in previous
tutorials, and we will next present the results, so that user can
check if the code works correctly.
SrVO3
We rerun SrVO3 with these default parameter. Notice that
before we correlated only t2g orbitals and used smaller
U=8eV. Now we correlate both the t2g and eg orbitals and
with increased U=10eV, we produce similar spectra and similar
occupancies. For example, the t2g only occupancy was before
n_{t2g}=1.45, while the new calculation gives n_{t2g}=1.522 and
n_{eg}=0.715. The total 3d occupancy is much bigger n_{3d}=2.24, but
this is because we now count both the eg and t2g electrons.
The converged results in info.file is
mu Vdc Etot Ftot+T*Simp Ftot+T*Simp n_latt n_imp Eimp[0] Eimp[-1]
8.661942 15.551639 -8710.159608 -8710.165781 -8710.158820 2.240679 2.237563 -0.085963 -1.448770
Here is the plot of density of states and the Green's function for
both t2g, eg, and oxygen bands.
These are similar than before, but correlations are now somewhat weaker. The mass
enhancement is now only around m*/m~2 as compared to m*/m~2.5 in t2g
only calculation. This is close, but if we wanted to get a better
agreement with previous t2g only calculation, we would need to further
reduce U in previous calculation. We notice however that
the calculations are much harder to converge now, because the typical
perturbation order is now around order 450 (extending beyond 500),
while in t2g only calculation, the typical order was 170 (extending to 230).
Finally, we show the hybridization function for t2g orbital:
This is almost identical to previous t2g only calculation.
LaVO3
In one of the previous tutorials we have performed t2g-only
calculation for LaVO3, which it turned out to be Mott insulating
material with t2g occupancy close to 2, and Mott gap close to, but smaller
than 2eV. In this tutorial we correlated all 3d orbitals, and
automatically select the best local axis. You can check that
case.indmfl files has local rotation equivalent to the one we
produced in previous tutorial.
The self-consistent calculation with all 5d orbitals and larger U=10eV
produces similar results. However, there are also difference.
First we point out that the Mott gap can be numerically stabilized
with fixing the chemical potential. We thus change the flag in
params.dat file to
and than check in dmft_info.out or case.outputdmf2 file
that
is close to zero. If there is a gap, this number will be an integer,
and we must ensure it is not +1 or -1, but close to zero.
The converged values in info.iterate are:
mu Vdc Etot Ftot+T*Simp Ftot+T*Simp n_latt n_imp Eimp[0] Eimp[-1]
10.803055 18.468704 -77383.390671 -77383.399318 -77383.389914 2.540813 2.543642 0.025545 -1.150281
Total occupancy for eg and t2g is 2.54 electrons. We can check what is
partial occupancy in imp.0/Gf.out in the first line mom
lists partial occupnacies of impurity. We got the following
occupancies
z^2 x^2-y^2 xz yz xy
mom=[0.2345946764349459,0.2332270335931207,0.7098984906471872,0.6736290320800302,0.6922923990033716,]
hence t2g occupancy is n_{t2g}=2.08, which is extremely close to
previous t2g only calculation with occupancy of n_{t2g}=2.1.
The local density of states is plotted below:
It shows a small gap, and the lower Hubbard band split into Slatter
peak (first peak in the valence band) and more broad reminder of the
Hubbard band. This signals that the Mott gap is somewhat closer to the
Mott transition (but above), hence Slater peak is very pronounced. The
fact that we are close to the Mott transition was observed also
numerically, as convergence is much more challenging in this settings.
We notice that the eg-states have shifted slightly upward, similar as
in SrVO3. This is not surprising, as correlations should remove such
orbitals that are in empty orbital regime from the Fermi level.
Finally, to check the size of the Mott gap we display the spectral
function. We notice that the size of the gap is very comparable to
what we have seen before (close to 2eV, but somewhat smaller than
2eV). We clearly see the splitting in the lower Hubbard band into
Slater peak and the rest. More importantly, the conduction band is
very different now. Before the conduction band started with eg states,
while now it starts with La-f states.
Since La-f states are not treated as correlated, they might be misplaced, and it
is an interesting question if more precise calculation with
correlations on La-f states would increase the gap size or not.
FeSe
Finally, we also recompute the properties of FeSe with similar input
parameters. If we choose U=8eV and J=0.8eV with DCs=exact, we get
relaxed structure with z parameter around 0.3, and occupancy very
close to 6 (nd=6.07). This parameters predict very strong correlations, a bit
more than experiment shows.
When U=5eV and J=0.8eV with DCs=exact, we get a relaxes structure with z=0.281 and
occupancy nd=6.26, which is in
a reasonable agreement with experiment. We want to point out that
occupancy could be reduced by choosing DCs=exacty, which would
increase correlation strength and increase z. On the other hand,
choosing DCs=exactd would do the opposite, decrease the occupancy and
decrease correlations and structural parameter z. Increase of Hund's
coupling has similar effect in decreasing occupancy and increasing
correlation strengt. Here is the table that demonstrates the
sensitivity of the results with these parameters.
U=5eV |
J=0.7eV |
J=0.8eV |
DCs='exact' |
z=0.270, nd=6.32 |
z=0.281, nd=6.26 |
|
DCs='exacty' |
z=0.300, nd=6.02 |
z=0.306, nd=5.95 |
Notice that J and DCs are even more crucial parameters than U in this case.
This is because FeSe is at the verge of selective Mott differentiation,
and therefore this strong sensitivity with small variation of
parameters.
RuO2 as Altermagnet
In this section we will demonstrate how to run eDMFT code for magnetic
materials, in this case altermagnet RuO2. This run will be done
without SO coupling, because this is the best way to distinguish
between altermagnets and other antiferromagnets that have SO induced
splitting of bands.
We start by downloading magnetic cif file from Bilbao
Crystallographic Server (RuO2 mcif
appears under number 0.607). For the purpose of this exercise we will
call it 0_607_RuO2.mcif.
First we will generate all eDMFT input files with cif2indmf.py
script. This script takes many options, which are listed with "-h" or
"--help" option:
Options:
-h, --help show this help message and exit
-w, --writek weather to write case.klist_band high symmetry k-path
(default False)
-s, --so is this with spin-orbit or not (default False)
-r, --real real axis sets matsubara to 0 in indmffile (default
False)
-f, --fix fix the chemical potential for Mott insulators
(default False)
-N NKP, --Nkp=NKP number of k-points along the high symmetry path
(default 300)
-l LOG, --log=LOG info file (default cif2struct.log)
-c COR, --cor=COR which atom types are correlated. all or 3,4 or 3-5 or
6-7 (default all)
-d DC, --dc=DC The type of double-counting: exact, exacty, exactd,
nominal (default exacty)
-U COULOMBU, --U=COULOMBU
Coulomb U if we want to set it through input (default
None, set inside for each type)
-J COULOMBJ, --J=COULOMBJ
Coulomb J if we want to set it through input (default
None, set inside for each type)
-b BETA, --beta=BETA inverse temperature (default 50/eV->232K)
-M QMC_M, --QMC_M=QMC_M
Number of MC steps per core (default = 5M)
-q QSPLIT, --qsplit=QSPLIT
qsplit (default = 2)
-m, --magnet should produce magnetic dft struct that allows broken
symmetry from mcif
-H, --hexagonal switches off hexagonal to rhombohedral conversion
-p NDECIMALS, --ndecimals=NDECIMALS
precision when determining the equivalency of atoms we
take nn distance with precision ndecimals. Compatible
with w2k nn method.
-R NRADIUS, --nradius=NRADIUS
How far in AA should nearest neighbors be checked.
Compatible with w2k nn method.
We will execute:
cif2indmf.py -w -m -U 6.0 0_607_RuO2.mcif
in which "-m" option allows to generate all magnetic input files, "-w"
creates high symmetry k-path, and "-U" reduced Coulomb U from default
8eV for 4d's to 6eV, because RuO2 is metallic.
This should generate
0_607_RuO2.struct
0_607_RuO2.indmfi
0_607_RuO2.indmfl
0_607_RuO2.indmfldn
0_607_RuO2.klist_band
params.dat
cif2struct.log
The structure file contains two inequivalent Ru atoms in P4_2/mnm
space group. Also the oxygen atoms are split into O1 and O2.
It is very useful to read cif2struct.log, which explains the algorithm
of generating all these files.
First it prints the structure read from cif file:
structure directly from given input cif file
---------------------------------------------
ca= 4.492 cb= 4.492 cc= 3.1061 calpha= 90.0 cbeta= 90.0 cgamma= 90.0
sgname= P 4_2/m n m sgnum= 136 ssetting= None
1 Ru 0.000000, 0.000000, 0.000000
2 O 0.305580, 0.305580, 0.000000
next it shows conventional unit cell, which is needed for Wien2k
structure file (notice that some atom positions that appear in
conventional but not primitive cell are remove later in the
cif2struct.py algorithm):
Full Formula (Ru2 O4)
Reduced Formula: RuO2
abc : 4.492000 4.492000 3.106100
angles: 90.000000 90.000000 90.000000
pbc : True True True
Sites (6)
# SP a b c magmom
--- ---- ------- ------- --- --------
0 Ru 0 0 0 0.05
1 Ru 0.5 0.5 0.5 -0.05
2 O 0.30558 0.30558 0 0
3 O 0.80558 0.19442 0.5 0
4 O 0.19442 0.80558 0.5 0
5 O 0.69442 0.69442 0 0
Next it prints all 16 symmetry operations of this magnetic system:
Number of symmetry operations available= 16
magnetic cif= True
0 : Time=1 I
1 0 0 0.00000000
0 1 0 0.00000000
0 0 1 0.00000000
1 : Time=1 R
1 0 0 0.50000000
0-1 0 0.50000000
0 0-1 0.50000000
2 : Time=1 R
-1 0 0 0.50000000
0 1 0 0.50000000
0 0-1 0.50000000
3 : Time=1 R
-1 0 0 0.00000000
0-1 0 0.00000000
0 0 1 0.00000000
4 : Time=1 P
-1 0 0 0.00000000
0-1 0 0.00000000
0 0-1 0.00000000
5 : Time=1 R
-1 0 0 0.50000000
0 1 0 0.50000000
0 0 1 0.50000000
6 : Time=1 R
1 0 0 0.50000000
0-1 0 0.50000000
0 0 1 0.50000000
7 : Time=1 R
1 0 0 0.00000000
0 1 0 0.00000000
0 0-1 0.00000000
8 : Time=-1 R
0-1 0 0.50000000
1 0 0 0.50000000
0 0 1 0.50000000
9 : Time=-1 R
0 1 0 0.50000000
-1 0 0 0.50000000
0 0 1 0.50000000
10 : Time=-1 R
0 1 0 0.00000000
1 0 0 0.00000000
0 0-1 0.00000000
11 : Time=-1 R
0-1 0 0.00000000
-1 0 0 0.00000000
0 0-1 0.00000000
12 : Time=-1 R
0 1 0 0.50000000
-1 0 0 0.50000000
0 0-1 0.50000000
13 : Time=-1 R
0-1 0 0.50000000
1 0 0 0.50000000
0 0-1 0.50000000
14 : Time=-1 R
0-1 0 0.00000000
-1 0 0 0.00000000
0 0 1 0.00000000
15 : Time=-1 R
0 1 0 0.00000000
1 0 0 0.00000000
0 0 1 0.00000000
Here the notation is like in w2k structure file, i.e., 3x3 rotation
with the last column real space translation. The time reversal (which
flips the spin) is denoted by Time=+1 or Time=-1. The name R,P,I
designates P for inversion, I for identity, and R for any other
operation.
Next few lines show how symmetry operations split the magnetic
symmetry operations to those that are present for spin-up (or
spin-down) only calculation. If operation flips spins, it should be
removed in spin-up calculation only. If it preserves the spin, it is
kept.
Ru[0] [0. 0. 0.] M[0]= [0. 0. 0.05]
Ru[1] [0.5 0.5 0.5] M[1]= [ 0. 0. -0.05]
Group[1] applied to r[1]= [0.5 0.5 0.5] and M[1]= [0.0, 0.0, -0.05] gives r[0]= [0. 0. 0.] and M[0]= [0.0, 0.0, 0.05]
Molap= -1.0
Since moments are different ig= 1 should be removed flipped= {1: 0}
Group[2] applied to r[1]= [0.5 0.5 0.5] and M[1]= [0.0, 0.0, -0.05] gives r[0]= [0. 0. 0.] and M[0]= [0.0, 0.0, 0.05]
Molap= -1.0
Since moments are different ig= 2 should be removed flipped= {1: 0}
Group[5] applied to r[1]= [0.5 0.5 0.5] and M[1]= [0.0, 0.0, -0.05] gives r[0]= [0. 0. 0.] and M[0]= [0.0, 0.0, 0.05]
Molap= -1.0
Since moments are different ig= 5 should be removed flipped= {1: 0}
Group[6] applied to r[1]= [0.5 0.5 0.5] and M[1]= [0.0, 0.0, -0.05] gives r[0]= [0. 0. 0.] and M[0]= [0.0, 0.0, 0.05]
Molap= -1.0
Since moments are different ig= 6 should be removed flipped= {1: 0}
Group[8] applied to r[1]= [0.5 0.5 0.5] and M[1]= [0.0, 0.0, -0.05] gives r[0]= [0. 0. 0.] and M[0]= [0.0, 0.0, 0.05]
Molap= -1.0
Since moments are different ig= 8 should be removed flipped= {1: 0}
Group[9] applied to r[1]= [0.5 0.5 0.5] and M[1]= [0.0, 0.0, -0.05] gives r[0]= [0. 0. 0.] and M[0]= [0.0, 0.0, 0.05]
Molap= -1.0
Since moments are different ig= 9 should be removed flipped= {1: 0}
Group[12] applied to r[1]= [0.5 0.5 0.5] and M[1]= [0.0, 0.0, -0.05] gives r[0]= [0. 0. 0.] and M[0]= [0.0, 0.0, 0.05]
Molap= -1.0
Since moments are different ig= 12 should be removed flipped= {1: 0}
Group[13] applied to r[1]= [0.5 0.5 0.5] and M[1]= [0.0, 0.0, -0.05] gives r[0]= [0. 0. 0.] and M[0]= [0.0, 0.0, 0.05]
Molap= -1.0
Since moments are different ig= 13 should be removed flipped= {1: 0}
Starting anew with ii=1 grp= [[0], [1]]
groups for magnetic atoms= [[[0], [1]]]
indx_by_element {'Ru': [0, 1], 'O': [2, 3, 4, 5]}
starting with groups for magnetic atoms= [[[0], [1]], [[2, 3, 4, 5]]]
Here "Molap" means the overlap between original spin and the spin
after the symmetry operation. If the spin is preserved, "Molap" is 1.0
and if it is flipped, is -1.0. Since many materials have canted
magnetic moments we allow abs(Molap) to be less than unity. As long as it
is bigger than 0.75, we consider spin to be parallel or antiparallel.
We apply all symmetry operations, and see that operation
[1,2,5,6,8,9,12,13] transform Ru[1] to Ru[0], and also flip the spin
(as they should),
while the rest of the operations [0,3,4,7,10,11,14,15] don't flip spins,
and they do not mix Ru[0] with Ru[1] with opposite spin, hence are
preserved in our calculation.
Next we produce a list of all magnetic atoms that form equivalent
group. We call that "groups for magnetic atoms", which is
"[[[0],[1]]]". It means that atom 0 and 1 are different. If the list
is "[[[0,1]]]" they would be considered equivalent.
The non-magnetic atoms are first considered to be equivalent if they
correspond to the same element. Since we only have oxygens at position
2,3,4,5, they are all considered equivalent for now, i.e.,
[2,3,4,5]. "indx_by_element" also shows which elements have which
successive number in the structure.
Next we print for each atom which symmetry operations transforms ups
into down spins. Here Ru[1] is transformed into Ru[0] and the
following symmetry operations flip the spin"
atoms which are flipped of each other:
1->0
T=1
R= 1, 0, 0
0,-1, 0
0, 0,-1
T=1
R=-1, 0, 0
0, 1, 0
0, 0,-1
T=1
R=-1, 0, 0
0, 1, 0
0, 0, 1
T=1
R= 1, 0, 0
0,-1, 0
0, 0, 1
T=-1
R= 0,-1, 0
1, 0, 0
0, 0, 1
T=-1
R= 0, 1, 0
-1, 0, 0
0, 0, 1
T=-1
R= 0, 1, 0
-1, 0, 0
0, 0,-1
T=-1
R= 0,-1, 0
1, 0, 0
0, 0,-1
symmetry operations that need to be removed= {1, 2, 5, 6, 8, 9, 12, 13}
Next we print all symmetry operations that are present for spin-up or
spin-down calculation only:
Symmetry operations left:
0 : Time=1 I
1 0 0 0.00000000
0 1 0 0.00000000
0 0 1 0.00000000
1 : Time=1 R
-1 0 0 0.00000000
0-1 0 0.00000000
0 0 1 0.00000000
2 : Time=1 P
-1 0 0 0.00000000
0-1 0 0.00000000
0 0-1 0.00000000
3 : Time=1 R
1 0 0 0.00000000
0 1 0 0.00000000
0 0-1 0.00000000
4 : Time=-1 R
0 1 0 0.00000000
1 0 0 0.00000000
0 0-1 0.00000000
5 : Time=-1 R
0-1 0 0.00000000
-1 0 0 0.00000000
0 0-1 0.00000000
6 : Time=-1 R
0-1 0 0.00000000
-1 0 0 0.00000000
0 0 1 0.00000000
7 : Time=-1 R
0 1 0 0.00000000
1 0 0 0.00000000
0 0 1 0.00000000
Hence, we keep T[1]==C2(z), T[2]==inversion=P, T[4]==C2(110),
and their combinations: T[3]=C2(z)*P, T[6]=C2(1,1,0)*P,
T[5]=C2(1,1,0)*C2(z), T[7]=C2(1,1,0)*C2(z)*P.
We dropped C2(x)+(1/2,1/2,1/2), C2(y)+(1/2,1/2,1/2), C2(x)*P+(1/2,1/2,1/2), C2(y)*P+(1/2,1/2,1/2), C4++(1/2,1/2,1/2), C4-(z)+(1/2,1/2,1/2),
C4+(z)*P+(1/2,1/2,1/2), C4-(z)*P+(1/2,1/2,1/2), because they were
transforming spin-up Ru in spin-down Ru.
Next we determine equivalency for non-magnetic atoms using shells of
neighboring atoms as a test. This algorithm mirrors w2k-nn algorithm,
which also looks at all neighbors to determine equivalency.
At the first iteration we have the following atoms and their neighbors:
Going over all neighbors to determine equivalency:
....
neigbors of inequivalent atom types after iteration 1
Ru1 ['1.941 O1 O1', '1.984 O1 O1 O1 O1', '3.106 Ru1 Ru1', '3.408 O1 O1 O1 O1', '3.536 Ru2 Ru2 Ru2 Ru2 Ru2 Ru2 Ru2 Ru2', '3.663 O1 O1 O1 O1', '4.034 O1 O1 O1 O1 O1 O1 >
Ru2 ['1.941 O1 O1', '1.984 O1 O1 O1 O1', '3.106 Ru2 Ru2', '3.408 O1 O1 O1 O1', '3.536 Ru1 Ru1 Ru1 Ru1 Ru1 Ru1 Ru1 Ru1', '3.663 O1 O1 O1 O1', '4.034 O1 O1 O1 O1 O1 O1 >
O1 ['1.941 Ru1', '1.984 Ru2 Ru2', '2.47 O1', '2.776 O1 O1 O1 O1 O1 O1 O1 O1', '3.106 O1 O1', '3.254 O1 O1', '3.408 Ru1 Ru1', '3.663 Ru1 Ru1', '3.882 O1', '3.969 O1 O1>
This shows that Ru1 atom has two O1 atoms at the distance of 1.941,
and 4 O1 atoms at 1.984, etc.
Next we recursively add more and more splitting between atoms until no
more splitting is needed. At the first pass we realize that two O1
atoms can not be equivalent, because one has Ru2 at distance 1.941,
and the other Ru1.
atom[ 3] with name=O1 neigbr= ['1.941 Ru2', '1.984 Ru1 Ru1', '2.47 O1', '2.776 O1 O1 O1 O1 O1 O1 O1 O1', '3.106 O1 O1', '3.254 O1 O1', '3.408 Ru2 Ru2', '3.663 Ru2 Ru2', >
atom[ 3] with name=O1 expect= ['1.941 Ru1', '1.984 Ru2 Ru2', '2.47 O1', '2.776 O1 O1 O1 O1 O1 O1 O1 O1', '3.106 O1 O1', '3.254 O1 O1', '3.408 Ru1 Ru1', '3.663 Ru1 Ru1', >
We thus split O1 into O1 and O2. We arrive at the following splitting
Ru1 ['1.941 O1 O1', '1.984 O2 O2 O2 O2', '3.106 Ru1 Ru1', '3.408 O1 O1 O1 O1', '3.536 Ru2 Ru2 Ru2 Ru2 Ru2 Ru2 Ru2 Ru2', '3.663 O1 O1 O1 O1', '4.034 O2 O2 O2 O2 O2 O2 >
Ru2 ['1.941 O2 O2', '1.984 O1 O1 O1 O1', '3.106 Ru2 Ru2', '3.408 O2 O2 O2 O2', '3.536 Ru1 Ru1 Ru1 Ru1 Ru1 Ru1 Ru1 Ru1', '3.663 O2 O2 O2 O2', '4.034 O1 O1 O1 O1 O1 O1 >
O1 ['1.941 Ru1', '1.984 Ru2 Ru2', '2.47 O1', '2.776 O2 O2 O2 O2 O2 O2 O2 O2', '3.106 O1 O1', '3.254 O1 O1', '3.408 Ru1 Ru1', '3.663 Ru1 Ru1', '3.882 O1', '3.969 O1 O1>
O2 ['1.941 Ru2', '1.984 Ru1 Ru1', '2.47 O2', '2.776 O1 O1 O1 O1 O1 O1 O1 O1', '3.106 O2 O2', '3.254 O2 O2', '3.408 Ru2 Ru2', '3.663 Ru2 Ru2', '3.882 O2', '3.969 O2 O2>
To determine equivalency, we measure distance between atoms, and keep
three digits after the dot. i.e, 1.941 (in units of
angstroms). Sometimes we need to either increase this precision or
reduce it, depending on how precise are positions given in the
original structure. Most of the time, the three digits work, but if
there is discrepancy between these equivalent atoms, and w2k-nn
routine, we need to change this number. This can be done through
parameter "-p NDECIMALS", which is "NDECIMALS=3" by default.
The other parameter that could potentially need to be changed is
"-R NRADIUS, --nradius=NRADIUS". By default we check neighbors up to
4.7A away from each atom. This is almost always enough to determine
equivalency. But if discrepancy between w2k-nn and this algorithm
occurs, one can check that this radius is sufficient. Note that in w2k we give
parameter in terms of number of shells for nn.
Finally, we determine the grouping of all atoms into equivalent
sets. We have:
mgroups= [[[0], [1]], [[2, 5], [3, 4]]]
which means that Ru atoms are split into [0],[1], while oxygen atoms
of the original structure file are split into O1=[2,5] group O2=[3,4].
In w2k we will list atoms consequently and O1 will appear as atoms
[2,3] and O2 as [4,5]. We now reorder atoms so as they will appear in
w2k structure file:
all_sites_order= [0, 1, 2, 5, 3, 4]
Next we go over all first atoms in the w2k structure file, and check
which are their neighbors. For example:
ATOM: 1 Ru AT 0.00000 0.00000 0.00000= 0.00000 0.00000 0.00000
nn_distance= 1.9412419687117457 Rmt[0]= 1.037157052833468
ATOM: 5 O AT -1.37267 -1.37267 -0.00000= -0.30558 -0.30558 0.00000 IS AWAY 1.941242 1.941242 ANG
ATOM: 2 O AT 1.37267 1.37267 0.00000= 0.30558 0.30558 0.00000 IS AWAY 1.941242 1.941242 ANG
ATOM: 3 O AT -0.87333 0.87333 -1.55305= -0.19442 0.19442 -0.50000 IS AWAY 1.984286 1.984286 ANG
ATOM: 3 O AT -0.87333 0.87333 1.55305= -0.19442 0.19442 0.50000 IS AWAY 1.984286 1.984286 ANG
ATOM: 4 O AT 0.87333 -0.87333 -1.55305= 0.19442 -0.19442 -0.50000 IS AWAY 1.984286 1.984286 ANG
ATOM: 4 O AT 0.87333 -0.87333 1.55305= 0.19442 -0.19442 0.50000 IS AWAY 1.984286 1.984286 ANG
ATOM: 0 Ru AT 0.00000 0.00000 -3.10610= 0.00000 0.00000 -1.00000 IS AWAY 3.106100 3.106100 ANG
ATOM: 0 Ru AT 0.00000 0.00000 3.10610= 0.00000 0.00000 1.00000 IS AWAY 3.106100 3.106100 ANG
ATOM: 5 O AT -1.37267 3.11933 0.00000= -0.30558 0.69442 0.00000 IS AWAY 3.407999 3.407999 ANG
ATOM: 2 O AT -3.11933 1.37267 -0.00000= -0.69442 0.30558 0.00000 IS AWAY 3.407999 3.407999 ANG
ATOM: 5 O AT 3.11933 -1.37267 0.00000= 0.69442 -0.30558 0.00000 IS AWAY 3.407999 3.407999 ANG
ATOM: 2 O AT 1.37267 -3.11933 -0.00000= 0.30558 -0.69442 0.00000 IS AWAY 3.407999 3.407999 ANG
ATOM: 1 Ru AT -2.24600 -2.24600 -1.55305= -0.50000 -0.50000 -0.50000 IS AWAY 3.535675 3.535675 ANG
ATOM: 1 Ru AT -2.24600 -2.24600 1.55305= -0.50000 -0.50000 0.50000 IS AWAY 3.535675 3.535675 ANG
ATOM: 1 Ru AT -2.24600 2.24600 -1.55305= -0.50000 0.50000 -0.50000 IS AWAY 3.535675 3.535675 ANG
ATOM: 1 Ru AT -2.24600 2.24600 1.55305= -0.50000 0.50000 0.50000 IS AWAY 3.535675 3.535675 ANG
ATOM: 1 Ru AT 2.24600 -2.24600 -1.55305= 0.50000 -0.50000 -0.50000 IS AWAY 3.535675 3.535675 ANG
ATOM: 1 Ru AT 2.24600 -2.24600 1.55305= 0.50000 -0.50000 0.50000 IS AWAY 3.535675 3.535675 ANG
ATOM: 1 Ru AT 2.24600 2.24600 -1.55305= 0.50000 0.50000 -0.50000 IS AWAY 3.535675 3.535675 ANG
ATOM: 1 Ru AT 2.24600 2.24600 1.55305= 0.50000 0.50000 0.50000 IS AWAY 3.535675 3.535675 ANG
ATOM: 5 O AT -1.37267 -1.37267 -3.10610= -0.30558 -0.30558 -1.00000 IS AWAY 3.662824 3.662824 ANG
ATOM: 5 O AT -1.37267 -1.37267 3.10610= -0.30558 -0.30558 1.00000 IS AWAY 3.662824 3.662824 ANG
ATOM: 2 O AT 1.37267 1.37267 -3.10610= 0.30558 0.30558 -1.00000 IS AWAY 3.662824 3.662824 ANG
ATOM: 2 O AT 1.37267 1.37267 3.10610= 0.30558 0.30558 1.00000 IS AWAY 3.662824 3.662824 ANG
We list first the atom number, the symbol, the vector between the two
atoms in cartesian coordinates, the vector between the two atoms in
fractional coordinates, and finally the distance in angstroms.
The high-symmetry k-path proposed by pymatgen is give by
high symmetry kpath=
\Gamma [0.0, 0.0, 0.0]
A [0.5, 0.5, 0.5]
M [0.5, 0.5, 0.0]
R [0.0, 0.5, 0.5]
X [0.0, 0.5, 0.0]
Z [0.0, 0.0, 0.5]
and we will produce case.klist_band with these k-points.
Next we list information about the structure we just found, as
appropriate for findsym. In rare cases, in which the current algorithm
could fail, one could check with findsym, the appropriate space group
and new cif file. We list the information in the way that allows
direct copy/paste in findsym:
conventional unit cell (cif.w2k_coords) for finsym: https://stokes.byu.edu/iso/findsym.php:
cartesian coordinates of the basis vectors:
4.49200 0.00000 0.00000
-0.00000 4.49200 0.00000
0.00000 0.00000 3.10610
Number of atoms in the unit cell: 6
Type of each atom in the unit cell: 1*Ru1 1*Ru2 2*O1 2*O2
0.000000 0.000000 0.000000
0.500000 0.500000 0.500000
0.305580 0.305580 0.000000
0.694420 0.694420 0.000000
0.805580 0.194420 0.500000
0.194420 0.805580 0.500000
If the bravais lattice is F, B, or C, some atoms need to be removed
from w2k structure file (those that do not appear in primitive unit
cell). We next remove those not in primitive cell. For RuO2 with
primitive bravais lattice, nothing is removed:
After removing atoms not in primitive cell, we have the following cif.w2k_coords list:
name=Ru1 Z=44 [0. 0. 0.]
name=Ru2 Z=44 [0.5 0.5 0.5]
name=O1 Z=8 [0.30558 0.30558 0. ]
name=O1 Z=8 [0.69442 0.69442 0. ]
name=O2 Z=8 [0.80558 0.19442 0.5 ]
name=O2 Z=8 [0.19442 0.80558 0.5 ]
Next we compare the choice of the unit cell between pymatgen and
wien2k conventional cell (later we will also compare it to VESTA
plotting program). We have
pymatgen_conventional=
8.48865 0.00000 0.00000 ==a1
-0.00000 8.48865 0.00000 ==a2
0.00000 0.00000 5.86968 ==a3
paymatgen_Unit cell volume= 422.9524415348472
primitive or simple lattice
w2k_conventional=
8.48865 0.00000 0.00000 ==a1
0.00000 8.48865 0.00000 ==a2
0.00000 0.00000 5.86968 ==a3
Unit cell volume= 422.95244153484725
Ortho= True
In wien2k we also have primitive reciprocal cell, which is called BR2,
and appears next:
BR2=
0.74019 -0.00000 -0.00000
0.00000 0.74019 -0.00000
0.00000 0.00000 1.07045
gbas=
0.11780 -0.00000 -0.00000
0.00000 0.11780 -0.00000
0.00000 0.00000 0.17037
gbas is BR2 divided by (2*pi) and finally, w2k primitive call is
called rbas, and is inverse of gbas:
w2k_primitive(rbas)=
8.48865 0.00000 0.00000 ==a1
0.00000 8.48865 0.00000 ==a2
0.00000 0.00000 5.86968 ==a3
There is one more concept in w2k, namely, the transformation from
primitive reciprocal to conventional reciprocal lattice. Namely, in
primitive unit cell the momentum points of the 1BZ are simply given by
k=n_1/N_1*b_1 + n_2/N_2*b_2 + n_3/N_3*b_3, where b1,b2,b3 are
reciprocal vectors, and n_i goes between 0 and N_i-1. However, w2k
uses (in case.klist and case.klist_band) momentum points written in
conventional unit cell notation, hence these momentum points are
normally transformed to conventional unit cell by k2icartes*k, and
the case.klist file list k2icartes*k rather than k. The
transformation is k2icartes, which is here just unity:
k2icartes=
1 0 0
0 1 0
0 0 1
We next print the momentum points for the special k-path both in
primitive notation (used by VASP) and conventional (used by w2k) unit cell:
Kpoints in the mesh:
\Gamma k-PBZ=[ 0, 0, 0] k-conBZ=[ 0, 0, 0]
A k-PBZ=[ 0.5, 0.5, 0.5] k-conBZ=[ 0.5, 0.5, 0.5]
M k-PBZ=[ 0.5, 0.5, 0] k-conBZ=[ 0.5, 0.5, 0]
R k-PBZ=[ 0, 0.5, 0.5] k-conBZ=[ 0, 0.5, 0.5]
X k-PBZ=[ 0, 0.5, 0] k-conBZ=[ 0, 0.5, 0]
Z k-PBZ=[ 0, 0, 0.5] k-conBZ=[ 0, 0, 0.5]
suggested and actual number of momentum points: 300 300 [72, 51, 63, 51, 63]
The last sentence shows that we have chosen 300 k-points, with 72
between A-M and 63 between X-Z.
Next we go one more time through all neighbors and find the best local
coordinate axis for each correlated atom. The local axis is chosen
by finding the polyhedra of neighbors around each atom, and for each
polyhedra there exist a choice of axis such that the Green's
function and hybridization has the smallest off-diagonal terms. We
have to do this optimization to reduce the sign problem of Monte
Carlo impurity sampling.
We first analize Ru1 at the origin:
Analizing Ru1 at [0. 0. 0.] with N= 6
with neigbrs:
n[0]= [1.9412419687117457, 'O', array([-0.30558, -0.30558, 0. ]), 0]
n[1]= [1.941241968711747, 'O', array([0.30558, 0.30558, 0. ]), 0]
n[2]= [1.9842860402038462, 'O', array([-0.19442, 0.19442, -0.5 ]), 0]
n[3]= [1.984286040203846, 'O', array([-0.19442, 0.19442, 0.5 ]), 0]
n[4]= [1.9842860402038465, 'O', array([ 0.19442, -0.19442, -0.5 ]), 0]
n[5]= [1.9842860402038462, 'O', array([ 0.19442, -0.19442, 0.5 ]), 0]
poly_sizes= {3, 4, 5, 6, 8, 12} group size= [2 6]
phi=
0.0 180.0 90.0 90.0 90.0 90.0
180.0 0.0 90.0 90.0 90.0 90.0
90.0 90.0 0.0 103.0 77.0 180.0
90.0 90.0 103.0 0.0 180.0 77.0
90.0 90.0 77.0 180.0 0.0 103.0
90.0 90.0 180.0 77.0 103.0 0.0
trying octahedra : accuracy 0.055 -N= 0.012 -= 0.235
trying trigonal prism : accuracy 0.950 -N= 0.975 -= 0.000
Found the environment is octahedra (= 0.012,= 0.235)
singular values= [1.10686883 1. 0.88025075]
# neigbors used to determine poly: (0, 6)
Rotation to input into case.indmfl by locrot=-1 :
0.70710678 0.70710678 0.00000000
-0.50000000 0.50000000 -0.70710678
-0.50000000 0.50000000 0.70710678
Rotation in fractional coords :
0.15741469 0.15741469 0.00000000
-0.11130899 0.11130899 -0.22765100
-0.11130899 0.11130899 0.22765100
Rotation for VESTA coords :
0.70710678 0.70710678 0.00000000
-0.50000000 0.50000000 -0.70710678
-0.50000000 0.50000000 0.70710678
We try polyhedra with size 3,4,5,6,8 and 12, and among them octahedra
and trigonal prism are the best fit. The polyhedron with the smallest
number "accuracy" wins, and here octahedra is the best match. The
mismatch between the actual and expected angles is 0.235 and actual
and expected distances is 0.012. Next we list the 3x3 rotation, which
is used in case.indmfl and case.indmfldn file. It is rotation from
the global to the local coordinate axis, written in w2k cartesian
coordinates. Since the choice of cartesian coordinates depend on the choice of
three axis in 3D, w2k and VESTA and pymatgen all choose different convention. To
help the user picture the choice of the local axis, we print the same
3x3 rotation, but written in fractional coordinates. Here rows are
e_x, e_y and e_z. Hence e_x=[0.15741469,0.15741469,0.00000000] and
e_z=[-0.11130899,0.11130899,0.22765100].
These can be entered in VESTA as vectors attached to a given atom, to
understand the choice of the local coordinate axis. We also give these
vectors in VESTA cartesian coordinates, which one can compare with
what VESTA recognizes when typing fractional coordinates.
To get proper symmetry in altermagnets, it is essential to choose
local axis on the opposite atoms (the one with opposite spin) using
the symmetry operation that flips the spin. As discussed above, we
have 8 possibilities which all flip the spins and all are accompanied
by translation for (1/2,1/2,1/2), i.e., C2(x), C2(y), C2(x)*P, C2(y)*P, C4+(z), C4-(z),
C4+(z)*P, C4-(z)*P. We are going to try
successive transformation and use them to transform axis. Here C2(x)
can be used, and is being used
We are trying to use transformed local axis of Ru1 for atom Ru2
positions of neigbors around Ru1 which we are checking:
[ -0.305580, -0.305580, 0.000000]
[ 0.305580, 0.305580, 0.000000]
[ -0.194420, 0.194420, -0.500000]
[ -0.194420, 0.194420, 0.500000]
[ 0.194420, -0.194420, -0.500000]
[ 0.194420, -0.194420, 0.500000]
using rotation:
[ 1, 0, 0]
[ 0,-1, 0]
[ 0, 0,-1]
transformed positions of neigbors around Ru2 which we are checking:
[ -0.305580, -0.305580, 0.000000]
[ 0.305580, 0.305580, 0.000000]
[ 0.194420, -0.194420, -0.500000]
[ -0.194420, 0.194420, -0.500000]
[ 0.194420, -0.194420, 0.500000]
[ -0.194420, 0.194420, 0.500000]
atom[0] -> atom[0] with accuracy= 5.551115123125783e-17
atom[1] -> atom[1] with accuracy= 5.551115123125783e-17
atom[4] -> atom[2] with accuracy= 5.551115123125783e-17
atom[2] -> atom[3] with accuracy= 5.551115123125783e-17
atom[5] -> atom[4] with accuracy= 5.551115123125783e-17
atom[3] -> atom[5] with accuracy= 5.551115123125783e-17
Works= True
Accepting above transformation to transform local axis of Ru1 to axis of Ru2 at [0.5 0.5 0.5]
Using transformation:
[ 1.000000, 0.000000, 0.000000]
[ 0.000000, -1.000000, 0.000000]
[ 0.000000, 0.000000, -1.000000]
# neigbors used to determine poly: (0, 6)
Rotation to input into case.indmfl by locrot=-1 :
0.70710678 -0.70710678 -0.00000000
-0.50000000 -0.50000000 0.70710678
-0.50000000 -0.50000000 -0.70710678
Rotation in fractional coords :
0.15741469 -0.15741469 -0.00000000
-0.11130899 -0.11130899 0.22765100
-0.11130899 -0.11130899 -0.22765100
Rotation for VESTA coords :
0.70710678 -0.70710678 -0.00000000
-0.50000000 -0.50000000 0.70710678
-0.50000000 -0.50000000 -0.70710678
As can be verified, our e_x, e_y and e_z all have their y and z
components with opposite sign, while the x component keeps its sign,
because we use C2(x).
Finally, we try to find how many impurity problems are necessary to
simulate this material.
cix2atom= {1: 1, 2: 2}
remain= [0, 1]
flipping[atom=2,icix=2]=atom=1,icix=1
remain at the end= []
nf0[Ru]= 7 atomic configuration= 7 oxidation= 0
We see that atom=1 and atoms=2 will have icix=1 and icix=2 in
case.indmfl file. We have [0,1] as correlated atoms. But we then
realize that atom=2,icix=2 can be spin-flipped to obtain
atom=1,icix=1, hence we actually need to simulate only one
impurity. When all impurities can be grouped by flipping, we write
"remain at the end=[]".
Finally, we also list what is default number of electrons expected on
this atom (ignoring oxidation state). We will later take occupancy
from DFT, and this number will be hence overwritten anyway.
Next we check the content of eDMFT input files. We start with
0_607_RuO2.indmfi:
1 # number of sigind blocks
10 # dimension of this sigind block
1 0 0 0 0 0 0 0 0 0
0 2 0 0 0 0 0 0 0 0
0 0 3 0 0 0 0 0 0 0
0 0 0 4 0 0 0 0 0 0
0 0 0 0 5 0 0 0 0 0
0 0 0 0 0 6 0 0 0 0
0 0 0 0 0 0 7 0 0 0
0 0 0 0 0 0 0 8 0 0
0 0 0 0 0 0 0 0 9 0
0 0 0 0 0 0 0 0 0 10
It means we have one impurity problem with diagonal hybridizations
enumerated from 1-10, hence we do not have spin-up down symmetry.
Next we check 0_607_RuO2.indmfl, which contains:
0 0 1 5 # hybridization band index nemin and nemax, renormalize for interstitials, projection type
1 0.025 0.025 200 -3.000000 1.000000 # matsubara, broadening-corr, broadening-noncorr, nomega, omega_min, omega_max (in eV)
2 # number of correlated atoms
1 1 -1 # iatom, nL, locrot
2 2 1 # L, qsplit, cix
0.70710678 0.70710678 0.00000000 # new x-axis
-0.50000000 0.50000000 -0.70710678 # new y-axis
-0.50000000 0.50000000 0.70710678 # new z-axis
2 1 -1 # iatom, nL, locrot
2 2 2 # L, qsplit, cix
0.70710678 -0.70710678 -0.00000000 # new x-axis
-0.50000000 -0.50000000 0.70710678 # new y-axis
-0.50000000 -0.50000000 -0.70710678 # new z-axis
#================ # Siginds and crystal-field transformations for correlated orbitals ================
2 5 5 # Number of independent kcix blocks, max dimension, max num-independent-components
1 5 5 # cix-num, dimension, num-independent-components
#---------------- # Independent components are --------------
'z^2' 'x^2-y^2' 'xz' 'yz' 'xy'
#---------------- # Sigind follows --------------------------
1 0 0 0 0
0 2 0 0 0
0 0 3 0 0
0 0 0 4 0
0 0 0 0 5
#---------------- # Transformation matrix follows -----------
0.00000000 0.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000
0.70710678 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.70710678 0.00000000
0.00000000 0.00000000 0.70710678 0.00000000 0.00000000 0.00000000 -0.70710678 0.00000000 0.00000000 0.00000000
0.00000000 0.00000000 0.00000000 0.70710678 0.00000000 0.00000000 0.00000000 0.70710678 0.00000000 0.00000000
0.00000000 0.70710678 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 -0.00000000 -0.70710678
2 5 5 # cix-num, dimension, num-independent-components
#---------------- # Independent components are --------------
'z^2' 'x^2-y^2' 'xz' 'yz' 'xy'
#---------------- # Sigind follows --------------------------
6 0 0 0 0
0 7 0 0 0
0 0 8 0 0
0 0 0 9 0
0 0 0 0 10
#---------------- # Transformation matrix follows -----------
0.00000000 0.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000
0.70710678 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.70710678 0.00000000
0.00000000 0.00000000 0.70710678 0.00000000 0.00000000 0.00000000 -0.70710678 0.00000000 0.00000000 0.00000000
0.00000000 0.00000000 0.00000000 0.70710678 0.00000000 0.00000000 0.00000000 0.70710678 0.00000000 0.00000000
0.00000000 0.70710678 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 -0.00000000 -0.70710678
We notice that local rotations are already properly set. The first
atom has hybridization components 1-5, and the second 6-10. We
encourage the user to now check 0_607_RuO2.indmfldn file, which
exchanges hybridization components, so that the first atom contains
indices 6-10 and the second 1-5. Using this symmetry, we manage to descrive
the two site problem with solving a single impurity problem.
A careful reader will see that the first line of indmfl file should
list the index of the bands which are augmented with eDMFT. Currently
these indices are set to "0 0". The reason for this is that we did
not yet perform DFT calculation to know the energy of bands, hence we
can finish this initialization only once the DFT program has finished
successfully.
Finally, the "params.dat" file is:
solver ='CTQMC' # impurity solver
DCs ='exacty' # double counting scheme
max_dmft_iterations =1 # number of iteration of the dmft-loop only
max_lda_iterations =100 # number of iteration of the LDA-loop only
finish =50 # number of iterations of full charge loop (1 = no charge self-consistency
ntail =300 # on imaginary axis, number of points in the tail of the logarithmic mesh
cc =1e-05 # the charge density precision to stop the LDA+DMFT run
ec =1e-05 # the energy precision to stop the LDA+DMFT run
recomputeEF =1 # Recompute EF in dmft2 step. If recomputeEF = 2, it tries to find an insulating gap.
# Impurity problem number 0
iparams0={
"exe" : ["ctqmc" , "# Name of the executable"],
"U" : [6.0 , "# Coulomb repulsion (F0) for Ru"],
"J" : [0.8 , "# Hunds coupling (J) for Ru"],
"CoulombF" : ["'Ising'" , "# Can be set to Full"],
"beta" : [50 , "# Inverse temperature"],
"svd_lmax" : [30 , "# We will use SVD basis to expand G, with this cutoff"],
"M" : [5000000 , "# Total number of Monte Carlo steps"],
"mode" : ["SH" , "# We will use self-energy sampling, and Hubbard I tail"],
"nom" : [250 , "# Number of Matsubara frequency points sampled"],
"tsample" : [400 , "# How often to record measurements"],
"GlobalFlip" : [1000000 , "# How often to try a global flip"],
"warmup" : [300000 , "# Warmup number of QMC steps"],
"nf0" : [7 , "# Nominal occupancy nd for double-counting"],
}
Here we choose "exacty"-double-counting, and U=6, J=0.8, and Ising
form of the Coulomb repulsion.
We next proceed to DFT calculation. Wien2k non-magnetic calculation
should be performed next. We will choose GGA functional (#13). During
initialization wien2k might complain that space group is not
compatible with bravais lattice:
Number and name of space group: 65 (C m m m)
warning: !!! Bravais lattice has changed.
because we used non-magnetic space group from mcif file, while w2k
wants to use another space group. But we should not accept w2k
suggestion here. If we accept w2k structure, we would need to change
case.indmfl file and case.indmfldn file, because the local axis choice
will no longer be appropriate. We therefore want to avoid any
transformation of the structure file by wien2k.
We can run initialization in batch mode, i.e.,
init_lapw -b -red 0 -vxc 13 -ecut -7.0 -numk 80
followed by
Now that we have DFT band-structure (the band energies for
hybridization window) and occupancy (for default nf0 in
double-counting) we finish eDMFT initialization. We execute
which gives the following information
INFO: case.indmfldn present => magnetic calculation with two dmft2 steps
Computing DMFT real space projector, which is written in projectorw.dat
atm_l_case= {0: ([2], 0), 1: ([2], 0)}
opening 0_607_RuO2.scf2
EF= 8.27056097924597 eV = 0.6078750733 Ry
dx= 0.015622910177195711
Rx[:]= 1e-05 1.9600000000000009 1.9600000000000009
using E= 0.6078750733
dx= 0.015622910177195711
Rx[:]= 1e-05 1.9600000000000009 1.9600000000000009
using E= 0.6078750733
Going over all case.energy files to find which bands are used to construct DMFT projector
Number of all atoms found in struct file 4
file: 0_607_RuO2.energy nemin= 13 nemax= 36
Finally set nemin= 13 nemax= 36
Found dft-occupancy[icix=1]= 4.5369
Found dft-occupancy[icix=2]= 4.5347
Impurity-lattice connection: imp2latt= {0: [1, 2]}
Finally nf0= {0: 5}
orig= "nf0" : [7 , "# Nominal occupancy nd for double-counting"],
repl= "nf0" : [5 , "# Nominal occupancy nd for double-counting"],
This output says that eDMFT will augment bands 13-36, hence this will
become first line in case.indmfl and case.indmfldn file. The DFT
occupancy is way smaller than atomic value 7, hence nf0 will be set to
the closest integer, which is here 5.
Finally we also initialize self-energy with finite spin splitting.
To do that, we use option "-m".
This option works for very simple cases like RuO2, however, it does
not always work, and one should carefully consider what is the best
choice of starting self-energy splitting. In this particular case we
choose self-energy at infinity (s_oo) to be 1eV lower for first five
orbitals, and 1eV higher for the second five orbitals, i.e.,
# s_oo= [24.4, 24.4, 24.4, 24.4, 24.4, 26.4, 26.4, 26.4, 26.4, 26.4]
# Edc= [25.4, 25.4, 25.4, 25.4, 25.4, 25.4, 25.4, 25.4, 25.4, 25.4]
The precise splitting is not important, and it will be adjusted during
self-consistent iteration. However, a bad choice for the splitting
will require many more iterations to achieve convergence. This is
especially important when we have many correlated atoms and many
different spin orientations. User should carefully consider which
columns correspond to which atom, and than shift s_oo or different
atoms according to their expected magnetic moments.
Before submitting this eDMFT run, we need to substantially increase
the number of momentum points. For example, 1000 momentum points is
reasonable. We do this by running:
We next submit the job to the supercomputer and use commensurate number
of cores to the number of momentum points in case.klist file (120 in
this case). Once the calculation is finished, we examine n_imp and
n_latt in info.iterate, i.e., column 9 and 10. If the two values are
sufficiently close, we can be confident in our choice of the
orbitals.
For the RuO2 the current choice of local orbitals is ok, and here is
how it should look like:
The lattice density is around 5.181 and the impurity density around 5.146,
which is acceptable, but later we will improve that with findRot.py script.
If the values are far off, there is either a bug, or, bad
choice of local orbitals. Currently we use cubic harmonics, but we
can execute "findRot.py" script on resulting calculation if the
mismatch between n_imp and n_latt is too large.
Even better is to compare case.gc[1-2] and imp.0/Gf.out.50.1. This
checks if the local green's function is the same as the impurity
green's function. If green's function is diagonal, our choice of diagonal
hybridization should make these two Green's function equal. But if
hybridization is chosen to be diagonal, while the Green's function is
not, we will have mismatch between the two quantities. Here is how they
look like in this run for up and down spins:
Similar conclusion can be drawn from the Green's function comparison
than the impurity/lattice density: the agreement is
not perfect, but it is acceptable. Hence we will proceed to the
analytic continuation.
We check a few last eDMFT self-energies (sig.inp.4[5-9].1
sig.inp.50.1) and we confirm that they differ only due to Monte
Carlo noise. We can hence average over the last few iterations. For example:
saverage.py sig.inp.4[5-9] sig.inp.50
to obtain "sig.inpx" averaged self-energy.
Next we proceed to the maximum-entropy method that produces
self-energy on the real axis.
For this example we will increase the real axis mesh to 30eV, because
it turns out that in some cases 20eV default is somewhat too small
window on the real axis. We also need to somewhat increase the number
of points on the real axis, since the range has increase (Nw=450). The
rest of the parameters are default, which we used before.
The content of "maxent_params.dat" file should be set to:
params={'statistics': 'fermi', # fermi/bose
'Ntau' : 400, # Number of time points
'L' : 30.0, # cutoff frequency on real axis
'x0' : 0.01, # low energy cut-off
'bwdth' : 0.004, # smoothing width
'Nw' : 450, # number of frequency points on real axis
'gwidth' : 2*15.0, # width of gaussian
'idg' : 1, # error scheme: idg=1 -> sigma=deltag ; idg=0 -> sigma=deltag*G(tau)
'deltag' : 0.005, # error
'Asteps' : 4000, # anealing steps
'alpha0' : 1000, # starting alpha
'min_ratio' : 0.001, # condition to finish, what should be the ratio
'iflat' : 1, # iflat=0 : constant model, iflat=1 : gaussian of width gwidth, iflat=2 : input using file model.dat
'Nitt' : 1000, # maximum number of outside iterations
'Nr' : 0, # number of smoothing runs
'Nf' : 40, # to perform inverse Fourier, high frequency limit is computed from the last Nf points
}
We next execute
and we should obtain the self-energy on the real axis "Sig.out", which
should look like this:
Next we create a directory for the real axis spectra and density of
states. Let's call it "onreal". We enter that subdirectory and copy all necessary files from the
self-consistent run by the script
Here the argument is
the name of the directory with the self-consistent run.
We will compute the band structure on the real axis now. But before we
run eDMFT on k-path in first BZ, we might need to fine tune the path.
The default path is [\Gamma,A,M,R,X,Z] (see "cif2struct.log" or look
into "0_607_RuO2.klist_band"). It turns out that this high symmetry path does not reveal the
nature of altermagnetic band splitting. The splitting is largest
between Gamma-M, hence we will modify the k-path to
[M,\Gamma,M,A,R,X,Z]. To do that, we will execute "klist_gen.py". This
script can be run interactively, or in batch mode. We will use the batch
mode here:
klist_gen.py -n 500 -p "[[0.5,0.5,0],[0,0,0],[0.5,0.5,0],[0.5,0.5,0.5],[0.,0.5,0.5],[0,0.5,0],[0,0,0.5]]" -m "['M','\Gamma','M','A','R','X','Z']"
which produces "case.klist_band", and we rename it to
"0_607_RuO2.klist_band".
Now we proceed to calculation of the densities of states and bands. We
execute the following
set of commands in the directory "onreal":
$WIENROOT/x_lapw lapw0 -f 0_607_RuO2 >& nohup.dat
$WIEN_DMFT_ROOT/x_dmft.py lapw1 >& nohup.dat
$WIEN_DMFT_ROOT/x_dmft.py dmft1 >& nohup.dat
$WIEN_DMFT_ROOT/x_dmft.py lapw1 --band >& nohup.dat
$WIEN_DMFT_ROOT/x_dmft.py dmftp >& nohup.dat
$WIEN_DMFT_ROOT/x_dmft.py dmftp -l dn >& nohup.dat
This first two produce DFT potential and DFT bands (vector file). Then
dmft1 produces local density of states and green's function on the
real axis. We could omit the two steps (lapw1 and dmft1) if DOS is not needed. Or, we could
add another dmft1 step with "-l dn" option. The latter would produce
DOS for down spins. For altermagnet the down-spins have identical DOS
as the up-spins. But in ferrimagnetic or ferromagnetic materials the density of
states for up and down are different, and we need additional dmft1
step.
Finally, dmftp step here produces dmft eigenvalues (dmft bands) and is
execute for both the up and the down spins,
because the two are expected to be different in altermagnets.
Finally, we want to plot the spectral function of both the up and down
spins simultaneously. We have a dedicated python script for that:
which reads both "eigvals.dat" and "eigvalsdn.dat", and displays them
in red-blue color, respectively.
Here is how it looks like for this run:
The argument for intensity can be given to makplot.py, however, its
value should be between 0-1, and a number very close to 1 is
desired. Default is 0.97.
Namely, in the old version of "wakplot.py" routine we would specify
intensity (the argument) as the ratio between maximum value of Akw
considered when plotting (the cutoff for plotting) and the maximum
value found in the 2D plot. The problem with this algorithm is that
sometimes intensity needs to be reduced to a very small
number. Namely, it sometimes happens that a
very few points (sometimes a single point) in the 2D plot are extremely singular, while
majority of the relevant points have modest values distributed between
[0,v_max]. But v_max in this case is much smaller than the maximum
value we find in 2D plot, hence the ratio (given as input parameter)
must be very small to have a reasonable plot.
In the new version of the plotting program, we obtain the histogram of
values in the 2D plot, and we keep 97\% of the values in the plot,
i.e., 3\% are cut-off for the purpose of the plot. If the shapes
appear too broad and intense, we would increase this number closer to
unity. If the quasiparticle bands appear very faint, we would decrease this value
towards 0.5. But a small value for intensity in this algorithm does
not make much sense.
For this run, the value of
sharpens up the spectra, and produces
Finally, we noticed above that lattice density and impurity density do
not match perfectly at the converged solution, because the impurity
problem is not completely diagonal in our chosen real harmonics
basis. But we have freedom to choose any orbital basis we want, and
a better basis can be often chosen by diagonalizing the hybridization
function at low frequency.
The script "findRot.py" does that. It can diagonalize hybridization
either at low energy, or at infinite frequency, and should
substantially reduce this mismatch.
We will slightly edit the self-energy file and we will add frequency
omega=0 on imaginary axis. This is not essential, but it is a good
idea to diagonalize hybridization at exactly zero frequency, which is
of course equal on real and imaginary axis. We will take the real part
of the self-energy for each orbital from the lowest matsubara point,
while we will zero out imaginary parts (because they should vanish at
zero frequency in a metal). The first two lines of the data in the
"sig.inp" file look like that
0.0 -9.299057493961586651e-01 0.0 -7.980767955268603941e-01 0.0 1.856077099430119670e+00 0 ....
6.283185307179600665e-02 -9.299057493961586651e-01 -2.480501738282099924e-02 -7.980767955268603941e-01 -1.601768961148599887e-02 1.856077099430119670e+00 -3.745090133373799729e-02 ...
We than execute lapw1 and dmft1 on this self-energy
x_dmft.py lapw1
x_dmft.py dmft1
which will compute the density matrix and the hybridization at zero
frequency and at infinite frequency. We look into
"0_607_RuO2.outputdmf1" and see
omega~0 is 0.000000000000000E+000 at i= 1
Full matrix of impurity levels follows
icix= 1
-2.19442993 -0.00000000 0.02491185 -0.00000000 0.00001048 -0.00000000 -0.10556106 0.00000000 -0.00000777 0.00000000
0.02491185 0.00000000 -2.22316952 -0.00000000 -0.00001503 0.00000000 0.18283159 -0.00000000 0.00001659 -0.00000000
0.00001048 0.00000000 -0.00001503 -0.00000000 -4.07898996 -0.00000000 0.00000261 0.00000000 0.03014284 -0.00000000
-0.10556106 -0.00000000 0.18283159 0.00000000 0.00000261 -0.00000000 -3.83831649 0.00000000 -0.00000261 -0.00000000
-0.00000777 -0.00000000 0.00001659 0.00000000 0.03014284 0.00000000 -0.00000261 0.00000000 -4.07898793 0.00000000
icix= 1 at omega=0
2.30955442 -0.00000000 -1.99477879 0.00000000 -0.00013691 0.00000000 -0.42448657 0.00000000 0.00015658 0.00000000
-1.99477879 -0.00000000 4.60893257 -0.00000000 0.00030171 0.00000000 0.73482339 0.00000000 -0.00020871 -0.00000000
-0.00013691 -0.00000000 0.00030171 -0.00000000 -3.46926140 -0.00000000 -0.00029553 0.00000000 0.24824833 -0.00000000
-0.42448657 -0.00000000 0.73482339 -0.00000000 -0.00029553 -0.00000000 -3.50311324 0.00000000 0.00029820 -0.00000000
0.00015658 -0.00000000 -0.00020871 0.00000000 0.24824833 0.00000000 0.00029820 0.00000000 -3.46903791 0.00000000
icix= 2
-2.19530225 -0.00000000 0.02477157 -0.00000000 0.00000775 -0.00000000 -0.10494473 -0.00000000 -0.00000479 0.00000000
0.02477157 0.00000000 -2.22386664 0.00000000 -0.00001001 0.00000000 0.18176118 0.00000000 0.00001172 0.00000000
0.00000775 0.00000000 -0.00001001 -0.00000000 -4.07979893 0.00000000 0.00000060 0.00000000 0.03043344 0.00000000
-0.10494473 0.00000000 0.18176118 -0.00000000 0.00000060 -0.00000000 -3.83803086 -0.00000000 -0.00000060 0.00000000
-0.00000479 -0.00000000 0.00001172 -0.00000000 0.03043344 0.00000000 -0.00000060 -0.00000000 -4.07979861 0.00000000
icix= 2 at omega=0
3.09647612 -0.00000000 -1.48434905 0.00000000 0.00087385 -0.00000000 -0.00526244 -0.00000000 -0.00005241 0.00000000
-1.48434905 -0.00000000 4.82431354 0.00000000 -0.00055118 0.00000000 0.01001850 -0.00000000 0.00100097 -0.00000000
0.00087385 0.00000000 -0.00055118 -0.00000000 -2.91196068 0.00000000 0.00005605 0.00000000 0.49142684 -0.00000000
-0.00526244 0.00000000 0.01001850 0.00000000 0.00005605 -0.00000000 -3.44759215 -0.00000000 -0.00004601 -0.00000000
-0.00005241 -0.00000000 0.00100097 0.00000000 0.49142684 0.00000000 -0.00004601 0.00000000 -2.91328536 0.00000000
First line shows that the code found the zero frequency in the first
line of self-energy, and it will compute the hybridization at that
frequency. The first and the third matrix correspond to the
impurity levels on Ru[0] and Ru[1] atom for up spins. They do not
depend on the self-energy. While there is some mixing between
orbitals, its mixing at infinite frequency is weak. But at zero
frequency this is not the case. If we look at the matrix two and
four we see large mixing between z^2 and x^2-y^2 orbital (the
first two orbitals) and x^2-y^2 with yz orbital. To diagonalize
this hybridization, we execute
This diagonalization mostly mixes z^2 with x^2-y^2 orbital and xz with
xy orbital, such that
the new choice of the orbitals on the first Ru is
Y_{z^2}*0.86583974+Y_{x^2-y^2}*0.49827165, and
Y_{z^2}*0.50032144-0.86228814*Y_{x^2-y^2}, as well as
(Y_{xz}+Y_{xy})/sqrt(2), (Y_{xz}-Y_{xy})/sqrt(2).
The script also corrected "0_607_RuO2.indmfl" file, which now has the
following local orbitals on Ru[0]
0.35378068 0.00000504 0.00000522 0.00001678 0.86583974 0.00000000 -0.00000522 0.00001678 0.35378068 -0.00000504
-0.60972979 0.00001695 -0.00002246 -0.06397079 0.49827165 0.00000000 0.00002246 -0.06397079 -0.60972979 -0.00001695
0.00020813 0.49988468 -0.50010977 -0.00233687 -0.00016978 0.00000000 0.50010977 -0.00233687 0.00020813 -0.49988468
0.05539642 -0.00166417 0.00165785 -0.70420329 -0.04524249 0.00000000 -0.00165785 -0.70420329 0.05539642 0.00166417
0.00000660 -0.50011252 -0.49988745 0.00000533 0.00000647 0.00000000 0.49988745 0.00000533 0.00000660 0.50011252
and the following on Ru[1]
0.35248283 0.00006914 0.00007282 0.00005369 0.86689773 0.00000000 -0.00007282 0.00005369 0.35248283 -0.00006914
-0.61298876 -0.00006949 0.00007121 -0.00087625 0.49848571 0.00000000 -0.00007121 -0.00087625 -0.61298876 0.00006949
0.00004893 -0.49966294 -0.50033683 -0.00000490 0.00012396 0.00000000 0.50033683 -0.00000490 0.00004893 0.49966294
-0.00078652 0.00084366 -0.00084945 0.70710522 0.00055202 -0.00000000 0.00084945 0.70710522 -0.00078652 -0.00084366
0.00008365 -0.50033611 0.49966221 0.00119733 -0.00007231 -0.00000000 -0.49966221 0.00119733 0.00008365 0.50033611
Note that each row correspond to one local orbital, but written in
spherical harmonics, starting with m=-2,-1,...2.
Next we want to rerun dmft1 step, and check how diagonal are impurity
levels now:
The output in "0_607_RuO2.outputdmf1" is
omega~0 is 0.000000000000000E+000 at i= 1
Full matrix of impurity levels follows
icix= 1
-2.18004748 0.00000000 0.00001289 0.00000000 0.00000022 -0.00000000 -0.00004107 0.00000000 0.00001917 -0.00000000
0.00001289 -0.00000000 -2.21263596 -0.00000000 0.00013626 -0.00000000 0.06353508 -0.00000000 -0.00001056 0.00000000
0.00000022 0.00000000 0.00013626 0.00000000 -4.10911936 0.00000000 0.00081448 0.00000000 0.00001455 0.00000000
-0.00004107 -0.00000000 0.06353508 0.00000000 0.00081448 -0.00000000 -3.86331357 0.00000000 -0.00000171 0.00000000
0.00001917 0.00000000 -0.00001056 -0.00000000 0.00001455 -0.00000000 -0.00000171 -0.00000000 -4.04884784 0.00000000
icix= 1 at omega=0
1.06866021 0.00000000 -0.00490263 -0.00000000 0.00000106 -0.00000000 -0.00014357 -0.00000000 0.00004811 0.00000000
-0.00490263 0.00000000 5.82362525 -0.00000000 -0.00039349 0.00000000 -0.00137855 0.00000000 -0.00004948 0.00000000
0.00000106 0.00000000 -0.00039349 -0.00000000 -3.71341613 0.00000000 0.00045141 0.00000000 0.00015137 -0.00000000
-0.00014357 0.00000000 -0.00137855 -0.00000000 0.00045141 -0.00000000 -3.58091974 0.00000000 0.00000151 0.00000000
0.00004811 -0.00000000 -0.00004948 -0.00000000 0.00015137 0.00000000 0.00000151 -0.00000000 -3.21766437 0.00000000
icix= 2
-2.18104942 -0.00000000 -0.00011523 0.00000000 0.00026524 -0.00000000 -0.00049293 -0.00000000 -0.00000774 0.00000000
-0.00011523 -0.00000000 -2.23759918 0.00000000 0.00000472 0.00000000 -0.20796699 0.00000000 -0.00061574 0.00000000
0.00026524 0.00000000 0.00000472 -0.00000000 -4.04936646 -0.00000000 -0.00000197 -0.00000000 0.00004117 0.00000000
-0.00049293 -0.00000000 -0.20796699 0.00000000 -0.00000197 0.00000000 -3.83847698 -0.00000000 0.00048766 -0.00000000
-0.00000774 -0.00000000 -0.00061574 -0.00000000 0.00004117 -0.00000000 0.00048766 0.00000000 -4.11017740 0.00000000
icix= 2 at omega=0
2.24446045 -0.00000000 0.00586448 0.00000000 0.00084256 -0.00000000 -0.00046833 -0.00000000 -0.00002755 0.00000000
0.00586448 -0.00000000 5.62743693 0.00000000 0.00001635 0.00000000 -0.00372699 -0.00000000 -0.00449864 0.00000000
0.00084256 0.00000000 0.00001635 -0.00000000 -2.41907272 -0.00000000 0.00000532 -0.00000000 0.00062370 -0.00000000
-0.00046833 0.00000000 -0.00372699 0.00000000 0.00000532 0.00000000 -3.44784432 -0.00000000 -0.00055677 -0.00000000
-0.00002755 -0.00000000 -0.00449864 -0.00000000 0.00062370 0.00000000 -0.00055677 0.00000000 -3.39060635 0.00000000
which shows that both at zero and infinite frequency the hybridization
is now pretty diagonal. But the hybridization is not exactly
diagonal and sometimes turns out to be quite off-diagonal after
using this script. This looks counterintuitive at first, as we
diagonalized the matrix, and hence expect exactly diagonal
result. If we use the "findRot.py" script on the DFT run, or
constant self-energy, it will exactly diagonalize the
hybridization. However, when using the same script on finite
self-energy (or not constant self-energy), diagonalization becomes
non-linear problem, because the hybridization does not only depend
on the choice of the orbital, but also non-linearly on the
self-energy embedded into the system. Namely, the hybridization
depends non-linearly on the embedded self-energy, which is also
changed by changing the local orbital basis. Therefore this
diagonalization will not always work at the first step. If the
resulting hybridization is still very off-diagonal, we might want
to repeat the procedure. Namely call the script finRot.py again
and recompute the hybridization with dmft1 step. We could repeat
this for several iterations, and see if this produces more
diagonal hybridization than the first step.
One more word of caution is in order. The current script "findRot.py"
currently changes only case.indmfl but not case.indmfldn. Once we are
happy with the choice of the orbitals in case.indmfl, we should also
change orbitals in case.indmfldn accordingly. For example, orbitals
1-5 in case.indmfl should be copied to 6-10 in case.indmfldn, and
viceversa.
Once we updated "0_607_RuO2.indmfl" and "0_607_RuO2.indmfldn", we copy
them to the converged run, and resubmit the job, to converge it again
with this superior choice of orbitals. The difference between the
impurity and lattice density disappears, and info.iterate (column 9
and 10) show the following:
We included for reference the original run with real harmonics, which
is compared with this run using diagonalized local orbitals.
The Green's function mismatch is also eliminated. We plot the
comparison between the impurity and lattice Green's function for
both Ru sites:
We now repeat previous steps to obtain the real axis spectra:
saverage.py sig.inp.4[5-9] sig.inp.50
mkdir maxent
cd maxent
cp ../sig.inpx .
cp ../../oldrun/maxent/maxent_params.dat .
maxent_run.py sig.inpx
mkdir ../onreal
cd ../onreal
dmft_copy.py ../
cp ../../oldrun/onreal/0_607_RuO2.klist_band
x_lapw lapw0 -f 0_607_RuO2
x_dmft.py lapw1 --band
x_dmft.py dmftp
x_dmft.py dmftp -l dn
makplot.py 0.99
Finally we obtain the following spectral function:
Plotting 2D cuts of spectral function at EF
In this section we will plot the Fermi surface as a 2D cut in the
BZ. This will show if the system has particular symmetry at the Gamma
point, i.e., d-wave symmetry, for example.
To do that, we first prepare input file "2D_params.py" in which we
write 2D path we want to take in first BZ. The file can contain a
single line, like:
This means that we will make a cut at z=0. We choose the variable x to
go from [-1,1], and variable y to also go from [-1,1]. Using these two
variables, we define 2D plane in BZ for the 2D plot.
We can execute
which will plot the first Brillouin zone and the 2D cut we choose to
make.
The python script bz.py will produce the plot of the BZ.
The blue plane shows the 2D cut we are making. The thick arrows are
three reciprocal basis vectors, and the thin lines are chosen
cartesian basis vectors. Note that the 2D plane in kpath=[] should be
specified in cartesian basis, which is usually easier to comprehend
than reciprocal basis. Note that the latter is in general
non-orthogonal, while cartesian basis is always orthonormal. In this
simple case the two basis coincide. Note also that
red/gren/blue arrows stand for x/y/z direction.
Next we execute
which will produce "case.klist_band" that can be used to plot
spectra. By default the number of k-points in single direction is
"Nxy=90", which can be changed, if desired. Number of all k-points for
this 2D plot is 91^2=8281. But when case.struct file contains all
symmetry operations, this number can be reduced substantially. For
example, RuO2 has 8 symmetry operations, and the non-equivalent
momentum points are cut down to 2116.
The output should say something like
Number of all irreducible points= 2116 versus all= 8281
We want to plot only single frequency omega=0 to obtain the
Fermi surface, hence we will slightly change "case.indmfl" file. The
second line should be changed to
0 0.025 0.025 2 0.0 0.01 # matsubara, broadening-corr, broadening-noncorr, nomega, omega_min, omega_max (in eV)
where nomega is set to 2, and frequency omega_min=0 and
omega_max=0.01. This will actually produce a single frequency at the
output (omega=0), but nomega=2 means that in addition to single point in
infinity, we also have one extra point at zero frequency.
Here we also assume that self-energy on the real axis is available in
the current directory, and for example, density of states was computed
prior.
Than we recompute Kohn-Sham states, and DMFT eigenvalues by executing
x_dmft.py lapw1 --band
x_dmft.py dmftp
x_dmft.py dmftp -l dn
This should produce "eigvals.dat" and "eigvalsdn.dat". These two files
are text files that contain DFT+DMFT eigenvalues for up and down
spins at specified zero frequency.
Next we execute
to plot the Fermi surface on this cut.
On the left we see separately
Fermi surface for up and down spins. On the right we see the combined
plot with both spins present. Clearly the cut shows d-wave symmetry.
Last modified: Mon Aug 5 18:20:54 EDT 2024