Calculates the multi-plane elastic energy. Returns 999 if no elastic
        tensor was given on init

        Args:
            film(Structure): conventional standard structure for the film
            match(dictionary) : match dictionary from substrate analyzer
            elasticity_tensor(ElasticTensor): elasticity tensor for the film
            include_strain(bool): include strain in the output or not; changes
             return from just the energy to a tuple with the energy and strain
             in voigt notation

def calculate_3D_elastic_energy(self, film, match, elasticity_tensor=None,
                                    include_strain=False):
        """
        Calculates the multi-plane elastic energy. Returns 999 if no elastic
        tensor was given on init

        Args:
            film(Structure): conventional standard structure for the film
            match(dictionary) : match dictionary from substrate analyzer
            elasticity_tensor(ElasticTensor): elasticity tensor for the film
            include_strain(bool): include strain in the output or not; changes
             return from just the energy to a tuple with the energy and strain
             in voigt notation
        """
        if elasticity_tensor is None:
            return 9999

        # Get the appropriate surface structure
        struc = SlabGenerator(self.film, match['film_miller'], 20, 15,
                              primitive=False).get_slab().oriented_unit_cell

        # Generate 3D lattice vectors for film super lattice
        film_matrix = list(match['film_sl_vecs'])
        film_matrix.append(np.cross(film_matrix[0], film_matrix[1]))

        # Generate 3D lattice vectors for substrate super lattice
        # Out of plane substrate super lattice has to be same length as
        # Film out of plane vector to ensure no extra deformation in that
        # direction
        substrate_matrix = list(match['sub_sl_vecs'])
        temp_sub = np.cross(substrate_matrix[0], substrate_matrix[1])
        temp_sub = temp_sub * fast_norm(film_matrix[2]) / fast_norm(temp_sub)
        substrate_matrix.append(temp_sub)

        transform_matrix = np.transpose(np.linalg.solve(film_matrix,
                                                        substrate_matrix))

        dfm = Deformation(transform_matrix)

        strain = dfm.green_lagrange_strain.convert_to_ieee(struc, initial_fit=False)

        energy_density = elasticity_tensor.energy_density(
            strain)

        if include_strain:
            return (film.volume * energy_density / len(film.sites), strain.von_mises_strain)
        else:
            return film.volume * energy_density / len(film.sites)