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

Develop #74

Merged
merged 9 commits into from
Jun 5, 2024
Merged
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
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Change Log
==========

v3.3.4
----------
- Make oxidation state guessing more efficient.
- Update Quantum Espresso and FHI-aims IO functions to work with new (and old) ASE release.
- Minor updates to ensure compatibility with recent ``pymatgen`` release.
- Allow unrecognised defect names when plotting.

v3.3.3
----------
- Add ``verbose`` option to more parsing/plotting functions for better control of output detail.
Expand Down
15 changes: 15 additions & 0 deletions docs/Tips.rst
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,21 @@ see `docs here <https://shakenbreak.readthedocs.io/en/latest/shakenbreak.energy_
Troubleshooting
-------------------

For most error cases, ``ShakeNBreak`` has been designed to try and give informative error messages about
why the functions are failing.
In the majority of cases, if you encounter an error using ``ShakeNBreak`` which does not have a clear error
message about the origin of the problem, it is likely to be an issue with your version of ``pymatgen``
(and/or ``ShakeNBreak``/``doped``), and may be fixed by doing:

.. code:: bash

pip install pymatgen pymatgen-analysis-defects monty --upgrade
pip install ShakeNBreak doped --upgrade

If this does not solve your issue, please check the specific cases noted below. If your issue still isn't
solved, then please contact the developers through the ``GitHub``
`Issues <https://github.com/SMTG-Bham/ShakeNBreak/issues>`_ page, or by email.

- A current known issue with ``numpy``/``pymatgen`` is that it might give an error similar to this:

.. code:: python
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
author = 'Irea Mosquera-Lois, Seán R. Kavanagh'

# The full version, including alpha/beta/rc tags
release = '3.3.3'
release = '3.3.4'


# -- General configuration ---------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def package_files(directory):

