Exemple #1
0
def read_CHGCAR(fname='CHGCAR', specorder=None):
    """
    Read CHGCAR file and get information of cell, atoms, and volumetric data.

    Parameters
    ----------
    fname : str
         File name to be read.
    """
    nsys = NAPSystem()
    with open(fname, 'r') as f:
        # 1st line: comment
        f.readline()
        # 2nd: lattice constant
        nsys.alc = float(f.readline().split()[0])
        # 3rd-5th: cell vectors
        nsys.a1 = np.array([float(x) for x in f.readline().split()])
        nsys.a2 = np.array([float(x) for x in f.readline().split()])
        nsys.a3 = np.array([float(x) for x in f.readline().split()])
        # 6th: species names or number of each species
        buff = f.readline().split()
        if not buff[0].isdigit():
            spcs = copy.deepcopy(buff)
            buff = f.readline().split()
            if specorder is None:
                nsys.specorder = spcs
            else:
                nsys.specorder = specorder
                for s in spcs:
                    if s not in nsys.specorder:
                        nsys.specorder.append(s)
        num_species = np.array([int(n) for n in buff])
        try:
            spcs
        except NameError:
            spcs = nsys.specorder
        #...Check number of species in POSCAR file and in specorder
        if len(num_species) > len(nsys.specorder):
            msg = '''
ers of species in POSCAR is greater than the one in specorder, which should be the same or less.
er of species in POSCAR = {0:d}
need to specify the species order correctly with --specorder option.
            '''.format(len(num_species))
            raise ValueError(msg)
        natm = np.sum(num_species)
        sids = [0 for i in range(natm)]
        poss = np.zeros((natm, 3))
        vels = np.zeros((natm, 3))
        frcs = np.zeros((natm, 3))
        #print("Number of atoms = {0:5d}".format(natm))
        # 7th or 8th line: comment
        c7 = f.readline()
        if c7[0] in ('s', 'S'):
            c7 = f.readline()
        if c7[0] in ('c', 'C'):  # positions are in Cartesian coordinate
            hi = nsys.get_hmat_inv()
            coord = 'cartesian'
        else:  # such as "Direct"
            coord = 'scaled'

        #...Atom positions
        for i in range(natm):
            buff = f.readline().split()
            sid = 1
            m = 0
            sindex = 0
            for n in num_species:
                m += n
                if i < m:
                    if spcs and nsys.specorder:
                        sid = nsys.specorder.index(spcs[sindex]) + 1
                    break
                sid += 1
                sindex += 1
            sids[i] = sid
            pos = [float(buff[0]), float(buff[1]), float(buff[2])]
            if coord == 'cartesian':
                x1, x2, x3 = cartesian_to_scaled(hi, pos[0], pos[1], pos[2])
            elif coord == 'scaled':
                x1, x2, x3 = pos[0], pos[1], pos[2]
            poss[i][:] = [x1, x2, x3]

        #...Up to here, code should be the same as read_POSCAR, in case of CHGCAR lines follow
        nsys.atoms[['x', 'y', 'z']] = poss
        nsys.atoms[['vx', 'vy', 'vz']] = vels
        nsys.atoms[['fx', 'fy', 'fz']] = frcs
        nsys.atoms['sid'] = sids

        #...Read volumetric data
        f.readline()  # should be one blank line
        ndiv = [int(x) for x in f.readline().split()]
        ndata = ndiv[0] * ndiv[1] * ndiv[2]
        voldata = np.zeros(ndata)
        inc = 0
        while True:
            line = [float(d) for d in f.readline().split()]
            for d in line:
                voldata[inc] = d
                inc += 1
            if inc >= ndata:
                break
        #...Stop reading CHGCAR file here, ignoring the rest of file
        nsys.ndiv = copy.copy(ndiv)
        nsys.voldata = np.reshape(voldata, ndiv, order='F')
    return nsys
