#/usr/bin/env python
#-code- utf-8
# mech2d is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# mech2d is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public Licensea
# along with mech2d. If not, see <http://www.gnu.org/licenses/>.
import os
import sys
import time
import shutil
import numpy as np
from uuid import uuid4
from monty.json import MSONable
from monty.serialization import loadfn,dumpfn
from pymatgen.core import Structure
from pymatgen.io.vasp import Incar,Kpoints,Poscar,Potcar, VaspInput, Vasprun
from mech2d.calculation.calculator import Calculator
[docs]class VASP(Calculator,MSONable):
name="VASP"
def __init__(self,inputdir,structure,
incar=None,
kpoints=None,
potcar=None,
structure_fmt='POSCAR',
outputdir=None,
params=None
):
#print(params)
self.outputdir=outputdir if outputdir else inputdir
self.inputdir=inputdir
self.structure_fmt=structure_fmt
self._set_structure(structure)
if params:
incar=params['INCAR']
kpoints=params['KPOINTS']
potcar=params['POTCAR']
self._set_incar(incar)
self._set_kpoints(kpoints)
self._set_potcar(potcar)
if 'vdw_kernel' in params.keys():
self._vdw=params['vdw_kernel']
else:
self._vdw=None
def _set_structure(self,structure):
if isinstance(structure,str):
structure_file=os.path.join(self.inputdir,structure)
if os.path.isfile(structure_file):
self.structure=Structure.from_file(structure_file)
else:
self.structure=Structure.from_str(structure,fmt=self.structure_fmt)
elif isinstance(structure,Structure):
self.structure=structure
elif isinstance(structure,dict):
self.structure=Structure.from_dict(structure)
else:
raise RuntimeError("structure must be a file, Structure Str, dictor Structure obj.")
def _set_incar(self,incar):
if isinstance(incar,str):
incar_file=os.path.join(self.inputdir,incar)
if os.path.isfile(incar_file):
self.incar=Incar.from_file(incar_file)
elif os.path.isfile(incar):
self.incar=Incar.from_file(incar)
else:
self.incar=Incar.from_string(incar)
elif isinstance(incar,Incar):
self.incar=incar
elif isinstance(incar,dict):
try:
self.incar=Incar.from_dict(incar)
except:
self.incar=None
elif incar is None:
try:
incar_file=os.path.join(self.inputdir,'INCAR')
self.incar=Incar.from_file(incar_file)
except:
self.incar=None
else:
raise RuntimeError("incar must be a file, Incar Str, dictor Incar obj.")
def _set_kpoints(self,kpoints):
if isinstance(kpoints,str):
kpoints_file=os.path.join(self.inputdir,kpoints)
if os.path.isfile(kpoints_file):
self.kpoints=Kpoints.from_file(kpoints_file)
else:
self.kpoints=Kpoints.from_file(kpoints)
elif isinstance(kpoints,Kpoints):
self.kpoints=kpoints
elif isinstance(kpoints,dict):
if 'kspacing' in kpoints.keys():
if kpoints['kspacing']>1:
if 'kgamma' in kpoints.keys():
_kpoints=Kpoints.automatic_density(self.structure,kpoints['kspacing'],force_gamma=True)
else:
_kpoints=Kpoints.automatic_density(self.structure,kpoints['kspacing'],force_gamma=False)
# we assume vaccum along the z direction
kpts=_kpoints.kpts.copy()
kpts[0][-1]=1
self.kpoints=Kpoints(kpts=kpts)
else:
if 'kgamma' in kpoints.keys():
self.kpoints=get_kpoints(self.structure, kpoints['kspacing'], kpoints['kgamma'], twod=True)
else:
self.kpoints=get_kpoints(self.structure, kpoints['kspacing'], False , twod=True)
else:
self.kpoints=Kpoints.from_dict(kpoints)
elif kpoints is None:
try:
kpoints_file=os.path.join(self.inputdir,"KPOINTS")
self.kpoints=Kpoints.from_file(kpoints_file)
except:
self.kpoints=None
else:
raise RuntimeError("kpoints must be a file, Kpoints Str, dictor Kpoints obj.")
def _set_potcar(self,potcar):
if isinstance(potcar,str):
potcar_file=os.path.join(self.inputdir,potcar)
if os.path.isfile(potcar_file):
self.potcar=Potcar.from_file(potcar_file)
elif os.path.isfile(potcar):
self.potcar=Potcar.from_file(potcar)
else:
raise RuntimeError("potcar must be a file, Potcar Str, dictor Potcar obj.")
elif isinstance(potcar,Potcar):
self.potcar=potcar
elif isinstance(potcar,dict):
if "functional" in potcar:
if 'symbol_set' in potcar:
self.potcar=Potcar(potcar['symbol_set'],functional=potcar["functional"])
else:
symbols=[el for el in self.structure.symbol_set]
self.potcar=Potcar(symbols,functional=potcar["functional"])
else:
try:
self.potcar=Potcar.from_dict(potcar)
except:
raise RuntimeError('unknow format for potcar dict')
elif potcar is None:
try:
potcar_file=os.path.join(self.inputdir,'POTCAR')
self.potcar=Potcar.from_file(potcar_file)
except:
raise RuntimeError("potcar must be a file, Potcar Str, dictor Potcar obj.")
else:
raise RuntimeError("potcar must be a file, Potcar Str, dictor Potcar obj.")
[docs] @staticmethod
def get_energy(outputdir):
fname=os.path.join(outputdir,'energy.json')
if os.path.exists(fname):
return loadfn(fname)
try:
vr=Vasprun(os.path.join(outputdir,'vasprun.xml'))
if vr.converged:
dumpfn(vr.final_energy,fname)
return vr.final_energy
except:
return None
[docs] @staticmethod
def get_stress(outputdir):
fname=os.path.join(outputdir,'stress.json')
if os.path.exists(fname):
return loadfn(fname)
try:
vr=Vasprun(os.path.join(outputdir,'vasprun.xml'))
if vr.converged:
dumpfn(vr.ionic_steps[-1]['stress'],fname)
return vr.ionic_steps[-1]['stress']
except:
return None
[docs]def get_kpoints(struct, kspacing, kgamma, twod=True) :
if isinstance(kspacing,list):
assert len(kspacing)==3
else:
kspacing = [kspacing, kspacing, kspacing]
rlat = struct.lattice.reciprocal_lattice.abc
kpts = [max(1,int(np.ceil(2 * np.pi * ii / ks))) for ii,ks in zip(rlat,kspacing)]
if twod:
kpts[2]=1
if kgamma:
return Kpoints.gamma_automatic(kpts=kpts)
else:
return Kpoints.monkhorst_automatic(kpts=kpts)
[docs]def test():
print(VASP.get_energy('.') )
if __name__=="__main__":
#test()
d=loadfn('input.yaml')
print(d)
vasp=VASP('.', 'POSCAR', params= d['code']['input'])
#kpoints = {'kspacing': 0.2,'kgamma':False}
#vasp=VASP('.','POSCAR',incar='INCAR',kpoints=kpoints,potcar='POTCAR') #{"functional":'PBE_54'})
#vasp=VASP('.','POSCAR',incar='INCAR',kpoints=kpoints,potcar={"functional":'unvie_PBE_52'})
print(vasp.name)
print(vasp)
print(vasp.incar)
print(vasp.structure)
#vasp.set_inputs()