Esempio n. 1
0
class Poscar(object):
    '''
    classdocs
    '''

    def __init__(self, path):
        '''
        Constructor
        '''
        self.path = path
        self.version = 0
        self.title = ''
        self.selective_dynamics = False
        self.direct_coords = False
        self.counts = []
        self.formula_unit = 0
        self.symbols = []
        self.supercell = SuperCell()
        self.surface_area = 0
        self._extract_data()

    def _extract_data(self):

        def _float_list(lst):
            new_lst = []
            for item in lst:
                new_lst.append(float(item))
            return new_lst

        def _int_list(lst):
            new_lst = []
            for item in lst:
                new_lst.append(int(item))
            return new_lst
        
        def _count_adatoms():
            """
            This function will count atoms as adatoms if there is less atoms on top 
            surface than in the bottom layer.
            
            Accuracy of the rounding is set with decimals variable
            """
            decimals = 5
            
            hp = round(self.supercell.get_highest_position(), decimals)
            atoms_at_hp = 0
            for atom in self.supercell.atoms:
                if round(atom.position[2], decimals) == hp:
                    atoms_at_hp += 1
            lp = round(self.supercell.get_lowest_position(), decimals)
            atoms_at_lp = 0
            for atom in self.supercell.atoms:
                if round(atom.position[2], decimals) == lp:
                    atoms_at_lp += 1
            if atoms_at_hp < atoms_at_lp:
                return atoms_at_hp
            else:
                return 0
            

        if getline("%s/POSCAR" % self.path, 6).strip().isdigit():
            self.version = 4
            self.counts = _int_list(getline("%s/POSCAR" % self.path, 6).split())
            self.symbols = ['None'] * len(self.counts)
        else:
            self.version = 5
            self.symbols = getline("%s/POSCAR" % self.path, 6).split()
            self.counts = _int_list(getline("%s/POSCAR" % self.path, 7).split())

        maximum = self.counts[0]
        for count in self.counts:
            if count > maximum:
                maximum = count
        self.formula_unit = maximum

        pos_starting_line = 0

        if self.version >= 5:
            if getline("%s/POSCAR" % self.path, 8)[0] in ['s', 'S']:
                self.selective_dynamics = True
                if  getline("%s/POSCAR" % self.path, 9)[0] in ['D', 'd']:
                    self.direct_coords = True
                pos_starting_line = 10
            else:
                if  getline("%s/POSCAR" % self.path, 8)[0] in ['D', 'd']:
                    self.direct_coords = True
                pos_starting_line = 9
        else:
            if getline("%s/POSCAR" % self.path, 7)[0] in ['s', 'S']:
                self.selective_dynamics = True
                if  getline("%s/POSCAR" % self.path, 8)[0] in ['D', 'd']:
                    self.direct_coords = True
                pos_starting_line = 9
            else:
                if  getline("%s/POSCAR" % self.path, 7)[0] in ['D', 'd']:
                    self.direct_coords = True
                pos_starting_line = 6

        self.title = getline("%s/POSCAR" % self.path, 1).rstrip()
        self.supercell.a0 = float(getline("%s/POSCAR" % self.path, 2))
        a1 = _float_list(getline("%s/POSCAR" % self.path, 3).split())
        a1 = array([a1[0], a1[1], a1[2]])
        a2 = _float_list(getline("%s/POSCAR" % self.path, 4).split())
        a2 = array([a2[0], a2[1], a2[2]])
        a3 = _float_list(getline("%s/POSCAR" % self.path, 5).split())
        a3 = array([a3[0], a3[1], a3[2]])
        self.surface_area = self.supercell.a0 * 2 * norm(cross(a1, a2))
        self.supercell.primitive_cell = PrimitiveCell(a1, a2, a3)
        f = open("%s/POSCAR" % self.path)
        for i in range(0, len(self.counts)):
            for j in range(pos_starting_line,
                              pos_starting_line + self.counts[i]):
                position = getline("%s/POSCAR" % self.path, j).split()
                if self.selective_dynamics:
                    relax = position[3:6]
                position = _float_list(position[:3])
                position = array([position[0], position[1], position[2]])
                if self.selective_dynamics:
                    self.supercell.add(self.symbols[i], position,
                                       relaxation=relax)
                else:
                    self.supercell.add(self.symbols[i], position)
            pos_starting_line += self.counts[i]
        
        # Mark adatoms
        nr_of_adatoms = _count_adatoms()
        for i in range(1, 1 + nr_of_adatoms):
            self.supercell.atoms[-i].adatom = True

        f.close()
