sagar.molecule.structure 源代码
# -*- coding: utf-8 -*-
"""
Created on Sat Aug 25 16:41:45 2018
@author: hecc
Modified by: Jason Yu
"""
import numpy
from sagar.molecule import symmetry
from sagar.toolkit.mathtool import closest_pair
from sagar.element.base import periodic_table_dict, get_symbol, symbol2number
[文档]class Molecule(object):
"""
Molecule object represent a 1D Molecule structure.
parameters:
positions: n tuples(x,y,z) in fraction. 可多态初始化
atoms: list of atoms, can be atomic number (int), can be
atomic symbol (string),
represent atom in periodic table. (用全称初始化??谁TM会这么用?)
"""
def __init__(self, positions, atoms):
# TODO: magmoms init setting
self._atom_numbers = len(atoms)
self._positions = numpy.array(positions).reshape((-1, 3))
if self._positions.shape[0] != self._atom_numbers:
raise ValueError("When init Cell, number of atoms not equal to "
"number of positions.\n"
"CHECK YOUR INPUT!")
if isinstance(atoms, numpy.ndarray):
atoms = atoms.tolist()
a = []
for s in atoms:
if isinstance(s, str):
if s in periodic_table_dict:
a.append(periodic_table_dict[s])
elif len(s.split("_")) == 2 and s.split("_")[0] == "NaN":
i = int(s.split("_")[1])
a.append(1000 + i)
else:
raise ValueError("Unkown atom symbols {:}".format(s))
else:
a.append(round(s))
self._atoms = numpy.array(a, dtype='intc')
@property
def positions(self):
return self._positions
@property
def atoms(self):
return self._atoms
def __repr__(self):
def _repr(number):
return "{:9.6f}".format(number)
sites = zip(self._positions, self._atoms)
out_pos = []
out_pos.append("Sites:")
for s in sites:
o = ' '.join(map(_repr, s[0])) + ' ' + get_symbol(s[1])
out_pos.append(o)
outs = out_pos
return "\n".join(outs)
[文档] def get_symmetry_permutation(self, symprec=1e-3):
return symmetry.get_permutations(self._positions,
self._atoms.tolist(),
symprec)
[文档] def check(self, elements=None, limit=0.1, warn=False):
"""
该方法用于自查对象中的位点是否过近
若过近则抛出一个warning
"""
if elements is None:
mol = self
else:
# 选取要check的元素,构建新的胞
ele_num = [symbol2number(s) for s in elements]
positions = []
atoms = []
for idx, e in enumerate(self.atoms):
if e in ele_num:
positions.append(self.positions[idx])
atoms.append(self.atoms[idx])
mol = self.__class__(positions, atoms)
points = mol.positions
if closest_pair(points) < limit:
if warn is True:
import warnings
warnings.warn("some atoms are too close(< {:f}), check cell".format(
limit), RuntimeWarning)
return False
else:
return True