Skip to content

Run open-shell species spin-polarised in DFTB+ automatically - #64

Merged
galjos merged 2 commits into
mainfrom
spin-polarized-dftbplus
Jul 2, 2026
Merged

Run open-shell species spin-polarised in DFTB+ automatically#64
galjos merged 2 commits into
mainfrom
spin-polarized-dftbplus

Conversation

@galjos

@galjos galjos commented Jul 2, 2026

Copy link
Copy Markdown
Member

Follow-up to #63. #63 made the user spin drive the electronic-degeneracy entropy; this makes it drive the DFTB+ calculation, so open-shell species are treated consistently (open-shell energy and the matching multiplicity), with no extra input.

Behaviour (charge is the only per-molecule input)

dftbplus_thermo resolves the spin — the electron-count guess when not given (even→singlet, odd→doublet) — and:

  • S > 0 → colinear spin-polarised DFTB+: SpinPolarisation = Colinear { UnpairedElectrons = round(2S) } + the 3ob SpinConstants for the atoms present, injected into Geoopt/Hessian.
  • S = 0 → restricted closed-shell calculation, byte-for-byte unchanged (the default methodology).

So a radical (odd electrons) is auto-detected and run spin-polarised — e.g. an anthraquinone radical anion (charge −1) just works. The same S drives the calculation and the entropy, so they stay consistent. Only even-electron triplets (O₂) need an explicit spin=1.

Spin constants

SPIN_CONSTANTS is the 3ob-3-1 PBE set — the compact single-shell form (HOMO W, ShellResolvedSpin = No) matching this tool’s atom-resolved 3ob SCC. Cross-verified across three independent sources (3ob Elstner list ↔ QUASINANO2015 arXiv:1605.01360 ↔ DFTB+ manual/mio/Köhler). Covers H, C, N, O, F, P, S, Cl; elements without an authoritative constant (Br, I, metals) raise a clear error rather than a guessed number. The constants are parameters tied to the SK set/functional — see the code comment.

Tests (offline; the slako files are absent here)

  • _spin_kwargs: restricted for S∈(None,0) and fractional S; colinear block for a doublet; error for an untabulated element.
  • dftbplus_thermo (mocked pipeline): an OH radical auto-spin-polarises (UnpairedElectrons=1, S passed to the analysis as 0.5); closed-shell water stays restricted; explicit O₂ spin=1UnpairedElectrons=2.

178 passed, 5 skipped; pylint 8.88.

Caveat

This is a methodology change gated behind an open-shell spin (restricted stays the default). I could not validate the energies here — the 3ob slako files are gone from this machine — so the wiring and constants are verified but the numbers should be confirmed with a real spin-polarised run (restored slako). The S d-shell constant is contested upstream, but only s/p are used for organic sulfur.

Follow-up to #63: make the spin actually drive the DFTB+ calculation, not just
the electronic-degeneracy entropy. dftbplus_thermo now resolves the spin (the
electron-count guess when not given) and, when S > 0, runs Geoopt/Hessian
colinear spin-polarised via _spin_kwargs: SpinPolarisation = Colinear with
UnpairedElectrons = round(2S) and the 3ob-PBE SpinConstants injected for the
elements present. Closed-shell (S = 0) keeps the restricted calculation
unchanged. So a radical (odd electrons) is auto-detected and treated open-shell
with no extra input; only even-electron triplets (O2) need an explicit spin.

The 3ob spin constants are cross-verified (3ob Elstner list vs QUASINANO2015 vs
DFTB+ manual/mio); elements without one (Br, I, metals) raise a clear error.
Energies should be validated with a real spin-polarised run.
@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.23%. Comparing base (1395885) to head (6a9f7fa).

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #64      +/-   ##
==========================================
+ Coverage   96.17%   96.23%   +0.05%     
==========================================
  Files          22       22              
  Lines        1308     1328      +20     
==========================================
+ Hits         1258     1278      +20     
  Misses         50       50              
Flag Coverage Δ
unittests 96.23% <100.00%> (+0.05%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@galjos

galjos commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

Validated end-to-end with real DFTB+ 24.1 (3ob slako), not just mocks:

  • DFTB+ accepts the generated dftb_in.hsd (SpinPolarisation = Colinear, UnpairedElectrons = 1, SpinConstants { ShellResolvedSpin = No ... }) and converges.
  • Physics is correct: spin-polarised OH radical (−3.579 H) is 0.40 eV lower than restricted (−3.564 H) — the expected exchange stabilization; and S_elec = R·ln 2 = 1.377 cal/(mol*K) for the doublet.
  • Full automatic path (no spin input): an OH radical auto-guesses a doublet, runs spin-polarised through geo-opt/Hessian/modes/thermo; closed-shell water auto-stays restricted (no spin block). Only the structure + charge are provided.

So the earlier "wiring verified, energies unvalidated" caveat is resolved — the spin constants and syntax produce a correct spin-polarised calculation.

The 3ob-3-1 set ships its own spin constants in extras/spinw.hsd (PBE,
slateratom). All eight organic values already matched it exactly; extend the
table with the remaining 3ob elements from that authoritative file (Na, Mg, K,
Ca, Zn, Br, I) so spin-polarised calculations work for any element the tool's
3ob parameters already support. Verified a Br-containing radical runs
spin-polarised and converges.
@galjos
galjos merged commit d51d08a into main Jul 2, 2026
3 checks passed
@galjos
galjos deleted the spin-polarized-dftbplus branch July 6, 2026 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant