Exemple #1
0
def make_bcc111(latconst=1.0):
    """
    Make a cell of bcc structure with z along [111].
    """
    s= NAPSystem(specorder=_default_specorder)
    #...lattice
    a1= np.array([ 1.414, 0.0, 0.0 ])
    a2= np.array([ 0.0, 2.449, 0.0 ])
    a3= np.array([ 0.0, 0.0, 1.732 ])
    s.set_lattice(latconst,a1,a2,a3)
    positions=[(0.00, 0.00, 0.00),
               (0.00, 0.00, 0.50),
               (0.00, 0.333, 0.167),
               (0.00, 0.333, 0.667),
               (0.00, 0.667, 0.333),
               (0.00, 0.667, 0.833),
               (0.50, 0.167, 0.333),
               (0.50, 0.167, 0.833),
               (0.50, 0.50, 0.00),
               (0.50, 0.50, 0.50),
               (0.50, 0.833, 0.167),
               (0.50, 0.833, 0.667)]
    for p in positions:
        atom= Atom()
        atom.set_pos(p[0],p[1],p[2])
        atom.set_symbol(_default_specorder[0])
        s.add_atom(atom)
    return s
Exemple #2
0
def make_nacl(latconst=1.0, specorder=None):
    if specorder is None:
        specorder = ['Na', 'Cl']
    if len(specorder) < 2:
        specorder = ['Na', 'Cl']
        print('Since len(specorder) < 2, specorder is reset to ', specorder)

    s = NAPSystem(specorder=specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 1.0, 0.0])
    a3 = np.array([0.0, 0.0, 1.0])
    s.set_lattice(latconst, a1, a2, a3)
    poss = [
        [0.00, 0.00, 0.00],
        [0.50, 0.00, 0.00],
        [0.00, 0.50, 0.00],
        [0.00, 0.00, 0.50],
        [0.50, 0.50, 0.00],
        [0.50, 0.00, 0.50],
        [0.00, 0.50, 0.50],
        [0.50, 0.50, 0.50],
    ]
    symbols = ['Na', 'Cl', 'Cl', 'Cl', 'Na', 'Na', 'Na', 'Cl']
    vels = [[0., 0., 0.] for i in range(len(poss))]
    frcs = [[0., 0., 0.] for i in range(len(poss))]
    s.add_atoms(symbols, poss, vels, frcs)
    return s
Exemple #3
0
def make_nacl(latconst=1.0):
    specorder = ['Na', 'Cl']
    s = NAPSystem(specorder=specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 1.0, 0.0])
    a3 = np.array([0.0, 0.0, 1.0])
    s.set_lattice(latconst, a1, a2, a3)
    positions = [
        (0.00, 0.00, 0.00),
        (0.50, 0.00, 0.00),
        (0.00, 0.50, 0.00),
        (0.00, 0.00, 0.50),
        (0.50, 0.50, 0.00),
        (0.50, 0.00, 0.50),
        (0.00, 0.50, 0.50),
        (0.50, 0.50, 0.50),
    ]
    species = ['Na', 'Cl', 'Cl', 'Cl', 'Na', 'Na', 'Na', 'Cl']
    for i, p in enumerate(positions):
        atom = Atom()
        atom.set_pos(p[0], p[1], p[2])
        atom.set_symbol(species[i])
        s.add_atom(atom)
    return s
Exemple #4
0
def make_zincblend(latconst=1.0, specorder=None):
    """
    Make a cell of diamond structure.
    """
    if specorder is None:
        specorder = ['Ga', 'N']
    if len(specorder) < 2:
        specorder = ['Ga', 'N']
        print('Since len(specorder) < 2, specorder is reset to ', specorder)

    s = NAPSystem(specorder=specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 1.0, 0.0])
    a3 = np.array([0.0, 0.0, 1.0])
    s.set_lattice(latconst, a1, a2, a3)
    poss = [[0.00, 0.00, 0.00], [0.50, 0.50, 0.00], [0.50, 0.00, 0.50],
            [0.00, 0.50, 0.50], [0.25, 0.25, 0.25], [0.75, 0.75, 0.25],
            [0.75, 0.25, 0.75], [0.25, 0.75, 0.75]]
    symbols = [
        specorder[0] if i < 4 else specorder[1] for i in range(len(poss))
    ]
    vels = [[0., 0., 0.] for i in range(len(poss))]
    frcs = [[0., 0., 0.] for i in range(len(poss))]
    s.add_atoms(symbols, poss, vels, frcs)
    return s
Exemple #5
0
def structure2aSys(structure,idoffset=1):
    """
    Converts Structure object of pymatgen to NAPSystem object in nap.

    Args:
        structure (Structure): pymatgen Structure object to be converted
        to NAPSystem object..

    Returns:
        aSys (NAPSystem): 
    """
    lattice= structure.lattice
    alc= 1.0
    a1= np.array(lattice.matrix[0])
    a2= np.array(lattice.matrix[1])
    a3= np.array(lattice.matrix[2])
    #... rescale a? vectors
    a1= a1/alc
    a2= a2/alc
    a3= a3/alc
    aSys= NAPSystem()
    aSys.set_lattice(alc,a1,a2,a3)
    for ia in range(structure.num_sites):
        ai= Atom()
        si= structure[ia]
        crd= si.frac_coords
        ai.set_pos(crd[0],crd[1],crd[2])
        sid= structure.symbol_set.index(si.species_string)+idoffset
        ai.set_sid(sid)
        ai.set_id(ia+1)
        aSys.add_atom(ai)
    return aSys