Exemple #2
0
def read_xsf(fname="xsf", specorder=None):
    from nappy.elements import get_symbol_from_number
    nsys = NAPSystem()
    if specorder is None:
        nsys.specorder = []
    else:
        nsys.specorder = specorder
    f = open(fname, 'r')
    mode = 'None'
    ixyz = 0
    iatm = 0
    natm = -1
    for line in f.readlines():
        if 'CRYSTAL' in line:
            mode = 'CRYSTAL'
            continue
        elif 'PRIMVEC' in line:
            mode = 'PRIMVEC'
            continue
        elif 'PRIMCOORD' in line:
            mode = 'PRIMCOORD'
            # Before going further, create inversed h-matrix
            hi = nsys.get_hmat_inv()
            # print 'Inversed h-matrix:'
            # print hi
            continue

        if mode == 'CRYSTAL':
            pass
        elif mode == 'PRIMVEC':
            if ixyz == 0:
                arr = [float(x) for x in line.split()]
                nsys.a1[0] = arr[0]
                nsys.a1[1] = arr[1]
                nsys.a1[2] = arr[2]
            elif ixyz == 1:
                arr = [float(x) for x in line.split()]
                nsys.a2[0] = arr[0]
                nsys.a2[1] = arr[1]
                nsys.a2[2] = arr[2]
            elif ixyz == 2:
                arr = [float(x) for x in line.split()]
                nsys.a3[0] = arr[0]
                nsys.a3[1] = arr[1]
                nsys.a3[2] = arr[2]
            ixyz += 1
        elif mode == 'PRIMCOORD':
            data = line.split()
            if len(data) == 1:
                natm = int(data[0])
                sids = [0 for i in range(natm)]
                poss = np.zeros((natm, 3))
                vels = np.zeros((natm, 3))
                frcs = np.zeros((natm, 3))
                continue
            elif len(data) == 2:
                natm = int(data[0])
                nspcs = int(data[1])
                sids = [0 for i in range(natm)]
                poss = np.zeros((natm, 3))
                vels = np.zeros((natm, 3))
                frcs = np.zeros((natm, 3))
                continue
            elif len(data) == 4 or len(data) == 7:
                if iatm >= natm:
                    continue
                symbol = get_symbol_from_number(int(data[0]))
                if symbol not in nsys.specorder:
                    nsys.specorder.append(symbol)
                sid = nsys.specorder.index(symbol) + 1
                sids[iatm] = sid
                # ai.set_sid(sid)
                xc = float(data[1])
                yc = float(data[2])
                zc = float(data[3])
                xi, yi, zi = cartesian_to_scaled(hi, xc, yc, zc)
                poss[iatm, :] = [xi, yi, zi]
                # print 'iatm,symbol,sid,xc,yc,zc = ',iatm,symbol,sid,xc,yc,zc
            else:
                continue
            iatm += 1
    nsys.alc = 1.0
    nsys.atoms[['x', 'y', 'z']] = poss
    nsys.atoms[['vx', 'vy', 'vz']] = vels
    nsys.atoms[['fx', 'fy', 'fz']] = frcs
    nsys.atoms['sid'] = sids
    f.close()
    return nsys
