Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
31d2085
"Claude PR Assistant workflow"
kavanase May 18, 2026
8e296a1
"Claude Code Review workflow"
kavanase May 18, 2026
9f08c3e
Merge pull request #152 from SMTG-Bham/add-claude-github-actions-1779…
kavanase May 18, 2026
40e770e
GPAW support
sblisesivdin Jan 25, 2026
a643095
Correcting some errors in gpaw.py and in example.
sblisesivdin Jan 27, 2026
f736dfc
LCAO support
sblisesivdin Jan 31, 2026
236be1b
Test for LCAO
sblisesivdin Jan 31, 2026
b8f1354
Refactor GPAW site potential extraction to use core sphere averaging
sblisesivdin Apr 2, 2026
99b0242
Changes in gpaw.py
sblisesivdin Apr 28, 2026
cb7dacd
Changes filenames in example
sblisesivdin Apr 28, 2026
08cc959
MgO example with GPAW
sblisesivdin Apr 28, 2026
8b20444
Update GPAW tests to use static .gpw files without mocking
sblisesivdin May 6, 2026
d148e4a
More robust parsing
sblisesivdin May 26, 2026
eb9da4c
More elegant output.
sblisesivdin May 26, 2026
a0e4d13
Correcting handling of charged structures
sblisesivdin May 26, 2026
bd5b227
Removing some comments of robust parsing of QE implementation
sblisesivdin May 26, 2026
8782555
Correct handling unrelaxed structure
sblisesivdin May 26, 2026
abac89a
Add all MgO calculations and other files to test folder
sblisesivdin May 26, 2026
38de5eb
Symmetrized CIF Writing
sblisesivdin Jun 1, 2026
a7c2c71
Configurable Optimizer
sblisesivdin Jun 1, 2026
737e334
Documenting Defaults
sblisesivdin Jun 1, 2026
9aceb4e
FNV info in Documentation
sblisesivdin Jun 1, 2026
b06e1a6
Correcting small syntax error
sblisesivdin Jun 1, 2026
90ba154
Remove symprec
sblisesivdin Jun 1, 2026
ba2e62a
Add commit to symprec problem
sblisesivdin Jun 2, 2026
f457ffe
New tests for mgo with FNV and 2D graphene
sblisesivdin Jun 2, 2026
8843ebf
Jupyter tutorial for GPAW
sblisesivdin Jun 2, 2026
6ea90c4
Implement defect radius region inside doped
sblisesivdin Jun 2, 2026
1c8d835
Comment about charge corrections are scaled with q^2
sblisesivdin Jun 16, 2026
601a8a2
Explicit FNV Testing for MgO test with GPAW
sblisesivdin Jun 16, 2026
a35b8c3
MgO example is running all defects now.
sblisesivdin Jun 23, 2026
457481a
Add new type of defects to Kumagai
sblisesivdin Jun 23, 2026
f6e1822
Update to `doped` `develop` parameter ordering, and formatting
kavanase Jun 23, 2026
8a93527
pre-commit formatting and cleanup
kavanase Jun 23, 2026
3006df2
More pre-commit formatting and cleanup
kavanase Jun 23, 2026
ed6bec9
More pre-commit formatting and cleanup
kavanase Jun 23, 2026
0e686b2
Merge branch 'SMTG-Bham:main' into main
sblisesivdin Jul 29, 2026
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
44 changes: 44 additions & 0 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Claude Code Review

on:
pull_request:
types: [opened, synchronize, ready_for_review, reopened]
# Optional: Only run on specific file changes
# paths:
# - "src/**/*.ts"
# - "src/**/*.tsx"
# - "src/**/*.js"
# - "src/**/*.jsx"

jobs:
claude-review:
# Optional: Filter by PR author
# if: |
# github.event.pull_request.user.login == 'external-contributor' ||
# github.event.pull_request.user.login == 'new-developer' ||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'

runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
plugins: 'code-review@claude-code-plugins'
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options

50 changes: 50 additions & 0 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Claude Code

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]

jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}

# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read

# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'

# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr *)'

3 changes: 2 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ repos:
rev: v2.1.0
hooks:
- id: mypy
<<: *skip_docs
# type-check the ``doped`` package + test modules directly under ``tests/``:
files: ^(doped/|tests/[^/]+\.py$)
additional_dependencies:
- numpy
- pandas
Expand Down
109 changes: 109 additions & 0 deletions docs/GPAW_Support.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
GPAW Support
====================================

``doped`` provides comprehensive support for defect calculations using `GPAW <https://wiki.fysik.dtu.dk/gpaw/>`_,
a Density Functional Theory (DFT) Python code based on the projector-augmented wave (PAW) method.
This support includes automated input generation, parsing of calculation results, and
integration with the full ``doped`` defect analysis workflow.

Installation & Requirements
---------------------------

To use the GPAW interface, you must have GPAW installed in your Python environment:

.. code-block:: bash

pip install gpaw

For the Kumagai (eFNV) charge correction, ``pydefect`` is also required:

.. code-block:: bash

pip install pydefect

Workflow Overview
-----------------

The workflow for GPAW defect calculations follows the standard ``doped`` logic:

1. **Generation**: Generate defect structures using ``DefectsGenerator``.
2. **Input Preparation**: Write GPAW Python scripts and structure files using ``GPAWDefectRelaxSet``.
3. **Execution**: Run the calculations using GPAW (typically via ``mpirun``).
4. **Parsing**: Parse the results (``.gpw(.gz)`` files) using ``GPAWDefectsParser``.
5. **Analysis**: Perform thermodynamic analysis and plotting.

Input Generation
----------------

The ``GPAWDefectRelaxSet`` class is used to generate the necessary files for a GPAW relaxation.
It produces a ``relax.py`` script and a ``structure.cif`` file.

.. code-block:: python

from doped.gpaw import GPAWDefectRelaxSet
from pymatgen.core.structure import Structure

# Load your supercell structure
structure = Structure.from_file("POSCAR")

# Define GPAW settings
gpaw_settings = {
"mode": {"name": "pw", "ecut": 400},
"xc": "PBE",
"kpts": {"size": (2, 2, 2), "gamma": True},
}

# Initialize the relax set for a +1 charge state
relax_set = GPAWDefectRelaxSet(structure, charge_state=1, gpaw_settings=gpaw_settings)

# Write files to a directory
relax_set.write_input("calculation_folder")

Parsing Results
---------------

Once calculations are complete, ``doped`` can parse the resulting ``relaxed.gpw(.gz)`` files.
The ``GPAWDefectsParser`` can handle multiple defect folders at once.

.. code-block:: python

from doped.gpaw import GPAWDefectsParser

# Initialize the parser
# output_path: directory containing defect folders
# bulk_path: directory containing the bulk reference calculation
parser = GPAWDefectsParser(
output_path=".",
bulk_path="calculation_bulk",
dielectric=10.0 # Required for charge corrections
)

# Parse all defects
defect_dict = parser.parse_all()

Finite-Size Corrections
-----------------------

GPAW calculations of charged defects require finite-size corrections to account for periodic image interactions. ``doped`` supports both the **Kumagai (eFNV)** correction (highly recommended) and the standard **Freysoldt-Neugebauer-Van de Walle (FNV)** correction for GPAW.

Anisotropic Systems (2D/1D)
~~~~~~~~~~~~~~~~~~~~~~~~~~~

For anisotropic systems like 2D materials (e.g., graphene, MoS2), the default sampling radius
calculation in standard tools often fails by setting a radius that encompasses the entire cell.
``doped`` implements an improved radius calculation:

- It automatically determines the optimal ``defect_region_radius`` based on the inscribed
sphere of the supercell (half the shortest distance between parallel planes).
- It includes safety checks to prevent errors when the sampling region is small or empty.

