FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Fix: correct Pauli-to-spinor Hamiltonian conversion for nspin=4 by dyzheng · Pull Request #7664 · deepmodeling/abacus-develop · GitHub

Fix: correct Pauli-to-spinor Hamiltonian conversion for nspin=4 - #7664

Merged
mohanchen merged 18 commits into
deepmodeling:developfrom
dyzheng:fix_pauli_to_spinor
Jul 23, 2026
Merged

Fix: correct Pauli-to-spinor Hamiltonian conversion for nspin=4 #7664
mohanchen merged 18 commits into
deepmodeling:developfrom
dyzheng:fix_pauli_to_spinor

Conversation

dyzheng commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Reminder

  • I have read AGENTS.md and docs/developers_guide/agent_governance.md.
  • I have linked an issue or explained why this PR does not need one.
  • I have added adequate unit tests and/or case tests, or explained why not.
  • I have listed the exact verification commands run and their results.
  • I have described user-visible behavior changes, including INPUT parameter changes.
  • I have explained core-module impact for ESolver, HSolver, ElecState, Hamilt, Operator, Psi, or other source/ changes.
  • I have requested any needed governance exception below.

Linked Issue

Fix #7513

Unit Tests and/or Case Tests for my changes

  • Commands run:
  • Result summary:
  • Checks not run, with reason:

What's changed?

  • Example: brief summary of the user-visible or developer-facing change.

Governance Notes

  • INPUT/docs changes:
  • Core module impact:
  • Exceptions requested:

dyzheng added 15 commits June 23, 2026 22:53
Fix two bugs in LCAO non-collinear Hamiltonian construction:

1. Wrong sign in off-diagonal elements: H_{up,down} = B_x + i*B_y (wrong)
   should be B_x - i*B_y (correct), and vice versa for H_{down,up}.
   Fixed by correcting clx_j coefficients in merge_hr_part_to_hR().

2. Missing complex conjugate in lower triangle fill: H(-R) used transpose
   instead of conjugate transpose, breaking Hermiticity for complex matrices.
   Fixed by using std::conj() when filling lower triangle.

These errors caused the non-collinear Hamiltonian to be the complex conjugate
of the correct result, leading to incorrect spin textures in nspin=4 calculations.
The PW code path was not affected.

Add test case and verification script to validate:
- H(R=0) Hermiticity: max|H - H^dagger| < 1e-10
- Off-diagonal phase: Im(H_{up,down}) < 0 for m||+y direction

See tests/03_NAO_multik/verify_hamiltonian_convention/TEST_DESIGN.md for details.
…pin=4

Fix three critical bugs in non-collinear (nspin=4) LCAO calculations:

1. DFT+U transfer_vu (dftu_lcao.cpp): Fix sign error in Pauli-to-spinor
   conversion. The off-diagonal elements had wrong imaginary part sign:
   - Before: V_{up,down} = 0.5*(V_x + i*V_y)  (wrong)
   - After:  V_{up,down} = 0.5*(V_x - i*V_y)  (correct, from sigma_y)

2. DFT+U force/stress (dftu_force_stress.hpp): Convert VU from Pauli basis
   to spinor basis before force calculation. The old code incorrectly mixed
   Pauli-basis VU with spinor-basis DM.

3. DeltaSpin force/stress (dspin_force_stress.hpp): Convert lambda from
   Pauli basis to spinor basis. The constraint force F = lambda·dM/dR
   requires proper Pauli-to-spinor conversion:
   - lambda_spinor = (lambda_z, lambda_x, lambda_x, -lambda_z)
   for (uu, ud, du, dd) components.

These fixes ensure consistent Pauli-to-spinor conversion across all modules:
- H construction (gint_common.cpp): already fixed
- DFT+U Hamiltonian: fixed in this commit
- DFT+U force/stress: fixed in this commit
- DeltaSpin force/stress: fixed in this commit

Verified by scf_u_spin4 test (nspin=4 + DFT+U): SCF converges correctly.
…ot spinor basis

Two bugs fixed in dftu_force_stress.hpp:
1. Removed incorrect VU Pauli-to-spinor conversion: DM for nspin=4 is stored in
   Pauli basis (rho_0, rho_x, rho_y, rho_z) per func_xyz_to_updown(), so VU must
   also stay in Pauli basis for the force trace formula F = -Tr(VU * dDM/dR).
