def make_cluster(element1,element2,a): atoms = Octahedron(element1, length=3, cutoff=1, latticeconstant=float(a)) atoms.center(vacuum=7.0) # if there is a second element, swap out 6 of the atoms for the other metal if element2: for i in range(1,len(atoms),2): atoms[i].symbol = element2 return Atoms(atoms)
def test_cuboctahedron(shells): cutoff = shells - 1 length = 2 * cutoff + 1 cubocta = Octahedron(sym, length=length, cutoff=cutoff) print(cubocta) assert len(cubocta) == ico_cubocta_sizes[shells] coordination = coordination_numbers(cubocta) expected_internal_atoms = ico_cubocta_sizes[shells - 1] assert sum(coordination == fcc_maxcoordination) == expected_internal_atoms
def test_regular_octahedron(shells): octa = Octahedron(sym, length=shells, cutoff=0) coordination = coordination_numbers(octa) assert len(octa) == octa_sizes[shells] if shells == 1: return assert min(coordination) == 4 # corner atoms assert sum(coordination == 4) == 6 # number of corners # All internal atoms must have coordination as if in bulk crystal: expected_internal_atoms = octa_sizes[shells - 2] assert sum(coordination == fcc_maxcoordination) == expected_internal_atoms
def makeMotif(motif_inputs, latticeconstant, remove_atoms=[]): if isinstance(motif_inputs, int) or len(motif_inputs) == 1: if isinstance(motif_inputs, int): motif_inputs = [motif_inputs] cluster = Icosahedron(symbol, motif_inputs[0], latticeconstant=latticeconstant) name = 'Ico' elif len(motif_inputs) == 2: cluster = Octahedron(symbol, motif_inputs[0], motif_inputs[1], latticeconstant=latticeconstant) name = 'Octa' elif len(motif_inputs) == 3: cluster = Decahedron(symbol, motif_inputs[0], motif_inputs[1], motif_inputs[2], latticeconstant=latticeconstant) name = 'Deca' else: print "Error" import pdb pdb.set_trace() exit() remove_atoms.sort(reverse=True) if any(remove_atoms.count(x) > 1 for x in remove_atoms): print 'You have got two of the same atom entered in to this list, check this.' print 'remove_atoms = ' + str(remove_atoms) import pdb pdb.set_trace() exit() for remove_atom_index in remove_atoms: del cluster[remove_atom_index] name += '_' + symbol + str(len(cluster)) motif_details = '' for motif_input in motif_inputs: motif_details += str(motif_input) + '_' motif_details = motif_details[:-1] name += '_' + motif_details if not remove_atoms == []: name += '_atoms_removed_' + str(len(remove_atoms)) + '_cluster_' counter = 1 while True: if not name + str(counter) + '.traj' in os.listdir('.'): name += str(counter) break counter += 1 ASE_write(name + '.traj', cluster, 'traj') return name
def get_scaffold(shape = "ico", i = 3, latticeconstant = 3.0, energies = [0.5,0.4,0.3], surfaces = [(1, 0, 0), (1, 1, 1), (1, 1, 0)], max_bondlength = None): """Builds a scaffold of ghost atoms in icosahedral, octahedral or wulff-shape. Takes a shape argument (string can be ico, octa or wulff) as well as the size argument i (int) and a latticeconstant. When shape = 'wulff', it is required to give energies and surfaces as lists of equal length. Returns a Cluster object with atom type 'X'. Args: shape (str) : nanocluster shape such as "ico" (default), "octa", "wulff" i (float) : size of the nanocluster. Has different implications depending on the shape latticeconstant (float) : lattice constant of the fcc crystal structure defining the scaling of the nanocluster energies (list) : Defines Wulff-shape, ignored otherwise. The proportions of the surface energies defining the prominence of certain slabs defined by surface (energies and corresponding surfaces must be in the same order) surfaces (list) : Defines Wulff-shape, ignored otherwise. The Miller-indices of the surface slabs. Their energies define the prominence of certain slabs (energies and corresponding surfaces must be in the same order) max_bondlength (float) : distance up to which two atoms are considered bound. If None, the minimum distance is used as a guess with a tolerance factor of 0.1. Works well with equidistant atoms. Returns: cluskit.Scaffold : Scaffold object, an enhanced ase.Atoms object with additional attributes such as bond_matrix """ if shape == "ico": atoms = Icosahedron('X', noshells = i, latticeconstant = latticeconstant) elif shape == "octa": atoms = Octahedron('X', length = i, latticeconstant = latticeconstant) elif shape == "wulff": # i gives size in atoms atoms = wulff_construction('X', latticeconstant = latticeconstant, surfaces=surfaces, energies=energies, size=i, structure='fcc', rounding='above') else: raise NameError("shape argument unknown! Use ico, octa or wulff") return Scaffold(atoms, max_bondlength = max_bondlength)
def write_octahedral_cluster(element,e_coh,maximum_size,manual_mode,filename_suffix,input_information_file,folder,sort_manual_mode_by='base details'): def get_max_cutoff_value(length): max_cutoff = (length-1.0)/2.0 - 0.5*((length-1.0)%2.0) if not max_cutoff%1 == 0: print('Error in Get_Interpolation_Data, at def Get_Energies_Of_Octahedrals, at def get_max_cutoff_value: max_cutoff did not come out as an interger.\nCheck this.\nmax_cutoff = '+str(max_cutoff)) import pdb; pdb.set_trace() exit() return int(max_cutoff) print('============================================================') print('Starting Obtaining Octahedral Delta Energies') print('no atoms\tlength\tcutoff') length = 2; cutoff = get_max_cutoff_value(length); cutoff_max = cutoff all_octa_details = [] while True: no_atoms = no_of_atoms_to_make_octa(length,cutoff) if (no_atoms > maximum_size) and (cutoff == cutoff_max): break if no_atoms <= maximum_size: print(str(no_atoms)+' \tlength: ' + str(length) + ' \tcutoff = ' + str(cutoff)) #--------------------------------------------------------------------------------- # Make cluster cluster = Octahedron(element,length=length,cutoff=cutoff) post_creating_cluster(cluster) name = 'Octa_'+str(length)+'_'+str(cutoff) save_cluster_to_folder(folder,name,filename_suffix,manual_mode,cluster) #--------------------------------------------------------------------------------- # make data for details octa_parameters = (length,cutoff) octa_details = (no_atoms, octa_parameters) all_octa_details.append(octa_details) #--------------------------------------------------------------------------------- cutoff -= 1 if cutoff < 0 or no_atoms > maximum_size: length += 1 cutoff = get_max_cutoff_value(length) cutoff_max = cutoff print('============================================================') with open(input_information_file,'a') as input_file: input_file.write('Octahedron\n') if sort_manual_mode_by == 'no of atoms': all_octa_details.sort(key=lambda x:x[0]) elif sort_manual_mode_by == 'base details': all_octa_details.sort(key=lambda x:x[1]) for no_atoms, details in all_octa_details: no_atoms = str(no_atoms) details = '('+', '.join([str(detail) for detail in details])+')' input_file.write(no_atoms+' '*(atom_writing-len(no_atoms))+details+' '*(details_writing-len(details))+'\n')
def calc_impurity_energy(self, structure, elements): if structure not in ['oct38-center', 'oct38-face', 'oct38-edge']: raise ValueError("Cannot calculate impurity energy for '%s'" % (structure, )) if len(elements) != 2: raise ValueError("Tuple of elements must be of length two") if self.debug: print "Calculating impurity energy..." print 40 * "*" print "Structure: %s" % (structure, ) print "Elements: %s\n" % (elements, ) name, impurity = structure.split('-') sym = reference_states[atomic_numbers[elements[1]]]['symmetry'] latticeconstant = self.get_lattice_constant_a(sym, (elements[1], )) if name == 'oct38': sites = {'center': 10, 'face': 9, 'edge': 0} atoms = Octahedron(elements[1], 4, 1, latticeconstant) atoms.set_calculator(self.get_calc()) dyn = BFGS(atoms, logfile=None, trajectory=None) dyn.run(fmax=0.001, steps=100) assert dyn.converged() s_clean = dyn.get_number_of_steps() e_clean = atoms.get_potential_energy() atoms[sites[impurity]].symbol = elements[0] dyn.run(fmax=0.001, steps=100) assert dyn.converged() s_impurity = dyn.get_number_of_steps() e_impurity = atoms.get_potential_energy() self.values[('impurity_energy', structure, elements)] = e_impurity - e_clean if self.debug: print "BFGS steps: %i %i" % (s_clean, s_impurity) print "Impurity energy: %.5f - %.5f = %.5f eV" % ( e_impurity, e_clean, e_impurity - e_clean) print 40 * "-" + "\n"
from ase import Atoms from ase.cluster.octahedron import Octahedron from ase.cluster.icosahedron import Icosahedron # script for setting up M13 cluster # replace with your assigned element and your optimized lattice parameter # if your assigned system is a binary alloy, specify element2 (e.g. 'Cu') element1 = 'Pt' element2 = None # change to 'Cu' for example if you have an alloy a = None # optionally specify a lattice parameter vacuum = 7.0 # create the cluster and add vacuum around the cluster # we use cuboctahedrons here, though other shapes are possible atoms = Octahedron(element1, length=3,cutoff=1) #atoms = Icosahedron(element1, noshells=2) atoms.center(vacuum=vacuum) # if there is a second element, swap out 6 of the atoms for the other metal if element2: for i in range(1,len(atoms),2): atoms[i].symbol = element2 # write out the cluster Atoms(atoms).write('cluster.traj')
new_atom_position = matmul(Rotation_Matrix, atom_position) new_atom_position.shape = (1, 3) new_atom_position = np.ndarray.tolist(new_atom_position)[0] output_cluster[index].position = new_atom_position return output_cluster rCut_low = 2.8840 rCut_high = round(rCut_low * (2.0)**0.5, 4) rCut_resolution = 0.0005 mode = 'total' symbol = 'Au' latticeconstant = rCut_high cluster_main = Octahedron(symbol, 4, 1, latticeconstant=latticeconstant) cluster_main = move_cluster_to_COM(cluster_main) original_cluster_name = 'Au39_original' ASE_write(original_cluster_name + '.traj', cluster_main) original_cluster_name_opt = optimise(original_cluster_name) def run_CNA_program(Cluster_1_name, Cluster_2_name): Cluster_1 = ASE_read(Cluster_1_name + '.traj') print 'Made ' + str(Cluster_1_name) Cluster_2 = ASE_read(Cluster_2_name + '.traj') print 'Made ' + str(Cluster_2_name) Structural_Recognition_Program(Cluster_1, Cluster_2, rCut_low, rCut_high,
def __init__(self, motif, motif_details, element=None, local_optimiser=None, e_coh=None, no_atoms=None, delta_energy=None, debug=False, get_energy=False): if debug: print('cluster: ' + str(cluster)) print('no_atoms: ' + str(no_atoms)) print('local_optimiser: ' + str(local_optimiser)) print('e_coh: ' + str(e_coh)) print('delta_energy: ' + str(delta_energy)) self.motif = motif self.motif_details = motif_details self.get_energy = get_energy # Calculate the delta energy of the clusters if not (element is None and local_optimiser is None and e_coh is None) and (no_atoms is None and delta_energy is None): if motif == 'Icosahedron': if isinstance(motif_details, list): noshells = motif_details[0] else: noshells = motif_details from ase.cluster.icosahedron import Icosahedron cluster = Icosahedron(element, noshells=noshells) elif motif == 'Octahedron': length = motif_details[0] cutoff = motif_details[1] from ase.cluster.octahedron import Octahedron cluster = Octahedron(element, length=length, cutoff=cutoff) elif motif == 'Decahedron': p = motif_details[0] q = motif_details[1] r = motif_details[2] from ase.cluster.decahedron import Decahedron cluster = Decahedron(element, p=p, q=q, r=r) else: print( 'Error in Get_Interpolation_Data.py, in class Cluster, in def __init__' ) print( 'No valid motif type has been entered, must be either Icosahedron, Octahedron, Decahedron.' ) print('Check this.') print('motif = ' + str(motif)) import pdb pdb.set_trace() exit() self.post_creating_cluster(cluster) self.no_atoms = len(cluster) cluster = local_optimiser(cluster) if self.get_energy: energy = cluster.get_potential_energy() self.delta_energy = get_Delta_Energy(energy, cluster, e_coh) elif (element is None and local_optimiser is None and e_coh is None ) and not (no_atoms is None and delta_energy is None): self.no_atoms = no_atoms self.delta_energy = delta_energy else: print( 'Error in Get_Interpolation_Data.py, in class Cluster, in def __init__' ) print('Error in Cluster') print('motif: ' + str(motif)) print('motif_details: ' + str(motif_details)) print('element: ' + str(element)) print('local_optimiser: ' + str(local_optimiser)) print('e_coh: ' + str(e_coh)) print('no_atoms: ' + str(no_atoms)) print('delta_energy: ' + str(delta_energy)) exit()
Cluster_2 = ASE_read(Cluster_2_name + '.traj') print 'Made ' + str(Cluster_2_name) Structural_Recognition_Program(Cluster_1, Cluster_2, rCut_low, rCut_high, rCut_resolution, mode, name_1=Cluster_1_name, name_2=Cluster_2_name, recognise_multimetallic=False, print_plots=True) symbol = 'Au' cluster_main = Octahedron(symbol, 4, 1) length_1 = 0 length_2 = 0 angle = 0 name_original = shift_x(0, 0, 0, 0) name_original_Opt, cluster_main_Opt = optimise(name_original) ############################################################################################################ ############################################################################################################ ############################################################################################################ layer = '1st_layer' ############################################################################################################ ############################################################################################################ ############################################################################################################ normal_length = 2.040 length_1s = np.arange(0.1, 1.01, 0.1)
from ase import Atoms from ase.cluster.octahedron import Octahedron from ase.cluster.icosahedron import Icosahedron # script for setting up M13 cluster # replace with your assigned element and your optimized lattice parameter # if your assigned system is a binary alloy, specify element2 (e.g. 'Cu') element1 = 'Pt' element2 = None # change to 'Cu' for example if you have an alloy a = None # optionally specify a lattice parameter vacuum = 7.0 # create the cluster and add vacuum around the cluster # we use cuboctahedrons here, though other shapes are possible atoms = Octahedron(element1, length=3, cutoff=1) #atoms = Icosahedron(element1, noshells=2) atoms.center(vacuum=vacuum) # if there is a second element, swap out 6 of the atoms for the other metal if element2: for i in range(1, len(atoms), 2): atoms[i].symbol = element2 # write out the cluster Atoms(atoms).write('cluster.traj')
delete() print '---------------------------' def make_structures(remove_atoms): cluster = copy.deepcopy(cluster_main) for remove_atom in remove_atoms: del cluster[remove_atom] return cluster rCut_low = 2.8840 rCut_high = round(rCut_low * (2.0)**0.5,4) rCut_resolution = 0.0005 mode = 'total' symbol = 'Au' cluster_main = Octahedron(symbol,4,1,latticeconstant=rCut_high) view(cluster_main) def run_CNA_program(Cluster_1_name,Cluster_2_name): Cluster_1 = ASE_read(Cluster_1_name+'.traj') print 'Made ' + str(Cluster_1_name) Cluster_2 = ASE_read(Cluster_2_name+'.traj') print 'Made ' + str(Cluster_2_name) Structural_Recognition_Program(Cluster_1,Cluster_2,rCut_low,rCut_high,rCut_resolution,mode,name_1=Cluster_1_name,name_2=Cluster_2_name,recognise_multimetallic=False,print_plots=True) ###################################################### ###################################################### remove_atoms = [] shift_x(normal_length,length_1,length_2,angle) run_CNA_program(name_original,name_comparing) ######################################################
def clusters(): yield Icosahedron(sym, 2) yield Octahedron(sym, length=3, cutoff=1) yield Decahedron(sym, 2, 3, 3)