def test_to_hdf5(self):
        """Test to_hdf5."""
        random = np.random.rand(2, 2, 2, 2)

        ints = TwoBodyElectronicIntegrals(ElectronicBasis.MO,
                                          (random, random, random, random))

        with tempfile.TemporaryFile() as tmp_file:
            with h5py.File(tmp_file, "w") as file:
                ints.to_hdf5(file)
Esempio n. 2
0
    def test_add(self):
        """Test addition."""
        mat_aa = np.arange(16).reshape((2, 2, 2, 2))
        mat_bb = np.arange(-16, 0).reshape((2, 2, 2, 2))

        ints_aa = TwoBodyElectronicIntegrals(ElectronicBasis.MO, (mat_aa, None, None, None))
        ints_bb = TwoBodyElectronicIntegrals(ElectronicBasis.MO, (mat_bb, None, None, None))

        ints_sum = ints_aa + ints_bb

        self.assertTrue(isinstance(ints_sum, TwoBodyElectronicIntegrals))
        self.assertTrue(np.allclose(ints_sum._matrices[0], mat_aa + mat_bb))
 def setUp(self):
     """Setup."""
     super().setUp()
     self.ints_1_ao = OneBodyElectronicIntegrals(ElectronicBasis.AO, (np.eye(2), None))
     self.ints_1_mo = OneBodyElectronicIntegrals(ElectronicBasis.MO, (np.eye(2), None))
     self.ints_2_ao = TwoBodyElectronicIntegrals(
         ElectronicBasis.AO, (np.ones((2, 2, 2, 2)), None, None, None)
     )
     self.ints_2_mo = TwoBodyElectronicIntegrals(
         ElectronicBasis.MO, (np.ones((2, 2, 2, 2)), None, None, None)
     )
     self.prop = IntegralProperty(
         "test", [self.ints_1_ao, self.ints_1_mo, self.ints_2_ao, self.ints_2_mo]
     )
Esempio n. 4
0
    def run(self) -> ElectronicStructureDriverResult:
        """Returns an ElectronicStructureDriverResult instance out of a FCIDump file."""
        fcidump_data = parse(self._fcidump_input)

        hij = fcidump_data.get("hij", None)
        hij_b = fcidump_data.get("hij_b", None)
        hijkl = fcidump_data.get("hijkl", None)
        hijkl_ba = fcidump_data.get("hijkl_ba", None)
        hijkl_bb = fcidump_data.get("hijkl_bb", None)

        multiplicity = fcidump_data.get("MS2", 0) + 1
        num_beta = (fcidump_data.get("NELEC") - (multiplicity - 1)) // 2
        num_alpha = fcidump_data.get("NELEC") - num_beta

        particle_number = ParticleNumber(
            num_spin_orbitals=fcidump_data.get("NORB") * 2,
            num_particles=(num_alpha, num_beta),
        )

        electronic_energy = ElectronicEnergy(
            [
                OneBodyElectronicIntegrals(ElectronicBasis.MO, (hij, hij_b)),
                TwoBodyElectronicIntegrals(ElectronicBasis.MO, (hijkl, hijkl_ba, hijkl_bb, None)),
            ],
            nuclear_repulsion_energy=fcidump_data.get("ecore", None),
        )

        driver_result = ElectronicStructureDriverResult()
        driver_result.add_property(electronic_energy)
        driver_result.add_property(particle_number)

        return driver_result
    def test_from_hdf5(self):
        """Test from_hdf5."""
        random = np.random.rand(2, 2, 2, 2)

        ints = TwoBodyElectronicIntegrals(ElectronicBasis.MO,
                                          (random, random, random, random))

        with tempfile.TemporaryFile() as tmp_file:
            with h5py.File(tmp_file, "w") as file:
                ints.to_hdf5(file)

            with h5py.File(tmp_file, "r") as file:
                new_ints = TwoBodyElectronicIntegrals.from_hdf5(
                    file["TwoBodyElectronicIntegrals"])

                self.assertEqual(ints, new_ints)
Esempio n. 6
0
    def test_compose(self):
        """Test composition."""
        mat_aa = np.arange(16).reshape((2, 2, 2, 2))
        mat_b = np.arange(-4, 0).reshape((2, 2))

        ints_aa = TwoBodyElectronicIntegrals(ElectronicBasis.AO, (mat_aa, None, None, None))
        ints_b = OneBodyElectronicIntegrals(ElectronicBasis.AO, (mat_b, None))

        einsum = "ijkl,ji->kl"
        composition = ints_aa.compose(ints_b, einsum)

        expected = np.einsum(einsum, mat_aa, mat_b)

        self.assertTrue(isinstance(composition, OneBodyElectronicIntegrals))
        self.assertTrue(composition._basis, ElectronicBasis.AO)
        self.assertTrue(np.allclose(composition._matrices[0], expected))