Exemple #6
0
def xdatcar2poscars(fname='XDATCAR', nskip=1):
    f = open(fname, 'r')

    isys = 0
    while True:
        #....."Direct configuration= #"
        try:
            line = f.readline()
            #...Check configuration
            if not "Direct configuration=" in line:
                alc, a1, a2, a3, species, num_atoms = read_header(f)
                # print(species)
                # print(num_atoms)
                natm = 0
                for n in num_atoms:
                    natm += n
                continue
            elif len(line.split()) == 0:
                break
        except:
            break
        #...Skip reading this configuration if requested
        if not isys % nskip == 0:
            for i in range(natm):
                f.readline()
            isys += 1
            continue
        #...Following lines: atom positions
        #...Make a NAPSystem from these information and write to POSCAR_#####
        nsys = NAPSystem(specorder=species)
        nsys.set_lattice(alc, a1, a2, a3)
        inc = 0
        for inum, ni in enumerate(num_atoms):
            for j in range(ni):
                inc += 1
                ai = Atom()
                ai.set_id(inc)
                ai.set_symbol(species[inum])
                data = f.readline().split()
                # print(data)
                if not is_number(data[0]):
                    raise ValueError('Wrong format?')
                x1, x2, x3 = [float(x) for x in data[0:3]]
                ai.set_pos(x1, x2, x3)
                ai.set_vel(0.0, 0.0, 0.0)
                nsys.add_atom(ai)
        foutname = 'POSCAR_{0:05d}'.format(isys)
        print(' >>> ' + foutname)
        nsys.write_POSCAR(fname=foutname)
        isys += 1
    f.close()
    return None
Exemple #7
0
def xdatcar2poscars(fname='XDATCAR',nskip=1):
    f= open(fname,'r')

    isys = 0
    while True:
        #....."Direct configuration= #"
        try:
            line = f.readline()
            #...Check configuration
            if not "Direct configuration=" in line:
                alc,a1,a2,a3,species,num_atoms = read_header(f)
                # print(species)
                # print(num_atoms)
                natm = 0
                for n in num_atoms:
                    natm += n
                continue
            elif len(line.split()) == 0:
                break
        except:
            break
        #...Skip reading this configuration if requested
        if not isys%nskip == 0:
            for i in range(natm):
                f.readline()
            isys += 1
            continue
        #...Following lines: atom positions
        #...Make a NAPSystem from these information and write to POSCAR_#####
        nsys = NAPSystem(specorder=species)
        nsys.set_lattice(alc,a1,a2,a3)
        inc = 0
        for inum,ni in enumerate(num_atoms):
            for j in range(ni):
                inc += 1
                ai = Atom()
                ai.set_id(inc)
                ai.set_symbol(species[inum])
                data= f.readline().split()
                # print(data)
                if not is_number(data[0]):
                    raise ValueError('Wrong format?')
                x1,x2,x3 = [ float(x) for x in data[0:3] ]
                ai.set_pos(x1,x2,x3)
                ai.set_vel(0.0,0.0,0.0)
                nsys.add_atom(ai)
        foutname = 'POSCAR_{0:05d}'.format(isys)
        print(' >>> '+foutname)
        nsys.write_POSCAR(fname=foutname)
        isys += 1
    f.close()
    return None
Exemple #8
0
def make_wurtzite(latconst=1.0, specorder=None, celltype='conventional'):
    """
    Make a cell of wurtzite structure.

    - celltype: conventional or primitive
    """
    if specorder is None:
        specorder = ['Ga', 'N']
    if len(specorder) < 2:
        specorder = ['Ga', 'N']
        print('Since len(specorder) < 2, specorder is reset to ', specorder)

    s = NAPSystem(specorder=specorder)
    if celltype[0] == 'c':
        #...conventional cell
        a1 = np.array([1.00, 0.00, 0.00])
        a2 = np.array([0.00, np.sqrt(3.0), 0.00])
        a3 = np.array([0.00, 0.00, 1.633])
        s.set_lattice(latconst, a1, a2, a3)
        poss = [
            [0.00, 0.00, 0.00],
            [0.50, 0.50, 0.00],
            [0.50, 0.5 / 3, 0.50],
            [0.00, 0.5 / 3 + 0.5, 0.50],
            [0.50, 0.5 / 3, 0.125],
            [0.00, 0.5 / 3 + 0.5, 0.125],
            [0.00, 0.00, 0.625],
            [0.50, 0.50, 0.625],
        ]
        symbols = [
            specorder[0] if i < 4 else specorder[1] for i in range(len(poss))
        ]
    elif cenlltype[0] == 'p':
        #...primitive cell
        a1 = np.array([1.0, 0.0, 0.0])
        a2 = np.array([-0.5, np.sqrt(3.0) / 2, 0.0])
        a3 = np.array([0.0, 0.0, 1.633])
        s.set_lattice(latconst, a1, a2, a3)
        poss = [
            [0.00, 0.00, 0.00],
            [2.0 / 3, 1.0 / 3, 0.125],
            [2.0 / 3, 1.0 / 3, 0.50],
            [0.00, 0.00, 0.625],
        ]
        symbols = [
            specorder[0] if i < 2 else specorder[1] for i in range(len(poss))
        ]
    vels = [[0., 0., 0.] for i in range(len(poss))]
    frcs = [[0., 0., 0.] for i in range(len(poss))]
    s.add_atoms(symbols, poss, vels, frcs)
    return s
Exemple #9
0
def make_sc(latconst=1.0):
    """
    Make a cell of simple cubic structure.
    """
    s = NAPSystem(specorder=_default_specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 1.0, 0.0])
    a3 = np.array([0.0, 0.0, 1.0])
    s.set_lattice(latconst, a1, a2, a3)
    p = [0.00, 0.00, 0.00]
    atom = Atom()
    atom.set_pos(p[0], p[1], p[2])
    atom.set_symbol(_default_specorder[0])
    s.add_atom(atom)
    return s
Exemple #10
0
def make_sc(latconst=1.0):
    """
    Make a cell of simple cubic structure.
    """
    s= NAPSystem(specorder=_default_specorder)
    #...lattice
    a1= np.array([ 1.0, 0.0, 0.0 ])
    a2= np.array([ 0.0, 1.0, 0.0 ])
    a3= np.array([ 0.0, 0.0, 1.0 ])
    s.set_lattice(latconst,a1,a2,a3)
    p=[0.00, 0.00, 0.00]
    atom= Atom()
    atom.set_pos(p[0],p[1],p[2])
    atom.set_symbol(_default_specorder[0])
    s.add_atom(atom)
    return s
Exemple #11
0
def make_hcp(latconst=1.0):
    """
    Make a cell of hcp structure.
    """
    s = NAPSystem(specorder=_default_specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([-0.5, np.sqrt(3.0) / 2, 0.0])
    a3 = np.array([0.0, 0.0, 1.633])
    s.set_lattice(latconst, a1, a2, a3)
    poss = [[0.00, 0.00, 0.00], [1.0 / 3, 2.0 / 3, 0.50]]
    symbol = _default_specorder[0]
    symbols = [symbol for i in range(len(poss))]
    vels = [[0., 0., 0.] for i in range(len(poss))]
    frcs = [[0., 0., 0.] for i in range(len(poss))]
    s.add_atoms(symbols, poss, vels, frcs)
    return s
Exemple #12
0
def make_bcc(latconst=1.0, specorder=_default_specorder):
    """
    Make a cell of bcc structure with z along [001].
    """
    s = NAPSystem(specorder=specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 1.0, 0.0])
    a3 = np.array([0.0, 0.0, 1.0])
    s.set_lattice(latconst, a1, a2, a3)
    positions = [(0.00, 0.00, 0.00), (0.50, 0.50, 0.50)]
    for p in positions:
        atom = Atom()
        atom.set_pos(p[0], p[1], p[2])
        atom.set_symbol(specorder[0])
        s.add_atom(atom)
    return s
Exemple #13
0
def make_sc(latconst=1.0):
    """
    Make a cell of simple cubic structure.
    """
    s = NAPSystem(specorder=_default_specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 1.0, 0.0])
    a3 = np.array([0.0, 0.0, 1.0])
    s.set_lattice(latconst, a1, a2, a3)
    symbol = _default_specorder[0]
    symbols = [symbol]
    poss = [[0.00, 0.00, 0.00]]
    vels = [[0., 0., 0.]]
    frcs = [[0., 0., 0.]]
    s.add_atoms(symbols, poss, vels, frcs)
    return s
Exemple #14
0
def make_hcp(latconst=1.0):
    """
    Make a cell of hcp structure.
    """
    s = NAPSystem(specorder=_default_specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([-0.5, np.sqrt(3.0) / 2, 0.0])
    a3 = np.array([0.0, 0.0, 1.633])
    s.set_lattice(latconst, a1, a2, a3)
    positions = [(0.00, 0.00, 0.00), (1.0 / 3, 2.0 / 3, 0.50)]
    for p in positions:
        atom = Atom()
        atom.set_pos(p[0], p[1], p[2])
        atom.set_symbol(_default_specorder[0])
        s.add_atom(atom)
    return s
Exemple #15
0
def make_honeycomb(latconst=1.0):
    """
    Make a cell of 2D honeycomb structure.
    """
    s = NAPSystem(specorder=_default_specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 1.5, 0.0])
    a3 = np.array([0.0, 0.0, np.sqrt(3.0)])
    s.set_lattice(latconst, a1, a2, a3)
    positions = [(0.00, 0.50, 0.00), (0.50, 0.50, 1. / 6), (0.50, 0.50, 0.50),
                 (0.00, 0.50, 0.5 + 1.0 / 6)]
    for p in positions:
        atom = Atom()
        atom.set_pos(p[0], p[1], p[2])
        atom.set_symbol(_default_specorder[0])
        s.add_atom(atom)
    return s
Exemple #16
0
def make_bcc(latconst=1.0,specorder=_default_specorder):
    """
    Make a cell of bcc structure with z along [001].
    """
    s= NAPSystem(specorder=specorder)
    #...lattice
    a1= np.array([ 1.0, 0.0, 0.0 ])
    a2= np.array([ 0.0, 1.0, 0.0 ])
    a3= np.array([ 0.0, 0.0, 1.0 ])
    s.set_lattice(latconst,a1,a2,a3)
    positions=[(0.00, 0.00, 0.00),
               (0.50, 0.50, 0.50)]
    for p in positions:
        atom= Atom()
        atom.set_pos(p[0],p[1],p[2])
        atom.set_symbol(specorder[0])
        s.add_atom(atom)
    return s
Exemple #17
0
def make_bcc110(latconst=1.0):
    """                                                  
    Make a cell of bcc structure with z along [110].
    """
    s = NAPSystem(specorder=_default_specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 1.414, 0.0])
    a3 = np.array([0.0, 0.0, 1.414])
    s.set_lattice(latconst, a1, a2, a3)
    symbol = _default_specorder[0]
    symbols = [symbol, symbol, symbol, symbol]
    poss = [[0.00, 0.00, 0.00], [0.00, 0.50, 0.50], [0.50, 0.50, 0.00],
            [0.50, 0.00, 0.50]]
    vels = [[0., 0., 0.] for i in range(4)]
    frcs = [[0., 0., 0.] for i in range(4)]
    s.add_atoms(symbols, poss, vels, frcs)
    return s
Exemple #18
0
def make_hcp(latconst=1.0):
    """
    Make a cell of hcp structure.
    """
    s= NAPSystem(specorder=_default_specorder)
    #...lattice
    a1= np.array([ 1.0, 0.0, 0.0 ])
    a2= np.array([-0.5, np.sqrt(3.0)/2, 0.0 ])
    a3= np.array([ 0.0, 0.0, 1.633 ])
    s.set_lattice(latconst,a1,a2,a3)
    positions=[(0.00, 0.00, 0.00),
               (1.0/3, 2.0/3, 0.50)]
    for p in positions:
        atom= Atom()
        atom.set_pos(p[0],p[1],p[2])
        atom.set_symbol(_default_specorder[0])
        s.add_atom(atom)
    return s
Exemple #19
0
def make_sc(latconst=1.0, specorder=None):
    """
    Make a cell of simple cubic structure.
    """
    if specorder is None:
        raise ValueError('specorder must be given.')
    s = NAPSystem(specorder=specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 1.0, 0.0])
    a3 = np.array([0.0, 0.0, 1.0])
    s.set_lattice(latconst, a1, a2, a3)
    symbols = [specorder[0]]
    poss = [[0.00, 0.00, 0.00]]
    vels = [[0., 0., 0.]]
    frcs = [[0., 0., 0.]]
    s.add_atoms(symbols, poss, vels, frcs)
    return s
Exemple #20
0
def make_diamond(latconst=1.0):
    """
    Make a cell of diamond structure.
    """
    s = NAPSystem(specorder=_default_specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 1.0, 0.0])
    a3 = np.array([0.0, 0.0, 1.0])
    s.set_lattice(latconst, a1, a2, a3)
    poss = [[0.00, 0.00, 0.00], [0.50, 0.50, 0.00], [0.50, 0.00, 0.50],
            [0.00, 0.50, 0.50], [0.25, 0.25, 0.25], [0.75, 0.75, 0.25],
            [0.75, 0.25, 0.75], [0.25, 0.75, 0.75]]
    symbol = _default_specorder[0]
    symbols = [symbol for i in range(len(poss))]
    vels = [[0., 0., 0.] for i in range(len(poss))]
    frcs = [[0., 0., 0.] for i in range(len(poss))]
    s.add_atoms(symbols, poss, vels, frcs)
    return s
Exemple #21
0
def make_diamond(latconst=1.0):
    """
    Make a cell of diamond structure.
    """
    s = NAPSystem(specorder=_default_specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 1.0, 0.0])
    a3 = np.array([0.0, 0.0, 1.0])
    s.set_lattice(latconst, a1, a2, a3)
    positions = [(0.00, 0.00, 0.00), (0.50, 0.50, 0.00), (0.50, 0.00, 0.50),
                 (0.00, 0.50, 0.50), (0.25, 0.25, 0.25), (0.75, 0.75, 0.25),
                 (0.75, 0.25, 0.75), (0.25, 0.75, 0.75)]
    for p in positions:
        atom = Atom()
        atom.set_pos(p[0], p[1], p[2])
        atom.set_symbol(_default_specorder[0])
        s.add_atom(atom)
    return s
Exemple #22
0
def make_bcc(latconst=1.0, specorder=None):
    """
    Make a cell of bcc structure with z along [001].
    """
    if specorder is None:
        specorder = ['Fe']
    s = NAPSystem(specorder=specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 1.0, 0.0])
    a3 = np.array([0.0, 0.0, 1.0])
    s.set_lattice(latconst, a1, a2, a3)
    poss = [[0.00, 0.00, 0.00], [0.50, 0.50, 0.50]]
    symbol = _default_specorder[0]
    symbols = [symbol for i in range(len(poss))]
    vels = [[0., 0., 0.] for i in range(len(poss))]
    frcs = [[0., 0., 0.] for i in range(len(poss))]
    s.add_atoms(symbols, poss, vels, frcs)
    return s
Exemple #23
0
def make_bcc111(latconst=1.0):
    """
    Make a cell of bcc structure with z along [111].
    """
    s = NAPSystem(specorder=_default_specorder)
    #...lattice
    a1 = np.array([1.414, 0.0, 0.0])
    a2 = np.array([0.0, 2.449, 0.0])
    a3 = np.array([0.0, 0.0, 1.732])
    s.set_lattice(latconst, a1, a2, a3)
    symbol = _default_specorder[0]
    poss = [[0.00, 0.00, 0.00], [0.00, 0.00, 0.50], [0.00, 0.333, 0.167],
            [0.00, 0.333, 0.667], [0.00, 0.667, 0.333], [0.00, 0.667, 0.833],
            [0.50, 0.167, 0.333], [0.50, 0.167, 0.833], [0.50, 0.50, 0.00],
            [0.50, 0.50, 0.50], [0.50, 0.833, 0.167], [0.50, 0.833, 0.667]]
    symbols = [symbol for i in range(len(poss))]
    vels = [[0., 0., 0.] for i in range(len(poss))]
    frcs = [[0., 0., 0.] for i in range(len(poss))]
    s.add_atoms(symbols, poss, vels, frcs)
    return s
Exemple #24
0
def make_honeycomb(latconst=1.0):
    """
    Make a cell of 2D honeycomb structure.
    """
    s= NAPSystem(specorder=_default_specorder)
    #...lattice
    a1= np.array([ 1.0, 0.0, 0.0 ])
    a2= np.array([ 0.0, 1.5, 0.0 ])
    a3= np.array([ 0.0, 0.0, np.sqrt(3.0) ])
    s.set_lattice(latconst,a1,a2,a3)
    positions=[(0.00, 0.50, 0.00),
               (0.50, 0.50, 1./6),
               (0.50, 0.50, 0.50),
               (0.00, 0.50, 0.5 +1.0/6)]
    for p in positions:
        atom= Atom()
        atom.set_pos(p[0],p[1],p[2])
        atom.set_symbol(_default_specorder[0])
        s.add_atom(atom)
    return s
Exemple #25
0
def make_bcc111(latconst=1.0):
    """
    Make a cell of bcc structure with z along [111].
    """
    s = NAPSystem(specorder=_default_specorder)
    #...lattice
    a1 = np.array([1.414, 0.0, 0.0])
    a2 = np.array([0.0, 2.449, 0.0])
    a3 = np.array([0.0, 0.0, 1.732])
    s.set_lattice(latconst, a1, a2, a3)
    positions = [(0.00, 0.00, 0.00), (0.00, 0.00, 0.50), (0.00, 0.333, 0.167),
                 (0.00, 0.333, 0.667), (0.00, 0.667, 0.333),
                 (0.00, 0.667, 0.833), (0.50, 0.167, 0.333),
                 (0.50, 0.167, 0.833), (0.50, 0.50, 0.00), (0.50, 0.50, 0.50),
                 (0.50, 0.833, 0.167), (0.50, 0.833, 0.667)]
    for p in positions:
        atom = Atom()
        atom.set_pos(p[0], p[1], p[2])
        atom.set_symbol(_default_specorder[0])
        s.add_atom(atom)
    return s
