-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #152 from JaGeo/master
Validators and Jobs for Lobster
- Loading branch information
Showing
46 changed files
with
39,360 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from __future__ import unicode_literals | ||
|
||
""" | ||
This package implements Lobster Jobs and Error Handlers. | ||
""" | ||
|
||
__author__ = "Janine George, Guido Petretto" | ||
__version__ = "0.1" | ||
__maintainer__ = "Janine George, Guido Petretto" | ||
__email__ = "[email protected]" | ||
__status__ = "Production" | ||
__date__ = "27/4/20" |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import os | ||
|
||
from custodian.custodian import Validator | ||
from pymatgen.io.lobster import Lobsterout | ||
|
||
""" This module implements specific error handler for Lobster runs. """ | ||
|
||
__author__ = "Janine George, Guido Petretto" | ||
__copyright__ = "Copyright 2020, The Materials Project" | ||
__version__ = "0.1" | ||
__maintainer__ = "Janine George" | ||
__email__ = "[email protected]" | ||
__date__ = "April 27, 2020" | ||
|
||
|
||
class EnoughBandsValidator(Validator): | ||
""" | ||
validates if enough bands for COHP calculation are available | ||
""" | ||
|
||
def __init__(self, output_filename: str = "lobsterout"): | ||
""" | ||
Args: | ||
output_filename: filename of output file, usually lobsterout | ||
""" | ||
self.output_filename = output_filename | ||
|
||
def check(self) -> bool: | ||
""" | ||
checks if the VASP calculation had enough bands | ||
Returns: | ||
(bool) if True, too few bands have been applied | ||
""" | ||
# checks if correct number of bands is available | ||
try: | ||
with open(self.output_filename) as f: | ||
data = f.read() | ||
return 'You are employing too few bands in your PAW calculation.' in data | ||
except OSError: | ||
return False | ||
|
||
|
||
class LobsterFilesValidator(Validator): | ||
""" | ||
Check for existence of some of the files that lobster | ||
normally create upon running. | ||
Check if lobster terminated normally by looking for finished | ||
""" | ||
|
||
def __init__(self): | ||
pass | ||
|
||
def check(self) -> bool: | ||
for vfile in ["lobsterout"]: | ||
if not os.path.exists(vfile): | ||
return True | ||
with open("lobsterout") as f: | ||
data = f.read() | ||
return ('finished' not in data) | ||
|
||
|
||
class ChargeSpillingValidator(Validator): | ||
""" | ||
Check if spilling is below certain threshold! | ||
""" | ||
|
||
def __init__(self, output_filename: str = 'lobsterout', charge_spilling_limit: float = 0.05): | ||
""" | ||
Args: | ||
output_filename: filename of the output file of lobter, usually lobsterout | ||
charge_spilling_limit: limit of the charge spilling that will be considered okay | ||
""" | ||
|
||
self.output_filename = output_filename | ||
self.charge_spilling_limit = charge_spilling_limit | ||
|
||
def check(self) -> bool: | ||
# open lobsterout and find charge spilling | ||
|
||
if os.path.exists(self.output_filename): | ||
lobsterout = Lobsterout(self.output_filename) | ||
if lobsterout.chargespilling[0] > self.charge_spilling_limit: | ||
return True | ||
if len(lobsterout.chargespilling) > 1: | ||
if lobsterout.chargespilling[1] > self.charge_spilling_limit: | ||
return True | ||
return False | ||
else: | ||
return False |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import logging | ||
import os | ||
import shutil | ||
import subprocess | ||
|
||
from custodian.custodian import Job | ||
from monty.io import zopen | ||
from monty.shutil import compress_file | ||
|
||
""" This module implements jobs for Lobster runs. """ | ||
|
||
__author__ = "Janine George, Guido Petretto" | ||
__copyright__ = "Copyright 2020, The Materials Project" | ||
__version__ = "0.1" | ||
__maintainer__ = "Janine George" | ||
__email__ = "[email protected]" | ||
__date__ = "April 27, 2020" | ||
|
||
LOBSTERINPUT_FILES = ["lobsterin"] | ||
LOBSTEROUTPUT_FILES = ["lobsterout", "CHARGE.lobster", "COHPCAR.lobster", "COOPCAR.lobster", "DOSCAR.lobster", | ||
"GROSSPOP.lobster", "ICOHPLIST.lobster", "ICOOPLIST.lobster", "lobster.out", | ||
"projectionData.lobster"] | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class LobsterJob(Job): | ||
""" | ||
Runs the Lobster Job | ||
""" | ||
|
||
def __init__(self, lobster_cmd: str, output_file: str = "lobsterout", stderr_file: str = "std_err_lobster.txt", | ||
gzipped: bool = True, add_files_to_gzip=[], backup: bool = True): | ||
""" | ||
Args: | ||
lobster_cmd: command to run lobster | ||
output_file: usually lobsterout | ||
stderr_file: standard output | ||
gzipped: if True, Lobster files and add_files_to_gzip will be gzipped | ||
add_files_to_gzip: list of files that should be gzipped | ||
backup: if True, lobsterin will be copied to lobsterin.orig | ||
""" | ||
self.lobster_cmd = lobster_cmd | ||
self.output_file = output_file | ||
self.stderr_file = stderr_file | ||
self.gzipped = gzipped | ||
self.add_files_to_gzip = add_files_to_gzip | ||
self.backup = backup | ||
|
||
def setup(self): | ||
""" | ||
will backup lobster input files | ||
""" | ||
if self.backup: | ||
for f in LOBSTERINPUT_FILES: | ||
shutil.copy(f, "{}.orig".format(f)) | ||
|
||
def run(self): | ||
""" | ||
runs the job | ||
""" | ||
cmd = self.lobster_cmd | ||
|
||
logger.info("Running {}".format(" ".join(cmd))) | ||
|
||
with zopen(self.output_file, 'w') as f_std, \ | ||
zopen(self.stderr_file, "w", buffering=1) as f_err: | ||
# use line buffering for stderr | ||
p = subprocess.Popen(cmd, stdout=f_std, stderr=f_err) | ||
|
||
return p | ||
|
||
def postprocess(self): | ||
""" | ||
will gzip relevant files (won't gzip custodian.json and other output files from the cluster) | ||
""" | ||
if self.gzipped: | ||
for file in LOBSTEROUTPUT_FILES: | ||
if os.path.exists(file): | ||
compress_file(file, compression="gz") | ||
for file in LOBSTERINPUT_FILES: | ||
if os.path.exists(file): | ||
compress_file(file, compression="gz") | ||
if self.backup: | ||
if os.path.exists("lobsterin.orig"): | ||
compress_file("lobsterin.orig", compression="gz") | ||
for file in self.add_files_to_gzip: | ||
compress_file(file, compression="gz") |
Empty file.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import os | ||
import unittest | ||
|
||
from custodian.lobster.handlers import ChargeSpillingValidator, EnoughBandsValidator, LobsterFilesValidator | ||
|
||
# get location of module | ||
TEST_DIR = os.path.dirname(os.path.abspath(__file__)) | ||
test_files_lobster = os.path.join(TEST_DIR, '../../../test_files/lobster/lobsterouts') | ||
|
||
|
||
class TestChargeSpillingValidator(unittest.TestCase): | ||
|
||
def test_check_and_correct(self): | ||
v = ChargeSpillingValidator(output_filename=os.path.join(test_files_lobster, "lobsterout.normal")) | ||
self.assertFalse(v.check()) | ||
|
||
v2 = ChargeSpillingValidator(output_filename=os.path.join(test_files_lobster, "lobsterout.largespilling")) | ||
self.assertTrue(v2.check()) | ||
|
||
v2b = ChargeSpillingValidator(output_filename=os.path.join(test_files_lobster, "lobsterout.largespilling_2")) | ||
self.assertTrue(v2b.check()) | ||
|
||
v3 = ChargeSpillingValidator(output_filename=os.path.join(test_files_lobster, "nolobsterout", "lobsterout")) | ||
self.assertFalse(v3.check()) | ||
|
||
v4 = ChargeSpillingValidator(output_filename=os.path.join(test_files_lobster, "no_spin", "lobsterout")) | ||
self.assertFalse(v4.check()) | ||
|
||
def test_as_dict(self): | ||
v = ChargeSpillingValidator(output_filename=os.path.join(test_files_lobster, "lobsterout.normal")) | ||
d = v.as_dict() | ||
v2 = ChargeSpillingValidator.from_dict(d) | ||
self.assertIsInstance(v2, ChargeSpillingValidator) | ||
|
||
|
||
class TestLobsterFilesValidator(unittest.TestCase): | ||
|
||
def test_check_and_correct_1(self): | ||
os.chdir(test_files_lobster) | ||
v = LobsterFilesValidator() | ||
self.assertFalse(v.check()) | ||
|
||
def test_check_and_correct_2(self): | ||
os.chdir(os.path.join(test_files_lobster, "../lobsterins")) | ||
v2 = LobsterFilesValidator() | ||
self.assertTrue(v2.check()) | ||
|
||
def test_check_and_correct_3(self): | ||
os.chdir(os.path.join(test_files_lobster, "crash")) | ||
v3 = LobsterFilesValidator() | ||
self.assertTrue(v3.check()) | ||
|
||
def test_as_dict(self): | ||
os.chdir(test_files_lobster) | ||
v = LobsterFilesValidator() | ||
d = v.as_dict() | ||
v2 = LobsterFilesValidator.from_dict(d) | ||
self.assertIsInstance(v2, LobsterFilesValidator) | ||
|
||
|
||
class TestEnoughBandsValidator(unittest.TestCase): | ||
|
||
def test_check_and_correct(self): | ||
v = EnoughBandsValidator(output_filename=os.path.join(test_files_lobster, "lobsterout.normal")) | ||
self.assertFalse(v.check()) | ||
|
||
def test_check_and_correct2(self): | ||
v2 = EnoughBandsValidator(output_filename=os.path.join(test_files_lobster, "lobsterout.nocohp")) | ||
self.assertTrue(v2.check()) | ||
|
||
def test_check_and_correct3(self): | ||
v3 = EnoughBandsValidator(output_filename=os.path.join(test_files_lobster, "nolobsterout/lobsterout")) | ||
self.assertFalse(v3.check()) | ||
|
||
def test_as_dict(self): | ||
v = EnoughBandsValidator(output_filename=os.path.join(test_files_lobster, "lobsterout.normal")) | ||
d = v.as_dict() | ||
v2 = EnoughBandsValidator.from_dict(d) | ||
self.assertIsInstance(v2, EnoughBandsValidator) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import os | ||
import shutil | ||
import unittest | ||
|
||
from custodian.lobster.jobs import LobsterJob | ||
from monty.os import cd | ||
from monty.tempfile import ScratchDir | ||
|
||
MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) | ||
test_files_lobster2 = os.path.join(MODULE_DIR, '../../../test_files/lobster/lobsterins') | ||
test_files_lobster3 = os.path.join(MODULE_DIR, '../../../test_files/lobster/vasp_lobster_output') | ||
|
||
VASP_OUTPUT_FILES = ["OUTCAR", "vasprun.xml", "CHG", "CHGCAR", "CONTCAR", "INCAR", "KPOINTS", "POSCAR", "POTCAR", | ||
"DOSCAR", "EIGENVAL", "IBZKPT", "OSZICAR", "PCDAT", "PROCAR", "REPORT", "WAVECAR", "XDATCAR"] | ||
|
||
|
||
class LobsterJobTest(unittest.TestCase): | ||
""" | ||
similar to VaspJobTest | ||
ommit test of run | ||
""" | ||
|
||
def test_to_from_dict(self): | ||
v = LobsterJob(lobster_cmd="hello") | ||
v2 = LobsterJob.from_dict(v.as_dict()) | ||
self.assertEqual(type(v2), type(v)) | ||
self.assertEqual(v2.lobster_cmd, "hello") | ||
|
||
def test_setup(self): | ||
with cd(test_files_lobster2): | ||
with ScratchDir('.', copy_from_current_on_enter=True) as d: | ||
# check if backup is done correctly | ||
v = LobsterJob("hello", backup=True) | ||
v.setup() | ||
self.assertTrue(os.path.exists("lobsterin.orig")) | ||
# check if backup id done correctly | ||
with ScratchDir('.', copy_from_current_on_enter=True) as d: | ||
v = LobsterJob("hello", backup=False) | ||
v.setup() | ||
self.assertFalse(os.path.exists("lobsterin.orig")) | ||
|
||
def test_postprocess(self): | ||
# test gzipped and zipping of additional files | ||
with cd(os.path.join(test_files_lobster3)): | ||
with ScratchDir('.', copy_from_current_on_enter=True) as d: | ||
shutil.copy('lobsterin', 'lobsterin.orig') | ||
v = LobsterJob("hello", gzipped=True, add_files_to_gzip=VASP_OUTPUT_FILES) | ||
v.postprocess() | ||
self.assertTrue(os.path.exists("WAVECAR.gz")) | ||
self.assertTrue(os.path.exists("lobsterin.gz")) | ||
self.assertTrue(os.path.exists("lobsterout.gz")) | ||
self.assertTrue(os.path.exists("INCAR.gz")) | ||
self.assertTrue(os.path.exists("lobsterin.orig.gz")) | ||
|
||
with ScratchDir('.', copy_from_current_on_enter=True) as d: | ||
shutil.copy('lobsterin', 'lobsterin.orig') | ||
v = LobsterJob("hello", gzipped=False, add_files_to_gzip=VASP_OUTPUT_FILES) | ||
v.postprocess() | ||
self.assertTrue(os.path.exists("WAVECAR")) | ||
self.assertTrue(os.path.exists("lobsterin")) | ||
self.assertTrue(os.path.exists("lobsterout")) | ||
self.assertTrue(os.path.exists("INCAR")) | ||
self.assertTrue(os.path.exists("lobsterin.orig")) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
COHPstartEnergy -15.0 | ||
COHPendEnergy 5.0 | ||
basisSet pbeVaspFit2015 | ||
cohpGenerator from 0.1 to 6.0 orbitalwise | ||
gaussianSmearingWidth 0.05 | ||
saveProjectionToFile | ||
basisfunctions K 3p 3s 4s | ||
basisfunctions Sn 4d 5p 5s | ||
basisfunctions O 2p 2s |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
COHPstartEnergy -15.0 | ||
COHPendEnergy 10.0 | ||
basisSet pbeVaspFit2015 | ||
cohpGenerator from 0.1 to 6.0 orbitalwise | ||
gaussianSmearingWidth 0.05 | ||
saveProjectionToFile | ||
basisfunctions K 3p 3s 4s | ||
basisfunctions Sn 4d 5p 5s | ||
basisfunctions O 2p 2s |
Oops, something went wrong.