def lattice_alteration(indiv, Optimizer): """Move function to perform Lattice Alteration of atoms 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 cell_max = numpy.maximum.reduce(indiv[0].get_positions()) cell_min = numpy.minimum.reduce(indiv[0].get_positions()) if Optimizer.structure == 'Defect': if Optimizer.isolate_mutation: indc, indb, vacant, swap, stro = find_defects( indiv[0], Optimizer.solidbulk, 0) positions = indc.get_positions() else: positions = indiv[0].get_positions() else: positions = indiv[0].get_positions() if len(positions) != 0: try: natomsmove = random.randint(1, len(positions) / 50) except ValueError: natomsmove = 1 ratmlocnew = [0] * natomsmove for i in range(natomsmove): ratmloc = random.randint(0, len(positions) - 1) ratmlocnew[i] = (random.uniform(cell_min[0], cell_max[0]), random.uniform(cell_min[1], cell_max[1]), random.uniform(cell_min[2], cell_max[2])) positions[ratmloc] = ratmlocnew[i] if Optimizer.structure == 'Defect': if Optimizer.isolate_mutation: indc.set_positions(positions) indiv[0] = indc.copy() indiv[0].extend(indb) else: indiv[0].set_positions(positions) else: indiv[0].set_positions(positions) else: natomsmove = 0 ratmlocnew = 0 Optimizer.output.write( 'Lattice Alteration Mutation performed on individual\n') Optimizer.output.write('Index = ' + repr(indiv.index) + '\n') Optimizer.output.write('Number of atoms moved = ' + repr(natomsmove) + '\n') Optimizer.output.write(repr(ratmlocnew) + '\n') Optimizer.output.write(repr(indiv[0]) + '\n') muttype = 'LA' + repr(natomsmove) if indiv.energy == 0: indiv.history_index = indiv.history_index + 'm' + muttype else: indiv.history_index = repr(indiv.index) + 'm' + muttype return indiv
def constrain_positions(indiv, bulk, sf): STR='' ts = indiv.copy() indc,indb,vacant,swap,stro = find_defects(ts,bulk,0) sbulk = bulk.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 > sf: STR+='Shifting structure to within region\n' r = random.random()*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] ts[id].position += trans return ts, STR
def lattice_alteration_rdrd(indiv, Optimizer): """Move function to move random atoms in random direction for random distance 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 d_max=numpy.minimum.reduce(numpy.maximum.reduce(indiv[0].get_positions())-numpy.minimum.reduce(indiv[0].get_positions())) if Optimizer.structure=='Defect': if Optimizer.isolate_mutation: indc,indb,vacant,swap,stro = find_defects(indiv[0],Optimizer.solidbulk,0) positions=indc.get_positions() else: positions = indiv[0].get_positions() else: positions=indiv[0].get_positions() if len(positions) != 0: try: # natomsmove=random.randint(1,len(positions)/5) natomsmove=random.randint(1,len(positions)/50) except ValueError: natomsmove=1 r=random.uniform(0.3,d_max) theta=math.radians(random.uniform(0,360)) phi=math.radians(random.uniform(0,180)) direction=[r*math.sin(theta)*math.cos(phi),r*math.sin(theta)*math.sin(phi),r*math.cos(theta)] ratmlocnew=[0]*natomsmove for i in range(natomsmove): ratmloc=random.randint(0,len(positions)-1) ratmlocnew[i]=(direction[0]+positions[ratmloc][0],direction[1]+positions[ratmloc][1],direction[2]+positions[ratmloc][2]) positions[ratmloc]=ratmlocnew[i] if Optimizer.structure=='Defect': if Optimizer.isolate_mutation: indc.set_positions(positions) indiv[0]=indc.copy() indiv[0].extend(indb) else: indiv[0].set_positions(positions) else: indiv[0].set_positions(positions) else: natomsmove=0 ratmlocnew=0 Optimizer.output.write('Lattice Alteration Mutation performed on individual\n') Optimizer.output.write('Index = '+repr(indiv.index)+'\n') Optimizer.output.write('Number of atoms moved = '+repr(natomsmove)+'\n') Optimizer.output.write(repr(ratmlocnew)+'\n') #Optimizer.output.write(repr(indiv[0])+'\n') muttype='LARD'+repr(natomsmove) if indiv.energy==0: indiv.history_index=indiv.history_index+'m'+muttype else: indiv.history_index=repr(indiv.index)+'m'+muttype return indiv
def lattice_alteration_crystal(indiv, Optimizer): """Move function to perform Lattice Alteration of atoms in size crystal 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 cell_max=numpy.maximum.reduce(indiv[0].get_cell()) cell_min=numpy.minimum.reduce(indiv[0].get_cell()) if Optimizer.structure=='Defect': if Optimizer.isolate_mutation: indc,indb,vacant,swap,stro = find_defects(indiv[0],Optimizer.solidbulk,0) positions=indc.get_positions() else: positions=indiv[0].get_positions() else: positions=indiv[0].get_positions() if len(positions) != 0: try: natomsmove=random.randint(1,len(positions)/5) except ValueError: natomsmove=1 ratmlocnew=[0]*natomsmove for i in range(natomsmove): ratmloc=random.randint(0,len(positions)-1) ratmlocnew[i]=(random.uniform(cell_min[0],cell_max[0]), random.uniform(cell_min[1],cell_max[1]), random.uniform(cell_min[2],cell_max[2])) positions[ratmloc]=ratmlocnew[i] if Optimizer.structure=='Defect': if Optimizer.isolate_mutation: indc.set_positions(positions) indiv[0]=indc.copy() indiv[0].extend(indb) else: indiv[0].set_positions(positions) else: indiv[0].set_positions(positions) else: natomsmove=0 ratmlocnew=0 Optimizer.output.write('Lattice Alteration Mutation performed on individual\n') Optimizer.output.write('Index = '+repr(indiv.index)+'\n') Optimizer.output.write('Number of atoms moved = '+repr(natomsmove)+'\n') Optimizer.output.write(repr(ratmlocnew)+'\n') Optimizer.output.write(repr(indiv[0])+'\n') muttype='LAC'+repr(natomsmove) if indiv.energy==0: indiv.history_index=indiv.history_index+'m'+muttype else: indiv.history_index=repr(indiv.index)+'m'+muttype return indiv
def rattle(indiv): """Function to slightly alter atoms in structure. Intended for use in defect function. """ atms,indb,vacant,swap,stro = find_defects(indiv[0],self.solidbulk,0.0) atmsl,indbl,vacantl,swapl,strol = find_defects(indiv[0],self.solidbulk,2.0) atmslist = [] for atm1 in atmsl: for atm2 in atms: if atm1.symbol==atm2.symbol: if atm1.position[0]==atm2.position[0] and atm1.position[1]==atm2.position[1] and atm1.position[2]==atm2.position[2]: atmslist.append(atm1.index) atmolist=[atm for atm in atmsl if atm.index not in atmslist] rat=Atoms(cell=atms.get_cell(), pbc=atms.get_pbc) for one in atmolist: rat.append(one) rat.rattle(stdev=0.2) ind=atms.copy() ind.extend(rat) ind.extend(indbl) return ind
def get_defect_restart_indiv(Optimizer, indiv): """ Function to generate an structopt Individual class object containing a defect structure from a previously existing structure Inputs: Optimizer = structopt Optimizer class indiv = ASE Atoms object containing the previously existing structure Outputs: individ = structopt Individual class object containing defect structure data """ if not Optimizer.solidbulk: #Initialize Bulk - Generate or load positions of bulk solid try: rank = MPI.COMM_WORLD.Get_rank() except: rank = 0 outfilename = os.path.join(os.path.join(os.getcwd(),Optimizer.filename+'-rank'+repr(rank)),'Bulkfile.xyz') if Optimizer.evalsolid: 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.summary.write('CIBS Run Pure Bulk Energy per Atom:'+ repr(PureBulkEnpa)+'\n') Optimizer.purebulkenpa = PureBulkEnpa Optimizer.natomsbulk = natomsbulk indiv.set_cell(Optimizer.solidcell) indiv.set_pbc(True) if Optimizer.restart_ints == 0: outt = find_defects(indiv,Optimizer.solidbulk,Optimizer.sf) else: indicop = [atm for atm in indiv if atm.symbol != 'X'] indiv = Atoms(cell=Optimizer.solidcell, pbc=True) for atm in indicop: indiv.append(atm) outt=[indiv[0:Optimizer.restart_ints],indiv[Optimizer.restart_ints::], Atoms(), Atoms(),'Assuming first '+repr(Optimizer.restart_ints)+' are interstitials\n'] indi = outt[0].copy() bulki = outt[1].copy() individ = Individual(indi) individ.bulko = bulki.copy() individ.bulki = bulki.copy() individ.purebulkenpa = Optimizer.purebulkenpa individ.natomsbulk = Optimizer.natomsbulk individ.vacancies = outt[2].copy() individ.swaps = outt[3].copy() Optimizer.output.write(outt[4]) return individ
def zp_rotation(indiv, Optimizer): """Move function to perform Zero point rotation of atoms 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.forcing != 'FreeNatom': ax=['x', '-x','y','-y','z','-z'] else: ax=['z','-z'] #Identify random rotation about axis and rotate all atoms rax=ax[random.randint(0,len(ax)-1)] #rang=random.uniform(30,180) rang=random.random()*math.pi #rang=random.random()*90 if Optimizer.structure=='Defect': if Optimizer.isolate_mutation: atms,indb,vacant,swap,stro = find_defects(indiv[0],Optimizer.solidbulk,0) else: atms = indiv[0] else: atms=indiv[0] atms.rotate(rax,a=rang,center='COM',rotate_cell=False) if Optimizer.structure=='Defect': if Optimizer.isolate_mutation: atms.extend(indb) indiv[0]=atms.copy() Optimizer.output.write('Zero point full rotation performed on individual\n') Optimizer.output.write('Index = '+repr(indiv.index)+'\n') Optimizer.output.write('Rotation vector = '+repr(rax)+'\n') Optimizer.output.write('Rotation angle = '+repr(rang)+'\n') muttype='ZPR' if indiv.energy==0: indiv.history_index=indiv.history_index+'m'+muttype else: indiv.history_index=repr(indiv.index)+'m'+muttype return indiv
def move_la(indiv, Optimizer): """Move function to move atoms in structure by lattice constant. Intended for use in Defect optimization. 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 #Move structure by lattice constant Optimizer.output.write('Lattice Constant Move Mutation performed on individual\n') if Optimizer.structure=='Defect': if Optimizer.isolate_mutation: indc,indb,vacant,swaps,stro = find_defects(indiv[0],Optimizer.solidbulk,0) ind = indc.copy() else: ind = indiv[0] la = numpy.maximum.reduce(numpy.maximum.reduce(ind.get_cell())/Optimizer.solidcell) ax = [[1,0,0],[0,1,0],[0,0,1],[-1,0,0],[0,-1,0],[0,0,-1]] selax = [la*i for i in random.choice(ax)] ind.translate(selax) indiv[0]=ind.copy() if Optimizer.isolate_mutation: indiv[0].extend(indb) else: Optimizer.output.write('WARNING: Move Mutation performed on non-Defect structure\n') Optimizer.output.write('Index = '+repr(indiv.index)+'\n') Optimizer.output.write(repr(indiv[0])+'\n') muttype='LM' if indiv.energy==0: indiv.history_index=indiv.history_index+'m'+muttype else: indiv.history_index=repr(indiv.index)+'m'+muttype return indiv
def get_defect_restart_indiv(Optimizer, indiv): """ Function to generate an structopt Individual class object containing a defect structure from a previously existing structure Inputs: Optimizer = structopt Optimizer class indiv = ASE Atoms object containing the previously existing structure Outputs: individ = structopt Individual class object containing defect structure data """ if not Optimizer.solidbulk: #Initialize Bulk - Generate or load positions of bulk solid try: rank = MPI.COMM_WORLD.Get_rank() except: rank = 0 outfilename = os.path.join( os.path.join(os.getcwd(), Optimizer.filename + '-rank' + repr(rank)), 'Bulkfile.xyz') if Optimizer.evalsolid: 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.summary.write('CIBS Run Pure Bulk Energy per Atom:' + repr(PureBulkEnpa) + '\n') Optimizer.purebulkenpa = PureBulkEnpa Optimizer.natomsbulk = natomsbulk indiv.set_cell(Optimizer.solidcell) indiv.set_pbc(True) if Optimizer.restart_ints == 0: outt = find_defects(indiv, Optimizer.solidbulk, Optimizer.sf) else: indicop = [atm for atm in indiv if atm.symbol != 'X'] indiv = Atoms(cell=Optimizer.solidcell, pbc=True) for atm in indicop: indiv.append(atm) outt = [ indiv[0:Optimizer.restart_ints], indiv[Optimizer.restart_ints::], Atoms(), Atoms(), 'Assuming first ' + repr(Optimizer.restart_ints) + ' are interstitials\n' ] indi = outt[0].copy() bulki = outt[1].copy() individ = Individual(indi) individ.bulko = bulki.copy() individ.bulki = bulki.copy() individ.purebulkenpa = Optimizer.purebulkenpa individ.natomsbulk = Optimizer.natomsbulk individ.vacancies = outt[2].copy() individ.swaps = outt[3].copy() Optimizer.output.write(outt[4]) return individ
def rotation_geo(indiv, Optimizer): '''Function to handle a geometry based rotation mutation Rotates a small group of atoms based on location within structure Input: indiv = structopt_stem Individual class object to be mutated Optimizer = structopt_stem Optimizer class object Output: indiv = structopt_stem Individual class object that has been mutated ''' if 'MU' in Optimizer.debug: debug = True else: debug = False #Rotate group of atoms based on geometry if Optimizer.structure == 'Defect': if Optimizer.isolate_mutation: atms, indb, vacant, swap, stro = find_defects( indiv[0], Optimizer.solidbulk, 0) else: atms = indiv[0].copy() else: atms = indiv[0].copy() nat = len(atms) if nat > 1: #Select number of atoms to rotate if nat == 2: natrot = 2 else: natrot = random.randint(2, nat) #Select random position in cluster cell = numpy.maximum.reduce( atms.get_positions()) - numpy.minimum.reduce(atms.get_positions()) pt = [ random.uniform(0, cell[0]), random.uniform(0, cell[1]), random.uniform(0, cell[2]) ] #Get distance of atoms from random point atpt = Atom(position=pt) atms.append(atpt) dist = [] for i in range(len(atms) - 1): dist.append(atms.get_distance(i, len(atms) - 1)) atms.pop() dlist = zip(dist, atms) dlist = sorted(dlist, key=lambda one: one[0], reverse=True) # Select atoms closest to random point atmsr = Atoms() indexlist = [] for i in range(natrot): atmsr.append(dlist[i][1]) indexlist.append(dlist[i][1].index) #Identify random rotation and rotate selected atoms ax = ['x', '-x', 'y', '-y', 'z', '-z'] rax = ax[random.randint(0, len(ax) - 1)] rang = random.uniform(30, 180) #rang=random.random()*90 atmsr.rotate(rax, a=rang, center='COM', rotate_cell=False) #Update individual with new atom positions for i in range(len(indexlist)): index = indexlist[i] atms[index].position = atmsr[i].position if Optimizer.structure == 'Defect': if Optimizer.isolate_mutation: atms.extend(indb) indiv[0] = atms.copy() #Optimizer.output.write('New positions = '+repr(indiv[0].get_positions())+'\n') else: natrot = 0 pt = 0 rax = 0 rang = 0 Optimizer.output.write( 'Geometry Rotation Mutation performed on individual\n') Optimizer.output.write('Index = ' + repr(indiv.index) + '\n') Optimizer.output.write('Number of atoms rotated = ' + repr(natrot) + '\n') Optimizer.output.write('Geometry point = ' + repr(pt) + '\n') Optimizer.output.write('Rotation vector = ' + repr(rax) + '\n') Optimizer.output.write('Rotation angle = ' + repr(rang) + '\n') Optimizer.output.write(repr(indiv[0]) + '\n') muttype = 'GR' + repr(natrot) if indiv.energy == 0: indiv.history_index = indiv.history_index + 'm' + muttype else: indiv.history_index = repr(indiv.index) + 'm' + muttype return indiv
def rotation_geo(indiv, Optimizer): '''Function to handle a geometry based rotation mutation Rotates a small group of atoms based on location within structure Input: indiv = structopt_stem Individual class object to be mutated Optimizer = structopt_stem Optimizer class object Output: indiv = structopt_stem Individual class object that has been mutated ''' if 'MU' in Optimizer.debug: debug = True else: debug = False #Rotate group of atoms based on geometry if Optimizer.structure=='Defect': if Optimizer.isolate_mutation: atms,indb,vacant,swap,stro = find_defects(indiv[0],Optimizer.solidbulk,0) else: atms = indiv[0].copy() else: atms=indiv[0].copy() nat=len(atms) if nat > 1: #Select number of atoms to rotate if nat==2: natrot=2 else: natrot = random.randint(2,nat) #Select random position in cluster cell=numpy.maximum.reduce(atms.get_positions())-numpy.minimum.reduce(atms.get_positions()) pt=[random.uniform(0,cell[0]),random.uniform(0,cell[1]),random.uniform(0,cell[2])] #Get distance of atoms from random point atpt=Atom(position=pt) atms.append(atpt) dist=[] for i in range(len(atms)-1): dist.append(atms.get_distance(i,len(atms)-1)) atms.pop() dlist=zip(dist,atms) dlist=sorted(dlist, key=lambda one: one[0], reverse=True) # Select atoms closest to random point atmsr=Atoms() indexlist=[] for i in range(natrot): atmsr.append(dlist[i][1]) indexlist.append(dlist[i][1].index) #Identify random rotation and rotate selected atoms ax=['x', '-x','y','-y','z','-z'] rax=ax[random.randint(0,len(ax)-1)] rang=random.uniform(30,180) #rang=random.random()*90 atmsr.rotate(rax,a=rang,center='COM',rotate_cell=False) #Update individual with new atom positions for i in range(len(indexlist)): index=indexlist[i] atms[index].position=atmsr[i].position if Optimizer.structure=='Defect': if Optimizer.isolate_mutation: atms.extend(indb) indiv[0]=atms.copy() #Optimizer.output.write('New positions = '+repr(indiv[0].get_positions())+'\n') else: natrot=0 pt=0 rax=0 rang=0 Optimizer.output.write('Geometry Rotation Mutation performed on individual\n') Optimizer.output.write('Index = '+repr(indiv.index)+'\n') Optimizer.output.write('Number of atoms rotated = '+repr(natrot)+'\n') Optimizer.output.write('Geometry point = '+repr(pt)+'\n') Optimizer.output.write('Rotation vector = '+repr(rax)+'\n') Optimizer.output.write('Rotation angle = '+repr(rang)+'\n') Optimizer.output.write(repr(indiv[0])+'\n') muttype='GR'+repr(natrot) if indiv.energy==0: indiv.history_index=indiv.history_index+'m'+muttype else: indiv.history_index=repr(indiv.index)+'m'+muttype return indiv
def rotation(indiv, Optimizer): """Move function to perform rotation of a group of atoms 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': if Optimizer.isolate_mutation: atms,indb,vacant,swap,stro = find_defects(indiv[0],Optimizer.solidbulk,0) else: atms = indiv[0] else: atms=indiv[0] nat=len(atms) if nat != 0: if nat<=1: natrot2=1 natrot1=0 elif nat<=6: natrot2=2 natrot1=0 else: natrot1=random.randint(1,nat/2) natrot2=random.randint(2,(nat-1)/2) if natrot2 >= natrot1: natrot2 +=1 else: natrot1, natrot2 = natrot2, natrot1 natrot=natrot2 - natrot1 atmsr=atms[natrot1:natrot2] del atms[natrot1:natrot2] ax=['x', '-x','y','-y','z','-z'] rax=ax[random.randint(0,len(ax)-1)] rang=random.uniform(30,180) #rang=random.random()*90 atmsr.rotate(rax,a=rang,center='COM',rotate_cell=False) atms.extend(atmsr) if Optimizer.structure=='Defect': if Optimizer.isolate_mutation: atms.extend(indb) indiv[0]=atms.copy() else: natrot=0 rax=0 rang=0 Optimizer.output.write('Rotation Mutation performed on individual\n') Optimizer.output.write('Index = '+repr(indiv.index)+'\n') Optimizer.output.write('Number of atoms rotated = '+repr(natrot)+'\n') Optimizer.output.write('Rotation vector = '+repr(rax)+'\n') Optimizer.output.write('Rotation angle = '+repr(rang)+'\n') Optimizer.output.write(repr(indiv[0])+'\n') muttype='R'+repr(natrot) if indiv.energy==0: indiv.history_index=indiv.history_index+'m'+muttype else: indiv.history_index=repr(indiv.index)+'m'+muttype return indiv
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 lattice_alteration_group(indiv, Optimizer): """Move function to perform Lattice Alteration of group of atoms based on location 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': if Optimizer.isolate_mutation: indc,indb,vacant,swap,stro = find_defects(indiv[0],Optimizer.solidbulk,0) atms=indc.copy() else: atms=indiv[0].copy() else: atms=indiv[0].copy() if len(atms) != 0: try: natomsmove=random.randint(1,len(atms)/5) except ValueError: natomsmove=1 #Select random position in cluster cellx=numpy.maximum.reduce(atms.get_positions()) cellm=numpy.minimum.reduce(atms.get_positions()) pt=[random.uniform(cellm[0],cellx[0]),random.uniform(cellm[1],cellx[1]),random.uniform(cellm[2],cellx[2])] #Get distance of atoms from random point atpt=Atom(position=pt) atms.append(atpt) dist=[] for i in range(len(atms)-1): dist.append(atms.get_distance(i,len(atms)-1)) atms.pop() dlist=zip(dist,atms) dlist=sorted(dlist, key=lambda one: one[0], reverse=True) # Select atoms closest to random point atmst=Atoms() indexlist=[] for i in range(natomsmove): atmst.append(dlist[i][1]) indexlist.append(dlist[i][1].index) trans=(random.uniform(0,cellx[0]-cellm[0]), random.uniform(0,cellx[1]-cellm[1]), random.uniform(0,cellx[2]-cellm[2])) atmst.translate(trans) for i in range(len(indexlist)): index=indexlist[i] atms[index].position=atmst[i].position if Optimizer.structure=='Defect': if Optimizer.isolate_mutation: indiv[0]=atms.copy() indiv[0].extend(indb) else: indiv[0] = atms.copy() else: indiv[0]=atms.copy() else: natomsmove=0 trans=0 Optimizer.output.write('Group Lattice Alteration Mutation performed on individual\n') Optimizer.output.write('Index = '+repr(indiv.index)+'\n') Optimizer.output.write('Number of atoms moved = '+repr(natomsmove)+'\n') Optimizer.output.write(repr(trans)+'\n') Optimizer.output.write(repr(indiv[0])+'\n') muttype='LAGC'+repr(natomsmove) if indiv.energy==0: indiv.history_index=indiv.history_index+'m'+muttype else: indiv.history_index=repr(indiv.index)+'m'+muttype return indiv
indiv.energy = 10000 f.close() print ' Writing structure to problemstructures.xyz file. Structure (hindex) : '+indiv.history_index print ' Setting individual energy to 50000.' outs = [10000, starting.bulki, starting, stro] indiv = outs[2] indiv.energy = outs[0] stro=outs[3] if Optimizer.structure == 'Defect' or Optimizer.structure=='Surface': indiv.bulki = outs[1] indiv.fitness = indiv.energy if abs(indiv.fitness) > Optimizer.energy_cutoff_factor*(len(indiv[0])+len(indiv.bulki)): indiv.fitness=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' if math.isnan(indiv.fitness): logger.warn('Found NAN energy structure HI={0}'.format(indiv.history_index)) indiv.fitness=10000 indiv.energy = 10000 indc,indb,vacant,swap,stro = find_defects(indiv[0],Optimizer.solidbulk,0) syms = indc.get_chemical_symbols() for sym in syms: if sym=='Si': message = 'Identified Si atom in defect added energy bias +50eV' logger.info(message) stro+=' '+message+'\n' indiv.fitness+=50 indiv.energy+=50 return indiv, stro
def lattice_alteration_nn(indiv, Optimizer): """Move function to perform random move along random axis for nearest neighbor distance to random atoms 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': if Optimizer.isolate_mutation: indc,indb,vacant,swaps,stro = find_defects(indiv[0],Optimizer.solidbulk,0) ind = indc.copy() ind.extend(indb) else: ind=indiv[0].copy() indc=indiv[0].copy() else: ind=indiv[0].copy() indc=indiv[0].copy() if len(indc) != 0: ctoff1 = [1.0 for one in ind] nl = NeighborList(ctoff1, bothways=True, self_interaction=False) nl.update(ind) try: natomsmove=random.randint(1,len(indc)/2) except ValueError: natomsmove=1 passn=0 for count in range(natomsmove): try: indexmv = random.choice([i for i in range(len(indc))]) indices, offsets = nl.get_neighbors(indexmv) nns = Atoms() nns.append(ind[indexmv]) for index, d in zip(indices,offsets): index = int(index) pos = ind[index].position + numpy.dot(d,ind.get_cell()) nns.append(Atom(symbol=ind[index].symbol, position=pos)) dist = [nns.get_distance(0,i) for i in range(1, len(nns))] r = sum(dist)/len(dist) dir = random.choice([[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]]) ind[indexmv].position += [i*r for i in dir] except: passn+=1 indiv[0]=ind.copy() else: natomsmove=0 passn=0 Optimizer.output.write('Lattice Alteration NN Mutation performed on individual\n') Optimizer.output.write('Index = '+repr(indiv.index)+'\n') natomsmove-=passn Optimizer.output.write('Number of atoms moved = '+repr(natomsmove)+'\n') Optimizer.output.write(repr(indiv[0])+'\n') muttype='LANN'+repr(natomsmove) if indiv.energy==0: indiv.history_index=indiv.history_index+'m'+muttype else: indiv.history_index=repr(indiv.index)+'m'+muttype return indiv
def lattice_alteration_rdrd(indiv, Optimizer): """Move function to move random atoms in random direction for random distance 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 d_max = numpy.minimum.reduce( numpy.maximum.reduce(indiv[0].get_positions()) - numpy.minimum.reduce(indiv[0].get_positions())) if Optimizer.structure == 'Defect': if Optimizer.isolate_mutation: indc, indb, vacant, swap, stro = find_defects( indiv[0], Optimizer.solidbulk, 0) positions = indc.get_positions() else: positions = indiv[0].get_positions() else: positions = indiv[0].get_positions() if len(positions) != 0: try: # natomsmove=random.randint(1,len(positions)/5) natomsmove = random.randint(1, len(positions) / 50) except ValueError: natomsmove = 1 r = random.uniform(0.3, d_max) theta = math.radians(random.uniform(0, 360)) phi = math.radians(random.uniform(0, 180)) direction = [ r * math.sin(theta) * math.cos(phi), r * math.sin(theta) * math.sin(phi), r * math.cos(theta) ] ratmlocnew = [0] * natomsmove for i in range(natomsmove): ratmloc = random.randint(0, len(positions) - 1) ratmlocnew[i] = (direction[0] + positions[ratmloc][0], direction[1] + positions[ratmloc][1], direction[2] + positions[ratmloc][2]) positions[ratmloc] = ratmlocnew[i] if Optimizer.structure == 'Defect': if Optimizer.isolate_mutation: indc.set_positions(positions) indiv[0] = indc.copy() indiv[0].extend(indb) else: indiv[0].set_positions(positions) else: indiv[0].set_positions(positions) else: natomsmove = 0 ratmlocnew = 0 Optimizer.output.write( 'Lattice Alteration Mutation performed on individual\n') Optimizer.output.write('Index = ' + repr(indiv.index) + '\n') Optimizer.output.write('Number of atoms moved = ' + repr(natomsmove) + '\n') Optimizer.output.write(repr(ratmlocnew) + '\n') #Optimizer.output.write(repr(indiv[0])+'\n') muttype = 'LARD' + repr(natomsmove) if indiv.energy == 0: indiv.history_index = indiv.history_index + 'm' + muttype else: indiv.history_index = repr(indiv.index) + 'm' + muttype return indiv
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_clus(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 if Optimizer.structure != 'Defect': Optimizer.output.write('Rotate-Cut Random Cluster Cx attempted on Non Defect structure. SKIPPING CX.\n') else: Optimizer.output.write('Rotate-Cut Random Cluster 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() indi1c,indi1b,vacant1,swap1,stro1 = find_defects(indi1,Optimizer.solidbulk,0) indi2c,indi2b,vacant2,swap2,stro2 = find_defects(indi2,Optimizer.solidbulk,0) if len(indi1c) !=0 and len(indi2c) != 0: #Translate individuals so COM is at (0,0,0) com1 = indi1c.get_center_of_mass() indi1c.translate(-1*com1) com2 = indi2c.get_center_of_mass() indi2c.translate(-1*com2) #Select random axis, random angle, and random position and rotate individuals cmax = [min(numpy.maximum.reduce(indi1c.get_positions())[i],numpy.maximum.reduce(indi2c.get_positions())[i]) for i in range(3)] cmin = [min(numpy.minimum.reduce(indi1c.get_positions())[i],numpy.minimum.reduce(indi2c.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)] indi1c.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 indi1c: 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 indi1c.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) indi2c.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 indi2c: if one.position[2] >= 0: group2.append(one) indices2.append(one.index) if Optimizer.forcing=='Concentration': symlist = list(set(indi1c.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 indi2c: if one.index not in indices2: other2.append(one) other1 = Atoms(cell=ind1[0].get_cell(),pbc=ind1[0].get_pbc()) for one in indi1c: if one.index not in indices1: other1.append(one) group1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) group1.translate(com1) other1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) other1.translate(com1) group2.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) group2.translate(com2) other2.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) other2.translate(com2) indi1 = group2.copy() indi1.extend(other1) indi1.extend(indi1b) indi2 = group1.copy() indi2.extend(other2) indi2.extend(indi2b) #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)) #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() else: Optimizer.output.write(' Warning: failed to identify a cluster:\n') Optimizer.output.write(' Individual '+repr(ind1.index)+' length = '+repr(len(indi1c))+'\n') Optimizer.output.write(' Individual '+repr(ind2.index)+' length = '+repr(len(indi2c))+'\n') ind1[0]=indi1 ind2[0]=indi2 return ind1, ind2
def random_replacement(indiv, Optimizer): """Move function to replace selection of atoms with randomly generated group 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': if Optimizer.isolate_mutation: atms,indb,vacant,swap,stro = find_defects(indiv[0],Optimizer.solidbulk,0) else: atms = indiv[0].copy() else: atms=indiv[0].copy() nat=len(atms) if nat != 0: #Select number of atoms to replace if nat<=1: natrep2=1 natrep1=0 elif nat<=5: natrep2=2 natrep1=0 else: natrep1=random.randint(1,nat/2) while True: natrep2=random.randint(2,nat/2) if natrep2 != natrep1: break natrep=abs(natrep2 - natrep1) #Select random position in cluster maxcell = numpy.maximum.reduce(atms.get_positions()) mincell = numpy.minimum.reduce(atms.get_positions()) pt=[random.uniform(mincell[0],maxcell[0]),random.uniform(mincell[1],maxcell[1]),random.uniform(mincell[2],maxcell[2])] #Get distance of atoms from random point atpt=Atom(position=pt) atms.append(atpt) dist=[] for i in range(len(atms)-1): dist.append(atms.get_distance(i,len(atms)-1)) atms.pop() dlist=zip(dist,atms) dlist=sorted(dlist, key=lambda one: one[0], reverse=True) # Select atoms closest to random point atmsr=Atoms() indexlist=[] for i in range(natrep): atmsr.append(dlist[i][1]) indexlist.append(dlist[i][1].index) natomlist=[0]*len(Optimizer.atomlist) for i in range(len(Optimizer.atomlist)): atms1=[inds for inds in atmsr if inds.symbol==Optimizer.atomlist[i][0]] natomlist[i]=(Optimizer.atomlist[i][0], len(atms1),Optimizer.atomlist[i][2],Optimizer.atomlist[i][3]) nsize = max(numpy.maximum.reduce(atmsr.get_positions())-numpy.minimum.reduce(atmsr.get_positions())) repcenter = atmsr.get_center_of_mass() atmsn = gen_pop_box(natomlist,nsize) atmsn.translate(repcenter) #Update individual with new atom positions for i in range(len(indexlist)): index=indexlist[i] atms[index].position=atmsn[i].position if Optimizer.structure=='Defect': if Optimizer.isolate_mutation: atms.extend(indb) indiv[0]=atms.copy() else: natrep=0 pt=0 Optimizer.output.write('Random Group Replacement Mutation performed on individual\n') Optimizer.output.write('Index = '+repr(indiv.index)+'\n') Optimizer.output.write('Number of atoms replaced = '+repr(natrep)+'\n') Optimizer.output.write('Geometry point = '+repr(pt)+'\n') Optimizer.output.write(repr(indiv[0])+'\n') muttype='RGR'+repr(natrep) if indiv.energy==0: indiv.history_index=indiv.history_index+'m'+muttype else: indiv.history_index=repr(indiv.index)+'m'+muttype return indiv
indiv = outs[2] indiv.energy = outs[0] stro = outs[3] if Optimizer.structure == 'Defect' or Optimizer.structure == 'Surface': indiv.bulki = outs[1] indiv.fitness = indiv.energy if abs(indiv.fitness) > Optimizer.energy_cutoff_factor * ( len(indiv[0]) + len(indiv.bulki)): indiv.fitness = 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' if math.isnan(indiv.fitness): logger.warn('Found NAN energy structure HI={0}'.format( indiv.history_index)) indiv.fitness = 10000 indiv.energy = 10000 indc, indb, vacant, swap, stro = find_defects(indiv[0], Optimizer.solidbulk, 0) syms = indc.get_chemical_symbols() for sym in syms: if sym == 'Si': message = 'Identified Si atom in defect added energy bias +50eV' logger.info(message) stro += ' ' + message + '\n' indiv.fitness += 50 indiv.energy += 50 return indiv, stro
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': # logger.info('M:') 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() #print 'rank, eval_energy.cell',rank,origcell if Optimizer.forcing != 'RelaxBox': 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]) # logger.info('M: set cell') 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') # logger.info('M:check dist') totalsol, STR = check_min_dist(Optimizer, 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: # logger.info('M:start calculator') 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, pea, energy, pressure, volume, STR = run_energy_eval(totalsol, Optimizer.calc_method, Optimizer.fixed_region, Optimizer.fitness_scheme, STR, Optimizer.static_calc) else: # logger.info('M:start run_energy_eval') totalsol, pea, energy, pressure, volume, STR = run_energy_eval(totalsol, Optimizer.calc_method, False, Optimizer.fitness_scheme, STR) logger.info('M:finish run_energy_eval, energy = {0} @ rank ={1}'.format(energy,rank)) 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') if Optimizer.forcing != 'RelaxBox': 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 #Add pealist to include atom index based on sorted PE. logger.info('before sort{0}'.format(individ.energy)) sort_pealist(Optimizer,individ,pea) energy = individ.energy logger.info('after sort {0}'.format(individ.energy)) 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
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:
def lattice_alteration_group(indiv, Optimizer): """Move function to perform Lattice Alteration of group of atoms based on location 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': if Optimizer.isolate_mutation: indc, indb, vacant, swap, stro = find_defects( indiv[0], Optimizer.solidbulk, 0) atms = indc.copy() else: atms = indiv[0].copy() else: atms = indiv[0].copy() if len(atms) != 0: try: natomsmove = random.randint(1, len(atms) / 5) except ValueError: natomsmove = 1 #Select random position in cluster cellx = numpy.maximum.reduce(atms.get_positions()) cellm = numpy.minimum.reduce(atms.get_positions()) pt = [ random.uniform(cellm[0], cellx[0]), random.uniform(cellm[1], cellx[1]), random.uniform(cellm[2], cellx[2]) ] #Get distance of atoms from random point atpt = Atom(position=pt) atms.append(atpt) dist = [] for i in range(len(atms) - 1): dist.append(atms.get_distance(i, len(atms) - 1)) atms.pop() dlist = zip(dist, atms) dlist = sorted(dlist, key=lambda one: one[0], reverse=True) # Select atoms closest to random point atmst = Atoms() indexlist = [] for i in range(natomsmove): atmst.append(dlist[i][1]) indexlist.append(dlist[i][1].index) trans = (random.uniform(0, cellx[0] - cellm[0]), random.uniform(0, cellx[1] - cellm[1]), random.uniform(0, cellx[2] - cellm[2])) atmst.translate(trans) for i in range(len(indexlist)): index = indexlist[i] atms[index].position = atmst[i].position if Optimizer.structure == 'Defect': if Optimizer.isolate_mutation: indiv[0] = atms.copy() indiv[0].extend(indb) else: indiv[0] = atms.copy() else: indiv[0] = atms.copy() else: natomsmove = 0 trans = 0 Optimizer.output.write( 'Group Lattice Alteration Mutation performed on individual\n') Optimizer.output.write('Index = ' + repr(indiv.index) + '\n') Optimizer.output.write('Number of atoms moved = ' + repr(natomsmove) + '\n') Optimizer.output.write(repr(trans) + '\n') Optimizer.output.write(repr(indiv[0]) + '\n') muttype = 'LAGC' + repr(natomsmove) if indiv.energy == 0: indiv.history_index = indiv.history_index + 'm' + muttype else: indiv.history_index = repr(indiv.index) + 'm' + muttype return indiv
def rotation(indiv, Optimizer): """Move function to perform rotation of a group of atoms 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': if Optimizer.isolate_mutation: atms,indb,vacant,swap,stro = find_defects(indiv[0],Optimizer.solidbulk,0) else: atms = indiv[0] else: atms=indiv[0] nat=len(atms) if nat != 0: if nat<=1: natrot2=1 natrot1=0 elif nat<=6: natrot2=2 natrot1=0 else: natrot1=random.randint(1,nat/2) natrot2=random.randint(2,(nat-1)/2) if natrot2 >= natrot1: natrot2 +=1 else: natrot1, natrot2 = natrot2, natrot1 natrot=natrot2 - natrot1 atmsr=atms[natrot1:natrot2] del atms[natrot1:natrot2] if Optimizer.forcing != 'FreeNatom': ax=['x', '-x','y','-y','z','-z'] else: ax=['z','-z'] rax=ax[random.randint(0,len(ax)-1)] #rang=random.uniform(30,180) rang=random.random()*math.pi #rang=random.random()*90 atmsr.rotate(rax,a=rang,center='COM',rotate_cell=False) atms.extend(atmsr) if Optimizer.structure=='Defect': if Optimizer.isolate_mutation: atms.extend(indb) indiv[0]=atms.copy() else: natrot=0 rax=0 rang=0 Optimizer.output.write('Rotation Mutation performed on individual\n') Optimizer.output.write('Index = '+repr(indiv.index)+'\n') Optimizer.output.write('Number of atoms rotated = '+repr(natrot)+'\n') Optimizer.output.write('Rotation vector = '+repr(rax)+'\n') Optimizer.output.write('Rotation angle = '+repr(rang)+'\n') Optimizer.output.write(repr(indiv[0])+'\n') muttype='R'+repr(natrot) if indiv.energy==0: indiv.history_index=indiv.history_index+'m'+muttype else: indiv.history_index=repr(indiv.index)+'m'+muttype return indiv
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:
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