From 635803bd1cde19d6f6295b3017795fafce03ca73 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Wed, 20 Nov 2024 18:22:12 -0500 Subject: [PATCH 1/3] added pre-commit hook requires the developer to once execute git config --local core.hooksPath .githooks/ --- .githooks/pre-commit | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100755 .githooks/pre-commit diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 00000000..24ddcf39 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,34 @@ +#!/bin/bash +# Stops accidental commits to master/main/develop. https://gist.github.com/stefansundin/9059706 +# Install: +# cd path/to/git/repo +# curl -fL -o .git/hooks/pre-commit https://gist.githubusercontent.com/stefansundin/9059706/raw/pre-commit-2 +# chmod +x .git/hooks/pre-commit + + +BRANCH=`git rev-parse --abbrev-ref HEAD` +if [[ "$BRANCH" =~ ^(master|main|develop)$ ]]; then + >&2 echo "You are on branch $BRANCH, direct comitting is not allowed." + exit 2 +fi + +if [ "`git diff --check --cached | wc -c`" -gt 0 ]; then + >&2 echo "Your spaces don't agree with your core.whitespace rules." + >&2 echo 'Please run `git diff --check HEAD` to see your errors.' + exit 3 +fi + + +if ! command -v ruff 2>&1 >/dev/null; then + >&2 echo "Please install ruff via 'pip install ruff'." + exit 1 +else + if ! ruff format --diff `git rev-parse --show-toplevel`; then + >&2 echo "There are problems with PEP8-compliance." + >&2 echo 'You can check yourself by executing "ruff format --diff `git rev-parse --show-toplevel`"' + exit 1 + fi +fi + + +exit 0 From 601d49d45b217a6ad48bdabc082c5cbe81e603a7 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Wed, 20 Nov 2024 19:05:25 -0500 Subject: [PATCH 2/3] fixed overlong lines --- .ruff.toml | 1 - example/molbe_dmrg_block2.py | 22 ++++--- setup.py | 3 +- src/kbe/_opt.py | 20 ++++-- src/kbe/autofrag.py | 44 ++++++++----- src/kbe/chain.py | 3 +- src/kbe/fragment.py | 29 ++++++--- src/kbe/helper.py | 6 +- src/kbe/lo.py | 13 ++-- src/kbe/lo_k.py | 5 +- src/kbe/pbe.py | 26 ++++---- src/kbe/pfrag.py | 12 ++-- src/molbe/_opt.py | 41 ++++++++---- src/molbe/autofrag.py | 38 +++++++---- src/molbe/be_parallel.py | 51 +++++++++------ src/molbe/eri_onthefly.py | 21 ++++-- src/molbe/external/cphf_utils.py | 9 ++- src/molbe/external/jac_utils.py | 3 +- src/molbe/external/optqn.py | 16 +++-- src/molbe/external/unrestricted_utils.py | 1 - src/molbe/fragment.py | 23 ++++--- src/molbe/helper.py | 40 +++++++----- src/molbe/lchain.py | 2 + src/molbe/lo.py | 15 +++-- src/molbe/mbe.py | 43 +++++++----- src/molbe/misc.py | 13 ++-- src/molbe/pfrag.py | 14 ++-- src/molbe/rdm.py | 30 +++++---- src/molbe/solver.py | 83 +++++++++++++++--------- src/molbe/ube.py | 14 ++-- tests/chem_dm_kBE_test.py | 3 +- tests/chempot_molBE_test.py | 3 +- tests/dm_molBE_test.py | 3 +- tests/eri_onthefly_test.py | 3 +- tests/hf-in-hf_BE_test.py | 3 +- 35 files changed, 414 insertions(+), 242 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index 90aff1ed..b94483a7 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -1,7 +1,6 @@ [lint] # see the rules [here](https://docs.astral.sh/ruff/rules/) select = ["E", "F", "I", "NPY", "ARG"] -# select = ["E501"] ignore = [ "S101", # https://docs.astral.sh/ruff/rules/assert/ diff --git a/example/molbe_dmrg_block2.py b/example/molbe_dmrg_block2.py index e1aa4a0a..8e6a6df9 100644 --- a/example/molbe_dmrg_block2.py +++ b/example/molbe_dmrg_block2.py @@ -67,8 +67,8 @@ # fragment DMRG calculation finishes. DMRG tempfiles can be quite large, so # be sure to keep an eye on them if `force_cleanup=False` (default). - # NOTE: This does *not* delete the log files `dmrg.conf` and `dmrg.out`for each frag, - # which can still be found in `/scratch/`. + # NOTE: This does *not* delete the log files `dmrg.conf` and `dmrg.out`for + # each frag, which can still be found in `/scratch/`. # Finally, plot the resulting potential energy curves: fig, ax = plt.subplots() @@ -94,10 +94,11 @@ fobj = fragpart(be_type="be2", mol=mol) mybe = BE(mf, fobj, lo_method="pipek-mezey", pop_method="lowdin") -# We automatically construct the fragment DMRG schedules based on user keywords. The following -# input, for example, yields a 60 sweep schedule which uses the two-dot algorithm from sweeps 0-49, -# and the one-dot algo from 50-60. The fragment orbitals are also reordered according the Fiedler -# vector procedure, along with a few other tweaks: +# We automatically construct the fragment DMRG schedules based on user keywords. +# The following # input, for example, yields a 60 sweep schedule which uses +# the two-dot algorithm from sweeps 0-49, +# and the one-dot algo from 50-60. The fragment orbitals are also reordered according +# to the Fiedler vector procedure, along with a few other tweaks: mybe.optimize( solver="block2", # or 'DMRG', 'DMRGSCF', 'DMRGCI' @@ -132,9 +133,10 @@ only_chem=True, ) -# To make sure the calculation is proceeding as expected, make sure to check `[scratch]/dmrg.conf` -# and `[scratch]/dmrg.out`, which are the fragment DMRG inputs and outputs, respectively, used -# by `block2`. +# To make sure the calculation is proceeding as expected, make sure to check +# `[scratch]/dmrg.conf` # and `[scratch]/dmrg.out`, +# which are the fragment DMRG inputs and outputs, respectively, used by `block2`. # NOTE: Parameters in `schedule_kwargs` will overwrite any other DMRG kwargs. -# NOTE: The DMRG schedule kwargs and related syntax follows the standard notation used in block2. +# NOTE: The DMRG schedule kwargs and related syntax follows the standard notation +# used in block2. diff --git a/setup.py b/setup.py index f0a48ce2..73170992 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,8 @@ setup( name="quemb", version="1.0", - description="QuEmb: A framework for efficient simulation of large molecules, surfaces, and solids via Bootstrap Embedding", + description="QuEmb: A framework for efficient simulation of large molecules, " + "surfaces, and solids via Bootstrap Embedding", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/oimeitei/quemb", diff --git a/src/kbe/_opt.py b/src/kbe/_opt.py index aa156754..b996e769 100644 --- a/src/kbe/_opt.py +++ b/src/kbe/_opt.py @@ -1,5 +1,7 @@ # Author(s): Oinam Romesh Meitei +import sys + from molbe._opt import BEOPT @@ -27,22 +29,27 @@ def optimize( method : str, optional Optimization method, by default 'QN' only_chem : bool, optional - If true, density matching is not performed -- only global chemical potential is optimized, by default False + If true, density matching is not performed -- only global chemical potential is + optimized, by default False conv_tol : _type_, optional Convergence tolerance, by default 1.e-6 relax_density : bool, optional Whether to use relaxed or unrelaxed densities, by default False - This option is for using CCSD as solver. Relaxed density here uses Lambda amplitudes, whereas unrelaxed density only uses T amplitudes. - c.f. See http://classic.chem.msu.su/cgi-bin/ceilidh.exe/gran/gamess/forum/?C34df668afbHW-7216-1405+00.htm for the distinction between the two + This option is for using CCSD as solver. Relaxed density here uses + Lambda amplitudes, whereas unrelaxed density only uses T amplitudes. + c.f. See http://classic.chem.msu.su/cgi-bin/ceilidh.exe/gran/gamess/forum/?C34df668afbHW-7216-1405+00.htm + for the distinction between the two use_cumulant : bool, optional Use cumulant-based energy expression, by default True max_iter : int, optional Maximum number of optimization steps, by default 500 nproc : int - Total number of processors assigned for the optimization. Defaults to 1. When nproc > 1, Python multithreading + Total number of processors assigned for the optimization. Defaults to 1. + When nproc > 1, Python multithreading is invoked. ompnum : int - If nproc > 1, ompnum sets the number of cores for OpenMP parallelization. Defaults to 4 + If nproc > 1, ompnum sets the number of cores for OpenMP parallelization. + Defaults to 4 J0 : list of list of float Initial Jacobian. """ @@ -53,7 +60,8 @@ def optimize( pot = self.pot if self.be_type == "be1": sys.exit( - "BE1 only works with chemical potential optimization. Set only_chem=True" + "BE1 only works with chemical potential optimization. " + "Set only_chem=True" ) else: pot = [0.0] diff --git a/src/kbe/autofrag.py b/src/kbe/autofrag.py index a64b2440..e90beeca 100644 --- a/src/kbe/autofrag.py +++ b/src/kbe/autofrag.py @@ -263,35 +263,45 @@ def autogen( """ Automatic cell partitioning - Partitions a unitcell into overlapping fragments as defined in BE atom-based fragmentations. - It automatically detects branched chemical chains and ring systems and partitions accordingly. - For efficiency, it only checks two atoms for connectivity (chemical bond) if they are within 3.5 Angstrom. - This value is hardcoded as normdist. Two atoms are defined as bonded if they are within 1.8 Angstrom (1.2 for Hydrogen atom). - This is also hardcoded as bond & hbond. Neighboring unitcells are used in the fragmentation, exploiting translational symmetry. + Partitions a unitcell into overlapping fragments as defined in + BE atom-based fragmentations. It automatically detects branched chemical chains + and ring systems and partitions accordingly. + For efficiency, it only checks two atoms for connectivity (chemical bond) + if they are within 3.5 Angstrom. This value is hardcoded as normdist. + Two atoms are defined as bonded if they are within 1.8 Angstrom + (1.2 for Hydrogen atom). + This is also hardcoded as bond & hbond. Neighboring unitcells are used in the + fragmentation, exploiting translational symmetry. Parameters ---------- mol : pyscf.pbc.gto.Cell - pyscf.pbc.gto.Cell object. This is required for the options, 'autogen' and 'chain' as frag_type. + pyscf.pbc.gto.Cell object. This is required for the options, 'autogen', + and 'chain' as frag_type. kpt : list of int Number of k-points in each lattice vector dimension. frozen_core : bool, optional Whether to invoke frozen core approximation. Defaults to True. be_type : str, optional - Specifies the order of bootstrap calculation in the atom-based fragmentation. Supported values are 'be1', 'be2', 'be3', and 'be4'. + Specifies the order of bootstrap calculation in the atom-based fragmentation. + Supported values are 'be1', 'be2', 'be3', and 'be4'. Defaults to 'be2'. write_geom : bool, optional - Whether to write a 'fragment.xyz' file which contains all the fragments in Cartesian coordinates. Defaults to False. + Whether to write a 'fragment.xyz' file which contains all the fragments in + Cartesian coordinates. Defaults to False. valence_basis : str, optional - Name of minimal basis set for IAO scheme. 'sto-3g' is sufficient for most cases. Defaults to None. + Name of minimal basis set for IAO scheme. 'sto-3g' is sufficient for most cases. + Defaults to None. valence_only : bool, optional - If True, all calculations will be performed in the valence basis in the IAO partitioning. This is an experimental feature. Defaults to False. + If True, all calculations will be performed in the valence basis in + the IAO partitioning. This is an experimental feature. Defaults to False. print_frags : bool, optional Whether to print out the list of resulting fragments. Defaults to True. interlayer : bool Whether the periodic system has two stacked monolayers. long_bond : bool - For systems with longer than 1.8 Angstrom covalent bond, set this to True otherwise the fragmentation might fail. + For systems with longer than 1.8 Angstrom covalent bond, + set this to True otherwise the fragmentation might fail. Returns @@ -303,13 +313,16 @@ def autogen( center : list of list of int List of center indices for each edge. edge_idx : list of list of list of int - List of edge indices for each fragment where each edge index is a list of LO indices. + List of edge indices for each fragment where each edge index is a list of + LO indices. center_idx : list of list of list of int - List of center indices for each fragment where each center index is a list of LO indices. + List of center indices for each fragment where each center index is a list of + LO indices. centerf_idx : list of list of int List of center fragment indices. ebe_weight : list of list - Weights for each fragment. Each entry contains a weight and a list of LO indices. + Weights for each fragment. Each entry contains a weight and a list of LO + indices. """ from pyscf import lib @@ -344,7 +357,8 @@ def autogen( if n_ > kpt[idx]: print("Use a larger number of k-points; ", flush=True) print( - "Fragment cell larger than all k-points combined is not supported", + "Fragment cell larger than all k-points combined " + "is not supported", flush=True, ) sys.exit() diff --git a/src/kbe/chain.py b/src/kbe/chain.py index 747d1dcd..c84986bc 100644 --- a/src/kbe/chain.py +++ b/src/kbe/chain.py @@ -26,7 +26,8 @@ def findH(mol, nh, tmphlist=[]): def polychain(self, mol, frozen_core=False, unitcell=1): """ - Hard coded fragmentation for polymer chains. This is not recommended for any production level calculations. + Hard coded fragmentation for polymer chains. This is not recommended + for any production level calculations. """ # group H diff --git a/src/kbe/fragment.py b/src/kbe/fragment.py index 7eea4717..80c7342e 100644 --- a/src/kbe/fragment.py +++ b/src/kbe/fragment.py @@ -40,41 +40,50 @@ def __init__( ): """Fragment/partitioning definition - Interfaces two main fragmentation functions (autogen & polychain) in MolBE. It defines edge & - center for density matching and energy estimation. It also forms the base for IAO/PAO partitioning for - a large basis set bootstrap calculation. Fragments are constructed based on atoms within a unitcell. + Interfaces two main fragmentation functions (autogen & polychain) in MolBE. + It defines edge & center for density matching and energy estimation. + It also forms the base for IAO/PAO partitioning for + a large basis set bootstrap calculation. Fragments are constructed based + on atoms within a unitcell. Parameters ---------- frag_type : str - Name of fragmentation function. 'autogen', 'hchain_simple', and 'chain' are supported. Defaults to 'autogen' - For systems with only hydrogen, use 'chain'; everything else should use 'autogen' + Name of fragmentation function. 'autogen', 'hchain_simple', and 'chain' are + supported. Defaults to 'autogen' + For systems with only hydrogen, use 'chain'; + everything else should use 'autogen' be_type : str - Specifies order of bootsrap calculation in the atom-based fragmentation. 'be1', 'be2', 'be3', & 'be4' are supported. + Specifies order of bootsrap calculation in the atom-based fragmentation. + 'be1', 'be2', 'be3', & 'be4' are supported. Defaults to 'be2' For a simple linear system A-B-C-D, be1 only has fragments [A], [B], [C], [D] be2 has [A, B, C], [B, C, D] ben ... mol : pyscf.pbc.gto.Cell - pyscf.pbc.gto.Cell object. This is required for the options, 'autogen' and 'chain' as frag_type. + pyscf.pbc.gto.Cell object. This is required for the options, 'autogen', + and 'chain' as frag_type. valence_basis: str Name of minimal basis set for IAO scheme. 'sto-3g' suffice for most cases. valence_only: bool - If this option is set to True, all calculation will be performed in the valence basis in the IAO partitioning. + If this option is set to True, all calculation will be performed in the + valence basis in the IAO partitioning. This is an experimental feature. frozen_core: bool Whether to invoke frozen core approximation. This is set to False by default print_frags: bool Whether to print out list of resulting fragments. True by default write_geom: bool - Whether to write 'fragment.xyz' file which contains all the fragments in cartesian coordinates. + Whether to write 'fragment.xyz' file which contains all the fragments in + cartesian coordinates. kpt : list of int No. of k-points in each lattice vector direction. This is the same as kmesh. interlayer : bool Whether the periodic system has two stacked monolayers. long_bond : bool - For systems with longer than 1.8 Angstrom covalent bond, set this to True otherwise the fragmentation might fail. + For systems with longer than 1.8 Angstrom covalent bond, set this to True + otherwise the fragmentation might fail. """ # No. of unitcells to use for fragment construction self.unitcell = unitcell diff --git a/src/kbe/helper.py b/src/kbe/helper.py index 6ca8154a..7c38a7b7 100644 --- a/src/kbe/helper.py +++ b/src/kbe/helper.py @@ -9,9 +9,11 @@ def get_veff(eri_, dm, S, TA, hf_veff, return_veff0=False): from pyscf import scf """ - Calculate the effective HF potential (Veff) for a given density matrix and electron repulsion integrals. + Calculate the effective HF potential (Veff) for a given density matrix + and electron repulsion integrals. - This function computes the effective potential by transforming the density matrix, computing the Coulomb (J) and + This function computes the effective potential by transforming the density matrix, + computing the Coulomb (J) and exchange (K) integrals. Parameters diff --git a/src/kbe/lo.py b/src/kbe/lo.py index c61b3836..192b0777 100644 --- a/src/kbe/lo.py +++ b/src/kbe/lo.py @@ -32,19 +32,21 @@ def localize( ): """Orbital localization - Performs orbital localization computations for periodic systems. For large basis, IAO is recommended - augmented with PAO orbitals. + Performs orbital localization computations for periodic systems. For large basis, + IAO is recommended augmented with PAO orbitals. Parameters ---------- lo_method : str - Localization method in quantum chemistry. 'lowdin', 'boys','iao', and 'wannier' are supported. + Localization method in quantum chemistry. 'lowdin', 'boys','iao', and 'wannier' + are supported. mol : pyscf.gto.Molecule pyscf.gto.Molecule object. valence_basis: str Name of minimal basis set for IAO scheme. 'sto-3g' suffice for most cases. valence_only: bool - If this option is set to True, all calculation will be performed in the valence basis in the IAO partitioning. + If this option is set to True, all calculation will be performed in the valence + basis in the IAO partitioning. This is an experimental feature. iao_wannier : bool Whether to perform Wannier localization in the IAO space @@ -239,7 +241,8 @@ def localize( c_core_val[k] = numpy.hstack((ciao_core[k], Ciao_[k])) arrange_by_atom = True - # tmp - aos are not rearrange and so below is not necessary (iaoind_by_atom is used to stack iao|pao later) + # tmp - aos are not rearrange and so below is not necessary + # (iaoind_by_atom is used to stack iao|pao later) if arrange_by_atom: nk, nao, nlo = c_core_val.shape for k in range(self.nkpt): diff --git a/src/kbe/lo_k.py b/src/kbe/lo_k.py index 09ddca61..aba3bd6e 100644 --- a/src/kbe/lo_k.py +++ b/src/kbe/lo_k.py @@ -40,8 +40,9 @@ def get_symm_orth_mat_k(A, thr=1.0e-7, ovlp=None): e, u = scipy.linalg.eigh(S) if int(numpy.sum(e < thr)) > 0: raise ValueError( - "Linear dependence is detected in the column space of A: smallest eigenvalue (%.3E) is less than thr (%.3E). Please use 'cano_orth' instead." - % (numpy.min(e), thr) + "Linear dependence is detected in the column space of A: " + "smallest eigenvalue (%.3E) is less than thr (%.3E). " + "Please use 'cano_orth' instead." % (numpy.min(e), thr) ) U = reduce(numpy.dot, (u, numpy.diag(e**-0.5), u.conj().T)) # U = reduce(numpy.dot, (u/numpy.sqrt(e), u.conj().T)) diff --git a/src/kbe/pbe.py b/src/kbe/pbe.py index 6cc427f4..9e76c0ee 100644 --- a/src/kbe/pbe.py +++ b/src/kbe/pbe.py @@ -17,9 +17,9 @@ class BE: """ Class for handling periodic bootstrap embedding (BE) calculations. - This class encapsulates the functionalities required for performing periodic bootstrap embedding calculations, - including setting up the BE environment, initializing fragments, performing SCF calculations, and - evaluating energies. + This class encapsulates the functionalities required for performing + periodic bootstrap embedding calculations, including setting up the BE environment, + initializing fragments, performing SCF calculations, and evaluating energies. Attributes ---------- @@ -87,7 +87,8 @@ def __init__( save_file : str, optional Path to the file storing save information, by default 'storebe.pk'. nproc : int, optional - Number of processors for parallel calculations, by default 1. If set to >1, threaded parallel computation is invoked. + Number of processors for parallel calculations, by default 1. If set to >1, + multi-threaded parallel computation is invoked. ompnum : int, optional Number of OpenMP threads, by default 4. """ @@ -596,9 +597,11 @@ def oneshot( Parameters ---------- solver : str, optional - High-level quantum chemistry method, by default 'MP2'. 'CCSD', 'FCI', and variants of selected CI are supported. + High-level quantum chemistry method, by default 'MP2'. 'CCSD', 'FCI', + and variants of selected CI are supported. nproc : int, optional - Number of processors for parallel calculations, by default 1. If set to >1, threaded parallel computation is invoked. + Number of processors for parallel calculations, by default 1. + If set to >1, threaded parallel computation is invoked. ompnum : int, optional Number of OpenMP threads, by default 4. calc_frag_energy : bool, optional @@ -727,9 +730,10 @@ def initialize_pot(Nfrag, edge_idx): """ Initialize the potential array for bootstrap embedding. - This function initializes a potential array for a given number of fragments (`Nfrag`) - and their corresponding edge indices (`edge_idx`). The potential array is initialized - with zeros for each pair of edge site indices within each fragment, followed by an + This function initializes a potential array for a given number of + fragments (`Nfrag`) and their corresponding edge indices (`edge_idx`). + The potential array is initialized with zeros for each pair of + edge site indices within each fragment, followed by an additional zero for the global chemical potential. Parameters @@ -737,8 +741,8 @@ def initialize_pot(Nfrag, edge_idx): Nfrag : int Number of fragments. edge_idx : list of list of list of int - List of edge indices for each fragment. Each element is a list of lists, where each - sublist contains the indices of edge sites for a particular fragment. + List of edge indices for each fragment. Each element is a list of lists, + where each sublist contains the indices of edge sites for a particular fragment. Returns ------- diff --git a/src/kbe/pfrag.py b/src/kbe/pfrag.py index a20cd112..eea12d18 100644 --- a/src/kbe/pfrag.py +++ b/src/kbe/pfrag.py @@ -45,13 +45,17 @@ def __init__( ifrag : int fragment index (∈ [0, pbe.Nfrag]) edge : list, optional - list of lists of edge site AOs for each atom in the fragment, by default None + list of lists of edge site AOs for each atom in the fragment, + by default None center : list, optional - list of fragment indices where edge site AOs are center site, by default None + list of fragment indices where edge site AOs are center site, + by default None edge_idx : list, optional - list of lists of indices for edge site AOs within the fragment, by default None + list of lists of indices for edge site AOs within the fragment, + by default None center_idx : list, optional - list of lists of indices within the fragment specified in `center` that points to the edge site AOs , by default None + list of lists of indices within the fragment specified in `center` that + points to the edge site AOs , by default None efac : list, optional weight used for energy contributions, by default None eri_file : str, optional diff --git a/src/molbe/_opt.py b/src/molbe/_opt.py index 5dd8c08d..d350bbb5 100644 --- a/src/molbe/_opt.py +++ b/src/molbe/_opt.py @@ -11,14 +11,16 @@ class BEOPT: """Perform BE optimization. - Implements optimization algorithms for bootstrap optimizations, namely, chemical potential optimization - and density matching. The main technique used in the optimization is a Quasi-Newton method. It interface to external + Implements optimization algorithms for bootstrap optimizations, namely, + chemical potential optimization and density matching. The main technique used in + the optimization is a Quasi-Newton method. It interface to external (adapted version) module originally written by Hong-Zhou Ye. Parameters ---------- pot : list - List of initial BE potentials. The last element is for the global chemical potential. + List of initial BE potentials. The last element is for the global + chemical potential. Fobjs : MolBE.fragpart Fragment object Nocc : int @@ -26,17 +28,22 @@ class BEOPT: enuc : float Nuclear component of the energy. solver : str - High-level solver in bootstrap embedding. 'MP2', 'CCSD', 'FCI' are supported. Selected CI versions, + High-level solver in bootstrap embedding. 'MP2', 'CCSD', 'FCI' are supported. + Selected CI versions, 'HCI', 'SHCI', & 'SCI' are also supported. Defaults to 'MP2' only_chem : bool - Whether to perform chemical potential optimization only. Refer to bootstrap embedding literatures. + Whether to perform chemical potential optimization only. + Refer to bootstrap embedding literatures. nproc : int - Total number of processors assigned for the optimization. Defaults to 1. When nproc > 1, Python multithreading + Total number of processors assigned for the optimization. Defaults to 1. + When nproc > 1, Python multithreading is invoked. ompnum : int - If nproc > 1, ompnum sets the number of cores for OpenMP parallelization. Defaults to 4 + If nproc > 1, ompnum sets the number of cores for OpenMP parallelization. + Defaults to 4 max_space : int - Maximum number of bootstrap optimizaiton steps, after which the optimization is called converged. + Maximum number of bootstrap optimizaiton steps, after which the optimization + is called converged. conv_tol : float Convergence criteria for optimization. Defaults to 1e-6 ebe_hf : float @@ -96,7 +103,8 @@ def objfunc(self, xk): """ Computes error vectors, RMS error, and BE energies. - If nproc (set in initialization) > 1, a multithreaded function is called to perform high-level computations. + If nproc (set in initialization) > 1, a multithreaded function is called to + perform high-level computations. Parameters ---------- @@ -255,22 +263,27 @@ def optimize( method : str, optional Optimization method, by default 'QN' only_chem : bool, optional - If true, density matching is not performed -- only global chemical potential is optimized, by default False + If true, density matching is not performed -- only global chemical potential + is optimized, by default False conv_tol : _type_, optional Convergence tolerance, by default 1.e-6 relax_density : bool, optional Whether to use relaxed or unrelaxed densities, by default False - This option is for using CCSD as solver. Relaxed density here uses Lambda amplitudes, whereas unrelaxed density only uses T amplitudes. - c.f. See http://classic.chem.msu.su/cgi-bin/ceilidh.exe/gran/gamess/forum/?C34df668afbHW-7216-1405+00.htm for the distinction between the two + This option is for using CCSD as solver. Relaxed density here uses + Lambda amplitudes, whereas unrelaxed density only uses T amplitudes. + c.f. See http://classic.chem.msu.su/cgi-bin/ceilidh.exe/gran/gamess/forum/?C34df668afbHW-7216-1405+00.htm + for the distinction between the two use_cumulant : bool, optional Use cumulant-based energy expression, by default True max_iter : int, optional Maximum number of optimization steps, by default 500 nproc : int - Total number of processors assigned for the optimization. Defaults to 1. When nproc > 1, Python multithreading + Total number of processors assigned for the optimization. Defaults to 1. + When nproc > 1, Python multithreading is invoked. ompnum : int - If nproc > 1, ompnum sets the number of cores for OpenMP parallelization. Defaults to 4 + If nproc > 1, ompnum sets the number of cores for OpenMP parallelization. + Defaults to 4 J0 : list of list of float Initial Jacobian. trust_region : bool, optional diff --git a/src/molbe/autofrag.py b/src/molbe/autofrag.py index a6fc2661..6bdb1993 100644 --- a/src/molbe/autofrag.py +++ b/src/molbe/autofrag.py @@ -19,27 +19,34 @@ def autogen( """ Automatic molecular partitioning - Partitions a molecule into overlapping fragments as defined in BE atom-based fragmentations. - It automatically detects branched chemical chains and ring systems and partitions accordingly. - For efficiency, it only checks two atoms for connectivity (chemical bond) if they are within 3.5 Angstrom. - This value is hardcoded as normdist. Two atoms are defined as bonded if they are within 1.8 Angstrom (1.2 for Hydrogen atom). + Partitions a molecule into overlapping fragments as defined in BE atom-based + fragmentations. It automatically detects branched chemical chains and ring systems + and partitions accordingly. For efficiency, it only checks two atoms + for connectivity (chemical bond) if they are within 3.5 Angstrom. + This value is hardcoded as normdist. Two atoms are defined as bonded + if they are within 1.8 Angstrom (1.2 for Hydrogen atom). This is also hardcoded as bond & hbond. Parameters ---------- mol : pyscf.gto.Molecule - pyscf.gto.Molecule object. This is required for the options, 'autogen' and 'chain' as frag_type. + pyscf.gto.Molecule object. This is required for the options, 'autogen', + and 'chain' as frag_type. frozen_core : bool, optional Whether to invoke frozen core approximation. Defaults to True. be_type : str, optional - Specifies the order of bootstrap calculation in the atom-based fragmentation. Supported values are 'be1', 'be2', 'be3', and 'be4'. + Specifies the order of bootstrap calculation in the atom-based fragmentation. + Supported values are 'be1', 'be2', 'be3', and 'be4'. Defaults to 'be2'. write_geom : bool, optional - Whether to write a 'fragment.xyz' file which contains all the fragments in Cartesian coordinates. Defaults to False. + Whether to write a 'fragment.xyz' file which contains all the fragments in + Cartesian coordinates. Defaults to False. valence_basis : str, optional - Name of minimal basis set for IAO scheme. 'sto-3g' is sufficient for most cases. Defaults to None. + Name of minimal basis set for IAO scheme. 'sto-3g' is sufficient for most cases. + Defaults to None. valence_only : bool, optional - If True, all calculations will be performed in the valence basis in the IAO partitioning. This is an experimental feature. Defaults to False. + If True, all calculations will be performed in the valence basis in + the IAO partitioning. This is an experimental feature. Defaults to False. print_frags : bool, optional Whether to print out the list of resulting fragments. Defaults to True. @@ -52,13 +59,16 @@ def autogen( center : list of list of int List of center indices for each edge. edge_idx : list of list of list of int - List of edge indices for each fragment where each edge index is a list of LO indices. + List of edge indices for each fragment where each edge index is a list of + LO indices. center_idx : list of list of list of int - List of center indices for each fragment where each center index is a list of LO indices. + List of center indices for each fragment where each center index is a list of + LO indices. centerf_idx : list of list of int List of center fragment indices. ebe_weight : list of list - Weights for each fragment. Each entry contains a weight and a list of LO indices. + Weights for each fragment. Each entry contains a weight and a list of + LO indices. Frag: list of lists Heavy atom indices for each fragment, per fragment cen: list @@ -66,8 +76,8 @@ def autogen( hlist: list of lists All hydrogen atom indices for each fragment, per fragment add_centers: list of lists - "additional centers" for all fragments, per fragment: contains heavy atoms which are not - centers in any other fragments + "additional centers" for all fragments, per fragment: contains heavy atoms + which are not centers in any other fragments """ diff --git a/src/molbe/be_parallel.py b/src/molbe/be_parallel.py index a5062ead..f8a76f98 100644 --- a/src/molbe/be_parallel.py +++ b/src/molbe/be_parallel.py @@ -71,7 +71,8 @@ def run_solver( h1_e : numpy.ndarray One-electron integral matrix. solver : str, optional - Solver to use for the calculation ('MP2', 'CCSD', 'FCI', 'HCI', 'SHCI', 'SCI'). Default is 'MP2'. + Solver to use for the calculation ('MP2', 'CCSD', 'FCI', 'HCI', 'SHCI', 'SCI'). + Default is 'MP2'. eri_file : str, optional Filename for the electron repulsion integrals. Default is 'eri_file.h5'. ompnum : int, optional @@ -81,7 +82,8 @@ def run_solver( eeval : bool, optional If True, evaluate the electronic energy. Default is True. return_rdm_ao : bool, optional - If True, return the reduced density matrices in the atomic orbital basis. Default is True. + If True, return the reduced density matrices in the atomic orbital basis. + Default is True. use_cumulant : bool, optional If True, use the cumulant approximation for RDM2. Default is True. frag_energy : bool, optional @@ -93,7 +95,8 @@ def run_solver( ------- tuple Depending on the input parameters, returns the molecular orbital coefficients, - one-particle and two-particle reduced density matrices, and optionally the fragment energy. + one-particle and two-particle reduced density matrices, and optionally the + fragment energy. """ # Get electron repulsion integrals (ERI) @@ -413,31 +416,36 @@ def be_func_parallel( """ Embarrassingly Parallel High-Level Computation - Performs high-level bootstrap embedding (BE) computation for each fragment. Computes 1-RDMs - and 2-RDMs for each fragment. It also computes error vectors in BE density match. For selected - CI solvers, this function exposes thresholds used in selected CI calculations (hci_cutoff, ci_coeff_cutoff, select_cutoff). + Performs high-level bootstrap embedding (BE) computation for each fragment. + Computes 1-RDMs and 2-RDMs for each fragment. It also computes error vectors + in BE density match. For selected CI solvers, this function exposes thresholds used + in selected CI calculations (hci_cutoff, ci_coeff_cutoff, select_cutoff). Parameters ---------- pot : list of float - Potentials (local & global) that are added to the 1-electron Hamiltonian component. - The last element in the list is the chemical potential. + Potentials (local & global) that are added to the 1-electron Hamiltonian + component. The last element in the list is the chemical potential. Fobjs : list of MolBE.fragpart Fragment definitions. Nocc : int Number of occupied orbitals for the full system. solver : str - High-level solver in bootstrap embedding. Supported values are 'MP2', 'CCSD', 'FCI', 'HCI', 'SHCI', and 'SCI'. + High-level solver in bootstrap embedding. Supported values are 'MP2', 'CCSD', + 'FCI', 'HCI', 'SHCI', and 'SCI'. enuc : float Nuclear component of the energy. hf_veff : numpy.ndarray, optional Hartree-Fock effective potential. nproc : int, optional - Total number of processors assigned for the optimization. Defaults to 1. When nproc > 1, Python multithreading is invoked. + Total number of processors assigned for the optimization. Defaults to 1. + When nproc > 1, Python multithreading is invoked. ompnum : int, optional - If nproc > 1, sets the number of cores for OpenMP parallelization. Defaults to 4. + If nproc > 1, sets the number of cores for OpenMP parallelization. + Defaults to 4. only_chem : bool, optional - Whether to perform chemical potential optimization only. Refer to bootstrap embedding literature. Defaults to False. + Whether to perform chemical potential optimization only. + Refer to bootstrap embedding literature. Defaults to False. eeval : bool, optional Whether to evaluate energies. Defaults to False. ereturn : bool, optional @@ -458,8 +466,8 @@ def be_func_parallel( Returns ------- float or tuple - Depending on the parameters, returns the error norm or a tuple containing the error norm, - error vector, and the computed energy. + Depending on the parameters, returns the error norm or a tuple containing + the error norm, error vector, and the computed energy. """ import os from multiprocessing import Pool @@ -589,14 +597,15 @@ def be_func_parallel_u( """ Embarrassingly Parallel High-Level Computation - Performs high-level unrestricted bootstrap embedding (UBE) computation for each fragment. Computes 1-RDMs - and 2-RDMs for each fragment to return the energy. As such, this currently is equipped for one-shot U-CCSD BE. + Performs high-level unrestricted bootstrap embedding (UBE) computation for each + fragment. Computes 1-RDMs and 2-RDMs for each fragment to return the energy. + As such, this currently is equipped for one-shot U-CCSD BE. Parameters ---------- pot : list of float - Potentials (local & global) that are added to the 1-electron Hamiltonian component. - The last element in the list is the chemical potential. + Potentials (local & global) that are added to the 1-electron + Hamiltonian component. The last element in the list is the chemical potential. Should always be 0, as this is still a one-shot only implementation Fobjs : list of tuples of MolBE.fragpart Fragment definitions, alpha and beta components. @@ -607,9 +616,11 @@ def be_func_parallel_u( hf_veff : tuple of numpy.ndarray, optional Alpha and beta Hartree-Fock effective potential. nproc : int, optional - Total number of processors assigned for the optimization. Defaults to 1. When nproc > 1, Python multithreading is invoked. + Total number of processors assigned for the optimization. Defaults to 1. + When nproc > 1, Python multithreading is invoked. ompnum : int, optional - If nproc > 1, sets the number of cores for OpenMP parallelization. Defaults to 4. + If nproc > 1, sets the number of cores for OpenMP parallelization. + Defaults to 4. eeval : bool, optional Whether to evaluate energies. Defaults to False. ereturn : bool, optional diff --git a/src/molbe/eri_onthefly.py b/src/molbe/eri_onthefly.py index 23ab8671..c3b6ac71 100644 --- a/src/molbe/eri_onthefly.py +++ b/src/molbe/eri_onthefly.py @@ -12,7 +12,8 @@ def integral_direct_DF(mf, Fobjs, file_eri, auxbasis=None): - """Calculate AO density-fitted 3-center integrals on-the-fly and transform to Schmidt space for given fragment objects + """Calculate AO density-fitted 3-center integrals on-the-fly and transform to + Schmidt space for given fragment objects Parameters ---------- @@ -20,20 +21,24 @@ def integral_direct_DF(mf, Fobjs, file_eri, auxbasis=None): Mean-field object for the chemical system (typically BE.mf) Fobjs : list of BE.Frags List containing fragment objects (typically BE.Fobjs) - The MO coefficients are taken from Frags.TA and the transformed ERIs are stored in Frags.dname as h5py datasets. + The MO coefficients are taken from Frags.TA and the transformed ERIs are stored + in Frags.dname as h5py datasets. file_eri : h5py.File HDF5 file object to store the transformed fragment ERIs auxbasis : string, optional - Auxiliary basis used for density fitting. If not provided, use pyscf's default choice for the basis set used to construct mf object; by default None + Auxiliary basis used for density fitting. If not provided, use pyscf's default + choice for the basis set used to construct mf object; by default None """ def calculate_pqL(aux_range): - """Internal function to calculate the 3-center integrals for a given range of auxiliary indices + """Internal function to calculate the 3-center integrals for a given range of + auxiliary indices Parameters ---------- aux_range : tuple of int - (start index, end index) of the auxiliary basis functions to calculate the 3-center integrals, i.e. (pq|L) with L ∈ [start, end) is returned + (start index, end index) of the auxiliary basis functions to calculate the + 3-center integrals, i.e. (pq|L) with L ∈ [start, end) is returned """ if be_var.PRINT_LEVEL > 10: print("Start calculating (μν|P) for range", aux_range, flush=True) @@ -63,7 +68,8 @@ def calculate_pqL(aux_range): return ints def block_step_size(nfrag, naux, nao): - """Internal function to calculate the block step size for the 3-center integrals calculation + """Internal function to calculate the block step size for the 3-center + integrals calculation Parameters ---------- @@ -92,7 +98,8 @@ def block_step_size(nfrag, naux, nao): "Evaluating fragment ERIs on-the-fly using density fitting...", flush=True ) print( - "In this case, note that HF-in-HF error includes DF error on top of numerical error from embedding.", + "In this case, note that HF-in-HF error includes DF error on top of " + "numerical error from embedding.", flush=True, ) auxmol = make_auxmol(mf.mol, auxbasis=auxbasis) diff --git a/src/molbe/external/cphf_utils.py b/src/molbe/external/cphf_utils.py index 94e2fdea..d33dbdb3 100644 --- a/src/molbe/external/cphf_utils.py +++ b/src/molbe/external/cphf_utils.py @@ -360,18 +360,21 @@ def get_cpuhf_A_spin_eri(C, moe, eri, no): def get_cpuhf_A(C, moe, eri, no): - """eri could be a single numpy array (in spinless basis) or a tuple/list of 3 numpy arrays in the order [aa,bb,ab]""" + """eri could be a single numpy array (in spinless basis) or a tuple/list of + 3 numpy arrays in the order [aa,bb,ab]""" if isinstance(eri, np.ndarray): return get_cpuhf_A_spinless_eri(C, moe, eri, no) elif isinstance(eri, (list, tuple)): if len(eri) != 3: raise ValueError( - "Input eri must be a list/tuple of 3 numpy arrays in the order [aa,bb,ab]" + "Input eri must be a list/tuple of 3 numpy arrays in the order " + "[aa,bb,ab]" ) return get_cpuhf_A_spin_eri(C, moe, eri, no) else: raise ValueError( - "Input eri must be either a numpy array or a list/tuple of 3 numpy arrays in the order [aa,bb,ab]." + "Input eri must be either a numpy array or a list/tuple of 3 numpy arrays " + "in the order [aa,bb,ab]." ) diff --git a/src/molbe/external/jac_utils.py b/src/molbe/external/jac_utils.py index 57715856..20cee9c6 100644 --- a/src/molbe/external/jac_utils.py +++ b/src/molbe/external/jac_utils.py @@ -8,7 +8,8 @@ """ Derivative of approximate t1 amplitudes t_ia = ((2*t2-t2)_ibjc g_cjba - g_ikbj (2*t2-t2)_jbka) / (e_i - e_a) -This approximate t1 is by substituting the MP2 t2 amplitudes into the CCSD equation and run it for one cycle. +This approximate t1 is by substituting the MP2 t2 amplitudes into the CCSD equation and +run it for one cycle. """ diff --git a/src/molbe/external/optqn.py b/src/molbe/external/optqn.py index caee0693..143dff70 100644 --- a/src/molbe/external/optqn.py +++ b/src/molbe/external/optqn.py @@ -1,7 +1,8 @@ # Author(s): Hong-Zhou Ye # Oinam Romesh Meitei # Minsik Cho -# NOTICE: The following code is mostly written by Hong-Zhou Ye (except for the trust region routine) +# NOTICE: The following code is mostly written by Hong-Zhou Ye +# (except for the trust region routine) # The code has been slightly modified. # @@ -11,7 +12,8 @@ def line_search_LF(func, xold, fold, dx, iter_): - """Adapted from D.-H. Li and M. Fukushima, Optimization Metheods and Software, 13, 181 (2000)""" + """Adapted from D.-H. Li and M. Fukushima, Optimization Metheods and Software, + 13, 181 (2000)""" beta = 0.1 rho = 0.9 sigma1 = 1e-3 @@ -47,7 +49,8 @@ def line_search_LF(func, xold, fold, dx, iter_): def trustRegion(func, xold, fold, Binv, c=0.5): - """Perform Trust Region Optimization. See "A Broyden Trust Region Quasi-Newton Method + """Perform Trust Region Optimization. See + "A Broyden Trust Region Quasi-Newton Method for Nonlinear Equations" (https://www.iaeng.org/IJCS/issues_v46/issue_3/IJCS_46_3_09.pdf) Algorithm 1 for more information @@ -60,7 +63,8 @@ def trustRegion(func, xold, fold, Binv, c=0.5): fold : list or numpy.ndarray Current f(x_p) (error vector) Binv : numpy.ndarray - Inverse of Jacobian approximate (B^{-1}); This is updated in Broyden's Method through Sherman-Morrison formula + Inverse of Jacobian approximate (B^{-1}); This is updated in Broyden's Method + through Sherman-Morrison formula c : float, optional Initial value of trust radius ∈ (0, 1), by default 0.5 @@ -110,7 +114,9 @@ def trustRegion(func, xold, fold, Binv, c=0.5): ) tdx_sd = t * dx_sd diff = dx_gn - tdx_sd - # s = (-dx_sd.T@diff + numpy.sqrt((dx_sd.T@diff)**2 - numpy.linalg.norm(diff)**2*(numpy.linalg.norm(dx_sd)**2-(c ** microiter)**2))) / (numpy.linalg.norm(dx_sd))**2 + # s = (-dx_sd.T@diff + numpy.sqrt((dx_sd.T@diff)**2 - + # norm(diff)**2*(norm(dx_sd)**2-(c ** microiter)**2))) + # / (norm(dx_sd))**2 # s is largest value in [0, 1] s.t. ||dx|| \le trust radius s = 1 dx = tdx_sd + s * diff diff --git a/src/molbe/external/unrestricted_utils.py b/src/molbe/external/unrestricted_utils.py index ba37ca37..17284c37 100644 --- a/src/molbe/external/unrestricted_utils.py +++ b/src/molbe/external/unrestricted_utils.py @@ -51,7 +51,6 @@ def make_uhf_obj(fobj_a, fobj_b, frozen=False): ] else: full_uhf.gcores_raw = [full_uhf.veff0_a, full_uhf.veff0_b] - # full_uhf.gcores_raw = [fobj_a.TA.T @ fobj_a.hf_veff @ fobj_a.TA, fobj_b.TA.T @ fobj_b.hf_veff @ fobj_b.TA] full_uhf.core_veffs = None return full_uhf, Vs diff --git a/src/molbe/fragment.py b/src/molbe/fragment.py index 13030de3..1eee2c07 100644 --- a/src/molbe/fragment.py +++ b/src/molbe/fragment.py @@ -9,35 +9,40 @@ class fragpart: """Fragment/partitioning definition - Interfaces two main fragmentation functions (autogen & chain) in MolBE. It defines edge & - center for density matching and energy estimation. It also forms the base for IAO/PAO partitioning for - a large basis set bootstrap calculation. + Interfaces two main fragmentation functions (autogen & chain) in MolBE. It defines + edge & center for density matching and energy estimation. It also forms the base + for IAO/PAO partitioning for a large basis set bootstrap calculation. Parameters ---------- frag_type : str - Name of fragmentation function. 'autogen', 'hchain_simple', and 'chain' are supported. Defaults to 'autogen' - For systems with only hydrogen, use 'chain'; everything else should use 'autogen' + Name of fragmentation function. 'autogen', 'hchain_simple', and 'chain' + are supported. Defaults to 'autogen' For systems with only hydrogen, + use 'chain'; everything else should use 'autogen' be_type : str - Specifies order of bootsrap calculation in the atom-based fragmentation. 'be1', 'be2', 'be3', & 'be4' are supported. + Specifies order of bootsrap calculation in the atom-based fragmentation. + 'be1', 'be2', 'be3', & 'be4' are supported. Defaults to 'be2' For a simple linear system A-B-C-D, be1 only has fragments [A], [B], [C], [D] be2 has [A, B, C], [B, C, D] ben ... mol : pyscf.gto.Molecule - pyscf.gto.Molecule object. This is required for the options, 'autogen' and 'chain' as frag_type. + pyscf.gto.Molecule object. This is required for the options, 'autogen' + and 'chain' as frag_type. valence_basis: str Name of minimal basis set for IAO scheme. 'sto-3g' suffice for most cases. valence_only: bool - If this option is set to True, all calculation will be performed in the valence basis in the IAO partitioning. + If this option is set to True, all calculation will be performed in + the valence basis in the IAO partitioning. This is an experimental feature. frozen_core: bool Whether to invoke frozen core approximation. This is set to False by default print_frags: bool Whether to print out list of resulting fragments. True by default write_geom: bool - Whether to write 'fragment.xyz' file which contains all the fragments in cartesian coordinates. + Whether to write 'fragment.xyz' file which contains all the fragments + in cartesian coordinates. """ def __init__( diff --git a/src/molbe/helper.py b/src/molbe/helper.py index 006d27a5..30448a0a 100644 --- a/src/molbe/helper.py +++ b/src/molbe/helper.py @@ -11,10 +11,11 @@ def get_veff(eri_, dm, S, TA, hf_veff): """ - Calculate the effective HF potential (Veff) for a given density matrix and electron repulsion integrals. + Calculate the effective HF potential (Veff) for a given density matrix and + electron repulsion integrals. - This function computes the effective potential by transforming the density matrix, computing the Coulomb (J) and - exchange (K) integrals. + This function computes the effective potential by transforming the density matrix, + computing the Coulomb (J) and exchange (K) integrals. Parameters ---------- @@ -70,8 +71,9 @@ def get_scfObj( """ Initialize and run a restricted Hartree-Fock (RHF) calculation. - This function sets up an SCF (Self-Consistent Field) object using the provided one-electron Hamiltonian, electron - repulsion integrals, and number of occupied orbitals. It then runs the SCF procedure, optionally using an initial + This function sets up an SCF (Self-Consistent Field) object using the provided + one-electron Hamiltonian, electron repulsion integrals, and number + of occupied orbitals. It then runs the SCF procedure, optionally using an initial density matrix. Parameters @@ -83,7 +85,8 @@ def get_scfObj( nocc : int Number of occupied orbitals. dm0 : numpy.ndarray, optional - Initial density matrix. If not provided, the SCF calculation will start from scratch. Defaults to None. + Initial density matrix. If not provided, the SCF calculation will start + from scratch. Defaults to None. enuc : float, optional Nuclear repulsion energy. Defaults to 0.0. @@ -147,9 +150,11 @@ def get_scfObj( def get_eri(i_frag, Nao, symm=8, ignore_symm=False, eri_file="eri_file.h5"): """ - Retrieve and optionally restore electron repulsion integrals (ERI) from an HDF5 file. + Retrieve and optionally restore electron repulsion integrals (ERI) + from an HDF5 file. - This function reads the ERI for a given fragment from an HDF5 file, and optionally restores the symmetry of the ERI. + This function reads the ERI for a given fragment from an HDF5 file, and optionally + restores the symmetry of the ERI. Parameters ---------- @@ -162,7 +167,8 @@ def get_eri(i_frag, Nao, symm=8, ignore_symm=False, eri_file="eri_file.h5"): ignore_symm : bool, optional If True, the symmetry step is skipped. Defaults to False. eri_file : str, optional - Filename of the HDF5 file containing the electron repulsion integrals. Defaults to 'eri_file.h5'. + Filename of the HDF5 file containing the electron repulsion integrals. + Defaults to 'eri_file.h5'. Returns ------- @@ -253,8 +259,9 @@ def get_frag_energy( """ Compute the fragment energy. - This function calculates the energy contribution of a fragment within a larger molecular system - using the provided molecular orbital coefficients, density matrices, and effective potentials. + This function calculates the energy contribution of a fragment within a + larger molecular system using the provided molecular orbital coefficients, + density matrices, and effective potentials. Parameters ---------- @@ -279,7 +286,8 @@ def get_frag_energy( dname : str Dataset name in the HDF5 file. eri_file : str, optional - Filename of the HDF5 file containing the electron repulsion integrals. Defaults to 'eri_file.h5'. + Filename of the HDF5 file containing the electron repulsion integrals. + Defaults to 'eri_file.h5'. Returns ------- @@ -369,8 +377,9 @@ def get_frag_energy_u( """ Compute the fragment energy for unrestricted calculations - This function calculates the energy contribution of a fragment within a larger molecular system - using the provided molecular orbital coefficients, density matrices, and effective potentials. + This function calculates the energy contribution of a fragment within + a larger molecular system using the provided molecular orbital coefficients, + density matrices, and effective potentials. Parameters ---------- @@ -395,7 +404,8 @@ def get_frag_energy_u( dname : list Dataset name in the HDF5 file. eri_file : str, optional - Filename of the HDF5 file containing the electron repulsion integrals. Defaults to 'eri_file.h5'. + Filename of the HDF5 file containing the electron repulsion integrals. + Defaults to 'eri_file.h5'. gcores : frozen : bool, optional diff --git a/src/molbe/lchain.py b/src/molbe/lchain.py index 82762d56..9223422d 100644 --- a/src/molbe/lchain.py +++ b/src/molbe/lchain.py @@ -1,5 +1,7 @@ # Author(s): Oinam Romesh Meitei +import sys + def chain(self, mol, frozen_core=False, closed=False): """ diff --git a/src/molbe/lo.py b/src/molbe/lo.py index a5023d0e..1cb66945 100644 --- a/src/molbe/lo.py +++ b/src/molbe/lo.py @@ -37,8 +37,9 @@ def get_symm_orth_mat(A, thr=1.0e-6, ovlp=None): e, u = numpy.linalg.eigh(S) if int(numpy.sum(e < thr)) > 0: raise ValueError( - "Linear dependence is detected in the column space of A: smallest eigenvalue (%.3E) is less than thr (%.3E). Please use 'cano_orth' instead." - % (numpy.min(e), thr) + "Linear dependence is detected in the column space of A: " + "smallest eigenvalue (%.3E) is less than thr (%.3E). " + "Please use 'cano_orth' instead." % (numpy.min(e), thr) ) U = u @ numpy.diag(e**-0.5) @ u.T @@ -244,19 +245,21 @@ def localize( ): """Molecular orbital localization - Performs molecular orbital localization computations. For large basis, IAO is recommended - augmented with PAO orbitals. + Performs molecular orbital localization computations. For large basis, + IAO is recommended augmented with PAO orbitals. Parameters ---------- lo_method : str - Localization method in quantum chemistry. 'lowdin', 'boys', and 'iao' are supported. + Localization method in quantum chemistry. 'lowdin', 'boys', and 'iao' + are supported. mol : pyscf.gto.Molecule pyscf.gto.Molecule object. valence_basis: str Name of minimal basis set for IAO scheme. 'sto-3g' suffice for most cases. valence_only: bool - If this option is set to True, all calculation will be performed in the valence basis in the IAO partitioning. + If this option is set to True, all calculation will be performed in the valence + basis in the IAO partitioning. This is an experimental feature. """ import functools diff --git a/src/molbe/mbe.py b/src/molbe/mbe.py index 37b0787e..e9d2c2e3 100644 --- a/src/molbe/mbe.py +++ b/src/molbe/mbe.py @@ -51,8 +51,9 @@ class BE: """ Class for handling bootstrap embedding (BE) calculations. - This class encapsulates the functionalities required for performing bootstrap embedding calculations, - including setting up the BE environment, initializing fragments, performing SCF calculations, and + This class encapsulates the functionalities required for performing + bootstrap embedding calculations, including setting up the BE environment, + initializing fragments, performing SCF calculations, and evaluating energies. Attributes @@ -116,13 +117,17 @@ def __init__( save_file : str, optional Path to the file storing save information, by default 'storebe.pk'. nproc : int, optional - Number of processors for parallel calculations, by default 1. If set to >1, threaded parallel computation is invoked. + Number of processors for parallel calculations, by default 1. If set to >1, + threaded parallel computation is invoked. ompnum : int, optional Number of OpenMP threads, by default 4. integral_direct_DF: bool, optional - If mf._eri is None (i.e. ERIs are not saved in memory using incore_anyway), this flag is used to determine if the ERIs are computed integral-directly using density fitting; by default False. + If mf._eri is None (i.e. ERIs are not saved in memory using incore_anyway), + this flag is used to determine if the ERIs are computed integral-directly + using density fitting; by default False. auxbasis : str, optional - Auxiliary basis for density fitting, by default None (uses default auxiliary basis defined in PySCF). + Auxiliary basis for density fitting, by default None + (uses default auxiliary basis defined in PySCF). """ if restart: @@ -379,13 +384,15 @@ def initialize(self, eri_, compute_hf, restart=False): # Do we have full (ij|kl)? # Yes -- ao2mo, incore version # No -- Do we have (ij|P) from density fitting? - # Yes -- ao2mo, outcore version, using saved (ij|P) - # No -- if integral_direct_DF is requested, invoke on-the-fly routine + # Yes -- ao2mo, outcore version, using saved (ij|P) + # No -- if integral_direct_DF is requested, invoke on-the-fly routine assert ( (eri_ is not None) or (hasattr(self.mf, "with_df")) or (self.integral_direct_DF) - ), "Input mean-field object is missing ERI (mf._eri) or DF (mf.with_df) object AND integral direct DF routine was not requested. Please check your inputs." + ), "Input mean-field object is missing ERI (mf._eri) or DF (mf.with_df) " + "object AND integral direct DF routine was not requested. " + "Please check your inputs." if ( eri_ is not None ): # incore ao2mo using saved eri from mean-field calculation @@ -393,7 +400,8 @@ def initialize(self, eri_, compute_hf, restart=False): eri = ao2mo.incore.full(eri_, self.Fobjs[I].TA, compact=True) file_eri.create_dataset(self.Fobjs[I].dname, data=eri) elif hasattr(self.mf, "with_df") and self.mf.with_df is not None: - # pyscf.ao2mo uses DF object in an outcore fashion using (ij|P) in pyscf temp directory + # pyscf.ao2mo uses DF object in an outcore fashion using (ij|P) + # in pyscf temp directory for I in range(self.Nfrag): eri = self.mf.with_df.ao2mo(self.Fobjs[I].TA, compact=True) file_eri.create_dataset(self.Fobjs[I].dname, data=eri) @@ -477,9 +485,11 @@ def oneshot( Parameters ---------- solver : str, optional - High-level quantum chemistry method, by default 'MP2'. 'CCSD', 'FCI', and variants of selected CI are supported. + High-level quantum chemistry method, by default 'MP2'. 'CCSD', 'FCI', + and variants of selected CI are supported. nproc : int, optional - Number of processors for parallel calculations, by default 1. If set to >1, threaded parallel computation is invoked. + Number of processors for parallel calculations, by default 1. + If set to >1, multi-threaded parallel computation is invoked. ompnum : int, optional Number of OpenMP threads, by default 4. calc_frag_energy : bool, optional @@ -615,9 +625,10 @@ def initialize_pot(Nfrag, edge_idx): """ Initialize the potential array for bootstrap embedding. - This function initializes a potential array for a given number of fragments (`Nfrag`) - and their corresponding edge indices (`edge_idx`). The potential array is initialized - with zeros for each pair of edge site indices within each fragment, followed by an + This function initializes a potential array for a given number of fragments + (`Nfrag`) and their corresponding edge indices (`edge_idx`). + The potential array is initialized with zeros for each pair of edge site indices + within each fragment, followed by an additional zero for the global chemical potential. Parameters @@ -625,8 +636,8 @@ def initialize_pot(Nfrag, edge_idx): Nfrag : int Number of fragments. edge_idx : list of list of list of int - List of edge indices for each fragment. Each element is a list of lists, where each - sublist contains the indices of edge sites for a particular fragment. + List of edge indices for each fragment. Each element is a list of lists, + where each sublist contains the indices of edge sites for a particular fragment. Returns ------- diff --git a/src/molbe/misc.py b/src/molbe/misc.py index 719de2c0..69260ea6 100644 --- a/src/molbe/misc.py +++ b/src/molbe/misc.py @@ -376,7 +376,8 @@ def be2puffin( from pyscf import qmmm print( - "Using QM/MM Point Charges: Assuming QM structure in Angstrom and MM Coordinates in Bohr !!!" + "Using QM/MM Point Charges: Assuming QM structure in Angstrom " + "and MM Coordinates in Bohr !!!" ) mf1 = scf.UHF(mol).set( max_cycle=200 @@ -384,8 +385,8 @@ def be2puffin( # mf1 = scf.UHF(mol).set(max_cycle = 200, level_shift = (0.3, 0.2)) # using level shift helps, but not always. level_shift and # scf.addons.dynamic_level_shift do not seem to work with QM/MM - # note: from the SCINE database, the structure is in Angstrom but the MM point charges - # are in Bohr !! + # note: from the SCINE database, the structure is in Angstrom but + # the MM point charges are in Bohr !! mf = qmmm.mm_charge( mf1, pts_and_charges[0], pts_and_charges[1], unit="bohr" ).newton() # mf object, coordinates, charges @@ -398,14 +399,16 @@ def be2puffin( from pyscf import qmmm print( - "Using QM/MM Point Charges: Assuming QM structure in Angstrom and MM Coordinates in Bohr !!!" + "Using QM/MM Point Charges: Assuming QM structure in Angstrom and " + "MM Coordinates in Bohr !!!" ) mf1 = scf.RHF(mol).set(max_cycle=200) mf = qmmm.mm_charge( mf1, pts_and_charges[0], pts_and_charges[1], unit="bohr" ).newton() print( - "Setting use_df to false and jk to none: have not tested DF and QM/MM from point charges at the same time" + "Setting use_df to false and jk to none: have not tested DF and " + "QM/MM from point charges at the same time" ) use_df = False jk = None diff --git a/src/molbe/pfrag.py b/src/molbe/pfrag.py index fddd63ea..c7469fa9 100644 --- a/src/molbe/pfrag.py +++ b/src/molbe/pfrag.py @@ -39,13 +39,17 @@ def __init__( ifrag : int fragment index (∈ [0, BE.Nfrag]) edge : list, optional - list of lists of edge site AOs for each atom in the fragment, by default None + list of lists of edge site AOs for each atom in the fragment, + by default None center : list, optional - list of fragment indices where edge site AOs are center site, by default None + list of fragment indices where edge site AOs are center site, + by default None edge_idx : list, optional - list of lists of indices for edge site AOs within the fragment, by default None + list of lists of indices for edge site AOs within the fragment, + by default None center_idx : list, optional - list of lists of indices within the fragment specified in `center` that points to the edge site AOs , by default None + list of lists of indices within the fragment specified in `center` + that points to the edge site AOs , by default None efac : list, optional weight used for energy contributions, by default None eri_file : str, optional @@ -367,7 +371,7 @@ def energy(self, rdm2s, eri=None, print_fragE=False): e2_ += self.efac[0] * e2[i] print( - "BE Energy Frag-{:>3} {:>12.7f} {:>12.7f} {:>12.7f}; Total : {:>12.7f}".format( + "BE Energy Frag-{:>3} {:>12.7f} {:>12.7f} {:>12.7f}; Total : {:>12.7f}".format( # noqa: E501 self.dname, e1_, ec_, e2_, etmp ) ) diff --git a/src/molbe/rdm.py b/src/molbe/rdm.py index 6131917a..57d6b451 100644 --- a/src/molbe/rdm.py +++ b/src/molbe/rdm.py @@ -24,7 +24,8 @@ def rdm1_fullbasis( only_rdm2 : bool, optional Whether to compute only the RDM2. Default is False. return_lo : bool, optional - Whether to return the RDMs in the localized orbital (LO) basis. Default is False. + Whether to return the RDMs in the localized orbital (LO) basis. + Default is False. return_RDM2 : bool, optional Whether to return the two-particle RDM (RDM2). Default is True. print_energy : bool, optional @@ -41,9 +42,11 @@ def rdm1_fullbasis( rdm2LO : numpy.ndarray The two-particle RDM in the LO basis (if return_lo and return_RDM2 are True). rdm1MO : numpy.ndarray - The one-particle RDM in the molecular orbital (MO) basis (if return_ao is False). + The one-particle RDM in the molecular orbital (MO) basis + (if return_ao is False). rdm2MO : numpy.ndarray - The two-particle RDM in the MO basis (if return_ao is False and return_RDM2 is True). + The two-particle RDM in the MO basis + (if return_ao is False and return_RDM2 is True). """ from pyscf import ao2mo @@ -61,7 +64,8 @@ def rdm1_fullbasis( drdm1 = fobjs.__rdm1.copy() drdm1[numpy.diag_indices(fobjs.nsocc)] -= 2.0 - # Compute the two-particle reduced density matrix (RDM2) and subtract non-connected component + # Compute the two-particle reduced density matrix (RDM2) and subtract + # non-connected component dm_nc = numpy.einsum( "ij,kl->ijkl", drdm1, drdm1, dtype=numpy.float64, optimize=True ) - 0.5 * numpy.einsum( @@ -212,7 +216,8 @@ def compute_energy_full( Parameters ---------- approx_cumulant : bool, optional - If True, use an approximate cumulant for the energy computation. Default is False. + If True, use an approximate cumulant for the energy computation. + Default is False. use_full_rdm : bool, optional If True, use the full two-particle RDM for energy computation. Default is False. return_rdm : bool, optional @@ -221,25 +226,28 @@ def compute_energy_full( Returns ------- tuple of numpy.ndarray or None - If `return_rdm` is True, returns a tuple containing the one-particle and two-particle - reduced density matrices (RDM1 and RDM2). Otherwise, returns None. + If `return_rdm` is True, returns a tuple containing the one-particle + and two-particle reduced density matrices (RDM1 and RDM2). + Otherwise, returns None. Notes ----- This function computes the total energy in the full basis, with options to use - approximate or true cumulants, and to return the reduced density matrices (RDMs). The - energy components are printed as part of the function's output. + approximate or true cumulants, and to return the reduced density matrices (RDMs). + The energy components are printed as part of the function's output. """ from pyscf import ao2mo, scf - # Compute the one-particle reduced density matrix (RDM1) and the cumulant (Kumul) in the full basis + # Compute the one-particle reduced density matrix (RDM1) and the cumulant (Kumul) + # in the full basis rdm1f, Kumul, rdm1_lo, rdm2_lo = self.rdm1_fullbasis( return_lo=True, return_RDM2=False ) if not approx_cumulant: - # Compute the true two-particle reduced density matrix (RDM2) if not using approximate cumulant + # Compute the true two-particle reduced density matrix (RDM2) if not using + # approximate cumulant Kumul_T = self.rdm1_fullbasis(only_rdm2=True) if return_rdm: diff --git a/src/molbe/solver.py b/src/molbe/solver.py index dbc09dfd..b3015ae5 100644 --- a/src/molbe/solver.py +++ b/src/molbe/solver.py @@ -43,7 +43,8 @@ def be_func( """ Perform bootstrap embedding calculations for each fragment. - This function computes the energy and/or error for each fragment in a molecular system using various quantum chemistry solvers. + This function computes the energy and/or error for each fragment in a + molecular system using various quantum chemistry solvers. Parameters ---------- @@ -85,7 +86,8 @@ def be_func( Returns ------- float or tuple - Depending on the options, it returns the norm of the error vector, the energy, or a combination of these values. + Depending on the options, it returns the norm of the error vector, the energy, + or a combination of these values. """ import os @@ -348,14 +350,16 @@ def be_func_u( """ Perform bootstrap embedding calculations for each fragment with UCCSD. - This function computes the energy and/or error for each fragment in a molecular system using various quantum chemistry solvers. + This function computes the energy and/or error for each fragment in a + molecular system using various quantum chemistry solvers. Parameters ---------- pot : list List of potentials. Fobjs : zip list of MolBE.fragpart, alpha and beta - List of fragment objects. Each element is a tuple with the alpha and beta components + List of fragment objects. Each element is a tuple with the alpha and + beta components solver : str Quantum chemistry solver to use ('UCCSD'). enuc : float @@ -383,7 +387,8 @@ def be_func_u( Returns ------- float or tuple - Depending on the options, it returns the norm of the error vector, the energy, or a combination of these values. + Depending on the options, it returns the norm of the error vector, the energy, + or a combination of these values. """ from molbe.external.unrestricted_utils import make_uhf_obj @@ -488,9 +493,9 @@ def solve_error(Fobjs, Nocc, only_chem=False): """ Compute the error for self-consistent fragment density matrix matching. - This function calculates the error in the one-particle density matrix for a given fragment, - matching the density matrix elements of the edges and centers. It returns the norm of the error - vector and the error vector itself. + This function calculates the error in the one-particle density matrix + for a given fragment, matching the density matrix elements of the edges and centers. + It returns the norm of the error vector and the error vector itself. Parameters ---------- @@ -565,8 +570,8 @@ def solve_mp2(mf, frozen=None, mo_coeff=None, mo_occ=None, mo_energy=None): """ Perform an MP2 (2nd order Moller-Plesset perturbation theory) calculation. - This function sets up and runs an MP2 calculation using the provided mean-field object. - It returns the MP2 object after the calculation. + This function sets up and runs an MP2 calculation using the provided + mean-field object. It returns the MP2 object after the calculation. Parameters ---------- @@ -623,8 +628,9 @@ def solve_ccsd( """ Solve the CCSD (Coupled Cluster with Single and Double excitations) equations. - This function sets up and solves the CCSD equations using the provided mean-field object. - It can return the CCSD amplitudes (t1, t2), the one- and two-particle density matrices, and the CCSD object. + This function sets up and solves the CCSD equations using the provided + mean-field object. It can return the CCSD amplitudes (t1, t2), + the one- and two-particle density matrices, and the CCSD object. Parameters ---------- @@ -639,7 +645,8 @@ def solve_ccsd( use_cumulant : bool, optional Whether to use cumulant-based energy expression. Defaults to False. with_dm1 : bool, optional - Whether to include one-particle density matrix in the two-particle density matrix calculation. Defaults to True. + Whether to include one-particle density matrix in the two-particle + density matrix calculation. Defaults to True. rdm2_return : bool, optional Whether to return the two-particle density matrix. Defaults to False. mo_occ : numpy.ndarray, optional @@ -656,9 +663,12 @@ def solve_ccsd( tuple - t1 (numpy.ndarray): Single excitation amplitudes. - t2 (numpy.ndarray): Double excitation amplitudes. - - rdm1a (numpy.ndarray, optional): One-particle density matrix (if rdm_return is True). - - rdm2s (numpy.ndarray, optional): Two-particle density matrix (if rdm2_return is True and rdm_return is True). - - cc__ (pyscf.cc.ccsd.CCSD, optional): CCSD object (if rdm_return is True and rdm2_return is False). + - rdm1a (numpy.ndarray, optional): One-particle density matrix + (if rdm_return is True). + - rdm2s (numpy.ndarray, optional): Two-particle density matrix + (if rdm2_return is True and rdm_return is True). + - cc__ (pyscf.cc.ccsd.CCSD, optional): CCSD object + (if rdm_return is True and rdm2_return is False). """ from pyscf import cc from pyscf.cc.ccsd_rdm import make_rdm2 @@ -735,9 +745,11 @@ def solve_block2(mf: object, nocc: int, frag_scratch: str = None, **solver_kwarg Parameters ---------- mf: pyscf.scf.hf.RHF - Mean field object or similar following the data signature of the pyscf.RHF class. + Mean field object or similar following the data signature of the + pyscf.RHF class. nocc: int - Number of occupied MOs in the fragment, used for constructing the fragment 1- and 2-RDMs. + Number of occupied MOs in the fragment, used for constructing the + fragment 1- and 2-RDMs. frag_scratch: str|pathlike, optional Fragment-level DMRG scratch directory. max_mem: int, optional @@ -751,7 +763,8 @@ def solve_block2(mf: object, nocc: int, frag_scratch: str = None, **solver_kwarg max_iter: int, optional Maximum number of sweeps. twodot_to_onedot: int, optional - Sweep index at which to transition to one-dot DMRG algorithm. All sweeps prior to this will use the two-dot algorithm. + Sweep index at which to transition to one-dot DMRG algorithm. + All sweeps prior to this will use the two-dot algorithm. block_extra_keyword: list(str), optional Other keywords to be passed to block2. See: https://block2.readthedocs.io/en/latest/user/keywords.html @@ -893,9 +906,11 @@ def solve_uccsd( verbose=0, ): """ - Solve the U-CCSD (Unrestricted Coupled Cluster with Single and Double excitations) equations. + Solve the U-CCSD (Unrestricted Coupled Cluster with Single and Double excitations) + equations. - This function sets up and solves the UCCSD equations using the provided mean-field object. + This function sets up and solves the UCCSD equations using the provided + mean-field object. It can return the one- and two-particle density matrices and the UCCSD object. Parameters @@ -913,7 +928,8 @@ def solve_uccsd( use_cumulant : bool, optional Whether to use cumulant-based energy expression. Defaults to False. with_dm1 : bool, optional - Whether to include one-particle density matrix in the two-particle density matrix calculation. Defaults to True. + Whether to include one-particle density matrix in the two-particle + density matrix calculation. Defaults to True. rdm2_return : bool, optional Whether to return the two-particle density matrix. Defaults to False. mo_occ : numpy.ndarray, optional @@ -929,8 +945,10 @@ def solve_uccsd( ------- tuple - ucc (pyscf.cc.ccsd.UCCSD): UCCSD object - - rdm1 (tuple, numpy.ndarray, optional): One-particle density matrix (if rdm_return is True). - - rdm2 (tuple, numpy.ndarray, optional): Two-particle density matrix (if rdm2_return is True and rdm_return is True). + - rdm1 (tuple, numpy.ndarray, optional): One-particle density matrix + (if rdm_return is True). + - rdm2 (tuple, numpy.ndarray, optional): Two-particle density matrix + (if rdm2_return is True and rdm_return is True). """ from pyscf import ao2mo, cc @@ -956,11 +974,11 @@ def ao2mofn(moish): s = ss break if s < 0: - raise RuntimeError("Input mo coeff matrix matches neither moa nor mob.") + raise ValueError("Input mo coeff matrix matches neither moa nor mob.") return ao2mo.incore.full(Vss[s], moish, compact=False) elif isinstance(moish, list) or isinstance(moish, tuple): if len(moish) != 4: - raise RuntimeError( + raise ValueError( "Expect a list/tuple of 4 numpy arrays but get %d of them." % len(moish) ) @@ -971,8 +989,9 @@ def ao2mofn(moish): numpy.allclose(moish_feature[2 * s], Cs_feature) and numpy.allclose(moish_feature[2 * s + 1], Cs_feature) ): - raise RuntimeError( - "Expect a list/tuple of 4 numpy arrays in the order (moa,moa,mob,mob)." + raise ValueError( + "Expect a list/tuple of 4 numpy arrays in the order " + "(moa,moa,mob,mob)." ) try: return ao2mo.incore.general(Vos, moish, compact=False) @@ -987,7 +1006,7 @@ def ao2mofn(moish): optimize=True, ) else: - raise RuntimeError( + raise TypeError( "moish must be either a numpy array or a list/tuple of 4 numpy arrays." ) @@ -1036,7 +1055,8 @@ def schmidt_decomposition( cinv : numpy.ndarray, optional Inverse of the transformation matrix. Defaults to None. rdm : numpy.ndarray, optional - Reduced density matrix. If not provided, it will be computed from the molecular orbitals. Defaults to None. + Reduced density matrix. If not provided, it will be computed from the molecular + orbitals. Defaults to None. norb : int, optional Specifies number of bath orbitals. Used for UBE to make alpha and beta spaces the same size. Defaults to None @@ -1050,7 +1070,8 @@ def schmidt_decomposition( Transformation matrix (TA) including both fragment and entangled bath orbitals. if return_orb_count: numpy.ndarray, int, int - returns TA (above), number of orbitals in the fragment space, and number of orbitals in bath space + returns TA (above), number of orbitals in the fragment space, and number of + orbitals in bath space """ import functools diff --git a/src/molbe/ube.py b/src/molbe/ube.py index 214c4a4d..1743c957 100644 --- a/src/molbe/ube.py +++ b/src/molbe/ube.py @@ -42,9 +42,9 @@ def __init__( ): """Initialize Unrestricted BE Object (ube🍠) ** NOTE ** - Currently only supports embedding Hamiltonian construction for molecular systems - In conjunction with molbe.misc.ube2fcidump, embedding Hamiltonians can be written - for external use. + Currently only supports embedding Hamiltonian construction for molecular + systems In conjunction with molbe.misc.ube2fcidump, + embedding Hamiltonians can be written for external use. See `unrestricted` branch for a work-in-progress full implmentation Parameters @@ -56,7 +56,8 @@ def __init__( eri_file : str, optional h5py file with ERIs, by default "eri_file.h5" lo_method : str, optional - Method for orbital localization. Supports 'lowdin', 'boys', and 'wannier', by default "lowdin" + Method for orbital localization. Supports 'lowdin', 'boys', and 'wannier', + by default "lowdin" """ self.unrestricted = True @@ -289,7 +290,8 @@ def initialize(self, eri_, compute_hf): b_TA = fobj_b.TA.shape if eri_ is None and self.mf.with_df is not None: # NOT IMPLEMENTED: should not be called, as no unrestricted DF tested - # for density-fitted integrals; if mf is provided, pyscf.ao2mo uses DF object in an outcore fashion + # for density-fitted integrals; if mf is provided, pyscf.ao2mo uses DF + # object in an outcore fashion eri_a = ao2mo.kernel(self.mf.mol, fobj_a.TA, compact=True) eri_b = ao2mo.kernel(self.mf.mol, fobj_b.TA, compact=True) else: @@ -371,7 +373,7 @@ def initialize(self, eri_, compute_hf): ) for I in range(self.Nfrag): print( - "| {:>2} | ({:>3},{:>3}) | ({:>3},{:>3}) | ({:>3},{:>3}) | ({:>3},{:>3}) |".format( + "| {:>2} | ({:>3},{:>3}) | ({:>3},{:>3}) | ({:>3},{:>3}) | ({:>3},{:>3}) |".format( # noqa: E501 I, all_noccs[I][0], all_noccs[I][1], diff --git a/tests/chem_dm_kBE_test.py b/tests/chem_dm_kBE_test.py index dcc0cc47..892678eb 100644 --- a/tests/chem_dm_kBE_test.py +++ b/tests/chem_dm_kBE_test.py @@ -1,5 +1,6 @@ """ -This script tests the period BE1 and BE2 workflows using chemical potential and density matching, respectively. +This script tests the period BE1 and BE2 workflows using chemical potential +and density matching, respectively. Also tests the gaussian density fitting interface, which is typically used by default. Author(s): Shaun Weatherly diff --git a/tests/chempot_molBE_test.py b/tests/chempot_molBE_test.py index 90daa152..a5cb5164 100644 --- a/tests/chempot_molBE_test.py +++ b/tests/chempot_molBE_test.py @@ -1,5 +1,6 @@ """ -This script tests the correlation energies of sample restricted molecular BE calculations from chemical potential matching +This script tests the correlation energies of sample restricted molecular +BE calculations from chemical potential matching Author(s): Minsik Cho """ diff --git a/tests/dm_molBE_test.py b/tests/dm_molBE_test.py index 672504d4..ef150817 100644 --- a/tests/dm_molBE_test.py +++ b/tests/dm_molBE_test.py @@ -1,5 +1,6 @@ """ -This script tests the correlation energies of sample restricted molecular BE calculations from density matching +This script tests the correlation energies of sample restricted molecular +BE calculations from density matching Author(s): Minsik Cho """ diff --git a/tests/eri_onthefly_test.py b/tests/eri_onthefly_test.py index 4880de22..7850185e 100644 --- a/tests/eri_onthefly_test.py +++ b/tests/eri_onthefly_test.py @@ -1,5 +1,6 @@ """ -This script tests the on-the-fly DF-based ERI transformation routine for molecular systems. +This script tests the on-the-fly DF-based ERI transformation routine for +molecular systems. Author(s): Minsik Cho """ diff --git a/tests/hf-in-hf_BE_test.py b/tests/hf-in-hf_BE_test.py index a41eb261..24166ea7 100644 --- a/tests/hf-in-hf_BE_test.py +++ b/tests/hf-in-hf_BE_test.py @@ -1,5 +1,6 @@ """ -This script tests the HF-in-HF energies of sample restricted molecular and periodic systems +This script tests the HF-in-HF energies of sample restricted molecular +and periodic systems Author(s): Minsik Cho """ From 51345ef1f47f401385bcf8515c34bae616e9303f Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Thu, 21 Nov 2024 10:59:24 -0500 Subject: [PATCH 3/3] fixed unnecessary linebreak --- src/kbe/helper.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/kbe/helper.py b/src/kbe/helper.py index 7c38a7b7..09e52097 100644 --- a/src/kbe/helper.py +++ b/src/kbe/helper.py @@ -13,8 +13,7 @@ def get_veff(eri_, dm, S, TA, hf_veff, return_veff0=False): and electron repulsion integrals. This function computes the effective potential by transforming the density matrix, - computing the Coulomb (J) and - exchange (K) integrals. + computing the Coulomb (J) and exchange (K) integrals. Parameters ----------