コード例 #1
0
    def del_atoms(self,
                  index_or_atoms,
                  isUpdatedInfo=False,
                  isPersist=False,
                  **kwargs):
        """
        delete atoms from structure.
        
        Arguments:
            index_or_atoms: collection of atom's index, formated atom or object. i.e. [atom0, atom1, atom2,...] 
                    ['Na', 0.1, 0.0, 0.0, 'Direct']
                    ['Na', 0.1, 0.0, 0.0]
                    ['Na', 5.234, 0.0, 0.0, 'Cartesian']
                    
            kwargs:
                symprec (default=1e-5): precision when to find the symmetry.
                angle_tolerance (default=-1.0): a experimental argument that controls angle tolerance between basis vectors.
        
        Returns:
            structureFactory's object.
        """
        from utils.check import check_formated_atom
        from materials.atom import Atom

        structure = self.structure
        for atom in index_or_atoms:
            formated_atom = None
            if isinstance(atom, int):
                index = atom
                if index < 0 or index > structure.natoms:
                    raise ValueError('beyond the range of atomic index')
                else:
                    formated_atom = structure.atoms[index].to_formated()
            elif isinstance(atom, Atom):
                formated_atom = atom.to_formated()
            elif check_formated_atom(atom):
                formated_atom = atom
            else:
                raise ValueError('unrecognized atom')
            status = structure.del_atom(formated_atom)
            if not status:
                raise StructureFactoryError('failed')
        # default
        symprec = 1e-5  # symprec
        angle_tolerance = -1.0  # angle_tolerance
        if 'symprec' in kwargs:
            symprec = kwargs['symprec']
        if 'angle_tolerance' in kwargs:
            angle_tolerance = kwargs['angle_tolerance']
        if isPersist:
            structure.update(isPersist=isPersist,
                             symprec=symprec,
                             angle_tolerance=angle_tolerance)
        elif isUpdatedInfo and not isPersist:
            structure.update(isPersist=False,
                             symprec=symprec,
                             angle_tolerance=angle_tolerance)
        self.structure = structure
        return self
