Finding Bond Length and Bond Angles in a composition

Hello

I am very new to using pymatgen and I found multiple modules that would return the bond lengths and angle in a composition such as the structure and composition modules. There is also the voronoi analysis submodule that does this as well. So, I would like to know which is the correct way of returning (say) a dict of the bond lengths between all the connected elements in a composition as well as their bond angles.

Hi Nishant_Abishaik,

Since you already have the coordinates of your system, you can calculate the bond length and bond angle by yourself.

import numpy as np
# calculate bond length
def bondlength(structure, index):
    if len(index) != 2:
        raise ValueError("Calculate bond length only needs 2 atoms")
    atom1 = structure[index[0]]
    atom2 = structure[index[1]]
    return np.linalg.norm(atom1.coords - atom2.coords)

# calculate bond angle, we assume index 2 is the center atom for bond angle
def bondangle(structure, index):
    if len(index) != 3:
        raise ValueError("Calculate bond angle only needs 3 atoms")
    atom1 = structure[index[0]]
    atom2 = structure[index[1]]
    atom3 = structure[index[2]]
    v1 = (atom2.coords-atom1.coords)/np.linalg.norm(atom2.coords-atom1.coords)
    v2 = (atom2.coords-atom3.coords)/np.linalg.norm(atom2.coords-atom3.coords)
    angle = np.arccos(np.dot(v1, v2))/np.pi*180.0
    # convert radius to angle
    return angle

Tell me if something went wrong.
Best,
ZDH

I apologize for the late reply but the MP site was down so I could not use the rest API to get data till today.

The code works really well, thank you so much!

Dear Zhengda

If I loop the above code through the positions of all the sites, I can get the data for even the unconnected sites as well. Is there a way to only find the bond lengths and angles for only the connected sites?

Hi Nishant,

I think you can use the function in pymatgen.core.structure: get_neighbors(site, r) to get all the closest atom. Then you can get all the connected sites.

If you want to do it by yourself, here’s a function which can also do the trick:

def connectedMatrix(struct_pmg, bond_length):
    import numpy as np
    cM = {} # connected Matrix
    for ind1, site1 in enumerate(struct_pmg):
        nameStr = site1.specie + str(ind1)
        cM[nameStr] = []
        for ind2, site2 in enumerate(struct_pmg):
            if ind != ind2 and np.linalg.norm(site1.coords - site2.coords) <= bond_length:
                cM[nameStr].append(ind2)
    return cM

You need to choose the bond_length that you want, also you can modify it to choose the desirable bond angle.
The output is like this:

cM = {
    'Pt0': [1, 3, 5] # just an example
}

Once you have the connected matrix, you can still doing the loop, but now you can check whether the two atoms are connected or not, this will help you only find all the connected sites.

if you have any issues, please do tell.

Best,
Zhengda