Example #1
0
    def check_polar(self):
        """
        Check if the surface structure is polar.

        Comparing atom types at top and bottom.
        Applicable for sufcae with vaccums only.

        Args:

             file:atoms object (surface with vacuum)

        Returns:
               polar:True/False
        """
        up = 0
        dn = 0
        coords = np.array(self.frac_coords)
        z_max = max(coords[:, 2])
        z_min = min(coords[:, 2])
        for site, element in zip(self.frac_coords, self.elements):
            if site[2] == z_max:
                up = up + Specie(element).Z
            if site[2] == z_min:
                dn = dn + Specie(element).Z
        polar = False
        if up != dn:
            print("Seems like a polar materials.")
            polar = True
        if up == dn:
            print("Non-polar")
            polar = False
        return polar
Example #2
0
def coulomb_matrix(atoms="", max_dim=100):
    """Convert Atoms class to max_dim x max_dim matrix.

    Args:

        atoms: atoms object

        max_dim: maximum number of atoms=sqrt(max_dim)

    Returns:
          z: numpy array of 1 x max_dim dimension
    """
    natoms = atoms.num_atoms
    mat = np.zeros((natoms, natoms))

    for ii, i in enumerate(atoms.elements):
        for jj, j in enumerate(atoms.elements):
            if ii == jj:
                mat[ii, jj] = 0.5 * Specie(i).Z**2.4
            else:
                a = atoms.cart_coords[ii]
                b = atoms.cart_coords[jj]
                dist = np.linalg.norm(a - b)
                mat[ii, jj] = (Specie(i).Z * Specie(j).Z) / dist
    tmp = mat.ravel()
    if max_dim < len(tmp):
        print("WARNING: Increase max_dim")
    padding = max_dim - len(tmp)
    z = np.pad(tmp, (0, padding), "constant")
    return z
Example #3
0
 def atomic_fraction_array(self):
     """Get atomic fraction array."""
     nelements = len(list(Specie()._data.keys()))
     frac_arr = np.zeros(nelements)
     fracs = self.atomic_fraction
     for i, j in fracs.items():
         frac_arr[int(Specie(i).Z) - 1] = j
     return frac_arr
Example #4
0
def find_ldau_magmom(
    atoms="",
    default_magmom=True,
    U=3.0,
    mag=5.0,
    amix=0.2,
    bmix=0.00001,
    amixmag=0.8,
    bmixmag=0.00001,
    lsorbit=False,
):
    """Get necessary INCAR tags for DFT+U calculations."""
    sps = atoms.uniq_species
    LDAUL = []
    LDAUU = []
    LDAUTYPE = 2
    lmix = 4
    for i in sps:
        el = Specie(i)
        el_u = 0
        el_l = -1
        if el.element_property("is_transition_metal"):
            el_u = U
            el_l = 2
        if el.element_property("is_actinoid") or el.element_property(
                "is_lanthanoid"):
            el_u = U
            el_l = 3
            lmix = 6
        LDAUL.append(el_l)
        LDAUU.append(el_u)
    if 3 in LDAUL:
        LDAUTYPE = 3
    nat = atoms.num_atoms
    magmom = str(nat) + str("*") + str(mag)
    if lsorbit:
        magmom = ""
        tmp = " 0 0 " + str(mag)
        for i in range(0, nat):
            magmom = magmom + tmp
    info = {}
    info["LDAU"] = ".TRUE."
    info["LDAUTYPE"] = LDAUTYPE
    info["LDAUL"] = " ".join(str(m) for m in LDAUL)
    info["LDAUU"] = " ".join(str(m) for m in LDAUU)
    info["LDAUPRINT"] = 2
    info["LMAMIX"] = lmix
    if not default_magmom:
        info["MAGMOM"] = magmom
    info["AMIX"] = amix
    info["BMIX"] = bmix
    info["AMIX_MAG"] = amixmag
    info["BMIX_MAG"] = bmixmag
    return info
Example #5
0
 def atomic_species_string(self):
     """Obtain string for QE atomic species."""
     line = ""
     for i in self.species:
         line = line + (i + " " + str(round(Specie(i).atomic_mass, 2)) +
                        " " + str(self.get_psp(i)) + "\n")
     return line
Example #6
0
 def packing_fraction(self):
     """Get packing fraction of the atoms object."""
     total_rad = 0
     for i in self.elements:
         total_rad = total_rad + Specie(i).atomic_rad**3
     pf = np.array([4 * np.pi * total_rad / (3 * self.volume)])
     return round(pf[0], 5)
Example #7
0
def test_sp():
    el = Specie("Al")
    assert (
        el.Z,
        round(el.atomic_mass, 2),
        el.symbol,
        round(el.get_chgdescrp_arr[1], 2),
        round(el.get_descrp_arr[1], 2),
    ) == (13, 26.98, "Al", 12.17, 2792.11)
Example #8
0
 def get_center_of_mass(self):
     """Get center of mass of the atoms object."""
     # atomic_mass
     m = []
     for i in self.elements:
         m.append(Specie(i).atomic_mass)
     m = np.array(m)
     com = np.dot(m, self.cart_coords) / m.sum()
     # com = np.linalg.solve(self.lattice_mat.T, com)
     return com
Example #9
0
def write_prismatic_xyz(atoms=None):
    """Write Atoms in prismatic format."""
    from jarvis.core.specie import Specie

    line = str(atoms.num_atoms) + "\n"
    abc = atoms.lattice.abc
    line += str(abc[0]) + " " + str(abc[1]) + " " + str(abc[2]) + "\n"
    for i, j in zip(atoms.elements, atoms.cart_coords):
        line += (str(Specie(i).Z) + " " + str(j[0]) + " " + str(j[1]) + " " +
                 str(j[2]) + str("  1 .076\n"))
    line += "-1\n"
    return line
Example #10
0
def test_sp():
    el = Specie("Al")
    assert (
        el.Z,
        round(el.atomic_mass, 2),
        el.symbol,
        round(el.get_chgdescrp_arr[1], 2),
        round(el.get_descrp_arr[1], 2),
    ) == (13, 26.98, "Al", 12.17, 2792.11)
    dat = get_feats_hot_encoded()
    fat = get_digitized_feats_hot_encoded()
    x, y, z = get_specie_data()
Example #11
0
    def reduced_formula(self):
        """Get reduced formula."""
        form = ""
        reduced, repeat = self.reduce()
        X = {}
        for i, j in reduced.items():
            X[i] = Specie(i).X
        Y = dict(sorted(X.items(), key=lambda item: item[1]))
        Z = {}
        for i, j in Y.items():
            Z[i] = reduced[i]
        for specie, count in Z.items():
            if float(count).is_integer():
                form = form + specie + str(int(count))
            else:
                form = form + specie + str(count)

        return form.replace("1", "")
Example #12
0
 def refined_atoms(self):
     """Refine atoms based on spacegroup data."""
     phonopy_atoms = (
         self._atoms.lattice_mat,
         self._atoms.frac_coords,
         self._atoms.atomic_numbers,
     )
     lattice, scaled_positions, numbers = spglib.refine_cell(
         phonopy_atoms, self._symprec, self._angle_tolerance)
     elements = self._atoms.elements
     el_dict = {}
     for i in elements:
         el_dict.setdefault(Specie(i).Z, i)
     ref_elements = [el_dict[i] for i in numbers]
     ref_atoms = Atoms(
         lattice_mat=lattice,
         elements=ref_elements,
         coords=scaled_positions,
         cartesian=False,
     )
     return ref_atoms
Example #13
0
 def primitive_atoms(self):
     """Get primitive atoms."""
     phonopy_atoms = (
         self._atoms.lattice_mat,
         self._atoms.frac_coords,
         self._atoms.atomic_numbers,
     )
     lattice, scaled_positions, numbers = spglib.find_primitive(
         phonopy_atoms, symprec=self._symprec)
     elements = self._atoms.elements
     el_dict = {}
     for i in elements:
         el_dict.setdefault(Specie(i).Z, i)
     prim_elements = [el_dict[i] for i in numbers]
     prim_atoms = Atoms(
         lattice_mat=lattice,
         elements=prim_elements,
         coords=scaled_positions,
         cartesian=False,
     )
     return prim_atoms
