Last active
August 1, 2024 01:19
-
-
Save Ionizing/1ac92f98e8b00a1cf6f16bd57694ff03 to your computer and use it in GitHub Desktop.
A script to plot work function using LOCPOT.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
''' | |
A script to plot work function using LOCPOT. | |
Requirement: python3, numpy, matplotlib, ase | |
Author: @Ionizing | |
Date: 22:46, Jan 11th, 2021. | |
CHANGELOG: | |
- 1:56, Jan 25th, 2021 | |
- Add E-fermi level correction | |
- More logging info | |
- 10:05, Dec 28th, 2021 | |
- Fix E-fermi extraction error, return the last one if there are many 'E-fermi' items. | |
''' | |
from argparse import ArgumentParser | |
import os | |
import logging | |
import re | |
import numpy as np | |
import matplotlib.pyplot as plt | |
from ase.calculators.vasp import VaspChargeDensity | |
logging.basicConfig(level=logging.INFO) | |
logger = logging.getLogger(__name__) | |
def locpot_mean(fname="LOCPOT", axis='z', savefile='locpot.dat', outcar="OUTCAR"): | |
''' | |
Reads the LOCPOT file and calculate the average potential along `axis`. | |
@in: See function argument. | |
@out: | |
- xvals: grid data along selected axis; | |
- mean: averaged potential corresponding to `xvals`. | |
''' | |
def get_efermi(outcar="OUTCAR"): | |
if not os.path.isfile(outcar): | |
logger.warning("OUTCAR file not found. E-fermi set to 0.0eV") | |
return None | |
txt = open(outcar).read() | |
efermi = re.findall(r'E-fermi :\s*([-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?)', txt)[-1][0] | |
logger.info("Found E-fermi = {}".format(efermi)) | |
return float(efermi) | |
logger.info("Loading LOCPOT file {}".format(fname)) | |
locd = VaspChargeDensity(fname) | |
cell = locd.atoms[0].cell | |
latlens = np.linalg.norm(cell, axis=1) | |
vol = np.linalg.det(cell) | |
iaxis = ['x', 'y', 'z'].index(axis.lower()) | |
axes = [0, 1, 2] | |
axes.remove(iaxis) | |
axes = tuple(axes) | |
locpot = locd.chg[0] | |
# must multiply with cell volume, similar to CHGCAR | |
logger.info("Calculating workfunction along {} axis".format(axis)) | |
mean = np.mean(locpot, axes) * vol | |
xvals = np.linspace(0, latlens[iaxis], locpot.shape[iaxis]) | |
# save to 'locpot.dat' | |
efermi = get_efermi(outcar) | |
logger.info("Saving raw data to {}".format(savefile)) | |
if efermi is None: | |
np.savetxt(savefile, np.c_[xvals, mean], | |
fmt='%13.5f', header='Distance(A) Potential(eV) # E-fermi not corrected') | |
else: | |
mean -= efermi | |
np.savetxt(savefile, np.c_[xvals, mean], | |
fmt='%13.5f', header='Distance(A) Potential(eV) # E-fermi shifted to 0.0eV') | |
return (xvals, mean) | |
def parse_cml_arguments(): | |
parser = ArgumentParser( | |
description='A tool to plot work function according to LOCPOT', add_help=True) | |
parser.add_argument('-a', '--axis', type=str, action='store', | |
help='Which axis to be calculated: x, y or z. Default by z', default='z', choices=['x', 'y', 'z']) | |
parser.add_argument('input', nargs='?', type=str, | |
help='The input file name, default by LOCPOT', default='LOCPOT') | |
parser.add_argument('-w', '--write', type=str, action='store', | |
help='Save raw work function data to file, default by locpot.dat', default='locpot.dat') | |
parser.add_argument('-o', '--output', type=str, action='store', | |
help='Output image file name, default by Workfunction.png', default='Workfunction.png') | |
parser.add_argument('--dpi', type=int, action='store', | |
help='DPI of output image, default by 400', default=400) | |
parser.add_argument('--title', type=str, action='store', | |
help='Title in output image. If none, no title is added, default is None', default=None) | |
return parser.parse_args() | |
if '__main__' == __name__: | |
args = parse_cml_arguments() | |
x, y = locpot_mean(args.input, args.axis, args.write) | |
logger.info("Plotting to image") | |
plt.plot(x, y, color='k') | |
plt.xlabel('Distance(A)') | |
plt.ylabel('Potential(eV)') | |
plt.grid(color='gray', ls='-.') | |
plt.xlim(0, np.max(x)) | |
plt.ylim(np.max(y)-2, np.max(y)+0.5) | |
plt.minorticks_on() | |
if args.title: | |
plt.title(args.title) | |
logger.info("Saving to {}".format(args.output)) | |
plt.savefig(args.output, dpi=args.dpi) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment