In [1]:
# Created 2016, Zack Gainsforth
%pylab inline

import sys, os
import QuickPlot
import matplotlib.pylab as pylab
pylab.rcParams['figure.figsize'] = 8, 6  # that's default image size for this interactive session
import glob2 as glob


Populating the interactive namespace from numpy and matplotlib
/Users/Zack/anaconda/envs/conda36/lib/python3.6/site-packages/matplotlib/__init__.py:1405: UserWarning: 
This call to matplotlib.use() has no effect because the backend has already
been chosen; matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
or matplotlib.backends is imported for the first time.

  warnings.warn(_use_error_msg)

In [2]:
# Example from http://hjklol.mit.edu/content/calculating-hubbard-u
# Using MnO, with U=0 and alpha -0.08 to 0.08

# alpha, SCF start, SCF end
x = np.array([[-0.08, 5.914787, 5.901457],
              [-0.05, 5.905068, 5.896886],
              [ 0.05, 5.872840, 5.881723],
              [ 0.08, 5.863222, 5.877153]
              ])
fig,ax = QuickPlot.QuickPlot(x[:,0], x[:,1], boldlevel=3)
QuickPlot.QuickPlot(x[:,0], x[:,2], boldlevel=3,
         figax=(fig,ax),
         title='DFT+U linear alpha fit',
         xlabel='alpha (eV)',
         ylabel='Occupancy',
         legendstrs=['Bare (SCF start)', 'Screened (SCF finish)'])

mbare,bbare = np.polyfit(x[:,0], x[:,1], 1)
mscreen,bscreen = np.polyfit(x[:,0], x[:,2], 1)

print('mbare=%f'%mbare)
print('mscreen=%f'%mscreen)
print('Uscf=%f'%(1/mbare - 1/mscreen))


mbare=-0.322281
mscreen=-0.151824
Uscf=3.483684

In [9]:
# Read the Hubbard U linear alpha response out of the .out files.
# List them.
OutFiles = glob.glob('VOct-HubbardAlpha*.out')

def ReadOneHubbardUOutFile(FileName):
    # Go through an output file from a Hubbard U + alpha output file
    # and get the alpha, bare occupancy and screened occupancy.
    
    with open(FileName, 'r') as f:
        # There are three lines which give N of occupied +U levels.  Count as we go.
        whichocc = 0
        
        # Loop through the file.
        lines = f.readlines()
        for line in lines:
            
            # Check for alpha.
            if 'alpha(' in line:
                _,alpha = line.split('=')
                alpha = float(alpha)
                
            # Check for occupancy.
            if 'N of occupied +U levels ' in line:
                _,occ = line.split('=')
                occ = float(occ)
                # 0 is before the first SCF iteration.
                if whichocc == 0:
                    loadedocc = occ
                # 1 is the first SCF iteration, i.e. bare.
                if whichocc == 1:
                    bareocc = occ
                # 2 is after the full SCF, i.e. screened.
                if whichocc == 2:
                    screenedocc = occ
                whichocc += 1

        if whichocc != 3:
            print(f'File {FileName} failed to load.  Ignoring.')
            return None
        
    if np.abs((bareocc-loadedocc)/loadedocc) > 0.01:
        print('Warning!  Bare occupancy and loaded occupancy differ by more than 1%.  This may indicate that the calculation started out too far from convergence.  Check that you loaded the wavefunction from a previous scf.')

    return [alpha, bareocc, screenedocc]

LinearResponseValues = list()
print('Getting linear reponse values from:')
print('(filename: [alpha, bare, screened])')
for o in OutFiles:
    print(o, end=':\t\t')
    result = ReadOneHubbardUOutFile(o)
    if result == None:
        continue
    print(result)
    LinearResponseValues.append(result)

# Turn that into a numpy array for the plotting below and sort the values by alpha.
LinearResponseValues = np.array(LinearResponseValues)
LinearResponseValues = LinearResponseValues[LinearResponseValues[:,0].argsort()]


Getting linear reponse values from:
(filename: [alpha, bare, screened])
VOct-HubbardAlpha--0.000.out:		[0.0, 4.36954, 4.36923]
VOct-HubbardAlpha--0.010.out:		[-0.01, 4.373498, 4.371122]
VOct-HubbardAlpha--0.020.out:		[-0.03, 4.38143, 4.374601]
VOct-HubbardAlpha--0.030.out:		[-0.03, 4.38143, 4.374601]
VOct-HubbardAlpha--0.040.out:		[-0.04, 4.385403, 4.376341]
VOct-HubbardAlpha--0.050.out:		[-0.05, 4.389378, 4.378081]
VOct-HubbardAlpha--0.060.out:		[-0.06, 4.393359, 4.379821]
VOct-HubbardAlpha--0.070.out:		[-0.07, 4.397345, 4.381561]
VOct-HubbardAlpha--0.080.out:		[-0.08, 4.401334, 4.383297]
VOct-HubbardAlpha--0.090.out:		[-0.09, 4.405328, 4.384825]
VOct-HubbardAlpha--0.100.out:		[-0.1, 4.409326, 4.386543]
VOct-HubbardAlpha-0.010.out:		[0.01, 4.365586, 4.368007]
VOct-HubbardAlpha-0.020.out:		[0.02, 4.361636, 4.365894]
VOct-HubbardAlpha-0.030.out:		[0.03, 4.357691, 4.364157]
VOct-HubbardAlpha-0.040.out:		[0.04, 4.353748, 4.362421]
VOct-HubbardAlpha-0.050.out:		[0.05, 4.349811, 4.360686]
VOct-HubbardAlpha-0.060.out:		[0.06, 4.345878, 4.358954]
VOct-HubbardAlpha-0.070.out:		[0.07, 4.341949, 4.357232]
VOct-HubbardAlpha-0.080.out:		[0.08, 4.338025, 4.355583]
VOct-HubbardAlpha-0.090.out:		[0.09, 4.334105, 4.35385]
VOct-HubbardAlpha-0.100.out:		File VOct-HubbardAlpha-0.100.out failed to load.  Ignoring.
VOct-HubbardAlpha-0.110.out:		[0.11, 4.326276, 4.350475]

In [10]:
# alpha, SCF start, SCF end
x= LinearResponseValues
# x = np.array([[-0.05, 8.694105, 8.688330],
#               [-0.03, 8.690243, 8.686773],
#               [-0.01, 8.686388, 8.685218],
#               [0.01, 8.682538, 8.683637],
#               [0.03, 8.678695, 8.682088],
#               [0.05, 8.674857, 8.680525],
#              ])
fig,ax = QuickPlot.QuickPlot(x[:,0], x[:,1], boldlevel=3)
QuickPlot.QuickPlot(x[:,0], x[:,2], boldlevel=3,
         figax=(fig,ax),
         title='DFT+U linear alpha fit',
         xlabel='alpha (eV)',
         ylabel='Occupancy',
         legendstrs=['Bare (SCF start)', 'Screened (SCF finish)'])

mbare,bbare = np.polyfit(x[:,0], x[:,1], 1)
mscreen,bscreen = np.polyfit(x[:,0], x[:,2], 1)

print('mbare=%f'%mbare)
print('mscreen=%f'%mscreen)
print('Uscf=%f'%(1/mbare - 1/mscreen))


mbare=-0.395598
mscreen=-0.172778
Uscf=3.259953

In [ ]: