コード例 #1
0
 def test_no_oxidation_state(self):
     mo0 = Species("Mo", None, {"spin": 5})
     self.assertEqual(str(mo0), "Mo,spin=5")
コード例 #2
0
 def test_stringify(self):
     self.assertEqual(self.specie2.to_latex_string(), "Fe$^{3+}$")
     self.assertEqual(self.specie2.to_unicode_string(), "Fe³⁺")
     self.assertEqual(Species("S", -2).to_latex_string(), "S$^{2-}$")
     self.assertEqual(Species("S", -2).to_unicode_string(), "S²⁻")
コード例 #3
0
 def test_deepcopy(self):
     el1 = Species("Fe", 4)
     el2 = Species("Na", 1)
     ellist = [el1, el2]
     self.assertEqual(ellist, deepcopy(ellist),
                      "Deepcopy operation doesn't produce exact copy.")
コード例 #4
0
    def test_get_crystal_field_spin(self):
        self.assertEqual(Species("Fe", 2).get_crystal_field_spin(), 4)
        self.assertEqual(Species("Fe", 3).get_crystal_field_spin(), 5)
        self.assertEqual(Species("Fe", 4).get_crystal_field_spin(), 4)
        self.assertEqual(
            Species("Co", 3).get_crystal_field_spin(spin_config="low"), 0)
        self.assertEqual(
            Species("Co", 4).get_crystal_field_spin(spin_config="low"), 1)
        self.assertEqual(
            Species("Ni", 3).get_crystal_field_spin(spin_config="low"), 1)
        self.assertEqual(
            Species("Ni", 4).get_crystal_field_spin(spin_config="low"), 0)

        self.assertRaises(AttributeError,
                          Species("Li", 1).get_crystal_field_spin)
        self.assertRaises(AttributeError,
                          Species("Ge", 4).get_crystal_field_spin)
        self.assertRaises(AttributeError,
                          Species("H", 1).get_crystal_field_spin)
        self.assertRaises(AttributeError,
                          Species("Fe", 10).get_crystal_field_spin)
        self.assertRaises(ValueError,
                          Species("Fe", 2).get_crystal_field_spin, "hex")

        s = Species("Co", 3).get_crystal_field_spin("tet", spin_config="low")
        self.assertEqual(s, 2)
コード例 #5
0
 def test_ionic_radius(self):
     self.assertEqual(self.specie2.ionic_radius, 78.5 / 100)
     self.assertEqual(self.specie3.ionic_radius, 92 / 100)
     self.assertAlmostEqual(Species("Mn", 4).ionic_radius, 0.67)
コード例 #6
0
 def test_cmp(self):
     self.assertLess(self.specie1, self.specie2, "Fe2+ should be < Fe3+")
     self.assertLess(Species("C", 1), Species("Se", 1))
コード例 #7
0
class SpecieTestCase(PymatgenTest):
    def setUp(self):
        self.specie1 = Species.from_string("Fe2+")
        self.specie2 = Species("Fe", 3)
        self.specie3 = Species("Fe", 2)
        self.specie4 = Species("Fe", 2, {"spin": 5})

    def test_init(self):
        self.assertRaises(ValueError, Species, "Fe", 2, {"magmom": 5})

    def test_ionic_radius(self):
        self.assertEqual(self.specie2.ionic_radius, 78.5 / 100)
        self.assertEqual(self.specie3.ionic_radius, 92 / 100)
        self.assertAlmostEqual(Species("Mn", 4).ionic_radius, 0.67)

    def test_eq(self):
        self.assertEqual(
            self.specie1,
            self.specie3,
            "Static and actual constructor gives unequal result!",
        )
        self.assertNotEqual(self.specie1, self.specie2,
                            "Fe2+ should not be equal to Fe3+")
        self.assertNotEqual(self.specie4, self.specie3)
        self.assertFalse(self.specie1 == Element("Fe"))
        self.assertFalse(Element("Fe") == self.specie1)

    def test_cmp(self):
        self.assertLess(self.specie1, self.specie2, "Fe2+ should be < Fe3+")
        self.assertLess(Species("C", 1), Species("Se", 1))

    def test_attr(self):
        self.assertEqual(self.specie1.Z, 26,
                         "Z attribute for Fe2+ should be = Element Fe.")
        self.assertEqual(self.specie4.spin, 5)

    def test_deepcopy(self):
        el1 = Species("Fe", 4)
        el2 = Species("Na", 1)
        ellist = [el1, el2]
        self.assertEqual(ellist, deepcopy(ellist),
                         "Deepcopy operation doesn't produce exact copy.")

    def test_pickle(self):
        self.assertEqual(self.specie1,
                         pickle.loads(pickle.dumps(self.specie1)))
        for i in range(1, 5):
            self.serialize_with_pickle(getattr(self, "specie%d" % i),
                                       test_eq=True)
        cs = Species("Cs", 1)
        cl = Species("Cl", 1)

        with open("cscl.pickle", "wb") as f:
            pickle.dump((cs, cl), f)

        with open("cscl.pickle", "rb") as f:
            d = pickle.load(f)
            self.assertEqual(d, (cs, cl))
        os.remove("cscl.pickle")

    def test_get_crystal_field_spin(self):
        self.assertEqual(Species("Fe", 2).get_crystal_field_spin(), 4)
        self.assertEqual(Species("Fe", 3).get_crystal_field_spin(), 5)
        self.assertEqual(Species("Fe", 4).get_crystal_field_spin(), 4)
        self.assertEqual(
            Species("Co", 3).get_crystal_field_spin(spin_config="low"), 0)
        self.assertEqual(
            Species("Co", 4).get_crystal_field_spin(spin_config="low"), 1)
        self.assertEqual(
            Species("Ni", 3).get_crystal_field_spin(spin_config="low"), 1)
        self.assertEqual(
            Species("Ni", 4).get_crystal_field_spin(spin_config="low"), 0)

        self.assertRaises(AttributeError,
                          Species("Li", 1).get_crystal_field_spin)
        self.assertRaises(AttributeError,
                          Species("Ge", 4).get_crystal_field_spin)
        self.assertRaises(AttributeError,
                          Species("H", 1).get_crystal_field_spin)
        self.assertRaises(AttributeError,
                          Species("Fe", 10).get_crystal_field_spin)
        self.assertRaises(ValueError,
                          Species("Fe", 2).get_crystal_field_spin, "hex")

        s = Species("Co", 3).get_crystal_field_spin("tet", spin_config="low")
        self.assertEqual(s, 2)

    def test_get_nmr_mom(self):
        self.assertEqual(Species("H").get_nmr_quadrupole_moment(), 2.860)
        self.assertEqual(Species("Li").get_nmr_quadrupole_moment(), -0.808)
        self.assertEqual(
            Species("Li").get_nmr_quadrupole_moment("Li-7"), -40.1)
        self.assertEqual(Species("Si").get_nmr_quadrupole_moment(), 0.0)
        self.assertRaises(ValueError,
                          Species("Li").get_nmr_quadrupole_moment, "Li-109")

    def test_get_shannon_radius(self):
        self.assertEqual(Species("Li", 1).get_shannon_radius("IV"), 0.59)
        mn2 = Species("Mn", 2)
        self.assertEqual(mn2.get_shannon_radius("IV", "High Spin"), 0.66)
        self.assertEqual(mn2.get_shannon_radius("V", "High Spin"), 0.75)

        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            # Trigger a warning.
            r = mn2.get_shannon_radius("V")
            # Verify some things
            self.assertEqual(len(w), 1)
            self.assertIs(w[-1].category, UserWarning)
            self.assertEqual(r, 0.75)

        self.assertEqual(mn2.get_shannon_radius("VI", "Low Spin"), 0.67)
        self.assertEqual(mn2.get_shannon_radius("VI", "High Spin"), 0.83)
        self.assertEqual(mn2.get_shannon_radius("VII", "High Spin"), 0.9)
        self.assertEqual(mn2.get_shannon_radius("VIII"), 0.96)

    def test_sort(self):
        els = map(get_el_sp, ["N3-", "Si4+", "Si3+"])
        self.assertEqual(
            sorted(els),
            [Species("Si", 3),
             Species("Si", 4),
             Species("N", -3)])

    def test_to_from_string(self):
        fe3 = Species("Fe", 3, {"spin": 5})
        self.assertEqual(str(fe3), "Fe3+,spin=5")
        fe = Species.from_string("Fe3+,spin=5")
        self.assertEqual(fe.spin, 5)
        mo0 = Species("Mo", 0, {"spin": 5})
        self.assertEqual(str(mo0), "Mo0+,spin=5")
        mo = Species.from_string("Mo0+,spin=4")
        self.assertEqual(mo.spin, 4)

        # Shyue Ping: I don't understand the need for a None for oxidation state. That to me is basically an element.
        # Why make the thing so complicated for a use case that I have never seen???
        # fe_no_ox = Species("Fe", oxidation_state=None, properties={"spin": 5})
        # fe_no_ox_from_str = Species.from_string("Fe,spin=5")
        # self.assertEqual(fe_no_ox, fe_no_ox_from_str)

    def test_no_oxidation_state(self):
        mo0 = Species("Mo", None, {"spin": 5})
        self.assertEqual(str(mo0), "Mo,spin=5")

    def test_stringify(self):
        self.assertEqual(self.specie2.to_latex_string(), "Fe$^{3+}$")
        self.assertEqual(self.specie2.to_unicode_string(), "Fe³⁺")
        self.assertEqual(Species("S", -2).to_latex_string(), "S$^{2-}$")
        self.assertEqual(Species("S", -2).to_unicode_string(), "S²⁻")