Esempio n. 7
0
    def _populate_driver_result_electronic_energy(
            self, driver_result: ElectronicStructureDriverResult) -> None:
        # pylint: disable=import-error
        from pyquante2 import onee_integrals
        from pyquante2.ints.integrals import twoe_integrals

        basis_transform = driver_result.get_property(ElectronicBasisTransform)

        integrals = onee_integrals(self._bfs, self._mol)

        hij = integrals.T + integrals.V
        hijkl = twoe_integrals(self._bfs)

        one_body_ao = OneBodyElectronicIntegrals(ElectronicBasis.AO,
                                                 (hij, None))

        two_body_ao = TwoBodyElectronicIntegrals(
            ElectronicBasis.AO,
            (hijkl.transform(np.identity(self._nmo)), None, None, None),
        )

        one_body_mo = one_body_ao.transform_basis(basis_transform)
        two_body_mo = two_body_ao.transform_basis(basis_transform)

        electronic_energy = ElectronicEnergy(
            [one_body_ao, two_body_ao, one_body_mo, two_body_mo],
            nuclear_repulsion_energy=self._mol.nuclear_repulsion(),
            reference_energy=self._calc.energy,
        )

        if hasattr(self._calc, "orbe"):
            orbs_energy = self._calc.orbe
            orbs_energy_b = None
        else:
            orbs_energy = self._calc.orbea
            orbs_energy_b = self._calc.orbeb

        orbital_energies = ((orbs_energy, orbs_energy_b)
                            if orbs_energy_b is not None else orbs_energy)
        electronic_energy.orbital_energies = np.asarray(orbital_energies)

        electronic_energy.kinetic = OneBodyElectronicIntegrals(
            ElectronicBasis.AO, (integrals.T, None))
        electronic_energy.overlap = OneBodyElectronicIntegrals(
            ElectronicBasis.AO, (integrals.S, None))

        driver_result.add_property(electronic_energy)
    def test_init(self):
        """Test construction."""
        random = np.random.rand(2, 2, 2, 2)

        with self.subTest("Normal"):
            TwoBodyElectronicIntegrals(ElectronicBasis.MO,
                                       (random, None, None, None))

        with self.subTest("Alpha and beta"):
            TwoBodyElectronicIntegrals(ElectronicBasis.MO,
                                       (random, random, random, random))

        with self.subTest("Alpha and beta but transpose last one"):
            TwoBodyElectronicIntegrals(ElectronicBasis.MO,
                                       (random, random, random, None))

        with self.subTest("Spin"):
            TwoBodyElectronicIntegrals(ElectronicBasis.SO, random)

        with self.subTest("Mismatching basis and number of matrices"):
            with self.assertRaises(TypeError):
                TwoBodyElectronicIntegrals(ElectronicBasis.MO, random)

        with self.subTest("Mismatching basis and number of matrices 2"):
            with self.assertRaises(TypeError):
                TwoBodyElectronicIntegrals(ElectronicBasis.SO,
                                           (random, None, None, None))

        with self.subTest("Missing alpha"):
            with self.assertRaises(TypeError):
                TwoBodyElectronicIntegrals(ElectronicBasis.MO,
                                           (None, random, random, random))
Esempio n. 9
0
    def test_mul(self):
        """Test multiplication."""
        mat_aa = np.arange(16).reshape((2, 2, 2, 2))

        ints_aa = TwoBodyElectronicIntegrals(ElectronicBasis.MO, (mat_aa, None, None, None))

        ints_mul = 2.0 * ints_aa

        self.assertTrue(isinstance(ints_mul, TwoBodyElectronicIntegrals))
        self.assertTrue(np.allclose(ints_mul._matrices[0], 2.0 * mat_aa))
