//  [python]
def calculate_energy(self, system):
        if self.verbose:
            print("# Computing trial energy.")
        if self.symmetrize:
            num_energy = 0.0
            num_e1b = 0.0
            num_e2b = 0.0
            denom = 0.0
            if len(self.psi.shape) == 3:  # multicoherent given
                betas = self.shift * numpy.sqrt(system.m * system.w0 / 2.0)
                for iperm in range(self.nperms):
                    psia = self.psi[iperm, :, : system.nup]
                    psib = self.psi[iperm, :, system.nup :]
                    G = [gab(psia, psia), gab(psib, psib)]
                    shift = self.shift[iperm, :]
                    beta = betas[iperm, :]

                    phi = HarmonicOscillator(system.m, system.w0, order=0, shift=shift)
                    Lap = phi.laplacian(shift)

                    (energy_i, e1b_i, e2b_i) = local_energy_hubbard_holstein_jax(
                        system.T, system.U, system.g, system.m, system.w0, G, shift, Lap
                    )
                    overlap = (
                        numpy.linalg.det(psia.T.dot(psia))
                        * numpy.linalg.det(psib.T.dot(psib))
                        * numpy.exp(-0.5 * numpy.sum((beta**2 + beta**2))) * numpy.exp(numpy.sum(beta * beta))
                    )

                    num_energy += energy_i * numpy.abs(self.coeffs[iperm]) ** 2 * overlap
                    num_e1b += e1b_i * numpy.abs(self.coeffs[iperm]) ** 2 * overlap
                    num_e2b += e2b_i * numpy.abs(self.coeffs[iperm]) ** 2 * overlap
                    denom += overlap * numpy.abs(self.coeffs[iperm]) ** 2

                    for jperm in range(iperm + 1, self.nperms):
                        psia_j = self.psi[jperm, :, : system.nup]
                        psib_j = self.psi[jperm, :, system.nup :]
                        G_j = [gab(psia, psia_j), gab(psib, psib_j)]
                        beta_j = betas[jperm, :]

                        rho = G_j[0].diagonal() + G_j[1].diagonal()
                        ke = numpy.sum(system.T[0] * G_j[0] + system.T[1] * G_j[1])
                        pe = system.U * numpy.dot(G_j[0].diagonal(), G_j[1].diagonal())
                        e_ph = system.w0 * numpy.sum(beta * beta_j)
                        e_eph = -system.g * numpy.dot(rho, beta + beta_j)

                        overlap = (
                            numpy.linalg.det(psia.T.dot(psia_j))
                            * numpy.linalg.det(psib.T.dot(psib_j))
                            * numpy.exp(-0.5 * numpy.sum((beta**2 + beta_j**2))) * numpy.exp(numpy.sum(beta * beta_j))
                        )

                        num_energy += (
                            (ke + pe + e_ph + e_eph)
                            * overlap
                            * self.coeffs[iperm]
                            * self.coeffs[jperm]
                            * 2.0
                        )  # 2.0 comes from hermiticity
                        num_e1b += (
                            (ke + pe) * overlap * self.coeffs[iperm] * self.coeffs[jperm] * 2.0
                        )  # 2.0 comes from hermiticity
                        num_e2b += (
                            (e_ph + e_eph) * overlap * self.coeffs[iperm] * self.coeffs[jperm] * 2.0
                        )  # 2.0 comes from hermiticity

                        denom += overlap * self.coeffs[iperm] * self.coeffs[jperm] * 2.0
            else:
                # single coherent state energy
                phi = HarmonicOscillator(system.m, system.w0, order=0, shift=self.shift)
                Lap = phi.laplacian(self.shift)
                (energy_single, e1b_single, e2b_single,) = local_energy_hubbard_holstein_jax(
                    system.T,
                    system.U,
                    system.g,
                    system.m,
                    system.w0,
                    self.G,
                    self.shift,
                    Lap,
                )

                psia = self.psi[:, : system.nup]
                psib = self.psi[:, system.nup :]

                beta = self.shift * numpy.sqrt(system.m * system.w0 / 2.0)

                for iperm in range(self.nperms):
                    ipermutation = self.perms[iperm]
                    psia_iperm = psia[ipermutation, :].copy()
                    psib_iperm = psib[ipermutation, :].copy()
                    beta_iperm = beta[ipermutation].copy()

                    num_energy += energy_single * self.coeffs[iperm] ** 2
                    num_e1b += e1b_single * self.coeffs[iperm] ** 2
                    num_e2b += e2b_single * self.coeffs[iperm] ** 2

                    denom += self.coeffs[iperm] ** 2

                    for jperm in range(iperm + 1, self.nperms):
                        jpermutation = self.perms[jperm]
                        psia_jperm = psia[jpermutation, :].copy()
                        psib_jperm = psib[jpermutation, :].copy()
                        beta_jperm = beta[jpermutation].copy()
                        Ga = gab(psia_iperm, psia_jperm)
                        Gb = gab(psib_iperm, psib_jperm)
                        rho = Ga.diagonal() + Gb.diagonal()

                        ke = numpy.sum(system.T[0] * Ga + system.T[1] * Gb)
                        pe = system.U * numpy.dot(Ga.diagonal(), Gb.diagonal())
                        e_ph = system.w0 * numpy.sum(beta_iperm * beta_jperm)
                        e_eph = -system.g * numpy.dot(rho, beta_iperm + beta_jperm)

                        overlap = (
                            numpy.linalg.det(psia_iperm.T.dot(psia_jperm))
                            * numpy.linalg.det(psib_iperm.T.dot(psib_jperm))
                            * numpy.exp(-0.5 * numpy.sum((beta_iperm**2 + beta_jperm**2)) )* numpy.exp(numpy.sum(beta_iperm * beta_jperm))
                        )

                        num_energy += (
                            (ke + pe + e_ph + e_eph)
                            * overlap
                            * self.coeffs[iperm]
                            * self.coeffs[jperm]
                            * 2.0
                        )  # 2.0 comes from hermiticity

                        num_e1b += (
                            (ke + pe) * overlap * self.coeffs[iperm] * self.coeffs[jperm] * 2.0
                        )  # 2.0 comes from hermiticity
                        num_e2b += (
                            (e_ph + e_eph) * overlap * self.coeffs[iperm] * self.coeffs[jperm] * 2.0
                        )  # 2.0 comes from hermiticity

                        denom += overlap * self.coeffs[iperm] * self.coeffs[jperm] * 2.0

            self.energy = num_energy / denom
            self.e1b = num_e1b / denom
            self.e2b = num_e2b / denom

        else:
            phi = HarmonicOscillator(system.m, system.w0, order=0, shift=self.shift)
            Lap = phi.laplacian(self.shift)
            (self.energy, self.e1b, self.e2b) = local_energy_hubbard_holstein_jax(
                system.T,
                system.U,
                system.g,
                system.m,
                system.w0,
                self.G,
                self.shift,
                Lap,
            )

        self.energy = complex(self.energy)
        self.e1b = complex(self.e1b)
        self.e2b = complex(self.e2b)