コード例 #8
0
 def setUp(self):
     self.specie1 = Species.from_string("Fe2+")
     self.specie2 = Species("Fe", 3)
     self.specie3 = Species("Fe", 2)
     self.specie4 = Species("Fe", 2, {"spin": 5})
コード例 #9
0
 def test_get_nmr_mom(self):
     self.assertEqual(Species("H").get_nmr_quadrupole_moment(), 2.860)
     self.assertEqual(Species("Li").get_nmr_quadrupole_moment(), -0.808)
     self.assertEqual(Species("Li").get_nmr_quadrupole_moment("Li-7"), -40.1)
     self.assertEqual(Species("Si").get_nmr_quadrupole_moment(), 0.0)
     self.assertRaises(ValueError, Species("Li").get_nmr_quadrupole_moment, "Li-109")
コード例 #10
0
 def test_sort(self):
     els = map(get_el_sp, ["N3-", "Si4+", "Si3+"])
     self.assertEqual(sorted(els), [Species("Si", 3), Species("Si", 4), Species("N", -3)])
コード例 #11
0
    def test_light_structure_environments(self):
        with ScratchDir("."):
            f = open(f"{se_files_dir}/se_mp-7000.json")
            dd = json.load(f)
            f.close()

            se = StructureEnvironments.from_dict(dd)

            strategy = SimplestChemenvStrategy()
            lse = LightStructureEnvironments.from_structure_environments(
                structure_environments=se,
                strategy=strategy,
                valences="undefined")
            isite = 6
            nb_set = lse.neighbors_sets[isite][0]
            neighb_coords = [
                np.array([0.2443798, 1.80409653, -1.13218359]),
                np.array([1.44020353, 1.11368738, 1.13218359]),
                np.array([2.75513098, 2.54465207, -0.70467298]),
                np.array([0.82616785, 3.65833945, 0.70467298]),
            ]
            neighb_indices = [0, 3, 5, 1]
            neighb_images = [[0, 0, -1], [0, 0, 0], [0, 0, -1], [0, 0, 0]]

            np.testing.assert_array_almost_equal(neighb_coords,
                                                 nb_set.neighb_coords)
            np.testing.assert_array_almost_equal(
                neighb_coords, [s.coords for s in nb_set.neighb_sites])
            nb_sai = nb_set.neighb_sites_and_indices
            np.testing.assert_array_almost_equal(
                neighb_coords, [sai["site"].coords for sai in nb_sai])
            np.testing.assert_array_almost_equal(
                neighb_indices, [sai["index"] for sai in nb_sai])
            nb_iai = nb_set.neighb_indices_and_images
            np.testing.assert_array_almost_equal(
                neighb_indices, [iai["index"] for iai in nb_iai])
            np.testing.assert_array_equal(
                neighb_images, [iai["image_cell"] for iai in nb_iai])

            self.assertEqual(nb_set.__len__(), 4)
            self.assertEqual(nb_set.__hash__(), 4)

            self.assertFalse(nb_set.__ne__(nb_set))

            self.assertEqual(
                nb_set.__str__(),
                "Neighbors Set for site #6 :\n"
                " - Coordination number : 4\n"
                " - Neighbors sites indices : 0, 1, 2, 3\n",
            )

            stats = lse.get_statistics()

            neighbors = lse.strategy.get_site_neighbors(
                site=lse.structure[isite])
            self.assertArrayAlmostEqual(
                neighbors[0].coords,
                np.array([0.2443798, 1.80409653, -1.13218359]))
            self.assertArrayAlmostEqual(
                neighbors[1].coords,
                np.array([1.44020353, 1.11368738, 1.13218359]))
            self.assertArrayAlmostEqual(
                neighbors[2].coords,
                np.array([2.75513098, 2.54465207, -0.70467298]))
            self.assertArrayAlmostEqual(
                neighbors[3].coords,
                np.array([0.82616785, 3.65833945, 0.70467298]))

            equiv_site_index_and_transform = lse.strategy.equivalent_site_index_and_transform(
                neighbors[0])
            self.assertEqual(equiv_site_index_and_transform[0], 0)
            self.assertArrayAlmostEqual(equiv_site_index_and_transform[1],
                                        [0.0, 0.0, 0.0])
            self.assertArrayAlmostEqual(equiv_site_index_and_transform[2],
                                        [0.0, 0.0, -1.0])

            equiv_site_index_and_transform = lse.strategy.equivalent_site_index_and_transform(
                neighbors[1])
            self.assertEqual(equiv_site_index_and_transform[0], 3)
            self.assertArrayAlmostEqual(equiv_site_index_and_transform[1],
                                        [0.0, 0.0, 0.0])
            self.assertArrayAlmostEqual(equiv_site_index_and_transform[2],
                                        [0.0, 0.0, 0.0])

            self.assertEqual(stats["atom_coordination_environments_present"],
                             {"Si": {
                                 "T:4": 3.0
                             }})
            self.assertEqual(stats["coordination_environments_atom_present"],
                             {"T:4": {
                                 "Si": 3.0
                             }})
            self.assertEqual(
                stats["fraction_atom_coordination_environments_present"],
                {"Si": {
                    "T:4": 1.0
                }},
            )

            site_info_ce = lse.get_site_info_for_specie_ce(specie=Species(
                "Si", 4),
                                                           ce_symbol="T:4")
            np.testing.assert_array_almost_equal(site_info_ce["fractions"],
                                                 [1.0, 1.0, 1.0])
            np.testing.assert_array_almost_equal(
                site_info_ce["csms"],
                [
                    0.009887784240541068, 0.009887786546730826,
                    0.009887787384385317
                ],
            )
            self.assertEqual(site_info_ce["isites"], [6, 7, 8])

            site_info_allces = lse.get_site_info_for_specie_allces(
                specie=Species("Si", 4))

            self.assertEqual(site_info_allces["T:4"], site_info_ce)

            self.assertFalse(lse.contains_only_one_anion("I-"))
            self.assertFalse(lse.contains_only_one_anion_atom("I"))
            self.assertTrue(
                lse.site_contains_environment(isite=isite, ce_symbol="T:4"))
            self.assertFalse(
                lse.site_contains_environment(isite=isite, ce_symbol="S:4"))
            self.assertFalse(
                lse.structure_contains_atom_environment(atom_symbol="Si",
                                                        ce_symbol="S:4"))
            self.assertTrue(
                lse.structure_contains_atom_environment(atom_symbol="Si",
                                                        ce_symbol="T:4"))
            self.assertFalse(
                lse.structure_contains_atom_environment(atom_symbol="O",
                                                        ce_symbol="T:4"))
            self.assertTrue(lse.uniquely_determines_coordination_environments)
            self.assertFalse(lse.__ne__(lse))

            envs = lse.strategy.get_site_coordination_environments(
                lse.structure[6])
            self.assertEqual(len(envs), 1)
            self.assertEqual(envs[0][0], "T:4")

            multi_strategy = MultiWeightsChemenvStrategy.stats_article_weights_parameters(
            )

            lse_multi = LightStructureEnvironments.from_structure_environments(
                strategy=multi_strategy,
                structure_environments=se,
                valences="undefined")
            self.assertAlmostEqual(
                lse_multi.coordination_environments[isite][0]["csm"],
                0.009887784240541068,
            )
            self.assertAlmostEqual(
                lse_multi.coordination_environments[isite][0]["ce_fraction"],
                1.0)
            self.assertEqual(
                lse_multi.coordination_environments[isite][0]["ce_symbol"],
                "T:4")