Esempio n. 10
0
    def _populate_driver_result_electronic_energy(
            self, driver_result: ElectronicStructureDriverResult) -> None:
        # pylint: disable=import-error
        from pyscf import gto

        basis_transform = driver_result.get_property(ElectronicBasisTransform)

        one_body_ao = OneBodyElectronicIntegrals(
            ElectronicBasis.AO,
            (self._calc.get_hcore(), None),
        )

        two_body_ao = TwoBodyElectronicIntegrals(
            ElectronicBasis.AO,
            (self._mol.intor("int2e", aosym=1), None, None, None),
        )

        one_body_mo = one_body_ao.transform_basis(basis_transform)
        two_body_mo = two_body_ao.transform_basis(basis_transform)

        electronic_energy = ElectronicEnergy(
            [one_body_ao, two_body_ao, one_body_mo, two_body_mo],
            nuclear_repulsion_energy=gto.mole.energy_nuc(self._mol),
            reference_energy=self._calc.e_tot,
        )

        electronic_energy.kinetic = OneBodyElectronicIntegrals(
            ElectronicBasis.AO,
            (self._mol.intor_symmetric("int1e_kin"), None),
        )
        electronic_energy.overlap = OneBodyElectronicIntegrals(
            ElectronicBasis.AO,
            (self._calc.get_ovlp(), None),
        )

        orbs_energy, orbs_energy_b = self._extract_mo_data("mo_energy")
        orbital_energies = ((orbs_energy, orbs_energy_b)
                            if orbs_energy_b is not None else orbs_energy)
        electronic_energy.orbital_energies = np.asarray(orbital_energies)

        driver_result.add_property(electronic_energy)
    def test_to_spin(self):
        """Test to_spin"""
        mat_aa = np.arange(16).reshape((2, 2, 2, 2))
        mat_ba = np.arange(16, 32).reshape((2, 2, 2, 2))
        mat_bb = np.arange(-16, 0).reshape((2, 2, 2, 2))

        with self.subTest("Only alpha"):
            ints = TwoBodyElectronicIntegrals(ElectronicBasis.MO,
                                              (mat_aa, None, None, None))
            mat_so = ints.to_spin()
            expected = np.fromfile(
                self.get_resource_path(
                    "two_body_test_to_spin_only_alpha_expected.numpy.bin",
                    "properties/second_quantization/electronic/integrals/resources",
                )).reshape((4, 4, 4, 4))
            self.assertTrue(np.allclose(mat_so, expected))

        with self.subTest("Alpha and beta"):
            ints = TwoBodyElectronicIntegrals(
                ElectronicBasis.MO, (mat_aa, mat_ba, mat_bb, mat_ba.T))
            mat_so = ints.to_spin()
            expected = np.fromfile(
                self.get_resource_path(
                    "two_body_test_to_spin_alpha_and_beta_expected.numpy.bin",
                    "properties/second_quantization/electronic/integrals/resources",
                )).reshape((4, 4, 4, 4))
            self.assertTrue(np.allclose(mat_so, expected))
    def test_aux_ops_reusability(self):
        """Test that the auxiliary operators can be reused"""
        # Regression test against #1475
        solver = NumPyMinimumEigensolverFactory()
        calc = GroundStateEigensolver(self.qubit_converter, solver)

        modes = 4
        h_1 = np.eye(modes, dtype=complex)
        h_2 = np.zeros((modes, modes, modes, modes))
        aux_ops = ElectronicEnergy([
            OneBodyElectronicIntegrals(ElectronicBasis.MO, (h_1, None)),
            TwoBodyElectronicIntegrals(ElectronicBasis.MO,
                                       (h_2, None, None, None)),
        ], ).second_q_ops()
        aux_ops_copy = copy.deepcopy(aux_ops)

        _ = calc.solve(self.electronic_structure_problem)
        assert all(
            frozenset(a.to_list()) == frozenset(b.to_list())
            for a, b in zip(aux_ops, aux_ops_copy))
Esempio n. 13
0
    def test_aux_ops_reusability(self):
        """Test that the auxiliary operators can be reused"""
        # Regression test against #1475
        solver = VQEUCCFactory(
            QuantumInstance(BasicAer.get_backend("statevector_simulator")))
        calc = AdaptVQE(self.qubit_converter, solver)

        modes = 4
        h_1 = np.eye(modes, dtype=complex)
        h_2 = np.zeros((modes, modes, modes, modes))
        aux_ops = ElectronicEnergy([
            OneBodyElectronicIntegrals(ElectronicBasis.MO, (h_1, None)),
            TwoBodyElectronicIntegrals(ElectronicBasis.MO,
                                       (h_2, None, None, None)),
        ]).second_q_ops()
        aux_ops_copy = copy.deepcopy(aux_ops)

        _ = calc.solve(self.problem)
        assert all(
            frozenset(a.to_list()) == frozenset(b.to_list())
            for a, b in zip(aux_ops, aux_ops_copy))
def build_ferm_op_from_ints(
        one_body_integrals: np.ndarray,
        two_body_integrals: np.ndarray = None) -> FermionicOp:
    """**DEPRECATED!**
    Builds a fermionic operator based on 1- and/or 2-body integrals. Integral values are used for
    the coefficients of the second-quantized Hamiltonian that is built. If integrals are stored
    in the '*chemist*' notation
             h2(i,j,k,l) --> adag_i adag_k a_l a_j
    they are required to be in block spin format and also have indices reordered as follows
    'ijkl->ljik'.
    There is another popular notation, the '*physicist*' notation
             h2(i,j,k,l) --> adag_i adag_j a_k a_l
    If you are using the '*physicist*' notation, you need to convert it to
    the '*chemist*' notation. E.g. h2=numpy.einsum('ikmj->ijkm', h2)
    The :class:`~qiskit_nature.drivers.QMolecule` class has
    :attr:`~qiskit_nature.drivers.QMolecule.one_body_integrals` and
    :attr:`~qiskit_nature.drivers.QMolecule.two_body_integrals` properties that
    can be directly supplied to the `h1` and `h2` parameters here respectively.

    Args:
        one_body_integrals (numpy.ndarray): One-body integrals stored in the chemist notation.
        two_body_integrals (numpy.ndarray): Two-body integrals stored in the chemist notation.

    Returns:
        FermionicOp: FermionicOp built from 1- and/or 2-body integrals.
    """
    integrals: List[ElectronicIntegrals] = []
    integrals.append(
        OneBodyElectronicIntegrals(ElectronicBasis.SO, one_body_integrals))
    if two_body_integrals is not None:
        integrals.append(
            TwoBodyElectronicIntegrals(ElectronicBasis.SO, two_body_integrals))

    prop = IntegralProperty("", integrals)

    fermionic_op = prop.second_q_ops()[0]

    return fermionic_op
