class CoupledClusterSinglesDoubles(CoupledCluster):

    def __init__(self, hartree_fock, threshold=1e-12):
        super().__init__(hartree_fock, threshold)
        self.amplitudes_factory = SinglesDoubles(self.repulsion, self.orbital_energies, self.occupied_orbitals,
        self.unoccupied_orbitals)

    def calculate_singles_doubles(self):
        print('*************************************************************************************************')
        print('\nMP2 INITIAL GUESS')
        start = time.clock()
        amplitudes = self.amplitudes_factory.mp2_initial_guess()
        correlation = self.singles_doubles_correlation(amplitudes)
        print('MP2 CORRELATION ENERGY: ' + str(correlation) + ' a.u.')
        print('TIME TAKEN: ' + str(time.clock() - start) + 's')

        print('\n*************************************************************************************************')
        print('\nBEGIN CCSD ITERATIONS')
        start = time.clock()
        previous_correlation = 0

        while True:

            amplitudes = self.amplitudes_factory.calculate_amplitudes(amplitudes)
            correlation = self.singles_doubles_correlation(amplitudes)
            delta_energy = previous_correlation - correlation
            previous_correlation = correlation
            print('CCSD CORRELATION ENERGY: ' + str(correlation) + ' a.u.')

            if abs(delta_energy) < self.threshold:
                break

        print('TIME TAKEN: ' + str(time.clock() - start) + 's\n\n')

        return correlation, amplitudes

    def singles_doubles_correlation(self, t):
        correlation = 0
        for i, j, a, b in self.doubles():
            correlation += self.repulsion.item(i, j, a, b) * (0.25 * t[i, j, a, b] + 0.5 * t[i, a] * t[j, b])
        return correlation
 def __init__(self, hartree_fock, threshold=1e-12):
     super().__init__(hartree_fock, threshold)
     self.amplitudes_factory = SinglesDoubles(self.repulsion, self.orbital_energies, self.occupied_orbitals,
     self.unoccupied_orbitals)