Skip to content
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

Collected bugfixes #8

Draft
wants to merge 6 commits into
base: 1.X
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ The CASM Python packages

The `casm-python` Python packages provide a Python interface to the CASM libraries, implement wrappers to fitting methods and DFT software, and provide other tools for plotting and analysis.

This version of `casm-python` is compatible with [CASM](https://prisms-center.github.io/CASMcode_docs/) >=1.2.

A basic online reference is located [here](https://prisms-center.github.io/CASMcode_pydocs/latest/index.html)
This version of `casm-python` is compatible with [CASM](https://prisms-center.github.io/CASMcode_docs/) >=1.2.

A basic online reference is located [here](https://prisms-center.github.io/CASMcode_pydocs/casm/overview/latest)

For a summary of changes, see [CHANGELOG.md](https://github.com/prisms-center/CASMpython/blob/1.X/CHANGELOG.md).
15 changes: 8 additions & 7 deletions casm/casm/scripts/vasp_relax_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import json
import sys

import six

from casm.misc import compat, noindent
import casm.vaspwrapper

Expand All @@ -26,13 +28,12 @@ def main():
% configdir))
raise

compat.dump(json,
output,
'properties.calc.json',
'w',
cls=noindent.NoIndentEncoder,
indent=4,
sort_keys=True)
with open('properties.calc.json', 'w') as f:
f.write(six.u(json.dumps(
output,
cls=noindent.NoIndentEncoder,
indent=4,
sort_keys=True)))

print("Finish vasp.relax.report\n\n")

Expand Down
26 changes: 14 additions & 12 deletions casm/casm/vasp/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,32 +724,34 @@ def fix(err_jobdir, new_jobdir, settings):

def error_check(jobdir, stdoutfile, err_types):
""" Check vasp stdout for errors """
if err_types is None: return None
err = dict()
err_objs = {}
check_once = ['FreezeError']
for i_err in _RunError.__subclasses__():
err_objs[i_err.__name__] = i_err()
if err_types is None:
possible = [SubSpaceMatrixError()]
else:
# err_objs = {'IbzkptError' : IbzkptError(), 'SubSpaceMatrixError' : SubSpaceMatrixError(), 'NbandsError' : NbandsError()}
for s in err_types:
if s not in err_objs.keys():
raise VaspError('Invalid err_type: %s' % s)
possible = [err_objs[s] for s in err_types]
for i_err in _FreezeError.__subclasses__():
err_objs[i_err.__name__] = i_err()
# err_objs = {'IbzkptError' : IbzkptError(), 'SubSpaceMatrixError' : SubSpaceMatrixError(),
# 'NbandsError' : NbandsError(), 'FreezeError' : FreezeError()}
for s in err_types:
if s not in err_objs.keys():
raise VaspError('Invalid err_type: %s' % s)
possible = [err_objs[s] for s in err_types]

# Error to check line by line, only look for first of each type
sout = open(stdoutfile, 'r')
for line in sout:
for p in possible:
if not p.__class__.__name__ in err:
if not p.__class__.__name__ in err and not p.__class__.__name__ in check_once:
if p.error(line=line, jobdir=jobdir):
err[p.__class__.__name__] = p

# Error to check for once
possible = [i_err() for i_err in _FreezeError.__subclasses__()]
for p in possible:
if p.error(line=None, jobdir=jobdir):
err[p.__class__.__name__] = p
if not p.__class__.__name__ in err and p.__class__.__name__ in check_once:
if p.error(line=None, jobdir=jobdir):
err[p.__class__.__name__] = p

sout.close()
if len(err) == 0:
Expand Down
24 changes: 12 additions & 12 deletions casm/casm/vasp/relax.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,17 @@ def complete(self):
def converged(self):
"""Check if configuration is relaxed.

This is called when self.rundir[-1] is complete and not a constant volume job.
This is called when self.rundir[-1] is complete.

Convergence criteria is: at least 2 relaxation jobs are complete, and:
1) the last job completed with <= 3 ionic steps
or 2) the last two jobs had final E0 differ by less than
self.settings["nrg_convergence"]
OR
at least 1 relaxation job is complete, and
the last job completed with 1 ionic step, and
the volume is fixed (ISIF = 0, 1, 2)
(ISIF must be set explicitly in the INCAR)
"""
if len(self.rundir) >= 2:
if io.ionic_steps(self.rundir[-1]) <= 3:
Expand All @@ -213,13 +218,18 @@ def converged(self):
if abs(o1.E[-1] -
o2.E[-1]) < self.settings["nrg_convergence"]:
return True
# note: this will not work if ISIF was not explicitly set in the INCAR
elif len(self.rundir) == 1:
if io.ionic_steps(self.rundir[-1]) == 1:
if io.get_incar_tag("ISIF", self.rundir[-1]) in [0, 1, 2]:
return True

return False

def not_converging(self):
"""Check if configuration is not converging.

This is called when self.rundir[-1] is complete and not a constant volume job and self.converged() == False.
This is called when self.rundir[-1] is complete and self.converged() == False.

Not converging criteria: >= 10 runs without completion
"""
Expand Down Expand Up @@ -416,16 +426,6 @@ def status(self):
# io.get_incar_tag("ISMEAR", self.rundir[-1]) == -5:
return ("complete", None)

# elif constant volume run (but not the final one)
if io.get_incar_tag("ISIF", self.rundir[-1]) in [0, 1, 2]:
if io.get_incar_tag("NSW", self.rundir[-1]) == len(
io.Oszicar(os.path.join(self.rundir[-1],
"OSZICAR")).E):
return ("incomplete", "relax"
) # static run hit NSW limit and so isn't "done"
else:
return ("incomplete", "constant")

# elif convergence criteria met
if self.converged():
return ("incomplete", "constant")
Expand Down
7 changes: 4 additions & 3 deletions casm/casm/vaspwrapper/relax.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,9 @@ def finalize(self, config_data):
super(Relax, self).finalize(config_data)
sys.stdout.flush()

def properties(self, calcdir, super_poscarfile=None, speciesfile=None):
@staticmethod
def properties(calcdir, super_poscarfile=None, speciesfile=None):
"""Make properties output as a list of dict of each image properties"""
output = super(Relax, self).properties(calcdir, super_poscarfile,
speciesfile)
output = super(Relax, Relax).properties(
calcdir, super_poscarfile, speciesfile)
return output
56 changes: 30 additions & 26 deletions casm/casm/vaspwrapper/vasp_calculator_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,9 @@ def submit(self):
message=settings["message"],
email=settings["email"],
priority=settings["priority"],
constraint=settings["constraint"],
exclude=settings["exclude"],
gpus=settings["gpus"],
command=cmd,
auto=self.auto)

Expand Down Expand Up @@ -671,7 +674,6 @@ def finalize(self, config_data):
@staticmethod
def properties(vaspdir, initial_structurefile=None, speciesfile=None):
""" return a dict of output form a vasp directory"""
structure_info = structure.StructureInfo(initial_structurefile)
output = dict()
# load the OSZICAR and OUTCAR
zcar = vasp.io.Oszicar(os.path.join(vaspdir, "OSZICAR"))
Expand All @@ -697,7 +699,7 @@ def properties(vaspdir, initial_structurefile=None, speciesfile=None):
# unsorted_dict[sorted_index] == orig_index
# For example:
# 'unsort_dict[0]' returns the index into the unsorted POSCAR of the first atom in the sorted POSCAR
output["atom_type"] = initial_structure.atom_type
output["atom_type"] = [i.occ_alias for i in initial_structure.basis]
#output["atoms_per_type"] = initial_structure.num_atoms
output["coordinate_mode"] = contcar.coordinate_mode

Expand All @@ -723,32 +725,34 @@ def properties(vaspdir, initial_structurefile=None, speciesfile=None):
output["global_properties"]["energy"] = {}
output["global_properties"]["energy"]["value"] = zcar.E[-1]

if structure_info.atom_properties is not None:
if "Cmagspin" in list(structure_info.atom_properties.keys()):
output["global_properties"]["Cmagspin"] = {}
cmagspin_specific_output = attribute_classes.CmagspinAttr(
structure_info).vasp_output_dictionary(ocar)
output["atom_properties"].update(cmagspin_specific_output)
#TODO: Need a better way to write global magmom. I don't like what I did here
output["global_properties"]["Cmagspin"]["value"] = zcar.mag[-1]

#TODO: When you don't have Cmagspin but have magnetic calculations. This part can be removed if you runall magnetic calculations as Cmagspin calculations.
#TODO: Need a better way of doing this. Some code duplication here.
else:
if ocar.ispin == 2:
if initial_structurefile is not None:
structure_info = structure.StructureInfo(initial_structurefile)
if structure_info.atom_properties is not None:
if "Cmagspin" in list(structure_info.atom_properties.keys()):
output["global_properties"]["Cmagspin"] = {}
cmagspin_specific_output = attribute_classes.CmagspinAttr(
structure_info).vasp_output_dictionary(ocar)
output["atom_properties"].update(cmagspin_specific_output)
#TODO: Need a better way to write global magmom. I don't like what I did here
output["global_properties"]["Cmagspin"]["value"] = zcar.mag[-1]
if ocar.lorbit in [1, 2, 11, 12]:
output["atom_properties"]["Cmagspin"] = {}
output["atom_properties"]["Cmagspin"]["value"] = [
None for i in range(len(contcar.basis))
]

for i, v in enumerate(contcar.basis):
output["atom_properties"]["Cmagspin"]["value"][
unsort_dict[i]] = [
noindent.NoIndent(ocar.mag[i])
]

#TODO: When you don't have Cmagspin but have magnetic calculations. This part can be removed if you runall magnetic calculations as Cmagspin calculations.
#TODO: Need a better way of doing this. Some code duplication here.
else:
if ocar.ispin == 2:
output["global_properties"]["Cmagspin"] = {}
output["global_properties"]["Cmagspin"]["value"] = zcar.mag[-1]
if ocar.lorbit in [1, 2, 11, 12]:
output["atom_properties"]["Cmagspin"] = {}
output["atom_properties"]["Cmagspin"]["value"] = [
None for i in range(len(contcar.basis))
]

for i, v in enumerate(contcar.basis):
output["atom_properties"]["Cmagspin"]["value"][
unsort_dict[i]] = [
noindent.NoIndent(ocar.mag[i])
]

#TODO: Code duplication here. If you have a magnetic calculation without dofs, you still need to write magmom values. This can be removed if you run all the magnetic calculations as Cmagspin dof calculations.
#TODO: If you still want to have this particular functionality, wrap it up in a helper function to avoid code duplication.
Expand Down
9 changes: 8 additions & 1 deletion casm/casm/vaspwrapper/vaspwrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ def read_settings(filename):
"pmem": string for requested memory (default None)
"priority": requested job priority (default "0")
"constraint": constraint. ex: ``"haswell"`` (default None)
"exclude": nodes to exclude (slurm only). ex: ``"node01,node02,node03"`` (default None)
"gpus": how many gpus to request (slurm only). ex: 4 (default None)
"message": when to send messages about jobs (ex. "abe", default "a")
"email": where to send messages (ex. "[email protected]", default None)
"qos": quality of service, 'qos' option (ex. "fluxoe")
Expand Down Expand Up @@ -78,7 +80,7 @@ def read_settings(filename):
select_one = [["nodes", "atom_per_proc", "nodes_per_image"]]

optional = [
"account", "pmem", "priority", "constraint", "message", "email", "qos",
"account", "pmem", "priority", "constraint", "exclude", "gpus", "message", "email", "qos",
"npar", "ncore", "kpar", "ncpus", "vasp_cmd", "run_limit",
"nrg_convergence", "encut", "kpoints", "extra_input_files", "move",
"copy", "remove", "compress", "backup", "initial", "final",
Expand All @@ -88,6 +90,11 @@ def read_settings(filename):
"endstate_calctype", "initial_deformation"
]

if "gpus" in settings:
# user must supply their own run command
if not "vasp_cmd" in settings or len(settings["vasp_cmd"]) == 0:
raise VaspWrapperError("gpu setting requires you to set vasp_cmd manually")

for key in required:
if not key in settings:
raise VaspWrapperError(key + "' missing from: '" + filename + "'")
Expand Down
2 changes: 1 addition & 1 deletion casm/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ pandas
prisms-jobs
scikit-learn
scipy
sh
sh==1.14.2
six
2 changes: 1 addition & 1 deletion casm/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def script_str(file):
entry_points={'console_scripts': console_scripts},
install_requires=[
'deap', 'mock', 'pandas', 'prisms-jobs', 'scikit-learn',
'scipy', 'sh'
'scipy', 'sh==1.14.2'
],
classifiers=[
'Development Status :: 5 - Production/Stable',
Expand Down