Exemple #3
0
def read_POSCAR(fname='POSCAR', specorder=None):
    nsys = NAPSystem()
    with open(fname, 'r') as f:
        # 1st line: comment
        f.readline()
        # 2nd: lattice constant
        nsys.alc = float(f.readline().split()[0])
        # 3rd-5th: cell vectors
        nsys.a1 = np.array([float(x) for x in f.readline().split()])
        nsys.a2 = np.array([float(x) for x in f.readline().split()])
        nsys.a3 = np.array([float(x) for x in f.readline().split()])
        # 6th: species names or number of each species
        buff = f.readline().split()
        if not buff[0].isdigit():
            spcs = copy.deepcopy(buff)
            buff = f.readline().split()
            if specorder is None:
                nsys.specorder = spcs
            else:
                nsys.specorder = specorder
                for s in spcs:
                    if s not in nsys.specorder:
                        nsys.specorder.append(s)
        num_species = np.array([int(n) for n in buff])
        try:
            spcs
        except NameError:
            spcs = nsys.specorder
        #...Check number of species in POSCAR file and in specorder
        if len(num_species) > len(nsys.specorder):
            msg = '''
ers of species in POSCAR is greater than the one in specorder, which should be the same or less.
er of species in POSCAR = {0:d}
need to specify the species order correctly with --specorder option.
            '''.format(len(num_species))
            raise ValueError(msg)
        natm = np.sum(num_species)
        sids = [0 for i in range(natm)]
        # poss = [ np.zeros(3) for i in range(natm) ]
        # vels = [ np.zeros(3) for i in range(natm) ]
        # frcs = [ np.zeros(3) for i in range(natm) ]
        poss = np.zeros((natm, 3))
        vels = np.zeros((natm, 3))
        frcs = np.zeros((natm, 3))
        #print("Number of atoms = {0:5d}".format(natm))
        # 7th or 8th line: comment
        c7 = f.readline()
        if c7[0] in ('s', 'S'):
            c7 = f.readline()
        if c7[0] in ('c', 'C'):  # positions are in Cartesian coordinate
            hi = nsys.get_hmat_inv()
            coord = 'cartesian'
        else:  # such as "Direct"
            coord = 'scaled'

        #...Atom positions
        for i in range(natm):
            buff = f.readline().split()
            sid = 1
            m = 0
            sindex = 0
            for n in num_species:
                m += n
                if i < m:
                    if spcs and nsys.specorder:
                        sid = nsys.specorder.index(spcs[sindex]) + 1
                    break
                sid += 1
                sindex += 1
            sids[i] = sid
            pos = [float(buff[0]), float(buff[1]), float(buff[2])]
            if coord == 'cartesian':
                x1, x2, x3 = cartesian_to_scaled(hi, pos[0], pos[1], pos[2])
            elif coord == 'scaled':
                x1, x2, x3 = pos[0], pos[1], pos[2]
            poss[i, :] = [x1, x2, x3]

    nsys.atoms[['x', 'y', 'z']] = poss
    nsys.atoms[['vx', 'vy', 'vz']] = vels
    nsys.atoms[['fx', 'fy', 'fz']] = frcs
    nsys.atoms['sid'] = sids
    return nsys
