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
p0= np.zeros((nmeasure,3)) pp= np.zeros(3) msd= np.zeros((len(infiles),nmeasure,3)) npbc= np.zeros((3,),dtype=int) hmat= np.zeros((3,3)) for ifile in range(len(infiles)): file= infiles[ifile] system= NAPSystem() system.read_akr(file) hmat[0]= system.a1 *system.alc hmat[1]= system.a2 *system.alc hmat[2]= system.a3 *system.alc #...human-readable ID to computer-oriented ID i= id-1 pi= system.get_atom_attr(i,'pos') if ifile == 0: pp= pi else: #...correct periodic motion dev= pi -pp if dev[0] > 0.5: npbc[0] += -1 elif dev[0] < -0.5: npbc[0] += 1 if dev[1] > 0.5: npbc[1] += -1 elif dev[1] < -0.5: npbc[1] += 1 if dev[2] > 0.5: npbc[2] += -1