def __init__(self, elems=ATOMS, valence=False, dense=False):
        """
        elems: a list of strings with the names of the elements to be assigned an orbital vector
        """
        self.vectors = np.zeros(shape=(len(elems), 118 if not dense else 59))

        self.dictionary = {}
        for i, elem in enumerate(elems):
            self.dictionary[elem] = i
            if not valence:
                electrons = pymatgen.Element(elem).full_electronic_structure
                for level, orb, occup in electrons:
                    self._populate(
                        i, level, orb,
                        occup) if not dense else self._populate_dense(
                            i, level, orb, occup)
            else:
                tokens = pymatgen.Element(elem).electronic_structure.split(".")
                for token in tokens:
                    found = RE.findall(token)
                    if found:
                        level, orb, occup = found[0]
                        self._populate(
                            i, int(level), orb,
                            int(occup)) if not dense else self._populate_dense(
                                i, int(level), orb, int(occup))
Esempio n. 2
0
def rawdataprocessing(elementdict, featperelem, datavariables, feattotal,
                      file):
    # Read and prepare Data
    dataraw = gzip.open('data.pickle.gz')
    data = pickle.load(dataraw, encoding='latin1')
    dataraw.close()
    print("Datensatzlaenge: ", len(data), "Anzahl der Features: ",
          datavariables)
    newdata = np.zeros(
        (len(data), datavariables))  # Features(Energy + 3*Elementfeatures)
    # Generate prepared Data
    count = 0
    for i in range(len(data)):
        newdata[i, 0] = data[i, 0]
        print("Ehull", newdata[i, 0])
        for j in range(1, 3 + 1):  # elementcount
            for k in range(1, featperelem + 1):
                count += 1
                print("Count", count, "| i j k ", i, j, k)
                print("data: ", data[i, j])
                print("featcount:", k + ((j - 1) * featperelem))
                elemstr = data[i,
                               j].decode('UTF-8')  # convert b'Elem' --> Elem
                print(elementdict[mg.Element(elemstr).number])
                print("k, feat.", k,
                      elementdict[mg.Element(elemstr).number][k])
                print("-----------")
                newdata[i, (k + ((j - 1) * featperelem)
                            )] = elementdict[mg.Element(elemstr).number][k]
        print(newdata[i, :])
    np.save(open(file, 'wb'), newdata)
    # dataraw = gzip.open('dataperpared.pickle.gz', 'wb')
    # pickle.dump(x)
    return newdata
Esempio n. 3
0
def readStructures(sfile, central, ligand, radius=3.):
    """
    Read structure from file sfile and look for environments of all central
    atoms in the structure. Only neighbors of type ligand are taken into
    account.

    Returns a list of mg.Molecule in which the first atom is the central atom
    and the following atoms are the neighbors of type ligand of this central
    atom.
    """

    struct = mg.Structure.from_file(sfile)
    central_sites = [
        site for site in struct if site.specie == mg.Element(central)
    ]

    envs = list()

    print("Identified sites:")
    for site in central_sites:

        mol = mg.Molecule([site.specie], [site.coords])

        neighbors = struct.get_neighbors(site, radius)

        for neighbor, d in neighbors:
            if neighbor.specie == mg.Element(ligand):
                mol.append(neighbor.specie, neighbor.coords)

        envs.append(mol)
        print("%2s[%2d] : #ligand = %d (%s)" %
              (site.specie, struct.index(site), len(mol[1:]), " ".join(
                  [at.specie.symbol for at in mol[1:]])))

    return envs
Esempio n. 4
0
    def find_next_site_to_reduce_pop(self,list_Fe_ions):
        """
        Identify the next item to be reduced, with the rules:
            - reduce Fe-C before Fe-N
            - reduce Fe nearest Na first
        """
        N = pymatgen.Element('N')
        C = pymatgen.Element('C')

        # Are there Fe-C ions?
        sub_list_Fe_ions = []
        for ion in list_Fe_ions:
            if ion.neighbor == C:
                sub_list_Fe_ions.append(ion)

        if len(sub_list_Fe_ions) == 0:
            # there are no Fe-C ion. They must all be Fe-N
            sub_list_Fe_ions = deepcopy(list_Fe_ions)

        # Find the site with the smallest Na distance
        sub_list_Na_d = []
        for ion in sub_list_Fe_ions:
            sub_list_Na_d.append(ion.distance_to_Na)

        next_ion = sub_list_Fe_ions[ np.argmin(sub_list_Na_d) ]


        # identify index of the identified ion, and 
        # pop it out of the list
        for i, ion in enumerate(list_Fe_ions):
            if ion == next_ion:
                list_Fe_ions.pop(i)
                break

        return next_ion
Esempio n. 5
0
def getAngles(struct, sigma, npts, amin, amax, cutoff, centralAtom,
              ligandAtom):
    """ compute all angles  """

    # info
    print("\nBending angles analyses :")
    print("-------------------------")
    print("Central atom : %s" % centralAtom)
    print("Ligand atom  : %s" % ligandAtom)
    print("cutoff       : %f" % cutoff)

    # central sites
    central_sites = [
        site for site in struct if site.specie == mg.Element(centralAtom)
    ]

    # x values for histogram
    aval = np.linspace(amin, amax, npts)

    # data
    data = np.zeros(npts)

    print("\nCoordinence")
    for csite in central_sites:
        neighbors = [(site, d)
                     for site, d in struct.get_neighbors(csite, cutoff)
                     if site.specie == mg.Element(ligandAtom)]
        iat = struct.index(csite)
        print("%5s(%2d)  : %d" % (csite.specie.symbol, iat, len(neighbors)))

        #neighbors.append((distance, xij))

        # compute bending angles and build histogram
        for i in range(len(neighbors)):
            isite, di = neighbors[i]
            xic = isite.coords - csite.coords
            for j in range(i + 1, len(neighbors)):
                jsite, dj = neighbors[j]
                xjc = jsite.coords - csite.coords
                scal = np.dot(xic, xjc) / di / dj
                if np.fabs(scal) > 1.:
                    print("Dot product error : %f" % scal)
                    raise ValueError
                angle = np.degrees(np.arccos(scal))

                # add a gaussian function
                data += norm.pdf(aval, loc=angle, scale=sigma)

    # print data
    line = "# structural analysis\n"
    line += "# column 1 : angle (degree)\n"
    line += "# column 2 : histogram of angle %s-%s-%s\n" % (
        ligandAtom, centralAtom, ligandAtom)
    for a, h in zip(aval, data):
        line += "%12.4f %12.4f\n" % (a, h)

    print("\n=> Print file anaAngles.dat\n")
    open("anaAngles.dat", "w").write(line)

    return aval, data
Esempio n. 6
0
	def ox_states_from_binary_formula(self,formula,anion=None,anion_ox_state=None):
		"""
		Determine oxidation states from binary formula.
		Could also use mg.Composition.oxi_state_guesses(), but the logic used is more complex.

		Args:
			formula: chemical formula
			anion: Element symbol of anion. If None, search for common anion
			anion_ox_state: oxidation state of anion. If None, assume common oxidation state
		"""
		comp = mg.Composition(formula)
		if len(comp.elements) != 2:
			raise ValueError('Formula must be binary')
		# determine anion
		if anion is None:
			anion = np.intersect1d([e.name for e in comp.elements],self.common_anions)
			if len(anion) > 1:
				raise ValueError('Found multiple possible anions in formula. Please specify anion')
			elif len(anion)==0:
				raise ValueError('No common anions found in formula. Please specify anion')
			else:
				anion = anion[0]
		metal = np.setdiff1d(comp.elements,mg.Element(anion))[0].name
			
		#get common oxidation state for anion
		if anion_ox_state is None:
			anion_ox_state = [ox for ox in mg.Element(anion).common_oxidation_states if ox < 0]
			if len(anion_ox_state) > 1:
				raise Exception(f"Multiple common oxidation states for {anion}. Please specify anion_ox_state")
			else:
				anion_ox_state = anion_ox_state[0]
				
		metal_ox_state = -comp.get(anion)*anion_ox_state/comp.get(metal)
		
		return {metal:metal_ox_state,anion:anion_ox_state}
Esempio n. 7
0
def bond_IC(a, b):
    """
	ionic character of bond between elemenets a and b based on Pauling electronegativities
	"""
    a_ = mg.Element(a)
    b_ = mg.Element(b)
    return 1 - np.exp(-0.25 * (a_.X - b_.X)**2)
Esempio n. 8
0
    def create_pure_structure(self,
                              oxidation_states,
                              basic_atoms,
                              noCells,
                              lattice_system='cubic',
                              lattice_lengths=None,
                              lattice_angles=None,
                              supercell=False):
        """Creates pure structure given input parameters.

        """

        oxidationA = oxidation_states[0]
        oxidationB = oxidation_states[1]
        oxidationC = oxidation_states[2]

        dopantAtoms = []
        noDopants = []
        noVacancies = []
        noInterstitials = []
        vacancyAtoms = []
        interstitialAtoms = []

        siteA = basic_atoms[0]
        siteB = basic_atoms[1]
        siteC = basic_atoms[2]

        atomA = mg.Element(siteA)
        atomB = mg.Element(siteB)
        atomC = mg.Element(siteC)

        if not lattice_lengths:
            ionic_radiiA = atomA.ionic_radii[oxidationA]
            ionic_radiiB = atomB.ionic_radii[oxidationB]
            ionic_radiiC = atomC.ionic_radii[oxidationC]
            latticeVal1 = 2 * (ionic_radiiA + ionic_radiiB) / math.pow(
                3, 1 / 2)
            latticeVal2 = 2 * (ionic_radiiA + ionic_radiiC) / math.pow(
                2, 1 / 2)
            latticeConst = max(latticeVal1, latticeVal2)
            latticeLength = [latticeConst, latticeConst, latticeConst]
            latticeAngles = [90, 90, 90]  # WARNING: HARD-CODE ALERT
        else:
            latticeLength = lattice_lengths
            latticeAngles = lattice_angles

        lattice = mg.Lattice.from_lengths_and_angles(latticeLength,
                                                     latticeAngles)
        structure = mg.Structure(lattice, [siteA, siteB, siteC, siteC, siteC],
                                 [[0, 0, 0], [0.5, 0.5, 0.5], [0.5, 0.5, 0],
                                  [0.5, 0, 0.5], [0, 0.5, 0.5]])
        if supercell:
            structure.make_supercell(noCells)

        keyVal = self.structureKey(lattice_system, basic_atoms, dopantAtoms,
                                   noDopants, vacancyAtoms, noVacancies,
                                   noCells, interstitialAtoms, noInterstitials)

        return structure, keyVal
 def _define_elements_(self, elements):
     if len(elements) == 1:
         self.elements = [mg.Element(elements[0])]
     else:
         elements_list = [mg.Element(elements[0])]
         for i in range(1,len(elements)):
             elements_list += mg.Element(elements[i])
         self.elements = elements_list
Esempio n. 10
0
 def _define_elements_(self, elements):
     if type(elements) == str:
         elements_list = [mg.Element(elements)]
     else:
         elements_list = [mg.Element(elements[0])]
         for i in range(1, len(elements)):
             elements_list += mg.Element(elements[i])
     return elements_list
Esempio n. 11
0
    def siteavg_mg_prop(self, property_name):
        '''
		general function for averaging properties in mg.Element data dict across A and B sites
		'''
        p_a = np.sum([
            self.norm_cat_wts[m] * mg.Element(m).data[property_name]
            for m in self.A_site
        ])
        p_b = np.sum([
            self.norm_cat_wts[m] * mg.Element(m).data[property_name]
            for m in self.B_site
        ])
        p_tot = (p_a * self.A_sum + p_b * self.B_sum) / (self.A_sum +
                                                         self.B_sum)
        return p_a, p_b, p_tot
def elemental_descriptor(A1_ion, A2_ion, B_ion):
    """Extract elemental descriptors according to the atomic properties of A1_ion, A2_ion and B_ion in the perovskite structure.
    Args:
       A1_ion (str): element at A1_ion site, e.g., "La"
       A2_ion (str): element at A2_ion site, e.g., "Ba" 
       B_ion (str): element at B_ion site, e.g., "Co" 
    Returns:
       array: compositional descriptors, including common oxidation state of A, common oxidation state of B, Pauling electronegativity of A, Pauling electronegativity B, Tolerance factor, Octahedral factor, ionic ration of A/O, ionic ration of B/O, electronegativity difference of A/O, electronegativity difference of B/O.
    """
    ele_A1 = mg.Element(A1_ion)
    ele_A2 = mg.Element(A2_ion)
    ele_B = mg.Element(B_ion)
    ele_O = mg.Element('O')
    # A/B ion oxidation state
    common_oxidation_states_A1 = ele_A1.common_oxidation_states[0]
    common_oxidation_states_A2 = ele_A2.common_oxidation_states[0]
    common_oxidation_states_A = np.mean(common_oxidation_states_A1 +
                                        common_oxidation_states_A2)
    common_oxidation_states_B = ele_B.common_oxidation_states[0]
    # ionic radius property
    ionic_radius_A1 = float(str(ele_A1.average_ionic_radius)[:-4])
    ionic_radius_A2 = float(str(ele_A2.average_ionic_radius)[:-4])
    ionic_radius_A = (ionic_radius_A1 + ionic_radius_A2) / 2
    ionic_radius_B = float(str(ele_B.average_ionic_radius)[:-4])
    ionic_radius_O = float(str(ele_O.average_ionic_radius)[:-4])
    # Tolerance factor
    TF = (ionic_radius_A +
          ionic_radius_O) / (np.sqrt(2) * (ionic_radius_B + ionic_radius_O))
    # Octahedral factor
    OF = ionic_radius_B / ionic_radius_O
    # ionic_radius ratios
    ionic_ration_AO = ionic_radius_A / ionic_radius_O
    ionic_ration_BO = ionic_radius_B / ionic_radius_O
    # averaged electronegativity for A and B atoms
    Pauling_electronegativity_A1 = ele_A1.X
    Pauling_electronegativity_A2 = ele_A2.X
    Pauling_electronegativity_A = (Pauling_electronegativity_A1 +
                                   Pauling_electronegativity_A2) / 2
    Pauling_electronegativity_B = ele_B.X
    Pauling_electronegativity_O = ele_O.X
    # Difference in the electronegativity for A-O and B-O
    Diff_A_O = Pauling_electronegativity_A - Pauling_electronegativity_O
    Diff_B_O = Pauling_electronegativity_B - Pauling_electronegativity_O
    return [
        common_oxidation_states_A, common_oxidation_states_B,
        Pauling_electronegativity_A, Pauling_electronegativity_B, TF, OF,
        ionic_ration_AO, ionic_ration_BO, Diff_A_O, Diff_B_O
    ]
def AtomTypeCount(
    unit_cell_formula
):  #this does not do a good job of uniquely identifying all elements
    #in fact, this variable distinction al
    finalVol = 0
    elementTypeArray = np.zeros(8)
    for elem in unit_cell_formula:
        el = mg.Element(elem)
        if (el.is_alkaline):
            elementTypeArray[7] += 1
            # all compounds will have lithium...so no
        if (el.is_halogen == True):
            elementTypeArray[0] += 1
        if (el.is_transition_metal):
            elementTypeArray[1] += 1
        if (el.is_actinoid):
            elementTypeArray[2] += 1
        if (el.is_chalcogen):
            elementTypeArray[3] += 1
        if (el.is_metalloid):
            elementTypeArray[4] += 1
        if (el.is_rare_earth_metal):
            elementTypeArray[5] += 1
        else:
            elementTypeArray[6] += 1
    return elementTypeArray
Esempio n. 14
0
    def main(self):
        with open(self.filename, 'a') as fout:
            fout.write('ATOMIC_SPECIES\n')
            for ppot in self.ppots:
                element_symbol = ppot.split('.')[0]
                mass = mg.Element(element_symbol).atomic_mass
                fout.write(' {0:>2s} '.format(element_symbol))
                fout.write('  {0:8.4f}'.format(mass))
                fout.write('  {}\n'.format(ppot))
            fout.write('\n')

            fout.write('ATOMIC_POSITIONS {crystal}\n')
            for atom in self.atom_info:
                element = atom['element']
                for i in range(len(atom['wyckoff_position'])):
                    for r in atom['positions'][i]:
                        if self.is_rhombohedral:
                            pos = self.hex2trig(r)
                        else:
                            pos = r
                        fout.write(' {:>2s}'.format(element))
                        for j in range(3):
                            fout.write('  {:9.6f}'.format(float(pos[j])))
                        fout.write('\n')
            fout.write('\n')
            fout.write('K_POINTS {automatic}\n')
            for i in range(3):
                fout.write(' {}'.format(self.kpoints[i]))
            fout.write(' 0 0 0\n')
def Forces(
    sitesDat
):  #input is the sites datastructure from the structures_asdict from structures_query
    '''
    calculates an array of forces given the forces from the relaxation...sort of like a stability measures
    '''
    Fmax = 0
    Ftot = 0
    for i in range(len(sitesDat)):
        elem = sitesDat[i]
        atom = mg.Element(elem['label'])
        forces = elem['properties']['forces']
        F = 0
        #we need to calculate magnitude
        for j in range(3):
            F += forces[j]**2
        F = F**.5
        if (F > Fmax):
            Fmax = F
        Ftot += F
    data = {
        'Forces': Ftot / len(sitesDat),
        'maxForce': Fmax
    }
    return data
Esempio n. 16
0
	def ionic_formula_from_ox_state(self,metal,anion,metal_ox_state,anion_ox_state=None,return_mn=False):
		"""
		Get binary ionic compound formula with reduced integer units based on oxidation state
		
		Parameters:
		-----------
		metal: metal element symbol
		anion: anion element symbol
		metal_ox_state: metal oxidation state
		anion_ox_state: anion oxidation state. If None, will attempt to find the common oxidation state for the anion
		return_mn: if True, return formula units for metal (m) and anion (n)
		
		Returns: chemical formula string MmXn, and m, n if return_mn=True
		"""
		#get common oxidation state for anion
		if anion_ox_state is None:
			anion_ox_state = [ox for ox in mg.Element(anion).common_oxidation_states if ox < 0]
			if len(anion_ox_state) > 1:
				raise Exception(f"Multiple common oxidation states for {anion}. Please specify anion_ox_state")
			else:
				anion_ox_state = anion_ox_state[0]
				
		#formula MmXn
		deno = gcd(metal_ox_state,-anion_ox_state)
		m = -anion_ox_state/deno
		n = metal_ox_state/deno
		formula = '{}{}{}{}'.format(metal,m,anion,n)
		if return_mn==False:
			return formula
		else:
			return formula, m, n
def get_ionization_lookup(df_input):
    """Convert the input dataframe into a lookup dataframe of ionization energies"""
    # get the column names
    columns = df_input.columns
    # get the first three column names
    specie_name, ion_charge, ionization_energy = columns[:3]
    # clean up the dataframe using the two helper functions
    df_input[specie_name] = df_input[specie_name].apply(clean_specie_name)
    df_input[ionization_energy] = df_input[ionization_energy].apply(
        clean_energy_str)

    # select the first 3 columns and rename them
    df_input = df_input.iloc[:, :3].rename(columns={
        specie_name: "element",
        ion_charge: "v",
        ionization_energy: "iv_p1"
    })

    # shift the iv_p1 columns down by one row and create a new column iv from it
    df_input["iv"] = df_input["iv_p1"].shift()
    # reorder the columns
    df_input = df_input[["element", "v", "iv", "iv_p1"]]
    # get the element
    element = mg.Element(df_input["element"][0])
    # return the rows with 0 < v < max_oxidation_state
    return df_input[(df_input.v > 0)
                    & (df_input.v <= element.max_oxidation_state)]
Esempio n. 18
0
 def check_bond_length(self):
     natom = self.config_obj.natom
     check = True
     for i in range(natom):
         atom1 = self.config_obj.atom_list[i]
         for j in range(i + 1, natom):
             atom2 = self.config_obj.atom_list[j]
             sum_atomic_radius = mg.Element(atom1).atomic_radius +\
                 mg.Element(atom2).atomic_radius
             bond_length = self.config_obj.calc_length(i, j, aunit=True)
             if bond_length < sum_atomic_radius:
                 print('{0}-{1}:'.format(atom1, atom2), end='')
                 print('ideal = {0:8.5f} but real = {1:8.5f}'.format(
                     sum_atomic_radius, bond_length))
                 check = False
     return check
Esempio n. 19
0
    def ion_class(self):
        """
        Classifies an element as cation or anion

        Returns
            classed: list with anion and cations
        """
        elements = self.elements.copy()
        max_eneg = 0
        for i in range(len(elements)):
            if mg.Element(elements[i]).X > max_eneg:
                max_eneg = mg.Element(elements[i]).X
                max_i = i
        anion = elements.pop(max_i)
        cations = elements
        classed = [anion, cations]
        return classed
def unitCellMass(unit_cell_formula):
    Mass = 0
    label = 'MassUnitcell'
    for elem in unit_cell_formula:
        element = mg.Element(elem)
        masscontribution = element.data['Atomic mass'] * unit_cell_formula[elem]
        Mass += masscontribution
    return Mass
Esempio n. 21
0
def mol_Oh(central, ligand, scale):
    """ 
    Return a perfect octahedra as a mg.Molecule object.

    Args:
        central: (string) Name of the central atom
        ligand: (string) Name of ligand atoms
        scale: (float) length of central-ligand distance

    Returns
        mg.Molecule object
    """
    species = [mg.Element(central)] + 6 * [mg.Element(ligand)]
    template = [[0., 0., 0.], [1., 0., 0.], [-1., 0., 0.], [0., 1., 0.],
                [0., -1., 0.], [0., 0., 1.], [0., 0., -1.]]
    coords = [[scale * xi for xi in coord] for coord in template]
    return mg.Molecule(species, coords)
Esempio n. 22
0
    def get_ABE(self, formula, A_site, B_site, verbose=False):
        """
		Estimate average metal-oxygen bond energy for complex perovskite oxide from simple oxide thermo data
		Formula from Sammells et al. (1992), Solid State Ionics 52, 111-123.
		
		Parameters:
		-----------
		formula: oxide formula
		A_site: list of A-site elements
		B_site: list of B-site elements
		verbose: if True, print info about which simple oxides used in calculation
		"""
        #validated on compounds in Sammells 1992 - all but CaTi0.7Al0.3O3 agree
        #validated on (La,Sr)(Cr,Co,Fe)O3 compounds in https://pubs.acs.org/doi/suppl/10.1021/acs.jpcc.6b10571/suppl_file/jp6b10571_si_001.pdf
        #works if Co3O4 specified in oxide_dict
        comp = mg.Composition(formula)
        cd = comp.get_el_amt_dict()
        metals = [x for x in cd.keys() if x != 'O']
        abe = 0
        if verbose == True:
            print('Oxides used for ABE calculation:')
        for metal in metals:
            amt = cd[metal]
            met_mg = mg.Element(metal)

            try:  #oxide_dict specifies which oxide to use
                oxide = self.oxide_dict[metal]
                oxide_mg = mg.Composition(oxide)
                m = oxide_mg.get(metal)
                n = oxide_mg.get('O')
                obe = self.oxide_obe(oxide)
            except KeyError:  #if no oxide indicated in oxide_dict
                "placeholder - for now, take the lowest common oxidation state with a corresponding stable oxide"
                i = 0
                while i != -1:
                    ox = met_mg.common_oxidation_states[i]
                    oxide, m, n = self.oxide_formula(metal, ox, return_mn=True)
                    try:
                        obe = self.oxide_obe(oxide)
                        #print(obe)
                        i = -1
                    except LookupError as err:
                        i += 1  #try the next oxidation state

            if verbose == True:
                print(oxide)
            #print('m: {}, n: {}'.format(m,n))
            if metal in A_site:
                abe += amt * obe / (12 * m)
            elif metal in B_site:
                abe += amt * obe / (6 * m)
            else:
                raise KeyError(
                    '{} is not assigned to A or B site'.format(metal))
            #print(abe)

        return abe
def classify_mx_pairs(elem_pair_lst: Union[list, Iterable]):
    """
    Classify all metal-non_metal pairs into three categories.
    The following represents how relevant the category is with decreasing relevance

    1. transition metal and oxygen
    2. transition metal and non_oxygen non-metal, non-transition metal and oxygen
    3. non-transition metal and non_oxygen non-metal

    :param elem_pair_lst: List or iterables, all metal-non_metal element pairs. e.g. ["Ti-O", "Ba-O"]
    :return: Ordered Dictionary, {"trans_oxy": [list of elem pairs in string format],
                                  "one_trans_or_one_oxy": [list of elem pairs in string format],
                                  "non_trans_non_oxy": [list of elem pairs in string format]}
    """
    # parse all the element pairs from strings to tuples with two Pymatgen Elements
    elem_pairs_parsed = [
        parse_elem_pair(elem_pair) for elem_pair in elem_pair_lst
    ]

    # initialize the empty lists
    trans_oxy = []
    one_trans_or_one_oxy = []
    non_trans_non_oxy = []

    for elem_pair_str, (elem_1, elem_2) in zip(elem_pair_lst,
                                               elem_pairs_parsed):
        # if elem_1 is non_metal and elem_2 is a metal, swap the elements
        if (not elem_1.is_metal) and elem_2.is_metal:
            elem_1, elem_2 = elem_2, elem_1
        # find all pairs where the metal is a transition metal and the non-metal is oxygen
        if elem_1.is_transition_metal and (elem_2 == mg.Element("O")):
            trans_oxy.append(elem_pair_str)
        # find all pairs where one element is a transition metal or one element is oxygen
        elif elem_1.is_transition_metal or (elem_2 == mg.Element("O")):
            one_trans_or_one_oxy.append(elem_pair_str)
        # find all pairs where the metal is non-transition metal and the non-metal is not oxygen
        else:
            non_trans_non_oxy.append(elem_pair_str)

    return OrderedDict({
        "trans_oxy": trans_oxy,
        "one_trans_or_one_oxy": one_trans_or_one_oxy,
        "non_trans_non_oxy": non_trans_non_oxy
    })
