def testget_unique_atoms(self): unit = Atoms("C4", positions=[(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0)]) unit1 = unit.copy() unit1.translate([1, 0, 0]) atoms = Atoms() atoms.extend(unit) atoms.extend(unit1) self.assertEqual(len(atoms), 8) atoms = get_unique_atoms(atoms) self.assertEqual(len(atoms), 6)
def unitcell(self,latx,laty): unit=Atoms('C2',[(0.5,0.5,0.0),(0.5+sqrt(2)/2,0.5+sqrt(2)/2,0)]) atoms=Atoms() for i in range(4): a=unit.copy() a.rotate('z',pi/2*i) atoms.extend(a) atoms.set_cell([2+sqrt(2),2+sqrt(2),10.0]) col=unit.repeat((latx,laty,1)) return col
def get_fingerprint(Optimizer, indiv, binsize, cutoffdist): """Function to calculate the fingerprint of a structure""" rs = numpy.linspace(0.0, cutoffdist, cutoffdist/binsize) indi = indiv[0] Vuc = indi.get_volume() if Optimizer.structure == 'Defect': solid = Atoms() solid.extend(indi) solid.extend(indiv.bulki) elif Optimizer.structure == 'Crystal': solid = indi.repeat([3, 3, 3]) else: solid = indi.copy() syms = sorted(list(set([atm.symbol for atm in solid]))) fingerprints = [] for i in range(len(syms)): for j in range(i, len(syms)): indl = [atm for atm in indi if atm.symbol == syms[i]] ind = Atoms() for one in indl: ind.append(one) soll = [atm for atm in solid if atm.symbol == syms[j]] sol = Atoms() for one in soll: sol.append(one) soli = [atm for atm in solid if atm.symbol == syms[i]] value = [] for R in rs: value2 = [] for k in range(len(ind)): value1 = [] for m in range(len(sol)): if k != m: rij = sol.get_distance(k, m, mic = True) if rij == 0: pass #pdb.set_trace() value1.append(dirac(R, a=rij, sig=0.02) * 1. / (4*math.pi * rij** 2*binsize * len(soli) * len(sol) / Vuc)) value2.append(sum(value1)) value.append(sum(value2)) fingerprints.append(value) fpt = [] for one in fingerprints: fpt.extend(one) return fpt
def update_structfile(ind, structfile, Optimizer): if Optimizer.structure == 'Defect' or Optimizer.structure == 'Surface': sols = Atoms() sols.extend(ind[0]) sols.extend(ind.bulki) elif Optimizer.structure == 'Crystal': sols = ind[0].repeat((3,3,3)) else: sols = ind[0].copy() positions = sols.get_positions() if Optimizer.vacancy_output: for one in ind.vacancies: sols.append(Atom(symbol='X',position=one.position)) #Optimizer.output.write('Number of positions = {0}\n'.format(len(positions))) write_xyz(structfile, sols, ind.energy) return positions
def lmp_structure(self): atoms=Atoms() lead1=self.m.lmp_structure() self.hatom=len(lead1) lead2=lead1.copy() lead3=lead1.copy() atoms.extend(lead1) lead2.translate(lead1.cell[0]) atoms.extend(lead2) lead3.translate(lead1.cell[0]*2) atoms.extend(lead3) atoms.cell=lead1.cell.copy() atoms.cell[0]=lead1.cell[0]*3 atoms.center() return atoms
def rotct_rand(ind1, ind2, Optimizer): """Rotate atoms cut and splice Rotates atoms randomly around center of mass and cuts with xy plane Maintains number of atoms Maintains concentration of atoms Returns individuals to standard positions at end (un-rotates) """ if 'CX' in Optimizer.debug: debug = True else: debug = False Optimizer.output.write('Random Rotate Cut/Splice Cx between individual '+repr(ind1.index)+' and individual '+repr(ind2.index)+'\n') #Perserve starting conditions of individual indi1 = ind1[0].copy() indi2 =ind2[0].copy() #Translate individuals so COM is at (0,0,0) com1 = indi1.get_center_of_mass() indi1.translate(-1*com1) com2 = indi2.get_center_of_mass() indi2.translate(-1*com2) #Select random axis, random angle, and random position and rotate individuals cmax = [min(numpy.maximum.reduce(indi1.get_positions())[i],numpy.maximum.reduce(indi2.get_positions())[i]) for i in range(3)] cmin = [min(numpy.minimum.reduce(indi1.get_positions())[i],numpy.minimum.reduce(indi2.get_positions())[i]) for i in range(3)] n=0 while n<10: rax = random.choice(['x', '-x','y','-y','z','-z']) rang = random.random()*90 rpos = [random.uniform(cmin[i]*0.8,cmax[i]*0.8) for i in range(3)] indi1.rotate(rax,a=rang,center=rpos,rotate_cell=False) #Search for atoms in individual 1 that are above the xy plane group1 = Atoms(cell=ind1[0].get_cell(),pbc=ind1[0].get_pbc()) indices1=[] for one in indi1: if one.position[2] >= 0: group1.append(one) indices1.append(one.index) if len(group1) > 2 and len(group1) < len(indi1): break else: n+=1 indi1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) indi2.rotate(rax,a=rang,center=rpos,rotate_cell=False) if debug: print 'Group1 size = ', len(group1) print 'Position = ', rpos print 'Angle = ', rang print 'Axis = ', rax print 'Number of tries = ', n if len(group1) != 0: #Apply concentration forcing if needed group2 = Atoms(cell=ind2[0].get_cell(),pbc=ind2[0].get_pbc()) indices2 = [] dellist = [] for one in indi2: if one.position[2] >= 0: group2.append(one) indices2.append(one.index) if Optimizer.forcing=='Concentration': symlist = list(set(indi1.get_chemical_symbols())) seplist = [[atm for atm in group2 if atm.symbol == sym] for sym in symlist] group2n=Atoms(cell=group2.get_cell(),pbc=group2.get_pbc()) indices2n = [] dellist = [] for one in group1: sym1=one.symbol listpos=[i for i,s in enumerate(symlist) if s==sym1][0] if len(seplist[listpos]) > 0: pos = random.choice(range(len(seplist[listpos]))) group2n.append(seplist[listpos][pos]) indices2n.append(indices2[seplist[listpos][pos].index]) del seplist[listpos][pos] else: dellist.append(one.index) if len(dellist) != 0: dellist.sort(reverse=True) for one in dellist: del group1[one] del indices1[one] indices2=indices2n group2=group2n.copy() else: dellist = [] while len(group2) < len(group1)-len(dellist): #Too many atoms in group 1 dellist.append(random.choice(group1).index) if len(dellist) != 0: dellist.sort(reverse=True) for one in dellist: del group1[one] del indices1[one] dellist = [] while len(group1) < len(group2)-len(dellist): #Too many atoms in group 2 dellist.append(random.choice(group2).index) if len(dellist) != 0: dellist.sort(reverse=True) for one in dellist: del group2[one] del indices2[one] other2 = Atoms(cell=ind2[0].get_cell(),pbc=ind2[0].get_pbc()) for one in indi2: if one.index not in indices2: other2.append(one) other1 = Atoms(cell=ind1[0].get_cell(),pbc=ind1[0].get_pbc()) for one in indi1: if one.index not in indices1: other1.append(one) indi1 = group2.copy() indi1.extend(other1) indi2 = group1.copy() indi2.extend(other2) #DEBUG: Write crossover to file if debug: write_xyz(Optimizer.debugfile, group1,'group1') write_xyz(Optimizer.debugfile, other1,'other1') write_xyz(Optimizer.debugfile, group2,'group2') write_xyz(Optimizer.debugfile, other2,'other2') print 'Length of group1 = ',len(group1),'Length of group2',len(group2) #DEBUG: Check structure of atoms exchanged for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in indi1 if atm.symbol==sym]) Optimizer.output.write('CX RANDROTCT: Individual 1 contains '+repr(nc)+' '+repr(sym)+' atoms\n') nc=len([atm for atm in indi2 if atm.symbol==sym]) Optimizer.output.write('CX RANDROTCT: Individual 2 contains '+repr(nc)+' '+repr(sym)+' atoms\n') if Optimizer.forcing !='Concentration': for i in range(len(Optimizer.atomlist)): atms1=[inds for inds in indi1 if inds.symbol==Optimizer.atomlist[i][0]] atms2=[inds for inds in indi2 if inds.symbol==Optimizer.atomlist[i][0]] if len(atms1)==0: if len(atms2)==0: indi1[random.randint(0,len(indi1)-1)].symbol==Optimizer.atomlist[i][0] indi2[random.randint(0,len(indi2)-1)].symbol==Optimizer.atomlist[i][0] else: indi1.append(atms2[random.randint(0,len(atms2)-1)]) indi1.pop(random.randint(0,len(indi1)-2)) else: if len(atms2)==0: indi2.append(atms1[random.randint(0,len(atms1)-1)]) indi2.pop(random.randint(0,len(indi2)-2)) indi1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) indi2.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) indi1.translate(com1) indi2.translate(com2) #DEBUG: Check structure and number of atoms in crystal if Optimizer.structure=='Defect': solid1=Atoms() solid1.extend(indi1) solid1.extend(ind1.bulki) solid2=Atoms() solid2.extend(indi2) solid2.extend(ind2.bulki) for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in solid1 if atm.symbol==sym]) Optimizer.output.write('CX RANDROTCT: Defect 1 configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n') nc=len([atm for atm in solid2 if atm.symbol==sym]) Optimizer.output.write('CX RANDROTCT: Defect 2 configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n') if debug: Optimizer.output.flush() #pdb.set_trace() ind1[0]=indi1 ind2[0]=indi2 return ind1, ind2
def getUnitCell(self): sideLen = self.sideLen edge = Atoms() nAtom = 2 * sideLen + 1 for i in range(nAtom): if i % 2 == 0: label = 'C' y = 0.5 else: label = 'N' if len(self.elements) == 1: label = 'C' y = 1.0 x = (-sideLen + i) * 0.5 * sqrt(3) y -= (sideLen + 1) * 1.5 atom = Atom(label, (x, y, 0.0)) edge.append(atom) unitCell = Atoms() for i in range(6): newEdge = edge.copy() newEdge.rotate('z', i * 2 * pi / 6.0) unitCell.extend(newEdge) #get cell dist = (self.sideLen + 1) * 3.0 #the distance between 2 hole center if self.cubic: newAtoms = unitCell.copy() newAtoms.translate([dist * sqrt(3) / 2, dist / 2.0, 0]) unitCell.extend(newAtoms) unitCell.set_cell([dist * sqrt(3), dist, 10.0]) else: cell = np.diag([dist * sqrt(3) / 2, dist, 10]) cell[0, 1] = dist / 2.0 unitCell.set_cell(cell) return unitCell
def structure(self): latysmall, latExtend, latxsmall, latxbig, bond = [ int(self.latysmall), int(self.latExtend), int(self.latxsmall), int(self.latxbig), float(self.bond) ] if (latxsmall % 2 == 0): latxsmall += 1 if (latxbig % 2 == 1): latxbig += 1 atoms = self.agnr(latysmall, latxsmall + 1, 0) unit = self.agnr(latysmall - 1 + 2 * latExtend, latxbig, 0) unit.translate([latxsmall * 1.5, -(latExtend - 0.5) * sqrt(3), 0]) atoms.extend(unit) unit = self.agnr(latysmall, latxsmall + 1, 0) unit.translate([(latxsmall + latxbig - 1) * 1.5, 0, 0]) atoms.extend(unit) temp = Atoms() for i in range(self.seg): unit = atoms.copy() unit.translate([(latxsmall + latxbig - 1) * 1.5 * i, 0, 0]) temp.extend(unit) atoms.extend(temp) atoms = get_unique_atoms(atoms) lx, ly = self.extent(atoms) atoms.set_cell([lx, ly, 100]) atoms.set_cell([lx * bond, ly * bond, 100], scale_atoms=True) atoms.set_pbc([1, 1, 1]) atoms.center(vacuum=10 * bond) self.atoms = atoms self.write() print 'read_data structure'
def structure(self): latysmall,latExtend,latxsmall,latxbig,bond=[int(self.latysmall),int(self.latExtend),int(self.latxsmall),int(self.latxbig),float(self.bond)] if(latxsmall%2==0):latxsmall+=1; if(latxbig%2==1):latxbig+=1; atoms=self.agnr(latysmall,latxsmall+1,0); unit=self.agnr(latysmall-1+2*latExtend,latxbig,0) unit.translate([latxsmall*1.5,-(latExtend-0.5)*sqrt(3),0]) atoms.extend(unit) unit=self.agnr(latysmall,latxsmall+1,0); unit.translate([(latxsmall+latxbig-1)*1.5,0,0]) atoms.extend(unit) temp=Atoms() for i in range(self.seg): unit=atoms.copy() unit.translate([(latxsmall+latxbig-1)*1.5*i,0,0]) temp.extend(unit) atoms.extend(temp) atoms=get_unique_atoms(atoms) lx,ly=self.extent(atoms) atoms.set_cell([lx,ly,100]) atoms.set_cell([lx*bond,ly*bond,100],scale_atoms=True) atoms.set_pbc([1,1,1]) atoms.center(vacuum=10*bond) self.atoms=atoms self.write() print 'read_data structure'
def getUnitCell(self): sideLen=self.sideLen edge=Atoms() nAtom=2*sideLen+1 for i in range(nAtom): if i%2==0: label='C' y=0.5 else: label='N' if len(self.elements)==1:label='C' y=1.0 x=(-sideLen+i)*0.5*sqrt(3) y-=(sideLen+1)*1.5 atom=Atom(label,(x,y,0.0)) edge.append(atom) unitCell=Atoms() for i in range(6): newEdge=edge.copy() newEdge.rotate('z',i*2*pi/6.0) unitCell.extend(newEdge) #get cell dist=(self.sideLen+1)*3.0 #the distance between 2 hole center if self.cubic: newAtoms=unitCell.copy() newAtoms.translate([dist*sqrt(3)/2,dist/2.0,0]) unitCell.extend(newAtoms) unitCell.set_cell([dist*sqrt(3),dist,10.0]) else: cell=np.diag([dist*sqrt(3)/2,dist,10]) cell[0,1]=dist/2.0 unitCell.set_cell(cell) return unitCell
def atoms_2co(): """Simple atoms object for testing with 2x CO molecules""" d = 1.14 atoms = Atoms('CO', positions=[(0, 0, 0), (0, 0, d)], pbc=True) atoms.extend(Atoms('CO', positions=[(0, 2, 0), (0, 2, d)])) atoms.center(vacuum=5.) return atoms
def create_random_atoms(gd, nmolecules=10, name='NH2', mindist=4.5 / Bohr): """Create gas-like collection of atoms from randomly placed molecules. Applies rigid motions to molecules, translating the COM and/or rotating by a given angle around an axis of rotation through the new COM. These atomic positions obey the minimum distance requirement to zero-boundaries. Warning: This is only intended for testing parallel grid/LFC consistency. """ atoms = Atoms(cell=gd.cell_cv * Bohr, pbc=gd.pbc_c) # Store the original state of the random number generator randstate = np.random.get_state() seed = np.array([md5_array(data, numeric=True) for data in [nmolecules, gd.cell_cv, gd.pbc_c, gd.N_c]]).astype(int) np.random.seed(seed % 4294967296) for m in range(nmolecules): amol = molecule(name) amol.set_cell(gd.cell_cv * Bohr) # Rotate the molecule around COM according to three random angles # The rotation axis is given by spherical angles phi and theta v,phi,theta = np.random.uniform(0.0, 2*np.pi, 3) # theta [0,pi[ really axis = np.array([cos(phi)*sin(theta), sin(phi)*sin(theta), cos(theta)]) amol.rotate(axis, v) # Find the scaled length we must transverse along the given axes such # that the resulting displacement vector is `mindist` from the cell # face corresponding to that direction (plane with unit normal n_v). sdist_c = np.empty(3) if not gd.orthogonal: for c in range(3): n_v = gd.xxxiucell_cv[c] / np.linalg.norm(gd.xxxiucell_cv[c]) sdist_c[c] = mindist / np.dot(gd.cell_cv[c], n_v) else: sdist_c[:] = mindist / gd.cell_cv.diagonal() assert np.all(sdist_c > 0), 'Displacment vectors must be inside cell.' # Scaled dimensions of the smallest possible box centered on the COM spos_ac = amol.get_scaled_positions() # NB! must not do a "% 1.0" scom_c = np.dot(gd.icell_cv, amol.get_center_of_mass()) sbox_c = np.abs(spos_ac-scom_c[np.newaxis,:]).max(axis=0) sdelta_c = (1-np.array(gd.pbc_c)) * (sbox_c + sdist_c) assert (sdelta_c < 1.0-sdelta_c).all(), 'Box is too tight to fit atoms.' scenter_c = [np.random.uniform(d,1-d) for d in sdelta_c] center_v = np.dot(scenter_c, gd.cell_cv) # Translate the molecule such that COM is located at random center offset_av = (center_v-amol.get_center_of_mass()/Bohr)[np.newaxis,:] amol.set_positions(amol.get_positions()+offset_av*Bohr) assert np.linalg.norm(center_v-amol.get_center_of_mass()/Bohr) < 1e-9 atoms.extend(amol) # Restore the original state of the random number generator np.random.set_state(randstate) assert compare_atoms(atoms) return atoms
def ellipsoid(atomlist, fill_factor=0.74, radii=None, ratio=[1, 1, 1], cell=None): """Generates a random ellipsoid by rejection sampling. Not the most efficient code but good at garaunteeing an even distribution inside the ellipsoid. Parameters ---------- fill_factor : float Determines how "close" the atoms are packed. See structopt.tools.get_particle_radius for description radii : list (3 elements) The size, in angstroms, of the ellipsoid in the x, y and z direction ratio : list (3 elements) The ratio of the dimensions of the ellipsoid in the x, y and z direction. cell : list (3 elements) The size, in angstroms, of the dimensions that holds the atoms object """ # Get the dimensions of the ellipsoid if required if radii is None: radius = get_particle_radius(atomlist, fill_factor) a = radius / ((ratio[1] / ratio[0])**(1.0 / 3.0) * (ratio[2] / ratio[0])**(1.0 / 3.0)) b = radius / ((ratio[0] / ratio[1])**(1.0 / 3.0) * (ratio[2] / ratio[1])**(1.0 / 3.0)) c = radius / ((ratio[0] / ratio[2])**(1.0 / 3.0) * (ratio[1] / ratio[2])**(1.0 / 3.0)) else: a, b, c = radii # Create a list of random order of the atoms chemical_symbols = [] for atom in atomlist: chemical_symbols += [atom[0]] * atom[1] random.shuffle(chemical_symbols) # Add atoms iteratively only if they fall inside the ellipsoid indiv = Atoms() while len(chemical_symbols) > 0: x, y, z = random.uniform(-a, a), random.uniform(-b, b), random.uniform(-c, c) if x**2 / a**2 + y**2 / b**2 + z**2 / c**2 <= 1: indiv.extend(Atom(chemical_symbols.pop(), [x, y, z])) if cell is not None: indiv.set_cell(cell) indiv.center() indiv.set_pbc(True) return indiv
def ase_minimization(indiv, Optimizer): """Function to use built in ASE minimizers to minimize atomic positions in structure. Input: indiv = Individual class object to be optimized Optimizer = Optimizer class object with needed parameters Output: indiv = Optimized Individual class object. """ if 'MU' in Optimizer.debug: debug = True else: debug = False cwd1=os.getcwd() olammpsmin = Optimizer.lammps_min if Optimizer.lammps_min: Optimizer.lammps_min = None calc2 = setup_calculator(Optimizer) # if 'mass' in indiv[0].get_calculator(): # mass2 = ['1 '+ str(Optimizer.atomlist[0][2])] # if len(Optimizer.atomlist) > 1: # for i in range(len(Optimizer.atomlist)-1): # mass2.append(str(i+2) + ' ' + str(Optimizer.atomlist[i+1][2])) # calc2=LAMMPS(parameters={ 'pair_style' : Optimizer.pair_style, 'pair_coeff' : Optimizer.pair_coeff , 'mass' : mass2 },files=[ Optimizer.pot_file ]) # else: # calc2=LAMMPS(parameters={ 'pair_style' : Optimizer.pair_style, 'pair_coeff' : Optimizer.pair_coeff},files=[ Optimizer.pot_file ]) if Optimizer.structure==Defect: nat=indiv[0].get_number_of_atoms sol=Atoms() sol.extend(indiv[0]) sol.extend(indiv.bulko) sol.set_calculator(calc2) sol.set_cell(indiv.bulko.get_cell()) sol.set_pbc(True) dyn=BFGS(sol) dyn.run(fmax=0.001, steps=2500) positions=sol[0:nat].get_positions() indiv[0].set_positions(positions) else: atomsdup=indiv[0].copy() atomsdup.set_calculator(calc2) dyn=BFGS(indiv[0]) dyn.run(fmax=0.001, steps=2500) positions=atomsdup.get_positions() indiv[0].set_positions(positions) os.chdir(cwd1) calc2.clean() Optimizer.lammps_min = olammpsmin Optimizer.output.write('ASE Minimization mutation performed on individual = '+repr(indiv.index)+'\n') muttype='ASEM' if indiv.energy==0: indiv.history_index=indiv.history_index+'m'+muttype else: indiv.history_index=repr(indiv.index)+'m'+muttype return indiv
def create_random_atoms(gd, nmolecules=10, name='H2O', mindist=4.5 / Bohr): """Create gas-like collection of atoms from randomly placed molecules. Applies rigid motions to molecules, translating the COM and/or rotating by a given angle around an axis of rotation through the new COM. These atomic positions obey the minimum distance requirement to zero-boundaries. Warning: This is only intended for testing parallel grid/LFC consistency. """ atoms = Atoms(cell=gd.cell_cv * Bohr, pbc=gd.pbc_c) # Store the original state of the random number generator randstate = np.random.get_state() np.random.seed(np.array([md5_array(data, numeric=True) for data in [nmolecules, gd.cell_cv, gd.pbc_c, gd.N_c]]).astype(int)) for m in range(nmolecules): amol = molecule(name) amol.set_cell(gd.cell_cv * Bohr) # Rotate the molecule around COM according to three random angles # The rotation axis is given by spherical angles phi and theta v,phi,theta = np.random.uniform(0.0, 2*np.pi, 3) # theta [0,pi[ really axis = np.array([cos(phi)*sin(theta), sin(phi)*sin(theta), cos(theta)]) amol.rotate(axis, v) # Find the scaled length we must transverse along the given axes such # that the resulting displacement vector is `mindist` from the cell # face corresponding to that direction (plane with unit normal n_v). sdist_c = np.empty(3) if not gd.orthogonal: for c in range(3): n_v = gd.xxxiucell_cv[c] / np.linalg.norm(gd.xxxiucell_cv[c]) sdist_c[c] = mindist / np.dot(gd.cell_cv[c], n_v) else: sdist_c[:] = mindist / gd.cell_cv.diagonal() assert np.all(sdist_c > 0), 'Displacment vectors must be inside cell.' # Scaled dimensions of the smallest possible box centered on the COM spos_ac = amol.get_scaled_positions() # NB! must not do a "% 1.0" scom_c = np.dot(gd.icell_cv, amol.get_center_of_mass()) sbox_c = np.abs(spos_ac-scom_c[np.newaxis,:]).max(axis=0) sdelta_c = (1-np.array(gd.pbc_c)) * (sbox_c + sdist_c) assert (sdelta_c < 1.0-sdelta_c).all(), 'Box is too tight to fit atoms.' scenter_c = [np.random.uniform(d,1-d) for d in sdelta_c] center_v = np.dot(scenter_c, gd.cell_cv) # Translate the molecule such that COM is located at random center offset_av = (center_v-amol.get_center_of_mass()/Bohr)[np.newaxis,:] amol.set_positions(amol.get_positions()+offset_av*Bohr) assert np.linalg.norm(center_v-amol.get_center_of_mass()/Bohr) < 1e-9 atoms.extend(amol) # Restore the original state of the random number generator np.random.set_state(randstate) assert compare_atoms(atoms) return atoms
def lmp_structure(self): ribbon=graphene(dict(latx=self.latx,laty=self.laty,latz=1,gnrtype=self.gnrtype)).lmp_structure() for atom in ribbon: atom.position=self.trans(atom.position) atoms=Atoms() atoms.extend(ribbon) atoms.center(vacuum=10) return atoms
def unitcell(self, latx, laty): unit = Atoms('C2', [(0.5, 0.5, 0.0), (0.5 + sqrt(2) / 2, 0.5 + sqrt(2) / 2, 0)]) atoms = Atoms() for i in range(4): a = unit.copy() a.rotate('z', pi / 2 * i) atoms.extend(a) atoms.set_cell([2 + sqrt(2), 2 + sqrt(2), 10.0]) col = unit.repeat((latx, laty, 1)) return col
def ring(self): #armchair ring atoms=Atoms() atom=Atoms('C',[(1.0,0.0,0.0)]) for i in range(6): atom.rotate('z',pi/3*i) atoms.extend(atom.copy()) atoms.set_cell([3.0,sqrt(3),self.az]) return atoms
def ring(self): #armchair ring b=3.134/self.bond/2 atoms=Atoms() atom=Atoms('MoS2',[(1.0,0.0,0.0),(-1.0,0,b),(-1.0,0,-b)]) for i in range(3): atom.rotate('z',pi*2.0/3*i) atoms.extend(atom.copy()) atoms.set_cell([3.0,sqrt(3),10.0]) return atoms
def get_atoms_adsorbate(): # We need the relaxed slab here! slab = Atoms([ Atom('Cu', [-1.028468159509163, -0.432387156877267, -0.202086055768265]), Atom('Cu', [0.333333333333333, 0.333333333333333, -2.146500000000000]), Atom('Cu', [1.671531840490805, -0.432387156877287, -0.202086055768242]), Atom('Cu', [3.033333333333334, 0.333333333333333, -2.146500000000000]), Atom('Cu', [4.371531840490810, -0.432387156877236, -0.202086055768261]), Atom('Cu', [5.733333333333333, 0.333333333333333, -2.146500000000000]), Atom('Cu', [7.071531840490944, -0.432387156877258, -0.202086055768294]), Atom('Cu', [8.433333333333335, 0.333333333333333, -2.146500000000000]), Atom('Cu', [0.321531840490810, 1.905881433340708, -0.202086055768213]), Atom('Cu', [1.683333333333333, 2.671601923551318, -2.146500000000000]), Atom('Cu', [3.021531840490771, 1.905881433340728, -0.202086055768250]), Atom('Cu', [4.383333333333334, 2.671601923551318, -2.146500000000000]), Atom('Cu', [5.721531840490857, 1.905881433340735, -0.202086055768267]), Atom('Cu', [7.083333333333333, 2.671601923551318, -2.146500000000000]), Atom('Cu', [8.421531840490820, 1.905881433340739, -0.202086055768265]), Atom('Cu', [9.783333333333335, 2.671601923551318, -2.146500000000000]), Atom('Cu', [1.671531840490742, 4.244150023558601, -0.202086055768165]), Atom('Cu', [3.033333333333334, 5.009870513769302, -2.146500000000000]), Atom('Cu', [4.371531840490840, 4.244150023558694, -0.202086055768265]), Atom('Cu', [5.733333333333333, 5.009870513769302, -2.146500000000000]), Atom('Cu', [7.071531840490880, 4.244150023558786, -0.202086055768352]), Atom('Cu', [8.433333333333335, 5.009870513769302, -2.146500000000000]), Atom('Cu', [9.771531840491031, 4.244150023558828, -0.202086055768371]), Atom('Cu', [11.133333333333335, 5.009870513769302, -2.146500000000000]), Atom('Cu', [3.021531840490714, 6.582418613776583, -0.202086055768197]), Atom('Cu', [4.383333333333334, 7.348139103987287, -2.146500000000000]), Atom('Cu', [5.721531840490814, 6.582418613776629, -0.202086055768203]), Atom('Cu', [7.083333333333333, 7.348139103987287, -2.146500000000000]), Atom('Cu', [8.421531840490985, 6.582418613776876, -0.202086055768357]), Atom('Cu', [9.783333333333335, 7.348139103987287, -2.146500000000000]), Atom('Cu', [11.121531840490929, 6.582418613776676, -0.202086055768221]), Atom('Cu', [12.483333333333334, 7.348139103987287, -2.146500000000000]), ]) mask = [a.position[2] < -1 for a in slab] slab.set_constraint(FixAtoms(mask=mask)) h = 1.85 d = 1.10 molecule = Atoms('2N', positions=[(0., 0., h), (0., 0., h + d)]) molecule.set_calculator(EMT()) slab.extend(molecule) return slab
def ring(self): # armchair ring atoms = Atoms() atom = Atoms('C', positions=[(1.0, 0.0, 0.0)]) for i in range(6): unit = atom.copy() unit.rotate('z', pi / 3 * i) atoms.extend(unit) atoms.set_cell([3.0, sqrt(3), self.az]) atoms.center() wrap(atoms) return atoms
def testget_unique_atoms(self): unit = Atoms( "C4", positions=[ (0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0)]) unit1 = unit.copy() unit1.translate([1, 0, 0]) atoms = Atoms() atoms.extend(unit) atoms.extend(unit1) self.assertEqual(len(atoms), 8) atoms = get_unique_atoms(atoms) self.assertEqual(len(atoms), 6)
def ellipsoid(atomlist, fill_factor=0.74, radii=None, ratio=[1, 1, 1], cell=None): """Generates a random ellipsoid by rejection sampling. Parameters ---------- atomlist : list A list of [sym, n] pairs where sym is the chemical symbol and n is the number of of sym's to include in the individual fill_factor : float Determines how "close" the atoms are packed. See structopt.tools.get_particle_radius for description radii : list The size, in angstroms, of the ellipsoid in the x, y and z direction. If None, with ratio parameters and the average atomic radii, radii is automatically calculated. ratio : list The ratio of the dimensions of the ellipsoid in the x, y and z direction. cell : list The size, in angstroms, of the dimensions that holds the atoms object. Must be an orthogonal box. """ # Get the dimensions of the ellipsoid if required if radii is None: radius = get_particle_radius(atomlist, fill_factor) a = radius / ((ratio[1]/ratio[0])**(1.0/3.0) * (ratio[2]/ratio[0])**(1.0/3.0)) b = radius / ((ratio[0]/ratio[1])**(1.0/3.0) * (ratio[2]/ratio[1])**(1.0/3.0)) c = radius / ((ratio[0]/ratio[2])**(1.0/3.0) * (ratio[1]/ratio[2])**(1.0/3.0)) else: a, b, c = radii # Create a list of random order of the atoms chemical_symbols = [] for atom in atomlist: chemical_symbols += [atom[0]] * atom[1] random.shuffle(chemical_symbols) # Add atoms iteratively only if they fall inside the ellipsoid indiv = Atoms() while len(chemical_symbols) > 0: x, y, z = random.uniform(-a, a), random.uniform(-b, b), random.uniform(-c, c) if x**2/a**2 + y**2/b**2 + z**2/c**2 <= 1: indiv.extend(Atom(chemical_symbols.pop(), [x, y, z])) if cell is not None: indiv.set_cell(cell) indiv.center() indiv.set_pbc(True) return indiv
def permutation_crystal_multi(indiv, Optimizer): """Move function to perform Permutation of multiple atom based on atomlist with entire crystal in Defect Inputs: indiv = Individual class object to be altered Optimizer = Optimizer class object with needed parameters Outputs: indiv = Altered Individual class object """ if 'MU' in Optimizer.debug: debug = True else: debug = False if Optimizer.structure != 'Defect': Optimizer.output.write('WARNING: Crystal extended permutation attempted on non-Defect system. Skipping Mutation\n') else: indexbulk=len(indiv[0]) solid=Atoms() solid.extend(indiv[0]) solid.extend(indiv.bulki) solid.set_pbc(True) solid.set_cell(indiv[0].get_cell()) a1=solid[random.randint(0,indiv[0].get_number_of_atoms()-1)] opts=[inds for inds in solid if inds.symbol != a1.symbol] inpts=[inds for inds in solid if inds.symbol == a1.symbol] maxperm=len(inpts) if maxperm > len(opts): maxperm=len(opts) Optimizer.output.write('Multiatom Crystal-wide Permutation Mutation performed on individual\n') Optimizer.output.write('Index = '+repr(indiv.index)+'\n') if maxperm==0: Optimizer.output.write('WARNING: Permutation Mutation attempted on single atom structure system\n') natperm=0 else: natperm=random.randint(1,maxperm/2) Optimizer.output.write('Number of atoms permutated = '+repr(natperm)+'\n') for i in range(natperm): a1=inpts[random.randint(0,len(inpts)-1)] a2=opts[random.randint(0,len(opts)-1)] solid[a1.index].symbol, solid[a2.index].symbol=a2.symbol, a1.symbol Optimizer.output.write(repr(a1.symbol) + ' swapped with ' + repr(a2.symbol)+'\n') indiv.bulki=solid[indexbulk::] indiv[0]=solid[0:indexbulk] Optimizer.output.write(repr(indiv[0])+'\n') for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in solid if atm.symbol==sym]) Optimizer.output.write('Defect configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n') muttype='PCMA'+repr(natperm) if indiv.energy==0: indiv.history_index=indiv.history_index+'m'+muttype else: indiv.history_index=repr(indiv.index)+'m'+muttype return indiv
def permutation_crystal(indiv, Optimizer): """Move function to perform Permutation of one atom based on atomlist with entire crystal in Defect Inputs: indiv = Individual class object to be altered Optimizer = Optimizer class object with needed parameters Outputs: indiv = Altered Individual class object """ if 'MU' in Optimizer.debug: debug = True else: debug = False if Optimizer.structure != 'Defect': Optimizer.output.write( 'WARNING: Crystal extended permutation attempted on non-Defect system. Skipping Mutation\n' ) else: indexbulk = len(indiv[0]) solid = Atoms() solid.extend(indiv[0]) solid.extend(indiv.bulki) solid.set_pbc(True) solid.set_cell(indiv.bulko.get_cell()) a1 = solid[random.randint(0, indiv[0].get_number_of_atoms() - 1)] opts = [inds for inds in solid if inds.symbol != a1.symbol] try: a2 = opts[random.randint(0, len(opts) - 1)] except ValueError: a2 = indiv[0][random.randint(0, indiv[0].get_number_of_atoms() - 1)] Optimizer.output.write( 'WARNING: Permutation Mutation attempted on single atom structure system\n' ) solid[a1.index].symbol, solid[a2.index].symbol = a2.symbol, a1.symbol indiv.bulki = solid[indexbulk::] indiv[0] = solid[0:indexbulk] Optimizer.output.write( 'Crystal-wide Permutation Mutation performed on individual\n') Optimizer.output.write('Index = ' + repr(indiv.index) + '\n') Optimizer.output.write( repr(a1.symbol) + ' swapped with ' + repr(a2.symbol) + '\n') Optimizer.output.write(repr(indiv[0]) + '\n') for sym, c, m, u in Optimizer.atomlist: nc = len([atm for atm in solid if atm.symbol == sym]) Optimizer.output.write('Defect configuration contains ' + repr(nc) + ' ' + repr(sym) + ' atoms\n') muttype = 'PC' if indiv.energy == 0: indiv.history_index = indiv.history_index + 'm' + muttype else: indiv.history_index = repr(indiv.index) + 'm' + muttype return indiv
def unitcell(self, latx, laty): unit = Atoms('C2N', [(1 / 2 * sqrt(3), 0.5, 0.0), (1 / 2 * sqrt(3), -0.5, 0), (1 / 2 * sqrt(3), 1.5, 0)]) atoms = Atoms() for i in range(3): a = unit.copy() a.rotate('z', pi * 2 / 3 * i) atoms.extend(a) if self.centerN: atoms.append(Atom('N', (0, 0, 0))) atoms.set_cell([6 * sqrt(3) / 2, 6, 10.0]) col = unit.repeat((latx, laty, 1)) return col
def get_atoms_adsorbate(): # We need the relaxed slab here! slab = Atoms([ Atom('Cu', [ -1.028468159509163, -0.432387156877267, -0.202086055768265]), Atom('Cu', [ 0.333333333333333, 0.333333333333333, -2.146500000000000]), Atom('Cu', [ 1.671531840490805, -0.432387156877287, -0.202086055768242]), Atom('Cu', [ 3.033333333333334, 0.333333333333333, -2.146500000000000]), Atom('Cu', [ 4.371531840490810, -0.432387156877236, -0.202086055768261]), Atom('Cu', [ 5.733333333333333, 0.333333333333333, -2.146500000000000]), Atom('Cu', [ 7.071531840490944, -0.432387156877258, -0.202086055768294]), Atom('Cu', [ 8.433333333333335, 0.333333333333333, -2.146500000000000]), Atom('Cu', [ 0.321531840490810, 1.905881433340708, -0.202086055768213]), Atom('Cu', [ 1.683333333333333, 2.671601923551318, -2.146500000000000]), Atom('Cu', [ 3.021531840490771, 1.905881433340728, -0.202086055768250]), Atom('Cu', [ 4.383333333333334, 2.671601923551318, -2.146500000000000]), Atom('Cu', [ 5.721531840490857, 1.905881433340735, -0.202086055768267]), Atom('Cu', [ 7.083333333333333, 2.671601923551318, -2.146500000000000]), Atom('Cu', [ 8.421531840490820, 1.905881433340739, -0.202086055768265]), Atom('Cu', [ 9.783333333333335, 2.671601923551318, -2.146500000000000]), Atom('Cu', [ 1.671531840490742, 4.244150023558601, -0.202086055768165]), Atom('Cu', [ 3.033333333333334, 5.009870513769302, -2.146500000000000]), Atom('Cu', [ 4.371531840490840, 4.244150023558694, -0.202086055768265]), Atom('Cu', [ 5.733333333333333, 5.009870513769302, -2.146500000000000]), Atom('Cu', [ 7.071531840490880, 4.244150023558786, -0.202086055768352]), Atom('Cu', [ 8.433333333333335, 5.009870513769302, -2.146500000000000]), Atom('Cu', [ 9.771531840491031, 4.244150023558828, -0.202086055768371]), Atom('Cu', [ 11.133333333333335, 5.009870513769302, -2.146500000000000]), Atom('Cu', [ 3.021531840490714, 6.582418613776583, -0.202086055768197]), Atom('Cu', [ 4.383333333333334, 7.348139103987287, -2.146500000000000]), Atom('Cu', [ 5.721531840490814, 6.582418613776629, -0.202086055768203]), Atom('Cu', [ 7.083333333333333, 7.348139103987287, -2.146500000000000]), Atom('Cu', [ 8.421531840490985, 6.582418613776876, -0.202086055768357]), Atom('Cu', [ 9.783333333333335, 7.348139103987287, -2.146500000000000]), Atom('Cu', [ 11.121531840490929, 6.582418613776676, -0.202086055768221]), Atom('Cu', [ 12.483333333333334, 7.348139103987287, -2.146500000000000]), ]) mask = [a.position[2] < -1 for a in slab] slab.set_constraint(FixAtoms(mask=mask)) a = 2.70 c = 1.59 * a h = 1.85 d = 1.10 x = slab.positions[0, 2] / (c / 2) * 100 molecule = Atoms('2N', positions=[(0., 0., h), (0., 0., h + d)]) molecule.set_calculator(EMT()) slab.extend(molecule) return slab
def get_fingerprint(Optimizer, indiv, binsize, cutoffdist): """Function to calculate the fingerprint of a structure """ rs = numpy.linspace(0.0, cutoffdist, cutoffdist / binsize) indi = indiv[0] Vuc = indi.get_volume() if Optimizer.structure == 'Defect': solid = Atoms() solid.extend(indi) solid.extend(indiv.bulki) elif Optimizer.structure == 'Crystal': solid = indi.repeat([3, 3, 3]) else: solid = indi.copy() syms = sorted(list(set([atm.symbol for atm in solid]))) fingerprints = [] for i in range(len(syms)): for j in range(i, len(syms)): indl = [atm for atm in indi if atm.symbol == syms[i]] ind = Atoms() for one in indl: ind.append(one) soll = [atm for atm in solid if atm.symbol == syms[j]] sol = Atoms() for one in soll: sol.append(one) soli = [atm for atm in solid if atm.symbol == syms[i]] value = [] for R in rs: value2 = [] for k in range(len(ind)): value1 = [] for m in range(len(sol)): if k != m: rij = sol.get_distance(k, m, mic=True) if rij == 0: pass #pdb.set_trace() value1.append( dirac(R, a=rij, sig=0.02) * 1 / (4 * math.pi * rij**2 * binsize * len(soli) * len(sol) / Vuc)) value2.append(sum(value1)) value.append(sum(value2)) fingerprints.append(value) fpt = [] for one in fingerprints: fpt.extend(one) return fpt
def make_supercell(prim, P, wrap=True, tol=1e-5): r"""Generate a supercell by applying a general transformation (*P*) to the input configuration (*prim*). The transformation is described by a 3x3 integer matrix `\mathbf{P}`. Specifically, the new cell metric `\mathbf{h}` is given in terms of the metric of the input configuraton `\mathbf{h}_p` by `\mathbf{P h}_p = \mathbf{h}`. Parameters: prim: ASE Atoms object Input configuration. P: 3x3 integer matrix Transformation matrix `\mathbf{P}`. wrap: bool wrap in the end tol: float tolerance for wrapping """ supercell_matrix = P supercell = clean_matrix(supercell_matrix @ prim.cell) # cartesian lattice points lattice_points_frac = lattice_points_in_supercell(supercell_matrix) lattice_points = np.dot(lattice_points_frac, supercell) superatoms = Atoms(cell=supercell, pbc=prim.pbc) for lp in lattice_points: shifted_atoms = prim.copy() shifted_atoms.positions += lp superatoms.extend(shifted_atoms) # check number of atoms is correct n_target = int(np.round(np.linalg.det(supercell_matrix) * len(prim))) if n_target != len(superatoms): msg = "Number of atoms in supercell: {}, expected: {}".format( n_target, len(superatoms) ) raise SupercellError(msg) if wrap: superatoms.wrap(eps=tol) return superatoms
def update_structfile(ind, structfile, Optimizer): if Optimizer.structure == 'Defect' or Optimizer.structure == 'Surface': sols = Atoms() sols.extend(ind[0]) sols.extend(ind.bulki) elif Optimizer.structure == 'Crystal': sols = ind[0].repeat((3, 3, 3)) else: sols = ind[0].copy() positions = sols.get_positions() if Optimizer.vacancy_output: for one in ind.vacancies: sols.append(Atom(symbol='X', position=one.position)) #Optimizer.output.write('Number of positions = {0}\n'.format(len(positions))) write_xyz(structfile, sols, ind.energy) return positions
def unitcell(self,latx,laty): unit=Atoms('C2N',[(1/2*sqrt(3),0.5,0.0), (1/2*sqrt(3),-0.5,0), (1/2*sqrt(3),1.5,0)]) atoms=Atoms() for i in range(3): a=unit.copy() a.rotate('z',pi*2/3*i) atoms.extend(a) if self.centerN: atoms.append(Atom('N',(0,0,0))) atoms.set_cell([6*sqrt(3)/2,6,10.0]) col=unit.repeat((latx,laty,1)) return col
def get_atoms(): srf = Atoms('Cu64', [(1.2763, 1.2763, 4.0000), (3.8290, 1.2763, 4.0000), (6.3816, 1.2763, 4.0000), (8.9343, 1.2763, 4.0000), (1.2763, 3.8290, 4.0000), (3.8290, 3.8290, 4.0000), (6.3816, 3.8290, 4.0000), (8.9343, 3.8290, 4.0000), (1.2763, 6.3816, 4.0000), (3.8290, 6.3816, 4.0000), (6.3816, 6.3816, 4.0000), (8.9343, 6.3816, 4.0000), (1.2763, 8.9343, 4.0000), (3.8290, 8.9343, 4.0000), (6.3816, 8.9343, 4.0000), (8.9343, 8.9343, 4.0000), (0.0000, 0.0000, 5.8050), (2.5527, 0.0000, 5.8050), (5.1053, 0.0000, 5.8050), (7.6580, 0.0000, 5.8050), (0.0000, 2.5527, 5.8050), (2.5527, 2.5527, 5.8050), (5.1053, 2.5527, 5.8050), (7.6580, 2.5527, 5.8050), (0.0000, 5.1053, 5.8050), (2.5527, 5.1053, 5.8050), (5.1053, 5.1053, 5.8050), (7.6580, 5.1053, 5.8050), (0.0000, 7.6580, 5.8050), (2.5527, 7.6580, 5.8050), (5.1053, 7.6580, 5.8050), (7.6580, 7.6580, 5.8050), (1.2409, 1.2409, 7.6081), (3.7731, 1.2803, 7.6603), (6.3219, 1.3241, 7.6442), (8.8935, 1.2669, 7.6189), (1.2803, 3.7731, 7.6603), (3.8188, 3.8188, 7.5870), (6.3457, 3.8718, 7.6649), (8.9174, 3.8340, 7.5976), (1.3241, 6.3219, 7.6442), (3.8718, 6.3457, 7.6649), (6.3945, 6.3945, 7.6495), (8.9576, 6.3976, 7.6213), (1.2669, 8.8935, 7.6189), (3.8340, 8.9174, 7.5976), (6.3976, 8.9576, 7.6213), (8.9367, 8.9367, 7.6539), (0.0582, 0.0582, 9.4227), (2.5965, -0.2051, 9.4199), (5.1282, 0.0663, 9.4037), (7.6808, -0.0157, 9.4235), (-0.2051, 2.5965, 9.4199), (2.1913, 2.1913, 9.6123), (5.0046, 2.5955, 9.4873), (7.5409, 2.5336, 9.4126), (0.0663, 5.1282, 9.4037), (2.5955, 5.0046, 9.4873), (5.3381, 5.3381, 9.6106), (7.8015, 5.0682, 9.4237), (-0.0157, 7.6808, 9.4235), (2.5336, 7.5409, 9.4126), (5.0682, 7.8015, 9.4237), (7.6155, 7.6155, 9.4317)]) c2 = Atoms('C2', [(3.2897, 3.2897, 10.6627), (4.2113, 4.2113, 10.6493)]) srf.extend(c2) srf.pbc = (1, 1, 0) srf.set_cell([10.2106, 10.2106, 20.6572], scale_atoms=False) mask = [a.index < 32 for a in srf] c1 = FixedPlane(-1, (1 / np.sqrt(2), 1 / np.sqrt(2), 1)) c2 = FixedPlane(-2, (1 / np.sqrt(2), 1 / np.sqrt(2), 1)) constraint = FixAtoms(mask=mask) srf.set_constraint([constraint, c1, c2]) return srf
def ori_structure(self): lead1=self.lead1=graphene(dict(latx=1,laty=self.laty,latz=1)).lmp_structure() n=len(lead1) center=graphene(dict(latx=self.latx,laty=self.laty,latz=1)).lmp_structure() center.translate(lead1.cell[0]) lead2=lead1.copy() lead2.translate(lead1.cell[0]+center.cell[0]) atoms=Atoms() atoms.extend(lead1) atoms.extend(center) atoms.extend(lead2) atoms.cell=center.cell atoms.cell[0]=lead1.cell[0]+center.cell[0]+lead2.cell[0] lx=self.extent(atoms)[0] self.getScale(lx/2) self.center_box(atoms) self.writeatoms(atoms,'graphene') low=atoms.positions[:,0].min()+2 hi=atoms.positions[:,0].max()-2 self.leftgroup=np.arange(len(atoms),dtype='int')[:n]+1 self.rightgroup=np.arange(len(atoms),dtype='int')[-n:]+1 self.fmag=self.strain/float(len(self.leftgroup)) self.posleft=atoms.positions[self.leftgroup[0]-1].copy()+(50,50,50) self.posright=atoms.positions[self.rightgroup[0]-1].copy()+(50,50,50) self.posleft[0]*=10 self.posright[0]*=10 for atom in atoms: atom.position=self.trans(atom.position) atoms.center(vacuum=50) return atoms
def lmp_structure(self): ribbon=graphene(dict(latx=20,laty=3,latz=1,gnrtype='zigzag')).lmp_structure() self.length=ribbon.cell[0,0] self.center_box(ribbon) self.w=.2 self.getW(self.length/2) newlx=2*self.phase(self.length/2,self.w) for atom in ribbon: atom.position=self.trans(atom.position) atoms=ribbon #atoms.center(vacuum=10,axis=[1,2]) #atoms.cell[0,0]=newlx #atoms.center(axis=[0]) newatoms=Atoms() for i in range(4): atoms.rotate('z',i*pi/2,center=[0,-newlx/4,0]) newatoms.extend(atoms.copy()) newatoms.cell[0,0]=newatoms.cell[1,1]=newlx newatoms.center() atoms=newatoms#.repeat([self.latx,self.laty,1]) return atoms
def select_atoms(self, atoms): subset = None subset_map = {} subset_weights = [] k = 0 ids = Mixer.get_atom_ids(atoms) for i in range(len(atoms)): if ids[i] not in self._atom_ids: continue if not subset: subset = Atoms(atoms[i:i+1]) else: subset.extend(atoms[i:i+1]) subset_map[k] = i subset_weights.append(self._weights[ids[i]]) k += 1 wa = np.zeros((len(subset_weights), 3)) for i in range(len(subset_weights)): wa[i] += subset_weights[i] return subset, subset_map, wa
def select_atoms(self, atoms): subset = None subset_map = {} subset_weights = [] k = 0 ids = Mixer.get_atom_ids(atoms) for i in range(len(atoms)): if ids[i] not in self._atom_ids: continue if not subset: subset = Atoms(atoms[i:i + 1]) else: subset.extend(atoms[i:i + 1]) subset_map[k] = i subset_weights.append(self._weights[ids[i]]) k += 1 wa = np.zeros((len(subset_weights), 3)) for i in range(len(subset_weights)): wa[i] += subset_weights[i] return subset, subset_map, wa
def lmp_structure(self): ribbon = graphene(dict(latx=20, laty=3, latz=1, gnrtype='zigzag')).lmp_structure() self.length = ribbon.cell[0, 0] self.center_box(ribbon) self.w = .2 self.getW(self.length / 2) newlx = 2 * self.phase(self.length / 2, self.w) for atom in ribbon: atom.position = self.trans(atom.position) atoms = ribbon #atoms.center(vacuum=10,axis=[1,2]) #atoms.cell[0,0]=newlx #atoms.center(axis=[0]) newatoms = Atoms() for i in range(4): atoms.rotate('z', i * pi / 2, center=[0, -newlx / 4, 0]) newatoms.extend(atoms.copy()) newatoms.cell[0, 0] = newatoms.cell[1, 1] = newlx newatoms.center() atoms = newatoms #.repeat([self.latx,self.laty,1]) return atoms
def lmp_structure(self): atoms = Atoms() unit = graphene( dict( latx=2, laty=1, latz=1, gnrtype='zigzag')).lmp_structure() # del unit[unit.positions[:,0].argsort()[-2:]] ly = unit.cell[1][1] lidx = unit.positions[:, 0].argsort()[0] left_of_unit = unit[lidx].position # the center must be assign because the atoms are centered unit.rotate('y', 30.0 / 180 * np.pi, center=left_of_unit) ridx = unit.positions[:, 0].argsort()[-1] right_of_unit = unit[ridx].position unit1 = unit.copy() unit1.rotate('y', 120.0 / 180 * np.pi, center=right_of_unit) ridx1 = unit1.positions[:, 0].argsort()[-1] right_of_unit1 = unit1[ridx1].position # cell[0,0] lx = right_of_unit1[0] - left_of_unit[0] unit2 = unit.copy() # translate unit2 but don't traslate along y deta = right_of_unit1 - right_of_unit + [0, 0, 1.42 * np.sqrt(3) / 2] deta[1] = 0 unit2.translate(deta) lidx2 = unit2.positions[:, 0].argsort()[0] left_of_unit2 = unit2.positions[lidx2] unit3 = unit2.copy() unit3.rotate('y', 120.0 / 180 * np.pi, center=left_of_unit2) lz = left_of_unit2[2] - right_of_unit[2] + 1.42 * np.sqrt(3) / 2 atoms.extend(unit) atoms.extend(unit1) atoms.extend(unit2) atoms.extend(unit3) atoms.set_cell([lx, ly, lz]) # important for distance calculation,default all False atoms.set_pbc([True] * 3) atoms.center() atoms = atomic.get_unique_atoms(atoms) # prevent xs~=1.0 atoms.translate([0.01, 0, 0]) atomic.wrap(atoms) return atoms
def lmp_structure(self): atoms = Atoms() unit = graphene(dict(latx=2, laty=1, latz=1, gnrtype='zigzag')).lmp_structure() # del unit[unit.positions[:,0].argsort()[-2:]] ly = unit.cell[1][1] lidx = unit.positions[:, 0].argsort()[0] left_of_unit = unit[lidx].position # the center must be assign because the atoms are centered unit.rotate('y', 30.0 / 180 * np.pi, center=left_of_unit) ridx = unit.positions[:, 0].argsort()[-1] right_of_unit = unit[ridx].position unit1 = unit.copy() unit1.rotate('y', 120.0 / 180 * np.pi, center=right_of_unit) ridx1 = unit1.positions[:, 0].argsort()[-1] right_of_unit1 = unit1[ridx1].position # cell[0,0] lx = right_of_unit1[0] - left_of_unit[0] unit2 = unit.copy() # translate unit2 but don't traslate along y deta = right_of_unit1 - right_of_unit + [0, 0, 1.42 * np.sqrt(3) / 2] deta[1] = 0 unit2.translate(deta) lidx2 = unit2.positions[:, 0].argsort()[0] left_of_unit2 = unit2.positions[lidx2] unit3 = unit2.copy() unit3.rotate('y', 120.0 / 180 * np.pi, center=left_of_unit2) lz = left_of_unit2[2] - right_of_unit[2] + 1.42 * np.sqrt(3) / 2 atoms.extend(unit) atoms.extend(unit1) atoms.extend(unit2) atoms.extend(unit3) atoms.set_cell([lx, ly, lz]) # important for distance calculation,default all False atoms.set_pbc([True] * 3) atoms.center() atoms = atomic.get_unique_atoms(atoms) # prevent xs~=1.0 atoms.translate([0.01, 0, 0]) atomic.wrap(atoms) return atoms
def lmp_structure(self): atoms = Atoms() lead1 = self.m1.lmp_structure() center = self.m.lmp_structure() lead2 = self.m2.lmp_structure() atoms.extend(lead1) center.translate(lead1.cell[0]) atoms.extend(center) lead2.translate(lead1.cell[0] + center.cell[0]) atoms.extend(lead2) atoms.cell = lead1.cell.copy() #atoms.set_pbc([0,0,0]) atoms.cell[0] = lead1.cell[0] + center.cell[0] + lead2.cell[0] #atoms.center(10.0,axis=[1,2]) #atoms.center() x = atoms.positions[:, 0] return center
def lmp_structure(self): atoms=Atoms() lead1=self.m1.lmp_structure() center=self.m.lmp_structure() lead2=self.m2.lmp_structure() atoms.extend(lead1) center.translate(lead1.cell[0]) atoms.extend(center) lead2.translate(lead1.cell[0]+center.cell[0]) atoms.extend(lead2) atoms.cell=lead1.cell.copy() #atoms.set_pbc([0,0,0]) atoms.cell[0]=lead1.cell[0]+center.cell[0]+lead2.cell[0] #atoms.center(10.0,axis=[1,2]) #atoms.center() x=atoms.positions[:,0] return center
def ori_structure(self): lead1 = self.lead1 = graphene(dict(latx=1, laty=self.laty, latz=1)).lmp_structure() n = len(lead1) center = graphene(dict(latx=self.latx, laty=self.laty, latz=1)).lmp_structure() center.translate(lead1.cell[0]) lead2 = lead1.copy() lead2.translate(lead1.cell[0] + center.cell[0]) atoms = Atoms() atoms.extend(lead1) atoms.extend(center) atoms.extend(lead2) atoms.cell = center.cell atoms.cell[0] = lead1.cell[0] + center.cell[0] + lead2.cell[0] lx = self.extent(atoms)[0] self.getScale(lx / 2) self.center_box(atoms) self.writeatoms(atoms, 'graphene') low = atoms.positions[:, 0].min() + 2 hi = atoms.positions[:, 0].max() - 2 self.leftgroup = np.arange(len(atoms), dtype='int')[:n] + 1 self.rightgroup = np.arange(len(atoms), dtype='int')[-n:] + 1 self.fmag = self.strain / float(len(self.leftgroup)) self.posleft = atoms.positions[self.leftgroup[0] - 1].copy() + (50, 50, 50) self.posright = atoms.positions[self.rightgroup[0] - 1].copy() + (50, 50, 50) self.posleft[0] *= 10 self.posright[0] *= 10 for atom in atoms: atom.position = self.trans(atom.position) atoms.center(vacuum=50) return atoms
fit = 10000 message = 'Warning: Found oddly large energy from Lammps in structure HI={0}'.format( indiv.history_index) logger.warn(message) print message print ' Setting fitness to 10000' passflag = False if math.isnan(fit): logger.warn('Found NAN energy structure HI={0}'.format( indiv.history_index)) fit = 10000 passflag = False indiv.energy = 10000 if passflag: if Optimizer.structure == 'Defect': solid = Atoms() solid.extend(indiv[0]) solid.extend(indiv.bulki) else: solid = indiv[0] for sym, c, m, u in Optimizer.atomlist: for sy, cs in indiv.swaplist: if sy == sym: en -= cs * u nc = len([atm for atm in solid if atm.symbol == sym]) en -= float(nc) * float(u) indiv.fitness = en else: indiv.fitness = fit return indiv, stro
def BestInds(pop, bests, Optimizer, writefile=False, fname=None): """Function to keep track of the best individuals throughout an optimization Inputs: pop = list of Individual class structures to be compared bests = list of previously obtained best structures Optimizer = Optimizer class structure that contains key parameters writefile = True/False boolean to tell function whether or not to output structures fname = filename to output structures Outputs: bests = list of Individual class structures updated with new options """ #logger = initialize_logger(Optimizer.loggername) logger = logging.getLogger(Optimizer.loggername) logger.info('best_inds_list recieved population with length = {0} and best list with length = {1} for generation {2}'.format( len(pop),len(bests),Optimizer.generation)) pop = sorted(pop, key=attrgetter('fitness')) tol=Optimizer.demin if len(bests)!=0: bfits=[ind.fitness for ind in bests] #Identify the fitnesses in the population popfits=[ind.fitness for ind in pop] #Initialize a list for individuals to not be added to best list indices=[] for i in range(len(popfits)): for j in range(len(bfits)): if popfits[i]==bfits[j]: indices.append(i) if popfits[i] < bfits[j]: diff = abs(bfits[j] - popfits[i]) diff2 = abs(bfits[j-1] - popfits[i]) if diff > tol: if diff2 > tol: if i not in indices: bests.append(pop[i]) logger.info('Best list found new structure for List HI = {0}'.format(pop[i].history_index)) indices.append(i) b=bfits[0:j] b.append(pop[i].fitness) b.extend(bfits[j::]) bfits=b else: indices.append(i) bests = sorted(bests, key=attrgetter('fitness')) if len(bests) < Optimizer.number_of_bests: bmax = bests[len(bests)-1].fitness for i in range(len(popfits)): if popfits[i] > bmax: diff = abs(popfits[i]-bmax) if diff > tol: bests.append(pop[i]) logger.info('Appending best list with lower energy structure') bmax = pop[i].fitness else: logger.info('Removing extra {0} structures from best list'.format(len(bests)-Optimizer.number_of_bests)) bests = bests[0:Optimizer.number_of_bests] bfits=[ind.fitness for ind in bests] else: bests = [] bfits = [] for one in pop: fit = one.fitness if len(bfits) == 0: bests.append(one) logger.info('Adding new structure to best list HI = {0}'.format(one.history_index)) bfits.append(fit) else: diff = abs(bfits[-1]-fit) if diff > tol: bests.append(one) bfits.append(fit) if len(bests) > Optimizer.number_of_bests: logger.info('Removing extra {0} structures from best list'.format(len(bests)-Optimizer.number_of_bests)) bests = bests[0:Optimizer.number_of_bests] if writefile==True: if fname==None: try: rank = MPI.COMM_WORLD.Get_rank() except: rank = 0 path = os.path.join(os.getcwd(),'{0}-rank{1}'.format(Optimizer.filename,rank)) logger.info('Writing Best lists to {0}'.format(path)) fxyzname=os.path.join(path,'Bests-{0}.xyz'.format(Optimizer.filename)) ffitname=os.path.join(path,'Bests-fitnesses-{0}.txt'.format(Optimizer.filename)) else: fxyzname='{0}.xyz'.format(fname) ffitname='{0}-fitnesses.txt'.format(fname) bestfile=open(fxyzname,'w') bestfitfile=open(ffitname,'w') for one in bests: if Optimizer.structure=='Defect': cbulk=Atoms() cbulk.extend(one[0]) cbulk.extend(one.bulki) write_xyz(bestfile,cbulk,one.energy) else: write_xyz(bestfile,one[0],one.energy) bestfitfile.write(repr(one.fitness)+'\n') bestfile.close() bestfitfile.close() return bests
def rotate_fixed(individual1, individual2, align_cutoff=0.1, repair_composition=True): """Similar to rotate except the children aren't borne out of cut out versions. Parameters ---------- individual1 : Individual The first parent individual2 : Individual The second parent center_at_atom : bool This centers the cut at an atom. This is particularly useful when one desires a crystalline solution. If both parents are crystalline, the children will likely not have grain boundaries. repair_composition : bool If True, conserves composition. For crossovers that create children with more (less) atoms, atoms are taken from (added to) the surface of the particle. For incorrect atomic ratios, atomic symbols are randomly interchanged throughout the particle Returns ------- Individual: The first child Individual: The second child """ # Translate individuals so atoms are most aligned # Pick a random rotation angle and vector rot_vec = random_three_vector() rot_angle = random.uniform(0, 180) * np.pi / 180.0 # Rotate both individuals ind1c.rotate(rot_vec, a=rot_angle, center=(0, 0, 0)) ind2c.rotate(rot_vec, a=rot_angle, center=(0, 0, 0)) # Create the children child1 = Atoms(cell=ind1c.get_cell()) child2 = Atoms(cell=ind2c.get_cell()) child1.extend(ind1c[ind1c.positions[:, 2] >= 0]) child1.extend(ind2c[ind2c.positions[:, 2] < 0]) child2.extend(ind2c[ind2c.positions[:, 2] >= 0]) child2.extend(ind1c[ind1c.positions[:, 2] < 0]) # Repair the children if repair_composition: syms = ind1c.get_chemical_symbols() atomlist = [[sym, syms.count(sym)] for sym in set(syms)] repair_cluster(child1, atomlist) repair_cluster(child2, atomlist) # Reorient the children child1.rotate(rot_vec, a=-rot_angle, center=(0, 0, 0)) child1.center() child2.rotate(rot_vec, a=-rot_angle, center=(0, 0, 0)) child2.center() # Convert the children to an Individual with the parent # module parameters full_child1 = ind1c.copy(include_atoms=False) full_child1.extend(child1) full_child2 = ind2c.copy(include_atoms=False) full_child2.extend(child2) return full_child1, full_child2
def eval_energy(Optimizer, individ): """Function to evaluate energy of an individual Inputs: input = [Optimizer class object with parameters, Individual class structure to be evaluated] Outputs: energy, bul, individ, signal energy = energy of Individual evaluated bul = bulk structure of Individual if simulation structure is Defect individ = Individual class structure evaluated signal = string of information about evaluation """ #logger = initialize_logger(Optimizer.loggername) logger = logging.getLogger(Optimizer.loggername) if 'MAST' in Optimizer.calc_method: energy = individ.energy bul = individ.bulki signal = 'Received MAST structure\n' logger.info('Received individual index = {0} from MAST with energy {1}. Returning with no evaluation'.format( individ.index, individ.energy)) else: if Optimizer.parallel: rank = MPI.COMM_WORLD.Get_rank() logger.info('Received individual HI = {0} with energy {1} for energy evaluation'.format( individ.history_index, individ.energy)) STR='----Individual ' + str(individ.history_index)+ ' Optimization----\n' indiv=individ[0] if 'EE' in Optimizer.debug: debug = True else: debug = False if debug: write_xyz(Optimizer.debugfile,indiv,'Received by eval_energy') Optimizer.debugfile.flush() logger.debug('Writing recieved individual to debug file') # Establish individual structure for evaluation. Piece together regions when necessary. if Optimizer.structure=='Defect': indi=indiv.copy() bulk=individ.bulki nat=indi.get_number_of_atoms() if debug: logger.info('Extending defect structure to include bulk len(r1+r2)={0} len(bulk)={1}'.format(nat,len(bulk))) csize=bulk.get_cell() totalsol=Atoms(cell=csize, pbc=True) totalsol.extend(indi) totalsol.extend(bulk) for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in totalsol if atm.symbol==sym]) STR+='Defect configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n' elif Optimizer.structure=='Surface': totalsol=Atoms() totalsol.extend(indiv) nat=indiv.get_number_of_atoms() totalsol.extend(individ.bulki) if debug: logger.info('Extending surface structure to include bulk len(r1+r2)={0} len(bulk)={1}'.format(nat,len(individ.bulki))) for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in totalsol if atm.symbol==sym]) STR+='Surface-Bulk configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n' cell=numpy.maximum.reduce(indiv.get_cell()) totalsol.set_cell([cell[0],cell[1],500]) totalsol.set_pbc([True,True,False]) elif Optimizer.structure=='Cluster': totalsol = indiv.copy() nat = len(totalsol) if debug: logger.info('Extending cluster with {0} atoms to center of evaluation box of size {1}'.format(nat,Optimizer.large_box_size)) origcell = indiv.get_cell() totalsol.set_cell([Optimizer.large_box_size,Optimizer.large_box_size,Optimizer.large_box_size]) totalsol.translate([Optimizer.large_box_size/2.0,Optimizer.large_box_size/2.0,Optimizer.large_box_size/2.0]) elif Optimizer.structure=='Crystal': totalsol = indiv.copy() nat = len(totalsol) else: print 'WARNING: In EvalEnergy. Optimizer.structure not recognized' logger.warning('Optimizer.structure not recognized') # Check for atoms that are too close or out of constrained location if Optimizer.constrain_position: if Optimizer.structure=='Defect': if debug: logger.info('Constraining positions of defect') totalsol, stro = constrain_positions(totalsol, Optimizer.solidbulk, Optimizer.sf) if debug: logger.info(stro) STR+=str0 min_len=0.7 if not Optimizer.fixed_region: if debug: logger.info('Running check minimum distance') totalsol, STR = check_min_dist(totalsol, Optimizer.structure, nat, min_len, STR) if debug: write_xyz(Optimizer.debugfile,totalsol,'After minlength check') Optimizer.debugfile.flush() logger.debug('Writing individual after checking minimum length') # Set calculator to use to get forces/energies if Optimizer.parallel: calc = setup_calculator(Optimizer) if Optimizer.fixed_region: if debug: logger.info('Setting up fixed region calculator') pms=copy.deepcopy(calc.parameters) try: pms['mass'][len(pms['mass'])-1] += '\ngroup RO id >= {0}\nfix freeze RO setforce 0.0 0.0 0.0\n'.format(nat) except KeyError: pms['pair_coeff'][0] += '\ngroup RO id >= {0}\nfix freeze RO setforce 0.0 0.0 0.0\n'.format(nat) calc = LAMMPS(parameters=pms, files=calc.files, keep_tmp_files=calc.keep_tmp_files, tmp_dir=calc.tmp_dir) lmin = copy.copy(Optimizer.lammps_min) if debug: logger.info('Setting up no local minimization calculator') Optimizer.lammps_min = None Optimizer.static_calc = setup_calculator(Optimizer) Optimizer.lammps_min = lmin else: calc=Optimizer.calc totalsol.set_calculator(calc) totalsol.set_pbc(True) # Perform Energy Minimization if not Optimizer.parallel: if debug: write_xyz(Optimizer.debugfile,totalsol,'Individual sent to Energy Minimizer') logger.debug('Writing structure sent to energy minimizer') try: cwd = os.getcwd() if Optimizer.ase_min == True: if debug: logger.info('Running ASE minimizer') if Optimizer.calc_method=='LennardJones': logger.warn('Must run ase LJ calculator with pbc=False') totalsol.set_pbc(False) totalsol, energy, pressure, volume, STR = run_ase_min(totalsol, Optimizer.ase_min_fmax, Optimizer.ase_min_maxsteps, Optimizer.fitness_scheme, STR) else: if debug: logger.info('Running local energy calculator') if Optimizer.fixed_region: totalsol, energy, pressure, volume, STR = run_energy_eval(totalsol, Optimizer.calc_method, Optimizer.fixed_region, Optimizer.fitness_scheme, STR, Optimizer.static_calc) else: totalsol, energy, pressure, volume, STR = run_energy_eval(totalsol, Optimizer.calc_method, False, Optimizer.fitness_scheme, STR) except Exception, e: logger.critical('Error in energy evaluation: {0}'.format(e), exc_info=True) path = os.path.join(cwd,'TroubledLammps') if not os.path.exists(path): os.mkdir(path) #Copy files over shutil.copyfile(calc.trajfile,os.path.join(path,os.path.basename(calc.trajfile))) shutil.copyfile(calc.infile,os.path.join(path,os.path.basename(calc.infile))) shutil.copyfile(calc.logfile,os.path.join(path,os.path.basename(calc.logfile))) shutil.copyfile(calc.datafile,os.path.join(path,os.path.basename(calc.datafile))) raise RuntimeError('{0}:{1}'.format(Exception,e)) if not Optimizer.parallel: if debug: write_xyz(Optimizer.debugfile,totalsol,'Individual after Energy Minimization') Optimizer.debugfile.flush() logger.debug('Writing structure recieved from energy minimizer') # Separate structures into distinct pieces if Optimizer.structure=='Defect': if Optimizer.fixed_region==True or Optimizer.finddefects==False: if debug: logger.info('Identifying atoms in defect structure based on ID') individ[0]=totalsol[0:nat] bul=totalsol[(nat):len(totalsol)] individ[0].set_cell(csize) else: if debug: logger.info('Applying find defects scheme to identify R1 and R2 for Defect') if 'FD' in Optimizer.debug: outt=find_defects(totalsol,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=Optimizer.debugfile) else: outt=find_defects(totalsol,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=False) individ[0]=outt[0] bul=outt[1] individ.vacancies = outt[2] individ.swaps = outt[3] STR += outt[4] indiv=individ[0] elif Optimizer.structure=='Surface': if debug: logger.info('Finding surface top layer') top,bul=find_top_layer(totalsol,Optimizer.surftopthick) indiv=top.copy() individ[0]=top.copy() bul = Atoms() elif Optimizer.structure=='Crystal': if debug: logger.info('Checking crystal cell type') celltype = check_cell_type(totalsol) STR+='Cell structure = {0}\n'.format(celltype) bul = Atoms() individ[0] = totalsol.copy() elif Optimizer.structure=='Cluster': volume = get_cluster_volume(totalsol) bul = Atoms() if debug: logger.info('Translating cluster back to smaller box size location') totalsol.translate([-Optimizer.large_box_size/2.0,-Optimizer.large_box_size/2.0,-Optimizer.large_box_size/2.0]) totalsol.set_cell(origcell) individ[0] = totalsol.copy() # Add concentration energy dependence if Optimizer.forcing=='energy_bias': if debug: logger.info('Applying energy bias for atoms with different number of atoms of type than in atomlist') n=[0]*len(Optimizer.atomlist) for i in range(len(Optimizer.atomlist)): n[i]=len([inds for inds in totalsol if inds.symbol==Optimizer.atomlist[i][0]]) n[i]=abs(n[i]-Optimizer.atomlist[i][1]) factor=sum(n)**3 energy=(energy+factor)/totalsol.get_number_of_atoms() STR+='Energy with Bias = {0}\n'.format(energy) elif Optimizer.forcing=='chem_pot': if debug: logger.info('Applying chemical potential bias for atoms with different number of atoms of type than in atomlist') n=[0]*len(Optimizer.atomlist) for i in range(len(Optimizer.atomlist)): n[i]=len([inds for inds in totalsol if inds.symbol==Optimizer.atomlist[i][0]]) n[i]=n[i]*Optimizer.atomlist[i][3] factor=sum(n) energy=(energy+factor)/totalsol.get_number_of_atoms() STR+='Energy with Chemical Potential = {0}\n'.format(energy) individ.energy=energy individ.buli=bul individ.pressure=pressure individ.volume=volume if Optimizer.fingerprinting: if debug: logger.info('Identifying fingerprint of new structure') individ.fingerprint=get_fingerprint(Optimizer,individ,Optimizer.fpbin,Optimizer.fpcutoff) if Optimizer.parallel: calc.clean() signal = 'Evaluated individual {0} on {1}\n'.format(individ.index,rank) signal +=STR else: signal=STR
from ase import units """ This script generates a cube evenly, but randomly filled out with CH4 molecules, and two "trains" of CH4 molecules that are set in motion. """ atoms = Atoms() # First do the random molecules methane_cube_pos = 100.0 * np.random.rand(100, 3) - 50.0 for i in range(len(methane_cube_pos)): m = molecule("CH4") m.set_positions(m.get_positions() + methane_cube_pos[i]) atoms.extend(m) MaxwellBoltzmannDistribution(atoms, 100*units.kB) # random completed, now the two trains v = 100.0 / (0.1 * units.fs * 1000) # 1000 simulation steps to cover # from edge to edge spread = np.linspace(-50.0, 50.0, 10) v_array = np.array([v] * (len(spread))) t1_x = spread t1_y = np.zeros_like(spread) t1_z = np.zeros_like(spread) v1_x = v_array v1_y = np.zeros_like(v_array)
def get_defect_indiv_random(Optimizer): """ Function to generate a structopt Individual class structure with a defect structure. Inputs: Optimizer = structopt Optimizer class object Outputs: individ = structopt Individual class object containing defect structure data """ #Initialize Bulk - Generate or load positions of bulk solid if not Optimizer.solidbulk: if 'Island_Method' not in Optimizer.algorithm_type: outfilename = os.path.join(os.path.join(os.getcwd(),Optimizer.filename),'Bulkfile.xyz') else: from mpi4py import MPI rank = MPI.COMM_WORLD.Get_rank() outfilename = os.path.join(os.path.join(os.getcwd(),Optimizer.filename+'-rank'+repr(rank)),'Bulkfile.xyz') if Optimizer.evalsolid: if Optimizer.parallel: from StructOpt.tools.setup_energy_calculator import setup_energy_calculator Optimizer.calc = setup_energy_calculator(Optimizer) bulk1, PureBulkEnpa, stro = gen_solid(Optimizer.solidfile, Optimizer.solidcell,outfilename,Optimizer.calc,Optimizer.calc_method) Optimizer.output.write(stro) else: bulk1 = gen_solid(Optimizer.solidfile,Optimizer.solidcell,outfilename) PureBulkEnpa = 0 natomsbulk = len(bulk1) Optimizer.solidbulk = bulk1.copy() Optimizer.purebulkenpa = PureBulkEnpa Optimizer.natomsbulk = natomsbulk # Identify nearby atoms for region 2 inclusion bulk = Optimizer.solidbulk.copy() bulkcom = bulk.get_center_of_mass() bulk.translate(-bulkcom) if Optimizer.sf != 0: bulk.append(Atom(position=[0,0,0])) nbulk = Atoms(pbc=True, cell=bulk.get_cell()) nr2 = Atoms(pbc=True, cell=bulk.get_cell()) for i in range(len(bulk)-1): dist = bulk.get_distance(-1,i) if dist <= Optimizer.sf: nr2.append(bulk[i]) else: nbulk.append(bulk[i]) else: nbulk = bulk.copy() nr2 = Atoms(pbc=True, cell=bulk.get_cell()) #Update atom list with atoms in region 2 natlist = [] for sym,c,m,u in Optimizer.atomlist: atsym = [atm for atm in nr2 if atm.symbol==sym] natlist.append((sym,len(atsym),m,u)) # Generate random individual and region 2 if 'sphere' in Optimizer.generate_flag: ind = gen_pop_sphere(Optimizer.atomlist,Optimizer.size) elif 'dumbbell' in Optimizer.generate_flag: ind = Atoms(cell=[Optimizer.size for i in range(3)], pbc=True) for sym,c,m,u in Optimizer.atomlist: if c > 0: dums = generate_dumbbells(c, dumbbellsym=sym, nindiv=1, solid = Optimizer.solidbulk, size=Optimizer.size)[0] ind.extend(dums) else: ind = gen_pop_box(Optimizer.atomlist,Optimizer.size) nnr2 = gen_pop_sphere(natlist, Optimizer.sf*2.0) nnr2.translate([-Optimizer.sf,-Optimizer.sf,-Optimizer.sf]) nnr2.set_pbc(True) nnr2.set_cell(bulk.get_cell()) # Initialize class individual with known values individ = Individual(ind) individ.purebulkenpa = Optimizer.purebulkenpa individ.natomsbulk = Optimizer.natomsbulk # Combine individual with R2 icom = ind.get_center_of_mass() ind.translate(-icom) ind.extend(nnr2) ind.set_pbc(True) ind.set_cell(bulk.get_cell()) # Recenter structure nbulk.translate(bulkcom) ind.translate(bulkcom) individ[0] = ind.copy() individ.bulki = nbulk.copy() individ.bulko = nbulk.copy() bulk = nbulk.copy() bul = bulk.copy() for atm in individ[0]: bul.append(atm) indices = [] for sym,c,m,u in Optimizer.atomlist: if c < 0: if Optimizer.randvacst: alist = [one for one in bul if one.symbol==sym] count = abs(c) while count > 0: indices.append(random.choice(alist).index) count -= 1 else: pos = individ[0][0:Optimizer.natoms].get_center_of_mass() count = abs(c) bul.append(Atom(position=pos)) alist = [one for one in bul if one.symbol==sym] alistd = [(bul.get_distance(len(bul)-1,one.index),one.index) for one in alist] alistd.sort(reverse=True) bul.pop() while count > 0: idx = alistd.pop()[1] indices.append(idx) count-=1 if len(indices) !=0: nbulklist = [at for at in bul if at.index not in indices and at.index<len(bulk)] nalist = [at for at in bul if at.index not in indices and at.index>=len(bulk)] bulkn = Atoms(cell=bulk.get_cell(),pbc=True) for atm in nbulklist: bulkn.append(atm) individ.bulki = bulkn.copy() individ.bulko = bulkn.copy() newind = Atoms() for atm in nalist: newind.append(atm) newind.set_cell(individ[0].get_cell()) newind.set_pbc(True) individ[0] = newind return individ
def rotate(individual1, individual2, center_at_atom=True, repair_composition=True): """Rotates the two individuals around their centers of mass, splits them in half at the xy-plane, then splices them together. Maintains number of atoms. Note, both individuals are rotated in the same way. Parameters ---------- individual1 : Individual The first parent individual2 : Individual The second parent center_at_atom : bool This centers the cut at an atom. This is particularly useful when one desires a crystalline solution. If both parents are crystalline, the children will likely not have grain boundaries. repair_composition : bool If True, conserves composition. For crossovers that create children with more (less) atoms, atoms are taken from (added to) the surface of the particle. For incorrect atomic ratios, atomic symbols are randomly interchanged throughout the particle Returns ------- Individual: The first child Individual: The second child """ # Translate individuals so COP is at (0, 0, 0) ind1c = individual1.copy() ind2c = individual2.copy() cop1 = ind1c.get_positions().mean(axis=0) cop2 = ind2c.get_positions().mean(axis=0) if center_at_atom: offset = get_offset(ind1c, ind2c, r=1.0, HWHM=0.4) ind1c.translate(offset) cop = ind1c.get_positions().mean(axis=0) ind1c.translate(-cop) ind2c.translate(-cop) else: ind1c.translate(ind1c.get_positions().mean(axis=0)) ind2c.translate(ind2c.get_positions().mean(axis=0)) # Pick a random rotation angle and vector rot_vec = random_three_vector() rot_angle = random.uniform(0, 180) * np.pi / 180.0 # Rotate both individuals ind1c.rotate(rot_vec, a=rot_angle, center=(0, 0, 0)) ind2c.rotate(rot_vec, a=rot_angle, center=(0, 0, 0)) # Create the children child1 = Atoms(cell=ind1c.get_cell()) child2 = Atoms(cell=ind2c.get_cell()) child1.extend(ind1c[ind1c.positions[:,2] >= 0]) child1.extend(ind2c[ind2c.positions[:,2] < 0]) child2.extend(ind2c[ind2c.positions[:,2] >= 0]) child2.extend(ind1c[ind1c.positions[:,2] < 0]) # Repair the children if repair_composition: syms = ind1c.get_chemical_symbols() atomlist = [[sym, syms.count(sym)] for sym in set(syms)] repair_cluster(child1, atomlist) repair_cluster(child2, atomlist) # Reorient the children child1.rotate(rot_vec, a=-rot_angle, center=(0, 0, 0)) child1.center() child2.rotate(rot_vec, a=-rot_angle, center=(0, 0, 0)) child2.center() # Convert the children to an Individual with the parent # module parameters full_child1 = ind1c.copy(include_atoms=False) full_child1.extend(child1) full_child2 = ind2c.copy(include_atoms=False) full_child2.extend(child2) return full_child1, full_child2
a = 2.70 c = 1.59 * a h = 1.85 d = 1.10 slab = Atoms('2Cu', [(0., 0., 0.), (1 / 3., 1 / 3., -0.5 * c)], tags=(0, 1), pbc=(1, 1, 0)) slab.set_cell([(a, 0, 0), (a / 2, 3**0.5 * a / 2, 0), (0, 0, 1)]) slab = slab.repeat((4, 4, 1)) slab.set_calculator(EMT()) mask = [a.tag == 1 for a in slab] slab.set_constraint(FixAtoms(mask=mask)) dyn = QuasiNewton(slab) dyn.run(fmax=0.05) e_slab = slab.get_potential_energy() x = slab.positions[0, 2] / (c / 2) * 100 print 'Relaxation of the top layer: %f %%' % x molecule = Atoms('2N', positions=[(0., 0., h), (0., 0., h + d)]) molecule.set_calculator(EMT()) e_N2 = molecule.get_potential_energy() slab.extend(molecule) dyn = QuasiNewton(slab) dyn.run(fmax=0.05) print 'Adsorption energy:', e_slab + e_N2 - slab.get_potential_energy()
def check_pop(self, pop): # Gather all the energies/fitnesses if self.output_format=='totalenergy': complist = [ind.energy for ind in pop] elif self.output_format=='formation_energy': complist = [] for ind in pop: solid=Atoms() solid.extend(ind[0]) solid.extend(ind.bulki) energy=ind.energy for sym,c,m,u in self.atomlist: nc=len([atm for atm in solid if atm.symbol==sym]) energy-= float(nc)*float(u) complist.append(energy) elif self.output_format=='formation_energy_per_int': complist = [] for ind in pop: solid=Atoms() solid.extend(ind[0]) solid.extend(ind.bulki) energy=ind.energy for sym,c,m,u in self.atomlist: nc=len([atm for atm in solid if atm.symbol==sym]) energy-= float(nc)*float(u) energy=energy/self.natoms complist.append(energy) elif self.output_format=='formation_energy2': complist = [(ind.energy - ind.purebulkenpa*(ind[0].get_number_of_atoms()+ind.bulki.get_number_of_atoms()))/(ind[0].get_number_of_atoms()+ind.bulki.get_number_of_atoms()-ind.natomsbulk) for ind in pop] elif self.output_format=='energy_per_atom': complist = [ind.energy/(ind[0].get_number_of_atoms()+ind.bulki.get_number_of_atoms()) for ind in pop] else: complist = [ind.fitness for ind in pop] # Calcluate and print the Stats length = len(pop) mean = sum(complist) / length complist.sort() medium = complist[length/2] sum2 = sum(x*x for x in complist) std = abs(sum2 / length - mean**2)**0.5 mine = min(complist) maxe = max(complist) self.output.write('\n----Stats----\n') self.output.write(' Min '+repr(mine)+'\n') self.output.write(' Max '+repr(maxe)+'\n') self.output.write(' Avg '+repr(mean)+'\n') self.output.write(' Medium '+repr(medium)+'\n') self.output.write(' Std '+repr(std)+'\n') self.output.write(' Genrep '+repr(self.genrep)+'\n') self.summary.write('{Gen} {Fitmin} {Fitavg} {Fitmed} {Fitmax} {Std} {time}\n'.format( Gen=str(self.generation),Fitmin=repr(mine),Fitavg=repr(mean),Fitmed=repr(medium),Fitmax=repr(maxe), Std=repr(std),time=repr(time.asctime( time.localtime(time.time()) )))) # Set new index values and write population index1 = 0 for ind in pop: ind.index=index1 index1+=1 inp_out.write_pop(self,pop) if self.allenergyfile: for ind in pop: self.tenergyfile.write(repr(ind.energy)+' ') self.tenergyfile.write('\n') #Check Convergence of population based on fitness fitnesses = [ind.fitness for ind in pop] popmin = min(fitnesses) popmean = sum(fitnesses) / len(fitnesses) sum2 = sum(x*x for x in fitnesses) popstd = abs(sum2 / len(fitnesses) - popmean**2)**0.5 convergence = False if self.convergence_scheme=='gen_rep_min': if self.generation < self.maxgen: if self.generation == 0: self.minfit = popmin if abs(self.minfit - popmin) < self.tolerance: self.genrep += 1 else: self.genrep = 0 self.minfit = popmin if self.genrep > self.reqrep: self.convergence = True else: self.convergence = True elif self.convergence_scheme=='gen_rep_avg': if self.generation < self.maxgen: if self.generation == 0: self.minfit = popmean if abs(self.minfit - popmean) < self.tolerance: self.genrep += 1 else: self.genrep = 0 self.minfit = popmean if self.genrep > self.reqrep: self.convergence = True else: self.convergence = True elif self.convergence_scheme=='std': if popstd < self.tolerance: self.convergence = True else:#self.convergence_scheme=='max_gen': if self.generation > self.maxgen: self.convergence = True #Flush output to files self.output.flush() self.summary.flush() for ind in self.files: ind.flush() if self.indiv_defect_write: for ind in self.ifiles: ind.flush() if self.genealogy: self.Genealogyfile.flush() if self.allenergyfile: self.tenergyfile.flush() if 'MA' in self.debug: self.debugfile.flush() if self.fingerprinting: self.fpfile.flush() self.fpminfile.flush() return self
if abs(fit) > Optimizer.energy_cutoff_factor*(len(indiv[0])+len(indiv.bulki)): fit=10000 message = 'Warning: Found oddly large energy from Lammps in structure HI={0}'.format(indiv.history_index) logger.warn(message) print message print ' Setting fitness to 10000' passflag = False if math.isnan(fit): logger.warn('Found NAN energy structure HI={0}'.format(indiv.history_index)) fit=10000 passflag = False indiv.energy = 10000 if passflag: if Optimizer.structure=='Defect': solid=Atoms() solid.extend(indiv[0]) solid.extend(indiv.bulki) else: solid = indiv[0] for sym,c,m,u in Optimizer.atomlist: for sy,cs in indiv.swaplist: if sy==sym: en -= cs * u nc=len([atm for atm in solid if atm.symbol==sym]) en -= float(nc)*float(u) indiv.fitness = en else: indiv.fitness = fit return indiv, stro
def eval_energy(input): """Function to evaluate energy of an individual Inputs: input = [Optimizer class object with parameters, Individual class structure to be evaluated] Outputs: energy, bul, individ, signal energy = energy of Individual evaluated bul = bulk structure of Individual if simulation structure is Defect individ = Individual class structure evaluated signal = string of information about evaluation """ if input[0]==None: energy=0 bul=0 individ=0 rank = MPI.COMM_WORLD.Get_rank() signal='Evaluated none individual on '+repr(rank)+'\n' else: [Optimizer, individ]=input if Optimizer.calc_method=='MAST': energy = individ.energy bul = individ.energy signal = 'Recieved MAST structure\n' else: if Optimizer.parallel: rank = MPI.COMM_WORLD.Get_rank() if not Optimizer.genealogy: STR='----Individual ' + str(individ.index)+ ' Optimization----\n' else: STR='----Individual ' + str(individ.history_index)+ ' Optimization----\n' indiv=individ[0] if 'EE' in Optimizer.debug: debug = True else: debug = False if debug: write_xyz(Optimizer.debugfile,indiv,'Recieved by eval_energy') Optimizer.debugfile.flush() if Optimizer.structure=='Defect': indi=indiv.copy() if Optimizer.alloy==True: bulk=individ.bulki else: bulk=individ.bulko nat=indi.get_number_of_atoms() csize=bulk.get_cell() totalsol=Atoms(cell=csize, pbc=True) totalsol.extend(indi) totalsol.extend(bulk) for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in totalsol if atm.symbol==sym]) STR+='Defect configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n' elif Optimizer.structure=='Surface': totalsol=Atoms() totalsol.extend(indiv) nat=indiv.get_number_of_atoms() totalsol.extend(individ.bulki) for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in totalsol if atm.symbol==sym]) STR+='Surface-Bulk configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n' cell=numpy.maximum.reduce(indiv.get_cell()) totalsol.set_cell([cell[0],cell[1],500]) totalsol.set_pbc([True,True,False]) if Optimizer.constrain_position: ts = totalsol.copy() indc,indb,vacant,swap,stro = find_defects(ts,Optimizer.solidbulk,0) sbulk = Optimizer.solidbulk.copy() bcom = sbulk.get_center_of_mass() #totalsol.translate(-bulkcom) #indc.translate(-bulkcom) #totalsol.append(Atom(position=[0,0,0])) # for one in indc: # index = [atm.index for atm in totalsol if atm.position[0]==one.position[0] and atm.position[1]==one.position[1] and atm.position[2]==one.position[2]][0] # if totalsol.get_distance(-1,index) > Optimizer.sf: # r = random.random() # totalsol.set_distance(-1,index,Optimizer.sf*r,fix=0) # totalsol.pop() # totalsol.translate(bulkcom) com = indc.get_center_of_mass() dist = (sum((bcom[i] - com[i])**2 for i in range(3)))**0.5 if dist > Optimizer.sf: STR+='Shifting structure to within region\n' r = random.random()*Optimizer.sf comv = numpy.linalg.norm(com) ncom = [one*r/comv for one in com] trans = [ncom[i]-com[i] for i in range(3)] indices = [] for one in indc: id = [atm.index for atm in totalsol if atm.position[0]==one.position[0] and atm.position[1]==one.position[1] and atm.position[2]==one.position[2]][0] totalsol[id].position += trans # Check for atoms that are too close min_len=0.7 #pdb.set_trace() if not Optimizer.fixed_region: if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': cutoffs=[2.0 for one in totalsol] nl=NeighborList(cutoffs,bothways=True,self_interaction=False) nl.update(totalsol) for one in totalsol[0:nat]: nbatoms=Atoms() nbatoms.append(one) indices, offsets=nl.get_neighbors(one.index) for index, d in zip(indices,offsets): index = int(index) sym=totalsol[index].symbol pos=totalsol[index].position + numpy.dot(d,totalsol.get_cell()) at=Atom(symbol=sym,position=pos) nbatoms.append(at) while True: dflag=False for i in range(1,len(nbatoms)): d=nbatoms.get_distance(0,i) if d < min_len: nbatoms.set_distance(0,i,min_len+.01,fix=0.5) STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n' dflag=True if dflag==False: break for i in range(len(indices)): totalsol[indices[i]].position=nbatoms[i+1].position totalsol[one.index].position=nbatoms[0].position nl.update(totalsol) if debug: write_xyz(Optimizer.debugfile,totalsol,'After minlength check') Optimizer.debugfile.flush() else: for i in range(len(indiv)): for j in range(len(indiv)): if i != j: d=indiv.get_distance(i,j) if d < min_len: indiv.set_distance(i,j,min_len,fix=0.5) STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n' if debug: write_xyz(Optimizer.debugfile,indiv,'After minlength check') Optimizer.debugfile.flush() # Set calculator to use to get forces/energies if Optimizer.parallel: calc = setup_calculator(Optimizer) if Optimizer.fixed_region: pms=copy.deepcopy(calc.parameters) try: pms['mass'][len(pms['mass'])-1] += '\ngroup RO id >= '+repr(nat)+'\nfix freeze RO setforce 0.0 0.0 0.0\n' except KeyError: pms['pair_coeff'][0] += '\ngroup RO id >= '+repr(nat)+'\nfix freeze RO setforce 0.0 0.0 0.0\n' calc = LAMMPS(parameters=pms, files=calc.files, keep_tmp_files=calc.keep_tmp_files, tmp_dir=calc.tmp_dir) lmin = copy.copy(Optimizer.lammps_min) Optimizer.lammps_min = None Optimizer.static_calc = setup_calculator(Optimizer) Optimizer.lammps_min = lmin else: calc=Optimizer.calc if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': totalsol.set_calculator(calc) totalsol.set_pbc(True) else: indiv.set_calculator(calc) indiv.set_pbc(True) #Current bug in ASE optimizer-Lammps prevents pbc=false if Optimizer.structure=='Cluster': indiv.set_cell([500,500,500]) indiv.translate([250,250,250]) cwd=os.getcwd() # Perform Energy Minimization if not Optimizer.parallel: Optimizer.output.flush() if Optimizer.ase_min == True: try: if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': dyn=BFGS(totalsol) else: dyn=BFGS(indiv) dyn.run(fmax=Optimizer.ase_min_fmax, steps=Optimizer.ase_min_maxsteps) except OverflowError: STR+='--- Error: Infinite Energy Calculated - Implement Random ---\n' box=Atoms() indiv=gen_pop_box(Optimizer.natoms, Optimizer.atomlist, Optimizer.size) indiv.set_calculator(calc) dyn=BFGS(indiv) dyn.run(fmax=fmax, steps=steps) except numpy.linalg.linalg.LinAlgError: STR+='--- Error: Singular Matrix - Implement Random ---\n' indiv=gen_pop_box(Optimizer.natoms, Optimizer.atomlist, Optimizer.size) indiv.set_calculator(calc) dyn=BFGS(indiv) dyn.run(fmax=fmax, steps=steps) # Get Energy of Minimized Structure if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': en=totalsol.get_potential_energy() #force=numpy.maximum.reduce(abs(totalsol.get_forces())) if Optimizer.fitness_scheme == 'enthalpyfit': pressure=totalsol.get_isotropic_pressure(totalsol.get_stress()) cell_max=numpy.maximum.reduce(totalsol.get_positions()) cell_min=numpy.minimum.reduce(totalsol.get_positions()) cell=cell_max-cell_min volume=cell[0]*cell[1]*cell[2] else: pressure=0 volume=0 na=totalsol.get_number_of_atoms() ena=en/na energy=en individ[0]=totalsol[0:nat] bul=totalsol[(nat):len(totalsol)] STR+='Number of positions = '+repr(len(bul)+len(individ[0]))+'\n' individ[0].set_cell(csize) indiv=individ[0] else: en=indiv.get_potential_energy() if Optimizer.fitness_scheme == 'enthalpyfit': pressure=indiv.get_isotropic_pressure(indiv.get_stress()) cell_max=numpy.maximum.reduce(indiv.get_positions()) cell_min=numpy.minimum.reduce(indiv.get_positions()) cell=cell_max-cell_min volume=cell[0]*cell[1]*cell[2] else: pressure=0 volume=0 na=indiv.get_number_of_atoms() ena=en/na energy=ena individ[0]=indiv bul=0 else: if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': if Optimizer.calc_method=='VASP': en=totalsol.get_potential_energy() calcb=Vasp(restart=True) totalsol=calcb.get_atoms() stress=calcb.read_stress() else: try: totcop=totalsol.copy() if debug: write_xyz(Optimizer.debugfile,totcop,'Individual sent to lammps') OUT=totalsol.calc.calculate(totalsol) totalsol=OUT['atoms'] totalsol.set_pbc(True) if Optimizer.fixed_region: if debug: print 'Energy of fixed region calc = ', OUT['thermo'][-1]['pe'] totalsol.set_calculator(Optimizer.static_calc) OUT=totalsol.calc.calculate(totalsol) totalsol=OUT['atoms'] totalsol.set_pbc(True) if debug: print 'Energy of static calc = ', OUT['thermo'][-1]['pe'] en=OUT['thermo'][-1]['pe'] stress=numpy.array([OUT['thermo'][-1][i] for i in ('pxx','pyy','pzz','pyz','pxz','pxy')])*(-1e-4*GPa) #force=numpy.maximum.reduce(abs(totalsol.get_forces())) if debug: write_xyz(Optimizer.debugfile,totalsol,'After Lammps Minimization') Optimizer.debugfile.flush() except Exception, e: os.chdir(cwd) STR+='WARNING: Exception during energy eval:\n'+repr(e)+'\n' f=open('problem-structures.xyz','a') write_xyz(f,totcop,data='Starting structure hindex='+individ.history_index) write_xyz(f,totalsol,data='Lammps Min structure') en=10 stress=0 f.close() if Optimizer.fitness_scheme == 'enthalpyfit': pressure=totalsol.get_isotropic_pressure(stress) cell_max=numpy.maximum.reduce(totalsol.get_positions()) cell_min=numpy.minimum.reduce(totalsol.get_positions()) cell=cell_max-cell_min volume=cell[0]*cell[1]*cell[2] else: pressure=totalsol.get_isotropic_pressure(stress) volume=0 na=totalsol.get_number_of_atoms() ena=en/na energy=en if Optimizer.structure=='Defect': if Optimizer.fixed_region==True or Optimizer.finddefects==False: individ[0]=totalsol[0:nat] bul=totalsol[(nat):len(totalsol)] individ[0].set_cell(csize) else: if 'FI' in Optimizer.debug: outt=find_defects(totalsol,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=Optimizer.debugfile) else: outt=find_defects(totalsol,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=False) individ[0]=outt[0] bul=outt[1] individ.vacancies = outt[2] individ.swaps = outt[3] STR += outt[4] indiv=individ[0] else: top,bul=find_top_layer(totalsol,Optimizer.surftopthick) indiv=top.copy() individ[0]=top.copy() else: