Skip to content

[wien2k] pure-Python dmftproj driver; remove the Fortran executable#13

Open
krystophny wants to merge 16 commits into
TRIQS:unstablefrom
krystophny:port/dmftproj-capstone
Open

[wien2k] pure-Python dmftproj driver; remove the Fortran executable#13
krystophny wants to merge 16 commits into
TRIQS:unstablefrom
krystophny:port/dmftproj-capstone

Conversation

@krystophny

@krystophny krystophny commented Jun 16, 2026

Copy link
Copy Markdown

Final step of the dmftproj port. Depends on #14 (Fortran precision fix), #15 (non-SO path) and #16 (odd-l parity fix); merge those first. Base unstable.

run_dmftproj writes every case.* file the Wien2k converter reads, so the Converter no longer shells out to the dmftproj binary. Deletes fortran/dmftproj and its CMake target; the build no longer needs a Fortran/LAPACK toolchain.

Two tests run the driver through the converter and h5diff the HDF5 at machine precision (1e-12):

  • wien2k_socfull_convert: wide-window SO cell, full-rank Loewdin overlap.
  • wien2k_noso_convert: non-SO partial cell, convert_dft_input on the SP/non-SO oubwin path plus convert_parproj_input.

Both use a full-rank window. The physical narrow window is rank-deficient (more correlated spin-orbitals than bands; the overlap O^{-1/2} has non-unique null eigenvectors across LAPACK builds), so it cannot be a machine-precision target. The narrow physical case stays locked exactly by wien2k_soc_convert (converter run on the Fortran output, no Python regeneration).

Verification

Full wien2k suite, TRIQS 3.3.1 container, precision-fixed dmftproj references:

14 passed, 0 failed
  wien2k_socfull_convert   (SO wide, driver end-to-end, h5diff 1e-12)
  wien2k_noso_convert      (non-SO, driver end-to-end, h5diff 1e-12)
  wien2k_soc_convert       (SO narrow, converter on Fortran output, exact)
  wien2k_oddl_python       (p, f generators, 2.6e-14)
  + 10 generator/converter tests

No 1e-6 tolerance anywhere; every Python-vs-Fortran comparison is on a full-rank case. The build configures and the test target runs with no fortran/dmftproj directory present.

…CaOs2)

dftkit's Wien2k converter is only covered by the non-SOC SrVO3 case. This adds a
SOC + spin-polarized golden test: CaOs2, a cubic fluorite cell with two
symmetry-equivalent correlated Os atoms whose magnetic point group has 16
operations, 8 of them time-reversal. It exercises the combined-spin 'ud' block
and the time-reversal symmetry path of dmftproj + the converter on a small
8-k-point fixture, validated by h5diff against a reference produced by this
converter.
triqs_dftkit.wien2k.symqmc.write_symqmc builds the correlated-shell spinor
symmetry matrices (case.symqmc) from case.dmftsym + case.indmftpr + case.struct,
reproducing the dmftproj Fortran construction (Wigner D, orbital and spinor
time-reversal operators, angular-harmonics basis transform, spin-1/2 phase
blocks). It is a full replacement of the symqmc-writing, covering every path:

- non-mixing spin-diagonal bases (complex, cubic): the up/up block scaled by
  the +-(a+g)/2 phase, with the orbital time-reversal operator on the magnetic
  operations;
- mixing fromfile bases that couple spin (the |j,m_j> basis): the full 2(2l+1)
  spinor representation P spinrot P^dag with the spinor time-reversal
  -i sigma_y (x) T on the magnetic operations;
- l=0 (s) shells: the 2x2 spin phase block.

Verified against the dmftproj Fortran output for all three paths on CaOs2 (16
operations, 8 time-reversal): the cubic converter HDF5 is identical (h5diff) and
every matrix matches to machine precision. The mixing fromfile path is the one
dft_tools #148 singles out; dmftproj reads that basis with a single-precision
CMPLX cast and a 250-column line cap (set_ang_trans.f), so its case.symqmc
carries a ~1e-7 error there while this generator is full double precision.

Tests: the cubic path reuses the SOC golden h5; the mixing and l=0 paths compare
to the dmftproj matrix data (single precision, ~26 kB) and assert unitarity.
Port the dmftproj almblm reader and case.oubwin writer to numpy. Given
case.almblm{up,dn} and the energy window in case.indmftpr, select the
contiguous band range per k-point and spin and write case.oubwin{up,dn}
in the dmftproj format. Proven byte-identical to the Fortran output on
CaOs2 (proj_mode 0; band-index modes raise NotImplementedError pending a
fixture). Part of TRIQS#7.
Port the dmftproj projector core to numpy: read the almblm Alm/Clm
coefficients, build the raw correlated projector over the in-window bands,
apply the local rotation and cubic basis transform, Loewdin-orthonormalize
the stacked shells (orthogonal_wannier_SO), and write case.ctqmcout. Matches
the dmftproj CaOs2 reference to 4.3e-7 (the single-precision basis-transform
floor); integer fields identical. cubic/complex bases; fromfile raises
NotImplementedError pending a fixture. almblm fixtures switched to gzip
(shared with the oubwin test). Part of TRIQS#7.
Port the dmftproj case.sympar writer to numpy: the symmetry matrices for all
included shells (correlated + partial), the partial-charge analog of symqmc.
Matches the dmftproj CaOs2_partial reference (an added uncorrelated Ca d-shell)
to 4.4e-8. cubic/complex bases; fromfile raises NotImplementedError. Part of TRIQS#7.
Port the dmftproj case.parproj writer to numpy: the partial projectors and
density matrices for all included orbitals (radial s12 normalization, the
point-integrated density matrix, the Rloc spinor rotations). Matches the
dmftproj CaOs2_partial reference to 1.2e-8. cubic/complex bases; fromfile
raises NotImplementedError. Part of TRIQS#7.
The five case.* generators each carried their own copy of the almblm reader,
Wigner-D, angular-basis transform, indmftpr/dmftsym parsers, band-window
selection and formatters. Extract them once into _dmftproj and make every
generator a thin consumer: 2260 -> 1699 lines, no shared function defined
twice. Add isolated unit tests for the shared primitives. Generators byte/1e-6
identical to before (all golden tests unchanged). Part of TRIQS#7.
…sion fix)

