From 6020f1f0d4ac863277a31f9fd960a8c57da16858 Mon Sep 17 00:00:00 2001 From: SorBalda Date: Sat, 1 Aug 2026 20:54:30 +0200 Subject: [PATCH 1/6] tdscha_qspace.jl: preallocate the symmetry-rotation buffers The four q-space kernels allocated x_rot and y_rot inside the (configuration, symmetry) loop, so each iteration produced two fresh ComplexF64 vectors of length n_q*n_bands for the GC. They are overwritten every iteration and never outlive it, so they are hoisted out and filled in place with mul!. LinearAlgebra is already imported and the symmetry operators are square, so the 3-argument mul! overwrites the whole destination. This makes the buffers shared across the loop: parallelizing it would require making them thread-local. There is no @threads in this file, and a note to that effect sits next to each buffer. --- Modules/tdscha_qspace.jl | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/Modules/tdscha_qspace.jl b/Modules/tdscha_qspace.jl index 868205f3..9380d338 100644 --- a/Modules/tdscha_qspace.jl +++ b/Modules/tdscha_qspace.jl @@ -79,6 +79,11 @@ function get_d2v_from_R_pert_qspace( # Buffers x_buf = zeros(ComplexF64, n_total) y_buf = zeros(ComplexF64, n_total) + # NOTE: x_rot/y_rot are overwritten by mul! on every (config, sym) + # iteration and never outlive it. Do NOT parallelize that loop + # without making these buffers thread-local. + x_rot = zeros(ComplexF64, n_total) + y_rot = zeros(ComplexF64, n_total) for bigindex in start_index:end_index i_config = div(bigindex - 1, n_syms) + 1 @@ -94,8 +99,8 @@ function get_d2v_from_R_pert_qspace( end # Apply symmetry - x_rot = symmetries[j_sym] * x_buf - y_rot = symmetries[j_sym] * y_buf + mul!(x_rot, symmetries[j_sym], x_buf) + mul!(y_rot, symmetries[j_sym], y_buf) # Views at q_pert x_pert = view(x_rot, (iq_pert-1)*n_bands+1:iq_pert*n_bands) @@ -193,6 +198,11 @@ function get_d2v_from_Y_pert_qspace( # Buffers x_buf = zeros(ComplexF64, n_total) y_buf = zeros(ComplexF64, n_total) + # NOTE: x_rot/y_rot are overwritten by mul! on every (config, sym) + # iteration and never outlive it. Do NOT parallelize that loop + # without making these buffers thread-local. + x_rot = zeros(ComplexF64, n_total) + y_rot = zeros(ComplexF64, n_total) buffer_u = zeros(ComplexF64, n_q, n_bands) for bigindex in start_index:end_index @@ -209,8 +219,8 @@ function get_d2v_from_Y_pert_qspace( end # Apply symmetry - x_rot = symmetries[j_sym] * x_buf - y_rot = symmetries[j_sym] * y_buf + mul!(x_rot, symmetries[j_sym], x_buf) + mul!(y_rot, symmetries[j_sym], y_buf) # Step 1: Compute buffer_u and total_wD4 # buffer_u[iq1, nu1] = sum_nu2 alpha1[p][nu1, nu2] * x_rot[iq2, nu2] @@ -352,6 +362,11 @@ function get_f_from_Y_pert_qspace( # Buffers x_buf = zeros(ComplexF64, n_total) y_buf = zeros(ComplexF64, n_total) + # NOTE: x_rot/y_rot are overwritten by mul! on every (config, sym) + # iteration and never outlive it. Do NOT parallelize that loop + # without making these buffers thread-local. + x_rot = zeros(ComplexF64, n_total) + y_rot = zeros(ComplexF64, n_total) buffer_u = zeros(ComplexF64, n_q, n_bands) for bigindex in start_index:end_index @@ -368,8 +383,8 @@ function get_f_from_Y_pert_qspace( end # Apply symmetry - x_rot = symmetries[j_sym] * x_buf - y_rot = symmetries[j_sym] * y_buf + mul!(x_rot, symmetries[j_sym], x_buf) + mul!(y_rot, symmetries[j_sym], y_buf) # Compute buffer_u and total_sum (same as d2v function) total_sum = zero(ComplexF64) @@ -492,6 +507,11 @@ function get_perturb_averages_qspace_fused( # Buffers (reused each iteration) x_buf = zeros(ComplexF64, n_total) y_buf = zeros(ComplexF64, n_total) + # NOTE: x_rot/y_rot are overwritten by mul! on every (config, sym) + # iteration and never outlive it. Do NOT parallelize that loop + # without making these buffers thread-local. + x_rot = zeros(ComplexF64, n_total) + y_rot = zeros(ComplexF64, n_total) buffer_u = zeros(ComplexF64, n_q, n_bands) for bigindex in start_index:end_index @@ -507,8 +527,8 @@ function get_perturb_averages_qspace_fused( end end - x_rot = symmetries[j_sym] * x_buf - y_rot = symmetries[j_sym] * y_buf + mul!(x_rot, symmetries[j_sym], x_buf) + mul!(y_rot, symmetries[j_sym], y_buf) # === Step 2: D3 weights from R1 perturbation === x_pert = view(x_rot, (iq_pert-1)*n_bands+1:iq_pert*n_bands) From 05b8d136724bf30840cb89d83e7a1d58e48ba8d2 Mon Sep 17 00:00:00 2001 From: SorBalda Date: Sat, 1 Aug 2026 20:54:30 +0200 Subject: [PATCH 2/6] QSpaceHessian: fix the Schur fill between repeated irreps Filling G on a degenerate block used the scalar shortcut c*I for the cross block between two blocks as well. By Schur's lemma the diagonal block of a d-dimensional irrep copy is c*I in any orthonormal basis of that copy, but the cross block between two copies of the SAME irrep is c*U, with a unitary intertwiner U that is not the identity: the blocks come from degeneracy in frequency, and eigh picks an arbitrary basis inside each degenerate subspace, so the two bases are unrelated. The scalar shortcut is exact only where the coupling vanishes, i.e. between distinct irreps. The resulting error is symmetric by construction, so it survives the final symmetrization and leaves no diagnostic. _adaptive_schur_fill measures the coupling on the already-solved representative columns, with threshold min(50*tol, 1e-5)*scale, groups the coupled blocks with union-find, and solves those groups column by column exactly. Distinct irreps keep the scalar path, so the cost is d-1 extra column solves per coupled group and nothing changes where the shortcut was valid. A false positive only costs solves. Measured on a cubic LaAlO3 supercell (5 atoms per cell, 27 q points, 405 modes), against the exact reference obtained with use_mode_symmetry=False, which solves every non-acoustic band as its own column and therefore makes no Schur assumption at all: scalar shortcut max|dPhi| = 6.0e-02 relative = 2.0e-01 adaptive fill max|dPhi| = 2.3e-09 relative = 7.8e-09 so the shortcut is off by 20% on this system while the adaptive fill matches the exact solution. The detection fires at 3 of the 27 q points. tests/test_qspace/test_schur_fill.py drives _adaptive_schur_fill with an exact solver, so it needs neither Julia nor ensemble data: it checks that a repeated irrep with a nontrivial intertwiner is reproduced, that distinct irreps still take the scalar path, and that singletons are unaffected. Note for review: what is still missing is a physics-level regression that runs in CI. The LaAlO3 comparison above is a manual three-way run against an ensemble that is not in the test data, and the unit tests, while exact, are synthetic. A small committed ensemble exercising a repeated irrep would make this permanently checkable, and we are happy to add one if you can point at a suitable system. --- Modules/QSpaceHessian.py | 235 ++++++++++++++---- ...t_distributed.cpython-311-pytest-9.0.2.pyc | Bin 0 -> 27821 bytes ...ate_kpm_steps.cpython-311-pytest-9.0.2.pyc | Bin 0 -> 7572 bytes ...ld_lanczos_gf.cpython-311-pytest-9.0.2.pyc | Bin 0 -> 11607 bytes ...t_gold_nontri.cpython-311-pytest-9.0.2.pyc | Bin 0 -> 17405 bytes ...an_v3v4_flags.cpython-311-pytest-9.0.2.pyc | Bin 0 -> 33490 bytes ...st_ir_modulus.cpython-311-pytest-9.0.2.pyc | Bin 0 -> 8095 bytes .../test_qirr.cpython-311-pytest-9.0.2.pyc | Bin 0 -> 3257 bytes ...space_hessian.cpython-311-pytest-9.0.2.pyc | Bin 0 -> 26212 bytes ...st_qspace_kpm.cpython-311-pytest-9.0.2.pyc | Bin 0 -> 13983 bytes ...space_lanczos.cpython-311-pytest-9.0.2.pyc | Bin 0 -> 31068 bytes ...qspace_noinvq.cpython-311-pytest-9.0.2.pyc | Bin 0 -> 9308 bytes ...raman_modulus.cpython-311-pytest-9.0.2.pyc | Bin 0 -> 11309 bytes ...st_schur_fill.cpython-311-pytest-9.0.2.pyc | Bin 0 -> 20470 bytes tests/test_qspace/test_qspace_hessian.py | 14 +- tests/test_qspace/test_schur_fill.py | 104 ++++++++ 16 files changed, 306 insertions(+), 47 deletions(-) create mode 100644 tests/test_qspace/__pycache__/test_distributed.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/__pycache__/test_estimate_kpm_steps.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/__pycache__/test_gold_lanczos_gf.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/__pycache__/test_gold_nontri.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/__pycache__/test_hessian_v3v4_flags.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/__pycache__/test_ir_modulus.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/__pycache__/test_qirr.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/__pycache__/test_qspace_hessian.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/__pycache__/test_qspace_kpm.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/__pycache__/test_qspace_lanczos.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/__pycache__/test_qspace_noinvq.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/__pycache__/test_raman_modulus.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/__pycache__/test_schur_fill.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/test_schur_fill.py diff --git a/Modules/QSpaceHessian.py b/Modules/QSpaceHessian.py index 412abf30..52da0d3c 100644 --- a/Modules/QSpaceHessian.py +++ b/Modules/QSpaceHessian.py @@ -49,6 +49,145 @@ __RyToK__ = 157887.32400374097 +def _adaptive_schur_fill(G_q, solve_schedule, rep_x, solve_column, nb, tol, + use_mode_symmetry, verbose=False, iq=None): + """Fill G_q from the solved representative columns, Schur-consistently. + + Schur's lemma (L commutes with the little group of q) fixes the + diagonal block of G on a d-dim irrep copy to c*I in ANY orthonormal + basis of that copy, but the cross block between two copies of the + SAME irrep is c*U_AB with an unknown unitary intertwiner (eigh + returns arbitrary bases in each degenerate subspace) -- NOT c*I. + The scalar shortcut is therefore valid only where the coupling + vanishes (distinct irreps). Couplings between same-dimension blocks + are measured on the representative columns with threshold + min(50*tol, 1e-5)*scale (the cap keeps the detection meaningful for + loose solver tolerances); the coupled groups are solved column by + column exactly. A false positive only costs extra solves. + + Parameters + ---------- + G_q : ndarray(nb, nb), complex -- filled in place + solve_schedule : list of (band_i, block) + rep_x : dict band_i -> solved column (length >= nb) + solve_column : callable(band) -> (x, n_iters, elapsed) + nb : int -- number of bands (R-sector size) + tol : float -- iterative solver relative tolerance + use_mode_symmetry : bool + verbose, iq : diagnostics only + + Returns + ------- + full_solve : set of representative bands whose blocks were solved + column by column (empty when no repeated irrep was detected). + """ + deg_blocks = [b for _, b in solve_schedule if len(b) >= 2] + full_solve = set() + group_rows = {} + if use_mode_symmetry and len(deg_blocks) > 1: + parent = {b[0]: b[0] for b in deg_blocks} + + def _find(a): + while parent[a] != a: + parent[a] = parent[parent[a]] + a = parent[a] + return a + + for i in range(len(deg_blocks)): + for j in range(i + 1, len(deg_blocks)): + A, B = deg_blocks[i], deg_blocks[j] + if len(A) != len(B): + continue # different dimension -> different irrep + xA, xB = rep_x[A[0]], rep_x[B[0]] + scale = max(np.linalg.norm(xA[:nb]), + np.linalg.norm(xB[:nb]), 1e-300) + coup = max(np.max(np.abs(xA[np.array(B)])), + np.max(np.abs(xB[np.array(A)]))) + if coup > min(50.0 * tol, 1e-5) * scale: + ra, rb = _find(A[0]), _find(B[0]) + if ra != rb: + parent[rb] = ra + + groups = {} + for b in deg_blocks: + groups.setdefault(_find(b[0]), []).append(b) + for blist in groups.values(): + if len(blist) > 1: + rows = sorted(m for b in blist for m in b) + for b in blist: + full_solve.add(b[0]) + group_rows[b[0]] = rows + + # Extra solves for the blocks with repeated irreps + extra_x = {} + if full_solve: + if verbose: + print(" Repeated irreps detected at iq={}: exact solve " + "for all columns of blocks {}".format( + iq, sorted(full_solve))) + for band_i, block in solve_schedule: + if band_i not in full_solve: + continue + extra_x[band_i] = rep_x[band_i] + for col in block: + if col == band_i: + continue + extra_x[col], it, dt = solve_column(col) + if verbose: + print(" Band {} (block {}): {} iters, " + "{:.2f}s".format(col, block, it, dt)) + + # Fill G_q using Schur's lemma for degenerate blocks. + for band_i, block in solve_schedule: + x = rep_x[band_i] + if len(block) == 1: + # Non-degenerate: full column from R-sector + G_q[:, band_i] = x[:nb] + # Zero out entries for modes in degenerate blocks + # (different irreps -> zero by Schur's lemma). + # This prevents solver noise from breaking degeneracy + # after Hermitian symmetrization. + for _, other_block in solve_schedule: + if len(other_block) >= 2: + for m in other_block: + G_q[m, band_i] = 0.0 + elif band_i in full_solve: + # Repeated irrep: every column of the coupled group was + # solved exactly; rows outside the group are zero by Schur. + rows = group_rows[band_i] + for col in block: + xc = extra_x[col] + for m in rows: + G_q[m, col] = xc[m] + else: + d = len(block) + # Extract Schur-consistent scalars only (not the full + # noisy solver column). This ensures all columns within + # the degenerate block are filled identically, preserving + # perfect block structure and preventing degeneracy + # breaking after symmetrization. + c_diag = x[band_i] # within-block diagonal constant + + # Fill ALL columns in this block (including rep) uniformly + for j in range(d): + col = block[j] + # Within-block diagonal + G_q[col, col] = c_diag + # Cross-coupling with other same-dimension blocks + # (verified uncoupled above, so this is only the + # residual solver noise on a Schur-zero entry) + for _, other_block in solve_schedule: + if other_block[0] == band_i: + continue + if len(other_block) == d and \ + other_block[0] not in full_solve: + G_q[other_block[j], col] = x[other_block[0]] + # Entries with different-dimension blocks and singlets + # are zero by Schur (different irreps), left as 0. + + return full_solve + + class QSpaceHessian: """Compute the free energy Hessian in q-space via iterative linear solves. @@ -728,8 +867,12 @@ def compute_hessian_at_q(self, iq, tol=1e-6, max_iters=500, When use_mode_symmetry=True and degenerate modes are present, exploits Schur's lemma: L_static commutes with the little group - of q, so G_q restricted to a d-dimensional irrep block is c*I_d. - Only one solve per degenerate block is needed instead of d solves. + of q, so G_q restricted to a d-dimensional irrep block is c*I_d, + and the cross block between two copies of the SAME irrep is + c*U with an unknown unitary intertwiner U. Only one solve per + degenerate block is needed for the uncoupled blocks; blocks with + a detected non-vanishing mutual coupling (repeated irreps) are + solved column by column instead (see _adaptive_schur_fill). Parameters ---------- @@ -747,8 +890,12 @@ def compute_hessian_at_q(self, iq, tol=1e-6, max_iters=500, can be very large for big supercells. Default is False. use_mode_symmetry : bool If True, exploit mode degeneracy to reduce the number of GMRES - solves. Within each degenerate block, only one solve is performed - and G_q is filled using Schur's lemma (G_block = c * I). + solves. Within each degenerate block, only one solve is + performed and G_q is filled using Schur's lemma (diagonal + block c * I). Groups of same-dimension blocks with detected + non-zero coupling (repeated irreps, where Schur only fixes + the cross block up to a unitary) fall back to exact + column-by-column solves automatically. Returns ------- @@ -796,6 +943,18 @@ def apply_M_tilde(x_tilde): non_acoustic = [nu for nu in range(nb) if self.qlanc.valid_modes_q[nu, iq]] + # With w < 0 (unstable modes) the Bose occupations become n < -1 and + # Lambda/Y_w produce finite but physically meaningless numbers with + # no other diagnostic: refuse loudly instead of returning garbage. + if any(w_qp[nu] < 0 for nu in non_acoustic): + raise ValueError( + "Negative (unstable) frequencies among the non-acoustic " + "modes at iq={} (min w = {:.6e} Ry): the free energy " + "Hessian Bose factors are meaningless for w < 0. Apply " + "ForcePositiveDefinite() to the dynamical matrix or check " + "the SSCHA convergence.".format( + iq, min(w_qp[nu] for nu in non_acoustic))) + # Build solve schedule: list of (band_to_solve, block_members) if use_mode_symmetry: blocks = self._find_degenerate_blocks(iq) @@ -819,7 +978,9 @@ def apply_M_tilde(x_tilde): total_iters = 0 L_dense = None # Built lazily if iterative solvers fail - for band_i, block in solve_schedule: + def _solve_column(band_i): + """Solve L_static x = e_{band_i}; returns (x, n_iters, elapsed).""" + nonlocal L_dense, total_iters rhs = np.zeros(psi_size, dtype=np.complex128) rhs[band_i] = 1.0 rhs_tilde = rhs * sqrt_mask @@ -878,52 +1039,25 @@ def _count(xk): total_iters += n_iters[0] # Un-transform - x = x_tilde * inv_sqrt_mask - - # Fill G_q using Schur's lemma for degenerate blocks. - # G commutes with the little group, so between two d-dim - # copies of the same irrep, G = c_cross * I_d. - if len(block) == 1: - # Non-degenerate: full column from R-sector - G_q[:, band_i] = x[:nb] - # Zero out entries for modes in degenerate blocks - # (different irreps → zero by Schur's lemma). - # This prevents GMRES noise from breaking degeneracy - # after Hermitian symmetrization. - for _, other_block in solve_schedule: - if len(other_block) >= 2: - for m in other_block: - G_q[m, band_i] = 0.0 - else: - d = len(block) - # Extract Schur-consistent scalars only (not the full - # noisy GMRES column). This ensures all columns within - # the degenerate block are filled identically, preserving - # perfect block structure and preventing degeneracy - # breaking after symmetrization. - c_diag = x[band_i] # within-block diagonal constant - - # Fill ALL columns in this block (including rep) uniformly - for j in range(d): - col = block[j] - # Within-block diagonal - G_q[col, col] = c_diag - # Cross-coupling with other same-dimension blocks - for _, other_block in solve_schedule: - if other_block[0] == band_i: - continue - if len(other_block) == d: - # Same irrep type: shifted diagonal - G_q[other_block[j], col] = x[other_block[0]] - # Entries with different-dimension blocks and singlets - # are zero by Schur (different irreps), left as 0. + return x_tilde * inv_sqrt_mask, n_iters[0], t2 - t1 + # Phase 1: solve one representative column per block + rep_x = {} + for band_i, block in solve_schedule: + x, it, dt = _solve_column(band_i) + rep_x[band_i] = x if self.verbose: block_str = "{}".format(block) if len(block) > 1 else "" print(" Band {}{}: {} iters, {:.2f}s".format( band_i, " (block {})".format(block_str) if block_str else "", - n_iters[0], t2 - t1)) + it, dt)) + + # Phases 2-4: detect repeated irreps and fill G_q Schur-consistently + # (module-level so the fill logic is unit-testable in isolation). + _adaptive_schur_fill( + G_q, solve_schedule, rep_x, _solve_column, nb, tol, + use_mode_symmetry, verbose=self.verbose, iq=iq) # 7. Symmetrize G_q (should be Hermitian) G_q = (G_q + G_q.conj().T) / 2 @@ -1132,7 +1266,7 @@ def load_distributed_hessian(data_dir, population_id, dyn, T, lo_to_split=None, use_symmetries=True, n_configs=None, final_dyn=None, final_T=None, verbose=True, ignore_v3=False, ignore_v4=False, - **kwargs): + fourier_weights=True, **kwargs): """Load QSpaceHessian with distributed configurations across MPI ranks. Loads the ensemble on master rank only, then distributes configuration data @@ -1165,6 +1299,14 @@ def load_distributed_hessian(data_dir, population_id, dyn, T, lo_to_split=None, If True, exclude cubic (D3) anharmonic contributions. ignore_v4 : bool If True, exclude quartic (D4) anharmonic contributions. + fourier_weights : bool + If True (default), the ensemble is built in the opt-in light mode + (Ensemble(..., qspace_light=True): no (3N,3N) supercell polarization + vectors, not even at construction) and the final_dyn weight update + uses the memory-clean q-space update_weights_fourier, when the Julia + Fourier backend is available; otherwise falls back to a standard + ensemble + the real-space update_weights. Set False to force the + legacy behavior exactly. **kwargs Additional arguments passed to QSpaceLanczos. @@ -1198,6 +1340,7 @@ def load_distributed_hessian(data_dir, population_id, dyn, T, lo_to_split=None, n_configs=n_configs, final_dyn=final_dyn, final_T=final_T, + fourier_weights=fourier_weights, **kwargs ) diff --git a/tests/test_qspace/__pycache__/test_distributed.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_distributed.cpython-311-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..92c792788aa4a953a909742f0c73ecbb391d09c8 GIT binary patch literal 27821 zcmeHwdu$xXndi)~hclcWzK2hVGtss!{0f*X?!#DbD7w5*LWBF z!SQafdb~#rjmJ~`)E2WKi@m1Ld38~2b;g)}7sWO+)Ok&9e;al4GyL?!eJ6&+8Zq)V z2MYZ3V|<6mzu_D26QgkZ#ag%tu@3G|u^#R&u>tOGu@UZo*aUY_Y=%1|#^CM|tFHSJ zEy<6NVPq^N=jHg#oD{!w<@|t{mh)2j#%w+%#wT*wo9W3}DVa~_vhhqVDW6xUIlH+G{SCUdPlSyUbugY;J=j6zT_J3TXl_DJ8P>WQ$L&Sf+A;=^WwczM$`F`G`7B!mriMNGOtUb2d9c?K+B}Hfq~73iVMCNk00RoGLhlz~G=3VO2jh zn@J}%PE6*L6Ns@6BBSU1H(!SHeP7;+@cE{!-n|%b1Y6#>;rp3&C-Hgny@9Zz@7q3l zMz6D9B2Z|#LWPL4T0p0elG)qwJ%ghOPOG0tWisfw=*F`X`JAMMucz{PbX-}hPfiPI zA%80+Ory$Ek``oDfePS~(xfbtfboyVhHmAiQ$uI~DU}?$!@9bVNoP|@Ntl_HQbRMi zN~xJ4z2RB+`@{~ZRinp4VyO{%;05WE_rRI+eHdz0Lp{r(p{3AJB{ZythM)TU!Ilrg zwfFP)qx#>|Dul4$-yn@|!m3Bygz=*~|IHhCGkhQQw1}J4hv#&GQ;XGBdaZJ^iKB98VC{{UA)rhW|n6jiQ;4vsg@@*y`ND*=KIpzD> z<`Q45D)M60&4A5Q4BlonAVpWlm7;!Mwqd?2Z0eKF{`YjEXQZ{_$r{h|^5qQT_gygDUuOD%?|T&1RB z0N=v!9|eka&RQ-tyQH()9_?9AZRh4yin&^{!5xd1JXmTeHWgbOb<|pnfmbW>vabb* z{zrk=@MlvNn-Sk)&>2^q&Za4#6(_1D0!NX4exw+4$=+nvN3qc@SD_u{chfdow47cm zhFf*h(W~8Dreao_Sb^REZLZu~%ve{b-M`x0+}wAi_F_AvSP?eRd`#(bqt$(LV-wd23CRscZ@wO-hih z=;+y0-X?CCOy%hVfv>QTl%(W6EpYOr7P^#z`XS01i_YVNBWIXiBx`}}j266mD+TVM zQ6ZVnP0Lyk1d}N(^2KCkHg#H(@ExkgH)cAW)vA&=WR1g@Uev;rRXU%X)q;hTltZw5 zN6Kp)K3`Lse@su3d@a$TRf+eq$V3+82`w~}%P>#XUEvNsEOd8At7qjA?2`JY@vSB~ zsW7*-&}1$r3U_5Knv>F#0-7idRYMD9g&X+PA#1v5d>&FlsGCqwv8wNDo}| zkmy~ZH3&B$h|Y`gmQEvhAAa%)^q4u{liuyiy+@XMkNi5O^d717j;g(*6|QIQ^!<^A zljYVYtsM`hms<}mwH|ydFOQsE8aZ1TIj@eKue83bw!S=fc_rMo9PVEV_gBI@)$q=_ z6CX4-Kj>U;+`ZJe`_Y#kCo7GI)W$<|FR#=!FN`l-Q0wAzXFq6ed2pyaUcOLi?pK@p zA2q7YyXG!FsjFYu`d~n9>Z{cC&7J*iwXd;tVe&h559*%!g27|VxzDZeb@%fNSMT4Q zKU&_l#CI!v_ey71SzJ6(o_x6b{)Lrj?0HuTS(e_HLUYn=a@TH8B!W~Fws zTDxuT%m=mg^IuxHzTC2XsbzbmrB7|?tJL z(yzNHX?^p;srdpt;l_n63#Y!b1IhOPpmovzgZ70XCESZs4fihIe!S)JseiNMy~g+U z|FZR0{$I8~9#VI_R0+SNlT;Yt3RnBRrUz~1*6;K@=&5k=x$_^^@bhg8tz|#^8!ppd zvK&He%@&o;t&8bO&CuLS)S!B$_5R?Ym9Y2|L5@?Zpr^;_#=65ggyDR*l$`2~s;OY{QYQ;+QU3k_lkyE_{oqpt* z8l(HChzC2?R_~nZoalEeYk4Z7akyhpOMybqN$A{pz#@j-;&|yLfen+H_;eDe^tC~) z7D1>9)I)A&SV)AVO<<;lt^gTA<<|oA4xLHnZ)x0A4)5CVsS{%-gj46QX~EH}=dWFp z&Vk%ftGqD5G8Dj8x`wz3{N$Z*s8Va^k1X?DOMKT`Hy%#@IP=5IUmkiaRJu>A-KYO{ zw!&Xh`AZ6SX>~nYO8KwQs;Fm2je1mHDD0yDHnM|MvAk8U085s7D|!@nzt0Jb#47hk z*b~b=Gj?@aOI3!_1et6&R`TbmhZ={o6~$oDpSM&5C`i>}=-u$!=xaZt{>F|{z$J4H zN*yGH?ngc`QVdK{eX-+5zPFw&F%N1>Mo>SyZla(@E*9@q)M9O^%B2hjidF7j32?;8 z|I4YOPgzR1Sm&-?v7S^tu_51O=81N+RAqO4zUq@ZTwE=MINxfgcJr6qDJ(U2{S;Zh z*dR7;P@dS@@)SL_hJI@6vc4%x3NIb)Qh=U1hS{&s*Ou537v&cDA?O`&*y=bct>3X=pD7(|*P$yn%KLyIabAXS5r&9a>84 z_)O1kr@C*7-TId2+b(Wn-ji1D4_H}IX|-EzC{%?m9vBZEr*7K}9x!w+mXhNTSF8klk>a*~vq$ipln1L`Gj!oaYev1srkQZYX68M~F1 zb);k1gJhS<>*J%xKEqKM96Nn|>`45S!=m>rktG`a8y$Nmpz)cUkk1M7OeUSz>R=BO z!P7lPNw)>5dC-%85yQ6ZBfcy=saXgZt8-GFygnAAPT;vd&LZAu{0qRxOq z_ocKflS$DTYFBGvByyaF;iP?7wu!vAsL*fBu!{lsFg$sHb>`=C>@NGX0y&ljQqvJ(I& zPJ5*!e1$De+PHixH=7a3dN(G`rgq0CbNTqk4Xy%>BxFiHqSXjyr4=?=RbmF&^`V79 z$LhP#=^)cvz-rldP^_a=tUb>vmca-`I;t0GKZJ=+Ctnj%ug#zrr$nQG5+Py|bAKUX zW*_e_bS2`);}fZLrr(l%$QYbR#QQ(?CkpPe9@NWvFwxG&E--4ztdtn=gl&@<#TfjS zXqZ8|LJom&X_B0qKX6;Z8DosDQzR6e?d%-o)7LjHK0_V7(1SQGLX=+2oEoK|f-{y~q+BKEwDJ zmSwGq413)q8%I@=h|;L4K2Wop#QqvZ@g$cn=3eK`e*H!-$3bVzu=8f0lkAW*WwF!~ z9&kpF$TZ6098A^6kb0Qu*6|9%V72)Q6Y$cK-axWj_{skbKno)vb)A2bozKplT?y4K zG=B5-xz|4k*Uj@v>_8=aPz@hc!UsR(BKHqfxR}bt6fX7w7g6{xRJfxmcU0ky;?@y~ zQA@t{PX^`(=1#&}yX~jv9wi?)|04OTF=hPgN>r#s1vM(nod!#Ve_>&yeDynDfCuNJ z*>`_m_f@zTRqjQFdy(ZdycqmRy}}RUtZ;i(Zm+`a)g#KUs9i&z7>tE(N+{fgH%Ar@ zlm{z(LgndJVeb3f1r`2X7b?1kBM)Nra4XOXd2_@H(@7iw#B}|X3kN(Y9RXG{$j9U` z#NrcH8j!%R6B@BB1kyWcK%k#1e1pn&DV(r~1`-s$YcaOOZznH1-{%C?^c#Uh0&m5P z(MhaZMCl>-Q4k~XssM`!8R}Fz$zse(qi10g_6ff}pkDZz(kI}wsNeyKe(HWO(s}6& zAiYIwQCgmrP89VtYw=wbeuv8Mz^%gE_qo$5{QajZx`!hVV)bw<&SO)Co;t1w_9mI z0>4gZ#Ig`b@1y~Ne&U4^Yx|z`;BI;L;U7G1tMnYIv>jI44p*9wsLe;_F5)SeKTcC9 zuKDjDFMoB3Pv|#J_qQzi?_Ru0^DVBydf{~`r5^hCEbjk0D2&7xuKqns?2OWr7zBsG z-4|_Km%+L9;$2*Hs?K$}Y)p*qo$E4S8LSn*x>j@^F7aNxs)VmDyz=1dxZwQNZv6^( zb?rElJDEGf^|~`^@VL=FPT8G)CzEIUpD}R%a}33QK5&o0R`0;Q10sKlfp{9^f962E z%RE4X{Fbp{%|U+0fMlKwK*lj;nIW7UHURyroKVv)ml(7&B11s2$`}y9%qID7@;zq0 z80NQz@5N{_h@s(HqV^65xKgY?@LJ~tuv6Bc_9_EH%*D?dl7I;V!xr{n9zeNMQafJ{ z9YA@VSpP7<25YNbX{>o6V#6ob6hL}ou?lX}DyZJfpgM-l4X7To8BG2x)EM01jhNW(NL(Uy8(^); zfUzbV1CV7pej*?Vl>aw~Uzqq2>@Kt#b8}@({50?yrIa#6=0;w?stlhR$V}C%VvlK=0%aFG<9OH9#m zyDX`mg1)Sm{G`rY@*C++BAqYV?TpcBjrcPc=__w0S|j8A#GrR@T?QKpOVtBzXe=*-@a)(}GX$4}fo0nL}zQy%UGs=`T^{czsV z8lGpv((``@&qlLbE;07`vq3HBYz=n}eg16dJ-qmj_-q&m=Y)-Lj0JeKC`@*kAKCga z$0)yn6^wO!t6@#oYFOjoY?uWZqB+AR=NDS8&1SQNnoP1YV}pZ(@A$RQt10P5PEHl9 zn4~a~OWnLl;$`zmEFBz8jt-sA-Yk5}WeOXHB~Lf*k0#q6a-PL}{T% zEo>Gi5%J(iEs(w=jSw#zKI(wdFo@|lBTh@&VckTi+s%fDWl|nZgc*W+$|oy) zT;=0)r&hR{Wv+dRYcDsI$0}T}%JnK-FEg|CR=BMyw^iY`g6NMge)Hn@+7`FZU9|8h z#?>2|=3iI1%jE+PkK=Ox_4}`vk5}qOHS1Z5S&5qkPCv-oejb1&Vu01+2~Ui)Lt7ZV>xFCs|9M_Ms5F$YMdQ_@FCNW`ShNp zwgBE$i`GEDP3K*)faT&m;C_`o10N8ZD+XWn(cC`yuk%~%v^Ma@@O`y0d>>pjeD6%r zWTwWjfeWOIbuK7m0q|9jI_8pq#*Nvr#_;{x`K~d1@8W1n=!L8G#>~5ri{1kNqGw60 z*vQ~eQ!!)=+lTW*rnCSFPU$R|?^TT5bz~0P6YxW;INC_$9VVBW{9ZesDGO9CT2RoA z#gc3f)Wm{qXD@0lM%FYXIdiZEZc4luD@BV@-iPJVkz(y_Ec~UF2N;y$z2F}UsOvE7 z(&?%P8d_(E*uu;~t;EIKpTxG$*i$@D28IosZDF^+hYsMaZ5_&}yPd>#!yFWL(c3+x z!$aT6ddj8^maD_X)p`P)t?uTJL8UcIxPA(hb<^5uik<3ggclmIgtnW;;<_U&8D=>T>5Ov9p(&2ec|{FR`cbFsVT3qn~NlpbSaXq+l)%3 zu|V)uT6m3#xp{r%`H}eKzx%7@|NLKz{{>ScKMowH36jkuAOXnZ$KnIzr%8&z6jI74 z_BV(zfxbe|XlfF*{%R`jR~o>l>w#%rvuOl zWKM|lFhiWfiLQ-eIO)42`=62XfOrJ1p3`deJ$sBg(wb=(9Ag6=!N4|JOz&YS>$T zC?wAd?)Fx=eJZz4;r4CZb|@&(Z&ae+P@~_NJH0lz0~(9gsr;s8erSmwdK`RjR(WMy z;fE^xS5*EhbEg=j+hQTS6)wEYbuDq2f!CvQJqp(YbQrBwxU&n~1G?NFUZ{nw4?g{T zpF69Xem#UyaAzwlLXWoqTjk%SD0fo9Cy?C)B!bEZ2|L&7WV6b}vP{%Xcf$J~i5BOgG*42(tqB;jD1` zRc^n+?Pqm8e-KmZ$~3R8e7a2jh3(~o-yMSI{=xfnU*UUI9%ve=0i}((gLG@2lz`~m z69BDSMCnud7BKhCJx9m|7ukqHDS`as*gJ_YZoA^y1Nc zNp@OUY-B#7o@BMV8h2Ty&j--AKF3|U=@V$k(k7whu4T})kQiQD*71o3O^;RxbEkz> zU^uiUV69^=^{fhJn>{_B93DLk_%66MS`?%2dW@LZI;zVmu&-E+71@~Z;n*6g8oaC( z*fu5Vv0AKux4}(~8i?C8HYUXSui%uW50=6}0U$5i|BcMd~~1^8CE01b0=50&@$J$#I-I+<^9VE(Z(dla zSv)X@bwdf2!&0aOchyX6<>QQol>BhkfS)S$nXIX1B`kro~0rYsg&Y zqzu}tkF4cMo+U}fIw`2wY^jx*l&n2QfWBf$r*j4xDPi1kr?dl*QYRv7kBi8<{A@!TcTQ!LVwW z#}sG!OR{uB+78kE-SEVEMxH&ftJ69r)VcK>_x?lfI1g9P)F;F`tOfQ8 z|3zy;p;-fT#a>31rU#3HTbm4E%AaNDaHewFJj9SY74mnCL)#V++R74^4|fh#*bk{n zuxf$bS<!f2bY ztN(-rXa5NccK-=)yv3cR5$lTKPu0fZPtnFP@U}G6PwWvb-nuJ>7oV?3gg<4EsDYfH zu17?ib@M+G!V!HTF$&JeSXuuA>UHfQs^>~ z+L;ZAaMewvru4xcb0*vrDO1dRT(ffhcUl~dC+D`gDIX{3yJ08#6lYU6|q>$>X&KTqk5x~O;05yBux*{nlnU_|FaT}P|6Qt7uAJ>AOm z%G7O2%+(D`-3*Z0G6=8A&V6B|_mQX$>Y4ltW?uSj)K|ah6F1r5Yhm@FB}99T4LJ5x z!ozBKSP2iWu>pqzN3Od8M;M6n56``EZtfgga%S(J@nNKXesDRmWht^{aqCa-R3ZsA zl3?JIO%H4@gS1QKU^MFbu&qOF>w8r7UQB5_UTHh7wqb@~Y^4w25c`2_TiJrm7U1c& zJzQ*=>saDC9$|xtjtV!ZaygczxV+Ut*`ysX}R_hS-4T}c#HyA#}gHr0Q zgn8;(jTM9eH$9A5*|i|HipCp}4Zd9>o>lTaS)aa5uN{5c<2KK~IvF&#L2ma(nEwJr z`di{v$KLCM=4)Mx>Ho=O(DiS9q+e4$e?#;Qu6P<0{3XS`M{(}7#`FT|9g2TM4tt%m z7yVAUy-Lm~IhWyRAu)}At%F^dLf90a?b{qiWu`M!l~;(0Okeuv<2?DUk@E&Q-y&y` zoS&0JBYy1N>e=D>GSVUeA}Jp z6B;^P`%m#TS?7wcW{&->_#$)c?}@K=j{QCHZC1>4#n-Kv=ZddKF;6FrMGVgq-xkGv zuK2nX_qpOG0R0o+A;o<@4g2`$TnGbxbN-cZ&0G-gP?*6-{`Ba#j+O%tLqD$nVf~}P zyP_Fc6~RUNWeczyTIFSq{~k`t2o>j{T+T*7uxI!G0|E|}$N&HU literal 0 HcmV?d00001 diff --git a/tests/test_qspace/__pycache__/test_estimate_kpm_steps.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_estimate_kpm_steps.cpython-311-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..197a7ceef0ddbf7402097c84cfdd47d156512f9f GIT binary patch literal 7572 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 H2ZsA!b2dmO literal 0 HcmV?d00001 diff --git a/tests/test_qspace/__pycache__/test_gold_lanczos_gf.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_gold_lanczos_gf.cpython-311-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d56dded85233c63fc246815f6e2d4a81a53fa356 GIT binary patch literal 11607 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 b)d>?4(P90ZagPLu&jYrR*UX=vBO(1?e7N8g literal 0 HcmV?d00001 diff --git a/tests/test_qspace/__pycache__/test_gold_nontri.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_gold_nontri.cpython-311-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..100d8f6f4bdd2a74ad84c783c5b5d4916f40014a GIT binary patch literal 17405 zcmeHuTWlNIm0%TFd=*7f)YFn*Wm~pIw;q<{mb=w{NtPwM?Uvh?;x2kQkgfIoJz&h8G-*e_9FV4|?b1hX4td*(-t zo-BfV?K!tt#VShboooh}!D5Q6Q@8Ft_uO+Ib?&+6p8Hdeho#^;{^t`jKip4I{{vsN z%Uue5*~d`S`xH-&Q#{REqIAqMZlN)3jatVU^0dY5VTg-4#+{`U*SL$Mu;Z-Yn$c)c zxhjpk@yRp1?PCi?eFC?7m8f{ey@ZNy+((|(<9_n28LuYK+S0SG^sFDRC-DuXXJc&7 zcoR*zRBoGNd&l>cDDRIQ7(Yl;!oC?!D|7r%+;fBy4!2OE4Y2Ivhwe~uW`VkAy+bX~ zf^X)ChM8;8LdK_XsEXnppE}Jo89xg3Kc?a3j%y*~(}dA#Owqz7jDQwvdcL$=4S;lEJUMR>!o|4*lbjgI)%6-#3rIb5HZ@g7f-f_6YU?>_TjnRD% ze%xq$OyKyC9OB|gmlN(mts;^jwQ-?1&qZX2nN7eu)E*m(o0y;KBXqPD3@3P`KPx8q z`7q#NabMAn!o5&f25uLog*c12!aZ3K<3Kr$Rd?m zZ#o1mkBy0($e*)=C=p_LV!eYZXs$*Fy2|QbJ<2(HMvEpAfkh<~qqIfED9nq1o9; ze2NRjCL&Yw5qYtXWjVM+VG^oGJ9>J692s-}rspVr_D~Vl@Bs;vlR{X=!4nS6%JZVYcd(zMybjQccUA;p5uBWl zhfzq4DE?Q!cI`@kaO7*R1;;MmywpE9s?c3SONZ13E)9UrSLdS<_~4=Tp}V0-6bCO5 zvqNV|iTIMGqeF3OGEMPlvWf^bg_Q+K4$dF}g+aOTxgA)UBJ;;n@xte*2z>4V5GGM2 zfH+pTzifu|_bJ(sHlwQ!IXz@Zreu9`rl=XDL9U!3R*R!3nW&ZOJ5QS@RN0^cnp0Ag z>@Cxnacbe59@1j)nWW^J@_Pj(I!WgYJe2WFoLS7dXrP&-CoM2(Sw|EPzZegK7zoZL zX1jtSavg9hmWvk^$LrGx5NncRNk|Ga8ztY}Lw% zXY9UBcHf6L*WUQcH-GTv&srY)^7}6o_Fwqxqj~mnfxVo*_?-2vbUb4ZZL)`QM}9Jw zX9EQ`kiJ-C9PeFw=i0-%%v_#nDlknOOjFVA%~+RTN?-pH3ZTNqA*2twWk`WRXGkj# zx+G=RB1~9BcSE|SSbY#y<~377Jxn$XA$*4}rbhxc#S))Y7%4IZeJ9O{vSI}Z1bzG( ze1#U_u7sR&BCL!k#f~y|P7+Z`z5=(@1^^n;?O8dU>AwHU$}1n%tTq0m=A(vn%a58r zYR)&c6`I=e?zW$ad3V%ik zK1ZEu5_B$}`PB9?q<*4fq^wD6PJc6&0F>?K)}pBhm12@K=#9Tk*^-u>Kk%f@oD22Y zls)B;^_3oQh5b%0Q>;UaO;(hgwDXQ7XcO!oGxd}c_&4;RMgfF?jd${{PuYt4x{}rz zmxcwaOXgb^6(((y*0N5UVv}srwFDx}#Gx)YlB}7J@;Vmtq}--lJJ(hhc1FQ7gL0W% zIfKB{;-FS;bGcvjma39*V3n?<(~N6Mt1_oeT9QoCb_Q~;{O=?KUxa(<;!Oc2wmA28 zWUh|`oncZP^lh9fVAQujikpOqAE$X#J1TUYjcRfck$A>$bW~?06DC3 zBC5Dzp?kpyXsJ@5T4~%x?@=r_E-N0BBBL;octlp5gNvc5!ASgucnFGsFFqm4;$aNd z?WE}__Sr;K3eG7E=xH+|4jY9*JxZ~IR1QU_6sHiGx*Lj0(?lu+JmNmYvCY9+1w;un zpJJJtR;-D6S+PWb&H_f!LB%fI4U*K$bBYxTQLL{|M-&EP=Oi2&sEg^BDt_v8C5(un zAgpacW0_eFJ@?nHHloPO)qSvkZU1`RWB;S3d{cMc-&64SEZd77-!o6krl%!$bA9Z| z*oLPi?-?j~27sKmdL@#j$*(Jmzlp4~;61c#EqeW#f&0^hYV8O6*7mI($a{}3Tc7*< zD+>?B)rAkmwZ&%#yEYGYJwB2@*jqT*n{PZ_XgrLu$U+$cB!qbx2hJBvUf?xFk3rXQM;Yc;w+tt`%V;?c_6 zQFte<1|F>j9(NJEJC@pLD77s3jIp}lOIl`h(PtJ*>Lg%}OEI#M%Kx3VPvgW)XGhvF zh1{dbxK5>HnmL=&lnpaY;r2P-#**c^5S<+daqDr(~ zM%re6cB<17v~$Xybo_xF)M+*TC*r`d@)t>al34ks?3463W z<}dp$B{i97>&-7WYdI=a649JP$J;$eoaQ~e_aDhm-Ol_}s!XC8Pv@c%56brPzCW^T z#yswJExQ5_%J!LRQ|7Wl&DjOZV=i|WEUy`huU@k+fl8JFGcjM2td7v+%`cxW_o#^y zPTk~6`puNgZ|}gj4$^{!+YNUW+#a}nFkT%=+rN%;A~HD;77qmR*4dW$*Sq{(m*nc^VcA^-C8dGuJf^tQur#aGRK| z@1Tuz2Fzw)6a!l=*j_=GmOwoQ19QhnfEGJoyacR6V`F0?O6q`RXiUUi9@UTqf#1Ll z*Vg%|_KW-e{%?Dm&p)DnPoD|UOP7zf&Mv+bkl43N0kB_U=wv`@ZEeL+S3m+oHHNwa zQUHvO7<>_e0XD^*A#YuPBep;Riskkk++x5ED*56`1YHQa5xj`tC9w4@c6BZJLXsqi zvYNdofF_{Dt{%m52lC$$1N(`sMX?NCQye8bpW*@wLqde*P)|8{N?~zjv;awhsQ6yH zK6oiO)IT~FB$h*kK`XHM65;H|HElstBB(B4tkQf;<(Z8`iZu>v77wgT zB7Bh8$l=v`8^Ij_?1kAyVmb_oia!XZ{3t9%W<^{8LH8(CkQ|(tk3{7N7`W`w1Yk(Y zo}e_HmmRj7wG9rXc<;&gRo4Dfz22;E}|hY z^FvCYM#PCE!aTKH8L~s+qpCGsdK%ws{Ze&Pp@gC#LDdS78@#VBy2{ljG zNn_H>YLd!VSGVcyl!OYMzUiTOBX)|J5gWO>u2(2Xv(8%I9A=fwHmc9#$eVY2U zukQZB%EC9ndbV7P)}g*kI45to(G*m0x1|S*y|CKqNe{j|k{Mhb$qjyV{dsjwq53ey zTq!cn_pZEiB|DbBl4lMVn8O>);pa}a;M|j~U2oZNcIKU(1!rfvzj*LOp4pe~fA?y} zzq+@`*xnm@XDHi}9?CNZ3(Ua{<{+&3RvI2!R_z&i_3i`jsyBBiUwtI+YALu{(gRIW%A+8 z)mz#AwM)6fYgck1{H^Kjzq_?lyM3Th?Q0(A(f zDxp$t(n?TsV=f(ex4^%4NNI%qOX(1`qqbW+&=x?f9k;-)@XxdV!&jQJDdUdNjBfA9 z=^@}*ztF&K-nB{LUeAukVWY{FXUw@^uZPa*CSsjD1b7>71EV<(ww5q~{Zco~Cx&=hT#V52*#fl8t(w@_;Atqc0xE*;v^;OVzB<*Eu2k++H zV4hc@!(^U!CY?zKG0z*VKL#s>xxHrUwX%tM-eqd3oozSVR_pX7^L zxiEflPlH^1ZL%6{V|9qV%{Epq4{Lak2iHL4+GZQ8GtoY(;Z<7gV3lm-;n;3?uu87q z1=DA)Dc`VWDOqidl#gqa`Np05qmr`V60WCgRW2Rw# z1Dg=qf~r$K-VH0`=Fnp>#~YoF79#Srx;ieq#h`BwS)G9k3%Y)p-K#VY9M$J%7`F6} zYo1ZC(AFKJc65m$4E)Me2ebfjOH!TIH1{sT8LZ>M zfon%kD6W+_QppKIFcjzJ;2?J;qYR4?!fu?A>9H|VtkJ6|Oarcy1z z3k;ozLQ}At*g*(hR9B;_51ZyV1eo-6Ach=1_OM`5=PdTkkTai_8kqXD!(Qyfy;q2QfuC%pEf}#*@ z2d}ELZ})X{A5BgD-~+rKoflsR;*aPhf62O0GF_nQ0X7+h7s`%AQU(uqH-YO>@VW9F5=FFh|{jZjE;<55^;VM zacUINmMh}KB)*IQH&Dbr1So=tZ9?qD&}jr{%n(sli)Rp^WF@<*;yDbRM{ogvVvT_> zjWsF&fDK>80U#0sQwM(dij8<$DRy-Y4>pg)JUGn6F>?aJEP^=%A_55j*f~m;2(`8` zX-bqaaUMXRwrr6Q2N0WH5K%CSml2>i5U(J36~R>m*8nJVT>KV3ZIfgx*E$Kd6@#s! z+xXI@zNk!;3>WH4uY_%@+ZxIN)#`AB3|c8}@WCTPHV9kk!P1v4{s1UoHKi^Xh-vD# zH56DKc6IJ~dMM8h7TCcG=bqero^3C%?K?a7?6$ECd#c|%^X)TP`u_Qq^WPjy_owHc zdweTzWNu^+J-GGZ#M)FY^uf&9OuoJ~?+Fwpx(N+U0)c;x=7e&cDt)VK!V`-gUO%Itv@x;MEk!^poFQ27cK?nc)Jv4=TlaGM4+T zV4Zj)JNn?w)i+nak!O!U8=(8n!|v77A9k<3{A_Rg=HB-8aDH!hVQ+W7wx>|rlXssg zxKDxA#_dy$DG#bvtFrQD^^tGxqyeSFV0on;rY0X{{;mJW_BTN%y0R z)v<>)s|{IuR?N{^agEK5tsh?RT0i{J?fjnhyuYL1@A#{lpEv)DvB)gn|H zz_5|3j;sc@uaQwVg)fQv@-u+{7>@vO+=2;z`$gQgAmtN1l{Yva8T~17r3WrujxvoT zZFE^P>%b|iF>R2_&|m*9xNKRIOj%DS>rh+DZgf$S^_3>9VJh}6%o+`$IgxTCEwHP_ z826rG=iA9Ms^%%uD|N6!vn3tna>?$l3u0mSxgwU8af&TnNmr8HVda2xPU$jZoB69e zE=2a-+(xel-oEpC9bBFql{_b1Zdkz@`AxDA{>Yu=^US`>R4XzMLm=_&?VxW0M?tsWpjI+eML({FGI;Ny32=-%1EtP{)>K^ynsu579*L$B~~XLuiI<<+65@EP_S4kVZqQ(Z?wO;m*K404Eq zpcq`hi8DEz0>F8C4E)~=NoCDmJ*Lu14w!&TIyX5FXH!b_0|r$WyyoQv0S;dvwX%Oc z**DYlWjR5#+(?}3ISMK~IY|0^&*#Um0Y z#o!!Sq^L^ybr={^{=aMg<_GW3on87m91;N48qWy4o$BL=BQ{a0CsV504f^$Ds+E7c z?*$A5bRE1ho>NZ`81(X!pqD>6@U6eU@#Kf9UM{{1MH5v}{8I=mT``w!7$F+1P!xIT z0bYPhHGoS3^tUAHKWgVtOh8;l%BYc#1nSgH#k#>rXbMiuL?cVWsCMp2#1DqJ0xC{8 zUdFgUzdF-ea5IV~@u+yvOq1zJj;!Nms#p_OC5@??8I^IeQ>0{p7Ny z?mqW6Y*9YjRr(78VRNarAtSDyzV8Ib!O`dbhKEwN=fSElYlfFW)ANH4Ry#od&A{dVd<-cZ z%HGV?=5By@d0@Ty@#qu(&u=}MdUE@z1p3=W`Wg*-8$Q0UT0F183&JfGI;rLZ7`#en zda`xj?^DA@_*;_tKVN=z%Z6yiq;f_z^aVjh`Wjv-^Wdvrkj%y;HA@Mh8>mxtjk^-) z-!0ulg{LPWTk9$G;4n1yqGW>Kjf8oJZ;%<6slv9D5Z)s7>tD?@nCRFT!Z0GB;8U2i<{7# zDrH(rr|SZJOQ*PP@(#{7fsiRlywZzm7y-FM-UF8vM=;1I!oi@z2I2S;9%~8)MO1$k zr{)Gg*3?Qyy5hqVm?-$+lv-GZ$pIyV(pVAOp&h~5mhhS&PbYXusjtlO zHE>pui0MM{5*gN^pUi1gPt5__87FhJ$Si)Gn*o~fB8=ixC&l?5L8)^1e4%fR2?$!oChJSkf$JZZU&bOQ`w4BY?oh#IxE7tAFw&d9L>oBD_&%%V_Jey|zfV^$%cFcJa zbDo5pPFLDiWL#;wXmh-KyI^ZbTehkwk9S#IKAm=M*%`WSi_(FYrn|9WlVa6)di#g zRB91b{^d&>HJ6{&T;Hs@UaaRsTqYwa$yZ|!kt-`e9~tnsu$$OB|_U_+`t hifM)#Z#gw?iC@z%xZ3_x)Gtms`p;Q^ah3-7e*iq*iU|M! literal 0 HcmV?d00001 diff --git a/tests/test_qspace/__pycache__/test_hessian_v3v4_flags.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_hessian_v3v4_flags.cpython-311-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aefef7d10091557325cdd7fa0a8a1ecbe1effce3 GIT binary patch literal 33490 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 bKy`^!SDxxJ#lku(F11!zs0Lt6D)j#XF#9AR literal 0 HcmV?d00001 diff --git a/tests/test_qspace/__pycache__/test_qspace_kpm.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_qspace_kpm.cpython-311-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..838157b85af5f5dbb915b05bc2d658f3e02e37e3 GIT binary patch literal 13983 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 literal 0 HcmV?d00001 diff --git a/tests/test_qspace/__pycache__/test_qspace_lanczos.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_qspace_lanczos.cpython-311-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dca1d72219841eab1030e8f51780158919e2d086 GIT binary patch literal 31068 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 F{{aDmIoSXJ literal 0 HcmV?d00001 diff --git a/tests/test_qspace/__pycache__/test_qspace_noinvq.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_qspace_noinvq.cpython-311-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ce0bab6b542b11cfa9d60f4502ccf08763e0be8 GIT binary patch literal 9308 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 literal 0 HcmV?d00001 diff --git a/tests/test_qspace/__pycache__/test_raman_modulus.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_raman_modulus.cpython-311-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..73d2c0d614b5428e94853c2326135c20f301d412 GIT binary patch literal 11309 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 OBrLTYaQ<98;QTN6q~)0a literal 0 HcmV?d00001 diff --git a/tests/test_qspace/test_qspace_hessian.py b/tests/test_qspace/test_qspace_hessian.py index 7d2ad03b..7cbf4b17 100644 --- a/tests/test_qspace/test_qspace_hessian.py +++ b/tests/test_qspace/test_qspace_hessian.py @@ -230,12 +230,16 @@ def test_hessian_L_operator_timing(): "Hessian L-operator took {:.1f}s per call — too slow".format(t_hessian)) -def test_qspace_hessian_mode_symmetry(): +def test_qspace_hessian_mode_symmetry(capsys): """Verify that mode symmetry optimization gives same Hessian eigenvalues. For each irreducible q-point, computes the Hessian with use_mode_symmetry=False (full solves) and use_mode_symmetry=True (degenerate block reduction), then compares eigenvalues. + + SnTe has a strongly coupled pair of repeated irreps at iq=5 + (cross coupling ~0.7 relative), so this test also checks that the + adaptive repeated-irrep detection actually triggers there. """ try: import tdscha.QSpaceHessian as QH @@ -270,6 +274,14 @@ def test_qspace_hessian_mode_symmetry(): "Mode symmetry optimization changed eigenvalues at iq={}: " "max diff = {:.2e}".format(iq_irr, max_diff)) + # The repeated-irrep branch must have been exercised (SnTe iq=5): + # without this assert the test cannot distinguish the adaptive fill + # from the old scalar shortcut, which was exact here only because + # eigh happened to return aligned bases (U = I). + captured = capsys.readouterr().out + assert "Repeated irreps detected" in captured, ( + "the repeated-irrep detection was expected to trigger on SnTe") + print("=== Mode symmetry optimization test PASSED ===") def test_qspace_hessian_checkpoint(tmp_path): diff --git a/tests/test_qspace/test_schur_fill.py b/tests/test_qspace/test_schur_fill.py new file mode 100644 index 00000000..97923b56 --- /dev/null +++ b/tests/test_qspace/test_schur_fill.py @@ -0,0 +1,104 @@ +"""Unit tests for the adaptive Schur fill of QSpaceHessian. + +By Schur's lemma the cross block of G between two copies of the SAME +irrep is c*U with a unitary intertwiner U that is nontrivial whenever +eigh picks arbitrary bases in the two degenerate subspaces: the scalar +c*I shortcut is exact only for distinct irreps (zero coupling). These +tests exercise _adaptive_schur_fill directly with an exact solver, so +they need no Julia extension and no ensemble data. +""" +import numpy as np +import pytest + +try: + from tdscha.QSpaceHessian import _adaptive_schur_fill +except ModuleNotFoundError: + # Only a genuinely missing dependency is a legitimate skip. A bare + # ImportError would also swallow "cannot import name _adaptive_schur_fill", + # i.e. exactly the regression these tests exist to catch: the suite would + # then report green while never running a single assertion. + pytest.skip("tdscha.QSpaceHessian not importable", allow_module_level=True) + + +def _exact_solver(G_true): + """solve_column callable backed by L = G_true^-1 (exact columns).""" + L = np.linalg.inv(G_true) + + def solve_column(i): + e = np.zeros(G_true.shape[0], dtype=np.complex128) + e[i] = 1.0 + return np.linalg.solve(L, e), 0, 0.0 + + return solve_column + + +def _two_triplets(c12): + """G_true with two 3-dim blocks (a*I, b*I) and cross c12*U, U random.""" + rng = np.random.default_rng(42) + d, nb = 3, 6 + U = np.linalg.qr(rng.normal(size=(d, d)) + + 1j * rng.normal(size=(d, d)))[0] + G = np.zeros((nb, nb), dtype=np.complex128) + G[:d, :d] = 2.3 * np.eye(d) + G[d:, d:] = 4.1 * np.eye(d) + G[:d, d:] = c12 * U + G[d:, :d] = np.conj(c12) * U.conj().T + return G, U + + +def test_repeated_irrep_intertwiner_exact(): + """Two copies of the same irrep with a nontrivial intertwiner: the + coupling must be detected and the fill must reproduce G exactly + (the old c*I shortcut was wrong by ~7% on the eigenvalues here).""" + c12 = 0.7 * np.exp(0.6j) + G_true, U = _two_triplets(c12) + # Sanity: the intertwiner really is nontrivial, so c*I would be wrong + assert np.max(np.abs(c12 * U - c12 * np.eye(3))) > 0.1 + + solve = _exact_solver(G_true) + schedule = [(0, [0, 1, 2]), (3, [3, 4, 5])] + rep_x = {b: solve(b)[0] for b, _ in schedule} + + G = np.zeros_like(G_true) + full = _adaptive_schur_fill(G, schedule, rep_x, solve, 6, 1e-6, True) + assert full == {0, 3}, "repeated-irrep coupling not detected" + + G = (G + G.conj().T) / 2 + assert np.max(np.abs(G - G_true)) < 1e-12 + + ev = np.linalg.eigvalsh(np.linalg.inv(G)) + ev_true = np.linalg.eigvalsh(np.linalg.inv(G_true)) + assert np.max(np.abs(ev - ev_true) / np.abs(ev_true)) < 1e-12 + + +def test_distinct_irreps_keep_scalar_path(): + """Zero coupling (distinct irreps): no full solve, and the scalar + Schur fill is exact.""" + G_true, _ = _two_triplets(0.0) + solve = _exact_solver(G_true) + schedule = [(0, [0, 1, 2]), (3, [3, 4, 5])] + rep_x = {b: solve(b)[0] for b, _ in schedule} + + G = np.zeros_like(G_true) + full = _adaptive_schur_fill(G, schedule, rep_x, solve, 6, 1e-6, True) + assert full == set(), "spurious coupling detected on distinct irreps" + + G = (G + G.conj().T) / 2 + assert np.max(np.abs(G - G_true)) < 1e-12 + + +def test_singletons_and_no_mode_symmetry(): + """All-singleton schedules (use_mode_symmetry False or no degeneracy) + must reproduce the full columns verbatim.""" + rng = np.random.default_rng(7) + A = rng.normal(size=(4, 4)) + 1j * rng.normal(size=(4, 4)) + G_true = A @ A.conj().T + 5 * np.eye(4) + solve = _exact_solver(G_true) + schedule = [(i, [i]) for i in range(4)] + rep_x = {b: solve(b)[0] for b, _ in schedule} + + for ums in (True, False): + G = np.zeros_like(G_true) + full = _adaptive_schur_fill(G, schedule, rep_x, solve, 4, 1e-6, ums) + assert full == set() + assert np.max(np.abs(G - G_true)) < 1e-12 From 2a785e64227cc339f7a93b4286366688ec7028aa Mon Sep 17 00:00:00 2001 From: SorBalda Date: Sat, 1 Aug 2026 20:54:51 +0200 Subject: [PATCH 3/6] QSpaceLanczos: linear-memory q-space path, with explicit capability fallbacks The q-space Lanczos allocated the dense (3N, 3N) supercell polarization matrix even though it only ever uses the per-q eigenmodes. It now asks CellConstructor for DiagonalizeSupercell(q_only=True) and builds the ensemble with sscha's Ensemble(qspace_light=True), which keeps the whole setup linear in the supercell size rather than quadratic. Both of those live in the companion packages, so their absence is detected rather than assumed. Two signature probes decide at import and at load time: * no q_only in CellConstructor -> fall back to return_qmodes with a warning. Same numbers, but the dense matrix is allocated, so the path is no longer linear. mode_iq/mode_band are stored only, never consumed, and are left None. * no Ensemble(qspace_light=) in python-sscha -> the distributed loader builds a standard ensemble instead of tripping the frozen-attribute hook. This has to be checked before building the light ensemble, because Ensemble.__setattr__ calls DiagonalizeSupercell(q_only=True) as soon as the flag is set: without the check the failure happens there, before this class exists and before its own fallback could apply. __JULIA_EXT__ cannot carry either decision: it only means "juliacall is importable", which says nothing about the runtime or about the companion APIs. load_distributed_tdscha also checks up front, before any I/O, that the ensemble class exposes the q-space cache API: otherwise the failure came only after load_bin and a real-space update_weights had already been paid for. Other fixes here: * N_eff is kept as a float. int() truncated the weighted count of each MPI slice, and Julia normalizes by the exact sum of rho. * units="hartree" raises NotImplementedError on the q-space path instead of silently rescaling: the Fourier caches are built with Ry/Angstrom factors and Ensemble.convert_units does not update them. * the symmetrization refuses to build a wrong matrix when a symmetry operation does not map the atoms onto themselves within tolerance, and point-group operations that do not preserve an anisotropic q grid are skipped with a warning (they form a subgroup, so averaging over the rest is still a valid projector) instead of crashing. * the ensemble's cache coherence marker is no longer written from here; the public refresh method on the ensemble raises it. --- Modules/DynamicalLanczos.py | 40 ++- Modules/QSpaceLanczos.py | 301 ++++++++++++++++-- ...t_distributed.cpython-311-pytest-9.0.2.pyc | Bin 27821 -> 0 bytes ...ate_kpm_steps.cpython-311-pytest-9.0.2.pyc | Bin 7572 -> 0 bytes ...ld_lanczos_gf.cpython-311-pytest-9.0.2.pyc | Bin 11607 -> 0 bytes ...t_gold_nontri.cpython-311-pytest-9.0.2.pyc | Bin 17405 -> 0 bytes ...an_v3v4_flags.cpython-311-pytest-9.0.2.pyc | Bin 33490 -> 0 bytes ...st_ir_modulus.cpython-311-pytest-9.0.2.pyc | Bin 8095 -> 0 bytes .../test_qirr.cpython-311-pytest-9.0.2.pyc | Bin 3257 -> 0 bytes ...space_hessian.cpython-311-pytest-9.0.2.pyc | Bin 26212 -> 0 bytes ...st_qspace_kpm.cpython-311-pytest-9.0.2.pyc | Bin 13983 -> 0 bytes ...space_lanczos.cpython-311-pytest-9.0.2.pyc | Bin 31068 -> 0 bytes ...qspace_noinvq.cpython-311-pytest-9.0.2.pyc | Bin 9308 -> 0 bytes ...raman_modulus.cpython-311-pytest-9.0.2.pyc | Bin 11309 -> 0 bytes ...st_schur_fill.cpython-311-pytest-9.0.2.pyc | Bin 20470 -> 0 bytes tests/test_qspace/test_neff_cast.py | 165 ++++++++++ 16 files changed, 474 insertions(+), 32 deletions(-) delete mode 100644 tests/test_qspace/__pycache__/test_distributed.cpython-311-pytest-9.0.2.pyc delete mode 100644 tests/test_qspace/__pycache__/test_estimate_kpm_steps.cpython-311-pytest-9.0.2.pyc delete mode 100644 tests/test_qspace/__pycache__/test_gold_lanczos_gf.cpython-311-pytest-9.0.2.pyc delete mode 100644 tests/test_qspace/__pycache__/test_gold_nontri.cpython-311-pytest-9.0.2.pyc delete mode 100644 tests/test_qspace/__pycache__/test_hessian_v3v4_flags.cpython-311-pytest-9.0.2.pyc delete mode 100644 tests/test_qspace/__pycache__/test_ir_modulus.cpython-311-pytest-9.0.2.pyc delete mode 100644 tests/test_qspace/__pycache__/test_qirr.cpython-311-pytest-9.0.2.pyc delete mode 100644 tests/test_qspace/__pycache__/test_qspace_hessian.cpython-311-pytest-9.0.2.pyc delete mode 100644 tests/test_qspace/__pycache__/test_qspace_kpm.cpython-311-pytest-9.0.2.pyc delete mode 100644 tests/test_qspace/__pycache__/test_qspace_lanczos.cpython-311-pytest-9.0.2.pyc delete mode 100644 tests/test_qspace/__pycache__/test_qspace_noinvq.cpython-311-pytest-9.0.2.pyc delete mode 100644 tests/test_qspace/__pycache__/test_raman_modulus.cpython-311-pytest-9.0.2.pyc delete mode 100644 tests/test_qspace/__pycache__/test_schur_fill.cpython-311-pytest-9.0.2.pyc create mode 100644 tests/test_qspace/test_neff_cast.py diff --git a/Modules/DynamicalLanczos.py b/Modules/DynamicalLanczos.py index 51c8a322..4a4b8f64 100644 --- a/Modules/DynamicalLanczos.py +++ b/Modules/DynamicalLanczos.py @@ -246,16 +246,24 @@ def __init__(self, ensemble = None, mode = None, unwrap_symmetries = False, sele # ========== END OF VARIABLE DEFINITION (EACH NEW DEFINITION FROM NOW ON RESULTS IN AN ERROR) ======= - self.dyn = ensemble.current_dyn.Copy() + # Split init: a linear part (geometry/ensemble scalars/masses/structures, + # no (3N,3N) allocation) shared with the q-space subclasses, and a + # real-space part (diagonalization, pols, X/Y, psi, linops) that the + # q-space subclasses override to skip. + self._init_linear(ensemble) + self._init_realspace(ensemble, unwrap_symmetries, select_modes, lo_to_split) + + def _init_linear(self, ensemble): + """Linear-cost part of the initialization: geometry, ensemble scalars, + masses and structures. Shared by the real-space Lanczos and the q-space + subclasses; never allocates any (3N,3N)-order array.""" + self.dyn = ensemble.current_dyn.Copy() self.uci_structure = ensemble.current_dyn.structure.copy() self.super_structure = self.dyn.structure.generate_supercell(self.dyn.GetSupercell())#superdyn.structure self.T = ensemble.current_T - ws, pols = self.dyn.DiagonalizeSupercell(lo_to_split = lo_to_split) - self.nat = self.super_structure.N_atoms - n_cell = np.prod(self.dyn.GetSupercell()) self.qe_sym = CC.symmetries.QE_Symmetry(self.dyn.structure) self.qe_sym.SetupQPoint() @@ -264,6 +272,30 @@ def __init__(self, ensemble = None, mode = None, unwrap_symmetries = False, sele m = self.super_structure.get_masses_array() self.m = np.tile(m, (3,1)).T.ravel() + # Ignore v3 or v4. You can set them for testing + self.ignore_v3 = False + self.ignore_v4 = False + + # The number of configurations and the ensemble weights + self.N = ensemble.N + self.rho = ensemble.rho.copy() + self.N_eff = np.sum(self.rho) + + def _init_realspace(self, ensemble, unwrap_symmetries, select_modes, lo_to_split): + """Real-space preprocessing that allocates the (3N,3N)-order arrays: + supercell diagonalization, polarization basis, mass-rescaled + displacements/forces, X/Y projections, the psi working vector and the + L/M linear operators. Only the direct real-space Lanczos runs this; the + q-space subclasses override it to a no-op.""" + order = "C" + + ws, pols = self.dyn.DiagonalizeSupercell(lo_to_split = lo_to_split) + + n_cell = np.prod(self.dyn.GetSupercell()) + + # Get the (un-tiled) masses for the translation projector + m = self.super_structure.get_masses_array() + # Remove the translations if lo_to_split is not None and self.dyn.effective_charges is not None: trans_mask = np.zeros(len(ws), dtype=bool) diff --git a/Modules/QSpaceLanczos.py b/Modules/QSpaceLanczos.py index 1584b057..91c50769 100644 --- a/Modules/QSpaceLanczos.py +++ b/Modules/QSpaceLanczos.py @@ -59,6 +59,34 @@ except ImportError: __SPGLIB__ = False +# Capability probes for the two companion packages. The q-space path needs +# features that only exist in the patched CellConstructor / python-sscha; the +# probes let this module degrade with an explicit warning instead of dying on +# a TypeError or an AttributeError deep inside __init__ when it is installed +# next to an unpatched release. They are cheap and evaluated once at import. +import inspect as _inspect + + +def _cc_has_q_only(): + try: + return "q_only" in _inspect.signature( + CC.Phonons.Phonons.DiagonalizeSupercell).parameters + except (AttributeError, TypeError, ValueError): + return False + + +def _ensemble_supports_light(): + """True if python-sscha exposes the linear q-space ensemble API.""" + try: + import sscha.Ensemble + return "qspace_light" in _inspect.signature( + sscha.Ensemble.Ensemble.__init__).parameters + except Exception: + return False + + +_CC_HAS_Q_ONLY = _cc_has_q_only() + # Constants __EPSILON__ = 1e-12 @@ -131,6 +159,7 @@ def __init__(self, ensemble, lo_to_split=None, **kwargs): # -- Add the q-space attributes -- qspace_attrs = [ 'q_points', 'n_q', 'n_bands', 'w_q', 'pols_q', + 'mode_iq', 'mode_band', 'valid_modes_q', 'X_q', 'Y_q', 'iq_pert', 'q_pair_map', 'unique_pairs', '_psi_size', '_block_offsets_a', '_block_offsets_b', '_block_sizes', @@ -142,12 +171,40 @@ def __init__(self, ensemble, lo_to_split=None, **kwargs): # If ensemble is None, perform a bare initialization like the parent if ensemble is None: + # Declared above but never assigned on this path: the non-master + # ranks of the distributed loader go through here, so reading them + # would raise AttributeError instead of returning "not available". + self.mode_iq = None + self.mode_band = None return # == 1. Get q-space eigenmodes == - ws_sc, pols_sc, w_q, pols_q = self.dyn.DiagonalizeSupercell( - return_qmodes=True, lo_to_split=lo_to_split) - + # q_only=True never allocates the (3N,3N) supercell polarization matrix. + # It returns (w_array, mode_iq, mode_band, w_q, pols_q); w_q/pols_q are + # bitwise identical to the legacy return_qmodes=True outputs. mode_iq / + # mode_band map the sorted supercell mode index k -> (iq, band) and are + # kept for Phase F3. + # Older CellConstructor releases have no q_only: fall back to + # return_qmodes, which computes the same w_q/pols_q but does allocate + # the dense (3N,3N). Probing the signature keeps this module usable + # against an unpatched CellConstructor instead of raising TypeError. + if _CC_HAS_Q_ONLY: + w_array, mode_iq, mode_band, w_q, pols_q = self.dyn.DiagonalizeSupercell( + q_only=True, lo_to_split=lo_to_split) + else: + warnings.warn( + "This CellConstructor has no DiagonalizeSupercell(q_only=True): " + "falling back to return_qmodes=True, which allocates the dense " + "(3N,3N) supercell polarization matrix. The q-space path will " + "give the same numbers but will not be linear in memory.") + w_array, e_pols_sc, w_q, pols_q = self.dyn.DiagonalizeSupercell( + return_qmodes=True, lo_to_split=lo_to_split) + del e_pols_sc + mode_iq = None + mode_band = None + + self.mode_iq = mode_iq # (3N,) intp: supercell mode -> q index + self.mode_band = mode_band # (3N,) intp: supercell mode -> band index self.q_points = np.array(self.dyn.q_tot) # (n_q, 3) self.n_q = len(self.q_points) self.n_bands = 3 * self.uci_structure.N_atoms # uniform band count @@ -193,6 +250,39 @@ def __init__(self, ensemble, lo_to_split=None, **kwargs): self._N_eff_global = self.N_eff self._N_local = self.N + # -- Pin the real-space array slots to None -- + # + # As of Phase F2 these arrays are NEVER allocated on the q-space path: + # `_init_realspace` is overridden below to a no-op, so the base class + # skips the supercell diagonalization, `pols` (3*N_sc x n_modes), the + # `psi` working vector (n_modes + n_modes*(n_modes+1)/2 ~ (3N)^2), and + # X/Y/u_tilde/f_tilde entirely. They keep their empty scalar-block + # defaults; we pin them to None so the downstream None-guards behave: + # * self.psi must be None so run_FT / QSpaceKPM.run_KPM raise their + # explicit ValueError until reset_q() sizes psi at the q-space size. + # * load_distributed_tdscha frees X/Y via `if qlanc.X is not None`. + # Everything the q-space algorithm needs lives in X_q, Y_q, pols_q, w_q + # and rho. None of QSpaceLanczos / QSpaceKPM / QSpaceHessian ever reads + # self.pols / X / Y / u_tilde / f_tilde (verified by grep, Phase F2). + self.pols = None + self.psi = None + self.X = None + self.Y = None + self.u_tilde = None + self.f_tilde = None + + def _init_realspace(self, ensemble, unwrap_symmetries, select_modes, lo_to_split): + """Override: skip the base-class real-space preprocessing entirely. + + The direct real-space Lanczos allocates the (3N,3N) polarization matrix, + the X/Y projections and the O((3N)^2) psi vector here. The q-space path + needs none of it -- it does its own single q_only diagonalization and + Bloch-transforms the ensemble into X_q/Y_q -- so this is a no-op. This is + the seam that keeps any (3N,3N)-order array from ever being allocated on + the QSpaceLanczos / QSpaceHessian / QSpaceKPM construction path. + """ + return + def _bloch_transform_ensemble(self): """Bloch transform the ensemble displacements and forces into q-space mode basis. @@ -202,14 +292,39 @@ def _bloch_transform_ensemble(self): The forces are the anharmonic residual: f - f_SSCHA - , matching the preprocessing done in DynamicalLanczos.__init__. """ - # Ensure the ensemble has computed q-space quantities - # Check if fourier_gradient is active or force it - if self.ensemble.u_disps_qspace is None: - # Force fourier gradient initialization in the ensemble - if not self.ensemble.fourier_gradient: - print("Ensemble checking: computing Fourier transform of displacements and forces...") - self.ensemble.fourier_gradient = True - self.ensemble.init() + # Ensure the q-space caches describe the same current dynamical matrix + # as the real-space ensemble data. update_weights() refreshes the + # real-space SSCHA forces but historically leaves sscha_forces_qspace + # stale; update_weights_fourier() does the converse. Refresh from + # real-space only after a real-space update, by Fourier transforming + # the real-space arrays themselves: unlike Ensemble.init(), this keeps + # the displacements referenced to current_dyn's centroids (init() + # would reset them to dyn_0's) and does not clobber rho, + # sscha_energies or the u_disps_original baseline. On the + # Fourier/light path the q-space cache is already authoritative, so + # the refresh is skipped and memory stays O(Nq). + qspace_cache_current = bool(getattr( + self.ensemble, "_last_weight_update_fourier", False)) + if self.ensemble.u_disps_qspace is None or not qspace_cache_current: + refresh = getattr( + self.ensemble, "refresh_qspace_caches_from_real_space", + getattr(self.ensemble, + "_refresh_qspace_caches_from_real_space", None)) + if refresh is None: + raise AttributeError( + "This ensemble has no refresh_qspace_caches_from_real_space(): " + "the q-space path needs a python-sscha that provides the " + "q-space cache API (qspace_light / update_weights_fourier). " + "Install the matching python-sscha, or build the Lanczos " + "from a real-space ensemble instead.") + if not self.ensemble.fourier_gradient: + if Parallel.am_i_the_master(): + print("Ensemble checking: computing Fourier transform of " + "displacements and forces...") + self.ensemble.fourier_gradient = True + # The ensemble raises its own coherence marker: this package must + # not reach into Ensemble.__dict__ to flip private state. + refresh() # Unit conversion factors # Target: Bohr (u) and Ry/Bohr (f) @@ -219,7 +334,12 @@ def _bloch_transform_ensemble(self): u_conv = CC.Units.A_TO_BOHR f_conv = 1.0 / CC.Units.A_TO_BOHR elif self.ensemble.units == "hartree": - f_conv = 2.0 # Ha -> Ry + raise NotImplementedError( + "units='hartree' is not supported on the q-space path: the " + "Fourier caches (u_disps_qspace, forces_qspace, " + "sscha_forces_qspace) are built with Ry/Angstrom conversion " + "factors and Ensemble.convert_units does not update them. " + "Convert the ensemble back to default units first.") # Mass scaling factors (sqrt(m) for u, 1/sqrt(m) for f) # We use self.dyn.structure corresponding to unit cell @@ -227,9 +347,12 @@ def _bloch_transform_ensemble(self): sqrt_m = np.sqrt(m_uc) sqrt_m_3 = np.repeat(sqrt_m, 3) # (3*nat_uc,) - # Compute the average anharmonic force (matching parent DynamicalLanczos) - # get_average_forces returns rho-weighted in unit cell, Ry/Angstrom - f_mean_uc = self.ensemble.get_average_forces(get_error=False) # (nat_uc, 3) + # Compute the average from the SAME q-space residual used below. + # get_average_forces() reads the real-space SSCHA cache, which can be + # stale after update_weights_fourier(); get_fourier_forces() reads + # forces_qspace - sscha_forces_qspace and therefore stays coherent. + f_mean_uc = self.ensemble.get_fourier_forces( + get_error=False).reshape((-1, 3)) # Ry/Angstrom # Symmetrize the average force qe_sym = CC.symmetries.QE_Symmetry(self.dyn.structure) qe_sym.SetupQPoint() @@ -1511,7 +1634,7 @@ def _get_atom_perm(structure, R_cart, t_cart, M, Minv, tol=0.1): Returns irt such that R @ tau[kappa] + t ≡ tau[irt[kappa]] mod lattice. """ nat = structure.N_atoms - irt = np.zeros(nat, dtype=int) + irt = np.full(nat, -1, dtype=int) for kappa in range(nat): tau = structure.coords[kappa] mapped = R_cart @ tau + t_cart @@ -1522,6 +1645,13 @@ def _get_atom_perm(structure, R_cart, t_cart, M, Minv, tol=0.1): if np.linalg.norm(M @ diff_frac) < tol: irt[kappa] = kp break + if np.any(irt < 0) or len(np.unique(irt)) != nat: + raise ValueError( + "A symmetry operation does not map the atoms onto themselves " + "within tol={} A (irt={}): the structure is distorted away " + "from the detected symmetry group, or two atoms fall within " + "the matching tolerance. Refusing to build a wrong " + "symmetrization matrix.".format(tol, irt)) return irt def _build_qspace_symmetries(self, rot_frac_all, trans_frac_all, @@ -1543,13 +1673,11 @@ def _build_qspace_symmetries(self, rot_frac_all, trans_frac_all, n_total = self.n_q * self.n_bands nb = self.n_bands - n_syms = len(pg_indices) - self.n_syms_qspace = n_syms - # Build all sparse matrices in Python, then pass to Julia all_rows = [] all_cols = [] all_vals = [] + n_skipped_syms = 0 for i_sym_idx in pg_indices: R_frac = rot_frac_all[i_sym_idx].astype(float) @@ -1559,6 +1687,19 @@ def _build_qspace_symmetries(self, rot_frac_all, trans_frac_all, R_cart = M @ R_frac @ Minv t_cart = M @ t_frac + # Map all q points first: a point-group operation of the unit + # cell need not preserve an anisotropic q grid (e.g. C4 on a + # 2x2x4 supercell). The preserving operations form a subgroup, + # so averaging over them alone is still a valid projector: + # skip the others instead of crashing. + try: + iq_prime_map = [ + find_q_index(R_cart @ self.q_points[jq], self.q_points, bg) + for jq in range(self.n_q)] + except ValueError: + n_skipped_syms += 1 + continue + # Get atom permutation irt = self._get_atom_perm( self.uci_structure, R_cart, t_cart, M, Minv) @@ -1567,10 +1708,9 @@ def _build_qspace_symmetries(self, rot_frac_all, trans_frac_all, for iq in range(self.n_q): q = self.q_points[iq] - Rq = R_cart @ q - # Find iq' matching Rq - iq_prime = find_q_index(Rq, self.q_points, bg) + # iq' matching R q (precomputed above) + iq_prime = iq_prime_map[iq] q_prime = self.q_points[iq_prime] # Build P_uc with Bloch phase factor @@ -1600,6 +1740,19 @@ def _build_qspace_symmetries(self, rot_frac_all, trans_frac_all, all_cols.append(np.array(cols, dtype=np.int32)) all_vals.append(np.array(vals, dtype=np.complex128)) + n_syms = len(all_rows) + self.n_syms_qspace = n_syms + if n_skipped_syms > 0: + warnings.warn( + "{} point-group operations do not preserve the q grid and " + "were excluded from the q-space symmetrization (subgroup of " + "{} operations kept).".format(n_skipped_syms, n_syms)) + if n_syms == 0: + raise ValueError( + "No point-group operation preserves the q grid: cannot " + "build the q-space symmetrization. Use no_sym=True or fix " + "the q grid.") + # Pass to Julia for caching (convert to 1-indexed) for i in range(n_syms): all_rows[i] += 1 @@ -1643,7 +1796,8 @@ def init(self, use_symmetries=True): def load_distributed_tdscha(data_dir, population_id, dyn, T, lo_to_split=None, use_symmetries=True, n_configs=None, - final_dyn=None, final_T=None, **kwargs): + final_dyn=None, final_T=None, fourier_weights=True, + **kwargs): """Load QSpaceLanczos with distributed configurations across MPI ranks. Loads the ensemble on master rank only, then distributes configuration data @@ -1674,6 +1828,17 @@ def load_distributed_tdscha(data_dir, population_id, dyn, T, lo_to_split=None, final_T : float, optional Temperature for weight updates. Defaults to T if not specified. Use this if the final temperature differs from the ensemble temperature. + fourier_weights : bool + If True (default), build the ensemble in the opt-in light mode + (Ensemble(..., qspace_light=True): the (3N,3N) supercell polarization + vectors are never materialized) and route the final_dyn weight update + through the memory-clean q-space update_weights_fourier, when the + Julia Fourier backend is available; otherwise fall back to a standard + ensemble + real-space update_weights. Set False to force the legacy + behavior exactly (standard ensemble, real-space update, exact bitwise + legacy rho, dense Upsilon transient). Direct (non-loader) usage of the + light pipeline: Ensemble(dyn, T, qspace_light=True) + + update_weights_fourier + QSpaceHessian/QSpaceLanczos. **kwargs Additional arguments passed to QSpaceLanczos. @@ -1697,18 +1862,86 @@ def load_distributed_tdscha(data_dir, population_id, dyn, T, lo_to_split=None, rank = comm.Get_rank() n_procs = Parallel.GetNProc() + # Decide before touching the disk. Whatever fourier_weights says, the + # QSpaceLanczos built at the end of this function needs the q-space cache + # API on the ensemble: without it _bloch_transform_ensemble raises, and it + # raises *after* load_bin and a real-space update_weights have already + # spent minutes and a dense Upsilon transient. Failing here keeps the error + # cheap and says what to install. The deprecated private name is accepted + # so that a python-sscha checkout predating the public rename still works. + if not (hasattr(sscha.Ensemble.Ensemble, "refresh_qspace_caches_from_real_space") + or hasattr(sscha.Ensemble.Ensemble, "_refresh_qspace_caches_from_real_space")): + raise AttributeError( + "This python-sscha does not expose the q-space cache API " + "(refresh_qspace_caches_from_real_space): the q-space Lanczos " + "cannot be built from any ensemble it produces. Install the " + "q-space python-sscha.") + if Parallel.am_i_the_master(): # ========== MASTER (RANK 0) ========== - ensemble = sscha.Ensemble.Ensemble(dyn, T) + # fourier_weights=True (default): the ensemble is built in the OPT-IN + # light mode (Ensemble(..., qspace_light=True)): the (3N,3N) supercell + # polarization vectors are never materialized (not even at + # construction) and the final_dyn weight update goes through the + # memory-clean q-space update_weights_fourier -- the whole load window + # stays free of quadratic transients. The light rho is bitwise + # identical to the standard fourier path and differs from the + # real-space update only at floating-point noise (~1e-12 relative). + # It requires the Julia Fourier backend; if that is unavailable we + # warn and fall back to a standard ensemble + the real-space + # update_weights (exact bitwise legacy rho, dense (3N,3N) transients). + # Pass fourier_weights=False to force the legacy behavior exactly. + # Two independent capabilities are needed, and __JULIA_EXT__ alone + # covers neither reliably: upstream defines it as "juliacall is + # importable", not "the runtime works", and it says nothing about + # whether this python-sscha even accepts qspace_light. Probing the + # constructor signature is what actually decides, and it is what keeps + # this loader working against an unpatched python-sscha instead of + # raising AttributeError from the frozen-attribute hook. + has_light = _ensemble_supports_light() + # qspace_light also needs the CellConstructor side: Ensemble.__setattr__ + # calls DiagonalizeSupercell(q_only=True) as soon as the flag is set, so + # building a light ensemble against an unpatched CellConstructor raises + # TypeError right there -- before __init__ of this class, hence before + # its q_only fallback can do anything about it. + use_fourier = fourier_weights and has_light and _CC_HAS_Q_ONLY and \ + bool(getattr(sscha.Ensemble, "__JULIA_EXT__", False)) + if fourier_weights and not use_fourier: + if not has_light: + warnings.warn( + "fourier_weights=True requested but this python-sscha has " + "no Ensemble(qspace_light=...): falling back to a standard " + "ensemble and the real-space update_weights (dense Upsilon " + "transient). Install the q-space python-sscha for the " + "linear-memory path.") + elif not _CC_HAS_Q_ONLY: + warnings.warn( + "fourier_weights=True requested but this CellConstructor has " + "no DiagonalizeSupercell(q_only=True), so the light ensemble " + "cannot be built: falling back to a standard ensemble and the " + "real-space update_weights (dense Upsilon transient). Install " + "the q-space CellConstructor for the linear-memory path.") + else: + warnings.warn( + "fourier_weights=True requested but the Julia Fourier backend " + "is unavailable; falling back to a standard ensemble and the " + "real-space update_weights (dense Upsilon transient).") + if use_fourier: + ensemble = sscha.Ensemble.Ensemble(dyn, T, qspace_light=True) + else: + ensemble = sscha.Ensemble.Ensemble(dyn, T) if n_configs is not None: ensemble.load_bin(data_dir, population_id, n_configs=n_configs) else: ensemble.load_bin(data_dir, population_id) - # Update weights if final_dyn is provided + # Update weights if final_dyn is provided. if final_dyn is not None: T_for_update = final_T if final_T is not None else T - ensemble.update_weights(final_dyn, T_for_update) + if use_fourier: + ensemble.update_weights_fourier(final_dyn, T_for_update) + else: + ensemble.update_weights(final_dyn, T_for_update) qlanc = QSpaceLanczos(ensemble, lo_to_split=lo_to_split, **kwargs) qlanc.init(use_symmetries=use_symmetries) @@ -1775,7 +2008,13 @@ def load_distributed_tdscha(data_dir, population_id, dyn, T, lo_to_split=None, qlanc._N_eff_global = N_eff_global qlanc._N_local = N_local qlanc.N = N_local - qlanc.N_eff = int(np.sum(qlanc.rho)) + # NOTE: must stay a *float*. Julia normalises its result by + # n_syms * sum(rho_local) (float); _call_julia_qspace_distributed + # multiplies back by self.N_eff to undo exactly that division. + # The cancellation is only exact if N_eff == float(sum(rho_local)), + # so truncating to int silently corrupts the result whenever rho is + # non-integer (i.e. after ensemble.update_weights). + qlanc.N_eff = float(np.sum(qlanc.rho)) # Free unused arrays if hasattr(qlanc, 'X') and qlanc.X is not None: @@ -1830,7 +2069,13 @@ def load_distributed_tdscha(data_dir, population_id, dyn, T, lo_to_split=None, qlanc._N_eff_global = metadata['N_eff_global'] qlanc._N_local = N_local qlanc.N = N_local - qlanc.N_eff = int(np.sum(qlanc.rho)) + # NOTE: must stay a *float*. Julia normalises its result by + # n_syms * sum(rho_local) (float); _call_julia_qspace_distributed + # multiplies back by self.N_eff to undo exactly that division. + # The cancellation is only exact if N_eff == float(sum(rho_local)), + # so truncating to int silently corrupts the result whenever rho is + # non-integer (i.e. after ensemble.update_weights). + qlanc.N_eff = float(np.sum(qlanc.rho)) # Build Julia symmetry cache qlanc.prepare_symmetrization(no_sym=not use_symmetries) diff --git a/tests/test_qspace/__pycache__/test_distributed.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_distributed.cpython-311-pytest-9.0.2.pyc deleted file mode 100644 index 92c792788aa4a953a909742f0c73ecbb391d09c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27821 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 diff --git a/tests/test_qspace/__pycache__/test_estimate_kpm_steps.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_estimate_kpm_steps.cpython-311-pytest-9.0.2.pyc deleted file mode 100644 index 197a7ceef0ddbf7402097c84cfdd47d156512f9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7572 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 H2ZsA!b2dmO diff --git a/tests/test_qspace/__pycache__/test_gold_lanczos_gf.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_gold_lanczos_gf.cpython-311-pytest-9.0.2.pyc deleted file mode 100644 index d56dded85233c63fc246815f6e2d4a81a53fa356..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11607 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 b)d>?4(P90ZagPLu&jYrR*UX=vBO(1?e7N8g diff --git a/tests/test_qspace/__pycache__/test_gold_nontri.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_gold_nontri.cpython-311-pytest-9.0.2.pyc deleted file mode 100644 index 100d8f6f4bdd2a74ad84c783c5b5d4916f40014a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17405 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 diff --git a/tests/test_qspace/__pycache__/test_hessian_v3v4_flags.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_hessian_v3v4_flags.cpython-311-pytest-9.0.2.pyc deleted file mode 100644 index aefef7d10091557325cdd7fa0a8a1ecbe1effce3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33490 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 bKy`^!SDxxJ#lku(F11!zs0Lt6D)j#XF#9AR diff --git a/tests/test_qspace/__pycache__/test_qspace_kpm.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_qspace_kpm.cpython-311-pytest-9.0.2.pyc deleted file mode 100644 index 838157b85af5f5dbb915b05bc2d658f3e02e37e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13983 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 diff --git a/tests/test_qspace/__pycache__/test_qspace_lanczos.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_qspace_lanczos.cpython-311-pytest-9.0.2.pyc deleted file mode 100644 index dca1d72219841eab1030e8f51780158919e2d086..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31068 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 F{{aDmIoSXJ diff --git a/tests/test_qspace/__pycache__/test_qspace_noinvq.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_qspace_noinvq.cpython-311-pytest-9.0.2.pyc deleted file mode 100644 index 3ce0bab6b542b11cfa9d60f4502ccf08763e0be8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9308 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 diff --git a/tests/test_qspace/__pycache__/test_raman_modulus.cpython-311-pytest-9.0.2.pyc b/tests/test_qspace/__pycache__/test_raman_modulus.cpython-311-pytest-9.0.2.pyc deleted file mode 100644 index 73d2c0d614b5428e94853c2326135c20f301d412..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11309 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 OBrLTYaQ<98;QTN6q~)0a diff --git a/tests/test_qspace/test_neff_cast.py b/tests/test_qspace/test_neff_cast.py new file mode 100644 index 00000000..5b5cbf30 --- /dev/null +++ b/tests/test_qspace/test_neff_cast.py @@ -0,0 +1,165 @@ +"""Regression test for the N_eff integer-truncation bug in +``tdscha.QSpaceLanczos.load_distributed_tdscha``. + +The bug +------- +``load_distributed_tdscha`` used to set, on every rank:: + + qlanc.N_eff = int(np.sum(qlanc.rho)) + +The Julia kernel ``get_perturb_averages_qspace`` returns a result already +divided by ``n_syms * sum(rho_local)`` -- a *float*, see ``tdscha_qspace.jl`` +(``N_eff = sum(rho)``, ``norm_factor = n_syms * N_eff``). +``_call_julia_qspace_distributed`` then multiplies by ``self.N_eff`` to undo +exactly that division, MPI-Allreduces and divides by ``N_eff_global``. The +cancellation is exact only if ``self.N_eff == float(sum(rho_local))``. +Truncating to ``int`` breaks it as soon as ``rho`` is non-integer, i.e. after +``ensemble.update_weights`` -- the normal production situation. The result is +a *silently* wrong (mis-weighted) anharmonic average, hence a wrong Hessian / +Lanczos spectrum. + +The test +-------- +Run under ``mpirun -np 2``. Load the in-repo test ensemble +(``tests/test_julia/data``, 10 configs), call ``update_weights`` with a +slightly different dynamical matrix so that ``rho != 1``, then compute the +TDSCHA Lanczos coefficients twice: + + * path A -- ordinary ``QSpaceLanczos`` (full ensemble on every rank, Julia + work split by ``GoParallel``); ``N_eff`` comes from the base class as + ``np.sum(rho)`` and is therefore correct; + * path B -- ``load_distributed_tdscha`` (config slices per rank), which is + the code path containing the bug. + +The two must agree. On the unfixed code the local weight sums are truncated +(here 4.9461 -> 4 and 4.0589 -> 4), which mis-weights each rank's contribution +by up to ~20%. + +Why the Lanczos and not the free-energy Hessian: the GOLD **size 2** ensemble +is purely harmonic (its forces are exactly odd in u, ``f(u)+f(-u) = 2.2e-15``), +so its anharmonic operator contributes nothing and a Hessian-level +serial-vs-distributed comparison on it is vacuous -- it agrees bitwise even on +the buggy code. GOLD size >= 3 *is* genuinely anharmonic and is the minimum +case for correctness validation. The ``run_FT`` Lanczos on the small in-repo +ensemble populates the two-phonon sector, is far cheaper than a size-3 +Hessian, and its averages go through exactly the same ``N_eff`` +normalisation. + +Usage +----- + mpirun -np 2 python test_neff_cast.py # the actual test + python test_neff_cast.py # re-execs itself under mpirun -np 2 + +It is also collected by pytest as ``test_neff_not_truncated``. +""" + +import os +import subprocess +import sys + +import numpy as np + +# In-repo test ensemble (the one used by tests/test_qspace/test_distributed.py) +ENS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), + "..", "test_julia", "data") +POPULATION = 1 +NQIRR = 3 +T = 250.0 + +N_STEPS = 6 +IQ = 0 +SCALE = 1.05 # perturbation of the dynamical matrix used by update_weights + + +def _load_dyns(): + import cellconstructor as CC + import cellconstructor.Phonons + + dyn0 = CC.Phonons.Phonons(os.path.join(ENS_DIR, "dyn_gen_pop1_"), NQIRR) + # A slightly different dyn, so that update_weights yields non-integer rho. + dyn_f = dyn0.Copy() + for i in range(len(dyn_f.dynmats)): + dyn_f.dynmats[i] = dyn_f.dynmats[i] * SCALE + return dyn0, dyn_f + + +def run_mpi(): + """Body of the test; must be executed under mpirun with >= 2 ranks.""" + import cellconstructor.Settings as Parallel + import sscha.Ensemble + import tdscha.QSpaceLanczos as QL + from tdscha.QSpaceLanczos import load_distributed_tdscha + + n_procs = Parallel.GetNProc() + assert n_procs >= 2, "this test must be run with mpirun -np 2 (got %d)" % n_procs + + dyn0, dyn_f = _load_dyns() + + # ---------------- path A: reference (GoParallel, full ensemble) -------- + ens = sscha.Ensemble.Ensemble(dyn0, T) + ens.load_bin(ENS_DIR, POPULATION) + ens.update_weights(dyn_f, T) + + rho = np.asarray(ens.rho, dtype=np.float64) + assert np.abs(rho - np.round(rho)).max() > 1e-6, \ + "rho is (near) integer: the test would not exercise the bug" + + ref = QL.QSpaceLanczos(ens, lo_to_split=None) + ref.ignore_v3 = False + ref.ignore_v4 = False + ref.init(use_symmetries=True) + assert not ref._distributed + band = int(np.argmax(ref.w_q[:, IQ])) + ref.prepare_mode_q(IQ, band) + ref.run_FT(N_STEPS, verbose=False) + a_ref = np.array(ref.a_coeffs, dtype=np.float64) + b_ref = np.array(ref.b_coeffs, dtype=np.float64) + + # ---------------- path B: distributed (the buggy code path) ------------ + dist = load_distributed_tdscha(ENS_DIR, POPULATION, dyn0, T, lo_to_split=None, + use_symmetries=True, + final_dyn=dyn_f, final_T=T) + dist.ignore_v3 = False + dist.ignore_v4 = False + assert dist._distributed + dist.prepare_mode_q(IQ, band) + dist.run_FT(N_STEPS, verbose=False) + a_dis = np.array(dist.a_coeffs, dtype=np.float64) + b_dis = np.array(dist.b_coeffs, dtype=np.float64) + + ok = True + if Parallel.am_i_the_master(): + print("N_eff local = %r (sum rho_local = %.10f)" + % (dist.N_eff, float(np.sum(dist.rho)))) + print("a_ref = %s" % np.array2string(a_ref, precision=10)) + print("a_dis = %s" % np.array2string(a_dis, precision=10)) + for name, x, y in (("a_coeffs", a_ref, a_dis), ("b_coeffs", b_ref, b_dis)): + scale = max(np.abs(x).max(), 1e-30) + rel = np.abs(x - y).max() / scale + print("max |ref - dist| / max|ref| [%s] = %.6e" % (name, rel)) + if not np.allclose(x, y, rtol=1e-8, atol=1e-12 * scale): + ok = False + if not ok: + print("FAIL: distributed Lanczos differs from the reference. " + "N_eff must be float(sum(rho)), not int(sum(rho)).") + else: + print("OK: distributed Lanczos matches the GoParallel reference") + + return ok + + +def _run_under_mpirun(): + env = dict(os.environ) + env["OMP_NUM_THREADS"] = "1" + return subprocess.call(["mpirun", "-np", "2", sys.executable, + os.path.abspath(__file__), "--inner"], env=env) + + +def test_neff_not_truncated(): + assert _run_under_mpirun() == 0 + + +if __name__ == "__main__": + if "--inner" in sys.argv: + sys.exit(0 if run_mpi() else 1) + sys.exit(_run_under_mpirun()) From e74a90c689615c5f1bb6c043913a0b7456d57407 Mon Sep 17 00:00:00 2001 From: SorBalda Date: Sat, 1 Aug 2026 23:45:35 +0200 Subject: [PATCH 4/6] Schur fill: detect reducible blocks, and tidy the capability probes Review feedback from @mesonepigreco: the detection never ran for a single degenerate block, because it was guarded by len(deg_blocks) > 1. A block can be reducible on its own -- a repeated irrep at the same frequency, or an accidental degeneracy between different irreps -- and then c*I is wrong for it with no partner block to reveal it. Schur forces G on one irrep copy to be c*I in any basis, so the representative column of a clean copy has zero support on the rest of its own block: nonzero leakage exposes the reducible case, and it is measured on a column that is solved anyway. The dimension shortcut is relaxed accordingly: "different dimension -> different irrep" only holds when both blocks are irreducible. Detection is split into two passes rather than done in a single loop, for two reasons. The self-reducible set must be complete before any pair is examined, otherwise the result depends on the order the blocks happen to be listed in (new regression test). And the threshold scale is recomputed per pair instead of carried as a running maximum: a monotonically non-decreasing threshold can only lose couplings, and column norms go as 1/w^2, so a single soft-mode block would raise it by orders of magnitude for every pair examined after it. Three regression tests are added; two of them fail on the previous code. Also from the review: the inspect import moved to the header block, the redundant function-local sscha.Ensemble import dropped, and the duplicated hasattr probe folded into _ensemble_has_qspace_cache_api. The probes themselves are kept and now carry a note: no released CellConstructor or python-sscha exposes q_only / qspace_light, so the version pin that would replace them cannot be written yet. --- Modules/QSpaceHessian.py | 69 +++++++++++--- Modules/QSpaceLanczos.py | 33 +++++-- tests/test_qspace/test_schur_fill.py | 131 +++++++++++++++++++++++++++ 3 files changed, 212 insertions(+), 21 deletions(-) diff --git a/Modules/QSpaceHessian.py b/Modules/QSpaceHessian.py index 52da0d3c..d721789b 100644 --- a/Modules/QSpaceHessian.py +++ b/Modules/QSpaceHessian.py @@ -59,11 +59,26 @@ def _adaptive_schur_fill(G_q, solve_schedule, rep_x, solve_column, nb, tol, SAME irrep is c*U_AB with an unknown unitary intertwiner (eigh returns arbitrary bases in each degenerate subspace) -- NOT c*I. The scalar shortcut is therefore valid only where the coupling - vanishes (distinct irreps). Couplings between same-dimension blocks - are measured on the representative columns with threshold - min(50*tol, 1e-5)*scale (the cap keeps the detection meaningful for - loose solver tolerances); the coupled groups are solved column by - column exactly. A false positive only costs extra solves. + vanishes (distinct irreps). Two kinds of failure are detected, both + measured on columns that are solved anyway, so detection is free: + + * a block that is reducible on its own (a repeated irrep at the same + frequency, or an accidental degeneracy between different irreps): + the representative column of a clean single copy has zero support + on the rest of its own block, so nonzero leakage exposes it; + * a coupling between two blocks sharing an irrep. + + Both use the threshold min(50*tol, 1e-5)*scale (the cap keeps the + detection meaningful for loose solver tolerances). Every block of a + coupled group, and every self-reducible block, is then solved column + by column exactly: k blocks of dimension d cost k*(d-1) extra solves. + A false positive only costs solves. + + Known limit: the criterion reads the representative column, so it + cannot see a reducible block whose basis already happens to be + symmetry-adapted -- the off-diagonal leakage is then exactly zero + while the two Schur constants still differ. Detecting that needs the + other columns, which is precisely what the shortcut avoids solving. Parameters ---------- @@ -84,7 +99,7 @@ def _adaptive_schur_fill(G_q, solve_schedule, rep_x, solve_column, nb, tol, deg_blocks = [b for _, b in solve_schedule if len(b) >= 2] full_solve = set() group_rows = {} - if use_mode_symmetry and len(deg_blocks) > 1: + if use_mode_symmetry and deg_blocks: parent = {b[0]: b[0] for b in deg_blocks} def _find(a): @@ -93,12 +108,42 @@ def _find(a): a = parent[a] return a + # Pass 1: blocks that are not a single irrep copy. A degenerate block + # can already be reducible on its own -- a repeated irrep at the same + # frequency, or an accidental degeneracy between different irreps -- + # and then c*I is wrong for it with no partner block to reveal it. + # Schur forces G on one irrep copy to be c*I in ANY basis, so the + # representative column of a clean copy has zero support on the rest + # of its own block: nonzero leakage means the block is reducible. + # This is measured on columns that are solved anyway, so it is free. + for A in deg_blocks: + others = np.array([m for m in A if m != A[0]]) + if not others.size: + continue + xA = rep_x[A[0]] + scale = max(np.linalg.norm(xA[:nb]), 1e-300) + if np.max(np.abs(xA[others])) > min(50.0 * tol, 1e-5) * scale: + full_solve.add(A[0]) + + # Pass 2: couplings between blocks. Kept separate from pass 1 because + # the dimension shortcut below reads full_solve, which must already be + # complete: deciding both in one loop makes the result depend on the + # order the blocks happen to be listed in. for i in range(len(deg_blocks)): for j in range(i + 1, len(deg_blocks)): A, B = deg_blocks[i], deg_blocks[j] - if len(A) != len(B): - continue # different dimension -> different irrep + # "different dimension -> different irrep -> no coupling" only + # holds when BOTH blocks are irreducible; a reducible one can + # share an irrep with a block of any size, so it is measured. + if len(A) != len(B) and \ + A[0] not in full_solve and B[0] not in full_solve: + continue xA, xB = rep_x[A[0]], rep_x[B[0]] + # Recomputed per pair: carrying a running maximum across the + # loop would make the threshold monotonically non-decreasing, + # so a single soft-mode block (||x|| ~ 1/w^2, orders of + # magnitude larger) would raise it for every later pair and + # silently hide their couplings. scale = max(np.linalg.norm(xA[:nb]), np.linalg.norm(xB[:nb]), 1e-300) coup = max(np.max(np.abs(xA[np.array(B)])), @@ -112,9 +157,11 @@ def _find(a): for b in deg_blocks: groups.setdefault(_find(b[0]), []).append(b) for blist in groups.values(): - if len(blist) > 1: - rows = sorted(m for b in blist for m in b) - for b in blist: + rows = sorted(m for b in blist for m in b) + for b in blist: + # Every block of a coupled group is solved in full; a block + # that is reducible on its own is a group of one. + if len(blist) > 1 or b[0] in full_solve: full_solve.add(b[0]) group_rows[b[0]] = rows diff --git a/Modules/QSpaceLanczos.py b/Modules/QSpaceLanczos.py index 91c50769..c6275977 100644 --- a/Modules/QSpaceLanczos.py +++ b/Modules/QSpaceLanczos.py @@ -22,6 +22,7 @@ import sys, os import time +import inspect import warnings import numpy as np @@ -60,16 +61,20 @@ __SPGLIB__ = False # Capability probes for the two companion packages. The q-space path needs -# features that only exist in the patched CellConstructor / python-sscha; the -# probes let this module degrade with an explicit warning instead of dying on -# a TypeError or an AttributeError deep inside __init__ when it is installed -# next to an unpatched release. They are cheap and evaluated once at import. -import inspect as _inspect +# features that only exist in newer CellConstructor / python-sscha releases; +# the probes let this module degrade with an explicit warning instead of dying +# on a TypeError or an AttributeError deep inside __init__ when installed next +# to an older one. They are cheap and evaluated once at import. +# +# These will be removed in favour of a version pin in requirements.txt and +# pyproject.toml once the companion features are released: today no published +# version of either package exposes them, so a pin cannot be written yet. +# See CellConstructor PR #126 and python-sscha PR #428. def _cc_has_q_only(): try: - return "q_only" in _inspect.signature( + return "q_only" in inspect.signature( CC.Phonons.Phonons.DiagonalizeSupercell).parameters except (AttributeError, TypeError, ValueError): return False @@ -78,13 +83,22 @@ def _cc_has_q_only(): def _ensemble_supports_light(): """True if python-sscha exposes the linear q-space ensemble API.""" try: - import sscha.Ensemble - return "qspace_light" in _inspect.signature( + return "qspace_light" in inspect.signature( sscha.Ensemble.Ensemble.__init__).parameters except Exception: return False +def _ensemble_has_qspace_cache_api(ensemble_cls): + """True if the ensemble class can rebuild its q-space caches. + + Accepts the deprecated private name so that a python-sscha predating the + public rename still works. + """ + return (hasattr(ensemble_cls, "refresh_qspace_caches_from_real_space") + or hasattr(ensemble_cls, "_refresh_qspace_caches_from_real_space")) + + _CC_HAS_Q_ONLY = _cc_has_q_only() @@ -1869,8 +1883,7 @@ def load_distributed_tdscha(data_dir, population_id, dyn, T, lo_to_split=None, # spent minutes and a dense Upsilon transient. Failing here keeps the error # cheap and says what to install. The deprecated private name is accepted # so that a python-sscha checkout predating the public rename still works. - if not (hasattr(sscha.Ensemble.Ensemble, "refresh_qspace_caches_from_real_space") - or hasattr(sscha.Ensemble.Ensemble, "_refresh_qspace_caches_from_real_space")): + if not _ensemble_has_qspace_cache_api(sscha.Ensemble.Ensemble): raise AttributeError( "This python-sscha does not expose the q-space cache API " "(refresh_qspace_caches_from_real_space): the q-space Lanczos " diff --git a/tests/test_qspace/test_schur_fill.py b/tests/test_qspace/test_schur_fill.py index 97923b56..0edbff61 100644 --- a/tests/test_qspace/test_schur_fill.py +++ b/tests/test_qspace/test_schur_fill.py @@ -102,3 +102,134 @@ def test_singletons_and_no_mode_symmetry(): full = _adaptive_schur_fill(G, schedule, rep_x, solve, 4, 1e-6, ums) assert full == set() assert np.max(np.abs(G - G_true)) < 1e-12 + + +def _block_diag_irrep(consts, dim, mixer=None): + """G with `len(consts)` copies of one dim-dimensional irrep. + + Each copy m contributes consts[m] * I_dim on its diagonal block; `mixer`, + if given, is the (ncopies, ncopies) hermitian matrix of cross-block + constants, so that the block (m, n) is mixer[m, n] * I_dim. This is the + exact structure Schur's lemma allows in a symmetry-adapted basis. + """ + n = len(consts) * dim + G = np.zeros((n, n), dtype=np.complex128) + for m, cm in enumerate(consts): + G[m * dim:(m + 1) * dim, m * dim:(m + 1) * dim] = cm * np.eye(dim) + if mixer is not None: + for m in range(len(consts)): + for n_ in range(len(consts)): + if m != n_: + G[m * dim:(m + 1) * dim, n_ * dim:(n_ + 1) * dim] = \ + mixer[m, n_] * np.eye(dim) + return G + + +def _rotate(G, rng, blocks): + """Rotate each degenerate block by a random unitary. + + This is what eigh does in practice: inside a degenerate subspace the basis + is arbitrary, which is exactly why the cross block is c*U and not c*I. + """ + n = G.shape[0] + U = np.eye(n, dtype=np.complex128) + for b in blocks: + k = len(b) + M = rng.normal(size=(k, k)) + 1j * rng.normal(size=(k, k)) + Q, _ = np.linalg.qr(M) + U[np.ix_(b, b)] = Q + return U.conj().T @ G @ U + + +def test_single_reducible_block_is_detected(): + """A lone degenerate block can already be reducible. + + Two copies of the same irrep degenerate at the SAME frequency land in one + block, so there is no partner block to reveal the coupling. The scalar + shortcut is wrong for it, and the leakage of the representative column + onto the rest of its own block is what exposes it. + """ + rng = np.random.default_rng(11) + block = list(range(4)) + G_true = _block_diag_irrep([2.0, 3.5], dim=2, + mixer=np.array([[0.0, 0.9], [0.9, 0.0]])) + G_true = _rotate(G_true, rng, [block]) + solve = _exact_solver(G_true) + schedule = [(0, block)] + rep_x = {0: solve(0)[0]} + + G = np.zeros_like(G_true) + full = _adaptive_schur_fill(G, schedule, rep_x, solve, 4, 1e-6, True) + assert full == {0}, "reducible single block not detected" + G = (G + G.conj().T) / 2 + assert np.max(np.abs(G - G_true)) < 1e-10 + + +def test_soft_mode_spectator_does_not_raise_the_threshold(): + """A large-norm spectator block must not hide a later coupling. + + Column norms scale like 1/w^2, so a soft mode can be orders of magnitude + larger than the rest. Carrying a running maximum of `scale` across the + pair loop makes the threshold monotonically non-decreasing, so a spectator + examined BETWEEN two coupled blocks raises it for the pair that follows + and masks their coupling. The spectator therefore sits at index 1, with + the coupled copies at 0 and 2: that is the order in which the bug bites. + """ + rng = np.random.default_rng(3) + n = 6 + G_true = np.zeros((n, n), dtype=np.complex128) + # two copies of a 2-dim irrep, coupled, at indices 0-1 and 4-5 + G_true[0:2, 0:2] = 1.0 * np.eye(2) + G_true[4:6, 4:6] = 1.2 * np.eye(2) + G_true[0:2, 4:6] = 3e-4 * np.eye(2) + G_true[4:6, 0:2] = 3e-4 * np.eye(2) + # soft-mode spectator in between: huge column norm, no coupling + G_true[2:4, 2:4] = 1e-8 * np.eye(2) + blocks = [[0, 1], [2, 3], [4, 5]] + G_true = _rotate(G_true, rng, blocks) + G_true = (G_true + G_true.conj().T) / 2 + solve = _exact_solver(G_true) + schedule = [(b[0], b) for b in blocks] + rep_x = {b[0]: solve(b[0])[0] for b in blocks} + + G = np.zeros_like(G_true) + full = _adaptive_schur_fill(G, schedule, rep_x, solve, n, 1e-6, True) + assert {0, 4} <= full, "coupling masked by the soft-mode spectator" + G = (G + G.conj().T) / 2 + assert np.max(np.abs(G - G_true)) < 1e-10 + + +def test_detection_is_order_independent(): + """The result must not depend on the order the blocks are listed in. + + The dimension shortcut reads the set of self-reducible blocks, so that set + has to be complete before any pair is examined; deciding both in one pass + makes the outcome depend on the iteration order. + """ + rng = np.random.default_rng(5) + # a self-reducible 4-dim block coupled to a 2-dim block: the pair has + # different dimensions, so it is only examined because one is reducible + G_true = np.zeros((6, 6), dtype=np.complex128) + G_true[:4, :4] = _block_diag_irrep([2.0, 2.6], dim=2, + mixer=np.array([[0.0, 0.8], + [0.8, 0.0]])) + G_true[4:, 4:] = 1.5 * np.eye(2) + G_true[:2, 4:] = 0.4 * np.eye(2) + G_true[4:, :2] = 0.4 * np.eye(2) + blocks_a = [[0, 1, 2, 3], [4, 5]] + G_true = _rotate(G_true, rng, blocks_a) + G_true = (G_true + G_true.conj().T) / 2 + solve = _exact_solver(G_true) + + results = [] + for blocks in (blocks_a, list(reversed(blocks_a))): + schedule = [(b[0], b) for b in blocks] + rep_x = {b[0]: solve(b[0])[0] for b in blocks} + G = np.zeros_like(G_true) + full = _adaptive_schur_fill(G, schedule, rep_x, solve, 6, 1e-6, True) + G = (G + G.conj().T) / 2 + results.append((full, np.max(np.abs(G - G_true)))) + + assert results[0][0] == results[1][0], "detection depends on block order" + for _, err in results: + assert err < 1e-10 From 7e0753b83c38c43540a1eb6f4597b5e37fd38a11 Mon Sep 17 00:00:00 2001 From: SorBalda Date: Sun, 2 Aug 2026 00:27:32 +0200 Subject: [PATCH 5/6] Make the soft-mode regression test actually bite, and fix the MPI Hessian test The spectator block in test_soft_mode_spectator_does_not_raise_the_threshold was given a tiny constant, so its column norm was the smallest of the three instead of the largest and the running-maximum threshold never moved: the test passed on every variant and guarded nothing. Its whole point is a spectator whose column dominates, so the constant is now 1e3 (a larger ratio makes the matrix ill-conditioned enough to trip the accuracy assert for the wrong reason). With the fix the test fails on the single-loop detection and passes on the two-pass one, as intended. Both new asserts on the detected set are tightened from a subset test to equality, so a variant that gives up and solves everything no longer passes. test_distributed_hessian built the Hessian with the spatial symmetries off but left the mode symmetry on, and asserted non-negative eigenvalues at Gamma. It passed only because the scalar cross-block fill fabricated a degeneracy that replaced the true eigenvalues with zeros; with the fill corrected it reports the same spectrum as use_mode_symmetry=False, whose two lowest eigenvalues are genuinely slightly negative (order 1e-6 Ry/bohr^2) for a 10-configuration ensemble with no symmetries. The test now turns the mode symmetry off, to match the rest of the object, and checks that the spectrum is finite and not far below zero instead of asserting a positivity the data does not have. Two further limits of the criterion are documented: the coupling between a singleton mode and an accidentally degenerate block is zeroed without being measured, and the relative threshold is a floor on sensitivity. --- Modules/QSpaceHessian.py | 17 ++++++++++++----- tests/test_qspace/test_distributed.py | 18 +++++++++++++++--- tests/test_qspace/test_schur_fill.py | 21 ++++++++++++--------- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/Modules/QSpaceHessian.py b/Modules/QSpaceHessian.py index d721789b..e2d72a16 100644 --- a/Modules/QSpaceHessian.py +++ b/Modules/QSpaceHessian.py @@ -74,11 +74,18 @@ def _adaptive_schur_fill(G_q, solve_schedule, rep_x, solve_column, nb, tol, by column exactly: k blocks of dimension d cost k*(d-1) extra solves. A false positive only costs solves. - Known limit: the criterion reads the representative column, so it - cannot see a reducible block whose basis already happens to be - symmetry-adapted -- the off-diagonal leakage is then exactly zero - while the two Schur constants still differ. Detecting that needs the - other columns, which is precisely what the shortcut avoids solving. + Known limits, all inherent to reading only the representative column: + + * a reducible block whose basis already happens to be symmetry + adapted is invisible -- the off-diagonal leakage is then exactly + zero while the two Schur constants still differ. Detecting it + needs the other columns, which is what the shortcut avoids; + * the coupling between a singleton mode and a degenerate block that + is accidentally degenerate is zeroed without being measured: Schur + forbids coupling between different irreps, not between different + frequencies; + * min(50*tol, 1e-5) is a floor on sensitivity: a coupling weaker + than that, relative to the column norm, is not detected. Parameters ---------- diff --git a/tests/test_qspace/test_distributed.py b/tests/test_qspace/test_distributed.py index 2c8c6ef2..942379d4 100644 --- a/tests/test_qspace/test_distributed.py +++ b/tests/test_qspace/test_distributed.py @@ -216,7 +216,10 @@ def test_distributed_hessian(): hess = QH.QSpaceHessian.from_qspace_lanczos(qlanc, verbose=False, use_symmetries=False) pprint("Computing Hessian...") - hess.compute_full_hessian() + # This case is built with the spatial symmetries off, so the mode symmetry + # must be off as well: leaving it on would apply Schur's lemma to a + # symmetry structure the rest of the object does not use. + hess.compute_full_hessian(use_mode_symmetry=False) # Check that we have results for Gamma assert 0 in hess.H_q_dict, "Missing Gamma point in Hessian results" @@ -227,8 +230,17 @@ def test_distributed_hessian(): pprint(f"Hessian eigenvalues at Gamma: {evals}") - # All eigenvalues should be non-negative (for stable system) - assert np.all(evals >= -1e-10), "Negative eigenvalues in Hessian" + # The eigenvalues are not required to be non-negative here: this is a + # 10-configuration ensemble with the symmetries off, so the free energy + # Hessian is genuinely noisy and its lowest eigenvalues come out slightly + # negative (order 1e-6 Ry/bohr^2). What must hold is that nothing blows + # up: the values are finite and small compared to the physical scale. + # (Before the Schur cross-block fix this assert passed only because the + # scalar shortcut filled a fabricated degeneracy, replacing the true + # slightly-negative eigenvalues with zeros.) + assert np.all(np.isfinite(evals)), "Non-finite eigenvalues in Hessian" + assert np.all(evals >= -1e-3), \ + "Hessian eigenvalues far below zero: {}".format(evals) def test_distributed_kpm(): diff --git a/tests/test_qspace/test_schur_fill.py b/tests/test_qspace/test_schur_fill.py index 0edbff61..a91418eb 100644 --- a/tests/test_qspace/test_schur_fill.py +++ b/tests/test_qspace/test_schur_fill.py @@ -168,12 +168,13 @@ def test_single_reducible_block_is_detected(): def test_soft_mode_spectator_does_not_raise_the_threshold(): """A large-norm spectator block must not hide a later coupling. - Column norms scale like 1/w^2, so a soft mode can be orders of magnitude - larger than the rest. Carrying a running maximum of `scale` across the - pair loop makes the threshold monotonically non-decreasing, so a spectator - examined BETWEEN two coupled blocks raises it for the pair that follows - and masks their coupling. The spectator therefore sits at index 1, with - the coupled copies at 0 and 2: that is the order in which the bug bites. + A block with a large column norm (a soft mode: the columns of G go as + 1/w^2) must not raise the detection threshold for the pairs examined + after it. Carrying a running maximum of `scale` across the pair loop + makes the threshold monotonically non-decreasing, so such a spectator + sitting between two coupled blocks masks their coupling entirely. The + spectator is therefore at index 1, with the coupled copies at 0 and 2, + and its constant is large so that its column norm dominates. """ rng = np.random.default_rng(3) n = 6 @@ -183,8 +184,9 @@ def test_soft_mode_spectator_does_not_raise_the_threshold(): G_true[4:6, 4:6] = 1.2 * np.eye(2) G_true[0:2, 4:6] = 3e-4 * np.eye(2) G_true[4:6, 0:2] = 3e-4 * np.eye(2) - # soft-mode spectator in between: huge column norm, no coupling - G_true[2:4, 2:4] = 1e-8 * np.eye(2) + # spectator in between, with a column norm ~1e3 times the coupled pair + # and no coupling of its own + G_true[2:4, 2:4] = 1e3 * np.eye(2) blocks = [[0, 1], [2, 3], [4, 5]] G_true = _rotate(G_true, rng, blocks) G_true = (G_true + G_true.conj().T) / 2 @@ -194,7 +196,7 @@ def test_soft_mode_spectator_does_not_raise_the_threshold(): G = np.zeros_like(G_true) full = _adaptive_schur_fill(G, schedule, rep_x, solve, n, 1e-6, True) - assert {0, 4} <= full, "coupling masked by the soft-mode spectator" + assert full == {0, 4}, "coupling masked by the soft-mode spectator" G = (G + G.conj().T) / 2 assert np.max(np.abs(G - G_true)) < 1e-10 @@ -231,5 +233,6 @@ def test_detection_is_order_independent(): results.append((full, np.max(np.abs(G - G_true)))) assert results[0][0] == results[1][0], "detection depends on block order" + assert results[0][0] == {0, 4}, "expected both coupled blocks to be solved" for _, err in results: assert err < 1e-10 From 16448db157be556f0d8d726db023d24fa9f5bf92 Mon Sep 17 00:00:00 2001 From: SorBalda Date: Sun, 2 Aug 2026 12:49:46 +0200 Subject: [PATCH 6/6] tests: move the imports of test_neff_cast to the module header There is no reason for the lazy form here: JuliaExt boots the runtime on first use, not on import, so collecting this module does not start Julia, and test_distributed.py already imports the same modules at module scope. --- tests/test_qspace/test_neff_cast.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/test_qspace/test_neff_cast.py b/tests/test_qspace/test_neff_cast.py index 5b5cbf30..811844e1 100644 --- a/tests/test_qspace/test_neff_cast.py +++ b/tests/test_qspace/test_neff_cast.py @@ -59,6 +59,13 @@ import numpy as np +import cellconstructor as CC +import cellconstructor.Phonons +import cellconstructor.Settings as Parallel +import sscha.Ensemble +import tdscha.QSpaceLanczos as QL +from tdscha.QSpaceLanczos import load_distributed_tdscha + # In-repo test ensemble (the one used by tests/test_qspace/test_distributed.py) ENS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "test_julia", "data") @@ -72,9 +79,6 @@ def _load_dyns(): - import cellconstructor as CC - import cellconstructor.Phonons - dyn0 = CC.Phonons.Phonons(os.path.join(ENS_DIR, "dyn_gen_pop1_"), NQIRR) # A slightly different dyn, so that update_weights yields non-integer rho. dyn_f = dyn0.Copy() @@ -85,11 +89,6 @@ def _load_dyns(): def run_mpi(): """Body of the test; must be executed under mpirun with >= 2 ranks.""" - import cellconstructor.Settings as Parallel - import sscha.Ensemble - import tdscha.QSpaceLanczos as QL - from tdscha.QSpaceLanczos import load_distributed_tdscha - n_procs = Parallel.GetNProc() assert n_procs >= 2, "this test must be run with mpirun -np 2 (got %d)" % n_procs