def test_get_concentration(self): doc = [["Na", 3], ["P", 1]] conc = get_concentration(doc, ["Na", "P"]) self.assertEqual(conc, [0.75]) conc = get_concentration(doc, ["Na", "P"], include_end=True) self.assertEqual(conc, [0.75, 0.25]) conc = get_concentration(doc, ["K", "P"], include_end=True) self.assertEqual(conc, [0.0, 0.25]) doc = {"stoichiometry": [["Na", 3], ["P", 1]]} conc = get_concentration(doc, ["Na", "P"]) self.assertEqual(conc, [0.75]) conc = get_concentration(doc, ["Na", "P"], include_end=True) self.assertEqual(conc, [0.75, 0.25])
def concentration(self): """ Return concentration of each species in stoichiometry. """ if 'concentration' not in self._data: self._data['concentration'] = get_concentration( self.stoichiometry, [elem[0] for elem in self.stoichiometry], include_end=True) return self._data['concentration']
def test_gravimetric_capacity(self): test_docs = [] test_elements = [] Q = [] # Li3P and symmetry test doc = dict() doc["stoichiometry"] = [["Li", 3], ["P", 1]] test_docs.append(doc) test_elements.append(["Li", "P"]) doc = dict() doc["stoichiometry"] = [["P", 1], ["Li", 3]] test_docs.append(doc) test_elements.append(["Li", "P"]) # ternary test doc = dict() doc["stoichiometry"] = [["Li", 1], ["Mo", 1], ["S", 2]] test_docs.append(doc) test_elements.append(["Li", "Mo", "S"]) doc = dict() doc["stoichiometry"] = [["Li", 8], ["Mo", 1], ["S", 2]] test_docs.append(doc) test_elements.append(["Li", "Mo", "S"]) doc = dict() doc["stoichiometry"] = [["Li", 1], ["Mo", 2], ["S", 4]] test_docs.append(doc) test_elements.append(["Li", "Mo", "S"]) for doc, elem in zip(test_docs, test_elements): doc["concentration"] = get_concentration(doc, elem) temp_conc = list(doc["concentration"]) temp_conc.append(1.0) for conc in doc["concentration"]: temp_conc[-1] -= conc Q.append(get_generic_grav_capacity(temp_conc, elem)) self.assertAlmostEqual(Q[0], 2596.096626125, places=3) self.assertAlmostEqual(Q[2], 167.449, places=3) self.assertEqual(Q[0], Q[1]) self.assertEqual(round(8 * Q[2], 3), round(Q[3], 3)) self.assertEqual(round(Q[2], 3), round(2 * Q[4], 3))
def _get_hull_distance(self, generation): """ Assign distance from the hull from hull for generation, assigning it. Parameters: generation (Generation): list of optimised structures. Returns: hull_dist (list(float)): list of distances to the hull. """ for ind, populum in enumerate(generation): generation[ind]["concentration"] = get_concentration( populum, self.hull.elements) generation[ind][ "formation_enthalpy_per_atom"] = get_formation_energy( self.chempots, populum) if self.debug: print( generation[ind]["concentration"], generation[ind]["formation_enthalpy_per_atom"], ) if self.testing: for ind, populum in enumerate(generation): generation[ind][ "formation_enthalpy_per_atom"] = np.random.rand() - 0.5 structures = np.hstack(( get_array_from_cursor(generation, "concentration"), get_array_from_cursor(generation, "formation_enthalpy_per_atom").reshape( len(generation), 1), )) if self.debug: print(structures) hull_dist = self.hull.get_hull_distances(structures, precompute=False) for ind, populum in enumerate(generation): generation[ind]["hull_distance"] = hull_dist[ind] return hull_dist
def construct_structure_attributes(self, doc: Crystal): structure_attributes = {} # from optimade StructureResourceAttributes structure_attributes["elements"] = doc.elems structure_attributes["nelements"] = len(doc.elems) concentration = get_concentration(doc._data, elements=doc.elems, include_end=True) structure_attributes["elements_ratios"] = concentration structure_attributes["chemical_formula_descriptive"] = doc.formula structure_attributes["chemical_formula_reduced"] = doc.formula structure_attributes["chemical_formula_hill"] = None sorted_stoich = sorted(doc.stoichiometry, key=lambda x: x[1], reverse=True) gen = anonymous_element_generator() for ind, elem in enumerate(sorted_stoich): elem[0] = next(gen) structure_attributes[ "chemical_formula_anonymous"] = get_formula_from_stoich( doc.stoichiometry, elements=[elem[0] for elem in sorted_stoich]) structure_attributes["dimension_types"] = [1, 1, 1] structure_attributes["nperiodic_dimensions"] = 3 structure_attributes["lattice_vectors"] = doc.lattice_cart structure_attributes["lattice_abc"] = doc.lattice_abc structure_attributes["cell_volume"] = cart2volume(doc.lattice_cart) structure_attributes["fractional_site_positions"] = doc.positions_frac structure_attributes["cartesian_site_positions"] = doc.positions_abs structure_attributes["nsites"] = doc.num_atoms structure_attributes["species_at_sites"] = doc.atom_types species = [] for ind, atom in enumerate(doc.elems): species.append( Species(name=atom, chemical_symbols=[atom], concentration=[1.0])) structure_attributes["species"] = species structure_attributes["assemblies"] = None structure_attributes["structure_features"] = [] # from optimade EntryResourceAttributes if "text_id" not in doc._data: structure_attributes["local_id"] = " ".join([ self.wlines[random.randint(0, self.num_words - 1)].strip(), self.nlines[random.randint(0, self.num_nouns - 1)].strip(), ]) else: structure_attributes["local_id"] = " ".join(doc._data["text_id"]) structure_attributes["last_modified"] = datetime.datetime.now() if "_id" in doc._data: structure_attributes["immutable_id"] = str(doc._data["_id"]) else: structure_attributes["immutable_id"] = str( bson.objectid.ObjectId()) # if "date" in doc._data: # date = [int(val) for val in doc._data["date"].split("-")] # structure_attributes["date"] = datetime.date( # year=date[-1], month=date[1], day=date[0] # ) # from matador extensions structure_attributes[ "dft_parameters"] = self.construct_dft_hamiltonian(doc) structure_attributes["submitter"] = self.construct_submitter(doc) structure_attributes["thermodynamics"] = self.construct_thermodynamics( doc) structure_attributes["space_group"] = self.construct_spacegroup(doc) structure_attributes["calculator"] = self.construct_calculator(doc) structure_attributes["stress_tensor"] = doc._data.get("stress") structure_attributes["stress"] = doc._data["pressure"] structure_attributes["forces"] = doc._data.get("forces") structure_attributes["max_force_on_atom"] = doc._data.get( "max_force_on_atom") return MatadorStructureResourceAttributes(**structure_attributes)
def test_toy_ternary(self): cursor = [ { "stoichiometry": [["K", 1.0]], "enthalpy_per_atom": 0, "cell_volume": 100, "num_atoms": 10, }, { "stoichiometry": [["Sn", 1.0]], "enthalpy_per_atom": 0, "cell_volume": 100, "num_atoms": 10, }, { "stoichiometry": [["P", 1.0]], "enthalpy_per_atom": 0, "cell_volume": 100, "num_atoms": 10, }, { "stoichiometry": [["K", 1.0], ["Sn", 1.0], ["P", 1.0]], "enthalpy_per_atom": -1, "cell_volume": 100, "num_atoms": 30, }, { "stoichiometry": [["K", 1.0], ["Sn", 1.0], ["P", 1.0]], "enthalpy_per_atom": -0.5, "cell_volume": 100, "num_atoms": 30, }, { "stoichiometry": [["Sn", 1.0], ["P", 1.0]], "enthalpy_per_atom": 0.1, "cell_volume": 100, "num_atoms": 30, }, { "stoichiometry": [["K", 4.0], ["Sn", 2.0], ["P", 2.0]], "enthalpy_per_atom": -0.74, "cell_volume": 100, "num_atoms": 30, }, { "stoichiometry": [["K", 2.0], ["Sn", 2.0], ["P", 4.0]], "enthalpy_per_atom": -0.74, "cell_volume": 100, "num_atoms": 30, }, { "stoichiometry": [["K", 2.0], ["Sn", 4.0], ["P", 2.0]], "enthalpy_per_atom": -0.74, "cell_volume": 100, "num_atoms": 30, }, { "stoichiometry": [["Sn", 1.0], ["P", 1.0]], "enthalpy_per_atom": 0, "cell_volume": 100, "num_atoms": 30, }, ] for ind, doc in enumerate(cursor): cursor[ind]["concentration"] = get_concentration( doc, ["K", "Sn", "P"]) cursor[ind]["source"] = ["abcde"] cursor[ind]["num_fu"] = 10 cursor[ind]["enthalpy"] = (cursor[ind]["enthalpy_per_atom"] * doc["num_atoms"]) hull = QueryConvexHull(cursor=cursor, elements=["K", "Sn", "P"], no_plot=True) hull_dists = [doc["hull_distance"] for doc in hull.cursor] np.testing.assert_array_almost_equal( hull_dists, [0, 0, 0, 0, 0.5, 0.1, 0.01, 0.01, 0.01, 0])
def test_ternary_volume_curve(self): cursor = [ { "stoichiometry": [["K", 1.0]], "enthalpy_per_atom": 0, "cell_volume": 10, "num_atoms": 10, "num_fu": 10, }, { "stoichiometry": [["Sn", 1.0]], "enthalpy_per_atom": 0, "cell_volume": 100, "num_atoms": 10, "num_fu": 10, }, { "stoichiometry": [["P", 1.0]], "enthalpy_per_atom": 0, "cell_volume": 100, "num_atoms": 10, "num_fu": 10, }, { "stoichiometry": [["K", 1.0], ["Sn", 1.0], ["P", 1.0]], "enthalpy_per_atom": -1, "cell_volume": 210, "num_atoms": 30, "num_fu": 10, }, { "stoichiometry": [["Sn", 2.0], ["P", 1.0]], "enthalpy_per_atom": -0.1, "cell_volume": 300, "num_atoms": 30, "num_fu": 10, }, ] for ind, doc in enumerate(cursor): cursor[ind]["concentration"] = get_concentration( doc, ["K", "Sn", "P"]) cursor[ind]["source"] = ["abcde"] cursor[ind]["enthalpy"] = (cursor[ind]["enthalpy_per_atom"] * doc["num_atoms"]) hull = QueryConvexHull(cursor=cursor, elements=["K", "Sn", "P"], no_plot=True, voltage=True) np.testing.assert_array_almost_equal( hull.volume_data["electrode_volume"][0], [30, 31]) np.testing.assert_array_almost_equal( hull.volume_data["volume_ratio_with_bulk"][0], [1, 31 / 30]) cursor = [ { "stoichiometry": [["K", 1.0]], "enthalpy_per_atom": 0, "cell_volume": 10, "num_atoms": 10, "num_fu": 10, }, { "stoichiometry": [["Sn", 1.0]], "enthalpy_per_atom": 0, "cell_volume": 100, "num_atoms": 10, "num_fu": 10, }, { "stoichiometry": [["P", 1.0]], "enthalpy_per_atom": 0, "cell_volume": 100, "num_atoms": 10, "num_fu": 10, }, { "stoichiometry": [["K", 1.0], ["Sn", 1.0], ["P", 1.0]], "enthalpy_per_atom": -1, "cell_volume": 210, "num_atoms": 30, "num_fu": 10, }, { "stoichiometry": [["Sn", 2.0], ["P", 1.0]], "enthalpy_per_atom": -0.1, "cell_volume": 150, "num_atoms": 30, "num_fu": 10, }, ] for ind, doc in enumerate(cursor): cursor[ind]["concentration"] = get_concentration( doc, ["K", "Sn", "P"]) cursor[ind]["source"] = ["abcde"] cursor[ind]["enthalpy"] = (cursor[ind]["enthalpy_per_atom"] * doc["num_atoms"]) hull = QueryConvexHull(cursor=cursor, elements=["K", "Sn", "P"], no_plot=True, voltage=True) np.testing.assert_array_almost_equal( hull.volume_data["electrode_volume"][0], [15, 31]) np.testing.assert_array_almost_equal( hull.volume_data["volume_ratio_with_bulk"][0], [1, 31 / 15])