import numpy as np
import re
import logging
import matplotlib.pyplot as plt
import sys
from ..utilsprocar import UtilsProcar
class ProcarParser:
"""Parses a PROCAR file and store it in memory. It only deals with
PROCAR files, that means no Fermi energy (UtilsProcar.FermiOutcar
can help), and the reciprocal vectors should be supplied (if used,
see UtilsProcar class).
Members:
__init__(self, loglevel): The setup the variables internally, `loglevel`
sets the verbosity level ie: `loglevel=logging.DEBUG` for debugging. Its
default is `logging.WARNING`
readFile(self, procar=None, permissive=False, recLattice=None):
The only method of the API it load the file completely.
Arguments:
`procar=None`: name of the PROCAR file, can be a gzipped file (the
extension is no required). The default covers a wide range
of obvious alternatives.
`permissive=False`: Set to `True` if the PROCAR file has problems reading
the Kpoints (stupid Fortran), but in that case the
Kpoints mesh will be discarded. Future updates could
allow it to handle other formating/corruption issues.
`recLattice`=None: Reciprical Vectors, you want to provide them since not
all the paths on the BZ are the same.
Don't use the other methods beggining with underscores "_"
Example:
To read a PROCAR or PROCAR.gz file:
>>> foo = ProcarParser()
>>> foo.readFile()
To include the reciprocal vectors, and file name MyFirstPROCAR
>>> outcarparser = UtilsProcar()
>>> recLat = outcarparser.RecLatOutcar(args.outcar)
>>> foo = ProcarParser()
>>> foo.readFile("MyFirstPROCAR", recLat=recLat)
"""
def __init__(self, loglevel=logging.WARNING):
# array with k-points, they have the following values
# -None: if not parsed (yet) or parsed with a `permissive` flag on
# -direct coordinates: if a recLattice was not supplied to the parser
# -cartesian coords: if a recLattice was supplied to the parser.
# In the later cases, self.kpoints.shape=(self.kpointsCount, 3)
self.kpoints = None
# Number of kpoints, as given by the KPOINTS header (PROCAR file)
self.kpointsCount = None
# bands headers present in PROCAR file.
# self.bands.shape=(self.kpointsCount,self.bandsCount)
self.bands = None
# Number of bands. For a spin polarized calculation the number of
# bands is double (spin ip + spin down). On this array there is no
# distinction between spin up and down
self.bandsCount = None
#Number of ions+1 the +1 is the 'tot' field, ie: the sum over all atoms
self.ionsCount = None
self.fileStr = None #the actual file, stored in memory
self.spd = None #the atom/orbital projected data
self.cspd = None #spd data with the phase
self.orbitalName = [
"s", "py", "pz", "px", "dxy", "dyz", "dz2", "dxz", "dx2", "tot"
]
self.orbitalCount = None #number of orbitals
# number of spin components (blocks of data), 1: non-magnetic non
# polarized, 2: spin polarized collinear, 4: non-collinear
# spin.
# NOTE: before calling to `self._readOrbital` the case '4'
# is marked as '1'
self.ispin = None
self.recLattice = None #reciprocal lattice vectors
self.utils = UtilsProcar()
self.log = logging.getLogger("ProcarParser")
self.log.setLevel(loglevel)
self.ch = logging.StreamHandler()
self.ch.setFormatter(
logging.Formatter("%(name)s::%(levelname)s:"
" %(message)s"))
self.ch.setLevel(logging.DEBUG)
self.log.addHandler(self.ch)
#At last, one message to the logger.
self.log.debug("Procar instanciated")
return
@property
def nspin(self):
"""
number of spin, default is 1.
"""
nspindict = {1: 1, 2: 2, 4: 2, None: 1}
return nspindict[self.ispin]
@property
def spd_orb(self):
# indices: ikpt, iband, ispin, iion, iorb
# remove indices and total from iorb.
return self.spd[:, :, :, 1:-1]
def _readKpoints(self, permissive=False):
"""Reads the k-point headers. A typical k-point line is:
k-point 1 : 0.00000000 0.00000000 0.00000000 weight = 0.00003704\n
fills self.kpoint[kpointsCount][3]
The weights are discarded (are they useful?)
"""
self.log.debug("readKpoints")
if not self.fileStr:
log.warning(
"You should invoke `procar.readFile()` instead. Returning")
return
# finding all the K-points headers
self.kpoints = re.findall(r"k-point\s+\d+\s*:\s+([-.\d\s]+)",
self.fileStr)
self.log.debug(str(len(self.kpoints)) + " K-point headers found")
self.log.debug("The first match found is: " + str(self.kpoints[0]))
# trying to build an array
self.kpoints = [x.split() for x in self.kpoints]
try:
self.kpoints = np.array(self.kpoints, dtype=float)
except ValueError:
self.log.error("Ill-formatted data:")
print('\n'.join([str(x) for x in self.kpoints]))
if permissive is True:
# Discarding the kpoints list, however I need to set
# self.ispin beforehand.
if len(self.kpoints) == self.kpointsCount:
self.ispin = 1
elif len(self.kpoints) == 2 * self.kpointsCount:
self.ispin = 2
else:
raise ValueError("Kpoints do not match with ispin=1 or 2.")
self.kpoints = None
self.log.warning(
"K-points list is useless, setting it to `None`")
return
else:
raise ValueError(
"Badly formated Kpoints headers, try `--permissive`")
# if successful, go on
# trying to identify an non-polarized or non-collinear case, a
# polarized case or a defective file
if len(self.kpoints) != self.kpointsCount:
#if they do not match, may means two things a spin polarized
#case or a bad file, lets check
self.log.debug("Number of kpoints do not match, looking for a "
"spin-polarized case")
# lets start testing if it is spin polarized, if so, there
# should be 2 identical blocks of kpoints.
up, down = np.vsplit(self.kpoints, 2)
if (up == down).all():
self.log.info("Spin-polarized calculation found")
self.ispin = 2
# just keeping one set of kpoints (the other will be
# discarded)
self.kpoints = up
else:
self.log.error("Number of K-points do not match! check them.")
raise RuntimeError("Bad Kpoints list.")
# if ISPIN != 2 setting ISPIN=1 (later for the non-collinear case 1->4)
# It is unknown until parsing the projected data
else:
self.ispin = 1
#checking again, for compatibility,
if len(self.kpoints) != self.kpointsCount:
raise RuntimeError(
"Kpoints number do not match with metadata (header of PROCAR)")
self.log.debug(str(self.kpoints))
self.log.info("The kpoints shape is " + str(self.kpoints.shape))
if self.recLattice is not None:
self.log.info("Changing to cartesians coordinates")
self.kpoints = np.dot(self.kpoints, self.recLattice)
self.log.debug("New kpoints: \n" + str(self.k
Python库 | pyprocar-4.1.3.tar.gz
版权申诉
48 浏览量
2022-04-13
19:22:28
上传
评论
收藏 56KB GZ 举报
挣扎的蓝藻
- 粉丝: 13w+
- 资源: 15万+
最新资源
- 基于Matlab人脸肤色定理的教师人数统计+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于Matlab霍夫曼变换的表盘读数识别+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于Matlab火灾烟雾检测源码带GUI界面+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于Matlab的恶劣天气交通标志识别系统+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于MATLAB的霍夫曼变换的表盘示数识别+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于Matlab的车道线识别系统 +源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于MATLAB的教室人数统计系统带Gui界面+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于MATLAB的教室人数统计系统带Gui界面+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于MATLAB 的霍夫曼变换答题卡识别源码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
- 基于Matlab+bp神经网络的神经网络汉字识别系统+源代码+全部数据+文档说明+详细注释+使用说明+截图(高分课程设计)
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