def has_common_oxi_states(row): comp = Composition(row.StructuredFormula) int_comp = Composition( comp.get_integer_formula_and_factor()[0]) # get integer formular ############################################################################################### # according to the documentation of pymatgen's Composition class' oxi_state_guesses(), the default # value of the argument all_oxi_states is False, which means that it should only use most common # oxidation states of elements to make the guesses. However, it seems to be using all oxidation states. # E.g. Try the compound - KCa9V10O30, This can't be solved only with Vanadium's common oxidation state (+5) # However, this is solved by oxi_state_guesses() function, which means it's using other oxidation states as well. # Therefore, we are going to overide the elements' oxidation states with the most common oxidation states # by setting the argument oxi_states_override in oxi_state_guesses() ################################################################################################ ## create a common oxidation states dictonary to overide dic = {} for element in ElementSym('H').ox_st_dict.keys( ): # dummy element to instantiate the ElementSym class if element == 'Eu': # common and most stable ox. st. of Eu is +3, pymatgen provides both (+2 & +3). However, we select only +3 common_ox_st = (3, ) else: common_ox_st = Element(element).common_oxidation_states dic[element] = common_ox_st # return true if it could be solved using common oxi states if len(int_comp.oxi_state_guesses(oxi_states_override=dic)) > 0: return 1 else: return 0
def create_formulas(bounds, charge_balanced=True, oxi_states_extend=None, oxi_states_override=None, all_oxi_states=False, create_subsystems=False, grid=None): """ Creates a list of formulas given the bounds of a chemical space. TODO: - implement create_subsystems """ stoichs = get_stoichiometric_formulas(len(bounds), grid=grid) formulas = [] for f in stoichs: f_ = '' for i in range(len(f)): f_ += bounds[i] + f.astype(str).tolist()[i] formulas.append(f_) if charge_balanced: charge_balanced_formulas = [] if oxi_states_extend: oxi_states_override = oxi_states_override if oxi_states_override else {} for k, v in oxi_states_extend.items(): v = v if type(v) == list else [v] _states = v + list(Element[k].common_oxidation_states) if k in oxi_states_override: oxi_states_override[k] += v else: oxi_states_override[k] = _states for formula in formulas: c = Composition(formula) if c.oxi_state_guesses(oxi_states_override=oxi_states_override, all_oxi_states=all_oxi_states): charge_balanced_formulas.append(formula) return charge_balanced_formulas else: return formulas
def has_common_oxi_states( row): # this snippet is borrowed from get_novel_perovskites.py comp = Composition(row.StructuredFormula) int_comp = Composition(comp.get_integer_formula_and_factor() [0]) # get integer formular ## create a common oxidation states dictonary to overide dic = {} for element in ElementSym('H').ox_st_dict.keys( ): # dummy element to instantiate the ElementSym class if element == 'Eu': common_ox_st = (3, ) else: common_ox_st = Element(element).common_oxidation_states dic[element] = common_ox_st # return true if it could be solved using common oxi states if len(int_comp.oxi_state_guesses(oxi_states_override=dic)) > 0: return 1 else: return 0
def create_formulas(bounds, charge_balanced=True, oxi_states_extend=None, oxi_states_override=None, all_oxi_states=False, grid=None, create_subsystems=False): """ Creates a list of formulas given the bounds of a chemical space. TODO: - implement create_subsystems Args: bounds ([str]): list of elements to bound the space charge_balanced (bool): whether to balance oxidations states in the generated formulae oxi_states_extend ({}): dictionary of {element: [int]} where the value is the added oxidation state to be included oxi_states_override ({str: int}): override for oxidation states, see Composition.oxi_state_guesses all_oxi_states ({str: int): global config for oxidation states, see Composition.oxi_state_guesses grid ([]): list of integers to use for coefficients create_subsystems (bool): whether to create formulas for sub-chemical systems, e. g. for Sr-Ti-O, whether to create Ti-O and Sr-O Returns: ([str]): list of chemical formulas """ if create_subsystems: raise NotImplementedError("Create subsystems not yet implemented.") stoichs = get_stoichiometric_formulas(len(bounds), grid=grid) formulas = [] for f in stoichs: f_ = '' for i in range(len(f)): f_ += bounds[i] + f.astype(str).tolist()[i] formulas.append(f_) if charge_balanced: charge_balanced_formulas = [] if oxi_states_extend: oxi_states_override = oxi_states_override if oxi_states_override else {} for element, states in oxi_states_extend.items(): states = states if isinstance(states, list) else [states] _states = states + list(Element[element].common_oxidation_states) if element in oxi_states_override: oxi_states_override[element] += states else: oxi_states_override[element] = _states for formula in formulas: c = Composition(formula) if c.oxi_state_guesses(oxi_states_override=oxi_states_override, all_oxi_states=all_oxi_states): charge_balanced_formulas.append(formula) return charge_balanced_formulas else: return formulas
def are_soluble(self, pair): """ Predict whether a pair of compounds are soluble with one another. Args: pair_info: a tuple containing containing two compounds denoted by their filenames Returns: The pair of compounds, if they are soluble. Otherwise, Nonetype is returned. """ reference_directory = self.ref_dir cmpd_A, cmpd_B = pair[0], pair[1] struc_A = Structure.from_file('%s/%s' % (reference_directory, cmpd_A)) formula_A = struc_A.composition.reduced_formula struc_B = Structure.from_file('%s/%s' % (reference_directory, cmpd_B)) formula_B = struc_B.composition.reduced_formula if formula_A != formula_B: if self.matcher.fit(struc_A, struc_B): solubility = True comp_A = Composition(formula_A) comp_B = Composition(formula_B) probable_oxis_A = comp_A.oxi_state_guesses() probable_oxis_B = comp_B.oxi_state_guesses() if len( probable_oxis_A ) == 0: ## This occurs for metals, in which case we'll just use atomic radii oxi_dict_A = {} for elem in [str(f) for f in comp_A.elements]: oxi_dict_A[elem] = 0.0 else: ## Take most probable list of oxidation states oxi_dict_A = probable_oxis_A[0] if len(probable_oxis_B) == 0: oxi_dict_B = {} for elem in [str(f) for f in comp_B.elements]: oxi_dict_B[elem] = 0.0 else: oxi_dict_B = probable_oxis_B[0] try: struc_B = self.matcher.get_s2_like_s1(struc_A, struc_B) except ValueError: ## Sometimes order matters struc_A = self.matcher.get_s2_like_s1(struc_B, struc_A) index = 0 for (site_A, site_B) in zip(struc_A, struc_B): elem_A = ''.join([ char for char in str(site_A.species_string) if char.isalpha() ]) elem_B = ''.join([ char for char in str(site_B.species_string) if char.isalpha() ]) if solubility == True: site_A_oxi = oxi_dict_A[elem_A] site_B_oxi = oxi_dict_B[elem_B] if site_A_oxi.is_integer(): if site_A_oxi == 0: possible_rA = [ pt.Element(elem_A).atomic_radius ] else: possible_rA = [ pt.Element(elem_A).ionic_radii[site_A_oxi] ] else: possible_rA = [] possible_rA.append( pt.Element(elem_A).ionic_radii[int( np.floor(site_A_oxi))]) possible_rA.append( pt.Element(elem_A).ionic_radii[int( np.ceil(site_A_oxi))]) if site_B_oxi.is_integer(): if site_B_oxi == 0: possible_rB = [ pt.Element(elem_B).atomic_radius ] else: possible_rB = [ pt.Element(elem_B).ionic_radii[site_B_oxi] ] else: possible_rB = [] possible_rB.append( pt.Element(elem_B).ionic_radii[int( np.floor(site_B_oxi))]) possible_rB.append( pt.Element(elem_B).ionic_radii[int( np.ceil(site_B_oxi))]) possible_diffs = [] for rA in possible_rA: for rB in possible_rB: possible_diffs.append( abs(float(rA) - float(rB)) / max([float(rA), float(rB)])) if min(possible_diffs) > 0.15: solubility = False if solubility == True: return [cmpd_A, cmpd_B]