Example #14
0
    def read_data(
        self,
        filename="lammps.data",
        element_order=[],
        potential_file="pot.mod",
        verbose=True,
    ):
        """Read Lammps data file."""
        # n_atoms = len(self._species)
        if element_order == []:
            # Reading potential file for element order
            if verbose:
                print("element_order is empty, reading from", potential_file)
            pot_file = open(potential_file, "r")
            lines = pot_file.read().splitlines()
            pot_file.close()
            symb = []
            # count = 0

            for i, line in enumerate(lines):
                if "pair_coeff" in line.split():
                    sp = line.split()
                    # print("spsplit", sp, os.getcwd())
                    for el in sp:
                        try:
                            if str(Specie(el).Z) != "nan":
                                # if el=='M':
                                #    el='Mo'
                                # count=count+1
                                # if count >4:
                                symb.append(Specie(el).symbol)
                        except Exception:
                            pass
        else:
            symb = [Specie(i).symbol for i in element_order]

        # print("symb=", symb)
        f = open(filename, "r")
        lines = f.read().splitlines()
        for i, line in enumerate(lines):
            if "atoms" in line.split():
                natoms = int(line.split()[0])
            if "types" in line.split():
                # print(line)
                ntypes = int(line.split()[0])
            if "xlo" in line.split():
                xlo = float(line.split()[0])
                xhi = float(line.split()[1])
            if "ylo" in line.split():
                ylo = float(line.split()[0])
                yhi = float(line.split()[1])
            if "zlo" in line.split():
                zlo = float(line.split()[0])
                zhi = float(line.split()[1])
            if "xy" in line.split():
                xy = float(line.split()[0])
                xz = float(line.split()[1])
                yz = float(line.split()[2])
        if len(symb) != ntypes:
            ValueError("Something wrong in atom type assignment", len(symb),
                       ntypes)
        lat = np.array([[xhi - xlo, 0.0, 0.0], [xy, yhi - ylo, 0.0],
                        [xz, yz, zhi - zlo]])
        typ = np.empty((natoms), dtype="S20")
        x = np.zeros((natoms))
        y = np.zeros((natoms))
        z = np.zeros((natoms))
        q = np.zeros((natoms))
        coords = list()
        for i, line in enumerate(lines):
            if "Atoms" in line.split():
                for j in range(0, natoms):
                    # print int(((lines[j+2]).split()[1]))-1
                    typ[j] = symb[int(((lines[i + j + 2]).split()[1])) - 1]
                    q[j] = (lines[i + j + 2]).split()[2]
                    x[j] = (lines[i + j + 2]).split()[3]
                    y[j] = (lines[i + j + 2]).split()[4]
                    z[j] = (lines[i + j + 2]).split()[5]
                    coords.append([x[j], y[j], z[j]])
        f.close()
        # print ("info",(typ),'coo',(coords),'latt',lat)
        typ_sp = [str(i, "utf-8") for i in typ]
        # print ('typ_sp',typ_sp)
        atoms = Atoms(
            lattice_mat=lat,
            elements=typ_sp,
            coords=np.array(coords),
            cartesian=True,
        )
        return atoms
Example #15
0
    def write_lammps_in(
        self,
        lammps_in="init.mod",
        lammps_in1="potential.mod",
        lammps_in2="in.main",
        lammps_trj=None,
        lammps_data=None,
        parameters={},
    ):
        """
        Write lammps input file.

        From ase with custom modifications
        LAMMPS input is devided into three parts

        Args:
            lammps_in: generally"init.mod",
            with unit and conversion factor information

            lammps_in1: generally "potential.mod",
            with force-field/potential style and
            element type information

            lammps_in2: generally "in.elastic",
            a generic main input file to be fed
            in LAMMPS usin lmp_*<...,parameters['exec']

            parameters: input parameters

        """
        f = open(lammps_in, "w")
        f1 = open(lammps_in1, "w")  # potential.mod
        f2 = open(lammps_in2, "w")
        f.write(('variable dump_file string "%s"\n' % lammps_trj) +
                ("variable up  equal 1.0e-6\n") +
                ("variable cfac  equal 1.0e-4\n") +
                ("variable cunits  string GPa\n") +
                ("variable etol  equal 0\n") +
                ("variable ftol  equal 1.0e-10\n") +
                ("variable maxiter equal 1000\n") +
                ("variable maxeval equal 10000\n") +
                ("variable dmax equal 1.0e-2\n") +
                ('variable data_file string "%s"\n' % "data"))
        if "control_file" in parameters:
            f2.write("include %s \n" % parameters["control_file"])
        if "units" in parameters:
            f.write("units %s \n" % parameters["units"])
        else:
            f.write("units metal \n")
        if "atom_style" in parameters:
            f.write("atom_style %s \n" % parameters["atom_style"])
        else:
            f.write("atom_style atomic \n")
        if "boundary" in parameters:
            f.write("boundary %s \n" % parameters["boundary"])
        else:
            pbc = self.pbc
            f.write("boundary %s %s %s \n" % (pbc[0], pbc[1], pbc[2]))
        f.write("atom_modify sort 0 0.0 \n")
        for key in ("neighbor", "newton"):
            if key in parameters:
                f.write("%s %s \n" % (key, parameters[key]))
        f.write("\n")
        f.write("read_data %s\n" % "data")
        f.write("\n### interactions \n")
        if "lib" in parameters:
            lib = parameters["lib"]
            f1.write("%s \n" % lib)
        if ("pair_style" in parameters) and ("pair_coeff" in parameters):
            pair_style = parameters["pair_style"]
            f1.write("pair_style %s \n" % pair_style)
            symbols = self.LammpsDataObj._element_order
            tag = ""
            for i in symbols:
                tag = tag + " " + i
            pair_coef = "* * " + str(parameters["pair_coeff"]) + " " + tag
            f1.write("pair_coeff %s \n" % pair_coef)

            masses = []
            for i in symbols:
                m = Specie(i).atomic_mass
                if m not in masses:
                    masses.append(m)
            count = 0
            for i in masses:
                count = count + 1
                f.write("mass" + " " + str(count) + " " + str(i) + "\n")

        else:

            # default interaction
            f.write("pair_style lj/cut 2.5 \n" + "pair_coeff * * 1 1 \n" +
                    "mass * 1.0 \n")
        f1.write("neighbor 1.0 nsq\n")
        f1.write("neigh_modify once no every 1 delay 0 check yes\n")
        if "min" not in parameters:
            f1.write("min_style  cg\n")
            f1.write("min_modify           dmax ${dmax} line quadratic\n")
        f1.write("thermo          1\n")
        f1.write("thermo_style custom step temp press cpu pxx pyy pzz\
             pxy pxz pyz ke pe etotal vol lx ly lz atoms\n")
        f1.write("thermo_modify norm no\n")
        if "fix" in parameters:
            if parameters["fix"]:
                for i in parameters["fix"]:
                    f1.write("fix %s\n" % i)
        f.close()
        f1.close()
        f2.close()
Example #16
0
    def get_string(self, cart=True, sort_order="X"):
        """
        Convert Atoms to string.

        Optional arguments below.

        Args:
          cart:True/False for cartesian/fractional coords.

          sort_order: sort by chemical properties of
                    elements. Default electronegativity.
        """
        system = str(self.composition.formula)
        header = (str(system) + str("\n1.0\n") + str(self.lattice_mat[0][0]) +
                  " " + str(self.lattice_mat[0][1]) + " " +
                  str(self.lattice_mat[0][2]) + "\n" +
                  str(self.lattice_mat[1][0]) + " " +
                  str(self.lattice_mat[1][1]) + " " +
                  str(self.lattice_mat[1][2]) + "\n" +
                  str(self.lattice_mat[2][0]) + " " +
                  str(self.lattice_mat[2][1]) + " " +
                  str(self.lattice_mat[2][2]) + "\n")
        if sort_order is None:
            order = np.argsort(self.elements)
        else:
            order = np.argsort([
                Specie(i).element_property(sort_order) for i in self.elements
            ])
        if cart:
            coords = self.cart_coords
        else:
            coords = self.frac_coords
        coords_ordered = np.array(coords)[order]
        elements_ordered = np.array(self.elements)[order]
        props_ordered = np.array(self.props)[order]
        # check_selective_dynamics = False # TODO
        counts = get_counts(elements_ordered)
        cart_frac = ""
        if cart:
            cart_frac = "\nCartesian\n"
        else:
            cart_frac = "\nDirect\n"

        if "T" in "".join(map(str, self.props[0])):
            middle = (" ".join(map(str, counts.keys())) + "\n" +
                      " ".join(map(str, counts.values())) +
                      "\nSelective dynamics\n" + cart_frac)
        else:
            middle = (" ".join(map(str, counts.keys())) + "\n" +
                      " ".join(map(str, counts.values())) + cart_frac)
        rest = ""

        for ii, i in enumerate(coords_ordered):
            if self.show_props:
                rest = (rest + " ".join(map(str, i)) + " " +
                        str(props_ordered[ii]) + "\n")
            else:
                rest = rest + " ".join(map(str, i)) + "\n"

        result = header + middle + rest
        return result
Example #17
0
 def dfpt_data(self, fc_mass=True):
     """Get DFPT IBRION=8 related data."""
     info = {}
     hessian = []
     data = self._data
     for i in (data["modeling"]["calculation"]["dynmat"]["varray"])[0]["v"]:
         hessian.append(i.split())
     hessian = np.array(hessian, dtype="double")
     struct = self.all_structures[-1]
     natoms = struct.num_atoms
     force_constants = np.zeros((natoms, natoms, 3, 3), dtype="double")
     for i in range(natoms):
         for j in range(natoms):
             force_constants[i, j] = hessian[
                 i * 3 : (i + 1) * 3, j * 3 : (j + 1) * 3
             ]
     masses = [Specie(i).atomic_mass for i in struct.elements]
     if fc_mass:
         for i in range(natoms):
             for j in range(natoms):
                 force_constants[i, j] *= -np.sqrt(masses[i] * masses[j])
     born_charges = []
     for n in range(natoms):
         born_charges.append(
             [
                 i.split()
                 for i in (data["modeling"]["calculation"]["array"]["set"])[
                     n
                 ]["v"]
             ]
         )
     born_charges = np.array(born_charges, dtype="double")
     phonon_eigenvals = np.array(
         data["modeling"]["calculation"]["dynmat"]["v"]["#text"].split(),
         dtype="double",
     )
     eigvecs = np.array(
         [
             i.split()
             for i in (
                 data["modeling"]["calculation"]["dynmat"]["varray"][1]["v"]
             )
         ],
         dtype="float",
     )
     phonon_eigenvectors = []
     for ev in eigvecs:
         phonon_eigenvectors.append(np.array(ev).reshape(natoms, 3))
     phonon_eigenvectors = np.array(phonon_eigenvectors, dtype="float")
     epsilon = {}
     for i in data["modeling"]["calculation"]["varray"]:
         if "epsilon" in i["@name"]:
             epsilon[i["@name"]] = np.array(
                 [j.split() for j in i["v"]], dtype="float"
             )
     info["born_charges"] = born_charges
     info["phonon_eigenvectors"] = phonon_eigenvectors
     info["epsilon"] = epsilon
     info["phonon_eigenvalues"] = phonon_eigenvals
     info["masses"] = masses
     return info
Example #18
0
 def atomic_numbers(self):
     """Get list of atomic numbers of atoms in the atoms object."""
     numbers = []
     for i in self.elements:
         numbers.append(Specie(i).Z)
     return numbers
Example #19
0
    def simulate(self, atoms=None):
        """
        Simulate XRD pattern.

        Forked from https://github.com/qzhu2017/XRD.
        """
        # atoms=Spacegroup3D(atoms).conventional_standard_structure
        rec_matrix = atoms.lattice.reciprocal_lattice_crystallographic().matrix

        min_r = self.wavelength / np.sin(self.max2theta / 2) / 2
        r1 = list(range(1, self.max_index + 1))
        r2 = list(range(-self.max_index, 1))
        r2.reverse()
        r3 = r1 + r2
        r = r3
        hkl_index = [
            miller for miller in itertools.product(r, r, r)
            if any([i != 0 for i in miller])
        ]
        # hkl_index=symmetrically_distinct_miller_indices(cvn_atoms=atoms,max_index=self.max_index)
        hkl_max = np.array([self.max_index, self.max_index, self.max_index])
        for index in hkl_index:
            d = np.linalg.norm(np.dot(index, rec_matrix))
            multiple = int(np.ceil(1 / d / min_r))
            index *= multiple
            for i in range(len(hkl_max)):
                if hkl_max[i] < index[i]:
                    hkl_max[i] = index[i]

        h1, k1, l1 = hkl_max
        h = np.arange(-h1, h1 + 1)
        k = np.arange(-k1, k1 + 1)
        L = np.arange(-l1, l1 + 1)

        hkl = np.array((np.meshgrid(h, k, L))).transpose()
        hkl_list = np.reshape(hkl, [len(h) * len(k) * len(L), 3])
        hkl_list = hkl_list[np.where(hkl_list.any(axis=1))[0]]
        d_hkl = 1 / np.linalg.norm(np.dot(hkl_list, rec_matrix), axis=1)

        shortlist = d_hkl > (min_r)
        d_hkl = d_hkl[shortlist]
        hkl_list = hkl_list[shortlist]
        sintheta = self.wavelength / 2 / d_hkl
        self.theta = np.arcsin(sintheta)
        self.hkl_list = np.array(hkl_list)
        self.d_hkl = d_hkl
        fp = os.path.join(os.path.dirname(__file__),
                          "atomic_scattering_params.json")
        with open(fp, "r") as f:
            ATOMIC_SCATTERING_PARAMS = json.load(f)
        d0 = (1 / 2 / self.d_hkl)**2
        coeffs = []
        zs = []
        for elem in atoms.elements:
            if elem == "D":
                elem = "H"
            c = ATOMIC_SCATTERING_PARAMS[elem]
            z = Specie(elem).Z
            coeffs.append(c)
            zs.append(z)
        coeffs = np.array(coeffs)
        self.peaks = {}
        two_thetas = []

        for hkl, s2, theta, d_hkl in zip(self.hkl_list, d0, self.theta,
                                         self.d_hkl):

            # Calculate the scattering factor sf
            g_dot_r = np.dot(atoms.frac_coords, np.transpose([hkl])).T[0]
            sf = zs - 41.78214 * s2 * np.sum(
                coeffs[:, :, 0] * np.exp(-coeffs[:, :, 1] * s2), axis=1)

            # Calculate the structure factor f
            f = np.sum(sf * np.exp(2j * np.pi * g_dot_r))

            # Calculate the lorentz polarization factor lf
            lf = (1 + np.cos(2 * theta)**2) / (np.sin(theta)**2 *
                                               np.cos(theta))

            po = 1
            # Calculate the intensity I
            intensity_tmp = (f * f.conjugate()).real

            # calculate 2*theta
            two_theta = np.degrees(2 * theta)

            # Find where the scattered angles are equal
            ind = np.where(
                np.abs(np.subtract(two_thetas, two_theta)) < self.two_theta_tol
            )

            # Append intensity, hkl plane, and thetas to lists
            if len(ind[0]) > 0:
                self.peaks[two_thetas[ind[0][0]]][0] += intensity_tmp * lf * po
                self.peaks[two_thetas[ind[0][0]]][1].append(tuple(hkl))
            else:
                self.peaks[two_theta] = [
                    intensity_tmp * lf * po,
                    [tuple(hkl)],
                    d_hkl,
                ]
                two_thetas.append(two_theta)

        # max_intensity = max([v[0] for v in self.peaks.values()])
        x = []
        y = []
        d_hkls = []
        hkl_families = []
        for k in sorted(self.peaks.keys()):
            v = self.peaks[k]
            x.append(k)
            y.append(v[0])
            d_hkls.append(v[2])
            family = self.get_unique_families(v[1])
            hkl_families.append(family)
        x = np.array(x)
        y = np.array(y)
        d_hkls = np.array(d_hkls)
        const = np.sum(y, axis=0)
        y = y * self.scaling_factor / const
        screen = y > self.intensity_tol
        self.intensity_array = y[screen]
        self.two_theta_array = x[screen]
        self.dhkl_array = d_hkls[screen]
        return (
            x[screen].tolist(),
            d_hkls[screen].tolist(),
            y[screen].tolist(),
            # hkl_families[screen],
        )
Example #20
0
 def weight(self):
     """Get atomic weight."""
     wt = 0.0
     for specie, count in self._content.items():
         wt = wt + Specie(specie).atomic_mass * count
     return wt