Esempio n. 15
0
    def run(self) -> ElectronicStructureDriverResult:
        """Returns an ElectronicStructureDriverResult instance out of a FCIDump file."""
        fcidump_data = parse(self._fcidump_input)

        hij = fcidump_data.get("hij", None)
        hij_b = fcidump_data.get("hij_b", None)
        hijkl = fcidump_data.get("hijkl", None)
        hijkl_ba = fcidump_data.get("hijkl_ba", None)
        hijkl_bb = fcidump_data.get("hijkl_bb", None)

        multiplicity = fcidump_data.get("MS2", 0) + 1
        num_beta = (fcidump_data.get("NELEC") - (multiplicity - 1)) // 2
        num_alpha = fcidump_data.get("NELEC") - num_beta

        particle_number = ParticleNumber(
            num_spin_orbitals=fcidump_data.get("NORB") * 2,
            num_particles=(num_alpha, num_beta),
        )

        electronic_energy = ElectronicEnergy(
            [
                OneBodyElectronicIntegrals(ElectronicBasis.MO, (hij, hij_b)),
                TwoBodyElectronicIntegrals(ElectronicBasis.MO, (hijkl, hijkl_ba, hijkl_bb, None)),
            ],
            nuclear_repulsion_energy=fcidump_data.get("ecore", None),
        )

        # NOTE: under Python 3.6, pylint appears to be unable to properly identify this case of
        # nested abstract classes (cf. https://github.com/Qiskit/qiskit-nature/runs/3245395353).
        # However, since the tests pass I am adding an exception for this specific case.
        # pylint: disable=abstract-class-instantiated
        driver_result = ElectronicStructureDriverResult()
        driver_result.add_property(electronic_energy)
        driver_result.add_property(particle_number)

        return driver_result
    def test_to_second_q_op(self):
        """Test to_second_q_op"""
        mat_aa = np.arange(16).reshape((2, 2, 2, 2))
        mat_ba = np.arange(16, 32).reshape((2, 2, 2, 2))
        mat_bb = np.arange(-16, 0).reshape((2, 2, 2, 2))

        with self.subTest("Only alpha"):
            ints = TwoBodyElectronicIntegrals(ElectronicBasis.MO,
                                              (mat_aa, None, None, None))
            op = ints.to_second_q_op()
            with open(
                    self.get_resource_path(
                        "two_body_test_to_second_q_op_only_alpha_expected.json",
                        "properties/second_quantization/electronic/integrals/resources",
                    ),
                    "r",
                    encoding="utf8",
            ) as file:
                expected = json.load(file)
            for (real_label,
                 real_coeff), (exp_label,
                               exp_coeff) in zip(op.to_list(), expected):
                self.assertEqual(real_label, exp_label)
                self.assertTrue(np.isclose(real_coeff, exp_coeff))

        with self.subTest("Alpha and beta"):
            ints = TwoBodyElectronicIntegrals(
                ElectronicBasis.MO, (mat_aa, mat_ba, mat_bb, mat_ba.T))
            op = ints.to_second_q_op()
            with open(
                    self.get_resource_path(
                        "two_body_test_to_second_q_op_alpha_and_beta_expected.json",
                        "properties/second_quantization/electronic/integrals/resources",
                    ),
                    "r",
                    encoding="utf8",
            ) as file:
                expected = json.load(file)
            for (real_label,
                 real_coeff), (exp_label,
                               exp_coeff) in zip(op.to_list(), expected):
                self.assertEqual(real_label, exp_label)
                self.assertTrue(np.isclose(real_coeff, exp_coeff))
    def test_transform_basis(self):
        """Test transform_basis"""
        mat_aa = np.arange(16).reshape((2, 2, 2, 2))
        mat_ba = np.arange(16, 32).reshape((2, 2, 2, 2))
        mat_bb = np.arange(-16, 0).reshape((2, 2, 2, 2))

        transform = ElectronicBasisTransform(ElectronicBasis.AO,
                                             ElectronicBasis.MO, 2 * np.eye(2))

        with self.subTest("Pure Alpha"):
            ints_ao = TwoBodyElectronicIntegrals(ElectronicBasis.AO,
                                                 (mat_aa, None, None, None))
            ints_mo = ints_ao.transform_basis(transform)
            self.assertTrue(np.allclose(ints_mo._matrices[0], 16 * mat_aa))
            self.assertIsNone(ints_mo._matrices[1])
            self.assertIsNone(ints_mo._matrices[2])
            self.assertIsNone(ints_mo._matrices[3])

        with self.subTest("Alpha and Beta"):
            ints_ao = TwoBodyElectronicIntegrals(
                ElectronicBasis.AO, (mat_aa, mat_ba, mat_bb, mat_ba.T))
            ints_mo = ints_ao.transform_basis(transform)
            self.assertTrue(np.allclose(ints_mo._matrices[0], 16 * mat_aa))
            self.assertTrue(np.allclose(ints_mo._matrices[1], 16 * mat_ba))
            self.assertTrue(np.allclose(ints_mo._matrices[2], 16 * mat_bb))
            self.assertTrue(np.allclose(ints_mo._matrices[3], 16 * mat_ba.T))

        with self.subTest("Beta custom coeff with only alpha"):
            transform_beta = ElectronicBasisTransform(ElectronicBasis.AO,
                                                      ElectronicBasis.MO,
                                                      2 * np.eye(2),
                                                      3 * np.eye(2))
            ints_ao = TwoBodyElectronicIntegrals(ElectronicBasis.AO,
                                                 (mat_aa, None, None, None))
            ints_mo = ints_ao.transform_basis(transform_beta)
            self.assertTrue(np.allclose(ints_mo._matrices[0], 16 * mat_aa))
            self.assertTrue(np.allclose(ints_mo._matrices[1], 36 * mat_aa))
            self.assertTrue(np.allclose(ints_mo._matrices[2], 81 * mat_aa))
            self.assertTrue(np.allclose(ints_mo._matrices[3], 36 * mat_aa))

        with self.subTest("Beta custom coeff"):
            transform_beta = ElectronicBasisTransform(ElectronicBasis.AO,
                                                      ElectronicBasis.MO,
                                                      2 * np.eye(2),
                                                      3 * np.eye(2))
            ints_ao = TwoBodyElectronicIntegrals(
                ElectronicBasis.AO, (mat_aa, mat_ba, mat_bb, mat_ba.T))
            ints_mo = ints_ao.transform_basis(transform_beta)
            self.assertTrue(np.allclose(ints_mo._matrices[0], 16 * mat_aa))
            self.assertTrue(np.allclose(ints_mo._matrices[1], 36 * mat_ba))
            self.assertTrue(np.allclose(ints_mo._matrices[2], 81 * mat_bb))
            self.assertTrue(np.allclose(ints_mo._matrices[3], 36 * mat_ba.T))

        with self.subTest("Final basis match"):
            ints_ao = TwoBodyElectronicIntegrals(ElectronicBasis.MO,
                                                 (mat_aa, None, None, None))
            ints_mo = ints_ao.transform_basis(transform)
            self.assertEqual(ints_ao, ints_mo)

        with self.subTest("Inital basis mismatch"):
            with self.assertRaises(QiskitNatureError):
                ints_ao = TwoBodyElectronicIntegrals(ElectronicBasis.SO,
                                                     mat_aa)
                ints_ao.transform_basis(transform)