コード例 #2
0
ファイル: species.py プロジェクト: CaptainDasheng/MMP2_learn
    def del_atom(self,
                 index_or_atom,
                 isUpdatedInfo=False,
                 isPersist=False,
                 **kwargs):
        """
        delete a atom from this species. Note that it will delete this atom's object from other related classes's objects.
        
        Arguments:
            index_or_atom: atom's index, formated atom and object.
            isUpdatedInfo (default=False): whether to update the composition and symmetry information (include the site, operation, wyckoffSite, spacegroup). 
            isPersist (default=False): whether to save to the database.
            
            kwargs:
                isNormalizingCoordinate (default=True): whether to remove the periodic boundary condition, 
                    ensure the value of atomic coordinate is between 0 and 1 (i.e. 1.3 -> 0.3).
                precision (default=1e-3): used to determine whether the two atoms are overlapped. Note that, 
                        to determine whether this atom is in collection by comparing its distance 
                        from other atoms.
                symprec (default=1e-5): precision when to find the symmetry.
                angle_tolerance (default=-1.0): a experimental argument that controls angle tolerance between basis vectors.
            
        Returns:
            True if delete a atom successfully. Conversely, False.
            
        从元素种类中删除一个原子。注意:当删除原子时,基于程序效率上的考虑(可能会多次对结构进行操作,可以在所有的操作完成后,更新内存中内建的结构关联信息以及同步数据库中的数据),
        程序默认不会更新结构(更新化学式,更新空间群和WyckoffSite,等)。
        
        参数:
            index_or_atom:其值可以是原子在结构的原子属性数组中的索引(index)、原子的格式化数组或原子对象。注意:原子的格式化数组的格式需要符合以下规则:
                1.程序默认晶体结构中原子坐标的类型为分数坐标。如果原子坐标为分数坐标,可以不用指定坐标类型。如,['Na', 0.1, 0.0, 0.0]。
                2.如果指定原子坐标类型,类型必须为‘Direct’或‘Cartesian’。如,['Na', 0.1, 0.0, 0.0, 'Direct']、['Na', 5.234, 0.0, 0.0, 'Cartesian']。
            isUpdatedInfo (default=False):是否更新结构的其他关联数据信息(如,化学式、不等价位置,等)。
            isPersist (default=False):是否持久化,即将结构保存到数据库中。
            
            kwargs:
                isNormalizingCoordinate (default=True):当给定原子的类型为格式化数组时,默认移除原子坐标上的平移周期性,以保证其值在0.0~1.0之间。
                precision (default=1e-3):比较原子是否重叠的精度。当“atom”参数为格式化数组时,此参数用于判断给定的原子是否在结构中(比较给定原子坐标与结构中的原子坐标之间的距离)。
                symprec (default=1e-5):找结构对称性时,采用的精度。
                angle_tolerance (default=-1.0):找结构对称性时,控制晶胞基矢之间的角度容差值。
        
        返回:
            布尔值(True/False)。
        """
        import warnings
        from utils.check import check_formated_atom
        from materials.atom import Atom

        atom = None
        if isinstance(index_or_atom, int):
            index = index_or_atom
            if index < 0 or index > len(self.atoms):
                warnings.warn('beyond the range of atomic index')
                return False
            atom = self.atoms[index]
        elif check_formated_atom(index_or_atom):
            # remove atomic translation periodicity
            isNormalizingCoordinate = True
            if 'isNormalizingCoordinate' in kwargs:
                isNormalizingCoordinate = kwargs['isNormalizingCoordinate']
            precision = 1e-3
            if 'precision' in kwargs:
                precision = kwargs['precision']

            formated_atom = index_or_atom
            atom = self.get_atom(
                formated_atom,
                isNormalizingCoordinate=isNormalizingCoordinate,
                precision=precision)
        elif isinstance(index_or_atom, Atom):
            atom = index_or_atom
        else:
            warnings.warn('unrecognized index_or_atom')
            return False

        if not atom is None:
            if len(self.structures) != 1:
                warnings.warn(
                    "exist more than one structure in element.structures array, don't know which structure the element belong to"
                )
                return None
            structure = self.structures[0]
            structure.del_atom(atom, isUpdatedInfo=False, isPersist=False)

            # default
            symprec = 1e-5  # symprec
            angle_tolerance = -1.0  # angle_tolerance
            if 'symprec' in kwargs:
                symprec = kwargs['symprec']
            if 'angle_tolerance' in kwargs:
                angle_tolerance = kwargs['angle_tolerance']
            if isPersist:
                structure.update(isPersist=isPersist,
                                 symprec=symprec,
                                 angle_tolerance=angle_tolerance)
            elif isUpdatedInfo and not isPersist:
                structure.update(isPersist=False,
                                 symprec=symprec,
                                 angle_tolerance=angle_tolerance)

            return True
        else:
            return False
コード例 #3
0
ファイル: fetch.py プロジェクト: CaptainDasheng/MMP2_learn
def get_entity_from_collection(entity, collection, entity_type, **kwargs):
    """
    get a entity's object from collection.
        
    Arguments:
        entity: 
            for atom: 
                atom's object or formated string. For formated string, if type of coordinate is 'Direct', you 
                    can not specify the type. But, for 'Cartesian', must be given. the valid formation:
                        ['Na', 0.1, 0.0, 0.0, 'Direct']
                        ['Na', 0.1, 0.0, 0.0]
                        ['Na', 5.234, 0.0, 0.0, 'Cartesian']
            
            for site:
                site's position. Note that type of coordinate is 'Direct',  you can not specify
                    the type. The valid formation:
                        [0.1, 0.0, 0.0, 'Direct']
                        [0.1, 0.0, 0.0]
                        [5.234, 0.0, 0.0, 'Cartesian']
                
        kwargs:
            isNormalizingCoordinate (default=True): whether to remove the periodic boundary condition, 
                    ensure the value of atomic coordinate is between 0 and 1 (i.e. 1.3 -> 0.3).
            precision (default=1e-3): used to determine whether the two atoms are overlapped. Note that, 
                    to determine whether this atom is in collection by comparing its distance 
                    from other atoms.
            lattice: this structure's lattice parameter.
                
    Returns:
        entity's object if exist. Conversely, None.
    """
    from utils.check import check_formated_atom, check_formated_atom_only_cartesian
    from utils.check import check_formated_position, check_formated_position_only_cartesian
    from utils.convert import any2direct, normalize_position

    result = None
    if entity_type == 'atom':
        # remove atomic translation periodicity
        isNormalizingCoordinate = True
        if 'isNormalizingCoordinate' in kwargs:
            isNormalizingCoordinate = kwargs['isNormalizingCoordinate']
        precision = 1e-3
        if 'precision' in kwargs:
            precision = kwargs['precision']

        if check_formated_atom(entity):
            for i in xrange(0, len(collection)):
                if collection[i].element.symbol == entity[0]:
                    position = None
                    #if len(entity) == 5 and entity[-1].strip().lower().startswith('c'): # Cartesian
                    if check_formated_atom_only_cartesian(entity):
                        if not 'lattice' in kwargs:
                            raise ValueError("need to be given the 'lattice'")
                        lattice = kwargs['lattice']
                        position = any2direct(lattice, entity[1:5])
                    else:
                        position = entity[1:]

                    if isNormalizingCoordinate:
                        position = normalize_position(position, 'Direct')[:-1]
                    distance = collection[i].position - np.array(position)
                    if np.linalg.norm(distance) <= precision:
                        result = collection[i]
    elif entity_type == 'site':
        # remove atomic translation periodicity
        isNormalizingCoordinate = True
        if 'isNormalizingCoordinate' in kwargs:
            isNormalizingCoordinate = kwargs['isNormalizingCoordinate']
        precision = 1e-3
        if 'precision' in kwargs:
            precision = kwargs['precision']

        position = entity
        if check_formated_position(position):
            for site in collection:
                if check_formated_position_only_cartesian(position):
                    position = any2direct(site.structure.lattice, position)

                if isNormalizingCoordinate:
                    position = normalize_position(position, 'Direct')[:-1]
                distance = site.position - np.array(position)
                if np.linalg.norm(distance) <= precision:
                    result = site

    return result
コード例 #4
0
    def translation(self,
                    index_or_atoms,
                    direction,
                    isUpdatedInfo=False,
                    isPersist=False,
                    **kwargs):
        """
        translation given atoms.
        
        arguments:
            direction: direction vector to add the vacuum along lattice vector(a/b/c). The valid format is :
                [0.1, 0, 0, 'Direct']
                [0.1, 0, 0] (for Direct, can not be specify)
                [5.234, 0, 0, 'Cartesian'] (for Cartesian, must be given)
            index_or_atoms: collection of atom's index, formated atom or object. i.e. [atom0, atom1, atom2,...] 
                    ['Na', 0.1, 0.0, 0.0, 'Direct']
                    ['Na', 0.1, 0.0, 0.0]
                    ['Na', 5.234, 0.0, 0.0, 'Cartesian']
            isUpdatedInfo (default=False): whether to update the composition and symmetry information (include the site, operation, wyckoffSite, spacegroup).
            isPersist (default=False): whether to save to the database.
            
            kwargs:
                symprec (default=1e-5): precision when to find the symmetry.
                angle_tolerance (default=-1.0): a experimental argument that controls angle tolerance between basis vectors.
        
        Returns:
            structureFactory's object.
        """
        from utils.check import check_formated_position, check_formated_atom
        from utils.convert import any2direct, normalize_position, translation
        from materials.atom import Atom

        structure = self.structure

        # check
        if not check_formated_position(direction):
            raise StructureFactoryError('invalid direction')
        direction = any2direct(structure.lattice, direction)

        for atom in index_or_atoms:
            formated_atom = None
            if isinstance(atom, int):
                index = atom
                if index < 0 or index > structure.natoms:
                    raise ValueError('beyond the range of atomic index')
                else:
                    formated_atom = structure.atoms[index].to_formated()
            elif isinstance(atom, Atom):
                formated_atom = atom.to_formated()
            elif check_formated_atom(atom):
                formated_atom = atom
            else:
                raise ValueError('unrecognized atom')
            atom0 = structure.get_atom(formated_atom)
            atom0.position = normalize_position(translation(
                atom0.position, direction),
                                                dtype='d')[:-1]
        # default
        symprec = 1e-5  # symprec
        angle_tolerance = -1.0  # angle_tolerance
        if 'symprec' in kwargs:
            symprec = kwargs['symprec']
        if 'angle_tolerance' in kwargs:
            angle_tolerance = kwargs['angle_tolerance']
        if isPersist:
            structure.update(isPersist=isPersist,
                             symprec=symprec,
                             angle_tolerance=angle_tolerance)
        elif isUpdatedInfo and not isPersist:
            structure.update(isPersist=False,
                             symprec=symprec,
                             angle_tolerance=angle_tolerance)
        self.structure = structure

        return self
コード例 #5
0
    def rotation(self,
                 index_or_atoms,
                 axis,
                 theta,
                 isUpdatedInfo=False,
                 isPersist=False,
                 **kwargs):
        """
        rotation given atoms.
        
        arguments:
            axis: rotation axis. Note that, for molecule, the type of axis is only 'Cartesian'. The valid format:
                [0.1, 0.0, 0.0, 'Direct']
                [0.1, 0.0, 0.0]
                [5.234, 0.0, 0.0, 'Cartesian']
            theta: rotation angle. The valid format:
                [30, 'Degree']
                [0.2, 'Radian']
            index_or_atoms: collection of atom's index, formated atom or object. i.e. [atom0, atom1, atom2,...] 
                    ['Na', 0.1, 0.0, 0.0, 'Direct']
                    ['Na', 0.1, 0.0, 0.0]
                    ['Na', 5.234, 0.0, 0.0, 'Cartesian']
            isUpdatedInfo (default=False): whether to update the composition and symmetry information (include the site, operation, wyckoffSite, spacegroup).
            isPersist (default=False): whether to save to the database.
            
            kwargs:
                symprec (default=1e-5): precision when to find the symmetry.
                angle_tolerance (default=-1.0): a experimental argument that controls angle tolerance between basis vectors.
                origin: rotation origin. The valid format:
                    [0.1, 0.0, 0.0, 'Direct']
                    [0.1, 0.0, 0.0]
                    [5.234, 0.0, 0.0, 'Cartesian']
        Returns:
            structureFactory's object.
        """
        from utils.check import check_formated_position, check_formated_position_only_cartesian, check_formated_angle, check_formated_atom
        from utils.convert import any2direct, normalize_position, rotation
        from materials.atom import Atom
        from materials.structure import Structure
        from materials.molStructure import MolStructure

        structure = self.structure

        # check
        # axis
        if not check_formated_position(axis):
            raise ValueError('unrecognized axis')
        if isinstance(structure, Structure):
            axis = any2direct(structure.lattice, axis)
        elif isinstance(structure, MolStructure):
            if not check_formated_position_only_cartesian(axis):
                raise ValueError('unrecognized axis')

        # theta
        if not check_formated_angle(theta):
            raise ValueError('unrecognized theta')

        # origin
        origin = None
        if 'origin' in kwargs:
            origin = kwargs['origin']

        for atom in index_or_atoms:
            formated_atom = None
            if isinstance(atom, int):
                index = atom
                if index < 0 or index > structure.natoms:
                    raise ValueError('beyond the range of atomic index')
                else:
                    formated_atom = structure.atoms[index].to_formated()
            elif isinstance(atom, Atom):
                formated_atom = atom.to_formated()
            elif check_formated_atom(atom):
                formated_atom = atom
            else:
                raise ValueError('unrecognized atom')
            atom0 = structure.get_atom(formated_atom)
            if origin is None:
                atom0.position = normalize_position(rotation(
                    atom0.position, axis, theta),
                                                    dtype='d')[:-1]
            else:
                atom0.position = normalize_position(rotation(atom0.position,
                                                             axis,
                                                             theta,
                                                             origin=origin),
                                                    dtype='d')[:-1]
        # default
        symprec = 1e-5  # symprec
        angle_tolerance = -1.0  # angle_tolerance
        if 'symprec' in kwargs:
            symprec = kwargs['symprec']
        if 'angle_tolerance' in kwargs:
            angle_tolerance = kwargs['angle_tolerance']
        if isPersist:
            structure.update(isPersist=isPersist,
                             symprec=symprec,
                             angle_tolerance=angle_tolerance)
        elif isUpdatedInfo and not isPersist:
            structure.update(isPersist=False,
                             symprec=symprec,
                             angle_tolerance=angle_tolerance)
        self.structure = structure

        return self