Esempio n. 24
0
def generateElementdict():
    # Dictionary with Elements and their properties
    # Delete preprocessed data when changing featperEle
    elementdict = {}
    for i in range(1, 100):  # 100 Elements in Dict
        commonoxidationstate = peri.Element.from_Z(i).common_oxidation_states
        orbitals = peri.Element.from_Z(i).full_electronic_structure
        sandp_count = 0
        dandf_count = 0
        ionizationenergy = 0
        valence = 0

        if len(commonoxidationstate) == 0:
            commonoxidationstate = 0
        else:
            commonoxidationstate = peri.Element.from_Z(
                i).common_oxidation_states[0]

        for j in range(len(orbitals)):
            for k in range(len(orbitals[j])):
                if orbitals[j][k] == "s" or orbitals[j][k] == "p":
                    sandp_count += orbitals[j][2]  # count in third position
                if orbitals[j][k] == "d" or orbitals[j][k] == "f":
                    dandf_count += orbitals[j][2]

        if i == 1:
            ionizationenergy = 13.6
        else:
            ionizationenergy = ((i - 1) ^ 2) * 13.6

        """
        if i == 4 or i == 12 or i == 20:
            valence = 2
            print("alkaine earth set to 2 valence e-")
        else: 
            valence = peri.Element.from_Z(i).valence
            print("Element: ", i, "Valence: ", valence, type(valence))
        """  # transition metals not working

        elementdict[i] = [
            peri.Element.from_Z(i),  # name
            peri.Element.from_Z(i).number,  # atomic number
            mg.Element(peri.Element.from_Z(i)).group,  # group
            peri.Element(peri.Element.from_Z(i)).row  # row
            #   peri.Element.from_Z(i).X,  # Pauling electronegativity (none equals zero)
            #   peri.Element.from_Z(i).number,  # atomic number
            #   commonoxidationstate,  # common oxidation state if non set to zero
            #   peri.Element.from_Z(i).average_ionic_radius,  # average ionic radius
            #   mg.Element(peri.Element.from_Z(i)).atomic_mass,  # avarage mass
            #   sandp_count,  # count of e- in s and p orbitals
            #   dandf_count,  # couunt of e- in d and f orbitals
            #   ionizationenergy,  # ionizationenergy in eV
        ]
        # peri.Element.from_Z(i).valence]  # number of valence electrons
    # print("Element and feat.:", elementdict)
    return elementdict
Esempio n. 25
0
def IonRadVsLattice(
    picklestruct, ion
):  #attempts to account for how rectangular the cell is by taking the smallest
    #unit cell length, and seeing how much larger or smaller than it is compared to the lithium atom volume
    initialvol = picklestruct.volume
    unitcelllengths = picklestruct.lattice.abc  #we sould not scal ehere as we are comparing lattice to lithium ion radius, which is fixed
    minlength = np.min(unitcelllengths)
    Lirad = mg.Element(ion).average_ionic_radius
    diff = minlength / Lirad
    return diff / initialvol**(1 / 3)
def atomicNumber(
        unit_cell_formula):  #remember, mean, mode, std, weighted mean,
    data = list()
    for elem in unit_cell_formula:
        element = mg.Element(elem)
        atmNumber = element.data['Atomic no']
        for i in range(int(unit_cell_formula[elem])):
            data.append(atmNumber)
    answer = [np.mean(data), np.std(data)]
    return answer
Esempio n. 27
0
def mol_D4h(central, ligand, d1, d2):
    """ 
    Return a D4h molecule as a mg.Molecule object.

    Args:
        central: (string) Name of the central atom
        ligand: (string) Name of ligand atoms
        d1: (float) length of central-ligand axial distance
        d2: (float) length of central-ligand equatorial distance

    Returns
        mg.Molecule object
    """
    species = [mg.Element(central)] + 6 * [mg.Element(ligand)]
    template = [[0., 0., 0.], [1., 0., 0.], [-1., 0., 0.], [0., 1., 0.],
                [0., -1., 0.], [0., 0., 1.], [0., 0., -1.]]
    coords = [template[0]] \
           + [[d1 * xi for xi in coord] for coord in template[1:5]] \
           + [[d2 * xi for xi in coord] for coord in template[5:]]
    return mg.Molecule(species, coords)
