-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added draft of vasp_util.py for VASP trajectories and OTF #82
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
4600693
added draft of vasp_util.py for VASP trajectories and OTF; need to wr…
kylebystrom 14f81b2
fix syntax error
kylebystrom f957186
Merge branch 'master' into kyle/pymatgen_utils
kylebystrom 49cd649
Fixed import bug; missing Union import
stevetorr a863416
JSON function now uses Numpy-friendly encoder
stevetorr 7345059
Undid breakage of struc import
stevetorr 58da52f
start unit testing vasp interface and move general io utils to flare_…
kylebystrom 91eb181
merge with Steve's fixes and add test files
kylebystrom f02a45e
fixed misnamed function
kylebystrom 0e504a8
fix various unit test bugs
kylebystrom 8277c76
add unit tests for trajector load and flare io, document new features
kylebystrom 8324cc8
Merge branch 'master' into kyle/pymatgen_utils
kylebystrom 39b6352
Tweak syntax for f.close() concision, add typehints
stevetorr 7cceedc
Clean up tst traj.json
stevetorr 4a8452b
additional vasp_util unit tests to complete coverage
kylebystrom b2061e4
update dummy_vasp.py to test failures and update test_from_pmg_struct…
kylebystrom 245ccc7
Merge branch 'kyle/pymatgen_utils' of https://github.com/mir-group/fl…
kylebystrom b9a09e0
tabs to spaces
kylebystrom d03b748
Merge branch 'master' of https://github.com/mir-group/flare into kyle…
kylebystrom efe74e2
last piece of coverage, testing that check_vasprun always works
kylebystrom File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,128 @@ | ||
from pymatgen.io.vasp.inputs import Poscar | ||
from pymatgen.io.vasp.outputs import Vasprun | ||
from subprocess import call | ||
import numpy as np | ||
from flare.struc import Structure | ||
from typing import List, Union | ||
from json import dump, load | ||
from flare.util import NumpyEncoder | ||
import os, shutil | ||
|
||
def check_vasprun(vasprun: Union[str, Vasprun]) -> Vasprun: | ||
""" | ||
Helper utility to take a vasprun file name or Vasprun object | ||
and return a vasprun object. | ||
:param vasprun: vasprun filename or object | ||
""" | ||
if type(vasprun) == str: | ||
return Vasprun(vasprun) | ||
elif type(vasprun) == Vasprun: | ||
return vasprun | ||
else: | ||
raise ValueError('Vasprun argument is not a string or Vasprun instance!') | ||
|
||
def run_dft(calc_dir: str, dft_loc: str, | ||
structure: Structure=None, en: bool=False, vasp_cmd="{}"): | ||
""" | ||
Run a VASP calculation. | ||
:param calc_dir: Name of directory to perform calculation in | ||
:param dft_loc: Name of VASP command (i.e. executable location) | ||
:param structure: flare structure object | ||
:param en: whether to return the final energy along with the forces | ||
:param vasp_cmd: Command to run VASP (leave a formatter "{}" to insert dft_loc); | ||
this can be used to specify mpirun, srun, etc. | ||
|
||
Returns: | ||
forces on each atom (and energy if en=True) | ||
""" | ||
|
||
currdir = os.getcwd() | ||
if structure: | ||
edit_dft_input_positions("POSCAR", structure) | ||
try: | ||
if currdir != calc_dir: | ||
os.chdir(calc_dir) | ||
call(vasp_cmd.format(dft_loc).split()) | ||
|
||
if en: | ||
parse_func = parse_dft_forces_and_energy | ||
else: | ||
parse_func = parse_dft_forces | ||
|
||
try: | ||
forces = parse_func("vasprun.xml") | ||
except FileNotFoundError: | ||
raise FileNotFoundError("""Could not load vasprun.xml. The calculation may not have finished. | ||
Current directory is %s""" % os.getcwd()) | ||
|
||
os.chdir(currdir) | ||
return forces | ||
|
||
except Exception as e: | ||
os.chdir(currdir) | ||
raise e | ||
|
||
|
||
def dft_input_to_structure(poscar: str): | ||
""" | ||
Parse the DFT input in a directory. | ||
:param vasp_input: directory of vasp input | ||
""" | ||
return Structure.from_pmg_structure(Poscar.from_file(poscar).structure) | ||
|
||
|
||
def edit_dft_input_positions(poscar: str, structure: Structure): | ||
""" | ||
Writes a VASP POSCAR file from structure with the name poscar . | ||
WARNING: Destructively replaces the file with the name specified by poscar | ||
:param poscar: Name of file | ||
:param structure: structure to write to file | ||
""" | ||
if os.path.isfile(poscar): | ||
shutil.copyfile(poscar, poscar+'.bak') | ||
f = open(poscar, 'w') | ||
f.write(Poscar(structure.to_pmg_structure()).get_string(significant_figures=15)) | ||
f.close() | ||
return poscar | ||
|
||
|
||
def parse_dft_forces(vasprun: Union[str, Vasprun]): | ||
""" | ||
Parses the DFT forces from a VASP vasprun.xml file | ||
:param vasprun: pymatgen Vasprun object or vasprun filename | ||
""" | ||
vasprun = check_vasprun(vasprun) | ||
istep = vasprun.ionic_steps[-1] | ||
return np.array(istep['forces']) | ||
|
||
|
||
def parse_dft_forces_and_energy(vasprun: Union[str, Vasprun]): | ||
""" | ||
Parses the DFT forces and energy from a VASP vasprun.xml file | ||
:param vasprun: pymatgen Vasprun object or vasprun filename | ||
""" | ||
vasprun = check_vasprun(vasprun) | ||
istep = vasprun.ionic_steps[-1] | ||
return np.array(istep['forces']), istep["electronic_steps"][-1]["e_0_energy"] | ||
|
||
|
||
def md_trajectory_from_vasprun(vasprun: Union[str, Vasprun], ionic_step_skips=1): | ||
""" | ||
Returns a list of flare Structure objects decorated with forces, stress, | ||
and total energy from a MD trajectory performed in VASP. | ||
:param vasprun: pymatgen Vasprun object or vasprun filename | ||
:param ionic_step_skips: if True, only samples the configuration every | ||
ionic_skip_steps steps. | ||
""" | ||
vasprun = check_vasprun(vasprun) | ||
|
||
struc_lst = [] | ||
for step in vasprun.ionic_steps[::ionic_step_skips]: | ||
structure = Structure.from_pmg_structure(step["structure"]) | ||
structure.energy = step["electronic_steps"][-1]["e_0_energy"] | ||
#TODO should choose e_wo_entrp or e_fr_energy? | ||
structure.forces = np.array(step["forces"]) | ||
structure.stress = np.array(step["stress"]) | ||
struc_lst.append(structure) | ||
|
||
return struc_lst |
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,23 @@ | ||
from flare.struc import Structure | ||
from typing import List | ||
from json import dump, load | ||
from flare.util import NumpyEncoder | ||
|
||
def md_trajectory_to_file(filename: str, structures: List[Structure]): | ||
""" | ||
Take a list of structures and write them to a json file. | ||
:param filename: | ||
:param structures: | ||
""" | ||
with open(filename, 'w') as f: | ||
dump([s.as_dict() for s in structures], f, cls=NumpyEncoder) | ||
|
||
def md_trajectory_from_file(filename: str): | ||
""" | ||
Read a list of structures from a json file, formatted as in md_trajectory_to_file. | ||
:param filename: | ||
""" | ||
with open(filename, 'r') as f: | ||
structure_list = load(f) | ||
structures = [Structure.from_dict(dictionary) for dictionary in structure_list] | ||
return structures |
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
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 @@ | ||
import os, shutil, sys | ||
|
||
if "test_fail" in sys.argv: | ||
exit(0) | ||
|
||
curr_path = os.path.dirname(os.path.abspath(__file__)) | ||
vasprun_name = os.path.join(curr_path, 'test_vasprun.xml') | ||
poscar_name = os.path.join(curr_path, 'test_POSCAR') | ||
calc_dir = os.path.join(curr_path, '..') | ||
|
||
shutil.copyfile(poscar_name, os.path.join(calc_dir, "POSCAR")) | ||
shutil.copyfile(vasprun_name, os.path.join(calc_dir, "vasprun.xml")) |
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,14 @@ | ||
H4 C1 O1 | ||
1.0 | ||
10.638000 0.000000 0.000000 | ||
0.000000 10.029603 0.000000 | ||
0.000000 0.000000 20.000000 | ||
C O H | ||
1 1 4 | ||
direct | ||
0.066840 0.466900 0.684808 C | ||
0.997467 0.388247 0.636881 O | ||
0.058718 0.354817 0.604874 H | ||
0.059432 0.573624 0.674176 H | ||
0.168523 0.443819 0.681503 H | ||
0.024984 0.447208 0.735591 H |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you ensure that this returns the cartesian coordinates every time since that's the FLARE convention?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is addressed by the unit test for the from_pmg_structure function, but I also will address it in the
test_structure_parsing
function when I assert the correct coordinate parsingThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually,
test_struc.test_from_pmg_structure
doesn't guarantee the cartesian coordinates are read because it sets the unit cell to np.eye(3). So I copy-pasted the test and changed the lattice parameters so that it will fail iffrom_pmg_structure
returns fractional coordinates.