Esempio n. 18
0
    def test_arbitrary_active_orbitals(self):
        """Test manual selection of active orbital indices."""
        driver = HDF5Driver(hdf5_input=self.get_resource_path(
            "H2_631g.hdf5", "transformers/second_quantization/electronic"))
        driver_result = driver.run()

        trafo = ActiveSpaceTransformer(num_electrons=2,
                                       num_molecular_orbitals=2,
                                       active_orbitals=[0, 2])
        driver_result_reduced = trafo.transform(driver_result)

        expected = ElectronicStructureDriverResult()
        expected.add_property(
            ElectronicEnergy(
                [
                    OneBodyElectronicIntegrals(
                        ElectronicBasis.MO,
                        (
                            np.asarray([[-1.24943841, -0.16790838],
                                        [-0.16790838, -0.18307469]]),
                            None,
                        ),
                    ),
                    TwoBodyElectronicIntegrals(
                        ElectronicBasis.MO,
                        (
                            np.asarray([
                                [
                                    [[0.65209847, 0.16790822],
                                     [0.16790822, 0.53250905]],
                                    [[0.16790822, 0.10962908],
                                     [0.10962908, 0.11981429]],
                                ],
                                [
                                    [[0.16790822, 0.10962908],
                                     [0.10962908, 0.11981429]],
                                    [[0.53250905, 0.11981429],
                                     [0.11981429, 0.46345617]],
                                ],
                            ]),
                            None,
                            None,
                            None,
                        ),
                    ),
                ],
                energy_shift={"ActiveSpaceTransformer": 0.0},
            ))
        expected.add_property(
            ElectronicDipoleMoment([
                DipoleMoment(
                    "x",
                    [
                        OneBodyElectronicIntegrals(ElectronicBasis.MO,
                                                   (np.zeros((2, 2)), None))
                    ],
                    shift={"ActiveSpaceTransformer": 0.0},
                ),
                DipoleMoment(
                    "y",
                    [
                        OneBodyElectronicIntegrals(ElectronicBasis.MO,
                                                   (np.zeros((2, 2)), None))
                    ],
                    shift={"ActiveSpaceTransformer": 0.0},
                ),
                DipoleMoment(
                    "z",
                    [
                        OneBodyElectronicIntegrals(
                            ElectronicBasis.MO,
                            (np.asarray([[0.69447435, 0.0], [0.0, 0.69447435]
                                         ]), None),
                        )
                    ],
                    shift={"ActiveSpaceTransformer": 0.0},
                ),
            ]))
        self.assertDriverResult(driver_result_reduced, expected)
Esempio n. 19
0
    def test_tuple_num_electrons_with_manual_orbitals(self):
        """Regression test against https://github.com/Qiskit/qiskit-nature/issues/434."""
        driver = HDF5Driver(hdf5_input=self.get_resource_path(
            "H2_631g.hdf5", "transformers/second_quantization/electronic"))
        driver_result = driver.run()

        trafo = ActiveSpaceTransformer(
            num_electrons=(1, 1),
            num_molecular_orbitals=2,
            active_orbitals=[0, 1],
        )
        driver_result_reduced = trafo.transform(driver_result)

        expected = ElectronicStructureDriverResult()
        expected.add_property(
            ElectronicEnergy(
                [
                    OneBodyElectronicIntegrals(
                        ElectronicBasis.MO,
                        (np.asarray([[-1.24943841, 0.0], [0.0, -0.547816138]
                                     ]), None),
                    ),
                    TwoBodyElectronicIntegrals(
                        ElectronicBasis.MO,
                        (
                            np.asarray([
                                [
                                    [[0.652098466, 0.0], [0.0, 0.433536565]],
                                    [[0.0, 0.0794483182], [0.0794483182, 0.0]],
                                ],
                                [
                                    [[0.0, 0.0794483182], [0.0794483182, 0.0]],
                                    [[0.433536565, 0.0], [0.0, 0.385524695]],
                                ],
                            ]),
                            None,
                            None,
                            None,
                        ),
                    ),
                ],
                energy_shift={"ActiveSpaceTransformer": 0.0},
            ))
        expected.add_property(
            ElectronicDipoleMoment([
                DipoleMoment(
                    "x",
                    [
                        OneBodyElectronicIntegrals(ElectronicBasis.MO,
                                                   (np.zeros((2, 2)), None))
                    ],
                    shift={"ActiveSpaceTransformer": 0.0},
                ),
                DipoleMoment(
                    "y",
                    [
                        OneBodyElectronicIntegrals(ElectronicBasis.MO,
                                                   (np.zeros((2, 2)), None))
                    ],
                    shift={"ActiveSpaceTransformer": 0.0},
                ),
                DipoleMoment(
                    "z",
                    [
                        OneBodyElectronicIntegrals(
                            ElectronicBasis.MO,
                            (
                                np.asarray([[0.69447435, -1.01418298],
                                            [-1.01418298, 0.69447435]]),
                                None,
                            ),
                        )
                    ],
                    shift={"ActiveSpaceTransformer": 0.0},
                ),
            ]))

        self.assertDriverResult(driver_result_reduced, expected)