def classify_xx_pairs(elem_pair_lst: Union[list, Iterable]):
    """
    Classify all non_metal-non_metal pairs into three categories.
    The following represents how relevant the category is with decreasing relevance

    1. oxygen and oxygen
    2. oxygen and non_oxygen non_metal
    3. non_oxygen non_metal and non_oxygen non_metal

    :param elem_pair_lst: List or iterables, all non_metal-non_metal element pairs. e.g. ["Ti-Ti", "Ba-Ba"]
    :return: Ordered Dictionary, {"oxy_oxy": [list of elem pairs in string format],
                                  "oxy_non_oxy": [list of elem pairs in string format],
                                  "non_oxy_non_oxy": [list of elem pairs in string format]}
    """
    # parse all the element pairs from strings to tuples with two Pymatgen Elements
    elem_pairs_parsed = [
        parse_elem_pair(elem_pair) for elem_pair in elem_pair_lst
    ]

    # initialize the empty lists
    oxy_oxy = []
    oxy_non_oxy = []
    non_oxy_non_oxy = []

    for elem_pair_str, (elem_1, elem_2) in zip(elem_pair_lst,
                                               elem_pairs_parsed):
        # find all pairs where both non_metals are oxygen
        if (elem_1 == mg.Element("O")) and (elem_2 == mg.Element("O")):
            oxy_oxy.append(elem_pair_str)
        # find all pairs where one of the two non_metals is an oxygen
        elif (elem_1 == mg.Element("O")) or (elem_2 == mg.Element("O")):
            oxy_non_oxy.append(elem_pair_str)
        # find all pairs where none of the two non_metals is an oxygen
        else:
            non_oxy_non_oxy.append(elem_pair_str)

    return OrderedDict({
        "oxy_oxy": oxy_oxy,
        "oxy_non_oxy": oxy_non_oxy,
        "non_oxy_non_oxy": non_oxy_non_oxy
    })
def return_relevant_potentials(structure_oxid: mg.Structure, **kwargs):
    """
    Return the relevant potentials for the metal site and non_metal site with the following relevance order

    1. transition metal and oxygen
    2. transition metal and non-oxygen
    3. non-transition metal and oxygen
    4. non-transition metal and non-oxygen

    :param structure_oxid: Pymatgen Structure, the input structure
    :return: Tuple, the maximum potentials (unit: V) for the metal site and non-metal site
    """
    # get the maximum potentials for all the elements in the structure
    max_potentials = calc_elem_max_potential(structure_oxid, **kwargs)
    # get the classification of each element into metal and non_metals
    _, elem_group, _ = get_elem_info(structure_oxid, makesupercell=False)
    # get all the metals
    all_metals = elem_group["all_metals"]
    # if there are metals, find the transition metals
    if all_metals:
        trans_metals = [
            metal for metal in all_metals if metal.is_transition_metal
        ]
    else:
        trans_metals = []
    # find all the non_metals
    non_metals = elem_group["non_metals"]

    # find the corresponding potentials in each group except oxygen
    all_metals_max = choose_most_elec_neg_potential(all_metals, max_potentials)
    trans_metals_max = choose_most_elec_neg_potential(trans_metals,
                                                      max_potentials)
    non_metals_max = choose_most_elec_neg_potential(non_metals, max_potentials)

    # if there is oxygen, find the corresponding potential
    try:
        oxygen_max = max_potentials[mg.Element("O")]
    except KeyError:
        oxygen_max = None

    # return potential tuples based on the hierarchy
    # if transition metal and oxygen both exist, return their potentials
    if trans_metals_max and oxygen_max:
        return trans_metals_max, oxygen_max
    # if only transition metal exists, return the transition metal and non_oxygen non_metal potentials
    elif trans_metals_max and (not oxygen_max):
        return trans_metals_max, non_metals_max
    # if only oxygen exists, return the non_transition metal and oxygen potentials
    elif (not trans_metals_max) and oxygen_max:
        return all_metals_max, oxygen_max
    # if neither transition metal nor oxygen exists, return the non_transition metal and non_oxygen potentials
    else:
        return all_metals_max, non_metals_max
Esempio n. 30
0
    def _closest_CN(self, el, ox, target):
        '''
		get closest coordination number (in roman numerals) to target
		convenience function for choosing appropriate Shannon radius - used in ox_combos
		'''
        cn_rom = mg.Element(el).data['Shannon radii']['{}'.format(ox)].keys()
        cn_rom = [rn for rn in cn_rom if rn in self._rom_to_num.keys()
                  ]  #remove any roman numerals not in dict (eg "IVSQ")
        cn = [self._rom_to_num[rn] for rn in cn_rom]
        idx = np.argmin(np.abs(np.array(cn) - target))
        rom = self._num_to_rom[cn[idx]]
        return rom