Example #21
0
    def from_atoms(
        atoms=None,
        get_prim=False,
        zero_diag=False,
        node_atomwise_angle_dist=False,
        node_atomwise_rdf=False,
        features="basic",
        enforce_c_size=10.0,
        max_n=100,
        max_cut=5.0,
        verbose=False,
        make_colormap=True,
    ):
        """
        Get Networkx graph. Requires Networkx installation.

        Args:
             atoms: jarvis.core.Atoms object.

             rcut: cut-off after which distance will be set to zero
                   in the adjacency matrix.

             features: Node features.
                       'atomic_number': graph with atomic numbers only.
                       'cfid': 438 chemical descriptors from CFID.
                       'basic':10 features
                       'atomic_fraction': graph with atomic fractions
                                         in 103 elements.
                       array: array with CFID chemical descriptor names.
                       See: jarvis/core/specie.py

             enforce_c_size: minimum size of the simulation cell in Angst.
        """
        if get_prim:
            atoms = atoms.get_primitive_atoms
        dim = get_supercell_dims(atoms=atoms, enforce_c_size=enforce_c_size)
        atoms = atoms.make_supercell(dim)

        adj = np.array(atoms.raw_distance_matrix.copy())

        # zero out edges with bond length greater than threshold
        adj[adj >= max_cut] = 0

        if zero_diag:
            np.fill_diagonal(adj, 0.0)
        nodes = np.arange(atoms.num_atoms)
        if features == "atomic_number":
            node_attributes = np.array(
                [[np.array(Specie(i).Z)] for i in atoms.elements],
                dtype="float",
            )
        if features == "atomic_fraction":
            node_attributes = []
            fracs = atoms.composition.atomic_fraction_array
            for i in fracs:
                node_attributes.append(np.array([float(i)]))
            node_attributes = np.array(node_attributes)

        elif features == "basic":
            feats = [
                "Z",
                "coulmn",
                "row",
                "X",
                "atom_rad",
                "nsvalence",
                "npvalence",
                "ndvalence",
                "nfvalence",
                "first_ion_en",
                "elec_aff",
            ]
            node_attributes = []
            for i in atoms.elements:
                tmp = []
                for j in feats:
                    tmp.append(Specie(i).element_property(j))
                node_attributes.append(tmp)
            node_attributes = np.array(node_attributes, dtype="float")
        elif features == "cfid":
            node_attributes = np.array(
                [np.array(Specie(i).get_descrp_arr) for i in atoms.elements],
                dtype="float",
            )
        elif isinstance(features, list):
            node_attributes = []
            for i in atoms.elements:
                tmp = []
                for j in features:
                    tmp.append(Specie(i).element_property(j))
                node_attributes.append(tmp)
            node_attributes = np.array(node_attributes, dtype="float")
        else:
            print("Please check the input options.")
        if node_atomwise_rdf or node_atomwise_angle_dist:
            nbr = NeighborsAnalysis(atoms,
                                    max_n=max_n,
                                    verbose=verbose,
                                    max_cut=max_cut)
        if node_atomwise_rdf:
            node_attributes = np.concatenate(
                (node_attributes, nbr.atomwise_radial_dist()), axis=1)
            node_attributes = np.array(node_attributes, dtype="float")
        if node_atomwise_angle_dist:
            node_attributes = np.concatenate(
                (node_attributes, nbr.atomwise_angle_dist()), axis=1)
            node_attributes = np.array(node_attributes, dtype="float")

        # construct edge list
        uv = []
        edge_features = []
        for ii, i in enumerate(atoms.elements):
            for jj, j in enumerate(atoms.elements):
                bondlength = adj[ii, jj]
                if bondlength > 0:
                    uv.append((ii, jj))
                    edge_features.append(bondlength)

        edge_attributes = edge_features

        if make_colormap:
            sps = atoms.uniq_species
            color_dict = random_colors(number_of_colors=len(sps))
            new_colors = {}
            for i, j in color_dict.items():
                new_colors[sps[i]] = j
            color_map = []
            for ii, i in enumerate(atoms.elements):
                color_map.append(new_colors[i])
        return Graph(
            nodes=nodes,
            edges=uv,
            node_attributes=np.array(node_attributes),
            edge_attributes=np.array(edge_attributes),
            color_map=color_map,
        )
