def toASE(molecule): """Convert a PLAMS |Molecule| to an ASE molecule (``ase.Atoms`` instance). Translate coordinates, atomic numbers, and lattice vectors (if present). The order of atoms is preserved.""" aseMol = aseAtoms() #iterate over PLAMS atoms for atom in molecule: #check if coords only consists of floats or ints if not all(isinstance(x, (int,float)) for x in atom.coords): raise ValueError("Non-Number in Atomic Coordinates, not compatible with ASE") #append atom to aseMol aseMol.append(aseAtom(atom.atnum, atom.coords)) #get lattice info if any lattice = npz((3,3)) pbc = [False,False,False] for i,vec in enumerate(molecule.lattice): #check if lattice only consists of floats or ints if not all(isinstance(x, (int,float)) for x in vec): raise ValueError("Non-Number in Lattice Vectors, not compatible with ASE") pbc[i] = True lattice[i] = npa(vec) #save lattice info to aseMol if any(pbc): aseMol.set_pbc(pbc) aseMol.set_cell(lattice) return aseMol
def gen_quad_smart(self, dis_type="easy"): alat = 2.82893 a1 = (1./3.)*alat*np.array([-1,-1,2]) a2 = (1.0/2.0)*alat*np.array([1,-1,0]) a3 = alat*0.5*np.array([1, 1, 1]) M = np.array([a1,a2,a3]) print M latt_1 = alat*np.array([-1.0,-1.0,2.0]) latt_2 = alat*np.array([1.0, 0.0,-1.0]) basis_1 = alat*np.array([0.0,0.0,0.0]) basis_2 = alat*np.array([0.0,0.0,1.0]) basis_3 = alat*np.array([0.5, 0.5, 0.5]) #basis_1 = alat*np.array([0.0,0.0,0.0]) #basis_2 = alat*np.array([0.81625, 0.0, 0.57734]) #basis_3 = alat*np.array([1.6329, 0.0, 0.288675]) #latt_1 = np.array([6.93206,0.0,0.0]) #latt_2 = np.array([-3.46603,2.00111,0.0]) #basis_2 = alat*np.sqrt(3.)*0.5*np.array([1.0,1.0,1.0]) print 'new latt 1', np.dot(np.linalg.inv(M.T), basis_1) print 'new latt 2', np.dot(np.linalg.inv(M.T), basis_2) #as integeres if dis_type == "easy": n = 15. m = 9. c1 = n*a1 - (1.0/(3.0*m))*a3 c2 = (n/2.)*a1 + m*a2 + (0.5 - (1.0/6*m))*a3 c3 = a3 elif dis_type == "hard": n = 21. m = 13. c1 = n*a1 + (1.0/(3*m))*a3 c2 = (n/2.)*a1 + m*a2 + (0.5 + 1./(6.*m))*a3 c3 = a3 #screw_slab_unit = BodyCenteredCubic(directions = [c1,c2,c3], # size = (1,1,1), symbol='Fe', pbc=(1,1,1), # latticeconstant = 2.83) screw_slab_unit = aseAtoms() for x in range(-30,30): for y in range(-30,30): latt = x*(latt_1) + y*(latt_2) Fe_1 = latt Fe_2 = latt + basis_2 Fe_3 = latt + basis_3 #latt_norm = np.linalg.norm(latt) #c1_norm = np.linalg.norm(c1) #c2_norm = np.linalg.norm(c2) #c1_arg = np.arccos((np.dot(c1,latt)/(c1_norm*latt_norm))) #c2_arg = np.dot(c2,latt)/(np.linalg.norm(c2)*np.linalg.norm(latt)) #c1_comp = np.linalg.norm(np.dot(c1,latt)*(c1_norm*latt_norm)) #c2_comp = np.linalg.norm(np.dot(c2,latt)*(c2_norm*latt_norm)) screw_slab_unit.append(Atom(symbol='Fe', position=Fe_1)) screw_slab_unit.append(Atom(symbol='Fe', position=Fe_2)) screw_slab_unit.append(Atom(symbol='Fe', position=Fe_3)) screw_slab_unit.set_cell([c1,c2,c3]) screw_slab_unit.write('screw.xyz')
def get_localEnv(frame, centerIdx, cutoff, onlyDict=False): ''' Get the local atomic environment around an atom in an atomic frame. :param frame: ase or quippy Atoms object :param centerIdx: int Index of the local environment center. :param cutoff: float Cutoff radius of the local environment. :return: ase Atoms object Local atomic environment. The center atom is in first position. ''' import ase.atoms import quippy.atoms from ase.neighborlist import NeighborList from ase import Atoms as aseAtoms if isinstance(frame, quippy.atoms.Atoms): atoms = qp2ase(frame) elif isinstance(frame, ase.atoms.Atoms): atoms = frame else: raise ValueError n = len(atoms.get_atomic_numbers()) nl = NeighborList([ cutoff / 2., ] * n, skin=0., sorted=False, self_interaction=False, bothways=True) nl.build(atoms) cell = atoms.get_cell() pbc = atoms.get_pbc() pos = atoms.get_positions() positions = [ pos[centerIdx], ] zList = atoms.get_atomic_numbers() numbers = [ zList[centerIdx], ] indices, offsets = nl.get_neighbors(centerIdx) # print offsets,len(atom.get_atomic_numbers()) for i, offset in zip(indices, offsets): positions.append(pos[i] + np.dot(offset, cell)) numbers.append(zList[i]) atomsParam = dict(numbers=numbers, cell=cell, positions=positions, pbc=pbc) if onlyDict: return atomsParam else: return aseAtoms(**atomsParam)
def get_atom(self): from ase import Atoms as aseAtoms frame = aseAtoms(numbers=self._atomic_numbers, positions=self._positions, cell=self._cell, pbc=self._pbc) for key,item in self._infoDict.iteritems(): frame.set_array(key,item) return frame
def get_centerInfo(self): if self.is_fast_average: print 'fast average -> no center' else: from ase import Atoms as aseAtoms info = {'z': self._atomic_number, 'position': self._position, 'cell': self._cell, 'idx': self._frameIdx, 'symbol': self._chemical_symbol, 'env': aseAtoms(**self._localEnvironementDict)} info.update(**self._info) return info
def qp2ase(qpatoms): from ase import Atoms as aseAtoms positions = qpatoms.get_positions() cell = qpatoms.get_cell() numbers = qpatoms.get_atomic_numbers() pbc = qpatoms.get_pbc() atoms = aseAtoms(numbers=numbers, cell=cell, positions=positions, pbc=pbc) for key, item in qpatoms.arrays.iteritems(): if key in ['positions', 'numbers', 'species', 'map_shift', 'n_neighb']: continue atoms.set_array(key, item) return atoms
def decorate_interface(): ats = Atoms('interface.xyz') dataset = spglib.get_symmetry_dataset(ats, symprec=1e-5) with open('unique_lattice_sites.json', 'w') as f: json.dump([ list(ats[site_num].position) for site_num in np.unique(dataset['equivalent_atoms']) ], f) unique_atoms = [] for at in ats: unique_atoms.append(at.position) voronoi = Voronoi(limits=tuple(np.diag(ats.cell)), periodic=(True, True, False)) cntr = voronoi.compute_voronoi(unique_atoms) ints_list = [] for site_num in np.unique(dataset['equivalent_atoms']): for vert in voronoi.get_vertices(site_num, cntr): ints_list.append(vert.tolist()) for unique in ints_list: ats.add_atoms(unique, 1) for i in range(len(ats)): ats.id[i] = i #remove voronoi duplicates print 'Fe_H atoms', len(ats) ats.wrap() del_ats = aseAtoms() for at in ats: del_ats.append(at) geometry.get_duplicate_atoms(del_ats, cutoff=0.2, delete=True) ats = del_ats.copy() print 'Fe_H atoms remove duplicates', len(ats) #select unique hydrogens #for i in range(len(ats)): # ats.id[i] = i ints_list = [at.position for at in ats if at.number == 1] with open('unique_h_sites.json', 'w') as f: json.dump([list(u) for u in ints_list], f) ats.write('hydrogenated_grain.xyz')
def toASE(molecule): """ Converts a PLAMS molecule to an ASE molecule. The following attributes are converted, conserving the order of atoms: -Coordinates -Atomic Number (Symbol is derived automaticaly) -Periodicity and Cell Vectors """ aseMol = aseAtoms() #iterate over PLAMS atoms for atom in molecule: #check if coords only consists of floats or ints if not all(isinstance(x, (int, float)) for x in atom.coords): raise ValueError( "Non-Number in Atomic Coordinates, not compatible with ASE") #append atom to aseMol aseMol.append(aseAtom(atom.atnum, atom.coords)) #get lattice info if any lattice = npz((3, 3)) pbc = [False, False, False] for i, vec in enumerate(molecule.lattice): #check if lattice only consists of floats or ints if not all(isinstance(x, (int, float)) for x in vec): raise ValueError( "Non-Number in Lattice Vectors, not compatible with ASE") pbc[i] = True lattice[i] = npa(vec) #save lattice info to aseMol if any(pbc): aseMol.set_pbc(pbc) aseMol.set_cell(lattice) return aseMol
def calc_bulk_dissolution(args): """Calculate the bulk dissolution energy for hydrogen in a tetrahedral position in bcc iron. Args: args(list): determine applied strain to unit cell. """ POT_DIR = os.path.join(app.root_path, 'potentials') eam_pot = os.path.join(POT_DIR, 'PotBH.xml') r_scale = 1.00894848312 pot = Potential( 'IP EAM_ErcolAd do_rescale_r=T r_scale={0}'.format(r_scale), param_filename=eam_pot) alat = 2.83 gb = BodyCenteredCubic(directions=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], size=(6, 6, 6), symbol='Fe', pbc=(1, 1, 1), latticeconstant=alat) cell = gb.get_cell() print 'Fe Cell', cell e1 = np.array([1, 0, 0]) e2 = np.array([0, 1, 0]) e3 = np.array([0, 0, 1]) if args.hydrostatic != 0.0: strain_tensor = np.eye(3) + args.hydrostatic * np.eye(3) cell = cell * strain_tensor gb.set_cell(cell, scale_atoms=True) print 'Hydrostatic strain', args.hydrostatic print 'strain tensor', strain_tensor print gb.get_cell() elif args.stretch != 0.0: strain_tensor = np.tensordot(e2, e2, axes=0) strain_tensor = np.eye(3) + args.stretch * strain_tensor cell = strain_tensor * cell print 'Stretch strain' print 'Cell:', cell gb.set_cell(cell, scale_atoms=True) elif args.shear != 0.0: strain_tensor = np.tensordot(e1, e2, axes=0) strain_tensor = np.eye(3) + args.shear * strain_tensor cell = strain_tensor.dot(cell) print 'Shear Strain', strain_tensor print 'Cell:', cell gb.set_cell(cell, scale_atoms=True) gb.write('sheared.xyz') else: print 'No strain applied.' tetra_pos = alat * np.array([0.25, 0.0, 0.5]) h2 = aseAtoms('H2', positions=[[0, 0, 0], [0, 0, 0.7]]) h2 = Atoms(h2) gb = Atoms(gb) gb_h = gb.copy() gb_h.add_atoms(tetra_pos, 1) #caclulators gb.set_calculator(pot) h2.set_calculator(pot) gb_h.set_calculator(pot) gb_h.write('hydrogen_bcc.xyz') #Calc Hydrogen molecule energy opt = BFGS(h2) opt.run(fmax=0.0001) E_h2 = h2.get_potential_energy() h2.write('h2mol.xyz') #strain_mask = [1,1,1,0,0,0] strain_mask = [0, 0, 0, 0, 0, 0] ucf = UnitCellFilter(gb_h, strain_mask) #opt = BFGS(gb_h) opt = FIRE(ucf) opt.run(fmax=0.0001) E_gb = gb.get_potential_energy() E_gbh = gb_h.get_potential_energy() E_dis = E_gbh - E_gb - 0.5 * E_h2 print 'E_gb', E_gb print 'E_gbh', E_gbh print 'H2 Formation Energy', E_h2 print 'Dissolution Energy', E_dis
symbols = unit_cell.get_chemical_symbols() cell = unit_cell.get_cell() scaled_positions = unit_cell.get_scaled_positions() THZ_to_mev = 4.135665538536 unit_cell = PhonopyAtoms(symbols=symbols, cell=cell, scaled_positions=scaled_positions) phonon = Phonopy(unit_cell, [[n_sup_x,0,0],[0,n_sup_y,0],[0,0,n_sup_z]]) phonon.generate_displacements(distance=0.05) supercells = phonon.get_supercells_with_displacements() #We need to get the forces on these atoms... forces = [] print 'There are', len(supercells), 'displacement patterns' for sc in supercells: cell = aseAtoms(symbols=sc.get_chemical_symbols(), scaled_positions=sc.get_scaled_positions(), cell=sc.get_cell(), pbc=(1,1,1)) cell = Atoms(cell) cell.set_calculator(pot) forces.append(cell.get_forces()) phonon.set_forces(forces) phonon.produce_force_constants() mesh = [nqx, nqy, nqz] phonon.set_mesh(mesh, is_eigenvectors=True) qpoints, weights, frequencies, eigvecs = phonon.get_mesh() #SHOW DOS STRUCTURE phonon.set_total_DOS(freq_min=0.0, freq_max=12.0, tetrahedron_method=False) phonon.get_total_DOS() phonon.write_total_DOS()
POT_DIR = os.path.join(app.root_path, 'potentials') eam_pot = os.path.join(POT_DIR, 'PotBH.xml') r_scale = 1.00894848312 pot = Potential('IP EAM_ErcolAd do_rescale_r=T r_scale={0}'.format(r_scale), param_filename=eam_pot) alat = 2.83 #Structures gb = BodyCenteredCubic(directions=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], size=(4, 4, 4), symbol='Fe', pbc=(1, 1, 1), latticeconstant=alat) tetra_pos = alat * np.array([0.25, 0.0, 0.5]) h2 = aseAtoms('H2', positions=[[0, 0, 0], [0, 0, 0.7]]) h2 = Atoms(h2) gb = Atoms(gb) gb_h = gb.copy() gb_h.add_atoms(tetra_pos, 1) #caclulators gb.set_calculator(pot) h2.set_calculator(pot) gb_h.set_calculator(pot) gb_h.write('hydrogen_bcc.xyz') #Calc Hydrogen molecule energy opt = BFGS(h2) opt.run(fmax=0.0001)
def get_localEnvironement(self): if self.is_fast_average: print 'fast average -> no center' else: from ase import Atoms as aseAtoms return aseAtoms(**self._localEnvironementDict)