def gen_solid(solidfile, solidcell, outfilename, calc=False, calcmeth=None): """Function to load a bulk solid from a file for use in Defect structure optimization Inputs: solidfile=String of filename to load solidcell=List/Matrix of cell parameters for ASE Atoms class outfilename=String of filename to write solid calc=False/calculator object for evaluating energy of solid calcmeth='VASP' or other method for calculating the energy of the solid Outputs: solid as ASE Atoms class energy and string if calc is not false """ try: sol = read_xyz(solidfile) except Exception as e1: try: sol = read(solidfile) except Exception as e2: raise RuntimeError('Encountered errror:' + repr(e1) + ' ' + repr(e2) + ' While trying to read solid file given as:' + repr(solidfile)) cell = solidcell sol.set_cell(cell) sol.set_pbc(True) #Evaluate pure Bulk structure if calc: cwd = os.getcwd() sol.set_calculator(calc) stro = '' try: if calcmeth == 'VASP': en = sol.get_potential_energy() calcb = Vasp(restart=True) sol = calcb.get_atoms() PureBulkEnpa = en / sol.get_number_of_atoms() else: OUT = sol.calc.calculate(sol) PureBulkEnpa = OUT['thermo'][-1][ 'pe'] / sol.get_number_of_atoms() sol = OUT['atoms'] sol.set_pbc(True) except: stro = 'WARNING: Unable to calculate energy of pure bulk solid' PureBulkEnpa = 0 os.chdir(cwd) # Write bulk file to directory write_xyz(outfilename, sol, PureBulkEnpa) return sol, PureBulkEnpa, stro else: # Write bulk file to directory write_xyz(outfilename, sol, 'Pure Bulk') return sol
def gen_solid(solidfile,solidcell,outfilename,calc=False,calcmeth=None): """Function to load a bulk solid from a file for use in Defect structure optimization Inputs: solidfile=String of filename to load solidcell=List/Matrix of cell parameters for ASE Atoms class outfilename=String of filename to write solid calc=False/calculator object for evaluating energy of solid calcmeth='VASP' or other method for calculating the energy of the solid Outputs: solid as ASE Atoms class energy and string if calc is not false """ try: sol = read_xyz(solidfile) except Exception as e1: try: sol = read(solidfile) except Exception as e2: raise RuntimeError('Encountered errror:'+repr(e1)+' '+repr(e2)+ ' While trying to read solid file given as:'+repr(solidfile)) cell = solidcell sol.set_cell(cell) sol.set_pbc(True) #Evaluate pure Bulk structure if calc: cwd = os.getcwd() sol.set_calculator(calc) stro = '' try: if calcmeth == 'VASP': en = sol.get_potential_energy() calcb = Vasp(restart=True) sol = calcb.get_atoms() PureBulkEnpa = en/sol.get_number_of_atoms() else: OUT = sol.calc.calculate(sol) PureBulkEnpa = OUT['thermo'][-1]['pe']/sol.get_number_of_atoms() sol = OUT['atoms'] sol.set_pbc(True) except: stro = 'WARNING: Unable to calculate energy of pure bulk solid' PureBulkEnpa = 0 os.chdir(cwd) # Write bulk file to directory write_xyz(outfilename,sol,PureBulkEnpa) return sol, PureBulkEnpa, stro else: # Write bulk file to directory write_xyz(outfilename,sol,'Pure Bulk') return sol
def initialize_structures(self): global logger self.output.write('\n----Initialize Structures----\n') #self.logger.info('Initializing Structures') # Initialize Population - Generate a list of ncluster individuals # Set bulk and index atributes if self.restart: logger.info('Loading previous population') pop = generate.get_restart_population(self) else: logger.info('Generating new population') pop = generate.get_population(self) if 'MA' in self.debug: inp_out.write_xyz(self.debugfile,pop[0][0],'First Generated Individual') #Use if concentration of interstitials is unknown if self.swaplist: mutlist=self.mutation_options self.mutation_options=['IntSwapLocal'] for i in range(len(pop)): one = pop[i] one.swaplist=copy.deepcopy(swaplist) if random.random() < 0.25: pop[i], opt = switches.moves_switch(one,self) self.mutation_options=mutlist # Write Initial structures to files self.output.write('\n---Starting Structures---\n') inp_out.write_pop(self, pop) #Print number of atoms to Summary file if self.structure=='Defect' or self.structure=='Surface': natstart=len(pop[0][0])+len(pop[0].bulki) else: natstart=len(pop[0][0]) if not self.restart: if self.structure=='Defect': self.summary.write('Defect Run Pure Bulk Energy per Atom : '+repr(self.purebulkenpa)+'\n') else: self.summary.write(self.structure+' Run : '+repr(0)+'\n') self.summary.write('Natoms '+repr(natstart)+ '\n') #Print data headers to summary file self.summary.write('Generation Fitmin Fitavg Fitmedium Fitmax std time \n') offspring=pop #pop=[] #BESTS=[] return offspring
def algorithm_serial(self): """Subprogram to run the optimizer in serial""" global logger self.algorithm_initialize() logger.info('Beginning main algorithm loop') #Begin main algorithm loop while not self.convergence: logger.info('Setup calculator for generation {0}'.format(self.generation)) pop = self.population logger.info('Setup population') offspring = self.generation_set(pop) # Identify the individuals with an invalid fitness invalid_ind = [ind for ind in offspring if ind.energy==0] #DEBUG: Write first invalid ind if 'MA' in self.debug: logger.info('Identified {0} structures with energy=0'.format(len(invalid_ind))) inp_out.write_xyz(self.debugfile,invalid_ind[0][0],\ 'First from Invalid_ind list '+repr(invalid_ind[0].energy)) #DEBUG: Write first invalid ind in solid if self.structure=='Defect' or self.structure=='Surface': sols = invalid_ind[0][0].copy() sols.extend(invalid_ind[0].bulki) inp_out.write_xyz(self.debugfile,sols,'First from Invalid-ind + Bulki') sols = invalid_ind[0][0].copy() sols.extend(invalid_ind[0].bulko) inp_out.write_xyz(self.debugfile,sols,'First from Invalid-ind + Bulko') self.output.write('\n--Evaluate Structures--\n') logger.info('Evaluating fitness of structures') for i in range(len(invalid_ind)): ind = invalid_ind[i] if 'MA' in self.debug: write_xyz(self.debugfile,ind[0],'Individual to fitness_switch') outs = switches.fitness_switch([self,ind]) self.output.write(outs[1]) invalid_ind[i] = outs[0] pop.extend(invalid_ind) logger.info('Eval Population') pop = self.generation_eval(pop) self.write() logger.info('Run algorithm stats') end_signal = self.algorithm_stats(self.population) return end_signal
def generation_set(self,pop): global logger self.calc = tools.setup_calculator(self) #Set up calculator for atomic structures #Set up calculator for fixed region calculations if self.fixed_region: self.static_calc = self.calc #May need to copy this self.calc = tools.setup_fixed_region_calculator(self) self.output.write('\n-------- Generation '+repr(self.generation)+' --------\n') self.files[self.nindiv].write('Generation '+str(self.generation)+'\n') if len(pop) == 0: logger.info('Initializing structures') offspring = self.initialize_structures() self.population = offspring else: for i in range(len(pop)): # Reset History index pop[i].history_index=repr(pop[i].index) # Select the next generation individuals offspring = switches.selection_switch(pop, self.nindiv, self.selection_scheme, self) # Clone the selected individuals offspring=[off1.duplicate() for off1 in offspring] # Apply crossover to the offspring self.output.write('\n--Applying Crossover--\n') cxattempts = 0 for child1, child2 in zip(offspring[::2], offspring[1::2]): if random.random() < self.cxpb: child1,child2 = switches.crossover_switch(child1, child2, self) cxattempts+=2 self.cxattempts=cxattempts #DEBUG: Write first child if 'MA' in self.debug: inp_out.write_xyz(self.debugfile,offspring[0][0],'First Child '+ repr(offspring[0].history_index)) # Apply mutation to the offspring self.output.write('\n--Applying Mutation--\n') mutattempts = [] muts = [] for mutant in offspring: if random.random() < self.mutpb: if self.mutant_add: mutant = mutant.duplicate() mutant, optsel = switches.moves_switch(mutant,self) mutattempts.append([mutant.history_index,optsel]) if self.mutant_add: muts.append(mutant) if self.mutant_add: offspring.extend(muts) self.mutattempts=mutattempts #DEBUG: Write first offspring if 'MA' in self.debug: inp_out.write_xyz(self.debugfile,muts[0][0],'First Mutant '+\ repr(muts[0].history_index)) if 'stem' in self.fitness_scheme: if self.stem_coeff==None: logger.info('Setting STEM coeff (alpha)') ind = offspring.pop() from MAST.structopt.tools.StemCalc import find_stem_coeff outs = find_stem_coeff(self,ind) ind = outs[1] ind.fitness = 0 ind.energy = 0 self.stem_coeff = outs[0] logger.info('STEM Coeff = {0}'.format(self.stem_coeff)) self.output.write('stem_coeff Calculated to be: '+repr(self.stem_coeff)+'\n') offspring.append(ind) return offspring
def generation_eval(self, pop): global logger emx = max(ind.energy for ind in pop) emn = min(ind.energy for ind in pop) for ind in pop: ind.tenergymx = emx ind.tenergymin = emn #DEBUG: Write relaxed individual if 'MA' in self.debug: if self.generation > 0: inp_out.write_xyz(self.debugfile,pop[self.nindiv][0],\ 'First Relaxed Offspring '+repr(pop[self.nindiv-1].energy)) #DEBUG: Write relaxed ind in solid if self.structure=='Defect' or self.structure=='Surface': inp_out.write_xyz(self.debugfile,pop[self.nindiv].bulki,\ 'First Relaxed bulki '+repr(pop[self.nindiv-1].energy)) sols = pop[self.nindiv][0].copy() sols.extend(pop[self.nindiv].bulki) inp_out.write_xyz(self.debugfile,sols,'First from Invalid-ind + Bulki '+\ repr(pop[self.nindiv].energy)) sols = pop[self.nindiv][0].copy() sols.extend(pop[self.nindiv].bulko) inp_out.write_xyz(self.debugfile,sols,\ 'First from Invalid-ind + Bulko '+repr(pop[self.nindiv].energy)) if self.generation==0: logger.info('Initializing Bests list') self.BESTS = list() if self.best_inds_list: self.BESTS = tools.BestInds(pop,self.BESTS,self,writefile=True) # Determine survival based on fitness predator if 'lambda,mu' not in self.algorithm_type: pop = tools.get_best(pop, len(pop)) if self.fingerprinting: logger.info('Writing fingerprint files') for one in pop: self.fpfile.write(repr(fingerprinting.fingerprint_dist( pop[0].fingerprint,one.fingerprint))+' '+repr(one.energy)+' ') self.fpfile.write('\n') self.fpminfile.write(repr(pop[0].fingerprint)+'\n') self.fpminfile.write(repr(pop[0].energy)+'\n') nevals = len(pop)/2 if self.generation !=0: logger.info('Applying predator') pop = predator_switch(pop,self) else: self.genrep = 0 self.minfit = 0 # Evaluate population logger.info('Checking population for convergence') self.check_pop(pop) #Update general output tracking if self.generation !=0: histlist = [] for ind in pop: histlist.append(ind.history_index) self.Runtimes.append(time.time()) self.Evaluations.append(nevals) cxsuccess = 0 mutsuccess = [] for one in histlist: if '+' in one: cxsuccess +=1 if 'm' in one: mutsuccess.append(one) self.CXs.append((self.cxattempts,cxsuccess)) mutslist = [[0,0] for one in self.mutation_options] for one in mutsuccess: for two, opt in self.mutattempts: if one==two: index = [ind for ind,value in enumerate( self.mutation_options) if value==opt][0] mutslist[index][1]+=1 for one,opt in self.mutattempts: index = [ind for ind,value in enumerate( self.mutation_options) if value==opt][0] mutslist[index][0]+=1 self.Muts.append(mutslist) self.output.write('\n----- Generation Stats -----\n') self.output.write('Attempted Crossovers: ' + repr(self.cxattempts)+'\n') self.output.write('Successful Crossovers: ' + repr(cxsuccess)+'\n') self.output.write('Mutations:\n') i=0 for opt in self.mutation_options: self.output.write(' Attempted ' + opt + ' : ' + repr(mutslist[i][0]) + '\n') self.output.write(' Successful ' + opt + ' : ' + repr(mutslist[i][1]) + '\n') i+=1 self.generation += 1 # Set new index values index1 = 0 for ind in pop: ind.index = index1 index1+=1 index1 = 0 if not self.convergence: try: self.calc.clean() if self.fixed_region: self.static_calc.clean() except: pass if self.lammps_keep_files: try: if self.parallel and ('Island_Method' not in self.algorithm_type): nproc = MPI.COMM_WORLD.Get_size() lmpfilepath = os.path.dirname(self.calc.tmp_dir) for proc in range(nproc): pth = os.path.join(lmpfilepath,'rank-{0}'.format(proc)) fls = [fl for fl in os.listdir(pth) if '.' not in fl] for one in fls: os.remove(pth+'/'+one) else: fls = [fl for fl in os.listdir(self.calc.tmp_dir) if '.' not in fl] for one in fls: os.remove(self.calc.tmp_dir+'/'+one) except Exception, e: logger.error('Print issue in removing files {0}.'.format(e),exc_info=True) print str(e) pass
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() if Optimizer.forcing != 'FreeNatom': rax = random.choice(['x', '-x','y','-y','z','-z']) else: rax = 'z' rang=random.random()*math.pi indi1.rotate(rax,a=rang,center='COM',rotate_cell=False) 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: if Optimizer.forcing != 'FreeNatom': rax = random.choice(['x', '-x','y','-y','z','-z']) rang = random.random()* math.pi/2.0 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) else: rax = random.choice(['x','-x','y','-y']) rangz = random.uniform(0,90)/180.0*math.pi rang = math.pi/2.0 rpos = [random.uniform(cmin[i]*0.7,cmax[i]*0.7) for i in range(3)] indi1.rotate('z',a=rangz,center=rpos,rotate_cell=False) 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 if Optimizer.forcing != 'FreeNatom': indi1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) else: indi1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) indi1.rotate('z',a=-1*rangz,center=rpos,rotate_cell=False) if Optimizer.forcing != 'FreeNatom': indi2.rotate(rax,a=rang,center=rpos,rotate_cell=False) else: indi2.rotate('z',a=rangz,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() elif Optimizer.forcing != 'FreeNatom': 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)) if Optimizer.forcing != 'FreeNatom': indi1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) indi2.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) else: indi1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) indi1.rotate('z',a=-1*rangz,center=rpos,rotate_cell=False) indi2.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) indi2.rotate('z',a=-1*rangz,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 randalloybox(ind1, ind2, Optimizer): """Select a box in the alloy configuration *** Note: CX may be obsolete. In development *** """ if 'CX' in Optimizer.debug: debug = True else: debug = False if Optimizer.structure != 'Defect': Optimizer.output.write( 'WARNING: Box Random alloy Cx attempted on nondefect structure. SKIPPING CX.\n' ) else: Optimizer.output.write('Box Random alloy 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() cell1 = numpy.maximum.reduce(indi1.get_cell()) cell2 = numpy.maximum.reduce(indi2.get_cell()) cell = numpy.minimum(cell1, cell2) pbc1 = indi1.get_pbc() pbc2 = indi2.get_pbc() #Build solids solid1 = indi1.copy() solid1.extend(ind1.bulki.copy()) solid2 = indi2.copy() solid2.extend(ind2.bulki.copy()) #Get starting concentrations and number of atoms nat1 = len(solid1) nat2 = len(solid2) symlist = list(set(solid1.get_chemical_symbols())) #Assumes same types of atoms in both solid1 and solid2 concent1 = [] concent2 = [] for one in symlist: atmss = [atm for atm in solid1 if atm.symbol == one] concent1.append(len(atmss)) atmss = [atm for atm in solid2 if atm.symbol == one] concent2.append(len(atmss)) # Pick a origin point for box in the cell #pt=[random.uniform(0,cell[0]),random.uniform(0,cell[1]),random.uniform(0,cell[2])] pt1 = solid1[0].position pt2 = solid2[0].position #Find max radius of circle cut r1 = min([ min(cell1[0] - pt1[0], pt1[0]), min(cell1[1] - pt1[1], pt1[1]), min(cell1[2] - pt1[2], pt1[2]) ]) r2 = min([ min(cell2[0] - pt2[0], pt2[0]), min(cell2[1] - pt2[1], pt2[1]), min(cell2[2] - pt2[2], pt2[2]) ]) r = min(r1, r2) mcell = min(cell) if r > mcell * 0.125: r = mcell * 0.125 if debug: Optimizer.output.write('Radius of box = ' + repr(r) + '\nPosition in solid1 = ' + repr(pt1) + '\nPosition in solid2 = ' + repr(pt2) + '\n') #Find atoms within sphere of radius r solid1.append(Atom(position=pt1)) dist1 = [] blist1 = [] for i in range(len(solid1) - 1): d = solid1.get_distance(i, len(solid1) - 1) if d < r: dist1.append((d, solid1[i])) else: blist1.append((d, solid1[i])) solid1.pop() solid2.append(Atom(position=pt2)) dist2 = [] blist2 = [] for i in range(len(solid2) - 1): d = solid2.get_distance(i, len(solid2) - 1) if d < r: dist2.append((d, solid2[i])) else: blist2.append((d, solid2[i])) solid2.pop() #Translate spheres to opposite location dats1 = Atoms() for d, atm in dist1: dats1.append(atm) dats1.translate(-pt1) dats1.translate(pt2) dats2 = Atoms() for d, atm in dist2: dats2.append(atm) dats2.translate(-pt2) dats2.translate(pt1) #Exchange atoms in sphere and build new solids nsolid1 = dats2.copy() for d, atm in blist1: nsolid1.append(atm) nsolid2 = dats1.copy() for d, atm in blist2: nsolid2.append(atm) #Identify new number of atoms nnat1 = len(nsolid1) nnat2 = len(nsolid2) if nnat1 > nat1: ds = [] #More atoms in new solid1 means solid2 has less atoms #Need to transfer atoms from solid1 to solid2 #Find atoms that are too close for i in range(len(dist2)): for j in range(len(dist2), len(nsolid1)): ds.append((nsolid1.get_distance(i, j), i)) #Sort distances by longest to shortest ds = sorted(ds, key=lambda one: one[0]) diff = nnat1 - nat1 exchangeindices = [] while len(exchangeindices) < diff: #Grab shortest distance in ds list d, index = ds.pop() if index not in exchangeindices: exchangeindices.append(index) nnsolid1 = Atoms() for i in range(len(nsolid1)): if i not in exchangeindices: nnsolid1.append(nsolid1[i]) nnsolid2 = nsolid2.copy() for i in exchangeindices: #for j in range(3): # position[j]=nsolid2[i].position[j]-pt1[j]+pt2[j] position = [ random.uniform(pt2[0] - r / (2**0.5), pt2[0] + r / (2**0.5)), random.uniform(pt2[1] - r / (2**0.5), pt2[1] + r / (2**0.5)), random.uniform(pt2[2] - r / (2**0.5), pt2[2] + r / (2**0.5)) ] nnsolid2.append( Atom(symbol=nsolid1[i].symbol, position=position)) nsolid1 = nnsolid1.copy() nsolid2 = nnsolid2.copy() elif nnat1 < nat1: ds = [] #More atoms in new solid2 means solid1 has less atoms #Need to transfer atoms from solid2 to solid1 #Find atoms that are too close for i in range(len(dist1)): for j in range(len(dist1), len(nsolid2)): ds.append((nsolid2.get_distance(i, j), i)) #Sort distances by longest to shortest ds = sorted(ds, key=lambda one: one[0]) diff = nnat2 - nat2 exchangeindices = [] while len(exchangeindices) < diff: #Grab shortest distance in ds list d, index = ds.pop() if index not in exchangeindices: exchangeindices.append(index) nnsolid2 = Atoms() for i in range(len(nsolid2)): if i not in exchangeindices: nnsolid2.append(nsolid2[i]) nnsolid1 = nsolid1.copy() for i in exchangeindices: #for j in range(3): # position[j]=nsolid2[i].position[j]-pt1[j]+pt2[j] position = [ random.uniform(pt1[0] - r / (2**0.5), pt1[0] + r / (2**0.5)), random.uniform(pt1[1] - r / (2**0.5), pt1[1] + r / (2**0.5)), random.uniform(pt1[2] - r / (2**0.5), pt1[2] + r / (2**0.5)) ] nnsolid1.append( Atom(symbol=nsolid2[i].symbol, position=position)) nsolid1 = nnsolid1.copy() nsolid2 = nnsolid2.copy() #Number of atoms in each individual should now be preserved if Optimizer.forcing == 'Concentration': #Need to check concentrations nconcent1 = [] for one in symlist: atmss = [atm for atm in nsolid1 if atm.symbol == one] nconcent1.append(len(atmss)) nconcent2 = [] for one in symlist: atmss = [atm for atm in nsolid2 if atm.symbol == one] nconcent2.append(len(atmss)) #Let's assume a random perturbation to concentration in order to correct this issue posd = [] negd = [] for i in range(len(nconcent1)): diff = nconcent1[i] - concent1[i] if diff > 0: posd.append((diff, symlist[i])) elif diff < 0: negd.append((diff, symlist[i])) for c, sym in negd: while c != 0: symr = posd[0][1] rlist = [ atm.index for atm in nsolid1 if atm.symbol == symr ] index1 = random.choice(rlist) nsolid1[index1].symbol = sym c += 1 posd[0] = (posd[0][0] - 1, posd[0][1]) if posd[0][0] == 0: posd = posd[1::] #Do the same for solid2 posd = [] negd = [] for i in range(len(nconcent2)): diff = nconcent2[i] - concent2[i] if diff > 0: posd.append((diff, symlist[i])) elif diff < 0: negd.append((diff, symlist[i])) for c, sym in negd: while c != 0: symr = posd[0][1] rlist = [ atm.index for atm in nsolid2 if atm.symbol == symr ] index1 = random.choice(rlist) nsolid2[index1].symbol = sym c += 1 posd[0] = (posd[0][0] - 1, posd[0][1]) if posd[0][0] == 0: posd = posd[1::] #DEBUG: Write crossover to file if debug: write_xyz(Optimizer.debugfile, nsolid1, 'CX(randalloybx):nsolid1') write_xyz(Optimizer.debugfile, nsolid2, 'CX(randalloybx):nsolid2') #DEBUG: Check structure of atoms exchanged for sym, c, m, u in Optimizer.atomlist: nc = len([atm for atm in nsolid1 if atm.symbol == sym]) Optimizer.output.write('CX(randalloybx):New solid1 contains ' + repr(nc) + ' ' + repr(sym) + ' atoms\n') nc = len([atm for atm in nsolid2 if atm.symbol == sym]) Optimizer.output.write('CX(randalloybx):New solid2 contains ' + repr(nc) + ' ' + repr(sym) + ' atoms\n') if Optimizer.forcing != 'Concentration': for i in range(len(Optimizer.atomlist)): atms1 = [ inds for inds in nsolid1 if inds.symbol == Optimizer.atomlist[i][0] ] atms2 = [ inds for inds in nsolid2 if inds.symbol == Optimizer.atomlist[i][0] ] if len(atms1) == 0: if len(atms2) == 0: nsolid1[random.randint( 0, len(indi1) - 1)].symbol = Optimizer.atomlist[i][0] nsolid2[random.randint( 0, len(indi2) - 1)].symbol = Optimizer.atomlist[i][0] else: nsolid1.append(atms2[random.randint(0, len(atms2) - 1)]) nsolid1.pop(random.randint(0, len(nsolid1) - 2)) else: if len(atms2) == 0: nsolid2.append(atms1[random.randint(0, len(atms1) - 1)]) nsolid2.pop(random.randint(0, len(nsolid2) - 2)) nsolid1.set_cell(cell1) nsolid2.set_cell(cell2) nsolid1.set_pbc(pbc1) nsolid2.set_pbc(pbc2) outs = find_defects(nsolid1, Optimizer.solidbulk, Optimizer.sf, atomlistcheck=Optimizer.atomlist, trackvacs=Optimizer.trackvacs, trackswaps=Optimizer.trackswaps, debug=False) ind1[0] = outs[0].copy() ind1.bulki = outs[1].copy() ind1.vacancies = outs[2].copy() ind1.swaps = outs[3].copy() outs = find_defects(nsolid2, Optimizer.solidbulk, Optimizer.sf, atomlistcheck=Optimizer.atomlist, trackvacs=Optimizer.trackvacs, trackswaps=Optimizer.trackswaps, debug=False) ind2[0] = outs[0].copy() ind2.bulki = outs[1].copy() ind2.vacancies = outs[2].copy() ind2.swaps = outs[3].copy() return ind1, ind2
def rotct_rand_defect(ind1, ind2, Optimizer): """Rotate atoms cut and splice Translates atoms to center of positions first 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 for defects 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 COP is at (0,0,0) if Optimizer.structure == 'Defect': #Identify center of positions for defect structure indi1c, indi1b, vacant1, swap1, stro1 = find_defects( indi1, Optimizer.solidbulk, 0) com1 = position_average(indi1c) indi1 = shift_atoms(indi1, com1) #Do the same for second individual indi2c, indi2b, vacant2, swap2, stro2 = find_defects( indi2, Optimizer.solidbulk, 0) com2 = position_average(indi2c) indi2 = shift_atoms(indi2, com2) else: 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_Defect: 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_Defect: 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) if Optimizer.structure == 'Defect': indi1 = shift_atoms(indi1, [-p for p in com1]) indi2 = shift_atoms(indi2, [-p for p in com2]) else: 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: 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: 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 rotct_defect(ind1, ind2, Optimizer): """Rotate atoms cut and splice Translates atoms to center of positions first 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('Rotate Cut/Splice Cx for defects 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 COP is at (0,0,0) if Optimizer.structure=='Defect': #Identify center of positions for defect structure indi1c,indi1b,vacant1,swap1,stro1 = find_defects(indi1,Optimizer.solidbulk,0) com1 = position_average(indi1c) indi1 = shift_atoms(indi1, com1) trans = [-p for p in numpy.maximum.reduce(indi1.get_cell())] indi1.translate(trans) #Do the same for second individual indi2c,indi2b,vacant2,swap2,stro2 = find_defects(indi2,Optimizer.solidbulk,0) com2 = position_average(indi2c) indi2 = shift_atoms(indi2, com2) indi2.translate(trans) else: 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 n=0 while n<10: rax = random.choice(['x', '-x','y','-y','z','-z']) rang = random.random()*90 indi1.rotate(rax,a=rang,center=[0,0,0],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=[0,0,0], rotate_cell=False) indi2.rotate(rax,a=rang,center=[0,0,0],rotate_cell=False) if debug: print 'Group1 size = ', len(group1) print 'Position = ', [0,0,0] print 'Angle = ', rang print 'Axis = ', rax print 'Number of tries = ', n+1 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 ROTCT_Defect: Individual 1 contains '+repr(nc)+' '+repr(sym)+' atoms\n') nc=len([atm for atm in indi2 if atm.symbol==sym]) Optimizer.output.write('CX ROTCT_Defect: 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=[0,0,0], rotate_cell=False) indi2.rotate(rax,a=-1*rang,center=[0,0,0], rotate_cell=False) if Optimizer.structure=='Defect': trans = [-p for p in trans] indi1.translate(trans) indi2.translate(trans) indi1 = shift_atoms(indi1, [-p for p in com1]) indi2 = shift_atoms(indi2, [-p for p in com2]) else: 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 ROTCT_Defect: 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 ROTCT_Defect: 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 randalloybox(ind1, ind2, Optimizer): """Select a box in the alloy configuration *** Note: CX may be obsolete. In development *** """ if 'CX' in Optimizer.debug: debug = True else: debug = False if Optimizer.structure != 'Defect': Optimizer.output.write('WARNING: Box Random alloy Cx attempted on nondefect structure. SKIPPING CX.\n') else: Optimizer.output.write('Box Random alloy 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() cell1 = numpy.maximum.reduce(indi1.get_cell()) cell2 = numpy.maximum.reduce(indi2.get_cell()) cell = numpy.minimum(cell1,cell2) pbc1 = indi1.get_pbc() pbc2 = indi2.get_pbc() #Build solids solid1 = indi1.copy() solid1.extend(ind1.bulki.copy()) solid2 = indi2.copy() solid2.extend(ind2.bulki.copy()) #Get starting concentrations and number of atoms nat1 = len(solid1) nat2 = len(solid2) symlist = list(set(solid1.get_chemical_symbols())) #Assumes same types of atoms in both solid1 and solid2 concent1 = [] concent2 = [] for one in symlist: atmss = [atm for atm in solid1 if atm.symbol==one] concent1.append(len(atmss)) atmss = [atm for atm in solid2 if atm.symbol==one] concent2.append(len(atmss)) # Pick a origin point for box in the cell #pt=[random.uniform(0,cell[0]),random.uniform(0,cell[1]),random.uniform(0,cell[2])] pt1 = solid1[0].position pt2 = solid2[0].position #Find max radius of circle cut r1 = min([min(cell1[0]-pt1[0],pt1[0]),min(cell1[1]-pt1[1],pt1[1]),min(cell1[2]-pt1[2],pt1[2])]) r2 = min([min(cell2[0]-pt2[0],pt2[0]),min(cell2[1]-pt2[1],pt2[1]),min(cell2[2]-pt2[2],pt2[2])]) r = min(r1,r2) mcell = min(cell) if r > mcell*0.125: r = mcell*0.125 if debug: Optimizer.output.write('Radius of box = '+repr(r)+'\nPosition in solid1 = '+repr(pt1)+'\nPosition in solid2 = '+repr(pt2)+'\n') #Find atoms within sphere of radius r solid1.append(Atom(position=pt1)) dist1 = [] blist1 = [] for i in range(len(solid1)-1): d = solid1.get_distance(i,len(solid1)-1) if d < r: dist1.append((d,solid1[i])) else: blist1.append((d,solid1[i])) solid1.pop() solid2.append(Atom(position=pt2)) dist2 = [] blist2 = [] for i in range(len(solid2)-1): d = solid2.get_distance(i,len(solid2)-1) if d < r: dist2.append((d,solid2[i])) else: blist2.append((d,solid2[i])) solid2.pop() #Translate spheres to opposite location dats1 = Atoms() for d,atm in dist1: dats1.append(atm) dats1.translate(-pt1) dats1.translate(pt2) dats2 = Atoms() for d,atm in dist2: dats2.append(atm) dats2.translate(-pt2) dats2.translate(pt1) #Exchange atoms in sphere and build new solids nsolid1 = dats2.copy() for d,atm in blist1: nsolid1.append(atm) nsolid2 = dats1.copy() for d,atm in blist2: nsolid2.append(atm) #Identify new number of atoms nnat1 = len(nsolid1) nnat2 = len(nsolid2) if nnat1 > nat1: ds = [] #More atoms in new solid1 means solid2 has less atoms #Need to transfer atoms from solid1 to solid2 #Find atoms that are too close for i in range(len(dist2)): for j in range(len(dist2),len(nsolid1)): ds.append((nsolid1.get_distance(i,j),i)) #Sort distances by longest to shortest ds = sorted(ds, key=lambda one:one[0]) diff = nnat1-nat1 exchangeindices = [] while len(exchangeindices) < diff: #Grab shortest distance in ds list d, index = ds.pop() if index not in exchangeindices: exchangeindices.append(index) nnsolid1 = Atoms() for i in range(len(nsolid1)): if i not in exchangeindices: nnsolid1.append(nsolid1[i]) nnsolid2 = nsolid2.copy() for i in exchangeindices: #for j in range(3): # position[j]=nsolid2[i].position[j]-pt1[j]+pt2[j] position = [random.uniform(pt2[0]-r/(2**0.5),pt2[0]+r/(2**0.5)),random.uniform(pt2[1]-r/(2**0.5),pt2[1]+r/(2**0.5)),random.uniform(pt2[2]-r/(2**0.5),pt2[2]+r/(2**0.5))] nnsolid2.append(Atom(symbol=nsolid1[i].symbol, position=position)) nsolid1 = nnsolid1.copy() nsolid2 = nnsolid2.copy() elif nnat1 < nat1: ds = [] #More atoms in new solid2 means solid1 has less atoms #Need to transfer atoms from solid2 to solid1 #Find atoms that are too close for i in range(len(dist1)): for j in range(len(dist1),len(nsolid2)): ds.append((nsolid2.get_distance(i,j),i)) #Sort distances by longest to shortest ds = sorted(ds, key=lambda one:one[0]) diff = nnat2-nat2 exchangeindices = [] while len(exchangeindices) < diff: #Grab shortest distance in ds list d, index = ds.pop() if index not in exchangeindices: exchangeindices.append(index) nnsolid2 = Atoms() for i in range(len(nsolid2)): if i not in exchangeindices: nnsolid2.append(nsolid2[i]) nnsolid1 = nsolid1.copy() for i in exchangeindices: #for j in range(3): # position[j]=nsolid2[i].position[j]-pt1[j]+pt2[j] position = [random.uniform(pt1[0]-r/(2**0.5),pt1[0]+r/(2**0.5)),random.uniform(pt1[1]-r/(2**0.5),pt1[1]+r/(2**0.5)),random.uniform(pt1[2]-r/(2**0.5),pt1[2]+r/(2**0.5))] nnsolid1.append(Atom(symbol=nsolid2[i].symbol, position=position)) nsolid1 = nnsolid1.copy() nsolid2 = nnsolid2.copy() #Number of atoms in each individual should now be preserved if Optimizer.forcing=='Concentration': #Need to check concentrations nconcent1 = [] for one in symlist: atmss = [atm for atm in nsolid1 if atm.symbol==one] nconcent1.append(len(atmss)) nconcent2 = [] for one in symlist: atmss = [atm for atm in nsolid2 if atm.symbol==one] nconcent2.append(len(atmss)) #Let's assume a random perturbation to concentration in order to correct this issue posd = [] negd = [] for i in range(len(nconcent1)): diff = nconcent1[i]-concent1[i] if diff >0: posd.append((diff,symlist[i])) elif diff<0: negd.append((diff,symlist[i])) for c,sym in negd: while c !=0: symr = posd[0][1] rlist = [atm.index for atm in nsolid1 if atm.symbol==symr] index1 = random.choice(rlist) nsolid1[index1].symbol=sym c += 1 posd[0] = (posd[0][0]-1,posd[0][1]) if posd[0][0]==0: posd = posd[1::] #Do the same for solid2 posd = [] negd = [] for i in range(len(nconcent2)): diff = nconcent2[i]-concent2[i] if diff >0: posd.append((diff,symlist[i])) elif diff<0: negd.append((diff,symlist[i])) for c,sym in negd: while c !=0: symr = posd[0][1] rlist = [atm.index for atm in nsolid2 if atm.symbol==symr] index1 = random.choice(rlist) nsolid2[index1].symbol=sym c += 1 posd[0] = (posd[0][0]-1,posd[0][1]) if posd[0][0]==0: posd = posd[1::] #DEBUG: Write crossover to file if debug: write_xyz(Optimizer.debugfile, nsolid1,'CX(randalloybx):nsolid1') write_xyz(Optimizer.debugfile, nsolid2,'CX(randalloybx):nsolid2') #DEBUG: Check structure of atoms exchanged for sym,c,m,u in Optimizer.atomlist: nc = len([atm for atm in nsolid1 if atm.symbol==sym]) Optimizer.output.write('CX(randalloybx):New solid1 contains '+repr(nc)+' '+repr(sym)+' atoms\n') nc = len([atm for atm in nsolid2 if atm.symbol==sym]) Optimizer.output.write('CX(randalloybx):New solid2 contains '+repr(nc)+' '+repr(sym)+' atoms\n') if Optimizer.forcing !='Concentration': for i in range(len(Optimizer.atomlist)): atms1 = [inds for inds in nsolid1 if inds.symbol==Optimizer.atomlist[i][0]] atms2 = [inds for inds in nsolid2 if inds.symbol==Optimizer.atomlist[i][0]] if len(atms1)==0: if len(atms2)==0: nsolid1[random.randint(0,len(indi1)-1)].symbol = Optimizer.atomlist[i][0] nsolid2[random.randint(0,len(indi2)-1)].symbol = Optimizer.atomlist[i][0] else: nsolid1.append(atms2[random.randint(0,len(atms2)-1)]) nsolid1.pop(random.randint(0,len(nsolid1)-2)) else: if len(atms2)==0: nsolid2.append(atms1[random.randint(0,len(atms1)-1)]) nsolid2.pop(random.randint(0,len(nsolid2)-2)) nsolid1.set_cell(cell1) nsolid2.set_cell(cell2) nsolid1.set_pbc(pbc1) nsolid2.set_pbc(pbc2) outs = find_defects(nsolid1,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=False) ind1[0] = outs[0].copy() ind1.bulki = outs[1].copy() ind1.vacancies = outs[2].copy() ind1.swaps = outs[3].copy() outs = find_defects(nsolid2,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=False) ind2[0] = outs[0].copy() ind2.bulki = outs[1].copy() ind2.vacancies = outs[2].copy() ind2.swaps = outs[3].copy() return ind1, ind2
def rotct(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('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 and random angle and rotate individuals n=0 while n<10: rax = random.choice(['x', '-x','y','-y','z','-z']) rang = random.random()*90 indi1.rotate(rax,a=rang,center='COM',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: indi1.rotate(rax,a=-1*rang,center='COM', rotate_cell=False) n+=1 indi2.rotate(rax,a=rang,center='COM', rotate_cell=False) if debug: print 'Group1 size = ', len(group1) print 'Position = ', [0,0,0] print 'Angle = ', rang print 'Axis = ', rax print 'Number of tries = ', n+1 #Apply concentration forcing if needed group2 = Atoms(cell=ind2[0].get_cell(),pbc=ind2[0].get_pbc()) indices2 = [] dellist = [] if Optimizer.forcing=='Concentration': symlist = list(set(group1.get_chemical_symbols())) seplist = [[atm for atm in indi2 if atm.symbol == sym] for sym, count in symlist] for one in group1: sym1=one.symbol listpos=[i for i,s in enumerate(symlist) if s==sym1][0] if len(seplist[listpos]) > 0: dist=[z for x,y,z in [one.position for one in seplist[listpos]]] pos = [i for i,value in enumerate(dist) if value==max(dist)][0] group2.append(seplist[listpos][pos]) indices2.append(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.append(pt2.index) else: for one in indi2: if one.position[2] >= 0: group2.append(one) indices2.append(one.index) 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] other1 = Atoms() other2 = Atoms() 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 ROTCT: Individual 1 contains '+repr(nc)+' '+repr(sym)+' atoms\n') nc=len([atm for atm in indi2 if atm.symbol==sym]) Optimizer.output.write('CX ROTCT: Individual 2 contains '+repr(nc)+' '+repr(sym)+' atoms\n') #Need to have at least one atom of each structure in atomlist to prevent Lammps for erroring 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='COM', rotate_cell=False) indi2.rotate(rax,a=-1*rang,center='COM', rotate_cell=False) indi1.translate(com1) indi2.translate(com2) if Optimizer.structure != 'Defect': cm = indi1.get_center_of_mass() cell = numpy.maximum.reduce(indi1.get_cell()) cop = [cell[0]/float(2), cell[1]/float(2), cell[2]/float(2)] indi1.translate(-1*cm) indi1.translate(cop) cm = indi2.get_center_of_mass() cell = numpy.maximum.reduce(indi2.get_cell()) cop = [cell[0]/float(2), cell[1]/float(2), cell[2]/float(2)] indi2.translate(-1*cm) indi2.translate(cop) ind1[0]=indi1 ind2[0]=indi2 #Check structure and number of atoms in crystal if Optimizer.structure=='Defect': solid1=Atoms() solid1.extend(ind1[0]) solid1.extend(ind1.bulki) solid2=Atoms() solid2.extend(ind1[0]) 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 ROTCT: CIBS 1 configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n') nc=len([atm for atm in solid2 if atm.symbol==sym]) Optimizer.output.write('CX ROTCT: CIBS 2 configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n') return ind1, ind2
def rotct(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('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 and random angle and rotate individuals n = 0 while n < 10: rax = random.choice(['x', '-x', 'y', '-y', 'z', '-z']) rang = random.random() * 90 indi1.rotate(rax, a=rang, center='COM', 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: indi1.rotate(rax, a=-1 * rang, center='COM', rotate_cell=False) n += 1 indi2.rotate(rax, a=rang, center='COM', rotate_cell=False) if debug: print 'Group1 size = ', len(group1) print 'Position = ', [0, 0, 0] print 'Angle = ', rang print 'Axis = ', rax print 'Number of tries = ', n + 1 #Apply concentration forcing if needed group2 = Atoms(cell=ind2[0].get_cell(), pbc=ind2[0].get_pbc()) indices2 = [] dellist = [] if Optimizer.forcing == 'Concentration': symlist = list(set(group1.get_chemical_symbols())) seplist = [[atm for atm in indi2 if atm.symbol == sym] for sym, count in symlist] for one in group1: sym1 = one.symbol listpos = [i for i, s in enumerate(symlist) if s == sym1][0] if len(seplist[listpos]) > 0: dist = [ z for x, y, z in [one.position for one in seplist[listpos]] ] pos = [ i for i, value in enumerate(dist) if value == max(dist) ][0] group2.append(seplist[listpos][pos]) indices2.append(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.append(pt2.index) else: for one in indi2: if one.position[2] >= 0: group2.append(one) indices2.append(one.index) 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] other1 = Atoms() other2 = Atoms() 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 ROTCT: Individual 1 contains ' + repr(nc) + ' ' + repr(sym) + ' atoms\n') nc = len([atm for atm in indi2 if atm.symbol == sym]) Optimizer.output.write('CX ROTCT: Individual 2 contains ' + repr(nc) + ' ' + repr(sym) + ' atoms\n') #Need to have at least one atom of each structure in atomlist to prevent Lammps for erroring 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='COM', rotate_cell=False) indi2.rotate(rax, a=-1 * rang, center='COM', rotate_cell=False) indi1.translate(com1) indi2.translate(com2) if Optimizer.structure != 'Defect': cm = indi1.get_center_of_mass() cell = numpy.maximum.reduce(indi1.get_cell()) cop = [cell[0] / float(2), cell[1] / float(2), cell[2] / float(2)] indi1.translate(-1 * cm) indi1.translate(cop) cm = indi2.get_center_of_mass() cell = numpy.maximum.reduce(indi2.get_cell()) cop = [cell[0] / float(2), cell[1] / float(2), cell[2] / float(2)] indi2.translate(-1 * cm) indi2.translate(cop) ind1[0] = indi1 ind2[0] = indi2 #Check structure and number of atoms in crystal if Optimizer.structure == 'Defect': solid1 = Atoms() solid1.extend(ind1[0]) solid1.extend(ind1.bulki) solid2 = Atoms() solid2.extend(ind1[0]) 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 ROTCT: CIBS 1 configuration contains ' + repr(nc) + ' ' + repr(sym) + ' atoms\n') nc = len([atm for atm in solid2 if atm.symbol == sym]) Optimizer.output.write('CX ROTCT: CIBS 2 configuration contains ' + repr(nc) + ' ' + repr(sym) + ' atoms\n') return ind1, ind2
def newclus(ind1, ind2, Optimizer): """Select a box in the cluster configuration""" if 'CX' in Optimizer.debug: debug = True else: debug = False Optimizer.output.write('Box Cluster Cx between individual '+repr(ind1.index)+' and individual '+repr(ind2.index)+'\n') #Perserve starting conditions of individual solid1 = ind1[0].copy() solid2 = ind2[0].copy() cello1 = ind1[0].get_cell() cello2 = ind2[0].get_cell() cell1 = numpy.maximum.reduce(solid1.get_positions()) cell1m = numpy.minimum.reduce(solid1.get_positions()) cell2 = numpy.maximum.reduce(solid2.get_positions()) cell2m = numpy.minimum.reduce(solid2.get_positions()) cell = numpy.minimum(cell1,cell2) pbc1 = solid1.get_pbc() pbc2 = solid2.get_pbc() #Get starting concentrations and number of atoms nat1 = len(solid1) nat2 = len(solid2) # Pick a origin point for box in the cell pt1 = random.choice(solid1) pt1f = [(pt1.position[i]-cell1m[i])/cell1[i] for i in range(3)] pt2 = [pt1f[i]*cell2[i]+cell2m[i] for i in range(3)] solid2.append(Atom(position=pt2)) pt2=solid2[len(solid2)-1] #Find max neighborsize of circle cut r = random.uniform(0,min(nat1,nat2)/5.0) if debug: print 'DEBUG CX: Point one =', pt1.position print 'DEBUG CX: Point two =', pt2.position #Find atoms within sphere of neighborsize r for both individuals #Make sure that crossover is only selection of atoms not all while True: ctoff = [r for on in solid1] nl = NeighborList(ctoff, bothways=True, self_interaction=False) nl.update(solid1) indices1, offsets = nl.get_neighbors(pt1.index) if len(indices1)==0: r = r*1.2 elif len(indices1) < nat1*.75: break else: r = r*0.8 if debug: print 'Neighborsize of box = '+repr(r)+'\nPosition in solid1 = '+repr(pt1.position)+'\nPosition in solid2 = '+repr(pt2.position) group1 = Atoms(cell=solid1.get_cell(),pbc=solid1.get_pbc()) group1.append(pt1) indices1a=[pt1.index] for index, d in zip(indices1,offsets): if index not in indices1a: index = int(index) pos = solid1[index].position + numpy.dot(d,solid1.get_cell()) group1.append(Atom(symbol=solid1[index].symbol,position=pos)) indices1a.append(index) indices1=indices1a ctoff = [r for on in solid2] nl = NeighborList(ctoff, bothways=True, self_interaction=False) nl.update(solid2) indices2, offsets = nl.get_neighbors(pt2.index) group2 = Atoms(cell=solid2.get_cell(),pbc=solid2.get_pbc()) indices2a = [] for index, d in zip(indices2,offsets): if index not in indices2a: index = int(index) pos = solid2[index].position + numpy.dot(d,solid2.get_cell()) group2.append(Atom(symbol=solid2[index].symbol,position=pos)) indices2a.append(index) indices2=indices2a if len(indices2)==0: for one in group1: while True: sel = random.choice(solid2) if sel.symbol==one.symbol: if sel.index not in indices2: group2.append(sel) indices2.append(sel.index) break if Optimizer.forcing=='Concentration': symlist = list(set(group1.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] indices2n.append(pt2.index) 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=solid2.get_cell(),pbc=solid2.get_pbc()) for one in solid2: if one.index not in indices2: other2.append(one) other1 = Atoms(cell=solid1.get_cell(),pbc=solid1.get_pbc()) for one in solid1: if one.index not in indices1: other1.append(one) #Exchange atoms in sphere and build new solids nsolid1 = other1.copy() nsolid1.extend(group2.copy()) nsolid2 = other2.copy() nsolid2.extend(group1.copy()) #DEBUG: Write crossover to file if debug: write_xyz(Optimizer.debugfile, nsolid1,'CX(randalloybx):nsolid1') write_xyz(Optimizer.debugfile, nsolid2,'CX(randalloybx):nsolid2') #DEBUG: Check structure of atoms exchanged for sym,c,m,u in Optimizer.atomlist: if Optimizer.structure=='Defect': nc=len([atm for atm in nsolid1 if atm.symbol==sym]) nc+=len([atm for atm in ind1.bulki if atm.symbol==sym]) oc=len([atm for atm in solid1 if atm.symbol==sym]) oc+=len([atm for atm in ind1.bulki if atm.symbol==sym]) else: nc=len([atm for atm in nsolid1 if atm.symbol==sym]) oc=len([atm for atm in solid1 if atm.symbol==sym]) Optimizer.output.write('CX(clustbx):New solid1 contains '+repr(nc)+' '+repr(sym)+' atoms\n') if debug: print 'DEBUG CX: New solid1 contains '+repr(nc)+' '+repr(sym)+' atoms' if oc != nc: #pdb.set_trace() print 'CX: Issue in maintaining atom concentration\n Dropping new individual' Optimizer.output.write('CX: Issue in maintaining atom concentration\n Dropping new individual 1\n') nsolid1 = solid1 for sym,c,m,u in Optimizer.atomlist: if Optimizer.structure=='Defect': nc=len([atm for atm in nsolid2 if atm.symbol==sym]) nc+=len([atm for atm in ind2.bulki if atm.symbol==sym]) oc=len([atm for atm in solid2 if atm.symbol==sym]) oc+=len([atm for atm in ind2.bulki if atm.symbol==sym]) else: nc=len([atm for atm in nsolid2 if atm.symbol==sym]) oc=len([atm for atm in solid2 if atm.symbol==sym]) Optimizer.output.write('CX(clustbx):New solid2 contains '+repr(nc)+' '+repr(sym)+' atoms\n') if debug: print 'DEBUG CX: New solid2 contains '+repr(nc)+' '+repr(sym)+' atoms' if oc != nc: #pdb.set_trace() print 'CX: Issue in maintaining atom concentration\n Dropping new individual' Optimizer.output.write('CX: Issue in maintaining atom concentration\n Dropping new individual 2\n') solid2.pop() nsolid2 = solid2 if Optimizer.forcing !='Concentration': for i in range(len(Optimizer.atomlist)): atms1=[inds for inds in nsolid1 if inds.symbol==Optimizer.atomlist[i][0]] atms2=[inds for inds in nsolid2 if inds.symbol==Optimizer.atomlist[i][0]] if len(atms1)==0: if len(atms2)==0: nsolid1[random.randint(0,len(indi1)-1)].symbol==Optimizer.atomlist[i][0] nsolid2[random.randint(0,len(indi2)-1)].symbol==Optimizer.atomlist[i][0] else: nsolid1.append(atms2[random.randint(0,len(atms2)-1)]) nsolid1.pop(random.randint(0,len(nsolid1)-2)) else: if len(atms2)==0: nsolid2.append(atms1[random.randint(0,len(atms1)-1)]) nsolid2.pop(random.randint(0,len(nsolid2)-2)) nsolid1.set_cell(cello1) nsolid2.set_cell(cello2) nsolid1.set_pbc(pbc1) nsolid2.set_pbc(pbc2) ind1[0]=nsolid1.copy() ind2[0]=nsolid2.copy() return ind1, ind2
def clustbx(ind1, ind2, Optimizer): """Select a box in the cluster configuration """ if 'CX' in Optimizer.debug: debug = True else: debug = False Optimizer.output.write('Box Cluster Cx between individual ' + repr(ind1.index) + ' and individual ' + repr(ind2.index) + '\n') #Perserve starting conditions of individual solid1 = ind1[0].copy() solid2 = ind2[0].copy() cello1 = ind1[0].get_cell() cello2 = ind2[0].get_cell() cell1 = numpy.maximum.reduce( solid1.get_positions()) #-numpy.minimum.reduce(solid1.get_positions()) cell2 = numpy.maximum.reduce( solid2.get_positions()) #-numpy.minimum.reduce(solid2.get_positions()) cell = numpy.minimum(cell1, cell2) pbc1 = solid1.get_pbc() pbc2 = solid2.get_pbc() #Get starting concentrations and number of atoms nat1 = len(solid1) nat2 = len(solid2) if Optimizer.alloy == False: #Atomlist-based concent1 = [c for sym, c, m, u in Optimizer.atomlist] concent2 = [c for sym, c, m, u in Optimizer.atomlist] symlist = [sym for sym, c, m, u in Optimizer.atomlist] else: symlist = list(set(solid1.get_chemical_symbols())) #Assumes same types of atoms in both solid1 and solid2 concent1 = [] for one in symlist: atmss = [atm for atm in solid1 if atm.symbol == one] concent1.append(len(atmss)) concent2 = [] for one in symlist: atmss = [atm for atm in solid2 if atm.symbol == one] concent2.append(len(atmss)) # Pick a origin point for box in the cell #pt=[random.uniform(0,cell[0]),random.uniform(0,cell[1]),random.uniform(0,cell[2])] pt1 = random.choice(solid1).position pt2 = random.choice(solid2).position #Find max radius of circle cut r1 = min([ min(cell1[0] - pt1[0], pt1[0]), min(cell1[1] - pt1[1], pt1[1]), min(cell1[2] - pt1[2], pt1[2]) ]) r2 = min([ min(cell2[0] - pt2[0], pt2[0]), min(cell2[1] - pt2[1], pt2[1]), min(cell2[2] - pt2[2], pt2[2]) ]) r = min(r1, r2) mcell = min(cell) if r > mcell * 0.125: r = mcell * 0.125 elif r == 0.0: r = 1.0 if debug: print 'Radius of box = ' + repr(r) + '\nPosition in solid1 = ' + repr( pt1) + '\nPosition in solid2 = ' + repr(pt2) #Find atoms within sphere of radius r solid1.append(Atom(position=pt1)) dist1 = [] blist1 = [] for i in range(len(solid1) - 1): d = solid1.get_distance(i, len(solid1) - 1) if d < r: dist1.append((d, solid1[i])) else: blist1.append((d, solid1[i])) solid1.pop() solid2.append(Atom(position=pt2)) dist2 = [] blist2 = [] for i in range(len(solid2) - 1): d = solid2.get_distance(i, len(solid2) - 1) if d < r: dist2.append((d, solid2[i])) else: blist2.append((d, solid2[i])) solid2.pop() #Translate spheres to opposite location dats1 = Atoms() for d, atm in dist1: dats1.append(atm) dats1.translate(-pt1) dats1.translate(pt2) dats2 = Atoms() for d, atm in dist2: dats2.append(atm) dats2.translate(-pt2) dats2.translate(pt1) #Exchange atoms in sphere and build new solids nsolid1 = dats2.copy() for d, atm in blist1: nsolid1.append(atm) nsolid2 = dats1.copy() for d, atm in blist2: nsolid2.append(atm) #Identify new number of atoms nnat1 = len(nsolid1) nnat2 = len(nsolid2) if nnat1 > nat1: ds = [] #More atoms in new solid1 means solid2 has less atoms #Need to transfer atoms from solid1 to solid2 #Find atoms that are too close for i in range(len(dist2)): for j in range(len(dist2), len(nsolid1)): ds.append((nsolid1.get_distance(i, j), i)) #Sort distances by longest to shortest ds = sorted(ds, key=lambda one: one[0]) diff = nnat1 - nat1 exchangeindices = [] while len(exchangeindices) < diff: #Grab shortest distance in ds list d, index = ds.pop() if index not in exchangeindices: exchangeindices.append(index) nnsolid1 = Atoms() for i in range(len(nsolid1)): if i not in exchangeindices: nnsolid1.append(nsolid1[i]) nnsolid2 = nsolid2.copy() for i in exchangeindices: #for j in range(3): # position[j]=nsolid2[i].position[j]-pt1[j]+pt2[j] position = [ random.uniform(pt2[0] - r / (2**0.5), pt2[0] + r / (2**0.5)), random.uniform(pt2[1] - r / (2**0.5), pt2[1] + r / (2**0.5)), random.uniform(pt2[2] - r / (2**0.5), pt2[2] + r / (2**0.5)) ] nnsolid2.append(Atom(symbol=nsolid1[i].symbol, position=position)) nsolid1 = nnsolid1.copy() nsolid2 = nnsolid2.copy() elif nnat1 < nat1: ds = [] #More atoms in new solid2 means solid1 has less atoms #Need to transfer atoms from solid2 to solid1 #Find atoms that are too close for i in range(len(dist1)): for j in range(len(dist1), len(nsolid2)): ds.append((nsolid2.get_distance(i, j), i)) #Sort distances by longest to shortest ds = sorted(ds, key=lambda one: one[0]) diff = nnat2 - nat2 exchangeindices = [] while len(exchangeindices) < diff: #Grab shortest distance in ds list d, index = ds.pop() if index not in exchangeindices: exchangeindices.append(index) nnsolid2 = Atoms() for i in range(len(nsolid2)): if i not in exchangeindices: nnsolid2.append(nsolid2[i]) nnsolid1 = nsolid1.copy() for i in exchangeindices: #for j in range(3): # position[j]=nsolid2[i].position[j]-pt1[j]+pt2[j] position = [ random.uniform(pt1[0] - r / (2**0.5), pt1[0] + r / (2**0.5)), random.uniform(pt1[1] - r / (2**0.5), pt1[1] + r / (2**0.5)), random.uniform(pt1[2] - r / (2**0.5), pt1[2] + r / (2**0.5)) ] nnsolid1.append(Atom(symbol=nsolid2[i].symbol, position=position)) nsolid1 = nnsolid1.copy() nsolid2 = nnsolid2.copy() #Number of atoms in each individual should now be preserved try: if Optimizer.forcing == 'Concentration': #Need to check concentrations nconcent1 = [] for one in symlist: atmss = [atm for atm in nsolid1 if atm.symbol == one] nconcent1.append(len(atmss)) nconcent2 = [] for one in symlist: atmss = [atm for atm in nsolid2 if atm.symbol == one] nconcent2.append(len(atmss)) #Let's assume a random perturbation to concentration in order to correct this issue posd = [] negd = [] for i in range(len(nconcent1)): diff = nconcent1[i] - concent1[i] if diff > 0: posd.append((diff, symlist[i])) elif diff < 0: negd.append((diff, symlist[i])) for c, sym in negd: while c != 0: symr = posd[0][1] rlist = [ atm.index for atm in nsolid1 if atm.symbol == symr ] index1 = random.choice(rlist) nsolid1[index1].symbol = sym c += 1 posd[0] = (posd[0][0] - 1, posd[0][1]) if posd[0][0] == 0: posd = posd[1::] #Do the same for solid2 posd = [] negd = [] for i in range(len(nconcent2)): diff = nconcent2[i] - concent2[i] if diff > 0: posd.append((diff, symlist[i])) elif diff < 0: negd.append((diff, symlist[i])) for c, sym in negd: while c != 0: symr = posd[0][1] rlist = [ atm.index for atm in nsolid2 if atm.symbol == symr ] index1 = random.choice(rlist) nsolid2[index1].symbol = sym c += 1 posd[0] = (posd[0][0] - 1, posd[0][1]) if posd[0][0] == 0: posd = posd[1::] except: f = open('problem-structures.xyz', 'a') write_xyz(f, nsolid1, data='Failed - CX(randalloybx):nsolid1 ' + ind1.history_index) write_xyz(f, nsolid2, data='Failed - CX(randalloybx):nsolid2 ' + ind2.history_index) nsolid1 = ind1[0].copy() nsolid2 = ind2[0].copy() f.close() #DEBUG: Write crossover to file if debug: write_xyz(Optimizer.debugfile, nsolid1, 'CX(randalloybx):nsolid1') write_xyz(Optimizer.debugfile, nsolid2, 'CX(randalloybx):nsolid2') #DEBUG: Check structure of atoms exchanged for sym, c, m, u in Optimizer.atomlist: nc = len([atm for atm in nsolid1 if atm.symbol == sym]) Optimizer.output.write('CX(clustbx):New solid1 contains ' + repr(nc) + ' ' + repr(sym) + ' atoms\n') nc = len([atm for atm in nsolid2 if atm.symbol == sym]) Optimizer.output.write('CX(clustbx):New solid2 contains ' + repr(nc) + ' ' + repr(sym) + ' atoms\n') if Optimizer.forcing != 'Concentration': for i in range(len(Optimizer.atomlist)): atms1 = [ inds for inds in nsolid1 if inds.symbol == Optimizer.atomlist[i][0] ] atms2 = [ inds for inds in nsolid2 if inds.symbol == Optimizer.atomlist[i][0] ] if len(atms1) == 0: if len(atms2) == 0: nsolid1[random.randint( 0, len(indi1) - 1)].symbol == Optimizer.atomlist[i][0] nsolid2[random.randint( 0, len(indi2) - 1)].symbol == Optimizer.atomlist[i][0] else: nsolid1.append(atms2[random.randint(0, len(atms2) - 1)]) nsolid1.pop(random.randint(0, len(nsolid1) - 2)) else: if len(atms2) == 0: nsolid2.append(atms1[random.randint(0, len(atms1) - 1)]) nsolid2.pop(random.randint(0, len(nsolid2) - 2)) nsolid1.set_cell(cello1) nsolid2.set_cell(cello2) nsolid1.set_pbc(pbc1) nsolid2.set_pbc(pbc2) ind1[0] = nsolid1.copy() ind2[0] = nsolid2.copy() return ind1, ind2
def newclus(ind1, ind2, Optimizer): """Select a box in the cluster configuration""" if 'CX' in Optimizer.debug: debug = True else: debug = False Optimizer.output.write('Box Cluster Cx between individual ' + repr(ind1.index) + ' and individual ' + repr(ind2.index) + '\n') #Perserve starting conditions of individual solid1 = ind1[0].copy() solid2 = ind2[0].copy() cello1 = ind1[0].get_cell() cello2 = ind2[0].get_cell() cell1 = numpy.maximum.reduce(solid1.get_positions()) cell1m = numpy.minimum.reduce(solid1.get_positions()) cell2 = numpy.maximum.reduce(solid2.get_positions()) cell2m = numpy.minimum.reduce(solid2.get_positions()) cell = numpy.minimum(cell1, cell2) pbc1 = solid1.get_pbc() pbc2 = solid2.get_pbc() #Get starting concentrations and number of atoms nat1 = len(solid1) nat2 = len(solid2) # Pick a origin point for box in the cell pt1 = random.choice(solid1) pt1f = [(pt1.position[i] - cell1m[i]) / cell1[i] for i in range(3)] pt2 = [pt1f[i] * cell2[i] + cell2m[i] for i in range(3)] solid2.append(Atom(position=pt2)) pt2 = solid2[len(solid2) - 1] #Find max neighborsize of circle cut r = random.uniform(0, min(nat1, nat2) / 5.0) if debug: print 'DEBUG CX: Point one =', pt1.position print 'DEBUG CX: Point two =', pt2.position #Find atoms within sphere of neighborsize r for both individuals #Make sure that crossover is only selection of atoms not all while True: ctoff = [r for on in solid1] nl = NeighborList(ctoff, bothways=True, self_interaction=False) nl.update(solid1) indices1, offsets = nl.get_neighbors(pt1.index) if len(indices1) == 0: r = r * 1.2 elif len(indices1) < nat1 * .75: break else: r = r * 0.8 if debug: print 'Neighborsize of box = ' + repr( r) + '\nPosition in solid1 = ' + repr( pt1.position) + '\nPosition in solid2 = ' + repr(pt2.position) group1 = Atoms(cell=solid1.get_cell(), pbc=solid1.get_pbc()) group1.append(pt1) indices1a = [pt1.index] for index, d in zip(indices1, offsets): if index not in indices1a: index = int(index) pos = solid1[index].position + numpy.dot(d, solid1.get_cell()) group1.append(Atom(symbol=solid1[index].symbol, position=pos)) indices1a.append(index) indices1 = indices1a ctoff = [r for on in solid2] nl = NeighborList(ctoff, bothways=True, self_interaction=False) nl.update(solid2) indices2, offsets = nl.get_neighbors(pt2.index) group2 = Atoms(cell=solid2.get_cell(), pbc=solid2.get_pbc()) indices2a = [] for index, d in zip(indices2, offsets): if index not in indices2a: index = int(index) pos = solid2[index].position + numpy.dot(d, solid2.get_cell()) group2.append(Atom(symbol=solid2[index].symbol, position=pos)) indices2a.append(index) indices2 = indices2a if len(indices2) == 0: for one in group1: while True: sel = random.choice(solid2) if sel.symbol == one.symbol: if sel.index not in indices2: group2.append(sel) indices2.append(sel.index) break if Optimizer.forcing == 'Concentration': symlist = list(set(group1.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] indices2n.append(pt2.index) 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=solid2.get_cell(), pbc=solid2.get_pbc()) for one in solid2: if one.index not in indices2: other2.append(one) other1 = Atoms(cell=solid1.get_cell(), pbc=solid1.get_pbc()) for one in solid1: if one.index not in indices1: other1.append(one) #Exchange atoms in sphere and build new solids nsolid1 = other1.copy() nsolid1.extend(group2.copy()) nsolid2 = other2.copy() nsolid2.extend(group1.copy()) #DEBUG: Write crossover to file if debug: write_xyz(Optimizer.debugfile, nsolid1, 'CX(randalloybx):nsolid1') write_xyz(Optimizer.debugfile, nsolid2, 'CX(randalloybx):nsolid2') #DEBUG: Check structure of atoms exchanged for sym, c, m, u in Optimizer.atomlist: if Optimizer.structure == 'Defect': nc = len([atm for atm in nsolid1 if atm.symbol == sym]) nc += len([atm for atm in ind1.bulki if atm.symbol == sym]) oc = len([atm for atm in solid1 if atm.symbol == sym]) oc += len([atm for atm in ind1.bulki if atm.symbol == sym]) else: nc = len([atm for atm in nsolid1 if atm.symbol == sym]) oc = len([atm for atm in solid1 if atm.symbol == sym]) Optimizer.output.write('CX(clustbx):New solid1 contains ' + repr(nc) + ' ' + repr(sym) + ' atoms\n') if debug: print 'DEBUG CX: New solid1 contains ' + repr(nc) + ' ' + repr( sym) + ' atoms' if oc != nc: #pdb.set_trace() print 'CX: Issue in maintaining atom concentration\n Dropping new individual' Optimizer.output.write( 'CX: Issue in maintaining atom concentration\n Dropping new individual 1\n' ) nsolid1 = solid1 for sym, c, m, u in Optimizer.atomlist: if Optimizer.structure == 'Defect': nc = len([atm for atm in nsolid2 if atm.symbol == sym]) nc += len([atm for atm in ind2.bulki if atm.symbol == sym]) oc = len([atm for atm in solid2 if atm.symbol == sym]) oc += len([atm for atm in ind2.bulki if atm.symbol == sym]) else: nc = len([atm for atm in nsolid2 if atm.symbol == sym]) oc = len([atm for atm in solid2 if atm.symbol == sym]) Optimizer.output.write('CX(clustbx):New solid2 contains ' + repr(nc) + ' ' + repr(sym) + ' atoms\n') if debug: print 'DEBUG CX: New solid2 contains ' + repr(nc) + ' ' + repr( sym) + ' atoms' if oc != nc: #pdb.set_trace() print 'CX: Issue in maintaining atom concentration\n Dropping new individual' Optimizer.output.write( 'CX: Issue in maintaining atom concentration\n Dropping new individual 2\n' ) solid2.pop() nsolid2 = solid2 if Optimizer.forcing != 'Concentration': for i in range(len(Optimizer.atomlist)): atms1 = [ inds for inds in nsolid1 if inds.symbol == Optimizer.atomlist[i][0] ] atms2 = [ inds for inds in nsolid2 if inds.symbol == Optimizer.atomlist[i][0] ] if len(atms1) == 0: if len(atms2) == 0: nsolid1[random.randint( 0, len(indi1) - 1)].symbol == Optimizer.atomlist[i][0] nsolid2[random.randint( 0, len(indi2) - 1)].symbol == Optimizer.atomlist[i][0] else: nsolid1.append(atms2[random.randint(0, len(atms2) - 1)]) nsolid1.pop(random.randint(0, len(nsolid1) - 2)) else: if len(atms2) == 0: nsolid2.append(atms1[random.randint(0, len(atms1) - 1)]) nsolid2.pop(random.randint(0, len(nsolid2) - 2)) nsolid1.set_cell(cello1) nsolid2.set_cell(cello2) nsolid1.set_pbc(pbc1) nsolid2.set_pbc(pbc2) ind1[0] = nsolid1.copy() ind2[0] = nsolid2.copy() return ind1, ind2