diff --git a/tests/analysis/chemenv/coordination_environments/test_coordination_geometry_finder.py b/tests/analysis/chemenv/coordination_environments/test_coordination_geometry_finder.py index fc26a3c33af..03cbe3f96e2 100644 --- a/tests/analysis/chemenv/coordination_environments/test_coordination_geometry_finder.py +++ b/tests/analysis/chemenv/coordination_environments/test_coordination_geometry_finder.py @@ -1,10 +1,17 @@ from __future__ import annotations +import json +import os + import numpy as np import pytest from numpy.testing import assert_allclose from pytest import approx +from pymatgen.analysis.chemenv.coordination_environments.chemenv_strategies import ( + SimpleAbundanceChemenvStrategy, + SimplestChemenvStrategy, +) from pymatgen.analysis.chemenv.coordination_environments.coordination_geometries import AllCoordinationGeometries from pymatgen.analysis.chemenv.coordination_environments.coordination_geometry_finder import ( AbstractGeometry, @@ -27,7 +34,7 @@ def setUp(self): structure_refinement=self.lgf.STRUCTURE_REFINEMENT_NONE, ) - # self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()] + # self.strategies = [SimplestChemenvStrategy(), SimpleAbundanceChemenvStrategy()] def test_abstract_geometry(self): cg_ts3 = self.lgf.allcg["TS:3"] @@ -117,45 +124,47 @@ def test_abstract_geometry(self): for perm_csm_dict in permutations_symmetry_measures: assert perm_csm_dict["symmetry_measure"] == approx(0.140355832317) - # def _strategy_test(self, strategy): - # files = [] - # for _dirpath, _dirnames, filenames in os.walk(json_dir): - # files.extend(filenames) - # break - - # for _ifile, json_file in enumerate(files): - # with self.subTest(json_file=json_file): - # with open(f"{json_dir}/{json_file}") as file: - # dct = json.load(file) - - # atom_indices = dct["atom_indices"] - # expected_geoms = dct["expected_geoms"] - - # struct = Structure.from_dict(dct["structure"]) - - # struct = self.lgf.setup_structure(struct) - # se = self.lgf.compute_structure_environments_detailed_voronoi( - # only_indices=atom_indices, maximum_distance_factor=1.5 - # ) - - # # All strategies should get the correct environment with their default parameters - # strategy.set_structure_environments(se) - # for ienv, isite in enumerate(atom_indices): - # ce = strategy.get_site_coordination_environment(struct[isite]) - # try: - # coord_env = ce[0] - # except TypeError: - # coord_env = ce - # # Check that the environment found is the expected one - # assert coord_env == expected_geoms[ienv] - - # def test_simplest_chemenv_strategy(self): - # strategy = SimplestChemenvStrategy() - # self._strategy_test(strategy) - - # def test_simple_abundance_chemenv_strategy(self): - # strategy = SimpleAbundanceChemenvStrategy() - # self._strategy_test(strategy) + def _strategy_test(self, strategy): + files = [] + for _dirpath, _dirnames, filenames in os.walk(json_dir): + files.extend(filenames) + break + + for _ifile, json_file in enumerate(files): + with self.subTest(json_file=json_file): + with open(f"{json_dir}/{json_file}") as file: + dct = json.load(file) + + atom_indices = dct["atom_indices"] + expected_geoms = dct["expected_geoms"] + + struct = Structure.from_dict(dct["structure"]) + + struct = self.lgf.setup_structure(struct) + se = self.lgf.compute_structure_environments_detailed_voronoi( + only_indices=atom_indices, maximum_distance_factor=1.5 + ) + + # All strategies should get the correct environment with their default parameters + strategy.set_structure_environments(se) + for ienv, isite in enumerate(atom_indices): + ce = strategy.get_site_coordination_environment(struct[isite]) + try: + coord_env = ce[0] + except TypeError: + coord_env = ce + # Check that the environment found is the expected one + assert coord_env == expected_geoms[ienv] + + @pytest.mark.skip("TODO: need someone to fix this") + def test_simplest_chemenv_strategy(self): + strategy = SimplestChemenvStrategy() + self._strategy_test(strategy) + + @pytest.mark.skip("TODO: need someone to fix this") + def test_simple_abundance_chemenv_strategy(self): + strategy = SimpleAbundanceChemenvStrategy() + self._strategy_test(strategy) def test_perfect_environments(self): allcg = AllCoordinationGeometries() diff --git a/tests/analysis/test_molecule_structure_comparator.py b/tests/analysis/test_molecule_structure_comparator.py index fe678ec8b42..6da037acb50 100644 --- a/tests/analysis/test_molecule_structure_comparator.py +++ b/tests/analysis/test_molecule_structure_comparator.py @@ -2,8 +2,11 @@ from unittest import TestCase +import pytest + from pymatgen.analysis.molecule_structure_comparator import MoleculeStructureComparator from pymatgen.core.structure import Molecule +from pymatgen.io.qchem.outputs import QCOutput from pymatgen.util.testing import TEST_FILES_DIR __author__ = "xiaohuiqu" @@ -129,14 +132,15 @@ def test_to_and_from_dict(self): d2 = MoleculeStructureComparator.from_dict(d1).as_dict() assert d1 == d2 - # def test_structural_change_in_geom_opt(self): - # qcout_path = f"{TEST_DIR}/mol_1_3_bond.qcout" - # qcout = QcOutput(qcout_path) - # mol1 = qcout.data[0]["molecules"][0] - # mol2 = qcout.data[0]["molecules"][-1] - # priority_bonds = [[0, 1], [0, 2], [1, 3], [1, 4], [1, 7], [2, 5], [2, 6], [2, 8], [4, 6], [4, 10], [6, 9]] - # msc = MoleculeStructureComparator(priority_bonds=priority_bonds) - # assert msc.are_equal(mol1, mol2) + @pytest.mark.skip("TODO: need someone to fix this") + def test_structural_change_in_geom_opt(self): + qcout_path = f"{TEST_DIR}/mol_1_3_bond.qcout" + qcout = QCOutput(qcout_path) + mol1 = qcout.data[0]["molecules"][0] + mol2 = qcout.data[0]["molecules"][-1] + priority_bonds = [[0, 1], [0, 2], [1, 3], [1, 4], [1, 7], [2, 5], [2, 6], [2, 8], [4, 6], [4, 10], [6, 9]] + msc = MoleculeStructureComparator(priority_bonds=priority_bonds) + assert msc.are_equal(mol1, mol2) def test_get_13_bonds(self): priority_bonds = [ diff --git a/tests/analysis/test_surface_analysis.py b/tests/analysis/test_surface_analysis.py index c05136305e9..efa70f94b75 100644 --- a/tests/analysis/test_surface_analysis.py +++ b/tests/analysis/test_surface_analysis.py @@ -2,6 +2,7 @@ import json +import pytest from numpy.testing import assert_allclose from pytest import approx from sympy import Number, Symbol @@ -248,41 +249,43 @@ def test_entry_dict_from_list(self): surf_ene_plotter = SurfaceEnergyPlotter(all_Pt_slab_entries, self.Pt_analyzer.ucell_entry) assert surf_ene_plotter.list_of_chempots == self.Pt_analyzer.list_of_chempots - # def test_monolayer_vs_BE(self): - # for el in self.Oads_analyzer_dict: - # # Test WulffShape for adsorbed surfaces - # analyzer = self.Oads_analyzer_dict[el] - # plt = analyzer.monolayer_vs_BE() - # - # def test_area_frac_vs_chempot_plot(self): - # - # for el in self.Oads_analyzer_dict: - # # Test WulffShape for adsorbed surfaces - # analyzer = self.Oads_analyzer_dict[el] - # plt = analyzer.area_frac_vs_chempot_plot(x_is_u_ads=True) - # - # def test_chempot_vs_gamma_clean(self): - # - # plt = self.Cu_analyzer.chempot_vs_gamma_clean() - # for el in self.Oads_analyzer_dict: - # # Test WulffShape for adsorbed surfaces - # analyzer = self.Oads_analyzer_dict[el] - # plt = analyzer.chempot_vs_gamma_clean(x_is_u_ads=True) - # - # def test_chempot_vs_gamma_facet(self): - # - # for el, val in self.metals_O_entry_dict.items(): - # for hkl in val: - # # Test WulffShape for adsorbed surfaces - # analyzer = self.Oads_analyzer_dict[el] - # plt = analyzer.chempot_vs_gamma_facet(hkl) - # def test_surface_chempot_range_map(self): - # - # for el, val in self.metals_O_entry_dict.items(): - # for hkl in val: - # # Test WulffShape for adsorbed surfaces - # analyzer = self.Oads_analyzer_dict[el] - # plt = analyzer.chempot_vs_gamma_facet(hkl) + @pytest.mark.skip("TODO: need someone to fix this") + def test_monolayer_vs_BE(self): + for el in self.Oads_analyzer_dict: + # Test WulffShape for adsorbed surfaces + analyzer = self.Oads_analyzer_dict[el] + analyzer.monolayer_vs_BE() + + @pytest.mark.skip("TODO: need someone to fix this") + def test_area_frac_vs_chempot_plot(self): + for el in self.Oads_analyzer_dict: + # Test WulffShape for adsorbed surfaces + analyzer = self.Oads_analyzer_dict[el] + analyzer.area_frac_vs_chempot_plot(x_is_u_ads=True) + + @pytest.mark.skip("TODO: need someone to fix this") + def test_chempot_vs_gamma_clean(self): + self.Cu_analyzer.chempot_vs_gamma_clean() + for el in self.Oads_analyzer_dict: + # Test WulffShape for adsorbed surfaces + analyzer = self.Oads_analyzer_dict[el] + analyzer.chempot_vs_gamma_clean(x_is_u_ads=True) + + @pytest.mark.skip("TODO: need someone to fix this") + def test_chempot_vs_gamma_facet(self): + for el, val in self.metals_O_entry_dict.items(): + for hkl in val: + # Test WulffShape for adsorbed surfaces + analyzer = self.Oads_analyzer_dict[el] + analyzer.chempot_vs_gamma_facet(hkl) + + @pytest.mark.skip("TODO: need someone to fix this") + def test_surface_chempot_range_map(self): + for el, val in self.metals_O_entry_dict.items(): + for hkl in val: + # Test WulffShape for adsorbed surfaces + analyzer = self.Oads_analyzer_dict[el] + analyzer.chempot_vs_gamma_facet(hkl) class TestWorkFunctionAnalyzer(PymatgenTest): diff --git a/tests/command_line/test_critic2_caller.py b/tests/command_line/test_critic2_caller.py index 46218f94e8c..0a068de2132 100644 --- a/tests/command_line/test_critic2_caller.py +++ b/tests/command_line/test_critic2_caller.py @@ -90,6 +90,22 @@ def setUp(self): self.c2o_new_format = Critic2Analysis(structure, reference_stdout_new_format) def test_to_from_dict(self): + """ + reference dictionary for c2o.critical_points[0].as_dict() + {'@class': 'CriticalPoint', + '@module': 'pymatgen.command_line.critic2_caller', + 'coords': None, + 'field': 93848.0413, + 'field_gradient': 0.0, + 'field_hessian': [[-2593274446000.0, -3.873587547e-19, -1.704530713e-08], + [-3.873587547e-19, -2593274446000.0, 1.386877485e-18], + [-1.704530713e-08, 1.386877485e-18, -2593274446000.0]], + 'frac_coords': [0.333333, 0.666667, 0.213295], + 'index': 0, + 'multiplicity': 1.0, + 'point_group': 'D3h', + 'type': < CriticalPointType.nucleus: 'nucleus' >} + """ assert len(self.c2o.critical_points) == 6 assert len(self.c2o.nodes) == 14 assert len(self.c2o.edges) == 10 @@ -98,21 +114,6 @@ def test_to_from_dict(self): assert len(self.c2o_new_format.nodes) == 14 assert len(self.c2o_new_format.edges) == 10 - # reference dictionary for c2o.critical_points[0].as_dict() - # {'@class': 'CriticalPoint', - # '@module': 'pymatgen.command_line.critic2_caller', - # 'coords': None, - # 'field': 93848.0413, - # 'field_gradient': 0.0, - # 'field_hessian': [[-2593274446000.0, -3.873587547e-19, -1.704530713e-08], - # [-3.873587547e-19, -2593274446000.0, 1.386877485e-18], - # [-1.704530713e-08, 1.386877485e-18, -2593274446000.0]], - # 'frac_coords': [0.333333, 0.666667, 0.213295], - # 'index': 0, - # 'multiplicity': 1.0, - # 'point_group': 'D3h', - # 'type': < CriticalPointType.nucleus: 'nucleus' >} - assert str(self.c2o.critical_points[0].type) == "CriticalPointType.nucleus" # test connectivity diff --git a/tests/core/test_structure.py b/tests/core/test_structure.py index 4a838ccfe34..7d1862920c0 100644 --- a/tests/core/test_structure.py +++ b/tests/core/test_structure.py @@ -680,67 +680,69 @@ def test_get_neighbor_list(self): assert_allclose(cy_indices2, py_indices2) assert len(cy_offsets) == len(py_offsets) - # @skipIf(not os.getenv("CI"), reason="Only run this in CI tests") - # def test_get_all_neighbors_crosscheck_old(self): - # for i in range(100): - # alpha, beta = np.random.rand(2) * 90 - # a, b, c = 3 + np.random.rand(3) * 5 - # species = ["H"] * 5 - # frac_coords = np.random.rand(5, 3) - # try: - # lattice = Lattice.from_parameters(a, b, c, alpha, beta, 90) - # struct = Structure.from_spacegroup("P1", lattice, species, frac_coords) - # for nn_new, nn_old in zip(struct.get_all_neighbors(4), struct.get_all_neighbors_old(4)): - # sites1 = [i[0] for i in nn_new] - # sites2 = [i[0] for i in nn_old] - # assert set(sites1) == set(sites2) - # break - # except Exception: - # pass - # else: - # raise ValueError("No valid structure tested.") - - # from pymatgen.electronic_structure.core import Spin - - # d = { - # "@module": "pymatgen.core.structure", - # "@class": "Structure", - # "charge": None, - # "lattice": { - # "matrix": [ - # [0.0, 0.0, 5.5333], - # [5.7461, 0.0, 3.518471486290303e-16], - # [-4.692662837312786e-16, 7.6637, 4.692662837312786e-16], - # ], - # "a": 5.5333, - # "b": 5.7461, - # "c": 7.6637, - # "alpha": 90.0, - # "beta": 90.0, - # "gamma": 90.0, - # "volume": 243.66653780778103, - # }, - # "sites": [ - # { - # "species": [{"element": "Mn", "oxidation_state": 0, "spin": Spin.down, "occu": 1}], - # "abc": [0.0, 0.5, 0.5], - # "xyz": [2.8730499999999997, 3.83185, 4.1055671618015446e-16], - # "label": "Mn0+,spin=-1", - # "properties": {}, - # }, - # { - # "species": [{"element": "Mn", "oxidation_state": None, "occu": 1.0}], - # "abc": [1.232595164407831e-32, 0.5, 0.5], - # "xyz": [2.8730499999999997, 3.83185, 4.105567161801545e-16], - # "label": "Mn", - # "properties": {}, - # }, - # ], - # } - # struct = Structure.from_dict(d) - # assert {i[0] for i in struct.get_neighbors(struct[0], 0.05)} == { - # i[0] for i in struct.get_neighbors_old(struct[0], 0.05) - # } + @pytest.mark.skip("TODO: need someone to fix this") + @pytest.mark.skipif(not os.getenv("CI"), reason="Only run this in CI tests") + def test_get_all_neighbors_crosscheck_old(self): + rng = np.random.default_rng() + for i in range(100): + alpha, beta = rng.random(2) * 90 + a, b, c = 3 + rng.random(3) * 5 + species = ["H"] * 5 + frac_coords = rng.random(5, 3) + try: + lattice = Lattice.from_parameters(a, b, c, alpha, beta, 90) + struct = Structure.from_spacegroup("P1", lattice, species, frac_coords) + for nn_new, nn_old in zip(struct.get_all_neighbors(4), struct.get_all_neighbors_old(4), strict=False): + sites1 = [i[0] for i in nn_new] + sites2 = [i[0] for i in nn_old] + assert set(sites1) == set(sites2) + break + except Exception: + pass + else: + raise ValueError("No valid structure tested.") + + from pymatgen.electronic_structure.core import Spin + + d = { + "@module": "pymatgen.core.structure", + "@class": "Structure", + "charge": None, + "lattice": { + "matrix": [ + [0.0, 0.0, 5.5333], + [5.7461, 0.0, 3.518471486290303e-16], + [-4.692662837312786e-16, 7.6637, 4.692662837312786e-16], + ], + "a": 5.5333, + "b": 5.7461, + "c": 7.6637, + "alpha": 90.0, + "beta": 90.0, + "gamma": 90.0, + "volume": 243.66653780778103, + }, + "sites": [ + { + "species": [{"element": "Mn", "oxidation_state": 0, "spin": Spin.down, "occu": 1}], + "abc": [0.0, 0.5, 0.5], + "xyz": [2.8730499999999997, 3.83185, 4.1055671618015446e-16], + "label": "Mn0+,spin=-1", + "properties": {}, + }, + { + "species": [{"element": "Mn", "oxidation_state": None, "occu": 1.0}], + "abc": [1.232595164407831e-32, 0.5, 0.5], + "xyz": [2.8730499999999997, 3.83185, 4.105567161801545e-16], + "label": "Mn", + "properties": {}, + }, + ], + } + struct = Structure.from_dict(d) + assert {i[0] for i in struct.get_neighbors(struct[0], 0.05)} == { + i[0] for i in struct.get_neighbors_old(struct[0], 0.05) + } def test_get_symmetric_neighbor_list(self): # tetragonal group with all bonds related by symmetry diff --git a/tests/electronic_structure/test_boltztrap.py b/tests/electronic_structure/test_boltztrap.py index f5762919507..1f4c799c705 100644 --- a/tests/electronic_structure/test_boltztrap.py +++ b/tests/electronic_structure/test_boltztrap.py @@ -211,15 +211,16 @@ def test_get_symm_bands(self): assert len(sbs_bzt.bands[Spin.up]) == approx(20) assert len(sbs_bzt.bands[Spin.up][1]) == approx(143) - # def test_check_acc_bzt_bands(self): - # structure = loadfn(f"{TEST_DIR}/structure_mp-12103.json") - # sbs = loadfn(f"{TEST_DIR}/dft_bs_sym_line.json") - # sbs_bzt = self.bz_bands.get_symm_bands(structure, -5.25204548) - # corr, werr_vbm, werr_cbm, warn = BoltztrapAnalyzer.check_acc_bzt_bands(sbs_bzt, sbs) - # assert corr[2] == 9.16851750e-05 - # assert werr_vbm["K-H"] == 0.18260273521047862 - # assert werr_cbm["M-K"] == 0.071552669981356981 - # assert not warn + @pytest.mark.skip("TODO: need someone to fix this") + def test_check_acc_bzt_bands(self): + structure = loadfn(f"{TEST_DIR}/structure_mp-12103.json") + sbs = loadfn(f"{TEST_DIR}/dft_bs_sym_line.json") + sbs_bzt = self.bz_bands.get_symm_bands(structure, -5.25204548) + corr, werr_vbm, werr_cbm, warn = BoltztrapAnalyzer.check_acc_bzt_bands(sbs_bzt, sbs) + assert corr[2] == 9.16851750e-05 + assert werr_vbm["K-H"] == 0.18260273521047862 + assert werr_cbm["M-K"] == 0.071552669981356981 + assert not warn def test_get_complete_dos(self): structure = loadfn(f"{TEST_DIR}/structure_mp-12103.json") diff --git a/tests/electronic_structure/test_boltztrap2.py b/tests/electronic_structure/test_boltztrap2.py index 1746cd64b87..cc3619811b5 100644 --- a/tests/electronic_structure/test_boltztrap2.py +++ b/tests/electronic_structure/test_boltztrap2.py @@ -98,15 +98,14 @@ def test_properties(self): def test_get_volume(self): assert self.loader.get_volume() == approx(477.6256714925874, abs=1e-5) - # def test_set_upper_lower_bands(self): - # min_bnd = min(self.loader_sp_up.ebands.min(), - # self.loader_sp_dn.ebands.min()) - # max_bnd = max(self.loader_sp_up.ebands.max(), - # self.loader_sp_dn.ebands.max()) - # self.loader_sp_up.set_upper_lower_bands(min_bnd, max_bnd) - # self.loader_sp_dn.set_upper_lower_bands(min_bnd, max_bnd) - # self.assertTupleEqual(self.loader_sp_up.ebands.shape, (14, 198)) - # self.assertTupleEqual(self.loader_sp_dn.ebands.shape, (14, 198)) + @pytest.mark.skip("TODO: need someone to fix this") + def test_set_upper_lower_bands(self): + min_bnd = min(self.loader_sp_up.ebands.min(), self.loader_sp_dn.ebands.min()) + max_bnd = max(self.loader_sp_up.ebands.max(), self.loader_sp_dn.ebands.max()) + self.loader_sp_up.set_upper_lower_bands(min_bnd, max_bnd) + self.loader_sp_dn.set_upper_lower_bands(min_bnd, max_bnd) + assert self.loader_sp_up.ebands.shape == (14, 198) + assert self.loader_sp_dn.ebands.shape == (14, 198) @pytest.mark.skipif(not BOLTZTRAP2_PRESENT, reason="No boltztrap2, skipping tests...") diff --git a/tests/electronic_structure/test_dos.py b/tests/electronic_structure/test_dos.py index dd9e7c36d80..27ef6060b9f 100644 --- a/tests/electronic_structure/test_dos.py +++ b/tests/electronic_structure/test_dos.py @@ -250,7 +250,7 @@ def test_get_band_kurtosis(self): assert kurtosis == approx(7.764506941340621) def test_get_dos_fp(self): - # normalize=True + # normalize is True dos_fp = self.dos.get_dos_fp(fp_type="s", min_e=-10, max_e=0, n_bins=56, normalize=True) bin_width = np.diff(dos_fp.energies)[0][0] assert max(dos_fp.energies[0]) <= 0 @@ -258,12 +258,12 @@ def test_get_dos_fp(self): assert len(dos_fp.energies[0]) == 56 assert dos_fp.fp_type == "s" assert sum(dos_fp.densities * bin_width) == approx(1) - # normalize=False + # normalize is False dos_fp2 = self.dos.get_dos_fp(fp_type="s", min_e=-10, max_e=0, n_bins=56, normalize=False) bin_width2 = np.diff(dos_fp2.energies)[0][0] assert sum(dos_fp2.densities * bin_width2) == approx(7.279303571428509) assert dos_fp2.bin_width == approx(bin_width2) - # binning=False + # binning is False dos_fp = self.dos.get_dos_fp(fp_type="s", min_e=None, max_e=None, n_bins=56, normalize=True, binning=False) assert dos_fp.n_bins == len(self.dos.energies) diff --git a/tests/ext/test_matproj.py b/tests/ext/test_matproj.py index 92b994c2401..529d4deb4d8 100644 --- a/tests/ext/test_matproj.py +++ b/tests/ext/test_matproj.py @@ -303,18 +303,17 @@ def test_get_exp_entry(self): entry = self.rester.get_exp_entry("Fe2O3") assert entry.energy == -825.5 - # def test_submit_query_delete_snl(self): - # struct = Structure(np.eye(3) * 5, ["Fe"], [[0, 0, 0]]) - # submission_ids = self.rester.submit_snl( - # [struct, struct], remarks=["unittest"], authors="Test User " - # ) - # assert len(submission_ids) == 2 - # data = self.rester.query_snl({"about.remarks": "unittest"}) - # assert len(data) == 2 - # snl_ids = [d["_id"] for d in data] - # self.rester.delete_snl(snl_ids) - # data = self.rester.query_snl({"about.remarks": "unittest"}) - # assert len(data) == 0 + @pytest.mark.skip("TODO: Need someone to fix this") + def test_submit_query_delete_snl(self): + struct = Structure(np.eye(3) * 5, ["Fe"], [[0, 0, 0]]) + submission_ids = self.rester.submit_snl([struct, struct]) + assert len(submission_ids) == 2 + data = self.rester.query_snl({"about.remarks": "unittest"}) + assert len(data) == 2 + snl_ids = [d["_id"] for d in data] + self.rester.delete_snl(snl_ids) + data = self.rester.query_snl({"about.remarks": "unittest"}) + assert len(data) == 0 def test_get_stability(self): entries = self.rester.get_entries_in_chemsys(["Fe", "O"]) @@ -458,11 +457,11 @@ def test_parse_criteria(self): crit = _MPResterLegacy.parse_criteria("POPO2") assert "P2O3" in crit["pretty_formula"]["$in"] + @pytest.mark.skip( + "TODO: this test started failing with 'pymatgen.ext.matproj.MPRestError: REST query " + "returned with error status code 403. Content: b'error code: 1020'" + ) def test_include_user_agent(self): - pytest.skip( - "this test started failing with 'pymatgen.ext.matproj.MPRestError: REST query " - "returned with error status code 403. Content: b'error code: 1020'" - ) headers = self.rester.session.headers assert "user-agent" in headers, "Include user-agent header by default" match = re.match( @@ -547,81 +546,84 @@ def test_get_all_materials_ids_doc(self): doc = self.rester.get_doc(mids.pop(0)) assert doc["formula_pretty"] == "Al2O3" - # - # def test_get_xas_data(self): - # # Test getting XAS data - # data = self.rester.get_xas_data("mp-19017", "Li") - # assert data["mid_and_el"] == "mp-19017,Li" - # assert data["spectrum"]["x"][0] == approx(55.178) - # assert data["spectrum"]["y"][0] == approx(0.0164634) - # - # def test_get_data(self): - # props = { - # "energy", - # "energy_per_atom", - # "formation_energy_per_atom", - # "nsites", - # "unit_cell_formula", - # "pretty_formula", - # "is_hubbard", - # "elements", - # "nelements", - # "e_above_hull", - # "hubbards", - # "is_compatible", - # "task_ids", - # "density", - # "icsd_ids", - # "total_magnetization", - # } - # mp_id = "mp-1143" - # vals = requests.get(f"https://legacy.materialsproject.org/materials/{mp_id}/json/", timeout=600) - # expected_vals = vals.json() - # - # for prop in props: - # if prop not in [ - # "hubbards", - # "unit_cell_formula", - # "elements", - # "icsd_ids", - # "task_ids", - # ]: - # val = self.rester.get_data(mp_id, prop=prop)[0][prop] - # if prop in ["energy", "energy_per_atom"]: - # prop = "final_" + prop - # assert expected_vals[prop] == approx(val), f"Failed with property {prop}" - # elif prop in ["elements", "icsd_ids", "task_ids"]: - # upstream_vals = set(self.rester.get_data(mp_id, prop=prop)[0][prop]) - # assert set(expected_vals[prop]) <= upstream_vals - # else: - # assert expected_vals[prop] == self.rester.get_data(mp_id, prop=prop)[0][prop] - # - # props = ["structure", "initial_structure", "final_structure", "entry"] - # for prop in props: - # obj = self.rester.get_data(mp_id, prop=prop)[0][prop] - # if prop.endswith("structure"): - # assert isinstance(obj, Structure) - # elif prop == "entry": - # obj = self.rester.get_data(mp_id, prop=prop)[0][prop] - # assert isinstance(obj, ComputedEntry) - # - # # Test chemsys search - # data = self.rester.get_data("Fe-Li-O", prop="unit_cell_formula") - # assert len(data) > 1 - # elements = {Element("Li"), Element("Fe"), Element("O")} - # for d in data: - # assert set(Composition(d["unit_cell_formula"]).elements).issubset(elements) - # - # with pytest.raises(MPRestError, match="REST query returned with error status code 404"): - # self.rester.get_data("Fe2O3", "badmethod") - # - # def test_get_materials_id_from_task_id(self): - # assert self.rester.get_materials_id_from_task_id("mp-540081") == "mp-19017" - # - # def test_get_materials_id_references(self): - # mpr = _MPResterLegacy() - # data = mpr.get_materials_id_references("mp-123") - # assert len(data) > 1000 + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_xas_data(self): + # Test getting XAS data + data = self.rester.get_xas_data("mp-19017", "Li") + assert data["mid_and_el"] == "mp-19017,Li" + assert data["spectrum"]["x"][0] == approx(55.178) + assert data["spectrum"]["y"][0] == approx(0.0164634) + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_data(self): + props = { + "energy", + "energy_per_atom", + "formation_energy_per_atom", + "nsites", + "unit_cell_formula", + "pretty_formula", + "is_hubbard", + "elements", + "nelements", + "e_above_hull", + "hubbards", + "is_compatible", + "task_ids", + "density", + "icsd_ids", + "total_magnetization", + } + mp_id = "mp-1143" + vals = requests.get(f"https://legacy.materialsproject.org/materials/{mp_id}/json/", timeout=600) + expected_vals = vals.json() + + for prop in props: + if prop not in [ + "hubbards", + "unit_cell_formula", + "elements", + "icsd_ids", + "task_ids", + ]: + val = self.rester.get_data(mp_id, prop=prop)[0][prop] + if prop in ["energy", "energy_per_atom"]: + prop = "final_" + prop + assert expected_vals[prop] == approx(val), f"Failed with property {prop}" + elif prop in ["elements", "icsd_ids", "task_ids"]: + upstream_vals = set(self.rester.get_data(mp_id, prop=prop)[0][prop]) + assert set(expected_vals[prop]) <= upstream_vals + else: + assert expected_vals[prop] == self.rester.get_data(mp_id, prop=prop)[0][prop] + + props = ["structure", "initial_structure", "final_structure", "entry"] + for prop in props: + obj = self.rester.get_data(mp_id, prop=prop)[0][prop] + if prop.endswith("structure"): + assert isinstance(obj, Structure) + elif prop == "entry": + obj = self.rester.get_data(mp_id, prop=prop)[0][prop] + assert isinstance(obj, ComputedEntry) + + # Test chemsys search + data = self.rester.get_data("Fe-Li-O", prop="unit_cell_formula") + assert len(data) > 1 + elements = {Element("Li"), Element("Fe"), Element("O")} + for d in data: + assert set(Composition(d["unit_cell_formula"]).elements).issubset(elements) + + with pytest.raises(MPRestError, match="REST query returned with error status code 404"): + self.rester.get_data("Fe2O3", "badmethod") + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_materials_id_from_task_id(self): + assert self.rester.get_materials_id_from_task_id("mp-540081") == "mp-19017" + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_materials_id_references(self): + mpr = _MPResterLegacy() + data = mpr.get_materials_id_references("mp-123") + assert len(data) > 1000 def test_get_entries_and_in_chemsys(self): # One large system test. @@ -659,32 +661,36 @@ def test_get_entry_by_material_id(self): with pytest.raises(IndexError, match="list index out of range"): self.rester.get_entry_by_material_id("mp-2022") # "mp-2022" does not exist - # def test_query(self): - # criteria = {"elements": {"$in": ["Li", "Na", "K"], "$all": ["O"]}} - # props = ["pretty_formula", "energy"] - # data = self.rester.query(criteria=criteria, properties=props, chunk_size=0) - # assert len(data) > 6 - # data = self.rester.query(criteria="*2O", properties=props, chunk_size=0) - # assert len(data) >= 52 - # assert "Li2O" in (d["pretty_formula"] for d in data) - - # def test_get_exp_thermo_data(self): - # data = self.rester.get_exp_thermo_data("Fe2O3") - # assert len(data) > 0 - # for d in data: - # assert d.formula == "Fe2O3" - # - # def test_get_dos_by_id(self): - # dos = self.rester.get_dos_by_material_id("mp-2254") - # assert isinstance(dos, CompleteDos) - - # def test_get_bandstructure_by_material_id(self): - # bs = self.rester.get_bandstructure_by_material_id("mp-2254") - # assert isinstance(bs, BandStructureSymmLine) - # bs_unif = self.rester.get_bandstructure_by_material_id("mp-2254", line_mode=False) - # assert isinstance(bs_unif, BandStructure) - # assert not isinstance(bs_unif, BandStructureSymmLine) - # + @pytest.mark.skip("TODO: need someone to fix this") + def test_query(self): + criteria = {"elements": {"$in": ["Li", "Na", "K"], "$all": ["O"]}} + props = ["pretty_formula", "energy"] + data = self.rester.query(criteria=criteria, properties=props, chunk_size=0) + assert len(data) > 6 + data = self.rester.query(criteria="*2O", properties=props, chunk_size=0) + assert len(data) >= 52 + assert "Li2O" in (d["pretty_formula"] for d in data) + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_exp_thermo_data(self): + data = self.rester.get_exp_thermo_data("Fe2O3") + assert len(data) > 0 + for d in data: + assert d.formula == "Fe2O3" + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_dos_by_id(self): + dos = self.rester.get_dos_by_material_id("mp-2254") + assert isinstance(dos, CompleteDos) + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_bandstructure_by_material_id(self): + bs = self.rester.get_bandstructure_by_material_id("mp-2254") + assert isinstance(bs, BandStructureSymmLine) + bs_unif = self.rester.get_bandstructure_by_material_id("mp-2254", line_mode=False) + assert isinstance(bs_unif, BandStructure) + assert not isinstance(bs_unif, BandStructureSymmLine) + def test_get_phonon_data_by_material_id(self): bs = self.rester.get_phonon_bandstructure_by_material_id("mp-661") assert isinstance(bs, PhononBandStructureSymmLine) @@ -698,182 +704,192 @@ def test_get_structures(self): structs = self.rester.get_structures("Mn3O4") assert len(structs) > 0 - # def test_get_entries(self): - # entries = self.rester.get_entries("TiO2") - # assert len(entries) > 1 - # for entry in entries: - # assert entry.reduced_formula == "TiO2" - # - # entries = self.rester.get_entries("TiO2", inc_structure=True) - # assert len(entries) > 1 - # for entry in entries: - # assert entry.structure.reduced_formula == "TiO2" - - # # all_entries = self.rester.get_entries("Fe", compatible_only=False) - # # entries = self.rester.get_entries("Fe", compatible_only=True) - # # assert len(entries) < len(all_entries) - # entries = self.rester.get_entries("Fe", compatible_only=True, property_data=["cif"]) - # assert "cif" in entries[0].data - # - # for entry in self.rester.get_entries("CdO2", inc_structure=False): - # assert entry.data["oxide_type"] is not None - # - # # test if it will retrieve the conventional unit cell of Ni - # entry = self.rester.get_entry_by_material_id("mp-23", inc_structure=True, conventional_unit_cell=True) - # Ni = entry.structure - # assert Ni.lattice.a == Ni.lattice.b - # assert Ni.lattice.a == Ni.lattice.c - # assert Ni.lattice.alpha == 90 - # assert Ni.lattice.beta == 90 - # assert Ni.lattice.gamma == 90 - # - # # Ensure energy per atom is same - # primNi = self.rester.get_entry_by_material_id("mp-23", inc_structure=True, conventional_unit_cell=False) - # assert primNi.energy_per_atom == entry.energy_per_atom - # - # Ni = self.rester.get_structure_by_material_id("mp-23", conventional_unit_cell=True) - # assert Ni.lattice.a == Ni.lattice.b - # assert Ni.lattice.a == Ni.lattice.c - # assert Ni.lattice.alpha == 90 - # assert Ni.lattice.beta == 90 - # assert Ni.lattice.gamma == 90 - # - # # Test case where convs are different from initial and final - # # th = self.rester.get_structure_by_material_id("mp-37", conventional_unit_cell=True) - # # th_entry = self.rester.get_entry_by_material_id("mp-37", inc_structure=True, conventional_unit_cell=True) - # # th_entry_initial = self.rester.get_entry_by_material_id( - # # "mp-37", inc_structure="initial", conventional_unit_cell=True - # # ) - # # assert th == th_entry.structure - # # assert len(th_entry.structure) == 4 - # # assert len(th_entry_initial.structure) == 2 - # - # # Test if the polymorphs of Fe are properly sorted - # # by e_above_hull when sort_by_e_above_hull=True - # Fe_entries = self.rester.get_entries("Fe", sort_by_e_above_hull=True) - # assert Fe_entries[0].data["e_above_hull"] == 0 - - # - # def test_get_exp_entry(self): - # entry = self.rester.get_exp_entry("Fe2O3") - # assert entry.energy == -825.5 - # - # def test_get_stability(self): - # entries = self.rester.get_entries_in_chemsys(["Fe", "O"]) - # modified_entries = [ - # ComputedEntry( - # entry.composition, - # entry.uncorrected_energy + 0.01, - # parameters=entry.parameters, - # entry_id=f"mod_{entry.entry_id}", - # ) - # for entry in entries - # if entry.reduced_formula == "Fe2O3" - # ] - # rester_ehulls = self.rester.get_stability(modified_entries) - # all_entries = entries + modified_entries - # compat = MaterialsProject2020Compatibility() - # all_entries = compat.process_entries(all_entries) - # pd = PhaseDiagram(all_entries) - # for entry in all_entries: - # if str(entry.entry_id).startswith("mod"): - # for dct in rester_ehulls: - # if dct["entry_id"] == entry.entry_id: - # data = dct - # break - # assert pd.get_e_above_hull(entry) == approx(data["e_above_hull"]) - - # def test_get_reaction(self): - # rxn = self.rester.get_reaction(["Li", "O"], ["Li2O"]) - # assert "Li2O" in rxn["Experimental_references"] - - # def test_get_substrates(self): - # substrate_data = self.rester.get_substrates("mp-123", 5, [1, 0, 0]) - # substrates = [sub_dict["sub_id"] for sub_dict in substrate_data] - # assert "mp-2534" in substrates - - # def test_get_surface_data(self): - # data = self.rester.get_surface_data("mp-126") # Pt - # one_surf = self.rester.get_surface_data("mp-129", miller_index=[-2, -3, 1]) - # assert one_surf["surface_energy"] == approx(2.99156963) - # assert_allclose(one_surf["miller_index"], [3, 2, 1]) - # assert "surfaces" in data - # surfaces = data["surfaces"] - # assert len(surfaces) > 0 - # surface = surfaces.pop() - # assert "miller_index" in surface - # assert "surface_energy" in surface - # assert "is_reconstructed" in surface - # data_inc = self.rester.get_surface_data("mp-126", inc_structures=True) - # assert "structure" in data_inc["surfaces"][0] - # - # def test_get_wulff_shape(self): - # ws = self.rester.get_wulff_shape("mp-126") - # assert isinstance(ws, WulffShape) - # - # def test_get_cohesive_energy(self): - # ecoh = self.rester.get_cohesive_energy("mp-13") - # assert ecoh, 5.04543279 - - # def test_get_gb_data(self): - # mo_gbs = self.rester.get_gb_data(chemsys="Mo") - # assert len(mo_gbs) == 10 - # mo_gbs_s5 = self.rester.get_gb_data(pretty_formula="Mo", sigma=5) - # assert len(mo_gbs_s5) == 3 - # mo_s3_112 = self.rester.get_gb_data( - # material_id="mp-129", - # sigma=3, - # gb_plane=[1, -1, -2], - # include_work_of_separation=True, - # ) - # assert len(mo_s3_112) == 1 - # gb_f = mo_s3_112[0]["final_structure"] - # assert_allclose(gb_f.rotation_axis, [1, 1, 0]) - # assert gb_f.rotation_angle == approx(109.47122) - # assert mo_s3_112[0]["gb_energy"] == approx(0.47965, rel=1e-4) - # assert mo_s3_112[0]["work_of_separation"] == approx(6.318144) - # assert "Mo24" in gb_f.formula - # hcp_s7 = self.rester.get_gb_data(material_id="mp-87", gb_plane=[0, 0, 0, 1], include_work_of_separation=True) - # assert hcp_s7[0]["gb_energy"] == approx(1.1206, rel=1e-4) - # assert hcp_s7[0]["work_of_separation"] == approx(2.4706, rel=1e-4) - - # def test_get_interface_reactions(self): - # kinks = self.rester.get_interface_reactions("LiCoO2", "Li3PS4") - # assert len(kinks) > 0 - # kink = kinks[0] - # assert "energy" in kink - # assert "ratio_atomic" in kink - # assert "rxn" in kink - # assert isinstance(kink["rxn"], Reaction) - # kinks_open_O = self.rester.get_interface_reactions("LiCoO2", "Li3PS4", open_el="O", relative_mu=-1) - # assert len(kinks_open_O) > 0 - # with pytest.warns( - # UserWarning, - # match="The reactant MnO9 has no matching entry with negative formation energy, " - # "instead convex hull energy for this composition will be used for reaction energy calculation.", - # ): - # self.rester.get_interface_reactions("LiCoO2", "MnO9") - - # - # def test_pourbaix_heavy(self): - # entries = self.rester.get_pourbaix_entries(["Na", "Ca", "Nd", "Y", "Ho", "F"]) - # _ = PourbaixDiagram(entries, nproc=4, filter_solids=False) - # - # def test_pourbaix_mpr_pipeline(self): - # data = self.rester.get_pourbaix_entries(["Zn"]) - # pbx = PourbaixDiagram(data, filter_solids=True, conc_dict={"Zn": 1e-8}) - # pbx.find_stable_entry(10, 0) - # - # data = self.rester.get_pourbaix_entries(["Ag", "Te"]) - # pbx = PourbaixDiagram(data, filter_solids=True, conc_dict={"Ag": 1e-8, "Te": 1e-8}) - # assert len(pbx.stable_entries) == 30 - # test_entry = pbx.find_stable_entry(8, 2) - # assert sorted(test_entry.entry_id) == ["ion-10", "mp-996958"] - # - # # Test against ion sets with multiple equivalent ions (Bi-V regression) - # entries = self.rester.get_pourbaix_entries(["Bi", "V"]) - # pbx = PourbaixDiagram(entries, filter_solids=True, conc_dict={"Bi": 1e-8, "V": 1e-8}) - # assert all("Bi" in entry.composition and "V" in entry.composition for entry in pbx.all_entries) + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_entries(self): + entries = self.rester.get_entries("TiO2") + assert len(entries) > 1 + for entry in entries: + assert entry.reduced_formula == "TiO2" + + entries = self.rester.get_entries("TiO2", inc_structure=True) + assert len(entries) > 1 + for entry in entries: + assert entry.structure.reduced_formula == "TiO2" + + all_entries = self.rester.get_entries("Fe", compatible_only=False) + entries = self.rester.get_entries("Fe", compatible_only=True) + assert len(entries) < len(all_entries) + entries = self.rester.get_entries("Fe", compatible_only=True, property_data=["cif"]) + assert "cif" in entries[0].data + + for entry in self.rester.get_entries("CdO2", inc_structure=False): + assert entry.data["oxide_type"] is not None + + # test if it will retrieve the conventional unit cell of Ni + entry = self.rester.get_entry_by_material_id("mp-23", inc_structure=True, conventional_unit_cell=True) + Ni = entry.structure + assert Ni.lattice.a == Ni.lattice.b + assert Ni.lattice.a == Ni.lattice.c + assert Ni.lattice.alpha == 90 + assert Ni.lattice.beta == 90 + assert Ni.lattice.gamma == 90 + + # Ensure energy per atom is same + primNi = self.rester.get_entry_by_material_id("mp-23", inc_structure=True, conventional_unit_cell=False) + assert primNi.energy_per_atom == entry.energy_per_atom + + Ni = self.rester.get_structure_by_material_id("mp-23", conventional_unit_cell=True) + assert Ni.lattice.a == Ni.lattice.b + assert Ni.lattice.a == Ni.lattice.c + assert Ni.lattice.alpha == 90 + assert Ni.lattice.beta == 90 + assert Ni.lattice.gamma == 90 + + # Test case where convs are different from initial and final + th = self.rester.get_structure_by_material_id("mp-37", conventional_unit_cell=True) + th_entry = self.rester.get_entry_by_material_id("mp-37", inc_structure=True, conventional_unit_cell=True) + th_entry_initial = self.rester.get_entry_by_material_id( + "mp-37", inc_structure="initial", conventional_unit_cell=True + ) + assert th == th_entry.structure + assert len(th_entry.structure) == 4 + assert len(th_entry_initial.structure) == 2 + + # Test if the polymorphs of Fe are properly sorted + # by e_above_hull when sort_by_e_above_hull=True + Fe_entries = self.rester.get_entries("Fe", sort_by_e_above_hull=True) + assert Fe_entries[0].data["e_above_hull"] == 0 + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_exp_entry(self): + entry = self.rester.get_exp_entry("Fe2O3") + assert entry.energy == -825.5 + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_stability(self): + entries = self.rester.get_entries_in_chemsys(["Fe", "O"]) + modified_entries = [ + ComputedEntry( + entry.composition, + entry.uncorrected_energy + 0.01, + parameters=entry.parameters, + entry_id=f"mod_{entry.entry_id}", + ) + for entry in entries + if entry.reduced_formula == "Fe2O3" + ] + rester_ehulls = self.rester.get_stability(modified_entries) + all_entries = entries + modified_entries + compat = MaterialsProject2020Compatibility() + all_entries = compat.process_entries(all_entries) + pd = PhaseDiagram(all_entries) + for entry in all_entries: + if str(entry.entry_id).startswith("mod"): + for dct in rester_ehulls: + if dct["entry_id"] == entry.entry_id: + data = dct + break + assert pd.get_e_above_hull(entry) == approx(data["e_above_hull"]) + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_reaction(self): + rxn = self.rester.get_reaction(["Li", "O"], ["Li2O"]) + assert "Li2O" in rxn["Experimental_references"] + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_substrates(self): + substrate_data = self.rester.get_substrates("mp-123", 5, [1, 0, 0]) + substrates = [sub_dict["sub_id"] for sub_dict in substrate_data] + assert "mp-2534" in substrates + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_surface_data(self): + data = self.rester.get_surface_data("mp-126") # Pt + one_surf = self.rester.get_surface_data("mp-129", miller_index=[-2, -3, 1]) + assert one_surf["surface_energy"] == approx(2.99156963) + assert_allclose(one_surf["miller_index"], [3, 2, 1]) + assert "surfaces" in data + surfaces = data["surfaces"] + assert len(surfaces) > 0 + surface = surfaces.pop() + assert "miller_index" in surface + assert "surface_energy" in surface + assert "is_reconstructed" in surface + data_inc = self.rester.get_surface_data("mp-126", inc_structures=True) + assert "structure" in data_inc["surfaces"][0] + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_wulff_shape(self): + ws = self.rester.get_wulff_shape("mp-126") + assert isinstance(ws, WulffShape) + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_cohesive_energy(self): + ecoh = self.rester.get_cohesive_energy("mp-13") + assert ecoh, 5.04543279 + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_gb_data(self): + mo_gbs = self.rester.get_gb_data(chemsys="Mo") + assert len(mo_gbs) == 10 + mo_gbs_s5 = self.rester.get_gb_data(pretty_formula="Mo", sigma=5) + assert len(mo_gbs_s5) == 3 + mo_s3_112 = self.rester.get_gb_data( + material_id="mp-129", + sigma=3, + gb_plane=[1, -1, -2], + include_work_of_separation=True, + ) + assert len(mo_s3_112) == 1 + gb_f = mo_s3_112[0]["final_structure"] + assert_allclose(gb_f.rotation_axis, [1, 1, 0]) + assert gb_f.rotation_angle == approx(109.47122) + assert mo_s3_112[0]["gb_energy"] == approx(0.47965, rel=1e-4) + assert mo_s3_112[0]["work_of_separation"] == approx(6.318144) + assert "Mo24" in gb_f.formula + hcp_s7 = self.rester.get_gb_data(material_id="mp-87", gb_plane=[0, 0, 0, 1], include_work_of_separation=True) + assert hcp_s7[0]["gb_energy"] == approx(1.1206, rel=1e-4) + assert hcp_s7[0]["work_of_separation"] == approx(2.4706, rel=1e-4) + + @pytest.mark.skip("TODO: need someone to fix this") + def test_get_interface_reactions(self): + kinks = self.rester.get_interface_reactions("LiCoO2", "Li3PS4") + assert len(kinks) > 0 + kink = kinks[0] + assert "energy" in kink + assert "ratio_atomic" in kink + assert "rxn" in kink + assert isinstance(kink["rxn"], Reaction) + kinks_open_O = self.rester.get_interface_reactions("LiCoO2", "Li3PS4", open_el="O", relative_mu=-1) + assert len(kinks_open_O) > 0 + with pytest.warns( + UserWarning, + match="The reactant MnO9 has no matching entry with negative formation energy, " + "instead convex hull energy for this composition will be used for reaction energy calculation.", + ): + self.rester.get_interface_reactions("LiCoO2", "MnO9") + + @pytest.mark.skip("TODO: need someone to fix this") + def test_pourbaix_heavy(self): + entries = self.rester.get_pourbaix_entries(["Na", "Ca", "Nd", "Y", "Ho", "F"]) + _ = PourbaixDiagram(entries, nproc=4, filter_solids=False) + + @pytest.mark.skip("TODO: need someone to fix this") + def test_pourbaix_mpr_pipeline(self): + data = self.rester.get_pourbaix_entries(["Zn"]) + pbx = PourbaixDiagram(data, filter_solids=True, conc_dict={"Zn": 1e-8}) + pbx.find_stable_entry(10, 0) + + data = self.rester.get_pourbaix_entries(["Ag", "Te"]) + pbx = PourbaixDiagram(data, filter_solids=True, conc_dict={"Ag": 1e-8, "Te": 1e-8}) + assert len(pbx.stable_entries) == 30 + test_entry = pbx.find_stable_entry(8, 2) + assert sorted(test_entry.entry_id) == ["ion-10", "mp-996958"] + + # Test against ion sets with multiple equivalent ions (Bi-V regression) + entries = self.rester.get_pourbaix_entries(["Bi", "V"]) + pbx = PourbaixDiagram(entries, filter_solids=True, conc_dict={"Bi": 1e-8, "V": 1e-8}) + assert all("Bi" in entry.composition and "V" in entry.composition for entry in pbx.all_entries) def test_parity_with_mp_api(self): try: diff --git a/tests/io/lobster/test_lobsterenv.py b/tests/io/lobster/test_lobsterenv.py index 63b5809d051..e4d7ff82738 100644 --- a/tests/io/lobster/test_lobsterenv.py +++ b/tests/io/lobster/test_lobsterenv.py @@ -339,13 +339,13 @@ def test_get_anion_types(self): assert self.chem_env_lobster0_second.anion_types == {Element("O")} def test_get_nn_info(self): - # NO_ADDITIONAL_CONDITION = 0 - # ONLY_ANION_CATION_BONDS = 1 - # NO_ELEMENT_TO_SAME_ELEMENT_BONDS = 2 - # ONLY_ANION_CATION_BONDS_AND_NO_ELEMENT_TO_SAME_ELEMENT_BONDS = 3 - # ONLY_ELEMENT_TO_OXYGEN_BONDS = 4 - # DO_NOT_CONSIDER_ANION_CATION_BONDS=5 - # ONLY_CATION_CATION_BONDS=6 + # 0: NO_ADDITIONAL_CONDITION + # 1: ONLY_ANION_CATION_BONDS + # 2: NO_ELEMENT_TO_SAME_ELEMENT_BONDS + # 3: ONLY_ANION_CATION_BONDS_AND_NO_ELEMENT_TO_SAME_ELEMENT_BONDS + # 4: ONLY_ELEMENT_TO_OXYGEN_BONDS + # 5: DO_NOT_CONSIDER_ANION_CATION_BONDS + # 6: ONLY_CATION_CATION_BONDS # All bonds # ReO3 @@ -367,7 +367,7 @@ def test_get_nn_info(self): ) == 2 ) - # ONLY_ANION_CATION_BONDS = 1 + # 1: ONLY_ANION_CATION_BONDS assert ( len( self.chem_env_lobster1.get_nn( @@ -404,7 +404,7 @@ def test_get_nn_info(self): ) == 8 ) - # NO_ELEMENT_TO_SAME_ELEMENT_BONDS = 2 + # 2: NO_ELEMENT_TO_SAME_ELEMENT_BONDS assert ( len( self.chem_env_lobster2.get_nn( @@ -423,7 +423,7 @@ def test_get_nn_info(self): ) == 2 ) - # ONLY_ANION_CATION_BONDS_AND_NO_ELEMENT_TO_SAME_ELEMENT_BONDS = 3 + # 3: ONLY_ANION_CATION_BONDS_AND_NO_ELEMENT_TO_SAME_ELEMENT_BONDS assert ( len( self.chem_env_lobster3.get_nn( @@ -442,7 +442,7 @@ def test_get_nn_info(self): ) == 2 ) - # ONLY_ELEMENT_TO_OXYGEN_BONDS = 4 + # 4: ONLY_ELEMENT_TO_OXYGEN_BONDS assert ( len( self.chem_env_lobster4.get_nn( @@ -461,7 +461,7 @@ def test_get_nn_info(self): ) == 2 ) - # DO_NOT_CONSIDER_ANION_CATION_BONDS=5 + # 5: DO_NOT_CONSIDER_ANION_CATION_BONDS assert ( len( self.chem_env_lobster5.get_nn( @@ -480,7 +480,7 @@ def test_get_nn_info(self): ) == 0 ) - # ONLY_CATION_CATION_BONDS=6 + # 6: ONLY_CATION_CATION_BONDS assert ( len( self.chem_env_lobster6.get_nn( @@ -514,7 +514,7 @@ def test_get_nn_info(self): == 8 ) - # ONLY_ANION_CATION_BONDS = 1 + # 1: ONLY_ANION_CATION_BONDS assert ( len( self.chem_env_lobster1_second.get_nn( @@ -555,7 +555,7 @@ def test_get_nn_info(self): == 3 ) - # NO_ELEMENT_TO_SAME_ELEMENT_BONDS = 2 + # 2: NO_ELEMENT_TO_SAME_ELEMENT_BONDS assert ( len( self.chem_env_lobster2_second.get_nn( @@ -575,7 +575,7 @@ def test_get_nn_info(self): == 4 ) - # DO_NOT_CONSIDER_ANION_CATION_BONDS=5 + # 5: DO_NOT_CONSIDER_ANION_CATION_BONDS assert ( len( self.chem_env_lobster5_second.get_nn( @@ -594,7 +594,7 @@ def test_get_nn_info(self): ) == 0 ) - # ONLY_CATION_CATION_BONDS=6 + # 6: ONLY_CATION_CATION_BONDS assert ( len( self.chem_env_lobster6_second.get_nn( diff --git a/tests/io/vasp/test_inputs.py b/tests/io/vasp/test_inputs.py index 59a3f038fd6..1eb97705c9e 100644 --- a/tests/io/vasp/test_inputs.py +++ b/tests/io/vasp/test_inputs.py @@ -1316,21 +1316,19 @@ def test_set_symbol(self): assert self.potcar.symbols == ["Fe_pv", "O"] assert self.potcar[0].nelectrons == 14 - # def test_default_functional(self): - # potcar = Potcar(["Fe", "P"]) - # assert potcar[0].functional_class == "GGA" - # assert potcar[1].functional_class == "GGA" - # SETTINGS["PMG_DEFAULT_FUNCTIONAL"] = "LDA" - # potcar = Potcar(["Fe", "P"]) - # assert potcar[0].functional_class == "LDA" - # assert potcar[1].functional_class == "LDA" + @pytest.mark.skip("TODO: need someone to fix this") + def test_default_functional(self): + potcar = Potcar(["Fe", "P"]) + assert potcar[0].functional_class == "GGA" + assert potcar[1].functional_class == "GGA" + SETTINGS["PMG_DEFAULT_FUNCTIONAL"] = "LDA" + potcar = Potcar(["Fe", "P"]) + assert potcar[0].functional_class == "LDA" + assert potcar[1].functional_class == "LDA" def test_pickle(self): pickle.dumps(self.potcar) - # def tearDown(self): - # SETTINGS["PMG_DEFAULT_FUNCTIONAL"] = "PBE" - class TestVaspInput(PymatgenTest): def setUp(self): diff --git a/tests/io/vasp/test_sets.py b/tests/io/vasp/test_sets.py index fe60e3f8d2f..8b7509a0973 100644 --- a/tests/io/vasp/test_sets.py +++ b/tests/io/vasp/test_sets.py @@ -1680,31 +1680,28 @@ def test_potcar(self): ): MVLScanRelaxSet(self.struct, user_potcar_functional="PBE") - # @skip_if_no_psp_dir - # def test_potcar(self): - # - # test_potcar_set_1 = self.set(self.struct, user_potcar_functional="PBE_54") - # assert test_potcar_set_1.potcar.functional == "PBE_54" - # - # with pytest.raises( - # ValueError, match=r"Invalid user_potcar_functional='PBE', must be one of \('PBE_52', 'PBE_54', 'PBE_64'\)" - # ): - # self.set(self.struct, user_potcar_functional="PBE") - # - # # https://github.com/materialsproject/pymatgen/pull/3022 - # # same test also in MITMPRelaxSetTest above (for redundancy, - # # should apply to all classes inheriting from VaspInputSet) - # for user_potcar_settings in [{"Fe": "Fe_pv"}, {"W": "W_pv"}, None]: - # for species in [("W", "W"), ("Fe", "W"), ("Fe", "Fe")]: - # struct = Structure(lattice=Lattice.cubic(3), species=species, coords=[[0, 0, 0], [0.5, 0.5, 0.5]]) - # relax_set = MPRelaxSet( - # structure=struct, user_potcar_functional="PBE_54", user_potcar_settings=user_potcar_settings - # ) - # expected = { - # **({"W": "W_sv"} if "W" in struct.symbol_set else {}), - # **(user_potcar_settings or {}), - # } or None - # assert relax_set.user_potcar_settings == expected + @pytest.mark.skip("TODO: need someone to fix this") + @skip_if_no_psp_dir + def test_potcar_need_fix(self): + test_potcar_set_1 = self.set(self.struct, user_potcar_functional="PBE_54") + assert test_potcar_set_1.potcar.functional == "PBE_54" + + with pytest.raises( + ValueError, match=r"Invalid user_potcar_functional='PBE', must be one of \('PBE_52', 'PBE_54', 'PBE_64'\)" + ): + self.set(self.struct, user_potcar_functional="PBE") + + # https://github.com/materialsproject/pymatgen/pull/3022 + # same test also in MITMPRelaxSetTest above (for redundancy, + # should apply to all classes inheriting from VaspInputSet) + for user_potcar_settings in [{"Fe": "Fe_pv"}, {"W": "W_pv"}, None]: + for species in [("W", "W"), ("Fe", "W"), ("Fe", "Fe")]: + struct = Structure(lattice=Lattice.cubic(3), species=species, coords=[[0, 0, 0], [0.5, 0.5, 0.5]]) + relax_set = MPRelaxSet( + structure=struct, user_potcar_functional="PBE_54", user_potcar_settings=user_potcar_settings + ) + expected = {**({"W": "W_sv"} if "W" in struct.symbol_set else {}), **(user_potcar_settings or {})} + assert relax_set.user_potcar_settings == expected def test_as_from_dict(self): dct = self.mvl_scan_set.as_dict() diff --git a/tests/phonon/test_dos.py b/tests/phonon/test_dos.py index c44d995a90c..0ba4ed39bec 100644 --- a/tests/phonon/test_dos.py +++ b/tests/phonon/test_dos.py @@ -128,19 +128,19 @@ def test_get_last_peak(self): assert peak_freq == approx(4.9662820761) def test_get_dos_fp(self): - # normalize=True + # normalize is True dos_fp = self.dos.get_dos_fp(min_f=-1, max_f=5, n_bins=56, normalize=True) bin_width = np.diff(dos_fp.frequencies)[0][0] assert max(dos_fp.frequencies[0]) <= 5 assert min(dos_fp.frequencies[0]) >= -1 assert len(dos_fp.frequencies[0]) == 56 assert sum(dos_fp.densities * bin_width) == approx(1) - # normalize=False + # normalize is False dos_fp2 = self.dos.get_dos_fp(min_f=-1, max_f=5, n_bins=56, normalize=False) bin_width2 = np.diff(dos_fp2.frequencies)[0][0] assert sum(dos_fp2.densities * bin_width2) == approx(13.722295798242834) assert dos_fp2.bin_width == approx(bin_width2) - # binning=False + # binning is False dos_fp = self.dos.get_dos_fp(min_f=None, max_f=None, n_bins=56, normalize=True, binning=False) assert dos_fp.n_bins == len(self.dos.frequencies)