Finds all topological matches for the substrate and calculates elastic
        strain energy and total energy for the film if elasticity tensor and
        ground state energy are provided:

        Args:
            film(Structure): conventional standard structure for the film
            substrate(Structure): conventional standard structure for the
                substrate
            elasticity_tensor(ElasticTensor): elasticity tensor for the film
                in the IEEE orientation
            film_millers(array): film facets to consider in search as defined by
                miller indicies
            substrate_millers(array): substrate facets to consider in search as
                defined by miller indicies
            ground_state_energy(float): ground state energy for the film
            lowest(bool): only consider lowest matching area for each surface

def calculate(self, film, substrate, elasticity_tensor=None,
                  film_millers=None, substrate_millers=None,
                  ground_state_energy=0, lowest=False):
        """
        Finds all topological matches for the substrate and calculates elastic
        strain energy and total energy for the film if elasticity tensor and
        ground state energy are provided:

        Args:
            film(Structure): conventional standard structure for the film
            substrate(Structure): conventional standard structure for the
                substrate
            elasticity_tensor(ElasticTensor): elasticity tensor for the film
                in the IEEE orientation
            film_millers(array): film facets to consider in search as defined by
                miller indicies
            substrate_millers(array): substrate facets to consider in search as
                defined by miller indicies
            ground_state_energy(float): ground state energy for the film
            lowest(bool): only consider lowest matching area for each surface
        """
        self.film = film
        self.substrate = substrate

        # Generate miller indicies if none specified for film
        if film_millers is None:
            film_millers = sorted(get_symmetrically_distinct_miller_indices(
                self.film, self.film_max_miller))

        # Generate miller indicies if none specified for substrate
        if substrate_millers is None:
            substrate_millers = sorted(
                get_symmetrically_distinct_miller_indices(self.substrate,
                                                          self.substrate_max_miller))

        # Check each miller index combination
        surface_vector_sets = self.generate_surface_vectors(film_millers, substrate_millers)
        for [film_vectors, substrate_vectors, film_miller, substrate_miller] in surface_vector_sets:
            for match in self.zsl(film_vectors, substrate_vectors, lowest):
                match['film_miller'] = film_miller
                match['sub_miller'] = substrate_miller
                if (elasticity_tensor is not None):
                    energy, strain = self.calculate_3D_elastic_energy(
                        film, match, elasticity_tensor, include_strain=True)
                    match["elastic_energy"] = energy
                    match["strain"] = strain
                if (ground_state_energy is not 0):
                    match['total_energy'] = match.get('elastic_energy', 0) + ground_state_energy

                yield match