Esempio n. 20
0
    def _parse_matrix_file(
            fname: str,
            useao2e: bool = False) -> ElectronicStructureDriverResult:
        """
        get_driver_class is used here because the discovery routine will load all the gaussian
        binary dependencies, if not loaded already. It won't work without it.
        """
        try:
            # add gauopen to sys.path so that binaries can be loaded
            gauopen_directory = os.path.join(
                os.path.dirname(os.path.realpath(__file__)), "gauopen")
            if gauopen_directory not in sys.path:
                sys.path.insert(0, gauopen_directory)
            # pylint: disable=import-outside-toplevel
            from .gauopen.QCMatEl import MatEl
        except ImportError as mnfe:
            msg = ((
                "qcmatrixio extension not found. "
                "See Gaussian driver readme to build qcmatrixio.F using f2py")
                   if mnfe.name == "qcmatrixio" else str(mnfe))

            logger.info(msg)
            raise QiskitNatureError(msg) from mnfe

        mel = MatEl(file=fname)
        logger.debug("MatrixElement file:\n%s", mel)

        driver_result = ElectronicStructureDriverResult()

        # molecule
        coords = np.reshape(mel.c, (len(mel.ian), 3))
        geometry: list[tuple[str, list[float]]] = []
        for atom, xyz in zip(mel.ian, coords):
            geometry.append((PERIODIC_TABLE[atom], BOHR * xyz))

        driver_result.molecule = Molecule(
            geometry,
            multiplicity=mel.multip,
            charge=mel.icharg,
        )

        # driver metadata
        driver_result.add_property(DriverMetadata("GAUSSIAN", mel.gversion,
                                                  ""))

        # basis transform
        moc = GaussianDriver._get_matrix(mel, "ALPHA MO COEFFICIENTS")
        moc_b = GaussianDriver._get_matrix(mel, "BETA MO COEFFICIENTS")
        if np.array_equal(moc, moc_b):
            logger.debug(
                "ALPHA and BETA MO COEFFS identical, keeping only ALPHA")
            moc_b = None

        nmo = moc.shape[0]

        basis_transform = ElectronicBasisTransform(ElectronicBasis.AO,
                                                   ElectronicBasis.MO, moc,
                                                   moc_b)
        driver_result.add_property(basis_transform)

        # particle number
        num_alpha = (mel.ne + mel.multip - 1) // 2
        num_beta = (mel.ne - mel.multip + 1) // 2

        driver_result.add_property(
            ParticleNumber(num_spin_orbitals=nmo * 2,
                           num_particles=(num_alpha, num_beta)))

        # electronic energy
        hcore = GaussianDriver._get_matrix(mel, "CORE HAMILTONIAN ALPHA")
        logger.debug("CORE HAMILTONIAN ALPHA %s", hcore.shape)
        hcore_b = GaussianDriver._get_matrix(mel, "CORE HAMILTONIAN BETA")
        if np.array_equal(hcore, hcore_b):
            # From Gaussian interfacing documentation: "The two core Hamiltonians are identical
            # unless a Fermi contact perturbation has been applied."
            logger.debug(
                "CORE HAMILTONIAN ALPHA and BETA identical, keeping only ALPHA"
            )
            hcore_b = None
        logger.debug(
            "CORE HAMILTONIAN BETA %s",
            "- Not present" if hcore_b is None else hcore_b.shape,
        )
        one_body_ao = OneBodyElectronicIntegrals(ElectronicBasis.AO,
                                                 (hcore, hcore_b))
        one_body_mo = one_body_ao.transform_basis(basis_transform)

        eri = GaussianDriver._get_matrix(mel, "REGULAR 2E INTEGRALS")
        logger.debug("REGULAR 2E INTEGRALS %s", eri.shape)
        if moc_b is None and mel.matlist.get("BB MO 2E INTEGRALS") is not None:
            # It seems that when using ROHF, where alpha and beta coeffs are
            # the same, that integrals
            # for BB and BA are included in the output, as well as just AA
            # that would have been expected
            # Using these fails to give the right answer (is ok for UHF).
            # So in this case we revert to
            # using 2 electron ints in atomic basis from the output and
            # converting them ourselves.
            useao2e = True
            logger.info(
                "Identical A and B coeffs but BB ints are present - using regular 2E ints instead"
            )
        two_body_ao = TwoBodyElectronicIntegrals(ElectronicBasis.AO,
                                                 (eri, None, None, None))
        two_body_mo: TwoBodyElectronicIntegrals
        if useao2e:
            # eri are 2-body in AO. We can convert to MO via the ElectronicBasisTransform but using
            # ints in MO already, as in the else here, is better
            two_body_mo = two_body_ao.transform_basis(basis_transform)
        else:
            # These are in MO basis but by default will be reduced in size by frozen core default so
            # to use them we need to add Window=Full above when we augment the config
            mohijkl = GaussianDriver._get_matrix(mel, "AA MO 2E INTEGRALS")
            logger.debug("AA MO 2E INTEGRALS %s", mohijkl.shape)
            mohijkl_bb = GaussianDriver._get_matrix(mel, "BB MO 2E INTEGRALS")
            logger.debug(
                "BB MO 2E INTEGRALS %s",
                "- Not present" if mohijkl_bb is None else mohijkl_bb.shape,
            )
            mohijkl_ba = GaussianDriver._get_matrix(mel, "BA MO 2E INTEGRALS")
            logger.debug(
                "BA MO 2E INTEGRALS %s",
                "- Not present" if mohijkl_ba is None else mohijkl_ba.shape,
            )
            two_body_mo = TwoBodyElectronicIntegrals(
                ElectronicBasis.MO, (mohijkl, mohijkl_ba, mohijkl_bb, None))

        electronic_energy = ElectronicEnergy(
            [one_body_ao, two_body_ao, one_body_mo, two_body_mo],
            nuclear_repulsion_energy=mel.scalar("ENUCREP"),
            reference_energy=mel.scalar("ETOTAL"),
        )

        kinetic = GaussianDriver._get_matrix(mel, "KINETIC ENERGY")
        logger.debug("KINETIC ENERGY %s", kinetic.shape)
        electronic_energy.kinetic = OneBodyElectronicIntegrals(
            ElectronicBasis.AO, (kinetic, None))

        overlap = GaussianDriver._get_matrix(mel, "OVERLAP")
        logger.debug("OVERLAP %s", overlap.shape)
        electronic_energy.overlap = OneBodyElectronicIntegrals(
            ElectronicBasis.AO, (overlap, None))

        orbs_energy = GaussianDriver._get_matrix(mel, "ALPHA ORBITAL ENERGIES")
        logger.debug("ORBITAL ENERGIES %s", overlap.shape)
        orbs_energy_b = GaussianDriver._get_matrix(mel,
                                                   "BETA ORBITAL ENERGIES")
        logger.debug("BETA ORBITAL ENERGIES %s", overlap.shape)
        orbital_energies = (
            orbs_energy, orbs_energy_b) if moc_b is not None else orbs_energy
        electronic_energy.orbital_energies = np.asarray(orbital_energies)

        driver_result.add_property(electronic_energy)

        # dipole moment
        dipints = GaussianDriver._get_matrix(mel, "DIPOLE INTEGRALS")
        dipints = np.einsum("ijk->kji", dipints)

        x_dip_ints = OneBodyElectronicIntegrals(ElectronicBasis.AO,
                                                (dipints[0], None))
        y_dip_ints = OneBodyElectronicIntegrals(ElectronicBasis.AO,
                                                (dipints[1], None))
        z_dip_ints = OneBodyElectronicIntegrals(ElectronicBasis.AO,
                                                (dipints[2], None))

        x_dipole = DipoleMoment(
            "x", [x_dip_ints,
                  x_dip_ints.transform_basis(basis_transform)])
        y_dipole = DipoleMoment(
            "y", [y_dip_ints,
                  y_dip_ints.transform_basis(basis_transform)])
        z_dipole = DipoleMoment(
            "z", [z_dip_ints,
                  z_dip_ints.transform_basis(basis_transform)])

        nucl_dip = np.einsum("i,ix->x", mel.ian, coords)
        nucl_dip = np.round(nucl_dip, decimals=8)

        driver_result.add_property(
            ElectronicDipoleMoment(
                [x_dipole, y_dipole, z_dipole],
                nuclear_dipole_moment=nucl_dip,
                reverse_dipole_sign=True,
            ))

        # extra properties
        # TODO: once https://github.com/Qiskit/qiskit-nature/issues/312 is fixed we can stop adding
        # these properties by default.
        # if not settings.dict_aux_operators:
        driver_result.add_property(AngularMomentum(nmo * 2))
        driver_result.add_property(Magnetization(nmo * 2))

        return driver_result