Esempio n. 2
0
class Poscar(object):
    '''
    classdocs
    '''

    def __init__(self, path, suffix="", supercell=None, title="", selective_dynamics=False, velocities=False):
        '''
        Constructor
        '''
        self.path = path
        self.suffix = suffix
        self.version = 0
        self.title = title
        self.selective_dynamics = selective_dynamics
        self.velocities = velocities
        self.direct_coords = False
        self.counts = []
        self.formula_unit = 0
        self.symbols = []
        if supercell == None:
            self.supercell=SuperCell()
        else:
            self.supercell = supercell
        self.surface_area = 0
        if supercell == None:
            self._extract_data()
        if self.direct_coords == False:
            self._convert_to_direct_coordinates()

    def find_adatoms(self):
        # Mark adatoms
        nr_of_adatoms = self._count_adatoms()
        for i in range(1, 1 + nr_of_adatoms):
            self.supercell.atoms[-i].adatom = True
            
            
    def _count_adatoms(self):
        """
        This function will count atoms as adatoms if there is less atoms on top 
        surface than in the bottom layer.
        
        Accuracy of the rounding is set with decimals variable
        """
        decimals = 5
        
        hp = round(self.supercell.get_highest_position(), decimals)
        atoms_at_hp = 0
        for atom in self.supercell.atoms:
            if round(atom.position[2], decimals) == hp:
                atoms_at_hp += 1
        lp = round(self.supercell.get_lowest_position(), decimals)
        atoms_at_lp = 0
        for atom in self.supercell.atoms:
            if round(atom.position[2], decimals) == lp:
                atoms_at_lp += 1
        if atoms_at_hp < atoms_at_lp:
            return atoms_at_hp
        else:
            return 0    
            
            
    def _extract_data(self):

        def _float_list(lst):
            new_lst = []
            for item in lst:
                new_lst.append(float(item))
            return new_lst

        def _int_list(lst):
            new_lst = []
            for item in lst:
                new_lst.append(int(item))
            return new_lst
        
            

        if getline("%s/POSCAR%s" % (self.path, self.suffix), 6).strip().isdigit():
            self.version = 4
            self.counts = _int_list(getline("%s/POSCAR%s" % (self.path, self.suffix), 6).split())
            self.symbols = ['None'] * len(self.counts)
        else:
            self.version = 5
            self.symbols = getline("%s/POSCAR%s" % (self.path, self.suffix), 6).split()
            try:
                self.counts = _int_list(getline("%s/POSCAR%s" % (self.path, self.suffix), 7).split())
            except:
                print getline("%s/POSCAR%s" % (self.path, self.suffix), 7)
        
        if len(self.counts) == 0:
            print "Error in POSCAR%s at: %s" % (self.suffix, self.path)
            exit()
        maximum = self.counts[0]
        for count in self.counts:
            if count > maximum:
                maximum = count
        self.formula_unit = maximum

        pos_starting_line = 0

        if self.version >= 5:
            if getline("%s/POSCAR%s" % (self.path, self.suffix), 8)[0] in ['s', 'S']:
                self.selective_dynamics = True
                if  getline("%s/POSCAR%s" % (self.path, self.suffix), 9)[0] in ['D', 'd']:
                    self.direct_coords = True
                pos_starting_line = 10
            else:
                if  getline("%s/POSCAR%s" % (self.path, self.suffix), 8)[0] in ['D', 'd']:
                    self.direct_coords = True
                pos_starting_line = 9
        else:
            if getline("%s/POSCAR%s" % (self.path, self.suffix), 7)[0] in ['s', 'S']:
                self.selective_dynamics = True
                if  getline("%s/POSCAR%s" % (self.path, self.suffix), 8)[0] in ['D', 'd']:
                    self.direct_coords = True
                pos_starting_line = 9
            else:
                if  getline("%s/POSCAR%s" % (self.path, self.suffix), 7)[0] in ['D', 'd']:
                    self.direct_coords = True
                pos_starting_line = 6

        self.title = getline("%s/POSCAR%s" % (self.path, self.suffix), 1).rstrip()
        self.supercell.a0 = float(getline("%s/POSCAR%s" % (self.path, self.suffix), 2))
        a1 = _float_list(getline("%s/POSCAR%s" % (self.path, self.suffix), 3).split())
        a1 = array([a1[0], a1[1], a1[2]])
        a2 = _float_list(getline("%s/POSCAR%s" % (self.path, self.suffix), 4).split())
        a2 = array([a2[0], a2[1], a2[2]])
        a3 = _float_list(getline("%s/POSCAR%s" % (self.path, self.suffix), 5).split())
        a3 = array([a3[0], a3[1], a3[2]])
        self.surface_area = self.supercell.a0 * 2 * norm(cross(a1, a2))
        self.supercell.primitive_cell = PrimitiveCell(a1, a2, a3)
        f = open("%s/POSCAR%s" % (self.path, self.suffix))
        for i in range(0, len(self.counts)):
            for j in range(pos_starting_line,
                              pos_starting_line + self.counts[i]):
                position = getline("%s/POSCAR%s" % (self.path, self.suffix), j).split()
                if self.selective_dynamics:
                    relax = position[3:6]
                position = _float_list(position[:3])
                position = array([position[0], position[1], position[2]])
                if self.selective_dynamics:
                    self.supercell.add(self.symbols[i], position,
                                       relaxation=relax)
                else:
                    self.supercell.add(self.symbols[i], position)
            pos_starting_line += self.counts[i]

        f.close()
        
    def _convert_to_direct_coordinates(self):
        print "Running convertion"
        new_sc = SuperCell()
        for atom in self.supercell.atoms:
            new_sc.add(atom.symbol, self.supercell.convert_to_direct(atom.position))
        self.supercell.atoms = new_sc.atoms
        self.direct_coords = True

    def create_file(self):
        outfile = open(self.path + '/POSCAR', 'w')
        outfile.write(self.title)
        outfile.write(' - %s\n' % datetime.now())
        outfile.write('%f\n' % self.supercell.a0)
        outfile.write(str(self.supercell.primitive_cell))
        outfile.write(" ".join(self.symbols) + '\n') # Change this
        outfile.write(" ".join(str(x) for x in self.counts) + '\n') # and this
        if self.selective_dynamics: outfile.write('Selective dynamics\n')
        outfile.write("Direct\n")
        for atom in self.supercell.atoms:
            if self.selective_dynamics:
                outfile.write("%s\n" % atom.str_with_relaxation())
            else:
                outfile.write("%s\n" % atom)
        if self.velocities:
            outfile.write(2 * '\n')        
            for atom in self.supercell.atoms:
                outfile.write("  %.9f  %.9f  %.9f\n" % (atom.velocity[0], atom.velocity[1], atom.velocity[2]))
        outfile.close()