コード例 #12
0
ファイル: composition.py プロジェクト: yiwang62/pymatgen
    def _get_oxid_state_guesses(self, all_oxi_states, max_sites,
                                oxi_states_override, target_charge):
        """
        Utility operation for guessing oxidation states.

        See `oxi_state_guesses` for full details. This operation does the
        calculation of the most likely oxidation states

        Args:
            oxi_states_override (dict): dict of str->list to override an
                element's common oxidation states, e.g. {"V": [2,3,4,5]}
            target_charge (int): the desired total charge on the structure.
                Default is 0 signifying charge balance.
            all_oxi_states (bool): if True, an element defaults to
                all oxidation states in pymatgen Element.icsd_oxidation_states.
                Otherwise, default is Element.common_oxidation_states. Note
                that the full oxidation state list is *very* inclusive and
                can produce nonsensical results.
            max_sites (int): if possible, will reduce Compositions to at most
                this many sites to speed up oxidation state guesses. If the
                composition cannot be reduced to this many sites a ValueError
                will be raised. Set to -1 to just reduce fully. If set to a
                number less than -1, the formula will be fully reduced but a
                ValueError will be thrown if the number of atoms in the reduced
                formula is greater than abs(max_sites).

        Returns:
            A list of dicts - each dict reports an element symbol and average
                oxidation state across all sites in that composition. If the
                composition is not charge balanced, an empty list is returned.
            A list of dicts - each dict maps the element symbol to a list of
                oxidation states for each site of that element. For example, Fe3O4 could
                return a list of [2,2,2,3,3,3] for the oxidation states of If the composition
                is

        """
        comp = self.copy()
        # reduce Composition if necessary
        if max_sites and max_sites < 0:
            comp = self.reduced_composition

            if max_sites < -1 and comp.num_atoms > abs(max_sites):
                raise ValueError("Composition {} cannot accommodate max_sites "
                                 "setting!".format(comp))

        elif max_sites and comp.num_atoms > max_sites:
            reduced_comp, reduced_factor = self.get_reduced_composition_and_factor(
            )
            if reduced_factor > 1:
                reduced_comp *= max(1, int(max_sites / reduced_comp.num_atoms))
                comp = reduced_comp  # as close to max_sites as possible
            if comp.num_atoms > max_sites:
                raise ValueError("Composition {} cannot accommodate max_sites "
                                 "setting!".format(comp))

        # Load prior probabilities of oxidation states, used to rank solutions
        if not Composition.oxi_prob:
            module_dir = os.path.join(
                os.path.dirname(os.path.abspath(__file__)))
            all_data = loadfn(
                os.path.join(module_dir, "..", "analysis", "icsd_bv.yaml"))
            Composition.oxi_prob = {
                Species.from_string(sp): data
                for sp, data in all_data["occurrence"].items()
            }
        oxi_states_override = oxi_states_override or {}
        # assert: Composition only has integer amounts
        if not all(amt == int(amt) for amt in comp.values()):
            raise ValueError("Charge balance analysis requires integer "
                             "values in Composition!")

        # for each element, determine all possible sum of oxidations
        # (taking into account nsites for that particular element)
        el_amt = comp.get_el_amt_dict()
        els = el_amt.keys()
        el_sums = []  # matrix: dim1= el_idx, dim2=possible sums
        el_sum_scores = collections.defaultdict(
            set)  # dict of el_idx, sum -> score
        el_best_oxid_combo = {
        }  # dict of el_idx, sum -> oxid combo with best score
        for idx, el in enumerate(els):
            el_sum_scores[idx] = {}
            el_best_oxid_combo[idx] = {}
            el_sums.append([])
            if oxi_states_override.get(el):
                oxids = oxi_states_override[el]
            elif all_oxi_states:
                oxids = Element(el).oxidation_states
            else:
                oxids = Element(el).icsd_oxidation_states or Element(
                    el).oxidation_states

            # get all possible combinations of oxidation states
            # and sum each combination
            for oxid_combo in combinations_with_replacement(
                    oxids, int(el_amt[el])):

                # List this sum as a possible option
                oxid_sum = sum(oxid_combo)
                if oxid_sum not in el_sums[idx]:
                    el_sums[idx].append(oxid_sum)

                # Determine how probable is this combo?
                score = sum([
                    Composition.oxi_prob.get(Species(el, o), 0)
                    for o in oxid_combo
                ])

                # If it is the most probable combo for a certain sum,
                #   store the combination
                if oxid_sum not in el_sum_scores[
                        idx] or score > el_sum_scores[idx].get(oxid_sum, 0):
                    el_sum_scores[idx][oxid_sum] = score
                    el_best_oxid_combo[idx][oxid_sum] = oxid_combo

        # Determine which combination of oxidation states for each element
        #    is the most probable
        all_sols = []  # will contain all solutions
        all_oxid_combo = [
        ]  # will contain the best combination of oxidation states for each site
        all_scores = []  # will contain a score for each solution
        for x in product(*el_sums):
            # each x is a trial of one possible oxidation sum for each element
            if sum(x) == target_charge:  # charge balance condition
                el_sum_sol = dict(zip(els, x))  # element->oxid_sum
                # normalize oxid_sum by amount to get avg oxid state
                sol = {el: v / el_amt[el] for el, v in el_sum_sol.items()}
                # add the solution to the list of solutions
                all_sols.append(sol)

                # determine the score for this solution
                score = 0
                for idx, v in enumerate(x):
                    score += el_sum_scores[idx][v]
                all_scores.append(score)

                # collect the combination of oxidation states for each site
                all_oxid_combo.append(
                    dict((e, el_best_oxid_combo[idx][v])
                         for idx, (e, v) in enumerate(zip(els, x))))

        # sort the solutions by highest to lowest score
        if all_scores:
            all_sols, all_oxid_combo = zip(*[(y, x) for (z, y, x) in sorted(
                zip(all_scores, all_sols, all_oxid_combo),
                key=lambda pair: pair[0],
                reverse=True,
            )])
        return all_sols, all_oxid_combo