setup(
name="shakenbreak",
version="3.3.3",
version="3.3.4",
description="Package to generate and analyse distorted defect structures, in order to "
"identify ground-state and metastable defect configurations.",
long_description=long_description,
Expand Down
38 changes: 15 additions & 23 deletions shakenbreak/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from subprocess import call

import click
from doped.core import _guess_and_set_oxi_states_with_timeout, _rough_oxi_state_cost_from_comp
from doped.core import guess_and_set_oxi_states_with_timeout
from doped.generation import get_defect_name_from_entry
from doped.utils.parsing import get_outcar
from doped.utils.plotting import format_defect_name
Expand Down Expand Up @@ -240,14 +240,14 @@ def generate(
if key not in valid_args:
user_settings.pop(key)

defect_struc = Structure.from_file(defect)
bulk_struc = Structure.from_file(bulk)
defect_struct = Structure.from_file(defect)
bulk_struct = Structure.from_file(bulk)

# Note that here the Defect.defect_structure is the defect `supercell`
# structure, not the defect `primitive` structure.
defect_object = input.identify_defect(
defect_structure=defect_struc,
bulk_structure=bulk_struc,
defect_structure=defect_struct,
bulk_structure=bulk_struct,
defect_index=defect_index,
defect_coords=defect_coords,
)
Expand Down Expand Up @@ -464,22 +464,14 @@ def generate_all(
Generate the trial distortions and input files for structure-searching
for all defects in a given directory.
"""
bulk_struc = Structure.from_file(bulk)
bulk_struct = Structure.from_file(bulk)
# try parsing the bulk oxidation states first, for later assigning defect "oxi_state"s (i.e.
# fully ionised charge states):
# First check if the cost of guessing oxidation states is too high:
if _rough_oxi_state_cost_from_comp(bulk_struc.composition) > 1e6:
# If the cost is too high, avoid setting oxidation states as it will take too long
_bulk_oxi_states = False # will take very long to guess oxi_state
else:
# Otherwise, proceed with setting oxidation states using a separate process to allow timeouts
from multiprocessing import Queue # only import when necessary

queue = Queue()
_bulk_oxi_states = _guess_and_set_oxi_states_with_timeout(bulk_struc, queue=queue)
if _bulk_oxi_states: # Retrieve the oxidation states if successfully guessed and set
bulk_struc = queue.get() # oxi-state decorated structure
_bulk_oxi_states = {el.symbol: el.oxi_state for el in bulk_struc.composition.elements}
if bulk_struct_w_oxi := guess_and_set_oxi_states_with_timeout(
bulk_struct, break_early_if_expensive=True
):
bulk_struct = bulk_struct_w_oxi
_bulk_oxi_states = {el.symbol: el.oxi_state for el in bulk_struct.composition.elements}

defects_dirs = os.listdir(defects)
if config is not None:
Expand Down Expand Up @@ -595,7 +587,7 @@ def parse_defect_position(defect_name, defect_settings):
for defect in defects_dirs: # file or directory
if os.path.isfile(f"{defects}/{defect}"):
try: # try to parse structure from it
defect_struc = Structure.from_file(f"{defects}/{defect}")
defect_struct = Structure.from_file(f"{defects}/{defect}")
defect_name = parse_defect_name(defect, defect_settings) # None if not recognised

except Exception:
Expand Down Expand Up @@ -624,7 +616,7 @@ def parse_defect_position(defect_name, defect_settings):
)
continue
if defect_file:
defect_struc = Structure.from_file(os.path.join(defects, defect, defect_file))
defect_struct = Structure.from_file(os.path.join(defects, defect, defect_file))
defect_name = parse_defect_name(defect, defect_settings)
else:
warnings.warn(f"Could not parse {defects}/{defect} as a defect, skipping.")
Expand All @@ -633,8 +625,8 @@ def parse_defect_position(defect_name, defect_settings):
# Check if indices are provided in config file
defect_index, defect_coords = parse_defect_position(defect_name, defect_settings)
defect_object = input.identify_defect(
defect_structure=defect_struc,
bulk_structure=bulk_struc,
defect_structure=defect_struct,
bulk_structure=bulk_struct,
defect_index=defect_index,
defect_coords=defect_coords,
oxi_state=(
Expand Down
5 changes: 4 additions & 1 deletion shakenbreak/distortions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
from hiphive.structure_generation.rattle import _probability_mc_rattle, generate_mc_rattled_structures
from pymatgen.analysis.local_env import CrystalNN, MinimumDistanceNN
from pymatgen.core.structure import Structure
from pymatgen.io.ase import AseAtomsAdaptor
from pymatgen.io.ase import AseAtomsAdaptor # could be removed to use the Structure.to/from_ase_atoms()

# methods added in pymatgen 2024.5.31, but then not backwards compatible. Will refactor to this if/when
# pymatgen>=2024.5.31 is a necessary requirement.


def _warning_on_one_line(message, category, filename, lineno, file=None, line=None):
Expand Down
11 changes: 10 additions & 1 deletion shakenbreak/energy_lowering_distortions.py
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@ def write_retest_inputs(
code (:obj:`str`):
Code used for the geometry relaxations. The supported codes
include "vasp", "cp2k", "espresso", "castep" and "fhi-aims"
(case insensitive).
(case-insensitive).
(Default: "vasp")
input_filename (:obj:`str`):
Name of the code input file if different from `ShakeNBreak`
Expand Down Expand Up @@ -1000,6 +1000,9 @@ def _copy_espresso_files(
filename=f"{distorted_dir}/{input_filename}",
images=atoms,
format="espresso-in",
pseudopotentials={ # doesn't matter, is rewritten below to use same as before
atom: "N/A" for atom in set(atoms.get_chemical_symbols())
},
)
with open(f"{distorted_dir}/{input_filename}") as f:
new_struct = f.read()
Expand Down Expand Up @@ -1027,6 +1030,9 @@ def _copy_espresso_files(
filename=f"{distorted_dir}/{input_filename}",
images=atoms,
format="espresso-in",
pseudopotentials={ # doesn't matter, is rewritten below to use same as before
atom: "N/A" for atom in set(atoms.get_chemical_symbols())
},
)
with open(f"{distorted_dir}/{input_filename}") as f:
new_struct = f.read()
Expand All @@ -1048,6 +1054,9 @@ def _copy_espresso_files(
filename=f"{distorted_dir}/{input_filename}",
images=atoms,
format="espresso-in",
pseudopotentials={
atom: "Pseudopotentials not specified" for atom in set(atoms.get_chemical_symbols())
},
)


Expand Down
Loading
Loading