Exemple #26
0
def doc_to_pos(doc, conf):
    """
    Make a pos file, which has pmd format, from a document in MongoDB.
    """
    psys = NAPSystem()
    matrix = doc['calculations'][-1]['output']['crystal']['lattice']['matrix']
    a1 = matrix[0]
    a2 = matrix[1]
    a3 = matrix[2]
    psys.set_lattice(1.0, a1, a2, a3)

    species_ids = conf['species_ids']

    sites = doc['calculations'][-1]['output']['crystal']['sites']
    for site in sites:
        ra = site['abc']
        ai = Atom()
        ai.set_pos(ra[0], ra[1], ra[2])
        ai.set_sid(species_ids[site['species'][0]['element']])
        psys.add_atom(ai)
    return psys
Exemple #27
0
def make_2D_triangle(latconst=3.8, size=(1, 1, 1)):
    """
    Make 2D triangle lattice on x-z plane. 
    Note that it is not x-y plane.
    """
    specorder = ['Ar']
    s = NAPSystem(specorder=specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 10.0, 0.0])
    a3 = np.array([0.0, 0.0, np.sqrt(3.0)])
    s.set_lattice(latconst, a1, a2, a3)
    poss = [[0.00, 0.50, 0.00], [0.50, 0.50, 0.50]]
    symbol = _default_specorder[0]
    symbols = [symbol for i in range(len(poss))]
    vels = [[0., 0., 0.] for i in range(len(poss))]
    frcs = [[0., 0., 0.] for i in range(len(poss))]
    s.add_atoms(symbols, poss, vels, frcs)

    s.repeat(*size)
    s.add_vacuum(2. * latconst, 0.0, 10. * latconst * np.sqrt(3))
    return s
Exemple #28
0
def make_dimer(distance, latconst, spcs):
    if distance > latconst / 2:
        raise ValueError('Lattice size is too small for given distance.')
    s = NAPSystem(specorder=spcs)
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 1.0, 0.0])
    a3 = np.array([0.0, 0.0, 1.0])
    s.set_lattice(latconst, a1, a2, a3)
    pos = [(0.0, 0.0, 0.0), (distance / latconst, 0.0, 0.0)]
    #...Atom 1
    atom = Atom()
    p = pos[0]
    atom.set_pos(p[0], p[1], p[2])
    atom.set_symbol(spcs[0])
    s.add_atom(atom)
    #...Atom 2
    atom = Atom()
    p = pos[1]
    atom.set_pos(p[0], p[1], p[2])
    atom.set_symbol(spcs[1])
    s.add_atom(atom)
    return s
Exemple #29
0
def make_2D_triangle(latconst=3.8, size=(1, 1, 1)):
    """
    Make 2D triangle lattice on x-z plane. 
    Note that it is not x-y plane.
    """
    specorder = ['Ar']
    s = NAPSystem(specorder=specorder)
    #...lattice
    a1 = np.array([1.0, 0.0, 0.0])
    a2 = np.array([0.0, 10.0, 0.0])
    a3 = np.array([0.0, 0.0, np.sqrt(3.0)])
    s.set_lattice(latconst, a1, a2, a3)
    positions = [(0.00, 0.50, 0.00), (0.50, 0.50, 0.50)]
    for p in positions:
        atom = Atom()
        atom.set_pos(p[0], p[1], p[2])
        atom.set_symbol(specorder[0])
        s.add_atom(atom)

    s.repeat(*size)
    s.add_vacuum(2. * latconst, 0.0, 10. * latconst * np.sqrt(3))
    return s
Exemple #30
0
def make_2D_triangle(latconst=3.8,size=(1,1,1)):
    """
    Make 2D triangle lattice on x-z plane. 
    Note that it is not x-y plane.
    """
    specorder = ['Ar']
    s = NAPSystem(specorder=specorder)
    #...lattice
    a1= np.array([ 1.0,  0.0, 0.0 ])
    a2= np.array([ 0.0, 10.0, 0.0 ])
    a3= np.array([ 0.0,  0.0, np.sqrt(3.0) ])
    s.set_lattice(latconst,a1,a2,a3)
    positions=[(0.00, 0.50, 0.00),
               (0.50, 0.50, 0.50)]
    for p in positions:
        atom= Atom()
        atom.set_pos(p[0],p[1],p[2])
        atom.set_symbol(specorder[0])
        s.add_atom(atom)
    
    s.repeat(*size)
    s.add_vacuum(2.*latconst, 0.0, 10.*latconst*np.sqrt(3))
    return s
Exemple #31
0
def make_dimer(distance,latconst,spcs):
    if distance > latconst/2:
        raise ValueError('Lattice size is too small for given distance.')
    s = NAPSystem(specorder=spcs)
    a1= np.array([ 1.0, 0.0, 0.0 ])
    a2= np.array([ 0.0, 1.0, 0.0 ])
    a3= np.array([ 0.0, 0.0, 1.0 ])
    s.set_lattice(latconst,a1,a2,a3)
    pos=[(0.0, 0.0, 0.0),
         (distance/latconst, 0.0, 0.0)]
    #...Atom 1
    atom = Atom()
    p = pos[0]
    atom.set_pos(p[0],p[1],p[2])
    atom.set_symbol(spcs[0])
    s.add_atom(atom)
    #...Atom 2
    atom = Atom()
    p = pos[1]
    atom.set_pos(p[0],p[1],p[2])
    atom.set_symbol(spcs[1])
    s.add_atom(atom)
    return s