コード例 #13
0
        "H", "B", "C", "Si", "N", "P", "As", "Sb", "O", "S", "Se", "Te", "F",
        "Cl", "Br", "I"
    ]
]

module_dir = os.path.dirname(os.path.abspath(__file__))

# Read in BV parameters.
BV_PARAMS = {}
for k, v in loadfn(os.path.join(module_dir, "bvparam_1991.yaml")).items():
    BV_PARAMS[Element(k)] = v

# Read in yaml containing data-mined ICSD BV data.
all_data = loadfn(os.path.join(module_dir, "icsd_bv.yaml"))
ICSD_BV_DATA = {
    Species.from_string(sp): data
    for sp, data in all_data["bvsum"].items()
}
PRIOR_PROB = {
    Species.from_string(sp): data
    for sp, data in all_data["occurrence"].items()
}


def calculate_bv_sum(site, nn_list, scale_factor=1.0):
    """
    Calculates the BV sum of a site.

    Args:
        site (PeriodicSite): The central site to calculate the bond valence
        nn_list ([Neighbor]): A list of namedtuple Neighbors having "distance"
コード例 #14
0
        "Cl",
        "Br",
        "I",
    ]
]

module_dir = os.path.dirname(os.path.abspath(__file__))

# Read in BV parameters.
BV_PARAMS = {}
for k, v in loadfn(os.path.join(module_dir, "bvparam_1991.yaml")).items():
    BV_PARAMS[Element(k)] = v

# Read in yaml containing data-mined ICSD BV data.
all_data = loadfn(os.path.join(module_dir, "icsd_bv.yaml"))
ICSD_BV_DATA = {Species.from_string(sp): data for sp, data in all_data["bvsum"].items()}
PRIOR_PROB = {Species.from_string(sp): data for sp, data in all_data["occurrence"].items()}


def calculate_bv_sum(site, nn_list, scale_factor=1.0):
    """
    Calculates the BV sum of a site.

    Args:
        site (PeriodicSite): The central site to calculate the bond valence
        nn_list ([Neighbor]): A list of namedtuple Neighbors having "distance"
            and "site" attributes
        scale_factor (float): A scale factor to be applied. This is useful for
            scaling distance, esp in the case of calculation-relaxed structures
            which may tend to under (GGA) or over bind (LDA).
    """
コード例 #15
0
 def test_find_codopant(self):
     self.assertEqual(_find_codopant(Species("Fe", 2), 1), Species("Cu", 1))
     self.assertEqual(_find_codopant(Species("Fe", 2), 3), Species("In", 3))