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
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
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
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
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
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
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
def convert(fname,specorder,index): """ Convert data in fname to fitpot format. """ ry2ev = 13.605698066 au2ang = 0.529177249 ryau2evang = ry2ev/au2ang if not os.path.exists(fname): raise RuntimeError(fname+' not found.') #atoms= read('POSCAR',index=0,format='vasp') try: natm,nspcs,spcs,cell,pos,elems,erg,frcs,pos_unit,strs \ = read_espresso_out(fname) except IOError as e: print('IOError({0:s}): {1:s}'.format(e.errno,e.strerror)) raise erg = erg *Ry_to_eV psys = NAPSystem(specorder=specorder) psys.set_hmat(cell) hi = unitvec_to_hi(cell[0,:],cell[1,:],cell[2,:]) # converting force here, not when reading the file frcs[:,:] *= ryau2evang for ia in range(natm): ai = Atom() pi = pos[ia,:] if pos_unit != "crystal": sx,sy,sz = cartesian_to_scaled(hi,pi[0],pi[1],pi[2]) else: sx,sy,sz = pi[:] ai.set_pos(sx,sy,sz) ai.set_frc(frcs[ia,0],frcs[ia,1],frcs[ia,2]) ai.set_symbol(elems[ia]) psys.add_atom(ai) psys.assign_pbc() if os.path.exists('POSCAR'): print(' cp original POSCAR to POSCAR.orig') os.system('cp POSCAR POSCAR.orig') psys.write_POSCAR() psys.write_pmd(fname='pos') write_ergref(fname='erg.ref',erg=erg) write_frcref(fname='frc.ref',frcs=frcs) #...write stress with open('strs.ref','w') as f: for s in strs: f.write(' {0:8.2f}'.format(s)) f.write('\n')
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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')
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
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_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