|
本帖最后由 丁越 于 2025-3-3 09:22 编辑
Oc, Osi, Ow在xyz文件中原子序号是固定不变的,直接通过原子序号查找某类O原子不就行了,再结合VMD的原子选择语法比如index 0 1 2 3选择Ow。之后就是用TCL语法遍历计算选中的原子与体系所有原子的键长,你自己设定一个判据标准,小于多少则视为成键。但缺点是TCL脚本运行起来挺慢。
第二种方法是通过ASE,里面的几何模块中有计算原子间的距离矩阵的函数,下面给你一段代码你自己参考一下:
- import numpy as np
- from ase import io
- from ase.data import covalent_radii
- from ase.geometry import get_distances
- def coordinated_bonds_num(atoms, index=None, scale=1.15):
- """
- calculate the number of coordinated bonds of each atom, simply based on geometry criteria.
- parameters:
- atoms: an ASE Atoms object.
- index: list.
- atomic index to be calculated.
- scale: float.
- the scale factor of covalent radii.
- return: list.
- """
- _, distances = get_distances(atoms.positions, pbc=atoms.pbc, cell=atoms.cell)
- radiis = (covalent_radii[atoms.get_atomic_numbers()] +
- covalent_radii[atoms.get_atomic_numbers()].reshape(-1, 1))
- distances = np.round(distances, decimals=1)
- radiis = np.round(radiis, decimals=1)
- is_bonded = np.where(distances <= scale * radiis, 1, 0) - np.eye(len(atoms))
- bond_num = np.sum(is_bonded, axis=1)
- if index is not None:
- bond_num = bond_num[index]
- return bond_num
复制代码 最后注意一点是CP2K的MD轨迹是不考虑PBC的,所以不论是拿VMD还是ASE统计都需要把原子卷回到盒子内。比如用ASE,参考下面代码:
- def wraped_coord(atoms, cell=None):
- """
- wrap atomic coordinates into unit cell.
- parameters:
- atoms: An Atoms object of ASE.
- cell: 3 * 3 nparray. cell parameters in vector formate.
- return:
- an Atoms object with wrapped coordinates.
- """
- if not all(atoms.pbc):
- if cell is None:
- raise ValueError("Cell parameters must be defined when atoms are wrapped.")
- else:
- atoms.set_cell(cell)
- atoms.pbc = (True, True, True)
- atoms.center(vacuum=7.5, axis=2)
- atoms.wrap(pretty_translation=True)
- return atoms
复制代码
|
|