Exemple #32
0
def make_nacl(latconst=1.0):
    specorder = ['Na','Cl']
    s = NAPSystem(specorder=specorder)
    #...lattice
    a1= np.array([ 1.0, 0.0, 0.0 ])
    a2= np.array([ 0.0, 1.0, 0.0 ])
    a3= np.array([ 0.0, 0.0, 1.0 ])
    s.set_lattice(latconst,a1,a2,a3)
    positions=[(0.00, 0.00, 0.00),
               (0.50, 0.00, 0.00),
               (0.00, 0.50, 0.00),
               (0.00, 0.00, 0.50),
               (0.50, 0.50, 0.00),
               (0.50, 0.00, 0.50),
               (0.00, 0.50, 0.50),
               (0.50, 0.50, 0.50),]
    species = ['Na','Cl','Cl','Cl','Na','Na','Na','Cl']
    for i,p in enumerate(positions):
        atom= Atom()
        atom.set_pos(p[0],p[1],p[2])
        atom.set_symbol(species[i])
        s.add_atom(atom)
    return s
Exemple #33
0
def make_diamond(latconst=1.0):
    """
    Make a cell of diamond structure.
    """
    s= NAPSystem(specorder=_default_specorder)
    #...lattice
    a1= np.array([ 1.0, 0.0, 0.0 ])
    a2= np.array([ 0.0, 1.0, 0.0 ])
    a3= np.array([ 0.0, 0.0, 1.0 ])
    s.set_lattice(latconst,a1,a2,a3)
    positions=[(0.00, 0.00, 0.00),
               (0.50, 0.50, 0.00),
               (0.50, 0.00, 0.50),
               (0.00, 0.50, 0.50),
               (0.25, 0.25, 0.25),
               (0.75, 0.75, 0.25),
               (0.75, 0.25, 0.75),
               (0.25, 0.75, 0.75)]
    for p in positions:
        atom= Atom()
        atom.set_pos(p[0],p[1],p[2])
        atom.set_symbol(_default_specorder[0])
        s.add_atom(atom)
    return s
Exemple #34
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
Exemple #35
0
def to_given_vector(infile,specorder,a1new,a2new,a3new):
    psys = NAPSystem(fname=infile,specorder=specorder)
    psys.assign_pbc()
    psys.a1 = psys.a1 *psys.alc
    psys.a2 = psys.a2 *psys.alc
    psys.a3 = psys.a3 *psys.alc
    psys.alc = 1.0
    print('a1  = ',psys.a1)
    print('a2  = ',psys.a2)
    print('a3  = ',psys.a3)
    
    pos = psys.get_real_positions()
    spos = psys.get_scaled_positions()
    for i in range(min(len(psys.atoms),10)):
        a = psys.atoms[i]
        print('{0:5d} {1:s}'.format(a.id,a.symbol)
              +' {0:12.5f} {1:12.5f} {2:12.5f}'.format(spos[i,0],
                                                       spos[i,1],
                                                       spos[i,2])
              +' {0:12.5f} {1:12.5f} {2:12.5f}'.format(pos[i,0],
                                                       pos[i,1],
                                                       pos[i,2]))
    
    # print(psys.get_scaled_positions())
    # print(psys.get_real_positions())
    # sa1new = np.zeros(3,dtype=float)
    # sa2new = np.zeros(3,dtype=float)
    # sa3new = np.zeros(3,dtype=float)
    #tmp = raw_input('Input new a1 vector: ')
    #a1new[:] = [ float(x) for x in tmp.split(',') ]
    # sa1new[:] = [ 0.5, 0.5, 0.0]
    #tmp = raw_input('Input new a2 vector: ')
    #a2new[:] = [ float(x) for x in tmp.split(',') ]
    # sa2new[:] = [ 0.0, 1.0, 0.0 ]
    #tmp = raw_input('Input new a3 vector: ')
    #a3new[:] = [ float(x) for x in tmp.split(',') ]
    # sa3new[:] = [ 0.5, 0.5, 1.0 ]
    hmat = psys.get_hmat()
    a1new = np.dot(hmat,sa1new)
    a2new = np.dot(hmat,sa2new)
    a3new = np.dot(hmat,sa3new)
    print('new a1 in hmat_orig =',sa1new)
    print('new a2 in hmat_orig =',sa2new)
    print('new a3 in hmat_orig =',sa3new)
    print('new a1 =',a1new)
    print('new a2 =',a2new)
    print('new a3 =',a3new)
    psnew = NAPSystem(specorder=specorder)
    psnew.set_lattice(psys.alc,a1new,a2new,a3new)

    # Expand the original system for the search of atoms to be included 
    # in the new system.
    # First, compute how much we have to expand the original system
    hi = np.linalg.inv(hmat)
    icsa1new = [0,0,0]
    icsa2new = [0,0,0]
    icsa3new = [0,0,0]
    for i in range(3):
        if sa1new[i] < 0.0:
            icsa1new[i] = int(sa1new[i]-1.0)
        else:
            icsa1new[i] = int(sa1new[i]+1.0)
        if sa2new[i] < 0.0: 
            icsa2new[i] = int(sa2new[i]-1.0) 
        else:
            icsa2new[i] = int(sa2new[i]+1.0)
        if sa3new[i] < 0.0:
            icsa3new[i] = int(sa3new[i]-1.0) 
        else:
            icsa3new[i] = int(sa3new[i]+1.0)
    print(icsa1new)
    print(icsa2new)
    print(icsa3new)
    for i in range(3):
        if icsa1new[i] == 0:
            raise RuntimeError('icsa1new[i] == 0')
        if icsa2new[i] == 0:
            raise RuntimeError('icsa2new[i] == 0')
        if icsa3new[i] == 0:
            raise RuntimeError('icsa3new[i] == 0')
    irange1 = (min(icsa1new[0],icsa2new[0],icsa3new[0]),
               max(icsa1new[0],icsa2new[0],icsa3new[0]))
    irange2 = (min(icsa1new[1],icsa2new[1],icsa3new[1]),
               max(icsa1new[1],icsa2new[1],icsa3new[1]))
    irange3 = (min(icsa1new[2],icsa2new[2],icsa3new[2]),
               max(icsa1new[2],icsa2new[2],icsa3new[2]))

    print('irange1: ',irange1)
    print('irange2: ',irange2)
    print('irange3: ',irange3)
    expos = []
    symbols = psys.get_symbols()
    print('symbols :',symbols)
    exsymbols = []
    print('Expanding the original system...')
    for n3 in range(min(0,irange3[0]),irange3[1]):
        for n2 in range(min(0,irange2[0]),irange2[1]):
            for n1 in range(min(0,irange1[0]),irange1[1]):
                for ia in range(len(spos)):
                    sposi = copy.deepcopy(spos[ia])
                    sposi[0] += n1
                    sposi[1] += n2
                    sposi[2] += n3
                    posi = np.dot(hmat,sposi)
                    symbol = symbols[ia]
                    # print(ia,n1,n2,n3,symbol,sposi)
                    expos.append(posi)
                    exsymbols.append(symbol)

    print('Extracting the atoms inside the new unit vectors...')
    hmat= psnew.get_hmat()
    hi = np.linalg.inv(hmat)
    for ia,posi in enumerate(expos):
        sposi = np.dot(hi,posi)
        if 0.0 <= sposi[0] < 1.0 and \
           0.0 <= sposi[1] < 1.0 and \
           0.0 <= sposi[2] < 1.0:
            atom = Atom()
            symbol = exsymbols[ia]
            print('{0:5d} {1:s}'.format(ia,symbol)
                  +' {0:12.5f} {1:12.5f} {2:12.5f}'.format(sposi[0],
                                                           sposi[1],
                                                           sposi[2]))
            
            atom.set_symbol(symbol)
            atom.set_pos(sposi[0],sposi[1],sposi[2])
            psnew.add_atom(atom)
            
    tmp = None
    #tmp = raw_input('Input periodic shift vector if you want: ')
    tmp = ' 0.5, 0.0, 0.5'
    if tmp:
        shift = [ float(x) for x in tmp.split(',')]
        for a in psnew.atoms:
            a.pos[0] += shift[0]
            a.pos[1] += shift[1]
            a.pos[2] += shift[2]
        psnew.assign_pbc()
    psnew.write_POSCAR(infile+'.new')
    print('Check '+infile+'.new')