Exemple #4
0
def read_dump(fname="dump", specorder=None):
    nsys = NAPSystem()
    f = open(fname, 'r')
    mode = 'None'
    ixyz = 0
    iatm = 0
    natm = -1
    symbol = None
    if specorder is None:
        nsys.specorder = []
    else:
        nsys.specorder = specorder
    nsys.alc = 1.0
    xy = 0.0
    xz = 0.0
    yz = 0.0
    aux_exists = {
        'x': -1,
        'y': -1,
        'z': -1,
        'xu': -1,
        'yu': -1,
        'zu': -1,
        'fx': -1,
        'fy': -1,
        'fz': -1,
        'ekin': -1,
        'epot': -1,
        'sxx': -1,
        'syy': -1,
        'szz': -1,
        'syz': -1,
        'sxz': -1,
        'sxy': -1,
        'chg': -1,
        'chi': -1
    }
    ivx = -1
    ivy = -1
    ivz = -1
    ifx = -1
    ify = -1
    ifz = -1
    for line in f.readlines():
        data = line.split()
        if 'ITEM' in line:
            if 'NUMBER OF ATOMS' in line:
                mode = 'NUMBER OF ATOMS'
                continue
            elif 'BOX BOUNDS' in line:
                mode = 'BOX BOUNDS'
                continue
            elif 'ATOMS' in line:
                mode = 'ATOMS'
                aux_names = [name for i, name in enumerate(data) if i > 1]
                aux_names.remove('id')
                aux_names.remove('type')
                if ('x' not in aux_names and 'xu' not in aux_names) or \
                   ('y' not in aux_names and 'zu' not in aux_names) or \
                   ('z' not in aux_names and 'zu' not in aux_names):
                    raise ValueError(
                        'Not enough coordinate info.\nCheck the dump file format.'
                    )
                try:
                    ix = aux_names.index('x') + 2
                except Exception:
                    ix = aux_names.index('xu') + 2
                try:
                    iy = aux_names.index('y') + 2
                except Exception:
                    iy = aux_names.index('yu') + 2
                try:
                    iz = aux_names.index('z') + 2
                    # iauxstart = 5
                except Exception:
                    iz = aux_names.index('zu') + 2
                    # iauxstart = 5
                try:
                    ivx = aux_names.index('vx') + 2
                    ivy = aux_names.index('vy') + 2
                    ivz = aux_names.index('vz') + 2
                    # iauxstart = 8
                except Exception:
                    pass
                try:
                    ifx = aux_names.index('fx') + 2
                    ify = aux_names.index('fy') + 2
                    ifz = aux_names.index('fz') + 2
                except Exception:
                    pass
                # for s in ('x','xu','y','yu','z','zu','vx','vy','vz'):
                #     if s in aux_names:
                #         aux_names.remove(s)
                if len(aux_names) > 0:
                    auxs = np.zeros((natm, len(aux_names)))
                continue
            elif 'TIMESTEP' in line:
                mode = 'TIMESTEP'
                continue

        if mode == 'TIMESTEP':
            timestep = int(data[0])
        elif mode == 'NUMBER OF ATOMS':
            natm = int(data[0])
            sids = [0 for i in range(natm)]
            # poss = [ np.zeros(3) for i in range(natm) ]
            # vels = [ np.zeros(3) for i in range(natm) ]
            # frcs = [ np.zeros(3) for i in range(natm) ]
            poss = np.zeros((natm, 3))
            vels = np.zeros((natm, 3))
            frcs = np.zeros((natm, 3))
        elif mode == 'BOX BOUNDS':
            if ixyz == 0:
                xlo_bound = float(data[0])
                xhi_bound = float(data[1])
                if len(data) > 2:
                    xy = float(data[2])
            elif ixyz == 1:
                ylo_bound = float(data[0])
                yhi_bound = float(data[1])
                if len(data) > 2:
                    xz = float(data[2])
            elif ixyz == 2:
                zlo_bound = float(data[0])
                zhi_bound = float(data[1])
                if len(data) > 2:
                    yz = float(data[2])
            ixyz += 1
            if ixyz > 2:
                xlo = xlo_bound - min(0.0, xy, xz, xy + xz)
                xhi = xhi_bound - max(0.0, xy, xz, xy + xz)
                ylo = ylo_bound - min(0.0, yz)
                yhi = yhi_bound - max(0.0, yz)
                zlo = zlo_bound
                zhi = zhi_bound
                #...Original definition of lattice vectors could be different
                #   from this, because the definition in dump format
                #   requires y,z-components of vector a1 to be zero.
                nsys.a1 = np.array([xhi - xlo, 0., 0.], dtype=float)
                nsys.a2 = np.array([xy, yhi - ylo, 0.], dtype=float)
                nsys.a3 = np.array([xz, yz, zhi - zlo], dtype=float)
                hmat = nsys.get_hmat()
                hmati = nsys.get_hmat_inv()
        elif mode == 'ATOMS':
            if iatm < natm:
                symbol = None
                if data[1].isdigit():
                    sid = int(data[1])
                    sids[iatm] = sid
                    symbol = nsys.specorder[sid - 1]
                else:
                    symbol = data[1]
                    if symbol not in nsys.specorder:
                        nsys.specorder.append(symbol)
                    sid = nsys.specorder.index(symbol) + 1
                    sids[iatm] = sid
                r0 = [float(data[ix]), float(data[iy]), float(data[iz])]
                if ivx > 0 and ivy > 0 and ivz > 0:
                    v0 = [float(data[ivx]), float(data[ivy]), float(data[ivz])]
                else:
                    v0 = [0., 0., 0.]
                if ifx > 0 and ify > 0 and ifz > 0:
                    f0 = [float(data[ifx]), float(data[ify]), float(data[ifz])]
                else:
                    f0 = [0., 0., 0.]
                sr = np.dot(hmati, r0)
                sv = np.dot(hmati, v0)
                sr[0] = pbc(sr[0])
                sr[1] = pbc(sr[1])
                sr[2] = pbc(sr[2])
                # poss[iatm][:] = sr[:]
                # vels[iatm][:] = sv[:]
                poss[iatm, :] = sr[:]
                vels[iatm, :] = sv[:]
                frcs[iatm, :] = f0[:]

                if len(aux_names) > 0:
                    # auxs[iatm,:] = [ float(x) for x in data[iauxstart:] ]
                    auxs[iatm, :] = [float(x) for x in data[2:]]

            iatm += 1

    nsys.atoms[['x', 'y', 'z']] = poss
    nsys.atoms[['vx', 'vy', 'vz']] = vels
    nsys.atoms[['fx', 'fy', 'fz']] = frcs
    nsys.atoms['sid'] = sids
    for ia in range(len(aux_names)):
        name = aux_names[ia]
        if name in ('x', 'xu', 'y', 'yu', 'z', 'zu', 'vx', 'vy', 'vz', 'fx',
                    'fy', 'fz'):
            continue
        aux = auxs[:, ia]
        nsys.atoms[name] = aux.tolist()
    f.close()
    return nsys