2. Removed force *= 2.0 for nspin=4: Pauli basis already includes all spin
   channels, unlike nspin=1 where the factor of 2 accounts for spin degeneracy.
Updated scf_u_spin4 result.ref accordingly.
Constructor 1 of ELPA_Solver was missing elpa_set_integer("blacs_context", ...)
while Constructor 2 (otherParameter) already had it. Without blacs_context,
ELPA's internal MPI operations (e.g. MPI_Bcast in complex Cholesky and
invert_triangular) can fail with INVALID DATATYPE when using complex eigensolves.
Also update scf_angle_spin4 result.ref with corrected reference energy.
…_updown)

For Pauli decomposition: rho = rho_0*I + rho_x*sigma_x + rho_y*sigma_y + rho_z*sigma_z
sigma_y = [[0,-i],[i,0]], so rho_updown = rho_x + i*rho_y, rho_downup = rho_x - i*rho_y
Thus rho_y = Im(rho_updown - rho_downup) = tmp[1].imag() - tmp[2].imag].

Previously the real version had -tmp[1].imag()+tmp[2].imag() = -2*rho_y (wrong sign),
and the complex version had i*(tmp[1].imag()-tmp[2].imag()) = 2i*rho_y (wrong formula).
This broke rotational invariance: mag along y gave wrong energy (~4 eV deviation vs x/z).
…verify_hamiltonian_convention test dir

- Revert density_matrix.cpp func_xyz_to_updown rho_y sign fix from
  commit 52ee608 (belongs on a separate DM-fix branch)
- Remove tests/03_NAO_multik/verify_hamiltonian_convention/ (debug helper)
- Update result.ref for scf_angle_spin4 and scf_u_spin4 to match
  current code (Pauli-to-spinor + ELPA fixes only)
…on clx_j fix)

The gint_common.cpp fix corrects Pauli→spinor (H construction) and the
density_matrix.cpp fix corrects spinor→Pauli (DM Fourier transform).
Both must use the same σ_y convention for self-consistency.
Also update result.ref files for both test cases.
…spin=4 block

Both VU (from cal_v_of_u) and DMR are stored in Pauli basis for nspin=4,
so the Pauli-to-spinor conversion in force/stress calculation is NOT needed.
The previous result.ref for scf_u_spin4 (totalforceref=6.562) was incorrect
because it was generated with code that mixed Pauli-basis VU with incorrectly
converted values. The correct force is 11.33, consistent with the physical
Pauli-basis trace Tr(VU * dDM/dR).

Changes:
- Remove empty if(nspin==4) block in dftu_force_stress.hpp (no conversion needed)
- Update scf_u_spin4/result.ref: totalforceref 6.562 -> 11.332 (correct value)
- Update scf_angle_spin4/result.ref: energy/stress to match computed values
- Add scf_angle_spin4/threshold: relax energy threshold to 1e-5 eV for
  non-collinear calculation numerical reproducibility
- Update scf_out_dos_spin4/result.ref: force/stress to match computed values
…nspin=4

Fix inconsistent Pauli-to-spinor and spinor-to-Pauli conversion signs
across multiple modules, which broke rotational invariance in
non-collinear (nspin=4) LCAO calculations.

The standard sigma_y = [[0,-i],[i,0]] convention requires:
  H_{up,down} = B_x - i*B_y
  rho_y = -Im(rho_updown - rho_downup)

Changes:
- density_matrix.cpp: fix rho_y sign in func_xyz_to_updown
  (real: restore correct -Im(updown)+Im(downup);
   complex: use i*(updown-downup) with full complex values)
- dftu_pw.cpp: fix Pauli-to-spinor sign in DFT+U transfer_vu (PW path)
- spin_constrain.h: fix pauli_to_moment My sign, update comments
- dspin_lcao.cpp: fix cal_coeff_lambda Pauli-to-spinor sign
- deltaspin_core_test.cpp: update unit test for corrected formula
- scf_u_spin4/result.ref: update reference values after correction
Resolved conflicts in density_matrix.cpp and result.ref by keeping
the corrected Pauli-spinor conversion signs.
Correct the comment to match the sigma_y = [[0,-i],[i,0]] convention:
My = -Im(occ[1] - occ[2]) instead of Im(occ[1] - occ[2])
dyzheng force-pushed the fix_pauli_to_spinor branch from 77703a6 to 8ea24b7 Compare July 22, 2026 04:23
mohanchen added Bugs Bugs that only solvable with sufficient knowledge of DFT collinear/non-collinear/SOC/delta-spin Issues related to SOC Refactor Refactor ABACUS codes labels Jul 22, 2026

