Source code for qmpy.analysis.vasp.potential
from django.db import models
import logging
import qmpy
import qmpy.materials.element as elt
logger = logging.getLogger(__name__)
[docs]class Potential(models.Model):
"""
Class for storing a VASP potential.
Relationships:
| calculation
| element
Attributes:
| name
| date
| electrons: Electrons in potential.
| enmax
| enmin
| gw
| id
| paw
| potcar
| us
| xc
"""
potcar = models.TextField()
element = models.ForeignKey(elt.Element, on_delete=models.PROTECT)
name = models.CharField(max_length=10)
xc = models.CharField(max_length=3)
gw = models.BooleanField(default=False)
paw = models.BooleanField(default=False)
us = models.BooleanField(default=False)
enmax = models.FloatField()
enmin = models.FloatField()
date = models.CharField(max_length=20)
electrons = models.TextField(blank=True, null=True)
class Meta:
app_label = "qmpy"
db_table = "vasp_potentials"
def __str__(self):
ident = "%s %s" % (self.name, self.xc)
if self.paw:
ident += " PAW"
if self.us:
ident += " US"
if self.gw:
ident += " GW"
return ident
[docs] @classmethod
def read_potcar(cls, potfile):
"""
Import pseudopotential(s) from VASP POTCAR.
Make sure to save each of them after importing
in order to store in them in the OQMD
Arguments:
potfile - string, Path to POTCAR file
Output:
List of Potential objects
"""
# Read entire POTCAR file
pots = open(potfile).read()
# Split into the component POTCARs
pots = pots.strip().split("End of Dataset")
# Parse each file
potobjs = []
for pot in pots:
if not pot:
continue
# Get key information from POTCAR
potcar = {}
for line in pot.split("\n"):
# Get element name
if "TITEL" in line:
potcar["name"] = line.split()[3]
telt = potcar["name"].split("_")[0]
date = potcar["name"].split("_")[-1]
try:
potcar["element"] = elt.Element.objects.get(symbol=telt)
except:
print("Unknown element in potcar", telt)
raise
if "GW" in line:
potcar["gw"] = True
if "PAW" in line:
potcar["paw"] = True
if "US" in line:
potcar["us"] = True
if "ENMAX" in line:
data = line.split()
potcar["enmax"] = float(data[2].rstrip(";"))
potcar["enmin"] = float(data[5])
if "VRHFIN" in line:
potcar["electrons"] = line.split(":")[1]
if "LEXCH" in line:
key = line.split()[-1]
if key == "91":
potcar["xc"] = "GGA"
elif key == "CA":
potcar["xc"] = "LDA"
elif key == "PE":
potcar["xc"] = "PBE"
potobj, created = cls.objects.get_or_create(**potcar)
if created:
potobj.potcar = pot
potobjs.append(potobj)
return potobjs
[docs]class Hubbard(models.Model):
"""
Base class for a hubbard correction parameterization.
Attributes:
| calculation
| convention
| correction
| element
| id
| l
| ligand
| ox
| u
"""
element = models.ForeignKey(
elt.Element, related_name="hubbards", on_delete=models.CASCADE
)
convention = models.CharField(max_length=20)
ox = models.FloatField(default=None, null=True)
ligand = models.ForeignKey(
elt.Element, related_name="+", on_delete=models.CASCADE, null=True, blank=True
)
u = models.FloatField(default=0)
l = models.IntegerField(default=-1)
class Meta:
app_label = "qmpy"
db_table = "hubbards"
def __bool__(self):
if self.u > 0 and self.l != -1:
return True
else:
return False
def __eq__(self, other):
if self.element != other.element:
return False
elif self.ligand != other.ligand:
return False
elif self.u != other.u:
return False
elif self.l != other.l:
return False
return True
def __str__(self):
retval = self.element_id
if self.ox:
retval += "+%d" % (self.ox)
if self.ligand:
retval += "-" + self.ligand_id
retval += ", U=%0.2f, L=%d" % (self.u, self.l)
return retval
def __hash__(self):
return hash(self.__str__())
@property
def key(self):
return "%s_%s" % (self.element_id, self.u)
@classmethod
def get(cls, elt, ox=None, u=0, l=-1, lig=None):
hub, new = Hubbard.objects.get_or_create(
element_id=elt, ligand=lig, ox=ox, l=l, u=u
)
if new:
hub.save()
return hub