Exemple #5
0
def make_polycrystal(grns,uc,n1,n2,n3,two_dim=False):
    """
    THIS ROUTINE IS NOT THAT UNIVERSAL.
    Each grain has to have neighboring grains within a supercell,
    otherwise there will be some unexpecting grain boundries.
    In order to do so, the system should be large enough and
    the number of grains should be large enough.
    """
    #...Calc the minimum bond distance in unit cell and use it as penetration depth
    dmin = 1.0e+30
    for i in range(uc.num_atoms()-1):
        for j in range(i+1,uc.num_atoms()):
            dij = uc.get_distance(i,j)
            dmin = min(dij,dmin)
    print(' Minimum bond distance in the unitcell: ',dmin)
    dmin = dmin *DMIN_RATE
    penetration_depth = dmin*2
    print(' Minimum bond distance allowed in the new system: ',dmin)
            
    sv,nsv= shift_vector(two_dim)
    # print(' nsv =',nsv)
    # for i in range(nsv):
    #     print(' i,sv[i]=',i,sv[i])
    nsys= NAPSystem(specorder=uc.specorder)
    nsys.set_lattice(uc.alc,uc.a1*n1,uc.a2*n2,uc.a3*n3)
    hmat = nsys.get_hmat()
    hmati = nsys.get_hmat_inv()
    nmax = n1*n2*n3 *uc.num_atoms()
    sidsl = np.zeros(nmax,dtype=int)
    symsl = []
    possl = np.zeros((nmax,3))
    velsl = np.zeros((nmax,3))
    frcsl = np.zeros((nmax,3))
    ix0 = -n1/2-1
    ix1 =  n1/2+2
    iy0 = -n2/2-1
    iy1 =  n2/2+2
    iz0 = -n3/2-1
    iz1 =  n3/2+2
    if two_dim:
        if n3 != 1:
            raise ValueError('n3 should be 1 in case two_dim is ON.')
        iz0 = 0
        iz1 = 1
    print(' x range = ',ix0,ix1)
    print(' y range = ',iy0,iy1)
    print(' z range = ',iz0,iz1)
    inc = 0
    for ig in range(len(grns)):
        grain= grns[ig]
        rmat= grain.rmat  # Rotation matrix of the grain
        pi= grain.point   # Grain center in reduced coordinate
        api= np.dot(hmat,pi)  # Grain center in Cartessian coordinate
        print(' grain-ID = ',ig+1)
        for ix in range(ix0,ix1):
            # print('ix=',ix)
            for iy in range(iy0,iy1):
                for iz in range(iz0,iz1):
                    for m in range(uc.num_atoms()):
                        sidt = uc.get_atom_attr(m,'sid')
                        rt= np.zeros((3,))
                        pm = uc.get_atom_attr(m,'pos')
                        rt[0]= (pm[0]+ix)/n1
                        rt[1]= (pm[1]+iy)/n2
                        rt[2]= (pm[2]+iz)/n3
                        #...rt to absolute position
                        art= np.dot(hmat,rt)
                        #...Rotate
                        ari= np.dot(rmat,art)
                        #...Shift origin to the grain center
                        ari[0]= ari[0]+api[0]
                        ari[1]= ari[1]+api[1]
                        ari[2]= ari[2]+api[2]
                        #...check distance from all the grain points
                        di= distance(ari,api,two_dim)
                        isOutside= False
                        for jg in range(len(grns)):
                            gj= grns[jg]
                            for isv in range(nsv):
                                pj= gj.point
                                if jg == ig:
                                    if not two_dim and isv == 13:
                                        continue
                                    elif two_dim and isv == 4:
                                        continue
                                svi= sv[isv]
                                pj= pj +svi
                                apj = np.dot(hmat,pj)
                                dj= distance(ari,apj,two_dim)
                                if dj +penetration_depth < di:  # Allow some penetration here
                                    isOutside= True
                                    break
                            if isOutside:
                                break
                        if isOutside:
                            break
                        #...here ri is inside this grain, register it
                        #...Cartessian coord to reduced coord
                        ri = np.dot(hmati,ari)
                        ri[0]= pbc(ri[0])
                        ri[1]= pbc(ri[1])
                        ri[2]= pbc(ri[2])
                        sidsl[inc] = sidt
                        possl[inc] = ri
                        velsl[inc,:] = 0.0
                        frcsl[inc,:] = 0.0
                        symsl.append(nsys.specorder[sidt-1])
                        inc += 1
                        if inc > nmax:
                            raise ValueError('inc > nmax')
    #...Create filled arrays from non-filled ones
    poss = np.array(possl[:inc])
    vels = np.array(velsl[:inc])
    frcs = np.array(frcsl[:inc])
    nsys.add_atoms(symsl,poss,vels,frcs)

    #...remove too-close atoms at the grain boundaries
    print(' Making pair list in order to remove close atoms...')
    print(' Number of atoms: ',nsys.num_atoms())
    nsys.make_pair_list(RCUT)
    nsys.write('POSCAR_orig')
    short_pairs = []
    # dmin2= dmin**2
    # xij= np.zeros((3,))
    print(' Making the list of SHORT pairs...')
    for ia in range(nsys.num_atoms()):
        lst= nsys.get_atom_attr(ia,'lspr')
        for j in range(len(lst)):
            ja= lst[j]
            if ja > ia:
                continue
            dij = nsys.get_distance(ia,ja)
            if dij < dmin:
                short_pairs.append((ia,ja,dij))

    print(' Number of short pairs: ',len(short_pairs))

    #...Remove only relevant atoms, not all the atoms in the short_pairs.
    ls_remove = []
    ls_not_remove = []
    for pair in short_pairs:
        ia = pair[0]
        ja = pair[1]
        if ia not in ls_not_remove and ja not in ls_not_remove:
            ls_remove.append(ia)
            ls_not_remove.append(ja)
        elif ia not in ls_not_remove:
            ls_remove.append(ia)
        elif ja not in ls_not_remove:
            ls_remove.append(ja)
        else:  # Both atoms are already in not_remove list, which should be avoided.
            ls_not_remove.remove(ia)
            ls_remove.append(ia)
            ls_not_remove.append(ja)
    #...Remove double registered IDs
    ls_remove = uniq(ls_remove)
    print(' Number of to be removed atoms: ',len(ls_remove))

    nsys.remove_atoms(*ls_remove)
    return nsys