Detailed API
------------

For more specific information on classes and functions, see the :ref:`doped.gpaw module` documentation.

Example Script
--------------

An end-to-end example of generating and parsing GPAW defects can be found in the
``examples/Graphene_with_GPAW`` directory of the ``doped`` repository.
1 change: 1 addition & 0 deletions docs/GPAW_tutorial.ipynb
1 change: 1 addition & 0 deletions docs/Tutorials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ tutorials:
GGA_workflow_tutorial
CCD_NEB_tutorial
stenciling_tutorial
GPAW_tutorial
6 changes: 6 additions & 0 deletions docs/doped.gpaw.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
doped.gpaw module
=================================================
.. automodule:: doped.gpaw
:members:
:undoc-members:
:show-inheritance:
1 change: 1 addition & 0 deletions docs/doped.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Modules
doped.core
doped.corrections
doped.generation
doped.gpaw
doped.init
doped.thermodynamics
doped.utils
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ Thanks to `Chaoqun Zhang <https://github.com/Warlocat>`__ for uploading the

Installation
Python API <doped>
GPAW_Support
Tutorials
Tips
Code Overview & Workflow Diagrams <https://deepwiki.com/SMTG-Bham/doped>
Expand Down
6 changes: 5 additions & 1 deletion doped/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,11 @@ def get_kumagai_correction(
)

# correction energy error can be estimated from standard error of the mean:
correction_error = sem(sampled_pot_diff_array) * abs(self.charge_state)
if sampled_pot_diff_array.size > 0:
correction_error = sem(sampled_pot_diff_array) * abs(self.charge_state)
else:
correction_error = np.nan

self.corrections_metadata.update({"kumagai_charge_correction_error": correction_error})
return self._check_correction_error_and_return_output(
efnv_correction_output,
Expand Down
17 changes: 15 additions & 2 deletions doped/corrections.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
get_core_potentials_from_outcar,
get_locpot,
get_site_mapping_indices,
get_wigner_seitz_radius,
)
from doped.utils.plotting import doped_plot_style, format_defect_name

Expand Down Expand Up @@ -464,6 +463,7 @@ def doped_make_efnv_correction(
dielectric_tensor: np.ndarray,
defect_coords: np.ndarray | list,
defect_region_radius: float | None = None,
radius_method: str = "min",
accuracy: float = defaults.ewald_accuracy,
unit_conversion: float = 180.95128169876497,
excluded_indices: list | None = None,
Expand Down Expand Up @@ -522,7 +522,19 @@ def ewald_rec(self, coord) -> float:
point_charge_correction = -ewald.lattice_energy * charge**2 if charge else 0.0

if defect_region_radius is None:
defect_region_radius = get_wigner_seitz_radius(lattice)
# 0.5 * np.pi / norm evaluates to d/4 (half the inscribed sphere radius)
distances = [
0.5 * np.pi / np.linalg.norm(lattice.reciprocal_lattice.matrix[i]) for i in range(3)
]

if radius_method.lower() == "min":
defect_region_radius = np.min(distances)
elif radius_method.lower() == "max":
defect_region_radius = np.max(distances)
elif radius_method.lower() == "average":
defect_region_radius = np.mean(distances)
else:
raise ValueError("radius_method must be 'min', 'max', or 'average'")

for site, rel_coord in zip(sites, rel_coords, strict=False):
if site.distance > defect_region_radius:
Expand Down Expand Up @@ -609,6 +621,7 @@ def ewald_rec(self, coord) -> float:
"defect_coords", _get_defect_supercell_frac_coords(defect_entry)
), # _relaxed_ defect coords (except for vacancies)
defect_region_radius=defect_region_radius,
radius_method=kwargs.pop("radius_method", "min"),
excluded_indices=excluded_indices,
**kwargs,
)
Expand Down
Loading