.. : 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 : : -- .. _hamiltonian_transformation: The AO/MO Transformation of the Hamiltonian ########################################### All post-HF methods in PyBEST are implemented for the (orthonormal) molecular orbital basis, while the Hamiltonian used in SCF calculations is expressed in the atomic orbital basis (see :ref:`user_molecularham_matrix_elements`). The AO/MO transformation is handled in all post-HF methods internally and the one- and two-electron integrals do not need to be transformed explicitly. If, however, an AO/MO transformation of the Hamiltonian is required, PyBEST provides the :py:func:`~pybest.orbital_utils.transform_integrals` function that transforms both one- and two-electron integrals to the MO basis. .. note:: :py:func:`~pybest.orbital_utils.transform_integrals` transforms the whole Hamiltonian to the MO basis. If only a subspace of the Hamiltonian has to be transformed, the :py:func:`~pybest.orbital_utils.split_core_active` function has to be used. See :ref:`hamiltonian_activespace` for more details on active space Hamiltonians. The :py:func:`~pybest.orbital_utils.transform_integrals` function requires all one- and two-electron integrals as input argument in any order. All one-electron terms will be collected and combined in one final transformed one-electron integral. The individual terms are defined in :ref:`user_molecularham_matrix_elements`. The :py:func:`~pybest.orbital_utils.transform_integrals` function is written in a general way so that it supports both **restricted** and **unrestricted** orbitals. Transform integrals for restricted orbitals =========================================== For restricted orbitals, the transformed one- and two-electron integrals are equivalent for alpha and beta orbitals and only one set of MO integrals is returned. Specifically, :py:func:`~pybest.orbital_utils.transform_integrals` returns an instance of the :py:class:`~pybest.io.iodata.IOData` container, where the transformed one- and two-electron integrals (expressed in the MO basis) are stored as a list in the attribute ``one`` and ``two`` (see also :ref:`user_iodata` for more details on the :py:class:`~pybest.io.iodata.IOData` container). .. code-block:: python # transform integrals for restricted orbitals orb ti_ = transform_integrals(kin, ne, er, orb) # transformed one-electron integrals: attribute 'one' (list) (one,) = ti_.one # or: one = ti_.one[0] # transformed two-electron integrals: attribute 'two' (list) (two,) = ti_.two # or: two = ti_.two[0] where ``kin`` and ``na`` (``er``) are the one- (two-)electron integrals expressed in the AO basis, ``orb`` are the molecular orbitals (for instance, the optimized canonical restricted HF orbitals). .. note:: Instead of passing the orbitals, we can also pass some :py:class:`~pybest.io.iodata.IOData` container (or a return value of some method) that contains some molecular orbitals. Transform integrals for unrestricted orbitals ============================================= In the case of unrestricted orbitals, the corresponding attributes of the :py:class:`~pybest.io.iodata.IOData` container returned by the :py:func:`~pybest.orbital_utils.transform_integrals` function form a list of 2 sets of one-electron integrals and 3 sets of two-electron integrals. The former correspond to the alpha-alpha and beta-beta blocks of the Hamiltonian, while the latter contains all possible spin combinations (alpha-alpha, alpha-beta, and beta-beta). Furthermore, for the unrestricted case, we have to pass both alpha (first argument) and beta (second argument) spin orbitals. .. code-block:: python # transform integrals for unrestricted orbitals orba and orbb ti_ = transform_integrals(kin, ne, er, orba, orbb) # one-electron integrals h_aa and h_bb one_mo_alpha, one_mo_beta = ti_.one # two-electron integrals , , and two_mo_alpha_alpha, two_mo_alpha_beta, two_mo_beta_beta = ti_.two Similarly, an :py:class:`~pybest.io.iodata.IOData` container can be passed that contains both alpha (stored as ``orb_a`` attribute) and beta (stored as ``orb_b`` attribute) orbitals instead of passing both orbitals explicitly.