diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 1f20498..f0a2973 100755 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -37,7 +37,7 @@ jobs: - name: ruff run: | ruff --version - ruff --fix shakenbreak + ruff check --fix shakenbreak - name: check docstrings run: | @@ -53,4 +53,4 @@ jobs: - name: flake8 run: | flake8 --version - flake8 --max-line-length 107 --color always --ignore=E121,E123,E126,E203,E226,E24,E704,W503,W504,F401,E203 shakenbreak \ No newline at end of file + flake8 --max-line-length 107 --color always --ignore=E121,E123,E126,E203,E226,E24,E704,W503,W504,F401,E203 shakenbreak diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0f5d629..90eeb66 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,11 @@ Change Log ========== +v3.3.6 +---------- +- Add `py.typed` to properly detect type hints by @Andrew-S-Rosen +- `snb-run` updates to improve efficiency + v3.3.5 ---------- - Enforce ``doped>=2.4.4`` requirement. diff --git a/README.md b/README.md index 079ec42..db69515 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ pip install --upgrade pymatgen shakenbreak `ShakeNBreak` can take `pymatgen` `Defect` objects as input (to then generate the trial distorted structures), **_but also_** can take in `pymatgen` `Structure` objects, `doped` defects or structure files (e.g. `POSCAR`s for `VASP`) as inputs. As such, it should be compatible with any defect code -(such as [`doped`](https://doped.readthedocs.io/en/latest/index.html), [`pydefect`](https://github.com/kumagai-group/pydefect), +(such as [`doped`](https://doped.readthedocs.io), [`pydefect`](https://github.com/kumagai-group/pydefect), [`PyCDT`](https://github.com/mbkumar/pycdt), [`PyLada`](https://github.com/pylada/pylada-defects), [`DASP`](http://hzwtech.com/files/software/DASP/htmlEnglish/index.html), [`Spinney`](https://gitlab.com/Marrigoni/spinney/-/tree/master), [`DefAP`](https://github.com/DefAP/defap), [`PyDEF`](https://github.com/PyDEF2/PyDEF-2.0)...) that generates these files. @@ -128,10 +128,15 @@ Automatic testing is run on the master and develop branches using Github Actions ## Studies using `ShakeNBreak` +- Z. Yuan & G. Hautier **_First-principles study of defects and doping limits in CaO_** [_Applied Physics Letters_](https://doi.org/10.1063/5.0211707) 2024 - B. E. Murdock et al. **_Li-Site Defects Induce Formation of Li-Rich Impurity Phases: Implications for Charge Distribution and Performance of LiNi0.5-xMxMn1.5O4 Cathodes (M = Fe and Mg; x = 0.05–0.2)_** [_Advanced Materials_](https://doi.org/10.1002/adma.202400343) 2024 -- A. G. Squires et al. **_Oxygen dimerization as a defect-driven process in bulk LiNiO22_** [_ChemRxiv_](https://doi.org/10.26434/chemrxiv-2024-lcmkj) 2024 +- Y. Fu & H. Lohan et al. **_Factors Enabling Delocalized Charge-Carriers in Pnictogen-Based +Solar Absorbers: In-depth Investigation into CuSbSe2_** [_arXiv_](https://doi.org/10.48550/arXiv.2401.02257) 2024 +- S. Hachmioune et al. **_Exploring the Thermoelectric Potential of MgB4: Electronic Band Structure, Transport Properties, and Defect Chemistry_** [_Chemistry of Materials_](https://doi.org/10.1021/acs.chemmater.4c00584) 2024 +- J. Hu et al. **_Enabling ionic transport in Li3AlP2 the roles of defects and disorder_** [_ChemRxiv_](https://doi.org/10.26434/chemrxiv-2024-3s0kh) 2024 +- A. G. Squires et al. **_Oxygen dimerization as a defect-driven process in bulk LiNiO22_** [_ACS Energy Letters_](https://pubs.acs.org/doi/10.1021/acsenergylett.4c01307) 2024 - X. Wang et al. **_Upper efficiency limit of Sb2Se3 solar cells_** [_Joule_](https://doi.org/10.1016/j.joule.2024.05.004) 2024 -- I. Mosquera-Lois et al. **_Machine-learning structural reconstructions for accelerated point defect calculations_** [_arXiv_](https://doi.org/10.48550/arXiv.2401.12127) 2024 +- I. Mosquera-Lois et al. **_Machine-learning structural reconstructions for accelerated point defect calculations_** [_npj Computational Materials_](https://doi.org/10.1038/s41524-024-01303-9) 2024 - S. R. Kavanagh et al. **_doped: Python toolkit for robust and repeatable charged defect supercell calculations_** [_Journal of Open Source Software_](https://doi.org/10.21105/joss.06433) 2024 - K. Li et al. **_Computational Prediction of an Antimony-based n-type Transparent Conducting Oxide: F-doped Sb2O5_** [_Chemistry of Materials_](https://doi.org/10.1021/acs.chemmater.3c03257) 2024 - X. Wang et al. **_Four-electron negative-U vacancy defects in antimony selenide_** [_Physical Review B_](https://journals.aps.org/prb/abstract/10.1103/PhysRevB.108.134102) 2023 diff --git a/docs/Analysis.rst b/docs/Analysis.rst index 7af8d52..3bcdd04 100644 --- a/docs/Analysis.rst +++ b/docs/Analysis.rst @@ -248,11 +248,11 @@ Further Defect Analysis ------------------------- Once the ground state (and metastable) defect structures have been identified, we will want to compute their formation energies using our final fully-converged calculation parameters (i.e. plane-wave cutoff -and k-point sampling). This can be done using `doped `_, +and k-point sampling). This can be done using `doped `_, manually (not recommended) or using the other defect codes listed on the `Code Compatibility `_ page. -As shown in the `doped `_ tutorials and docs, you may +As shown in the `doped `_ tutorials and docs, you may want to further analyse the behaviour and impact on material properties of your defects using advanced defect analysis codes such as `easyunfold `_ (to analyse the electronic structure of defects in your material), diff --git a/docs/Code_Compatibility.rst b/docs/Code_Compatibility.rst index 9f74fc5..18e9dd2 100644 --- a/docs/Code_Compatibility.rst +++ b/docs/Code_Compatibility.rst @@ -14,7 +14,7 @@ most recent version of :code:`pymatgen`. If you are receiving :code:`pymatgen`-r :code:`ShakeNBreak` can take :code:`pymatgen` :code:`DefectEntry` objects as input (to then generate the trial distorted structures), **but also** can take in :code:`pymatgen` :code:`Structure` objects, :code:`doped` defect dictionaries or structure files (e.g. :code:`POSCAR`\s for :code:`VASP`) as inputs. As such, it should be compatible with any defect code -(such as `doped `_, `pydefect `_, +(such as `doped `_, `pydefect `_, `PyCDT `_, `PyLada `_, `DASP `_, `Spinney `_, `DefAP `_, `PyDEF `_...) that generates these files. diff --git a/docs/ShakeNBreak_Example_Workflow.ipynb b/docs/ShakeNBreak_Example_Workflow.ipynb index a61a15b..517a8ed 100644 --- a/docs/ShakeNBreak_Example_Workflow.ipynb +++ b/docs/ShakeNBreak_Example_Workflow.ipynb @@ -130,7 +130,7 @@ "id": "9a98b5d2-c17f-4d00-8a0f-b5dfe8997420", "metadata": {}, "source": [ - "## 1. Generate defects with [`doped`](https://doped.readthedocs.io/en/latest/)/`pymatgen`" + "## 1. Generate defects with [`doped`](https://doped.readthedocs.io)/`pymatgen`" ] }, { @@ -139,9 +139,9 @@ "metadata": {}, "source": [ "The input defect objects for `ShakeNBreak` can be generated using either\n", - "[`doped`](https://doped.readthedocs.io/en/latest/), `pymatgen` or alternatively just\n", + "[`doped`](https://doped.readthedocs.io), `pymatgen` or alternatively just\n", " the bulk and defect structures can be provided. Below we show how to generate the defect `python`\n", - " objects using [`doped`](https://doped.readthedocs.io/en/latest/) (Section\n", + " objects using [`doped`](https://doped.readthedocs.io) (Section\n", " 1.1) and `pymatgen` (Section 1.1).\n", "\n", "In this case we take CdTe as our example system:" @@ -163,7 +163,7 @@ "metadata": {}, "source": [ "To generate defects with doped, we can use the code below. This procedure is described in much more\n", - "detail on the [`doped` docs](https://doped.readthedocs.io/en/latest/), which also shows how to generate\n", + "detail on the [`doped` docs](https://doped.readthedocs.io), which also shows how to generate\n", "and calculate the chemical potential terms (needed for defect formation energies), perform defect\n", "supercell (finite-size) charge\n", " corrections, calculate & plot the final defect formation energy diagram, and perform further defect\n", @@ -960,7 +960,7 @@ " folder names will be set equal to `DefectEntry.name` if the `name`\n", " attribute is set for all input `DefectEntry`s, otherwise generated\n", " according to the `doped` convention\n", - " (see: https://doped.readthedocs.io/en/latest/dope_workflow_example.html).\n", + " (see: https://doped.readthedocs.io/en/latest/generation_tutorial.html).\n", "\n", " Defect charge states (from which bond distortions are determined) are\n", " taken from the `DefectEntry.charge_state` property.\n", @@ -3946,9 +3946,9 @@ "metadata": {}, "source": [ "### Further Defect Analysis\n", - "Once the ground state (and metastable) defect structures have been identified, we will want to compute their formation energies using our final fully-converged calculation parameters (i.e. plane-wave cutoff and k-point sampling). This can be done using [`doped`](https://doped.readthedocs.io/en/latest/), manually (not recommended) or using the other defect codes listed on the [Code Compatibility](https://shakenbreak.readthedocs.io/en/latest/Code_Compatibility.html) page.\n", + "Once the ground state (and metastable) defect structures have been identified, we will want to compute their formation energies using our final fully-converged calculation parameters (i.e. plane-wave cutoff and k-point sampling). This can be done using [`doped`](https://doped.readthedocs.io), manually (not recommended) or using the other defect codes listed on the [Code Compatibility](https://shakenbreak.readthedocs.io/en/latest/Code_Compatibility.html) page.\n", "\n", - "As shown in the [`doped`](https://doped.readthedocs.io/en/latest/) examples and docs, you may want to further analyse the behaviour and impact on material properties of your defects using advanced defect analysis codes such as [`easyunfold`](https://smtg-bham.github.io/easyunfold/) (to analyse the electronic structure of defects in your material), [`py-sc-fermi`](https://py-sc-fermi.readthedocs.io/en/latest/) (to analyse defect concentrations, doping and Fermi level tuning), or [`nonrad`](https://nonrad.readthedocs.io/en/latest/)/[`CarrierCapture.jl`](https://wmd-group.github.io/CarrierCapture.jl/dev/) (to analyse non-radiative electron-hole recombination at defects)." + "As shown in the [`doped`](https://doped.readthedocs.io) examples and docs, you may want to further analyse the behaviour and impact on material properties of your defects using advanced defect analysis codes such as [`easyunfold`](https://smtg-bham.github.io/easyunfold/) (to analyse the electronic structure of defects in your material), [`py-sc-fermi`](https://py-sc-fermi.readthedocs.io/en/latest/) (to analyse defect concentrations, doping and Fermi level tuning), or [`nonrad`](https://nonrad.readthedocs.io/en/latest/)/[`CarrierCapture.jl`](https://wmd-group.github.io/CarrierCapture.jl/dev/) (to analyse non-radiative electron-hole recombination at defects)." ] }, { diff --git a/docs/Tips.rst b/docs/Tips.rst index 9073038..5062744 100644 --- a/docs/Tips.rst +++ b/docs/Tips.rst @@ -220,7 +220,7 @@ message about the origin of the problem, it is likely to be an issue with your v 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 `_ page, or by email. +`Issues `_ page. - A current known issue with ``numpy``/``pymatgen`` is that it might give an error similar to this: diff --git a/docs/conf.py b/docs/conf.py index 09c1dbc..1057987 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -25,7 +25,7 @@ author = 'Irea Mosquera-Lois, Seán R. Kavanagh' # The full version, including alpha/beta/rc tags -release = '3.3.5' +release = '3.3.6' # -- General configuration --------------------------------------------------- diff --git a/docs/index.rst b/docs/index.rst index 1cd2301..a318a60 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -171,7 +171,7 @@ Code Compatibility :code:`ShakeNBreak` can take :code:`pymatgen` :code:`Defect` objects as input (to then generate the trial distorted structures), **but also** can take in :code:`pymatgen` :code:`Structure` objects, :code:`doped` defect dictionaries or structure files (e.g. :code:`POSCAR`\s for :code:`VASP`) as inputs. As such, it should be compatible with any defect code -(such as `doped `_, `pydefect `_, +(such as `doped `_, `pydefect `_, `PyCDT `_, `PyLada `_, `DASP `_, `Spinney `_, `DefAP `_, `PyDEF `_...) that generates these files. @@ -211,10 +211,14 @@ run tests and add new tests for any new features whenever submitting pull reques Studies using ``ShakeNBreak`` ============================= +- Z\. Yuan & G. Hautier **First-principles study of defects and doping limits in CaO** `Applied Physics Letters `_ 2024 - B\. E. Murdock et al. **Li-Site Defects Induce Formation of Li-Rich Impurity Phases: Implications for Charge Distribution and Performance of LiNi** :sub:`0.5-x` **M** :sub:`x` **Mn** :sub:`1.5` **O** :sub:`4` **Cathodes (M = Fe and Mg; x = 0.05–0.2)** `Advanced Materials `_ 2024 -- A\. G. Squires et al. **Oxygen dimerization as a defect-driven process in bulk LiNiO₂** `ChemRxiv `_ 2024 +- A\. G. Squires et al. **Oxygen dimerization as a defect-driven process in bulk LiNiO₂** `ACS Energy Letters `__ 2024 +- Y\. Fu & H. Lohan et al. **Factors Enabling Delocalized Charge-Carriers in Pnictogen-Based Solar Absorbers: In-depth Investigation into CuSbSe2** `arXiv `_ 2024 +- S\. Hachmioune et al. **Exploring the Thermoelectric Potential of MgB4: Electronic Band Structure, Transport Properties, and Defect Chemistry** `Chemistry of Materials `_ 2024 +- J\. Hu et al. **Enabling ionic transport in Li3AlP2 the roles of defects and disorder** `ChemRxiv `_ 2024 - X\. Wang et al. **Upper efficiency limit of Sb₂Se₃ solar cells** `Joule `_ 2024 -- I\. Mosquera-Lois et al. **Machine-learning structural reconstructions for accelerated point defect calculations** `arXiv `_ 2024 +- I\. Mosquera-Lois et al. **Machine-learning structural reconstructions for accelerated point defect calculations** `npj Computational Materials `_ 2024 - S\. R. Kavanagh et al. **doped: Python toolkit for robust and repeatable charged defect supercell calculations** `Journal of Open Source Software `_ 2024 - K\. Li et al. **Computational Prediction of an Antimony-based n-type Transparent Conducting Oxide: F-doped Sb₂O₅** `Chemistry of Materials `_ 2024 - X\. Wang et al. **Four-electron negative-U vacancy defects in antimony selenide** `Physical Review B `_ 2023 diff --git a/setup.py b/setup.py index 16807d9..3e0ba5a 100644 --- a/setup.py +++ b/setup.py @@ -131,7 +131,7 @@ def package_files(directory): setup( name="shakenbreak", - version="3.3.5", + version="3.3.6", description="Package to generate and analyse distorted defect structures, in order to " "identify ground-state and metastable defect configurations.", long_description=long_description, diff --git a/shakenbreak/SnB_run.sh b/shakenbreak/SnB_run.sh index 64eb165..eecb0ad 100755 --- a/shakenbreak/SnB_run.sh +++ b/shakenbreak/SnB_run.sh @@ -41,7 +41,7 @@ check_multiple_single_step_outcars() { counter=0 # Iterate over all OUTCAR*on* files in the current directory - for file in OUTCAR*on* + for file in OUTCAR* do # Check if file is a regular file if [[ -f $file ]]; then @@ -85,16 +85,23 @@ SnB_run_loop() { if [[ "$i" == *"_High_Energy"* ]]; then continue fi - if [ ! -f "${i}"/OUTCAR ] || ( ! grep -q "required accuracy" "${i}"/OUTCAR && ! grep -q "considering this converged" "${i}"/OUTCAR ); then # check calculation not converged + if [ ! -f "${i}"/OUTCAR ] || { ! grep -q "required accuracy" "${i}"/OUTCAR && ! grep -q "considering this converged" "${i}"/OUTCAR; }; then # check calculation not converged builtin cd "$i" || return if [ ! -f "${job_filepath}" ] && [ ! "$job_in_cwd" = false ]; then "cp" ../"${job_filepath}" "./${job_filename}" 2>/dev/null || "cp" ../../"${job_filepath}" "./${job_filename}" 2>/dev/null || return fi + if [ -f "../Unperturbed/OUTCAR" ] && (($(grep -c entropy= ../Unperturbed/OUTCAR) > 0)); then + unperturbed_energy=$(grep entropy= ../Unperturbed/OUTCAR | awk '{print $NF}' | tail -1) + else + unperturbed_energy=-10000 + fi if [ -f OUTCAR ]; then # if OUTCAR exists so rerunning rather than 1st run # count number of ionic steps with positive energies, after the first 5 ionic steps - pos_energies=$(grep entropy= OUTCAR | awk 'FNR>5 && $NF !~ /^-/{print $0}' | wc -l) + pos_energies=$(grep "entropy=" OUTCAR | awk 'FNR>5 && $NF !~ /^-/' | grep -cE '[-+]?[0-9]*\.?[0-9]+$') # second grep ensures only lines that end in numbers are matched errors=$(grep -Ec "(EDDDAV|ZHEGV|CNORMN|ZPOTRF|ZTRTRI|FEXC)" OUTCAR) - if ((pos_energies > 0)) || ((errors > 0)); then # if there are positive energies or errors in OUTCAR + last_energy=$(grep entropy= OUTCAR | awk '{print $NF}' | tail -1) + energy_diff_to_unperturbed=$(echo "$last_energy - $unperturbed_energy" | bc) + if ((errors > 0)) || { ((pos_energies > 0)) && { (($(echo "$energy_diff_to_unperturbed > 1" | bc -l))) || [[ "$i" == *"Unperturbed"* ]]; }; }; then # if there are positive energies or errors in OUTCAR, and at least 1 eV higher than Unperturbed if [[ "$i" == *"Unperturbed"* ]]; then # positive energies / errors for Unperturbed structure, indicates pathological defect structure echo "Positive energies or forces error encountered for ${i%/}. " @@ -142,7 +149,7 @@ SnB_run_loop() { fi # check if multiple <=single-step OUTCARs present, and CONTCAR empty/less than 9 lines or same as POSCAR - if check_multiple_single_step_outcars && { ( [[ -f "CONTCAR" ]] && [[ $(wc -l < "CONTCAR") -le 9 ]] ) || ( [[ -f "CONTCAR" ]] && diff -q "POSCAR" "CONTCAR" >/dev/null ) || [[ ! -f "CONTCAR" ]]; }; then + if check_multiple_single_step_outcars && { [[ ! -f "CONTCAR" ]] || { [[ -f "CONTCAR" ]] && { [[ $(wc -l < "CONTCAR") -le 9 ]] || diff -q "POSCAR" "CONTCAR" >/dev/null; }; }; }; then echo "Previous run for ${i%?} did not yield more than one ionic step, and multiple OUTCARs with <=1 ionic " echo "steps present, suggesting poor convergence. Recommended to manually check the VASP output files for this!" fi @@ -152,18 +159,12 @@ SnB_run_loop() { # echo "More than 2 OUTCARs present for ${i%?}, suggesting tricky relaxation. " #sed -i.bak 's/IBRION.*/IBRION = 1/g' INCAR && rm -f INCAR.bak # sometimes helps to change IBRION if relaxation taking long # Check total number of ionic steps in all OUTCARs - num_ionic_steps=$(grep entropy= OUTCAR* | wc -l) + num_ionic_steps=$(grep entropy= OUTCAR* | wc -l) # use wc -l rather than grep -c because multiple files if [ -f ../Unperturbed/OUTCAR ]; then # only compare if Unperturbed folder present # If equal or higher than 150, compare to final energy in Unperturbed OUTCAR if ((num_ionic_steps >= 150)); then - # Get final energy from Unperturbed OUTCAR - final_energy=$(grep entropy= ../Unperturbed/OUTCAR | awk '{print $NF}' | tail -1) - # Get final energy from last OUTCAR - last_energy=$(grep entropy= OUTCAR | awk '{print $NF}' | tail -1) - # Calculate difference between final energies - energy_diff=$(echo "$final_energy - $last_energy" | bc) - # If difference is higher than 2 eV, rename to _High_Energy and continue - if (($(echo "${energy_diff#-} > 2" | bc -l))); then + # If energy difference to Unperturbed is higher than 2 eV, rename to _High_Energy and continue + if (($(echo "$energy_diff_to_unperturbed > 1" | bc -l))); then echo "More than 150 ionic steps present for ${i%?}. The energy difference to last structure in Unperturbed relaxation" echo "is higher than 2 eV, indicating that ${i%?} is stuck in a high energy basin. " echo "Renaming to ${i%?}_High_Energy and continuing." @@ -192,9 +193,9 @@ SnB_run_loop() { # save_vasp_files: current_time=$(date +%H_%M_%Son%d_%m_%y) for vasp_file in {CONTCAR,OUTCAR,XDATCAR,POSCAR,INCAR,OSZICAR,vasprun.xml}; do - cp ${vasp_file} ${vasp_file}_${current_time} + cp "${vasp_file}" "${vasp_file}_${current_time}" 2>/dev/null done - gzip vasprun.xml_${current_time} # gzip to save file space + gzip "vasprun.xml_${current_time}" # gzip to save file space if [[ -f "CONTCAR" ]] && [[ $(wc -l < "CONTCAR") -ge 9 ]]; then # CONTCAR exists and greater than 9 lines "cp" CONTCAR POSCAR @@ -212,14 +213,14 @@ SnB_run_loop() { echo "Running job for ${i%?}" folder_shortname="${i#*_*_}" # Remove % from folder_shortname as messes with some HPC schedulers - if ! ( "${job_submit_command}" "${job_name_option}" "${defect_name%?}"_"${folder_shortname%?}" "${job_filename}" 2>/dev/null || \ - "${job_submit_command}" "${job_name_option}" "${defect_name%?}"_"${folder_shortname%??}" "${job_filename}" ); then + if ! { "${job_submit_command}" "${job_name_option}" "${defect_name%?}"_"${folder_shortname%?}" "${job_filename}" 2>/dev/null || \ + "${job_submit_command}" "${job_name_option}" "${defect_name%?}"_"${folder_shortname%??}" "${job_filename}"; }; then if ! [ "$current_time" == false ]; then - rm *_"${current_time}" # only save over files if job submit command is successful (to prevent unwanted duplication of files) + rm ./*_"${current_time}" # only save over files if job submit command is successful (to prevent unwanted duplication of files) fi fi - else - rm *_"${current_time}" # only save over files if job successfully submitted + elif ! [ "$current_time" == false ]; then + rm ./*_"${current_time}" 2>/dev/null # only save over files if job successfully submitted fi builtin cd .. || return else diff --git a/shakenbreak/energy_lowering_distortions.py b/shakenbreak/energy_lowering_distortions.py index 51feeea..c857347 100644 --- a/shakenbreak/energy_lowering_distortions.py +++ b/shakenbreak/energy_lowering_distortions.py @@ -273,6 +273,13 @@ def _prune_dict_across_charges( defect_species_snb_name = f"{defect}_{'+' if charge > 0 else ''}{charge}" for i in ["+", "", "+"]: # back to SnB name with "+" if all fail defect_species = defect_species_snb_name.replace("+", i) # try with and without '+' + distorted_struct = distortion_dict["structures"][0] + if not isinstance(distorted_struct, Structure): + raise ValueError( + f"Distorted structure for {defect_species} was not correctly parsed. Instead " + f"of a pymatgen Structure object, got: {type(distorted_struct)}; " + f"{distorted_struct}" + ) comparison_results = compare_struct_to_distortions( distortion_dict["structures"][0], defect_species, @@ -460,7 +467,7 @@ def get_energy_lowering_distortions( structure_filename=structure_filename, ) # get the final structure of the # energy lowering distortion - if any(warning.category == UserWarning for warning in w): + if any(issubclass(warning.category, UserWarning) for warning in w): # problem parsing structure, user will have received appropriate # warning from io.read_vasp_structure() print( @@ -532,7 +539,7 @@ def get_energy_lowering_distortions( structure_path=f"{output_path}/{defect_species}/{bond_distortion}", structure_filename=structure_filename, ) - if any(warning.category == UserWarning for warning in w): + if any(issubclass(warning.category, UserWarning) for warning in w): # problem parsing structure, user will have received appropriate # warning from io.read_vasp_structure() print( diff --git a/shakenbreak/input.py b/shakenbreak/input.py index a2aa93a..86fc805 100644 --- a/shakenbreak/input.py +++ b/shakenbreak/input.py @@ -1740,7 +1740,7 @@ def __init__( folder names will be set equal to `DefectEntry.name` if the `name` attribute is set for all input `DefectEntry`s, otherwise generated according to the `doped` convention - (see: https://doped.readthedocs.io/en/latest/dope_workflow_example.html). + (see: https://doped.readthedocs.io/en/latest/generation_tutorial.html). Defect charge states (from which bond distortions are determined) are taken from the `DefectEntry.charge_state` property. diff --git a/shakenbreak/py.typed b/shakenbreak/py.typed new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/shakenbreak/py.typed @@ -0,0 +1 @@ + diff --git a/tests/test_energy_lowering_distortions.py b/tests/test_energy_lowering_distortions.py index d00f118..5c50570 100644 --- a/tests/test_energy_lowering_distortions.py +++ b/tests/test_energy_lowering_distortions.py @@ -45,13 +45,13 @@ def setUp(self): self.FHI_AIMS_DATA_DIR = os.path.join(self.DATA_DIR, "fhi_aims") self.ESPRESSO_DATA_DIR = os.path.join(self.DATA_DIR, "quantum_espresso") self.V_Cd_minus_0pt55_structure = Structure.from_file( - self.VASP_CDTE_DATA_DIR + "/vac_1_Cd_0/Bond_Distortion_-55.0%/CONTCAR" + f"{self.VASP_CDTE_DATA_DIR}/vac_1_Cd_0/Bond_Distortion_-55.0%/CONTCAR" ) # create fake distortion folders for testing functionality: for defect_dir in ["Int_Cd_2_+1", "vac_1_Cd_-1", "vac_1_Cd_-2"]: if not os.path.exists(f"{self.VASP_CDTE_DATA_DIR}/{defect_dir}"): - os.mkdir(self.VASP_CDTE_DATA_DIR + f"/{defect_dir}") + os.mkdir(f"{self.VASP_CDTE_DATA_DIR}/{defect_dir}") # Int_Cd_2_+1 without data, to test warnings V_Cd_1_dict = {"distortions": {-0.075: -205.740}, "Unperturbed": -205.800} dumpfn( @@ -79,16 +79,10 @@ def setUp(self): "sub_1_In_on_Cd_+1", ] - self.orig_castep_0pt3_files = os.listdir( - self.CASTEP_DATA_DIR + "/vac_1_Cd_0/Bond_Distortion_30.0%" - ) - self.orig_cp2k_0pt3_files = os.listdir(self.CP2K_DATA_DIR + "/vac_1_Cd_0/Bond_Distortion_30.0%") - self.orig_fhi_aims_0pt3_files = os.listdir( - self.FHI_AIMS_DATA_DIR + "/vac_1_Cd_0/Bond_Distortion_30.0%" - ) - self.orig_espresso_0pt3_files = os.listdir( - self.ESPRESSO_DATA_DIR + "/vac_1_Cd_0/Bond_Distortion_30.0%" - ) + self.orig_castep_0pt3_files = os.listdir(f"{self.CASTEP_DATA_DIR}/vac_1_Cd_0/Bond_Distortion_30.0%") + self.orig_cp2k_0pt3_files = os.listdir(f"{self.CP2K_DATA_DIR}/vac_1_Cd_0/Bond_Distortion_30.0%") + self.orig_fhi_aims_0pt3_files = os.listdir(f"{self.FHI_AIMS_DATA_DIR}/vac_1_Cd_0/Bond_Distortion_30.0%") + self.orig_espresso_0pt3_files = os.listdir(f"{self.ESPRESSO_DATA_DIR}/vac_1_Cd_0/Bond_Distortion_30.0%") def tearDown(self): # removed generated folders @@ -228,6 +222,7 @@ def test_get_energy_lowering_distortions(self): low_energy_defects_dict = energy_lowering_distortions.get_energy_lowering_distortions( self.defect_charges_dict, self.VASP_CDTE_DATA_DIR ) + print([str(warning.message) for warning in w]) # for debugging mock_print.assert_any_call("\nvac_1_Cd") mock_print.assert_any_call( "vac_1_Cd_0: Energy difference between minimum, found with -0.55 bond distortion, "