.. : PyBEST: Pythonic Black-box Electronic Structure Tool : Copyright (C) 2016-- The PyBEST Development Team : : This file is part of PyBEST. : : PyBEST is free software; you can redistribute it and/or : modify it under the terms of the GNU General Public License : as published by the Free Software Foundation; either version 3 : of the License, or (at your option) any later version. : : PyBEST is distributed in the hope that it will be useful, : but WITHOUT ANY WARRANTY; without even the implied warranty of : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the : GNU General Public License for more details. : : You should have received a copy of the GNU General Public License : along with this program; if not, see : -- .. _modphysham: Model Hamiltonians ################## Supported Features ================== PyBEST includes a flexible framework for model Hamiltonians relevant to quantum chemistry and condensed matter physics. These models are implemented through a hierarchy of classes based on the abstract base class :py:class:`~pybest.modelhamiltonians.physical_model_base.PhysModBase`. The following Hamiltonians are currently supported: - Hückel model Hamiltonian (see :ref:`huckelham`) - Hubbard model Hamiltonian (see :ref:`hubbardham`) - Pariser-Parr-Pople (PPP) model Hamiltonian (see :ref:`pppham`) - Contact interaction model in 1D (see :ref:`contactham`) The Hückel and PPP models are built using adjacency matrices derived from covalent radii, allowing general applicability to π-conjugated systems. The Hubbard model is implemented as an extension of the Hückel model, and in the absence of an XYZ file, it defaults to a 1D lattice-based site model with support for both open and periodic boundary conditions. The PPP model extends the Hubbard model with long-range Coulomb interactions (V-terms). The Hamiltonian for 1D contact interactions can be combined with any arbitrary external potential. .. note:: Only ``DenseLinalgFactory`` is supported for model Hamiltonians (see also :ref:`user_linalg`). If you use model Hamiltonians, please cite [karimi2025]_. Preliminaries ============= Unlike full molecular Hamiltonians, physical model Hamiltonians do not require an atomic basis set to be defined. Thus, no :py:class:`~pybest.core.Basis` instance is needed. To begin, create a :py:class:`~pybest.linalg.dense.DenseLinalgFactory` instance for the number of atoms (or sites) in the system: .. code-block:: python # The number of sites is represented as a `LinalgFactory` object (indicating the number of supported atoms). lf = DenseLinalgFactory(n) The xyz structure can optionally be provided using the .xyz format by passing the ``xyz_file`` argument. In the 1D Hubbard model, we default to a site model if an xyz file is not provided (``xyz_file`` defaults to None). To work with physical model Hamiltonians, you must assign a proper occupation model representing your physical problem, that is, how many sites or states are filled by electrons. Currently, only the :py:class:`~pybest.occ_model.AufbauOccModel` is supported. .. code-block:: python # We assume n sites with one electron each, resulting in n/2 doubly-filled sites occ_model = AufbauOccModel(lf, nel=n) This allows later reuse in any model class constructor: .. code-block:: python # Calculate overlap matrix for the on-site basis olp = modelham.compute_overlap() Computing the Hamiltonian ========================= The general procedure to calculate model Hamiltonians in PyBEST is uniform across models and involves the following steps: 1. Instantiate the model Hamiltonian class (e.g., :py:class:`Huckel`, :py:class:`Hubbard`, and :py:class:`PPP`), providing the linear algebra factory, occupation model, and optionally the xyz structure. 2. Specify model-specific parameters as a dictionary, such as hopping strengths, on-site energies, interaction parameters (U, V), boundary conditions, etc. 3. Call the instance with the parameter dictionary to compute the Hamiltonian, which returns an object containing the one-body and two-body terms. 4. The one-body terms are calculated using the method :py:meth:`compute_one_body` with hopping parameters, and the two-body terms via :py:meth:`compute_two_body` with interaction parameters. 5. Model Hamiltonian classes (e.g., :py:class:`Huckel`, :py:class:`Hubbard`, :py:class:`PPP`) support an optional ``"rhf"`` boolean parameter. When set to ``True`` (default), the model will internally perform a Restricted Hartree-Fock (RHF) calculation during its evaluation and return the result. To skip the RHF calculation (e.g., if you only want the tight-binding data), set ``"rhf": False``. 6. The resulting Hamiltonian can then be used seamlessly in wave function methods such as RHF, pCCD, or other post-HF calculations. Examples for each model are provided in their respective sections below. Specifying Model Hamiltonian Parameters --------------------------------------- Model parameters are passed as a dictionary when invoking the model instance, allowing flexible tuning of physical quantities: - For the Hückel model, typical parameters include: - ``hopping``: nearest-neighbor hopping integral (e.g., -1.0) - ``on_site``: on-site energy (often 0.0) - ``rhf``: boolean to enable RHF calculation. - For the Hubbard model, the Hückel parameters dictionary contains the additional keys: - ``u``: on-site interaction strength - ``pbc``: boolean for periodic boundary conditions (for the 1D-Hubbard model). - For the PPP model, additional keys are: - ``k``: dielectric constant for screening in the Coulomb interaction - ``hubbard``: boolean to enable Hubbard-type interactions - ``u`` and ``hopping`` similarly defined, often in electronvolts - For the 1D Contact Interaction, accepted parameter keys are: - ``grid``: tuple specifying the spatial domain and discretization, given as (x_min, x_max, dx) (e.g., (-10.0, 10.0, 0.05)), which defines the DVR grid. - ``mass``: mass of the particle in atomic units (default is 1.0), representing the fermion mass used in kinetic energy calculations. - ``g_coupling``: coupling strength of the contact interaction (e.g., 2.0), scaling the two-body interaction integrals. Changing these parameters allows modeling different physical regimes or fitting to experimental data. .. note:: In Hückel, Hubbard and PPP model Hamiltonians, if you want to run only the RHF calculation with the given Hamiltonian, set ``"rhf": True`` in the parameters dictionary and call the model Hamiltonian instance once. .. _huckelham: Hückel Hamiltonian ================== The Hückel model Hamiltonian features the tight-binding and Hartree-Fock methods for electronic structure calculations. .. math:: :label: huckel \hat{H}_{\rm Huckel} = -\sum_{i,j} t_{ij} \left( c_i^\dagger c_j + c_j^\dagger c_i \right) where :math:`t_{ij}` is the hopping integral between atoms :math:`i` and :math:`j`. The molecular structure is encoded through the adjacency matrix derived from covalent radii and interatomic distances. The list of currently supported atoms is - Carbon - Oxygen - Nitrogen - Fluorine - Aluminum - Silicon - Phosphorus - Sulfur - Chlorine - Gallium - Germanium - Arsenic - Selenium - Bromine Usage Example ------------- To construct the Hückel Hamiltonian, create an instance of the :py:class:`~pybest.modelhamiltonians.huckel_model.Huckel` class providing a linear algebra factory and an optional xyz structure file: .. code-block:: python # Instantiate the Hückel class providing the xyz structure filename (an xyz file, here ``"mol.xyz"``) modelham = Huckel(lf, occ_model, xyz_file="mol.xyz") # Use modelham to compute Hückel Hamiltonian with the following parameters # "rhf"=True runs an RHF calculation with the defined Hamiltonian huckel_output = modelham( parameters={"on_site": 0.0, "hopping": -1.0, "rhf": True} ) # Set the parameters internally (without running RHF) so that compute_one_body # and compute_two_body methods can access these parameters when called modelham(parameters={"on_site": 0.0, "hopping": -1.0}) # compute the one-body term (tight-binding Hamiltonian) # Calculate hopping term one_body = modelham.compute_one_body() # Compute the two-body term (zero tensor for Hückel, required for RHF/post-HF) two_body = modelham.compute_two_body() .. note:: The hopping parameter ``hopping`` is directly used in the method :py:meth:`~pybest.modelhamiltonians.huckel_model."py:func:`~pybest.modelhamiltonians.huckel_model.compute_one_body` to calculate the hopping term. The two-body term in the Hückel model is constructed using :py:meth:`~pybest.modelhamiltonians.huckel_model."py:func:`~pybest.modelhamiltonians.huckel_model.compute_two_body`, which returns a zero-initialized four-index tensor of electron repulsion integrals labeled ``"eri"``. While the Hückel model neglects electron–electron interactions, this zero-valued tensor is still required to satisfy the interface expected by PyBEST’s Hartree–Fock (RHF) and post-HF methods. It has to be created in order to run RHF (or any post-RHF) calculations, as otherwise PyBEST will raise an error. By defining both the one-body and two-body parts, the Hückel Hamiltonian is fully defined and can be seamlessly used in any wave function-based method available in PyBEST. .. _hubbardham: Hubbard Hamiltonian =================== The Hubbard model extends the Hückel framework by adding an on-site electron-electron interaction (U-term), capturing basic electron correlation effects. It can be understood as a tight-binding model with an additional on-site repulsion (or attraction) term parameterized by :math:`U`. .. math:: :label: hubbard \hat{H}_{\rm Hubbard} = -\sum_{i,j} t_{ij} \left( c_i^\dagger c_j + c_j^\dagger c_i \right) +U\sum_j n_{j\uparrow} n_{j\downarrow} Usage Example ------------- .. code-block:: python # Instantiate the Hubbard class providing the xyz structure filename (an xyz file, here "mol.xyz") modelham = Hubbard(lf, occ_model, xyz_file="mol.xyz") # If the xyz file is not provided, a site model is assumed # Instantiate the 1D-Hubbard class with periodic boundary condition (parameters are set below) modelham = Hubbard(lf, occ_model, pbc=True) # Use modelham to compute the Hubbard Hamiltonian with the following parameters hubbard_output = modelham( parameters={"on_site": 0.0, "hopping": -1.0, "u": 1.0} ) The nearest-neighbor hopping term (``hopping`` in eq. :eq:`hubbard`) is calculated using the method :py:meth:`~pybest.modelhamiltonians.Hubbard_model.compute_one_body` of the :py:class:`~pybest.modelhamiltonians.Hubbard` class, while the on-site repulsion term (:math:`U`) is calculated using the :py:meth:`~pybest.modelhamiltonians.Hubbard_model.compute_two_body` method: .. code-block:: python modelham(parameters={"on_site": 0.0, "hopping": -1.0, "u": 1.0}) # Calculate hopping term one_body = modelham.compute_one_body() # Calculate on-site electron-electron repulsion term two_body = modelham.compute_two_body() .. note:: The two-body term in the Hubbard model is constructed using :py:meth:`~pybest.modelhamiltonians.Hubbard_model.compute_two_body`, which defines a minimal form of electron–electron interaction by assigning the on-site repulsion parameter :math:`U` to the diagonal elements of the four-index electron repulsion tensor. As in the Huckel models within PyBEST, both the one-body and two-body components must be defined to construct a valid Hamiltonian. The inclusion of the two-body term is necessary to run HF or any post-HF methods, as PyBEST requires an electron repulsion integrals labeled ``"eri"`` for all wave function-based calculations. - The hopping term is a two-index object of ``DenseLinalgFactory``. - The on-site interaction is a four-index object of ``DenseLinalgFactory``. .. _pppham: PPP Hamiltonian =============== The Pariser-Parr-Pople (PPP) model extends the Hubbard model by including long-range Coulomb interactions in addition to the on-site interaction. It is particularly well-suited for accurate modeling of large π-conjugated systems. .. math:: :label: ppp \hat{H}_{\mathrm{PPP}} = - \sum_{i,j} t_{ij} \left( c_i^\dagger c_j + c_j^\dagger c_i \right) + U \sum_i n_{i\uparrow} n_{i\downarrow} + \sum_{i