Exemple #36
0
        pi[1]= random()
        if two_dim:
            pi[2]= 0.0
            ai[0]= 0.0
            ai[1]= 0.0
            ai[2]= random()*np.pi*2 -np.pi
        else:
            pi[2]= random()
            ai[0]= random()*np.pi*2 -np.pi
            ai[1]= random()*np.pi/2 -np.pi/2
            ai[2]= random()*np.pi*2 -np.pi
        print(' point,angle =',pi,ai)
        gi= Grain(pi,ai)
        grains.append(gi)
    uc= makestruct(latconst)
    uc.write('POSCAR_uc')
    gsys = NAPSystem(specorder=['H'])
    gsys.set_lattice(uc.alc, uc.a1*nx, uc.a2*ny, uc.a3*nz)
    for g in grains:
        pi = g.point
        a = Atom()
        a.set_pos(pi[0],pi[1],pi[2])
        a.set_symbol('H')
        gsys.add_atom(a)
    gsys.write('POSCAR_gpoints')
    system= make_polycrystal(grains,uc,nx,ny,nz,two_dim)
    system.write(ofname)

    print(' Elapsed time = {0:12.2f}'.format(time.time()-t0))
    print(' Wrote a file: {0:s}'.format(ofname))
Exemple #37
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])
    system= NAPSystem(specorder=uc.specorder)
    system.set_lattice(uc.alc,uc.a1*n1,uc.a2*n2,uc.a3*n3)
    hmat= np.zeros((3,3))
    hmat[0]= system.a1 *system.alc
    hmat[1]= system.a2 *system.alc
    hmat[2]= system.a3 *system.alc
    hmati= np.linalg.inv(hmat)
    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)
    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(len(uc.atoms)):
                        rt= np.zeros((3,))
                        rt[0]= (uc.atoms[m].pos[0]+ix)/n1
                        rt[1]= (uc.atoms[m].pos[1]+iy)/n2
                        rt[2]= (uc.atoms[m].pos[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
                        atom= Atom()
                        #...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])
                        atom.set_pos(ri[0],ri[1],ri[2])
                        atom.set_symbol(uc.atoms[m].symbol)
                        system.add_atom(atom)

    #...remove too-close atoms at the grain boundaries
    print(' Making pair list in order to remove close atoms...')
    print(' Number of atoms: ',system.num_atoms())
    system.make_pair_list(RCUT)
    system.write('POSCAR_orig')
    short_pairs = []
    # dmin2= dmin**2
    # xij= np.zeros((3,))
    print(' Making the list of SHORT pairs...')
    for ia in range(system.num_atoms()):
        # ai= system.atoms[ia]
        # pi= ai.pos
        nlst= system.nlspr[ia]
        lst= system.lspr[ia]
        for j in range(nlst):
            ja= lst[j]
            if ja > ia:
                continue
            dij = system.get_distance(ia,ja)
            if dij < dmin:
                short_pairs.append((ia,ja,dij))
            # aj= system.atoms[ja]
            # pj= aj.pos
            # xij[0]= pj[0]-pi[0] -anint(pj[0]-pi[0])
            # xij[1]= pj[1]-pi[1] -anint(pj[1]-pi[1])
            # xij[2]= pj[2]-pi[2] -anint(pj[2]-pi[2])
            # xij= np.dot(hmat,xij)
            # d2= xij[0]**2 +xij[1]**2 +xij[2]**2
            # if d2 < dmin2:
            #     if not ia in ls_remove:
            #         ls_remove.append(ia)
            #     elif not ja in ls_remove:
            #         ls_remove.append(ja)
        # print('ia,len(ls_remove)=',ia,len(ls_remove))

    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))
            
    # print(' Number of to be removed atoms: ',len(ls_remove))
    #...one of two will survive
    # print(' One of two too-close atoms will survive...')
    # count= [ ls_remove.count(ls_remove[i]) for i in range(len(ls_remove))]
    # for i in range(0,len(ls_remove),2):
    #     if count[i] > count[i+1]:
    #         ls_remove[i+1]= -1
    #     elif count[i] < count[i+1]:
    #         ls_remove[i]= -1
    #     else:
    #         n= int(random()*2.0) # 0 or 1
    #         ls_remove[i+n]= -1
    ls_remove.sort()
    # for ia in range(len(ls_remove)-1,-1,-1):
    #     n= ls_remove[ia]
    #     if ia != len(ls_remove)-1:
    #         if n == nprev: continue
    #     system.atoms.pop(n)
    #     nprev= n
    for i in reversed(range(len(ls_remove))):
        ia = ls_remove[i]
        system.atoms.pop(ia)
    return system
        pi[1] = random()
        if two_dim:
            pi[2] = 0.0
            ai[0] = 0.0
            ai[1] = 0.0
            ai[2] = random() * np.pi * 2 - np.pi
        else:
            pi[2] = random()
            ai[0] = random() * np.pi * 2 - np.pi
            ai[1] = random() * np.pi / 2 - np.pi / 2
            ai[2] = random() * np.pi * 2 - np.pi
        print(' point,angle =', pi, ai)
        gi = Grain(pi, ai)
        grains.append(gi)
    uc = makestruct(latconst)
    uc.write('POSCAR_uc')
    gsys = NAPSystem(specorder=['H'])
    gsys.set_lattice(uc.alc, uc.a1 * nx, uc.a2 * ny, uc.a3 * nz)
    for g in grains:
        pi = g.point
        a = Atom()
        a.set_pos(pi[0], pi[1], pi[2])
        a.set_symbol('H')
        gsys.add_atom(a)
    gsys.write('POSCAR_gpoints')
    system = make_polycrystal(grains, uc, nx, ny, nz, two_dim)
    system.write(ofname)

    print(' Elapsed time = {0:12.2f}'.format(time.time() - t0))
    print(' Wrote a file: {0:s}'.format(ofname))
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])
    system = NAPSystem(specorder=uc.specorder)
    system.set_lattice(uc.alc, uc.a1 * n1, uc.a2 * n2, uc.a3 * n3)
    hmat = np.zeros((3, 3))
    hmat[0] = system.a1 * system.alc
    hmat[1] = system.a2 * system.alc
    hmat[2] = system.a3 * system.alc
    hmati = np.linalg.inv(hmat)
    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)
    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(len(uc.atoms)):
                        rt = np.zeros((3, ))
                        rt[0] = (uc.atoms[m].pos[0] + ix) / n1
                        rt[1] = (uc.atoms[m].pos[1] + iy) / n2
                        rt[2] = (uc.atoms[m].pos[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
                        atom = Atom()
                        #...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])
                        atom.set_pos(ri[0], ri[1], ri[2])
                        atom.set_symbol(uc.atoms[m].symbol)
                        system.add_atom(atom)

    #...remove too-close atoms at the grain boundaries
    print(' Making pair list in order to remove close atoms...')
    print(' Number of atoms: ', system.num_atoms())
    system.make_pair_list(RCUT)
    system.write('POSCAR_orig')
    short_pairs = []
    # dmin2= dmin**2
    # xij= np.zeros((3,))
    print(' Making the list of SHORT pairs...')
    for ia in range(system.num_atoms()):
        # ai= system.atoms[ia]
        # pi= ai.pos
        nlst = system.nlspr[ia]
        lst = system.lspr[ia]
        for j in range(nlst):
            ja = lst[j]
            if ja > ia:
                continue
            dij = system.get_distance(ia, ja)
            if dij < dmin:
                short_pairs.append((ia, ja, dij))
            # aj= system.atoms[ja]
            # pj= aj.pos
            # xij[0]= pj[0]-pi[0] -anint(pj[0]-pi[0])
            # xij[1]= pj[1]-pi[1] -anint(pj[1]-pi[1])
            # xij[2]= pj[2]-pi[2] -anint(pj[2]-pi[2])
            # xij= np.dot(hmat,xij)
            # d2= xij[0]**2 +xij[1]**2 +xij[2]**2
            # if d2 < dmin2:
            #     if not ia in ls_remove:
            #         ls_remove.append(ia)
            #     elif not ja in ls_remove:
            #         ls_remove.append(ja)
        # print('ia,len(ls_remove)=',ia,len(ls_remove))

    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))

    # print(' Number of to be removed atoms: ',len(ls_remove))
    #...one of two will survive
    # print(' One of two too-close atoms will survive...')
    # count= [ ls_remove.count(ls_remove[i]) for i in range(len(ls_remove))]
    # for i in range(0,len(ls_remove),2):
    #     if count[i] > count[i+1]:
    #         ls_remove[i+1]= -1
    #     elif count[i] < count[i+1]:
    #         ls_remove[i]= -1
    #     else:
    #         n= int(random()*2.0) # 0 or 1
    #         ls_remove[i+n]= -1
    ls_remove.sort()
    # for ia in range(len(ls_remove)-1,-1,-1):
    #     n= ls_remove[ia]
    #     if ia != len(ls_remove)-1:
    #         if n == nprev: continue
    #     system.atoms.pop(n)
    #     nprev= n
    for i in reversed(range(len(ls_remove))):
        ia = ls_remove[i]
        system.atoms.pop(ia)
    return system