def mutation_dups_adapt_stem(pop, Optimizer): """Predator function that removes individuals based on fitness and mutates replacements """ fitlist = [one.fitness for one in pop] nfitlist, nindices = remove_duplicates(fitlist, Optimizer.demin) STR = '' newpop = [] if len(nfitlist) != len(fitlist): STR+='Predator: Removed total of '+repr(len(fitlist)-len(nfitlist))+' from population\n' otherlist = [] for i in range(len(pop)): if i not in nindices: STR+='Predator: Removed '+repr(pop[i].history_index)+'\n' otherlist.append(pop[i]) else: newpop.append(pop[i]) while len(newpop) < Optimizer.nindiv: indiv = random.choice(otherlist).duplicate() indiv, scheme = moves_switch(indiv,Optimizer) indiv.energy = 1000 indiv.fitness = 1000 newpop.append(indiv) STR+='Predator: Adding mutated duplicates to new pop history='+indiv.history_index+'\n' nindices.append(indiv.index) nindices.sort() if Optimizer.natural_selection_scheme=='fussf': for ind in newpop: if ind.fingerprint == 0: ind.fingerprint = get_fingerprint(Optimizer,ind,Optimizer.fpbin,Optimizer.fpcutoff) if 'lambda,mu' in Optimizer.algorithm_type: try: mark = [ index for index,n in enumerate(nindices) if n > Optimizer.nindiv-1][0] except: mark = Optimizer.nindiv Optimizer.mark = mark pop, str1 = lambdacommamu.lambdacommamu(newpop, Optimizer) STR+=str1 else: pop = selection_switch(newpop, Optimizer.nindiv, Optimizer.natural_selection_scheme, Optimizer) pop = get_best(pop,len(pop)) indiv = pop[0] if (indiv.fitness/indiv.energy <2.0): from MAST.structopt.tools.StemCalc import find_stem_coeff outs = find_stem_coeff(Optimizer,indiv) ind = outs[1] Optimizer.stem_coeff = outs[0] STR+='Readjusting STEM Coeff = {0}'.format(Optimizer.stem_coeff)) return pop, STR
def adapting(pop, Optimizer): """Function to provide an adapting fitness function for GA evaluation Input: pop = population consisting of list of Individual Class objects to be evaluated Optimizer = Optimizer class object with fitness parameters Output: pop = new population updated based on fitness evaluation *** needs work *** """ fitlist = [one.fitness for one in pop] nfitlist, nindices = remove_duplicates(fitlist, Optimizer.demin) STR = '' newpop = [] if len(nfitlist) != len(fitlist): STR += 'Predator: Removed total of ' + repr( len(fitlist) - len(nfitlist)) + ' from population\n' otherlist = [] for i in range(len(pop)): if i not in nindices: STR += 'Predator: Removed ' + repr(pop[i].history_index) + '\n' otherlist.append(pop[i]) else: newpop.append(pop[i]) while len(newpop) < Optimizer.nindiv: Optimizer.output.write('Predator: Adding duplicates back') indiv = random.choice(otherlist) newpop.append(indiv) STR += 'Predator: Adding mutated duplicates to new pop history=' + indiv.history_index + '\n' if Optimizer.natural_selection_scheme == 'fussf': for ind in newpop: if ind.fingerprint == 0: ind.fingerprint = get_fingerprint(Optimizer, ind, Optimizer.fpbin, Optimizer.fpcutoff) if genrep >= Optimizer.reqrep * Optimizer.adaptbegin: ofusslim = Optimizer.fusslimit nfusslim = ofusslim * math.exp(-Optimizer.adaptmultiplier * float( Optimizer.genrep) / float(Optimizer.reqrep)) Optimizer.fusslimit = nfusslim else: ofusslim = Optimizer.fusslimit pop = selection_switch(newpop, Optimizer.nindiv, Optimizer.natural_selection_scheme, Optimizer) pop = get_best(pop, len(pop)) Optimizer.fusslimit = ofusslim return pop, STR
def mutation_dups_zp(pop, Optimizer): """Predator function that selects individuals that are too similar based fitness and replaces them with a zero point rotation of the structure """ fitlist = [one.fitness for one in pop] nfitlist, nindices = remove_duplicates(fitlist, Optimizer.demin) STR = '' newpop = [] if len(nfitlist) != len(fitlist): STR+='Predator: Removed total of '+repr(len(fitlist)-len(nfitlist))+' from population\n' otherlist = [] for i in range(len(pop)): if i not in nindices: STR+='Predator: Removed '+repr(pop[i].history_index)+'\n' otherlist.append(pop[i]) else: newpop.append(pop[i]) while len(newpop) < Optimizer.nindiv: indiv = random.choice(otherlist).duplicate() mutopts = Optimizer.mutation_options Optimizer.mutation_options = ['ZP_Rotation'] indiv = moves_switch(indiv, Optimizer) Optimizer.mutation_options = mutopts newpop.append(indiv) nindices.append(indiv.index) STR+='Predator: Adding mutated duplicates to new pop history='+indiv.history_index+'\n' nindices.sort() if Optimizer.natural_selection_scheme=='FUSSF': for ind in newpop: if ind.fingerprint == 0: ind.fingerprint = get_fingerprint(Optimizer,ind,Optimizer.fpbin,Optimizer.fpcutoff) if 'lambda,mu' in Optimizer.algorithm_type: try: mark = [ index for index,n in enumerate(nindices) if n > Optimizer.nindiv-1][0] except: mark = Optimizer.nindiv Optimizer.mark = mark pop, str1 = lambdacommamu.lambdacommamu(newpop, Optimizer) STR+=str1 else: pop = selection_switch(newpop, Optimizer.nindiv, Optimizer.natural_selection_scheme, Optimizer) pop = get_best(pop,len(pop)) return pop, STR
def mutation_dups_energy(pop, Optimizer): """Predator function that removes duplicates based on energy and replaces with mutations """ fitlist = [one.energy for one in pop] nfitlist, nindices = remove_duplicates(fitlist, Optimizer.demin) STR = '' newpop = [] if len(nfitlist) != len(fitlist): STR+='Predator: Removed total of '+repr(len(fitlist)-len(nfitlist))+' from population\n' otherlist = [] for i in range(len(pop)): if i not in nindices: STR+='Predator: Removed '+repr(pop[i].history_index)+'\n' otherlist.append(pop[i]) else: newpop.append(pop[i]) while len(newpop) < Optimizer.nindiv: indiv = random.choice(otherlist).duplicate() indiv, scheme = moves_switch(indiv,Optimizer) indiv.energy = 1000 indiv.fitness = 1000 newpop.append(indiv) STR+='Predator: Adding mutated duplicates to new pop history='+indiv.history_index+'\n' nindices.append(indiv.index) nindices.sort() if Optimizer.natural_selection_scheme=='fussf': for ind in newpop: if ind.fingerprint == 0: ind.fingerprint = get_fingerprint(Optimizer,ind,Optimizer.fpbin,Optimizer.fpcutoff) if 'lambda,mu' in Optimizer.algorithm_type: try: mark = [ index for index,n in enumerate(nindices) if n > Optimizer.nindiv-1][0] except: mark = Optimizer.nindiv Optimizer.mark = mark pop, str1 = lambdacommamu.lambdacommamu(newpop, Optimizer) STR+=str1 else: pop = selection_switch(newpop, Optimizer.nindiv, Optimizer.natural_selection_scheme, Optimizer) pop = get_best(pop,len(pop)) return pop, STR
def adapting(pop, Optimizer): """Function to provide an adapting fitness function for GA evaluation Input: pop = population consisting of list of Individual Class objects to be evaluated Optimizer = Optimizer class object with fitness parameters Output: pop = new population updated based on fitness evaluation *** needs work *** """ fitlist = [one.fitness for one in pop] nfitlist, nindices = remove_duplicates(fitlist, Optimizer.demin) STR = '' newpop = [] if len(nfitlist) != len(fitlist): STR+='Predator: Removed total of '+repr(len(fitlist)-len(nfitlist))+' from population\n' otherlist = [] for i in range(len(pop)): if i not in nindices: STR+='Predator: Removed '+repr(pop[i].history_index)+'\n' otherlist.append(pop[i]) else: newpop.append(pop[i]) while len(newpop) < Optimizer.nindiv: Optimizer.output.write('Predator: Adding duplicates back') indiv = random.choice(otherlist) newpop.append(indiv) STR+='Predator: Adding mutated duplicates to new pop history='+indiv.history_index+'\n' if Optimizer.natural_selection_scheme=='fussf': for ind in newpop: if ind.fingerprint == 0: ind.fingerprint = get_fingerprint(Optimizer,ind,Optimizer.fpbin,Optimizer.fpcutoff) if genrep >= Optimizer.reqrep*Optimizer.adaptbegin: ofusslim = Optimizer.fusslimit nfusslim = ofusslim*math.exp(-Optimizer.adaptmultiplier*float(Optimizer.genrep)/float(Optimizer.reqrep)) Optimizer.fusslimit = nfusslim else: ofusslim = Optimizer.fusslimit pop = selection_switch(newpop, Optimizer.nindiv,Optimizer.natural_selection_scheme,Optimizer) pop = get_best(pop,len(pop)) Optimizer.fusslimit=ofusslim return pop, STR
def eval_energy(Optimizer, individ): """Function to evaluate energy of an individual Inputs: input = [Optimizer class object with parameters, Individual class structure to be evaluated] Outputs: energy, bul, individ, signal energy = energy of Individual evaluated bul = bulk structure of Individual if simulation structure is Defect individ = Individual class structure evaluated signal = string of information about evaluation """ #logger = initialize_logger(Optimizer.loggername) logger = logging.getLogger(Optimizer.loggername) if 'MAST' in Optimizer.calc_method: energy = individ.energy bul = individ.bulki signal = 'Received MAST structure\n' logger.info( 'Received individual index = {0} from MAST with energy {1}. Returning with no evaluation' .format(individ.index, individ.energy)) else: if Optimizer.parallel: rank = MPI.COMM_WORLD.Get_rank() logger.info( 'Received individual HI = {0} with energy {1} for energy evaluation' .format(individ.history_index, individ.energy)) STR = '----Individual ' + str( individ.history_index) + ' Optimization----\n' indiv = individ[0] if 'EE' in Optimizer.debug: debug = True else: debug = False if debug: write_xyz(Optimizer.debugfile, indiv, 'Received by eval_energy') Optimizer.debugfile.flush() logger.debug('Writing recieved individual to debug file') # Establish individual structure for evaluation. Piece together regions when necessary. if Optimizer.structure == 'Defect': indi = indiv.copy() bulk = individ.bulki nat = indi.get_number_of_atoms() if debug: logger.info( 'Extending defect structure to include bulk len(r1+r2)={0} len(bulk)={1}' .format(nat, len(bulk))) csize = bulk.get_cell() totalsol = Atoms(cell=csize, pbc=True) totalsol.extend(indi) totalsol.extend(bulk) for sym, c, m, u in Optimizer.atomlist: nc = len([atm for atm in totalsol if atm.symbol == sym]) STR += 'Defect configuration contains ' + repr( nc) + ' ' + repr(sym) + ' atoms\n' elif Optimizer.structure == 'Surface': totalsol = Atoms() totalsol.extend(indiv) nat = indiv.get_number_of_atoms() totalsol.extend(individ.bulki) if debug: logger.info( 'Extending surface structure to include bulk len(r1+r2)={0} len(bulk)={1}' .format(nat, len(individ.bulki))) for sym, c, m, u in Optimizer.atomlist: nc = len([atm for atm in totalsol if atm.symbol == sym]) STR += 'Surface-Bulk configuration contains ' + repr( nc) + ' ' + repr(sym) + ' atoms\n' cell = numpy.maximum.reduce(indiv.get_cell()) totalsol.set_cell([cell[0], cell[1], 500]) totalsol.set_pbc([True, True, False]) elif Optimizer.structure == 'Cluster': totalsol = indiv.copy() nat = len(totalsol) if debug: logger.info( 'Extending cluster with {0} atoms to center of evaluation box of size {1}' .format(nat, Optimizer.large_box_size)) origcell = indiv.get_cell() totalsol.set_cell([ Optimizer.large_box_size, Optimizer.large_box_size, Optimizer.large_box_size ]) totalsol.translate([ Optimizer.large_box_size / 2.0, Optimizer.large_box_size / 2.0, Optimizer.large_box_size / 2.0 ]) elif Optimizer.structure == 'Crystal': totalsol = indiv.copy() nat = len(totalsol) else: print 'WARNING: In EvalEnergy. Optimizer.structure not recognized' logger.warning('Optimizer.structure not recognized') # Check for atoms that are too close or out of constrained location if Optimizer.constrain_position: if Optimizer.structure == 'Defect': if debug: logger.info('Constraining positions of defect') totalsol, stro = constrain_positions(totalsol, Optimizer.solidbulk, Optimizer.sf) if debug: logger.info(stro) STR += str0 min_len = 0.7 if not Optimizer.fixed_region: if debug: logger.info('Running check minimum distance') totalsol, STR = check_min_dist(totalsol, Optimizer.structure, nat, min_len, STR) if debug: write_xyz(Optimizer.debugfile, totalsol, 'After minlength check') Optimizer.debugfile.flush() logger.debug( 'Writing individual after checking minimum length') # Set calculator to use to get forces/energies if Optimizer.parallel: calc = setup_calculator(Optimizer) if Optimizer.fixed_region: if debug: logger.info('Setting up fixed region calculator') pms = copy.deepcopy(calc.parameters) try: pms['mass'][ len(pms['mass']) - 1] += '\ngroup RO id >= {0}\nfix freeze RO setforce 0.0 0.0 0.0\n'.format( nat) except KeyError: pms['pair_coeff'][ 0] += '\ngroup RO id >= {0}\nfix freeze RO setforce 0.0 0.0 0.0\n'.format( nat) calc = LAMMPS(parameters=pms, files=calc.files, keep_tmp_files=calc.keep_tmp_files, tmp_dir=calc.tmp_dir) lmin = copy.copy(Optimizer.lammps_min) if debug: logger.info('Setting up no local minimization calculator') Optimizer.lammps_min = None Optimizer.static_calc = setup_calculator(Optimizer) Optimizer.lammps_min = lmin else: calc = Optimizer.calc totalsol.set_calculator(calc) totalsol.set_pbc(True) # Perform Energy Minimization if not Optimizer.parallel: if debug: write_xyz(Optimizer.debugfile, totalsol, 'Individual sent to Energy Minimizer') logger.debug('Writing structure sent to energy minimizer') try: cwd = os.getcwd() if Optimizer.ase_min == True: if debug: logger.info('Running ASE minimizer') if Optimizer.calc_method == 'LennardJones': logger.warn('Must run ase LJ calculator with pbc=False') totalsol.set_pbc(False) totalsol, energy, pressure, volume, STR = run_ase_min( totalsol, Optimizer.ase_min_fmax, Optimizer.ase_min_maxsteps, Optimizer.fitness_scheme, STR) else: if debug: logger.info('Running local energy calculator') if Optimizer.fixed_region: totalsol, energy, pressure, volume, STR = run_energy_eval( totalsol, Optimizer.calc_method, Optimizer.fixed_region, Optimizer.fitness_scheme, STR, Optimizer.static_calc) else: totalsol, energy, pressure, volume, STR = run_energy_eval( totalsol, Optimizer.calc_method, False, Optimizer.fitness_scheme, STR) except Exception, e: logger.critical('Error in energy evaluation: {0}'.format(e), exc_info=True) path = os.path.join(cwd, 'TroubledLammps') if not os.path.exists(path): os.mkdir(path) #Copy files over shutil.copyfile( calc.trajfile, os.path.join(path, os.path.basename(calc.trajfile))) shutil.copyfile(calc.infile, os.path.join(path, os.path.basename(calc.infile))) shutil.copyfile(calc.logfile, os.path.join(path, os.path.basename(calc.logfile))) shutil.copyfile( calc.datafile, os.path.join(path, os.path.basename(calc.datafile))) raise RuntimeError('{0}:{1}'.format(Exception, e)) if not Optimizer.parallel: if debug: write_xyz(Optimizer.debugfile, totalsol, 'Individual after Energy Minimization') Optimizer.debugfile.flush() logger.debug( 'Writing structure recieved from energy minimizer') # Separate structures into distinct pieces if Optimizer.structure == 'Defect': if Optimizer.fixed_region == True or Optimizer.finddefects == False: if debug: logger.info( 'Identifying atoms in defect structure based on ID') individ[0] = totalsol[0:nat] bul = totalsol[(nat):len(totalsol)] individ[0].set_cell(csize) else: if debug: logger.info( 'Applying find defects scheme to identify R1 and R2 for Defect' ) if 'FD' in Optimizer.debug: outt = find_defects(totalsol, Optimizer.solidbulk, Optimizer.sf, atomlistcheck=Optimizer.atomlist, trackvacs=Optimizer.trackvacs, trackswaps=Optimizer.trackswaps, debug=Optimizer.debugfile) else: outt = find_defects(totalsol, Optimizer.solidbulk, Optimizer.sf, atomlistcheck=Optimizer.atomlist, trackvacs=Optimizer.trackvacs, trackswaps=Optimizer.trackswaps, debug=False) individ[0] = outt[0] bul = outt[1] individ.vacancies = outt[2] individ.swaps = outt[3] STR += outt[4] indiv = individ[0] elif Optimizer.structure == 'Surface': if debug: logger.info('Finding surface top layer') top, bul = find_top_layer(totalsol, Optimizer.surftopthick) indiv = top.copy() individ[0] = top.copy() bul = Atoms() elif Optimizer.structure == 'Crystal': if debug: logger.info('Checking crystal cell type') celltype = check_cell_type(totalsol) STR += 'Cell structure = {0}\n'.format(celltype) bul = Atoms() individ[0] = totalsol.copy() elif Optimizer.structure == 'Cluster': volume = get_cluster_volume(totalsol) bul = Atoms() if debug: logger.info( 'Translating cluster back to smaller box size location') totalsol.translate([ -Optimizer.large_box_size / 2.0, -Optimizer.large_box_size / 2.0, -Optimizer.large_box_size / 2.0 ]) totalsol.set_cell(origcell) individ[0] = totalsol.copy() # Add concentration energy dependence if Optimizer.forcing == 'energy_bias': if debug: logger.info( 'Applying energy bias for atoms with different number of atoms of type than in atomlist' ) n = [0] * len(Optimizer.atomlist) for i in range(len(Optimizer.atomlist)): n[i] = len([ inds for inds in totalsol if inds.symbol == Optimizer.atomlist[i][0] ]) n[i] = abs(n[i] - Optimizer.atomlist[i][1]) factor = sum(n)**3 energy = (energy + factor) / totalsol.get_number_of_atoms() STR += 'Energy with Bias = {0}\n'.format(energy) elif Optimizer.forcing == 'chem_pot': if debug: logger.info( 'Applying chemical potential bias for atoms with different number of atoms of type than in atomlist' ) n = [0] * len(Optimizer.atomlist) for i in range(len(Optimizer.atomlist)): n[i] = len([ inds for inds in totalsol if inds.symbol == Optimizer.atomlist[i][0] ]) n[i] = n[i] * Optimizer.atomlist[i][3] factor = sum(n) energy = (energy + factor) / totalsol.get_number_of_atoms() STR += 'Energy with Chemical Potential = {0}\n'.format(energy) individ.energy = energy individ.buli = bul individ.pressure = pressure individ.volume = volume if Optimizer.fingerprinting: if debug: logger.info('Identifying fingerprint of new structure') individ.fingerprint = get_fingerprint(Optimizer, individ, Optimizer.fpbin, Optimizer.fpcutoff) if Optimizer.parallel: calc.clean() signal = 'Evaluated individual {0} on {1}\n'.format( individ.index, rank) signal += STR else: signal = STR
# dist=[10]*len(indiv) # for i in range(len(indiv)): # for j in range(len(indiv)): # if i != j: # dist[j]=indiv.get_distance(i,j,mic=True) # if min(dist) > 3.5: # energy+=10 #if Optimizer.structure=='Defect': # individ.force=force individ.energy = energy individ.buli = bul individ.pressure = pressure individ.volume = volume if Optimizer.structure == 'Cluster': indiv.translate([-250, -250, -250]) if Optimizer.fingerprinting: individ.fingerprint = get_fingerprint(Optimizer, individ, Optimizer.fpbin, Optimizer.fpcutoff) if Optimizer.parallel: calc.clean() signal = 'Evaluated individual ' + repr( individ.index) + ' on ' + repr(rank) + '\n' signal += STR else: signal = STR return energy, bul, individ, signal
def mutation_dups_quench(pop, Optimizer): """Predator function that removes individuals based on fitness and mutates replacements Also quenches top individuals """ fitlist = [one.fitness for one in pop] nfitlist, nindices = remove_duplicates(fitlist, Optimizer.demin) STR = '' newpop = [] if len(nfitlist) != len(fitlist): STR+='Predator: Removed total of '+repr(len(fitlist)-len(nfitlist))+' from population\n' otherlist = [] for i in range(len(pop)): if i not in nindices: STR+='Predator: Removed '+repr(pop[i].history_index)+'\n' otherlist.append(pop[i]) else: newpop.append(pop[i]) while len(newpop) < Optimizer.nindiv: indiv = random.choice(otherlist).duplicate() indiv, scheme = moves_switch(indiv,Optimizer) indiv.energy = 1000 indiv.fitness = 1000 newpop.append(indiv) STR+='Predator: Adding mutated duplicates to new pop history='+indiv.history_index+'\n' nindices.append(indiv.index) nindices.sort() if Optimizer.natural_selection_scheme=='fussf': for ind in newpop: if ind.fingerprint == 0: ind.fingerprint = get_fingerprint(Optimizer,ind,Optimizer.fpbin,Optimizer.fpcutoff) if 'lambda,mu' in Optimizer.algorithm_type: try: mark = [ index for index,n in enumerate(nindices) if n > Optimizer.nindiv-1][0] except: mark = Optimizer.nindiv Optimizer.mark = mark pop, str1 = lambdacommamu.lambdacommamu(newpop, Optimizer) STR+=str1 else: pop = selection_switch(newpop, Optimizer.nindiv, Optimizer.natural_selection_scheme, Optimizer) pop = get_best(pop,len(pop)) if Optimizer.genrep >10: from MAST.structopt.moves.quench import quench import os olammpsvar = os.environ['LAMMPS_COMMAND'] try: from mpi4py import MPI if '-n' in olammpsvar: lcommand = olammpsvar.split('-n') lcommand[1]=lcommand[1].split() nproc = MPI.COMM_WORLD.Get_size() os.environ['LAMMPS_COMMAND'] = '{0}-n {1} {2}'.format(lcommand[0],nproc,lcommand[1][1]) except: pass oqns2 = Optimizer.quench_n_steps_2 Optimizer.quench_n_steps_2 = 100000 opar = Optimizer.parallel Optimizer.parallel = False for i in range(3): pop[i] = quench(pop[i],Optimizer) Optimizer.quench_n_steps_2 = oqns2 os.environ['LAMMPS_COMMAND'] = olammpsvar Optimizer.parallel = opar return pop, STR
def eval_energy(Optimizer, individ): """Function to evaluate energy of an individual Inputs: input = [Optimizer class object with parameters, Individual class structure to be evaluated] Outputs: energy, bul, individ, signal energy = energy of Individual evaluated bul = bulk structure of Individual if simulation structure is Defect individ = Individual class structure evaluated signal = string of information about evaluation """ #logger = initialize_logger(Optimizer.loggername) logger = logging.getLogger(Optimizer.loggername) if 'MAST' in Optimizer.calc_method: energy = individ.energy bul = individ.bulki signal = 'Received MAST structure\n' logger.info('Received individual index = {0} from MAST with energy {1}. Returning with no evaluation'.format( individ.index, individ.energy)) else: if Optimizer.parallel: rank = MPI.COMM_WORLD.Get_rank() logger.info('Received individual HI = {0} with energy {1} for energy evaluation'.format( individ.history_index, individ.energy)) STR='----Individual ' + str(individ.history_index)+ ' Optimization----\n' indiv=individ[0] if 'EE' in Optimizer.debug: debug = True else: debug = False if debug: write_xyz(Optimizer.debugfile,indiv,'Received by eval_energy') Optimizer.debugfile.flush() logger.debug('Writing recieved individual to debug file') # Establish individual structure for evaluation. Piece together regions when necessary. if Optimizer.structure=='Defect': indi=indiv.copy() bulk=individ.bulki nat=indi.get_number_of_atoms() if debug: logger.info('Extending defect structure to include bulk len(r1+r2)={0} len(bulk)={1}'.format(nat,len(bulk))) csize=bulk.get_cell() totalsol=Atoms(cell=csize, pbc=True) totalsol.extend(indi) totalsol.extend(bulk) for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in totalsol if atm.symbol==sym]) STR+='Defect configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n' elif Optimizer.structure=='Surface': totalsol=Atoms() totalsol.extend(indiv) nat=indiv.get_number_of_atoms() totalsol.extend(individ.bulki) if debug: logger.info('Extending surface structure to include bulk len(r1+r2)={0} len(bulk)={1}'.format(nat,len(individ.bulki))) for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in totalsol if atm.symbol==sym]) STR+='Surface-Bulk configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n' cell=numpy.maximum.reduce(indiv.get_cell()) totalsol.set_cell([cell[0],cell[1],500]) totalsol.set_pbc([True,True,False]) elif Optimizer.structure=='Cluster': totalsol = indiv.copy() nat = len(totalsol) if debug: logger.info('Extending cluster with {0} atoms to center of evaluation box of size {1}'.format(nat,Optimizer.large_box_size)) origcell = indiv.get_cell() totalsol.set_cell([Optimizer.large_box_size,Optimizer.large_box_size,Optimizer.large_box_size]) totalsol.translate([Optimizer.large_box_size/2.0,Optimizer.large_box_size/2.0,Optimizer.large_box_size/2.0]) elif Optimizer.structure=='Crystal': totalsol = indiv.copy() nat = len(totalsol) else: print 'WARNING: In EvalEnergy. Optimizer.structure not recognized' logger.warning('Optimizer.structure not recognized') # Check for atoms that are too close or out of constrained location if Optimizer.constrain_position: if Optimizer.structure=='Defect': if debug: logger.info('Constraining positions of defect') totalsol, stro = constrain_positions(totalsol, Optimizer.solidbulk, Optimizer.sf) if debug: logger.info(stro) STR+=str0 min_len=0.7 if not Optimizer.fixed_region: if debug: logger.info('Running check minimum distance') totalsol, STR = check_min_dist(totalsol, Optimizer.structure, nat, min_len, STR) if debug: write_xyz(Optimizer.debugfile,totalsol,'After minlength check') Optimizer.debugfile.flush() logger.debug('Writing individual after checking minimum length') # Set calculator to use to get forces/energies if Optimizer.parallel: calc = setup_calculator(Optimizer) if Optimizer.fixed_region: if debug: logger.info('Setting up fixed region calculator') pms=copy.deepcopy(calc.parameters) try: pms['mass'][len(pms['mass'])-1] += '\ngroup RO id >= {0}\nfix freeze RO setforce 0.0 0.0 0.0\n'.format(nat) except KeyError: pms['pair_coeff'][0] += '\ngroup RO id >= {0}\nfix freeze RO setforce 0.0 0.0 0.0\n'.format(nat) calc = LAMMPS(parameters=pms, files=calc.files, keep_tmp_files=calc.keep_tmp_files, tmp_dir=calc.tmp_dir) lmin = copy.copy(Optimizer.lammps_min) if debug: logger.info('Setting up no local minimization calculator') Optimizer.lammps_min = None Optimizer.static_calc = setup_calculator(Optimizer) Optimizer.lammps_min = lmin else: calc=Optimizer.calc totalsol.set_calculator(calc) totalsol.set_pbc(True) # Perform Energy Minimization if not Optimizer.parallel: if debug: write_xyz(Optimizer.debugfile,totalsol,'Individual sent to Energy Minimizer') logger.debug('Writing structure sent to energy minimizer') try: cwd = os.getcwd() if Optimizer.ase_min == True: if debug: logger.info('Running ASE minimizer') if Optimizer.calc_method=='LennardJones': logger.warn('Must run ase LJ calculator with pbc=False') totalsol.set_pbc(False) totalsol, energy, pressure, volume, STR = run_ase_min(totalsol, Optimizer.ase_min_fmax, Optimizer.ase_min_maxsteps, Optimizer.fitness_scheme, STR) else: if debug: logger.info('Running local energy calculator') if Optimizer.fixed_region: totalsol, energy, pressure, volume, STR = run_energy_eval(totalsol, Optimizer.calc_method, Optimizer.fixed_region, Optimizer.fitness_scheme, STR, Optimizer.static_calc) else: totalsol, energy, pressure, volume, STR = run_energy_eval(totalsol, Optimizer.calc_method, False, Optimizer.fitness_scheme, STR) except Exception, e: logger.critical('Error in energy evaluation: {0}'.format(e), exc_info=True) path = os.path.join(cwd,'TroubledLammps') if not os.path.exists(path): os.mkdir(path) #Copy files over shutil.copyfile(calc.trajfile,os.path.join(path,os.path.basename(calc.trajfile))) shutil.copyfile(calc.infile,os.path.join(path,os.path.basename(calc.infile))) shutil.copyfile(calc.logfile,os.path.join(path,os.path.basename(calc.logfile))) shutil.copyfile(calc.datafile,os.path.join(path,os.path.basename(calc.datafile))) raise RuntimeError('{0}:{1}'.format(Exception,e)) if not Optimizer.parallel: if debug: write_xyz(Optimizer.debugfile,totalsol,'Individual after Energy Minimization') Optimizer.debugfile.flush() logger.debug('Writing structure recieved from energy minimizer') # Separate structures into distinct pieces if Optimizer.structure=='Defect': if Optimizer.fixed_region==True or Optimizer.finddefects==False: if debug: logger.info('Identifying atoms in defect structure based on ID') individ[0]=totalsol[0:nat] bul=totalsol[(nat):len(totalsol)] individ[0].set_cell(csize) else: if debug: logger.info('Applying find defects scheme to identify R1 and R2 for Defect') if 'FD' in Optimizer.debug: outt=find_defects(totalsol,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=Optimizer.debugfile) else: outt=find_defects(totalsol,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=False) individ[0]=outt[0] bul=outt[1] individ.vacancies = outt[2] individ.swaps = outt[3] STR += outt[4] indiv=individ[0] elif Optimizer.structure=='Surface': if debug: logger.info('Finding surface top layer') top,bul=find_top_layer(totalsol,Optimizer.surftopthick) indiv=top.copy() individ[0]=top.copy() bul = Atoms() elif Optimizer.structure=='Crystal': if debug: logger.info('Checking crystal cell type') celltype = check_cell_type(totalsol) STR+='Cell structure = {0}\n'.format(celltype) bul = Atoms() individ[0] = totalsol.copy() elif Optimizer.structure=='Cluster': volume = get_cluster_volume(totalsol) bul = Atoms() if debug: logger.info('Translating cluster back to smaller box size location') totalsol.translate([-Optimizer.large_box_size/2.0,-Optimizer.large_box_size/2.0,-Optimizer.large_box_size/2.0]) totalsol.set_cell(origcell) individ[0] = totalsol.copy() # Add concentration energy dependence if Optimizer.forcing=='energy_bias': if debug: logger.info('Applying energy bias for atoms with different number of atoms of type than in atomlist') n=[0]*len(Optimizer.atomlist) for i in range(len(Optimizer.atomlist)): n[i]=len([inds for inds in totalsol if inds.symbol==Optimizer.atomlist[i][0]]) n[i]=abs(n[i]-Optimizer.atomlist[i][1]) factor=sum(n)**3 energy=(energy+factor)/totalsol.get_number_of_atoms() STR+='Energy with Bias = {0}\n'.format(energy) elif Optimizer.forcing=='chem_pot': if debug: logger.info('Applying chemical potential bias for atoms with different number of atoms of type than in atomlist') n=[0]*len(Optimizer.atomlist) for i in range(len(Optimizer.atomlist)): n[i]=len([inds for inds in totalsol if inds.symbol==Optimizer.atomlist[i][0]]) n[i]=n[i]*Optimizer.atomlist[i][3] factor=sum(n) energy=(energy+factor)/totalsol.get_number_of_atoms() STR+='Energy with Chemical Potential = {0}\n'.format(energy) individ.energy=energy individ.buli=bul individ.pressure=pressure individ.volume=volume if Optimizer.fingerprinting: if debug: logger.info('Identifying fingerprint of new structure') individ.fingerprint=get_fingerprint(Optimizer,individ,Optimizer.fpbin,Optimizer.fpcutoff) if Optimizer.parallel: calc.clean() signal = 'Evaluated individual {0} on {1}\n'.format(individ.index,rank) signal +=STR else: signal=STR
# Add explosion prevention protection # if 'prevent_explosions' in globals(): # dist=[10]*len(indiv) # for i in range(len(indiv)): # for j in range(len(indiv)): # if i != j: # dist[j]=indiv.get_distance(i,j,mic=True) # if min(dist) > 3.5: # energy+=10 #if Optimizer.structure=='Defect': # individ.force=force individ.energy=energy individ.buli=bul individ.pressure=pressure individ.volume=volume if Optimizer.structure=='Cluster': indiv.translate([-250,-250,-250]) if Optimizer.fingerprinting: individ.fingerprint=get_fingerprint(Optimizer,individ,Optimizer.fpbin,Optimizer.fpcutoff) if Optimizer.parallel: calc.clean() signal = 'Evaluated individual '+repr(individ.index)+' on '+repr(rank)+'\n' signal +=STR else: signal=STR return energy, bul, individ, signal
def mutation_dups_quench(pop, Optimizer): """Predator function that removes individuals based on fitness and mutates replacements Also quenches top individuals """ fitlist = [one.fitness for one in pop] nfitlist, nindices = remove_duplicates(fitlist, Optimizer.demin) STR = '' newpop = [] if len(nfitlist) != len(fitlist): STR += 'Predator: Removed total of ' + repr( len(fitlist) - len(nfitlist)) + ' from population\n' otherlist = [] for i in range(len(pop)): if i not in nindices: STR += 'Predator: Removed ' + repr(pop[i].history_index) + '\n' otherlist.append(pop[i]) else: newpop.append(pop[i]) while len(newpop) < Optimizer.nindiv: indiv = random.choice(otherlist).duplicate() indiv, scheme = moves_switch(indiv, Optimizer) indiv.energy = 1000 indiv.fitness = 1000 newpop.append(indiv) STR += 'Predator: Adding mutated duplicates to new pop history=' + indiv.history_index + '\n' nindices.append(indiv.index) nindices.sort() if Optimizer.natural_selection_scheme == 'fussf': for ind in newpop: if ind.fingerprint == 0: ind.fingerprint = get_fingerprint(Optimizer, ind, Optimizer.fpbin, Optimizer.fpcutoff) if 'lambda,mu' in Optimizer.algorithm_type: try: mark = [ index for index, n in enumerate(nindices) if n > Optimizer.nindiv - 1 ][0] except: mark = Optimizer.nindiv Optimizer.mark = mark pop, str1 = lambdacommamu.lambdacommamu(newpop, Optimizer) STR += str1 else: pop = selection_switch(newpop, Optimizer.nindiv, Optimizer.natural_selection_scheme, Optimizer) pop = get_best(pop, len(pop)) if Optimizer.genrep > 10: from MAST.structopt.moves.quench import quench import os olammpsvar = os.environ['LAMMPS_COMMAND'] try: from mpi4py import MPI if '-n' in olammpsvar: lcommand = olammpsvar.split('-n') lcommand[1] = lcommand[1].split() nproc = MPI.COMM_WORLD.Get_size() os.environ['LAMMPS_COMMAND'] = '{0}-n {1} {2}'.format( lcommand[0], nproc, lcommand[1][1]) except: pass oqns2 = Optimizer.quench_n_steps_2 Optimizer.quench_n_steps_2 = 100000 opar = Optimizer.parallel Optimizer.parallel = False for i in range(3): pop[i] = quench(pop[i], Optimizer) Optimizer.quench_n_steps_2 = oqns2 os.environ['LAMMPS_COMMAND'] = olammpsvar Optimizer.parallel = opar return pop, STR