dragonfruit package

Subpackages

Submodules

Module contents

class dragonfruit.AseVisualizable

Bases: object

abstract get_visualizable()
class dragonfruit.ErrorHandler(*_args, **_kwargs)

Bases: mincepy.base_savable.BaseSavableObject

NAME = None
SKIP = None
classmethod accept_run(restart_run: typing.Optional[<class 'dragonfruit.vasp.base.VaspRun'>]) bool

Check if we want to accept the results from an error handler. Returns True if the returned value is OK, and otherwise False.

class dragonfruit.Fexcp(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_default_errors.SimpleAdjustment

ADJUSTMENT = {'algo': 'all'}
ERROR_STRING = 'ERROR FEXCP: supplied Exchange'
NAME = 'fexcp'
TYPE_ID = UUID('e8ff0772-2727-44a0-858a-efaad5990367')
class dragonfruit.Invgrp(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_default_errors.SimpleAdjustment

Handles a single error

ADJUSTMENT = {'symprec': 1e-08}
ERROR_STRING = 'inverse of rotation matrix was not found (increase SYMPREC)'
NAME = 'invgrp'
TYPE_ID = UUID('86ba6293-8f07-4207-a834-ca43315f227e')
class dragonfruit.MaxRestarts(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_errors.ErrorHandler

If no one else deals with the error then this handler attempts a simple restart changing no settings. If this happens more than max_count times in a task then it will order a termination.

ATTRS = ('count', 'max_count', 'raises')
NAME = 'max-restarts'
TYPE_ID = UUID('108aee5f-a67e-4648-91bf-a65f6f56fcca')
raises = True
class dragonfruit.NotHermitian(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_default_errors.SimpleAdjustment

Handles a single error

ADJUSTMENT = {'prec': 'accurate'}
ERROR_STRING = 'WARNING: Sub-Space-Matrix is not hermitian in DAV'
NAME = 'not-hermitian'
TYPE_ID = UUID('e7a5acb2-08b8-41cd-b5d1-b49c2caa25c7')
exception dragonfruit.PermanentFailure

Bases: dragonfruit.vasp.vasp_errors.BaseVaspError

An exception raise when an error handler detects that a situation has arisen that cannot be fixed

class dragonfruit.Posmap(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_default_errors.SimpleAdjustment

ADJUSTMENT = {'symprec': 1e-08}
ERROR_STRING = 'POSMAP internal error: symmetry equivalent atom not found'
NAME = 'posmap'
TYPE_ID = UUID('22bad6b1-6d9a-4790-bc05-7ff2cd201f35')
class dragonfruit.Pssyevx(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_default_errors.SimpleAdjustment

Handles a single error

ADJUSTMENT = {'algo': 'normal'}
ERROR_STRING = 'ERROR in subspace rotation PSSYEVX'
NAME = 'pssyevx'
TYPE_ID = UUID('cf961d8f-eac1-4215-9a0f-3ea8ff95e525')
class dragonfruit.PssyevxParallelization(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_default_errors.SimpleAdjustment

Alternate fix for PSSYEVX error, in case it’s a parallelization issue

ADJUSTMENT = {'ncore': 1, 'npar': None}
ERROR_STRING = 'ERROR in subspace rotation PSSYEVX'
NAME = 'pssyevx-parallelization'
TYPE_ID = UUID('b18d9736-a864-4e93-beb1-7bb272932ae9')
class dragonfruit.Pzstein(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_default_errors.SimpleAdjustment

ADJUSTMENT = {'algo': 'all'}
ERROR_STRING = 'PZSTEIN parameter number'
NAME = 'pzstein'
TYPE_ID = UUID('1de05f4e-7ff9-41c3-b4b0-68a9e09be7cc')
class dragonfruit.Rhosyg(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_default_errors.SimpleAdjustment

ADJUSTMENT = {'isym': 0, 'symprec': 0.0001}
ERROR_STRING = 'RHOSYG internal error: stars are not distinct'
NAME = 'rhosyg'
TYPE_ID = UUID('25b9f6d4-f213-43b8-abb4-d018a0ab86a8')
class dragonfruit.RunRestarter(*_args, **_kwargs)

Bases: mincepy.base_savable.BaseSavableObject

Check if vask task should execute a new run

ATTRS = ('_all_check_functions',)
TYPE_ID = UUID('700d9498-9d3c-4c7c-ab40-29a4f86665d8')
create_restart(vasp_task)
deregister(name)
register(handler: <class 'dragonfruit.vasp.vasp_errors.ErrorHandler'>, priority=0)

Register a virtual subclass of an ABC.

Returns the subclass, to allow usage as a class decorator.

register_many(handler_params: typing.Iterable[typing.Union[<class 'dragonfruit.vasp.vasp_errors.ErrorHandler'>, typing.Tuple[<class 'dragonfruit.vasp.vasp_errors.ErrorHandler'>, int]]])
class dragonfruit.SchedulerEnvironment(*_args, **_kwargs)

Bases: mincepy.base_savable.BaseSavableObject

ATTRS = ('_scheduler', '_stdout', '_stderr', '_extra')
TYPE_ID = UUID('6d0b5788-ac75-4cb3-9ea3-996fa15bf8ca')
property extra
property scheduler
property stderr
property stdout
class dragonfruit.Settings

Bases: object

property default_profile
get_profile(profile=None)
property profiles
read_settings()
write_settings()
class dragonfruit.Sgrcon(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_default_errors.SimpleAdjustment

ADJUSTMENT = {'ediff': 1e-07, 'isym': 0, 'symprec': 1e-08}
ERROR_STRING = 'internal error in subroutine SGRCON'
NAME = 'sgrcon'
TYPE_ID = UUID('c3ee2a32-6c51-4685-9f2b-6e979c4c4e8d')
class dragonfruit.SimpleAdjustment(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_errors.ErrorHandler

ADJUSTMENT = None
ERROR_STRING = None
NAME = None
TEMPORARY = False
class dragonfruit.SimpleVaspWorkflow(*_args, **_kwargs)

Bases: dragonfruit.vasp.base.VaspTask

TYPE_ID = UUID('d29adce9-8f39-4024-9c29-27e3c09e2d9f')
create_restart()
do_run(vasp_run: <class 'dragonfruit.vasp.base.VaspRun'>)
load_instance_state(saved_state, loader)

Take the given object and load the instance state into it

run()
class dragonfruit.SlurmTimedOut(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_errors.ErrorHandler

Handle cases where slurm killed the job because it exceeded the allowed time

NAME = 'slurm-timed-out'
TYPE_ID = UUID('db59fe0c-460d-4c46-aa39-ea4ea97c565c')
class dragonfruit.VaspProject(*_args, **_kwargs)

Bases: mincepy.base_savable.BaseSavableObject

ATTRS = ('name', 'tasks')
TYPE_ID = UUID('6ecedecf-b108-4c3f-93ce-8f52c4527fdc')
classmethod get_or_create(name, historian=None)
class dragonfruit.VaspRun(*_args, **_kwargs)

Bases: dragonfruit.mince.process.Process, dragonfruit.ase_utils.AseVisualizable

ATTRS = (AttrSpec(name='initial_atoms', as_ref=True), '_atom_steps', '_result_steps', '_settings', '_sort', '_resort', '_run_path', '_vasp_stdout', '_scheduler_env', 'description', '_files', 'keep_files', '_files', '_settings_overwrites', 'post_calculation_state')
TYPE_ID = UUID('139d0f75-7178-43fe-85e4-f609469122e1')
property atoms: ase.atoms.Atoms

Get the latest atoms

property atoms_history: Sequence[ase.atoms.Atoms]

Get a list of all the atoms from this run

property converged: bool
property crashed: bool
create_restart(new_path: pathlib.Path = None, atoms: ase.atoms.Atoms = None, copy_files=('WAVECAR',), init_kwargs: dict = None)

Create a restart from this VaspRun and give back a new VaspRun ready to be executed

Parameters
  • new_path – the new path to run the restart in

  • atoms – Optionally specify a specific atoms object to use. Default: Use the last atoms in the task.

  • copy_files – the files to copy over to the new path for the restart

  • init_kwargs – will be passed on to the constructor of the new VaspRun

fake_run()

Run VASP with the current settings, atoms in the running path

classmethod from_vasp_run(run_directory: pathlib.Path)
get_file_contents(filename, encoding='utf-8')

Get the content of a stored file

get_visualizable()
load_instance_state(saved_state, loader)

Take the given object and load the instance state into it

print_file_contents(filename, encoding='utf-8')

“Prints the contents from .get_file_contents

property resort: List
property results: Optional[dict]

Get the latest results, returns None if there aren’t any yet

property results_history: Sequence[dict]

Get a list of all the results dictionaries for this run

run()

Run VASP with the current settings, atoms in the running path. We don’t run if we already did the calculation

property run_path: pathlib.Path

The folder where this VASP calculation runs

property run_settings: Dict

The _actual_ settings this will run with if calling run(). This returns a dictionary that is a copy of self.settings.update(self.settings_overwrites).

save_instance_state(saver)

Save the instance state of an object, should return a saved instance

property scheduler_env: Optional[<class 'dragonfruit.environments.SchedulerEnvironment'>]
property settings: Dict

The vasp calculator settings

property settings_overwrites: Dict

A dictionary that can be used to overwrite particular keys for this run without propagating them to any restarts of this run

property sort: List
property stored_files: Dict[str, mincepy.files.File]

The dictionary of stored files. These are updated each time the run is saved based on the keep files attribute

update_and_set_results() None

Update the results, and set as completed.

update_results() bool

Returns true if it managed to update with new results. Will not update if we already have results present

property vasp_stdout
class dragonfruit.VaspTask(*_args, **_kwargs)

Bases: dragonfruit.mince.process.Process, dragonfruit.ase_utils.AseVisualizable

Represents a particular VASP task like geometry optimisation or singlepoint calculation. This could involve multiple restarts until it is completed which is why it has a list of individual vasp executions called `VaspRun`s.

ATTRS = (AttrSpec(name='_initial_atoms', as_ref=True), '_initial_settings', '_runs', '_restarter')
TYPE_ID = UUID('0420e8e1-1315-4d0c-b1b1-0f20f3686fa0')
append_run(vasp_run: <class 'dragonfruit.vasp.base.VaspRun'>)
property atoms

The current atoms

property atoms_history: List[ase.atoms.Atoms]

Get a list of all the atoms from this task (spanning all runs)

property converged: bool
property crashed: bool
execute_run(vasp_run: <class 'dragonfruit.vasp.base.VaspRun'>)
get_last_run() Optional[<class 'dragonfruit.vasp.base.VaspRun'>]
get_restarter() <class 'dragonfruit.vasp.vasp_errors.RunRestarter'>
get_visualizable()
property initial_atoms: ase.atoms.Atoms

Get the initial atoms object

property initial_settings: dict
new_run(**kwargs) <class 'dragonfruit.vasp.base.VaspRun'>

Gives you a new run for this task. If there are previous runs in this task the new run will be initialised with atoms and settings from the previous. Otherwise initial settings are used.

The new run will be appended to our list of runs. THe previous run (if present) will have its state set to done if not already done so which means it can no longer be modified.

property results: Optional[dict]

Get the latest results, returns None if there aren’t any yet

property results_history

Get a list of all the results dictionaries for this task (spanning all runs)

property runs: Sequence[<class 'dragonfruit.vasp.base.VaspRun'>]
save_instance_state(saver) dict

Save the instance state of an object, should return a saved instance

property settings

The current settings

class dragonfruit.WavecarUnusable(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_default_errors.SimpleAdjustment

If the wavecar is unusable from the previous run then temporarily disable it’s use for the next run only

ADJUSTMENT = {'istart': 0}
ERROR_STRING = 'ERROR: while reading WAVECAR, plane wave coefficients changed'
NAME = 'wavecar_sucks'
TEMPORARY = True
TYPE_ID = UUID('ba1a5e64-b140-4fe3-9920-a2b7a5f11d33')
class dragonfruit.Zbrent(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_default_errors.SimpleAdjustment

ADJUSTMENT = {'algo': 'all', 'ediff': 1e-06}
ERROR_STRING = 'ZBRENT: fatal error'
NAME = 'zbrent'
TYPE_ID = UUID('ed5edfad-3924-404e-8914-7ff9a970b5d9')
class dragonfruit.ZbrentAlternative(*_args, **_kwargs)

Bases: dragonfruit.vasp.vasp_errors.ErrorHandler

Zbrent error can cause VASP to have the last atoms object be the same as the first. Instead, we use the second-to-last atoms object.

We use a max count, to prevent any possible deadlocks, so we cannot get stuck in this error handler.

ATTRS = ('count', 'max_count')
ERROR_STRING = 'ZBRENT: fatal error'
NAME = 'zbrent_alternative'
TYPE_ID = UUID('5c79a739-a052-4455-86f9-f69fe207c7bd')
count = 0
max_count = 3
dragonfruit.clean_large_vasp_files(curpath, remove=('WAVECAR', 'CHGCAR', 'CHG', 'PROCAR'))
dragonfruit.get_default_handlers() Sequence[typing.Tuple[<class 'dragonfruit.vasp.vasp_errors.ErrorHandler'>, int]]
dragonfruit.get_file(vasppath: Union[str, pathlib.Path, mincepy.files.File])
dragonfruit.get_historian()
dragonfruit.get_ok_output_files(path='.')

Check if the VASP files are corrupt. Checks the OUTCAR and vasprun.xml

Returns the files which ASE was able to parse.

dragonfruit.get_scheduler_environment() Optional[<class 'dragonfruit.environments.SchedulerEnvironment'>]
dragonfruit.get_settings() dragonfruit.settings.Settings
dragonfruit.get_visualizable(obj)
dragonfruit.is_converged(atoms_history, settings) bool

Check that the current results are converged as defined in according to the settings

dragonfruit.is_outcar_corrupt(filename='OUTCAR') bool

Check we can read the last image from the OUTCAR. Note: We don’t care about middle images being corrupt.

dragonfruit.is_output_corrupt(path='.', outcar_file='OUTCAR', xml_file='vasprun.xml') bool

Check if both OUTCAR and XML files are corrupted

dragonfruit.is_relaxation(settings) bool
dragonfruit.is_stress_converged(atoms: ase.atoms.Atoms, ediffg: float, isif: int, tol: float = 0.01) bool

Read if stress tensor would be considered converged - this is a little more tricky, as VASP won’t explicitly tell us how they do it - requires a bit of re-calculations based on the vasp source code. A tolerance is used to accept a bit of numerical noise, due to conversions.

dragonfruit.is_xml_corrupt(filename='vasprun.xml') bool

Helper function for determining if the XML file is readable

dragonfruit.load(*to_load)
dragonfruit.parse_scf(outcar: Union[str, pathlib.Path, mincepy.files.File])

Get the SCF energy. Based on Alexander’s grad2 script.

dragonfruit.read_is_converged(outcar: Union[str, pathlib.Path, mincepy.files.File]) bool

Determine if VASP calculation converged based on messages ín the VASP OUTCAR

dragonfruit.read_is_crashed(outcar: Union[str, pathlib.Path, mincepy.files.File]) bool

Check if VASP printed end timing statements in OUTCAR. Returns True if job is considered crashed, otherwise False

dragonfruit.sanitize_meta(meta: dict) dict

Sanitize a meta dictionary, and remove protected keywords

dragonfruit.save(*objs)