Use the exact analytic cubic harmonics (no float32 cast) and call the same
LAPACK/BLAS routines the Fortran does for the Loewdin step (scipy ZHEEV('V','U')
and ZGEMM with the matching trans flags, not numpy's ZHEEVD / conj-transpose
copies). Regenerate references from the precision-fixed dmftproj (PR TRIQS#14) with
full-precision templates.

The port is now exact to machine precision on every output:
  oubwin   byte-identical
  symqmc   1.5e-14
  sympar   1.9e-14
  parproj  1.5e-14
  ctqmcout 1.5e-14   (full-rank window: 50 bands > 20 correlated spin-orbitals,
                      so the Loewdin overlap O is non-singular and its
                      eigenvectors are unique. The physical narrow-window CaOs2
                      makes O rank-deficient; O^{-1/2} then amplifies the
                      last-ULP libm difference, a property of that degenerate
                      case, not the port.)
Tolerances tightened to 1e-11. Part of TRIQS#7.
…fixtures

The committed CaOs2 dmftproj outputs are now full double precision (precision
fix TRIQS#14 + exact Python TRIQS#12), so the converter golden h5 is regenerated to match.
…window

Replace the NotImplementedError guards in ctqmcout/sympar/parproj (fromfile) and
oubwin/ctqmcout (proj_mode). fromfile reuses symqmc's spinor machinery (now
shared in _dmftproj: mixing_rotrep, rotloc_rotl_so); proj_mode 1/2 add the
band-index window selection (set_projections.f). All exercised by full-rank
fixtures from the precision-fixed dmftproj and matched to machine precision
(fromfile 1.9e-14, proj_mode 1.5e-14, oubwin byte-identical). Part of TRIQS#7.
The band-structure analog of case.ctqmcout, feeding the converter's
convert_bands_input. Same correlated-projector machinery on a band k-path; reads
nkband from case.klist_band and the Fermi energy from the last line of
case.indmftpr (band-mode convention). Fixture generated by a Wien2k band run
(lapw1/lapwso/lapw2 -band) + the precision-fixed dmftproj -band on a wide
(full-rank) window; the port matches to 2.8e-16. Completes the converter's
dmftproj inputs. Part of TRIQS#7.
The Fortran stays on the generator stack; only the capstone removes it.
@krystophny krystophny force-pushed the port/dmftproj-capstone branch from 3f38a84 to ae1a791 Compare June 16, 2026 16:28
@krystophny krystophny force-pushed the port/dmftproj-capstone branch from ae1a791 to 015948f Compare June 16, 2026 16:43
The generators were validated only for the SO case (2*(2l+1) spinor matrices);
the non-SO path (ifSO=0, the common DMFT case e.g. SrVO3) wrongly emitted
SO-sized matrices. Handle ifSO=0 in symqmc/ctqmcout/sympar/parproj: (2l+1)
matrices, per-spin orthonormalization (orthogonal_wannier), bare (2l+1)
representation and Rloc, two independent density-matrix spin blocks, timeinv
always false. Add wien2k_noso test against a precision-fixed dmftproj run
without -so (CaOs2 spin-polarized non-SO, full-rank window): ctqmcout 1.4e-15,
symqmc 2.1e-14, sympar/parproj at machine precision; SO tests unchanged. Part of TRIQS#7.
@krystophny krystophny force-pushed the port/dmftproj-capstone branch from 015948f to b1717cd Compare June 16, 2026 17:38
dmat received np.linalg.det(krotm) as the rotation parity, but krotm in
case.dmftsym is the proper part (determinant +1 even for improper ops);
the parity lives in iprop. For even l the (-1)^l factor is +1 either way,
so the d-shell fixtures never exposed it; for odd l the symmetry matrices
came out with the wrong sign. Use iprop in symqmc, sympar and the mixing
spinor representation.

Add p (l=1) and f (l=3) generator tests against precision-fixed dmftproj.
The f-shell projector is rank-deficient on the standard CaOs2 bands (Os
carries no f weight near E_F); CaOs2_fshell.almblm is recomputed with a
raised lapw1/lapwso band cutoff so a high-energy window has real l=3
character and the Loewdin overlap is full rank. Both match to ~1e-14.
run_dmftproj writes every case.* file the Wien2k converter reads, so the
Converter no longer shells out to the dmftproj binary. Delete
fortran/dmftproj and its CMake target; the build no longer needs a
Fortran/LAPACK toolchain.

The driver is verified end to end by two tests that run it through the
converter and h5diff the HDF5 at machine precision (1e-12):
- wien2k_socfull_convert: wide-window SO cell (full-rank Loewdin overlap).
- wien2k_noso_convert: non-SO partial cell, convert_dft_input on the
  SP/non-SO oubwin path plus convert_parproj_input.

Both use a full-rank window. The physical narrow window is rank-deficient
(more correlated spin-orbitals than bands; O^{-1/2} has non-unique null
eigenvectors), so it cannot be a machine-precision regression target; it
stays locked exactly by wien2k_soc_convert (converter on the Fortran
output).
@krystophny krystophny force-pushed the port/dmftproj-capstone branch from b532d32 to 0463e19 Compare June 16, 2026 18:52
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