mohanchen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

LGTM

mohanchen merged commit 1457e26 into deepmodeling:develop Jul 23, 2026
17 checks passed
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 11, 2026
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 11, 2026
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 12, 2026
mohanchen added a commit that referenced this pull request Aug 12, 2026
Co-authored-by: Mohan Chen <mohanchen@pku.edu.cn>
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 18, 2026
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 18, 2026
Fix comment

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 18, 2026
These nspin=4 LCAO references were updated by deepmodeling#7664 (1457e26) to match its
m_y sign convention in func_xyz_to_updown, which sign-flips the transverse
magnetization (the stored DM block is conj(P); m_y reads Im so it flips).
Commit fa8492f reverts that convention and restores the correct pre-deepmodeling#7664
physics (verified: Mn3Sn recovers the 120-deg AFM ground state, lower energy).

scf_u_spin4 (mag[111]+U): force 14.360->11.332, stress 4334.0->4697.8,
etot -6789.142->-6789.282 (the deepmodeling#7664 bug raised the energy by ~0.14 eV).
scf_out_dos_spin4 / scf_angle_spin4: tiny (1e-4) reverts, near-collinear.
099_PW_DJ_SO left unchanged (PW path, not affected by the LCAO fix).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 18, 2026
Guards the func_xyz_to_updown m_y convention against the deepmodeling#7664 regression.
Asserts the physical invariant: the magnetization <sigma> encoded in a DM
spinor block (built with cal_dm_psi's convention DM=conj(P)) is recovered
with the correct sign in ALL THREE components by func_xyz_to_updown. The
m_y channel (Im) is the sensitive one; m_x/m_z (Re) are conj-invariant.
Fails on the deepmodeling#7664 convention (m_y sign-flipped), passes after the fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 18, 2026
Follow-up to deepmodeling#7832 (revert deepmodeling#7664 m_y convention) addressing review feedback.

DeltaSpin (was left in the deepmodeling#7664 y-convention while the DM was reverted):
- dspin_lcao.cpp cal_coeff_lambda: revert to lambda_ud = lambda_x + i*lambda_y.
  pauli_to_moment already reads the bare +Im (via deepmodeling#7748) and measures the
  physical +m_y from the conj-first occupation; deepmodeling#7664 flipped both the
  measurement and this drive (y-mirror), deepmodeling#7748 reverted only the measurement,
  so the constraint loop was driving the y-mirror of the target. Restoring the
  pre-deepmodeling#7664 drive re-pairs it with the (correct) measurement.
- spin_constrain.h/.cpp: fix stale comments (occ is conj-first; My=+Im).
- deltaspin_core_test.cpp: local re-impl and GeneralCase pinned My=-0.4
  (deepmodeling#7664); corrected to the bare +0.4 so it stops enshrining the wrong sign.

Tests:
- test_soc_magnetization_roundtrip: add the <complex> (multi-k) specialization
  case; drop the dangling ref/MSG doc path from the comment.
- symm_rho_soc_test: relabel SpinConventionCoupling — it validates spin_so3 in
  the PHYSICAL-rho frame, not the runtime conj-first DM path; note it does not
  pin the DM convention.

Mulliken:
- output_mulliken.cpp: comment flagging that M_y (pre-existing, since 3.7.0)
  likely reports -m_y from the conj-first DM and must not be used as an oracle
  for the DM convention; real fix + unit test deferred to a separate PR.

Not covered here (need integration runs / separate PR): regenerate & report
the nspin=4 reference values from post-PR code; nspin=4 DeltaSpin regression
with nonzero m_y target; in-plane non-collinear symmetry integration test;
nspin=4 DMR restart compatibility with deepmodeling#7664-era files.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 18, 2026
…updown

Replaces the local Pauli re-implementation with the actual
elecstate::DensityMatrix_Tools::func_xyz_to_updown, fed the conj-first stored
DM block (DM=conj(P)) exactly as the runtime does, and asserts (a) it recovers
the physical magnetization and (b) spin_so3 (the rotation psymmg_soc applies to
the grid) agrees with the SU(2) block rotation + real extraction. The two
conventions can no longer drift apart silently; the test fails on the deepmodeling#7664
m_y flip. Links density_matrix.cpp only (no io/mocks needed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 27, 2026
Fix comment

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 27, 2026
These nspin=4 LCAO references were updated by deepmodeling#7664 (1457e26) to match its
m_y sign convention in func_xyz_to_updown, which sign-flips the transverse
magnetization (the stored DM block is conj(P); m_y reads Im so it flips).
Commit fa8492f reverts that convention and restores the correct pre-deepmodeling#7664
physics (verified: Mn3Sn recovers the 120-deg AFM ground state, lower energy).

scf_u_spin4 (mag[111]+U): force 14.360->11.332, stress 4334.0->4697.8,
etot -6789.142->-6789.282 (the deepmodeling#7664 bug raised the energy by ~0.14 eV).
scf_out_dos_spin4 / scf_angle_spin4: tiny (1e-4) reverts, near-collinear.
099_PW_DJ_SO left unchanged (PW path, not affected by the LCAO fix).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 27, 2026
Guards the func_xyz_to_updown m_y convention against the deepmodeling#7664 regression.
Asserts the physical invariant: the magnetization <sigma> encoded in a DM
spinor block (built with cal_dm_psi's convention DM=conj(P)) is recovered
with the correct sign in ALL THREE components by func_xyz_to_updown. The
m_y channel (Im) is the sensitive one; m_x/m_z (Re) are conj-invariant.
Fails on the deepmodeling#7664 convention (m_y sign-flipped), passes after the fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 27, 2026
Follow-up to deepmodeling#7832 (revert deepmodeling#7664 m_y convention) addressing review feedback.

DeltaSpin (was left in the deepmodeling#7664 y-convention while the DM was reverted):
- dspin_lcao.cpp cal_coeff_lambda: revert to lambda_ud = lambda_x + i*lambda_y.
  pauli_to_moment already reads the bare +Im (via deepmodeling#7748) and measures the
  physical +m_y from the conj-first occupation; deepmodeling#7664 flipped both the
  measurement and this drive (y-mirror), deepmodeling#7748 reverted only the measurement,
  so the constraint loop was driving the y-mirror of the target. Restoring the
  pre-deepmodeling#7664 drive re-pairs it with the (correct) measurement.
- spin_constrain.h/.cpp: fix stale comments (occ is conj-first; My=+Im).
- deltaspin_core_test.cpp: local re-impl and GeneralCase pinned My=-0.4
  (deepmodeling#7664); corrected to the bare +0.4 so it stops enshrining the wrong sign.

Tests:
- test_soc_magnetization_roundtrip: add the <complex> (multi-k) specialization
  case; drop the dangling ref/MSG doc path from the comment.
- symm_rho_soc_test: relabel SpinConventionCoupling — it validates spin_so3 in
  the PHYSICAL-rho frame, not the runtime conj-first DM path; note it does not
  pin the DM convention.

Mulliken:
- output_mulliken.cpp: comment flagging that M_y (pre-existing, since 3.7.0)
  likely reports -m_y from the conj-first DM and must not be used as an oracle
  for the DM convention; real fix + unit test deferred to a separate PR.

Not covered here (need integration runs / separate PR): regenerate & report
the nspin=4 reference values from post-PR code; nspin=4 DeltaSpin regression
with nonzero m_y target; in-plane non-collinear symmetry integration test;
nspin=4 DMR restart compatibility with deepmodeling#7664-era files.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
maki49 added a commit to maki49/abacus-develop that referenced this pull request Aug 27, 2026
…updown

Replaces the local Pauli re-implementation with the actual
elecstate::DensityMatrix_Tools::func_xyz_to_updown, fed the conj-first stored
DM block (DM=conj(P)) exactly as the runtime does, and asserts (a) it recovers
the physical magnetization and (b) spin_so3 (the rotation psymmg_soc applies to
the grid) agrees with the SU(2) block rotation + real extraction. The two
conventions can no longer drift apart silently; the test fails on the deepmodeling#7664
m_y flip. Links density_matrix.cpp only (no io/mocks needed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bugs Bugs that only solvable with sufficient knowledge of DFT collinear/non-collinear/SOC/delta-spin Issues related to SOC Refactor Refactor ABACUS codes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants


Back | FazBrowse Home | New Git URL