def run(self) -> GroupedSecondQuantizedProperty: """ Returns: GroupedSecondQuantizedProperty re-constructed from the HDF5 file. Raises: LookupError: file not found. QiskitNatureError: Legacy HDF5 format. QiskitNatureError: if the HDF5 file did not contain a GroupedSecondQuantizedProperty. """ hdf5_file = self._get_path() with h5py.File(hdf5_file, "r") as file: if "origin_driver" in file.keys(): raise QiskitNatureError( "Your HDF5 file contains a not supported legacy QMolecule object!" ) driver_result = load_from_hdf5(str(hdf5_file)) if not isinstance(driver_result, GroupedSecondQuantizedProperty): raise QiskitNatureError( f"Expected a GroupedSecondQuantizedProperty but found a {type(driver_result)} " "object instead.") return driver_result
def test_save_to_hdf5(self): """Test save_to_hdf5.""" driver_result = load_from_hdf5( self.get_resource_path( "electronic_structure_driver_result.hdf5", "second_q/properties/resources", )) with self.subTest("Normal behavior"): with TemporaryDirectory() as tmp_dir: tmp_file = Path(tmp_dir) / "tmp.hdf5" save_to_hdf5(driver_result, tmp_file) self.assertTrue(tmp_file.exists()) with self.subTest("FileExistsError"): with NamedTemporaryFile() as tmp_file: with self.assertRaises(FileExistsError): save_to_hdf5(driver_result, tmp_file.name) with self.subTest("replace=True"): with TemporaryDirectory() as tmp_dir: tmp_file = Path(tmp_dir) / "tmp.hdf5" tmp_file.touch() self.assertTrue(tmp_file.exists()) save_to_hdf5(driver_result, tmp_file, replace=True)
def test_vibrational_energy(self): """Test the VibrationalEnergy.""" result = GaussianLogResult(self.logfile) vib_energy = result.get_vibrational_energy() expected = load_from_hdf5( self.get_resource_path( "test_driver_gaussian_log_vibrational_energy.hdf5", "drivers/second_quantization/gaussiand", )) self.addTypeEqualityFunc(VibrationalIntegrals, self.compare_vibrational_integral) self.addTypeEqualityFunc(VibrationalEnergy, self.compare_vibrational_energy) self.assertEqual(vib_energy, expected)
def run(self) -> GroupedSecondQuantizedProperty: """ Returns: GroupedSecondQuantizedProperty re-constructed from the HDF5 file. Raises: LookupError: file not found. QiskitNatureError: if the HDF5 file did not contain a GroupedSecondQuantizedProperty. """ hdf5_file = self._get_path() legacy_hdf5_file = False with h5py.File(hdf5_file, "r") as file: if "origin_driver" in file.keys(): legacy_hdf5_file = True warn_deprecated( "0.4.0", DeprecatedType.METHOD, "HDF5Driver.run with legacy HDF5 file", additional_msg= (". Your HDF5 file contains the legacy QMolecule object! You should consider " "converting it to the new property framework. See also HDF5Driver.convert" ), ) if legacy_hdf5_file: warnings.filterwarnings("ignore", category=DeprecationWarning) try: molecule = QMolecule(hdf5_file) molecule.load() return ElectronicStructureDriverResult.from_legacy_driver_result( molecule) finally: warnings.filterwarnings("default", category=DeprecationWarning) driver_result = load_from_hdf5(str(hdf5_file)) if not isinstance(driver_result, GroupedSecondQuantizedProperty): raise QiskitNatureError( f"Expected a GroupedSecondQuantizedProperty but found a {type(driver_result)} " "object instead.") return driver_result
def test_load_from_hdf5(self): """Test load_from_hdf5.""" with self.subTest("Normal behavior"): driver_result = load_from_hdf5( self.get_resource_path( "electronic_structure_driver_result.hdf5", "second_q/properties/resources", )) self.assertTrue( isinstance(driver_result, ElectronicStructureDriverResult)) with self.subTest("multiple groups"): with self.assertRaisesRegex(QiskitNatureError, "more than one HDF5Storable"): _ = load_from_hdf5( self.get_resource_path( "test_hdf5_error_multiple_groups.hdf5", "resources")) with self.subTest("missing class"): with self.assertRaisesRegex(QiskitNatureError, "faulty object without a '__class__'"): _ = load_from_hdf5( self.get_resource_path( "test_hdf5_error_missing_class.hdf5", "resources")) with self.subTest("non native"): with self.assertRaisesRegex(QiskitNatureError, "non-native object"): _ = load_from_hdf5( self.get_resource_path("test_hdf5_error_non_native.hdf5", "resources")) with self.subTest("import failure"): with self.assertRaisesRegex(QiskitNatureError, "import failure of .+ from .+"): _ = load_from_hdf5( self.get_resource_path( "test_hdf5_error_import_failure.hdf5", "resources")) with self.subTest("non protocol"): with self.assertRaisesRegex( QiskitNatureError, "object of type .+ which is not an HDF5Storable"): _ = load_from_hdf5( self.get_resource_path("test_hdf5_error_non_protocol.hdf5", "resources"))
def test_save_to_hdf5(self): """Test save_to_hdf5.""" driver_result = load_from_hdf5( self.get_resource_path( "electronic_structure_driver_result.hdf5", "properties/second_quantization/electronic/resources", )) with self.subTest("Normal behavior"): # pylint: disable=consider-using-with tmp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".hdf5") tmp_file.close() os.unlink(tmp_file.name) save_to_hdf5(driver_result, tmp_file.name) try: self.assertTrue(os.path.exists(tmp_file.name)) finally: os.unlink(tmp_file.name) with self.subTest("FileExistsError"): with tempfile.NamedTemporaryFile() as tmp_file: with self.assertRaises(FileExistsError): save_to_hdf5(driver_result, tmp_file.name) with self.subTest("replace=True"): # pylint: disable=consider-using-with tmp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".hdf5") # we need to use delete=False here because on Windows it is not possible to open an # existing file a second time: # https://docs.python.org/3.9/library/tempfile.html#tempfile.NamedTemporaryFile tmp_file.close() try: save_to_hdf5(driver_result, tmp_file.name, replace=True) finally: os.unlink(tmp_file.name)
def run(self) -> ElectronicStructureDriverResult: cfg = self._config psi4d_directory = Path(__file__).resolve().parent template_file = psi4d_directory.joinpath("_template.txt") qiskit_nature_directory = psi4d_directory.parent.parent input_text = [cfg] input_text += ["import sys"] syspath = ("['" + qiskit_nature_directory.as_posix() + "','" + "','".join(Path(p).as_posix() for p in sys.path) + "']") input_text += ["sys.path = " + syspath + " + sys.path"] with open(template_file, "r", encoding="utf8") as file: input_text += [line.strip("\n") for line in file.readlines()] file_fd, hdf5_file = tempfile.mkstemp(suffix=".hdf5") os.close(file_fd) input_text += [ f'save_to_hdf5(_q_driver_result, "{Path(hdf5_file).as_posix()}", replace=True)' ] file_fd, input_file = tempfile.mkstemp(suffix=".inp") os.close(file_fd) with open(input_file, "w", encoding="utf8") as stream: stream.write("\n".join(input_text)) file_fd, output_file = tempfile.mkstemp(suffix=".out") os.close(file_fd) try: PSI4Driver._run_psi4(input_file, output_file) if logger.isEnabledFor(logging.DEBUG): with open(output_file, "r", encoding="utf8") as file: logger.debug("PSI4 output file:\n%s", file.read()) finally: run_directory = os.getcwd() for local_file in os.listdir(run_directory): if local_file.endswith(".clean"): os.remove(run_directory + "/" + local_file) try: os.remove("timer.dat") except Exception: # pylint: disable=broad-except pass try: os.remove(input_file) except Exception: # pylint: disable=broad-except pass try: os.remove(output_file) except Exception: # pylint: disable=broad-except pass driver_result = cast(ElectronicStructureDriverResult, load_from_hdf5(hdf5_file)) try: os.remove(hdf5_file) except Exception: # pylint: disable=broad-except pass # 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: num_spin_orbitals = driver_result.get_property( "ParticleNumber").num_spin_orbitals driver_result.add_property(AngularMomentum(num_spin_orbitals)) driver_result.add_property(Magnetization(num_spin_orbitals)) # inject Psi4 config (because it is not available at runtime inside the template) driver_metadata = driver_result.get_property("DriverMetadata") driver_metadata.config = cfg return driver_result