Esempio n. 3
0
class Contcar(object):
    '''
    classdocs
    '''

    def __init__(self, path):
        '''
        Constructor
        '''
        self.path = path
        self.version = 0
        self.title = ''
        self.selective_dynamics = False
        self.direct_coords = False
        self.counts = []
        self.formula_unit = 0
        self.symbols = []
        self.supercell = SuperCell()
        self.surface_area = 0
        self.coa = 0
        try:
            self._extract_data()
        except:
            print "Error with CONTCAR in: %s" % self.path
            #print exc_info()
            
    def find_adatoms(self):
        # Mark adatoms
        nr_of_adatoms = self._count_adatoms()
        for i in range(1, 1 + nr_of_adatoms):
            self.supercell.atoms[-i].adatom = True
            
    def _count_adatoms(self):
        """
        This function will count atoms as adatoms if there is less atoms on top 
        surface than in the bottom layer.
        
        Accuracy of the rounding is set with decimals variable
        """
        decimals = 5
        
        hp = round(self.supercell.get_highest_position(), decimals)
        atoms_at_hp = 0
        for atom in self.supercell.atoms:
            if round(atom.position[2], decimals) == hp:
                atoms_at_hp += 1
        lp = round(self.supercell.get_lowest_position(), decimals)
        atoms_at_lp = 0
        for atom in self.supercell.atoms:
            if round(atom.position[2], decimals) == lp:
                atoms_at_lp += 1
        if atoms_at_hp < atoms_at_lp:
            return atoms_at_hp
        else:
            return 0

    def _convert_to_direct_coordinates(self):
        print "Running convertion"
        new_sc = SuperCell()
        for atom in self.supercell.atoms:
            new_sc.add(atom.symbol, self.supercell.convert_to_direct(atom.position))
        self.supercell.atoms = new_sc.atoms
        self.direct_coords = True

    def _extract_data(self):
        def _float_list(lst):
            new_lst = []
            for item in lst:
                new_lst.append(float(item))
            return new_lst

        def _int_list(lst):
            new_lst = []
            for item in lst:
                new_lst.append(int(item))
            return new_lst

        if getline("%s/CONTCAR" % self.path, 6).strip().isdigit():
            self.version = 4
            self.counts = _int_list(getline("%s/CONTCAR" % self.path, 6).split())
            self.symbols = ['None'] * len(self.counts)
        else:
            self.version = 5
            self.symbols = getline("%s/CONTCAR" % self.path, 6).split()
            self.counts = _int_list(getline("%s/CONTCAR" % self.path, 7).split())

        maximum = self.counts[0]
        for count in self.counts:
            if count > maximum:
                maximum = count
        self.formula_unit = maximum

        pos_starting_line = 0

        if self.version >= 5:
            if getline("%s/CONTCAR" % self.path, 8)[0] in ['s', 'S']:
                self.selective_dynamics = True
                if  getline("%s/CONTCAR" % self.path, 9)[0] in ['D', 'd']:
                    self.direct_coords = True
                pos_starting_line = 10
            else:
                if  getline("%s/CONTCAR" % self.path, 8)[0] in ['D', 'd']:
                    self.direct_coords = True
                pos_starting_line = 9
        else:
            if getline("%s/CONTCAR" % self.path, 7)[0] in ['s', 'S']:
                self.selective_dynamics = True
                if  getline("%s/CONTCAR" % self.path, 8)[0] in ['D', 'd']:
                    self.direct_coords = True
                pos_starting_line = 9
            else:
                if  getline("%s/CONTCAR" % self.path, 7)[0] in ['D', 'd']:
                    self.direct_coords = True
                pos_starting_line = 6

        self.title = getline("%s/CONTCAR" % self.path, 1).rstrip()
        self.supercell.a0 = float(getline("%s/CONTCAR" % self.path, 2).split()[0])
        a1 = _float_list(getline("%s/CONTCAR" % self.path, 3).split())
        a1 = array([a1[0], a1[1], a1[2]])
        a2 = _float_list(getline("%s/CONTCAR" % self.path, 4).split())
        a2 = array([a2[0], a2[1], a2[2]])
        a3 = _float_list(getline("%s/CONTCAR" % self.path, 5).split())
        a3 = array([a3[0], a3[1], a3[2]])
        self.coa = norm(a3)       
        self.supercell.primitive_cell = PrimitiveCell(a1, a2, a3)
        if self.supercell.a0 < 0:
            self.supercell.a0 = (self.supercell.a0/np.linalg.det(self.supercell.primitive_cell.matrix))**(1./3.)
        self.surface_area = self.supercell.a0**2 * norm(cross(a1, a2))
        f = open("%s/CONTCAR" % self.path)
        for i in range(0, len(self.counts)):
            for j in range(pos_starting_line,
                              pos_starting_line + self.counts[i]):
                position = getline("%s/CONTCAR" % self.path, j).split()
                if self.selective_dynamics:
                    relax = position[3:6]
                position = _float_list(position[:3])
                position = array([position[0], position[1], position[2]])
                if self.selective_dynamics:
                    self.supercell.add(self.symbols[i], position,
                                       relaxation=relax)
                else:
                    self.supercell.add(self.symbols[i], position)
            pos_starting_line += self.counts[i]

        f.close()
        if not self.direct_coords:
            self._convert_to_direct_coordinates()
    
    def distance(self, r1, r2):
        delta = np.linalg.norm(self.supercell.convert_to_real(r1 - r2))
        return delta
    
    def _calculate_sqs_repetitions(self, other):
        if abs(self.supercell.primitive_cell.matrix[1, 0]) > 1.1:
            return (4, 4, 2)
        elif abs(self.supercell.primitive_cell.matrix[1, 0]) > 0.51:
            return (4, 2, 4)
        else:
            return (1, 1, 1)
        
    
    def calculate_average_u(self, return_all=False):
        sqs_repetitions = self._calculate_sqs_repetitions('N')
        print sqs_repetitions
        u_list = []
        cd_list = []
        for atom1 in self.supercell.atoms:
            if atom1.symbol != 'N':
                d = 0.0
                cd = 0.0
                for atom2 in self.supercell.atoms:
                    if atom2.symbol == 'N':
                        for i in range(-1, 2):
                            for j in range(-1, 2):
                                if (atom2.position[2] > atom1.position[2] 
                                    and self.distance(array([atom1.position[0] + i, atom1.position[1] + j, 0]),
                                                      array([atom2.position[0], atom2.position[1], 0])) < 1.5):
                                    new_d = self.distance(atom1.position, atom2.position) 
                                    new_cd = atom2.position[2] - atom1.position[2]
                                    if d == 0 or new_d < d:
                                        d = new_d
                                    if cd == 0 or new_cd < cd:
                                        cd = new_cd
                                elif (atom2.position[2] + 1. > atom1.position[2] 
                                    and self.distance(array([atom1.position[0] + i, atom1.position[1] + j, 0]),
                                                      array([atom2.position[0], atom2.position[1], 0])) < 1.5 ):
                                    new_d = self.distance(atom1.position, atom2.position + array([0, 0, 1.]))
                                    new_cd = atom2.position[2] + 1 - atom1.position[2]
                                    if d == 0 or new_d < d: 
                                        d = new_d
                                    if cd == 0 or new_cd < cd: 
                                        cd = new_cd
                if d == 0 or cd == 0:
                    print "Found no atom to compare with"
                else:
                    u_list.append(d / (self.coa * self.supercell.a0) * sqs_repetitions[2])
                    cd_list.append(cd * sqs_repetitions[2])
        
        # Change to u_list to get u parameter not only in c-direction
        if return_all:
            return cd_list
        else:
            return sum(cd_list) / len(cd_list)