Example #22
0
    def get_comp_descp(
        self,
        jcell=True,
        jmean_chem=True,
        jmean_chg=True,
        jrdf=False,
        jrdf_adf=True,
        print_names=False,
    ):
        """
        Get chemo-structural CFID decriptors.

        Args:

            struct: Structure object

            jcell: whether to use cell-size descriptors

            jmean_chem: whether to use average chemical descriptors

            jmean_chg: whether to use average charge distribution descriptors

            jmean_rdf: whether to use radial distribution descriptors

            jrdf_adf: whether to use radial and angle distribution descriptors

            print_names: whether to print names of descriptors

        Returns:
          cat: catenated final descriptors
        """
        cat = []
        s = self._atoms
        cell = []
        mean_chem = []
        rdf = []
        nn = []
        mean_chg = []
        adfa = []
        adfb = []
        ddf = []
        if jmean_chem:
            el_dict = s.composition._content
            # print (el_dict,type(el_dict))
            arr = []
            for k, v in el_dict.items():
                des = Specie(k).get_descrp_arr
                arr.append(des)
            mean_chem = np.mean(np.array(arr), axis=0)
            # print ('mean_chem',len(mean_chem))

        if jcell:
            v_pa = round(float(s.volume) / float(s.num_atoms), 5)
            logv_pa = round(log(v_pa), 5)
            pf = s.packing_fraction
            density = round(s.density, 5)
            cell = np.array([v_pa, logv_pa, pf, density])
            # print ('jcell',len(cell))

        if jrdf:
            Nbrs = NeighborsAnalysis(s)
            _, distrdf, nn = Nbrs.get_rdf()
            rdf = np.array(distrdf)
            print("rdf", len(rdf))

        if jrdf_adf:
            try:
                adfa = np.zeros(179)
                adfb = np.zeros(179)
                ddf = np.zeros(179)
                rdf = np.zeros(100)
                nn = np.zeros(100)
                distributions = NeighborsAnalysis(s).get_all_distributions
                rdf = distributions["rdf"]
                nn = distributions["nn"]
                adfa = distributions["adfa"]
                adfb = distributions["adfb"]
                ddf = distributions["ddf"]

            except Exception:
                pass
            adfa = np.array(adfa)
            adfb = np.array(adfb)
            rdf = np.array(rdf)
            ddf = np.array(ddf)
            nn = np.array(nn)
            # print ('adfa',len(adfa))
            # print ('ddf',len(ddf))
            # print ('adfb',len(adfb))
            # print ('rdf',len(rdf))
            # print ('nn',len(nn))

        if jmean_chg:
            chgarr = []
            el_dict = s.composition._content
            for k, v in el_dict.items():
                chg = Specie(k).get_chgdescrp_arr
                chgarr.append(chg)
            mean_chg = np.mean(chgarr, axis=0)
            # print ('mean_chg',len(mean_chg))

        if print_names:
            nmes = []
            chem_nm = get_descrp_arr_name()
            for d, nm in zip(
                [mean_chem, cell, mean_chg, rdf,
                 adfa, adfb, ddf, nn],
                ["mean_chem", "cell", "mean_chg",
                 "rdf", "adfa", "adfb", "ddf", "nn"],
            ):
                if len(d) != 0:
                    for ff, dd in enumerate(d):
                        cat.append(dd)
                        if nm == "mean_chem":
                            tag = chem_nm[ff]
                        else:
                            tag = str(nm) + str("_") + str(ff)
                        nmes.append(str(tag))
            cat = np.array(cat).astype(float)
            # print (nmes,len(nmes))
            return nmes
        else:
            for d, nm in zip(
                [mean_chem, cell, mean_chg, rdf,
                 adfa, adfb, ddf, nn],
                ["mean_chem", "cell", "mean_chg",
                 "rdf", "adfa", "adfb", "ddf", "nn"],
            ):
                if len(d) != 0:
                    # if d != []:
                    for ff, dd in enumerate(d):
                        cat.append(dd)
            cat = np.array(cat).astype(float)
        return cat