コード例 #6
0
    def constraint(self, index_or_atoms, isPersist=False, **kwargs):
        """
        selected dynamics. assign the constraint information to given atoms. Meanwhile, the constraint of remainder atoms 
            are set to the default [False, False, False] if don't give the value of 'constraint_of_remainder'.
        
        Arguments:
            index_or_atoms: collection of atom contain constraint information. The valid formation:
                [[1, True, True, False],
                ['Na', 0.1, 0.0, 0.0, True, True, False],
                ['Na', 0.1, 0.0, 0.0, 'Direct, True, True, False],
                ['Na', 5.234, 0.0, 0.0, 'Cartesian', True, True, False],
                [atom1, True, True, True]]
            isPersist (default=False): whether to save to the database.
                
            kwarges:
                constraint_of_remainder (default=[False, False, False]): constraint of remainder atoms.
            
        Returns:
            structureFactory's object.
            
        用于VASP的选择动力学,指定给定原子的束缚信息。同时,对于没有给出原子束缚信息的原子:
            1)没有指定束缚条件的情况下,按照默认值设置([False, False, False])。
            2)给出剩余原子束缚条件时,剩余原子的束缚信息全部设置为指定的值。
            
        参数:
            index_or_atom:其值可以是原子在结构的原子属性数组中的索引(index)、原子的格式化数组或原子对象。注意:原子的格式化数组的格式需要符合以下规则:
                1.程序默认晶体结构中原子坐标的类型为分数坐标。如果原子坐标为分数坐标,可以不用指定坐标类型。如,['Na', 0.1, 0.0, 0.0]。
                2.如果指定原子坐标类型,类型必须为‘Direct’或‘Cartesian’。如,['Na', 0.1, 0.0, 0.0, 'Direct']、['Na', 5.234, 0.0, 0.0, 'Cartesian']。
            isPersist (default=False):是否持久化,即将结构保存到数据库中。
            
            kwargs:
                constraint_of_remainder (default=[False, False, False]):剩余原子的束缚值。
                
        返回:
            结构操作对象。
        """
        import warnings
        from utils.check import check_constraint, check_formated_atom, compare_with_memory
        from materials.atom import Atom

        structure = self.structure

        atoms = []
        constraints = []
        for index_or_atom in index_or_atoms:
            constraint = index_or_atom[-3:]
            index_or_atom = index_or_atom[:-3]
            if len(index_or_atom) == 1:
                index_or_atom = index_or_atom[0]
            if not check_constraint(constraint):
                warnings.warn('invalid constrain in index_or_atoms')
                return False

            # get given atom from structure
            atom = None
            if isinstance(index_or_atom, int):
                index = index_or_atom
                if index < 0 or index > structure.natoms:
                    warnings.warn('beyond the range of atomic index')
                    return False
                atom = structure.atoms[index]
            elif check_formated_atom(index_or_atom):
                # remove atomic translation periodicity
                isNormalizingCoordinate = True
                if 'isNormalizingCoordinate' in kwargs:
                    isNormalizingCoordinate = kwargs['isNormalizingCoordinate']
                precision = 1e-3
                if 'precision' in kwargs:
                    precision = kwargs['precision']

                formated_atom = index_or_atom
                atom = structure.get_atom(
                    formated_atom,
                    isNormalizingCoordinate=isNormalizingCoordinate,
                    precision=precision)
            elif isinstance(index_or_atom, Atom):
                atom = index_or_atom
                if not atom in structure.atoms:
                    warnings.warn("atom doesn't belong to this structure")
                    return False
            else:
                warnings.warn('unrecognized index_or_atom')
                return False
            if atom in atoms:
                warnings.warn('exist duplication in index_of_atoms')
                return False
            atoms.append(atom)
            constraints.append(constraint)

        for i in xrange(0, len(atoms)):
            atoms[i].constraint = constraints[i]
        result = compare_with_memory(atoms, structure, 'atom')
        remainders = result['memory']
        constraint_of_remainder = [False, False, False]
        if 'constraint_of_remaider' in kwargs:
            constraint_of_remainder = kwargs['constraint_of_remaider']
            if not check_constraint(constraint_of_remainder):
                warnings.warn('invalid constrain in index_or_atoms')
                return False
        for atom in remainders:
            atom.constraint = constraint_of_remainder

        if isPersist:
            structure._persist()
        self.structure = structure
        return self
コード例 #7
0
    def substitute_atoms(self,
                         index_or_atoms,
                         symbol_of_elements,
                         isUpdatedInfo=False,
                         isPersist=False,
                         **kwargs):
        """
        delete atoms from structure.
        
        Arguments:
            index_or_atoms: collection of atom's index, formated atom or object. i.e. [atom0, atom1, atom2,...] 
                    ['Na', 0.1, 0.0, 0.0, 'Direct']
                    ['Na', 0.1, 0.0, 0.0]
                    ['Na', 5.234, 0.0, 0.0, 'Cartesian']
            symbol_of_elements: element's symbol. If replacing by an element for all atom, you can only specify the a element' symbol.
                i.e. 'Na', ['Na', 'Na', 'Na']
                    
            kwargs:
                symprec (default=1e-5): precision when to find the symmetry.
                angle_tolerance (default=-1.0): a experimental argument that controls angle tolerance between basis vectors.
        
        Returns:
            structureFactory's object.
        """
        from utils.check import check_formated_atom
        from materials.atom import Atom

        structure = self.structure
        for i in xrange(0, len(index_or_atoms)):
            formated_atom = None
            atom = index_or_atoms[i]
            if isinstance(atom, int):
                index = atom
                if index < 0 or index > structure.natoms:
                    raise ValueError('beyond the range of atomic index')
                formated_atom = structure.atoms[index].to_formated()
            elif isinstance(atom, Atom):
                formated_atom = atom.to_formated()
            elif check_formated_atom(atom):
                formated_atom = atom
            else:
                raise ValueError('unrecognized atom')

            if isinstance(symbol_of_elements, str):
                symbol_of_element = symbol_of_elements
                structure.substitute_atom(formated_atom, symbol_of_element)
            elif isinstance(symbol_of_elements, list) or isinstance(
                    symbol_of_element, np.ndarray):
                symbol_of_element = symbol_of_elements[i]
                structure.substitute_atom(formated_atom, symbol_of_element)

        # default
        symprec = 1e-5  # symprec
        angle_tolerance = -1.0  # angle_tolerance
        if 'symprec' in kwargs:
            symprec = kwargs['symprec']
        if 'angle_tolerance' in kwargs:
            angle_tolerance = kwargs['angle_tolerance']
        if isPersist:
            structure.update(isPersist=isPersist,
                             symprec=symprec,
                             angle_tolerance=angle_tolerance)
        elif isUpdatedInfo and not isPersist:
            structure.update(isPersist=False,
                             symprec=symprec,
                             angle_tolerance=angle_tolerance)
        self.structure = structure
        return self