From 96a3600c0c56e5e4693a978344630cc83e54eed0 Mon Sep 17 00:00:00 2001 From: Yannick Calvino Alonso Date: Thu, 22 Jan 2026 12:24:34 +0100 Subject: [PATCH 1/4] added verbosity level (`verbose<1` supresses warnings) --- qstack/spahm/compute_spahm.py | 5 +++-- qstack/spahm/guesses.py | 12 ++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/qstack/spahm/compute_spahm.py b/qstack/spahm/compute_spahm.py index 541803b..25c7bdf 100644 --- a/qstack/spahm/compute_spahm.py +++ b/qstack/spahm/compute_spahm.py @@ -114,7 +114,7 @@ def get_guess_orbitals_grad(mol, guess, field=None): return e, eigenvalue_grad(mol, e, c, s1, h1), de_dfield -def get_spahm_representation(mol, guess_in, xc="pbe", field=None): +def get_spahm_representation(mol, guess_in, xc="pbe", field=None, verbose=1): """Compute the ε-SPAHM molecular representation. Reference: @@ -128,6 +128,7 @@ def get_spahm_representation(mol, guess_in, xc="pbe", field=None): xc (str): Exchange-correlation functional name. Defaults to 'pbe'. field (numpy ndarray, optional): 3-component uniform electric field (∇φ) in atomic units. Defaults to None. + verbose (int): Level of verbosity Returns: numpy ndarray: SPAHM representation consisting of occupied orbital eigenvalues. @@ -136,7 +137,7 @@ def get_spahm_representation(mol, guess_in, xc="pbe", field=None): """ guess = get_guess(guess_in) e, _v = get_guess_orbitals(mol, guess, xc, field=field) - e1 = get_occ(e, mol.nelec, mol.spin) + e1 = get_occ(e, mol.nelec, mol.spin, verbose=verbose) return e1 diff --git a/qstack/spahm/guesses.py b/qstack/spahm/guesses.py index 72ed240..7029084 100644 --- a/qstack/spahm/guesses.py +++ b/qstack/spahm/guesses.py @@ -217,7 +217,7 @@ def check_nelec(nelec, nao): warnings.warn(msg, RuntimeWarning, stacklevel=2) -def get_occ(e, nelec, spin): +def get_occ(e, nelec, spin, verbose=1): """Extract occupied orbital eigenvalues/energies. Args: @@ -225,13 +225,15 @@ def get_occ(e, nelec, spin): or possibly arrays of larger dimensionality. nelec (tuple): Number of (alpha, beta) electrons. spin (int or None): Spin multiplicity. If None, assumes closed-shell. + verbose (int): Level of verbosity Returns: numpy ndarray: Occupied eigenvalues. Shape depends on spin: - Closed-shell (spin=None): 1D array of occupied eigenvalues - Open-shell: 2D array (2, nocc) for alpha and beta separately """ - check_nelec(nelec, e.shape[0]) + if verbose > 0: + check_nelec(nelec, e.shape[0]) if spin is None: nocc = nelec[0] return e[:nocc,...] @@ -243,20 +245,22 @@ def get_occ(e, nelec, spin): return e1 -def get_dm(v, nelec, spin): +def get_dm(v, nelec, spin, verbose=1): """Construct density matrix from occupied molecular orbitals. Args: v (numpy ndarray): 2D array of MO coefficients (eigenvectors), columns are MOs. nelec (tuple): Number of (alpha, beta) electrons. spin (int or None): Spin multiplicity. If None, assumes closed-shell (RHF). + verbose (int): Level of verbosity Returns: numpy ndarray: Density matrix in AO basis. - Closed-shell: 2D array (nao, nao) - Open-shell: 3D array (2, nao, nao) for alpha and beta """ - check_nelec(nelec, len(v)) + if verbose > 0 : + check_nelec(nelec, len(v)) if spin is None: nocc = nelec[0] dm = v[:,:nocc] @ v[:,:nocc].T From eaf6db5503ec0753cf43602b7f32505d00c6c5da Mon Sep 17 00:00:00 2001 From: calvinoY Date: Mon, 26 Jan 2026 16:10:59 +0100 Subject: [PATCH 2/4] pass `verbose` to `check_nelec()` as `full_shell_warning` does not supress `RuntimeError` (too many electrons) --- qstack/spahm/guesses.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/qstack/spahm/guesses.py b/qstack/spahm/guesses.py index 7029084..eedfef5 100644 --- a/qstack/spahm/guesses.py +++ b/qstack/spahm/guesses.py @@ -197,7 +197,7 @@ def get_guess(arg): return guesses_dict[arg] -def check_nelec(nelec, nao): +def check_nelec(nelec, nao, full_shell_warning=1): """Validate that the number of electrons can be accommodated by available orbitals. Args: @@ -212,7 +212,7 @@ def check_nelec(nelec, nao): """ if np.any(np.array(nelec) > nao): raise RuntimeError(f'Too many electrons ({nelec}) for {nao} orbitals') - elif np.any(np.array(nelec) == nao): + elif np.any(np.array(nelec) == nao) and full_shell_warning>0: msg = f'{nelec} electrons for {nao} orbitals. Is the input intended to have a complete shell?' warnings.warn(msg, RuntimeWarning, stacklevel=2) @@ -225,15 +225,14 @@ def get_occ(e, nelec, spin, verbose=1): or possibly arrays of larger dimensionality. nelec (tuple): Number of (alpha, beta) electrons. spin (int or None): Spin multiplicity. If None, assumes closed-shell. - verbose (int): Level of verbosity + verbose (int): Level of verbosity (< 1 supresses full-shell warnings) Returns: numpy ndarray: Occupied eigenvalues. Shape depends on spin: - Closed-shell (spin=None): 1D array of occupied eigenvalues - Open-shell: 2D array (2, nocc) for alpha and beta separately """ - if verbose > 0: - check_nelec(nelec, e.shape[0]) + check_nelec(nelec, e.shape[0], full_shell_warning=verbose) if spin is None: nocc = nelec[0] return e[:nocc,...] @@ -252,15 +251,14 @@ def get_dm(v, nelec, spin, verbose=1): v (numpy ndarray): 2D array of MO coefficients (eigenvectors), columns are MOs. nelec (tuple): Number of (alpha, beta) electrons. spin (int or None): Spin multiplicity. If None, assumes closed-shell (RHF). - verbose (int): Level of verbosity + verbose (int): Level of verbosity (< 1 supresses full-shell warnings) Returns: numpy ndarray: Density matrix in AO basis. - Closed-shell: 2D array (nao, nao) - Open-shell: 3D array (2, nao, nao) for alpha and beta """ - if verbose > 0 : - check_nelec(nelec, len(v)) + check_nelec(nelec, len(v), full_shell_warning=verbose) if spin is None: nocc = nelec[0] dm = v[:,:nocc] @ v[:,:nocc].T From ae80d2d0a5f6102c61bba021a49833d1abd424ba Mon Sep 17 00:00:00 2001 From: calvinoY Date: Mon, 26 Jan 2026 18:41:22 +0100 Subject: [PATCH 3/4] completed `check_nelec()` docs --- qstack/spahm/guesses.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qstack/spahm/guesses.py b/qstack/spahm/guesses.py index eedfef5..a3bcaf6 100644 --- a/qstack/spahm/guesses.py +++ b/qstack/spahm/guesses.py @@ -203,7 +203,7 @@ def check_nelec(nelec, nao, full_shell_warning=1): Args: nelec (tuple or int): Number of electrons (alpha, beta) or total. nao (int): Number of atomic orbitals. - + full_shell_warning (int): if < 1 supresses warnings about fully occupied shells Raises: RuntimeError: If there are more electrons than available orbitals. From 38743aae034db073191dc0b25b3186ca71855531 Mon Sep 17 00:00:00 2001 From: Yannick Calvino Alonso Date: Wed, 28 Jan 2026 09:49:51 +0100 Subject: [PATCH 4/4] pass and shifts `printlevel` to supress full shell warning --- qstack/spahm/rho/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qstack/spahm/rho/utils.py b/qstack/spahm/rho/utils.py index c87c2c5..93fec9b 100644 --- a/qstack/spahm/rho/utils.py +++ b/qstack/spahm/rho/utils.py @@ -106,7 +106,7 @@ def mols_guess(mols, xyzlist, guess, xc=defaults.xc, spin=None, readdm=None, pri xc (str): Exchange-correlation functional for guess. Defaults to defaults.xc. spin (list or None): List of spin multiplicities. Defaults to None. readdm (str, optional): Directory path to load pre-computed density matrices. Defaults to None. - printlevel (int): Verbosity level. Defaults to 0. + printlevel (int): Verbosity level. Defaults to 0. (if < 0 supresses warnings) Returns: list: List of density matrices (2D or 3D numpy arrays). @@ -120,7 +120,7 @@ def mols_guess(mols, xyzlist, guess, xc=defaults.xc, spin=None, readdm=None, pri print(xyzfile, flush=True) if readdm is None: _e, v = spahm.get_guess_orbitals(mol, guess, xc=xc) - dm = guesses.get_dm(v, mol.nelec, mol.spin if sp is not None else None) + dm = guesses.get_dm(v, mol.nelec, mol.spin if sp is not None else None, verbose=printlevel+1) else: dm = np.load(f'{readdm}/{os.path.basename(xyzfile)}.npy') if spin and dm.ndim==2: