def update_structfile(ind, structfile, Optimizer): if Optimizer.structure == 'Defect' or Optimizer.structure == 'Surface': sols = Atoms() sols.extend(ind[0]) sols.extend(ind.bulki) elif Optimizer.structure == 'Crystal': sols = ind[0].repeat((3,3,3)) else: sols = ind[0].copy() positions = sols.get_positions() if Optimizer.vacancy_output: for one in ind.vacancies: sols.append(Atom(symbol='X',position=one.position)) #Optimizer.output.write('Number of positions = {0}\n'.format(len(positions))) write_xyz(structfile, sols, ind.energy) return positions
def stem_cost(indiv, Optimizer): '''Function to calculate STEM_Cost fitness of individual. Input: indiv = structopt Individual class object to be evaluated Optimizer = structopt Optimizer class object Must have STEM Calc function attached Output: indiv = structopt Individual class object with new fitness. ''' #logger = initialize_logger(Optimizer.loggername) logger = logging.getLogger(Optimizer.loggername) starting = indiv.duplicate() cwd = os.getcwd() try: outs = eval_energy(Optimizer,indiv) except Exception, e: logger.warn('Error in energy evaluation: {0}'.format(e), exc_info=True) stro = 'ERROR: Problem in Energy Evaluation' print stro print e stro += '\n' + repr(e) os.chdir(cwd) f=open('problem-structures.xyz','a') totalsol = indiv[0].copy() totalsol.extend(indiv.bulki) write_xyz(f,totalsol,data='Starting structure hindex={0}'.format(indiv.history_index)) 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]
def write_pop(Optimizer,pop): """ Function to write the data from a given population. Inputs: Optimizer = structopt Optimizer class object with output file data pop = List of structopt Individual class objects with data to be written Outputs: None. Data is written to output files provided by Optimizer class object """ Optimizer.output.write('\n--New Population--\n') #Write structures for ind in pop: update_outfile(ind, Optimizer.output) if Optimizer.genealogy: update_genealogy(ind, Optimizer.Genealogyfile) if Optimizer.swaplist: swaplist_check(ind,Optimizer.structure,Optimizer.output) if Optimizer.indiv_defect_write: write_xyz(Optimizer.ifiles[ind.index],ind[0],ind.energy) update_structsumfile(ind, Optimizer.files[Optimizer.nindiv]) if Optimizer.generation % 10 == 0: positions = update_structfile(ind, Optimizer.files[ind.index], Optimizer) Optimizer.output.write('Number of positions = {0}\n'.format(len(positions))) if Optimizer.genealogy: Optimizer.Genealogyfile.write('\n') return
def surfaceenergy(indiv, Optimizer): '''Function to calculate surface energy fitness of individual. Input: indiv = structopt Individual class object to be evaluated Optimizer = structopt Optimizer class object Output: indiv = structopt Individual class object with new fitness. ''' logger = logging.getLogger(Optimizer.loggername) #logger = initialize_logger(Optimizer.loggername) starting = indiv.duplicate() cwd = os.getcwd() try: outs = eval_energy(Optimizer, indiv) except Exception, e: logger.warn('Error in energy evaluation: {0}'.format(e), exc_info=True) stro = 'ERROR: Problem in Energy Evaluation' print stro print e stro += '\n' + repr(e) os.chdir(cwd) f = open('problem-structures.xyz', 'a') totalsol = indiv[0].copy() totalsol.extend(indiv.bulki) write_xyz(f, totalsol, data='Starting structure hindex={0}'.format( indiv.history_index)) 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]
def crossover_switch(child1, child2, Optimizer): """Functions for selecting and pairing individuals for crossovers""" #logger = initialize_logger(Optimizer.loggername) logger = logging.getLogger(Optimizer.loggername) if 'CX' in Optimizer.debug: debug = True else: debug = False if debug: s1 = child1[0].copy() s2 = child2[0].copy() if Optimizer.structure == 'Defect': s1.extend(child1.bulki.copy()) s2.extend(child2.bulki.copy()) write_xyz(Optimizer.debugfile, s1, 'First Cx Individual - Pre ') write_xyz(Optimizer.debugfile, s2, 'Second Cx Individual - Pre') passflag = True scheme = Optimizer.cx_scheme try: exec "from MAST.structopt.crossover.{0} import {0}".format(scheme) nchild1, nchild2 = eval( '{0}(child1, child2, Optimizer)'.format(scheme)) except NameError, e: logger.warning( 'Specified Crossover not one of the available options. Please check documentation and spelling! Crossover : {0}. {1}' .format(Optimizer.cx_scheme, e), exc_info=True) print 'Name Error:', e passflag = False
def enpafit(indiv,Optimizer): """Fitness function to evaluate the energy per atom of an individual structure. Inputs: indiv = Individual class object to be evaluated Optimizer = Optimizer class object with needed parameters Outputs: indiv = Evaluated Individual class object """ #logger = initialize_logger(Optimizer.loggername) logger = logging.getLogger(Optimizer.loggername) starting = indiv.duplicate() cwd = os.getcwd() try: outs = eval_energy(Optimizer,indiv) except Exception, e: logger.warn('Error in energy evaluation: {0}'.format(e), exc_info=True) stro = 'ERROR: Problem in Energy Evaluation' print stro print e stro += '\n' + repr(e) os.chdir(cwd) f=open('problem-structures.xyz','a') totalsol = indiv[0].copy() totalsol.extend(indiv.bulki) write_xyz(f,totalsol,data='Starting structure hindex={0}'.format(indiv.history_index)) 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]
def enthalpyfit(indiv, Optimizer): """Fitness function to evaluate the enthalpy of an individual structure. Inputs: indiv = Individual class object to be evaluated Optimizer = Optimizer class object with needed parameters Outputs: indiv = Evaluated Individual class object """ #logger = initialize_logger(Optimizer.loggername) logger = logging.getLogger(Optimizer.loggername) starting = indiv.duplicate() cwd = os.getcwd() try: outs = eval_energy(Optimizer, indiv) passflag = True except Exception, e: logger.warn('Error in energy evaluation: {0}'.format(e), exc_info=True) stro = 'ERROR: Problem in Energy Evaluation' print stro print e stro += '\n' + repr(e) os.chdir(cwd) f = open('problem-structures.xyz', 'a') totalsol = indiv[0].copy() totalsol.extend(indiv.bulki) write_xyz(f, totalsol, data='Starting structure hindex={0}'.format( indiv.history_index)) 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] passflag = False
def crossover_switch(child1, child2, Optimizer): """Functions for selecting and pairing individuals for crossovers""" # logger = initialize_logger(Optimizer.loggername) logger = logging.getLogger(Optimizer.loggername) if "CX" in Optimizer.debug: debug = True else: debug = False if debug: s1 = child1[0].copy() s2 = child2[0].copy() if Optimizer.structure == "Defect": s1.extend(child1.bulki.copy()) s2.extend(child2.bulki.copy()) write_xyz(Optimizer.debugfile, s1, "First Cx Individual - Pre ") write_xyz(Optimizer.debugfile, s2, "Second Cx Individual - Pre") passflag = True scheme = Optimizer.cx_scheme try: exec "from MAST.structopt.crossover.{0} import {0}".format(scheme) nchild1, nchild2 = eval("{0}(child1, child2, Optimizer)".format(scheme)) except NameError, e: logger.warning( "Specified Crossover not one of the available options. Please check documentation and spelling! Crossover : {0}. {1}".format( Optimizer.cx_scheme, e ), exc_info=True, ) print "Name Error:", e passflag = False
def write_pop(Optimizer, pop): """ Function to write the data from a given population. Inputs: Optimizer = structopt Optimizer class object with output file data pop = List of structopt Individual class objects with data to be written Outputs: None. Data is written to output files provided by Optimizer class object """ Optimizer.output.write('\n--New Population--\n') #Write structures for ind in pop: update_outfile(ind, Optimizer.output) if Optimizer.genealogy: update_genealogy(ind, Optimizer.Genealogyfile) if Optimizer.swaplist: swaplist_check(ind, Optimizer.structure, Optimizer.output) if Optimizer.indiv_defect_write: write_xyz(Optimizer.ifiles[ind.index], ind[0], ind.energy) update_structsumfile(ind, Optimizer.files[Optimizer.nindiv]) positions = update_structfile(ind, Optimizer.files[ind.index], Optimizer) Optimizer.output.write('Number of positions = {0}\n'.format( len(positions))) if Optimizer.genealogy: Optimizer.Genealogyfile.write('\n') return
def update_structfile(ind, structfile, Optimizer): if Optimizer.structure == 'Defect' or Optimizer.structure == 'Surface': sols = Atoms() sols.extend(ind[0]) sols.extend(ind.bulki) elif Optimizer.structure == 'Crystal': sols = ind[0].repeat((3, 3, 3)) else: sols = ind[0].copy() positions = sols.get_positions() if Optimizer.vacancy_output: for one in ind.vacancies: sols.append(Atom(symbol='X', position=one.position)) Optimizer.output.write('Number of positions = {0}\n'.format( len(positions))) write_xyz(structfile, sols, ind.energy) return positions
def write_individual(individ, indivfile): """Function to write the data of an individual class object to a flat file Input: individ = Individual class object to be written indivfile = String or fileobject for file to be written to Output: No output returned. Information is written to file """ if isinstance(indivfile, str): indivfile=open(indivfile, 'a') #Write break indivfile.write('----------\n') #Write structure information indivfile.write('Structure information\n') write_xyz(indivfile, individ[0]) indivfile.write('structure cell = {0}\n'.format(get_atom_cell(individ[0]))) #Write additional information indivfile.write('fitness = {0}\n'.format(individ.fitness)) indivfile.write('index = {0}\n'.format(individ.index)) indivfile.write('history_index = {0}\n'.format(individ.index)) indivfile.write('energy = {0}\n'.format(individ.energy)) indivfile.write('tenergymx = {0}\n'.format(individ.tenergymx)) indivfile.write('tenergymin = {0}\n'.format(individ.tenergymin)) indivfile.write('pressure = {0}\n'.format(individ.pressure)) indivfile.write('volume = {0}\n'.format(individ.volume)) indivfile.write('force = {0}\n'.format(individ.force)) indivfile.write('purebulkenpa = {0}\n'.format(individ.purebulkenpa)) indivfile.write('natomsbulk = {0}\n'.format(individ.natomsbulk)) indivfile.write('fingerprint = {0}\n'.format(individ.fingerprint)) indivfile.write('swaplist = {0}\n'.format(individ.swaplist)) #Write additional structure information indivfile.write('bulki\n') write_xyz(indivfile, individ.bulki) indivfile.write('bulki cell = {0}\n'.format(get_atom_cell(individ.bulki))) indivfile.write('bulko\n') write_xyz(indivfile, individ.bulko) indivfile.write('bulko cell = {0}\n'.format(get_atom_cell(individ.bulko))) indivfile.write('box\n') write_xyz(indivfile, individ.box) indivfile.write('box cell = {0}\n'.format(get_atom_cell(individ.box))) indivfile.write('vacancies\n') write_xyz(indivfile, individ.vacancies) indivfile.write('vacancies cell = {0}\n'.format(get_atom_cell(individ.vacancies))) indivfile.write('swaps\n') write_xyz(indivfile, individ.swaps) indivfile.write('swaps cell = {0}\n'.format(get_atom_cell(individ.swaps))) indivfile.write('Finish') indivfile.close() return
'Error attempting to load back up cxTP Crossover. Something very wrong!! {1}' .format(e), exc_info=True) print 'CXTP Name Error: ', e except Exception, e: logger.error('Error in cxtp Crossover {0}'.format(e), exc_info=True) print 'Exception: ', e if passflag: child1 = nchild1 child2 = nchild2 child1.energy = 0 child2.energy = 0 child1.fitness = 0 child2.fitness = 0 ch1hi = child1.history_index child1.history_index = '(' + repr(child1.index) + '+' + repr( child2.index) + ')' child2.history_index = '(' + repr(child2.index) + '+' + repr( child1.index) + ')' if debug: s1 = child1[0].copy() s2 = child2[0].copy() if Optimizer.structure == 'Defect': s1.extend(child1.bulki.copy()) s2.extend(child2.bulki.copy()) write_xyz(Optimizer.debugfile, s1, 'First Cx Individual - Post') write_xyz(Optimizer.debugfile, s2, 'Second Cx Individual - Post') return child1, child2
# Set up calculator parcoff = '* * SiC.edip C Si' pair_coeff = [parcoff] mass = ['1 12.011','2 28.0855'] parameters = { 'pair_style' : 'edip', 'pair_coeff' : pair_coeff , 'mass' : mass, 'newton': 'on' } mincomd = '1e-8 1e-8 5000 10000' parameters['minimize'] = mincomd filesL = [ 'SiC.edip' ] calc = LAMMPS(parameters=parameters, files=filesL) # Read File structure = read_xyz('indiv00.xyz',-1) # Calculate Energy structure.set_cell([13.092,13.092,13.092]) structure.set_pbc(True) structure.set_calculator(calc) OUT=structure.calc.calculate(structure) totalsol=OUT['atoms'] totalsol.set_pbc(True) en=OUT['thermo'][-1]['pe'] #Write Relaxed Structure write_xyz('re-relaxed.xyz',totalsol,repr(en)) fe = en for sym,u in [('C',-7.371),('Si',-5.3062)]: nc=len([atm for atm in structure if atm.symbol==sym]) fe-= float(nc)*float(u) print 'SiC Interstitial' print ' Potential Energy = '+repr(en) print ' Formation Energy = '+repr(fe)
nchild1, nchild2 = cxtp(child1, child2, Optimizer) passflag = True except NameError, e: logger.error( "Error attempting to load back up cxTP Crossover. Something very wrong!! {1}".format(e), exc_info=True ) print "CXTP Name Error: ", e except Exception, e: logger.error("Error in cxtp Crossover {0}".format(e), exc_info=True) print "Exception: ", e if passflag: child1 = nchild1 child2 = nchild2 child1.energy = 0 child2.energy = 0 child1.fitness = 0 child2.fitness = 0 ch1hi = child1.history_index child1.history_index = "(" + repr(child1.index) + "+" + repr(child2.index) + ")" child2.history_index = "(" + repr(child2.index) + "+" + repr(child1.index) + ")" if debug: s1 = child1[0].copy() s2 = child2[0].copy() if Optimizer.structure == "Defect": s1.extend(child1.bulki.copy()) s2.extend(child2.bulki.copy()) write_xyz(Optimizer.debugfile, s1, "First Cx Individual - Post") write_xyz(Optimizer.debugfile, s2, "Second Cx Individual - Post") return child1, child2
'pair_style': 'edip', 'pair_coeff': pair_coeff, 'mass': mass, 'newton': 'on' } mincomd = '1e-8 1e-8 5000 10000' parameters['minimize'] = mincomd filesL = ['SiC.edip'] calc = LAMMPS(parameters=parameters, files=filesL) # Read File structure = read_xyz('indiv00.xyz', -1) # Calculate Energy structure.set_cell([13.092, 13.092, 13.092]) structure.set_pbc(True) structure.set_calculator(calc) OUT = structure.calc.calculate(structure) totalsol = OUT['atoms'] totalsol.set_pbc(True) en = OUT['thermo'][-1]['pe'] #Write Relaxed Structure write_xyz('re-relaxed.xyz', totalsol, repr(en)) fe = en for sym, u in [('C', -7.371), ('Si', -5.3062)]: nc = len([atm for atm in structure if atm.symbol == sym]) fe -= float(nc) * float(u) print 'SiC Interstitial' print ' Potential Energy = ' + repr(en) print ' Formation Energy = ' + repr(fe)
def find_defects(solid, bulko, rcutoff, atomlistcheck=False, trackvacs=False, trackswaps=False, debug=False, dcheck=0.6): """Function to find interstitials, vacancies, and substitutional atoms (swaps) in a defected structure. Identifies species by comparison to perfect structure. Inputs: solid = ASE atoms class for defected structure bulko = ASE atoms class for perfect structure rcutoff = float value of distance to surrounding atoms to include atomlistcheck = False/list of atom types and concentrations according to atomlist format trackvacs = True/False whether or not to identify vacancies in defect trackswaps = True/False whether or not to identify substitutional defects debug = False/file object to write debug structures""" # Combine perfect and defect structures together b = bulko.copy() b.extend(solid) b.set_pbc(True) #Debug: Write solid and bulko to file if debug: print len(bulko) write_xyz(debug, b, 'Find Ints: Solid and Bulko') # Identify nearest neighbor atoms for each atom in perfect structure ntot = len(bulko) ctoff1 = [1.2 for one in b] nl = NeighborList(ctoff1, bothways=True, self_interaction=False) nl.update(b) slist = [] blist = [] wlist = [] #Loop over each atom in perfect structure for one in range(ntot): indices, offsets = nl.get_neighbors(one) for index, d in zip(indices, offsets): index = int(index) if index >= ntot: pos = b[index].position + numpy.dot(d, bulko.get_cell()) natm1 = Atom(position=pos) dist, dx, dy, dz = calc_dist(b[one], natm1) if dist <= dcheck: #Assume atoms closer than 0.6 Angstroms to be equivalent slist.append(index - ntot) blist.append(one) if b[one].symbol == b[index].symbol: wlist.append(index - ntot) #Identify those atoms corresponding to interstitials, vacancies, and substitutions oslist = [atm.index for atm in solid if atm.index not in slist] vlist = [atm.index for atm in bulko if atm.index not in blist] swlist = [ atm.index for atm in solid if atm.index not in wlist and atm.index not in oslist ] # Create Atoms objects for each identified defect ntot = len(solid) cluster = Atoms() for one in oslist: cluster.append(solid[one]) vacant = Atoms() if trackvacs == True: for one in vlist: vacant.append( Atom(symbol=bulko[one].symbol, position=bulko[one].position)) solid.append(Atom(symbol='X', position=bulko[one].position)) oslist.append(len(solid) - 1) stro = 'Cluster Identified with length = {0}\nIdentified {1} vacancies\n'.format( len(cluster), len(vlist)) swaps = Atoms() if trackswaps == True: for one in swlist: swaps.append(solid[one]) oslist.append(one) stro = 'Cluster Identified with length = {0}\nIdentified {1} swaps\n'.format( len(cluster), len(swlist)) else: stro = 'Cluster Identified with length = {0}\n'.format(len(cluster)) #Debug: write cluster to file if debug: b = cluster.copy() write_xyz(debug, b, 'Find Ints: Cluster') debug.flush() print 'Found cluster size = ', len(b) # Identify atoms surrounding the identified defects in the defected structure box = Atoms() bulki = Atoms() if rcutoff != 0: if rcutoff > 2.0: cutoffs = [rcutoff for one in solid] else: cutoffs = [2.0 for one in solid] solid.set_pbc(True) nl = NeighborList(cutoffs, bothways=True, self_interaction=False) nl.update(solid) nbatmsd = [] repinds = [] for one in oslist: if one not in repinds: if one < ntot: nbatmsd.append((0, one)) repinds.append(one) for one in oslist: indices, offsets = nl.get_neighbors(one) for index, d in zip(indices, offsets): index = int(index) if index not in repinds and index < ntot: opos = copy.copy(solid[index].position) solid[index].position = solid[index].position + numpy.dot( d, solid.get_cell()) dist = solid.get_distance(one, index) solid[index].position = opos if dist <= rcutoff: nbatmsd.append((dist, index)) repinds.append(index) else: nbatmsd = [] repinds = [] for one in oslist: if one not in repinds: if one < ntot: nbatmsd.append((0, one)) repinds.append(one) nbatmsd = sorted(nbatmsd, key=lambda one: one[0], reverse=True) indices = [] natomsbox = 0 # Select only atoms closest to defects that satisfy concentrations specified by atomlist given in atomlistcheck if atomlistcheck: for sym, c, m, u in atomlistcheck: i = 0 nbsym = [one for one in nbatmsd if solid[one[1]].symbol == sym] if len(nbsym) > c: while i < c: a = nbsym.pop() box.append(solid[a[1]]) indices.append(a[1]) i += 1 else: for a in nbsym: box.append(solid[a[1]]) indices.append(a[1]) i += 1 if len(box) - natomsbox < c: try: while True: for n in range(len(nbatmsd) - 1, -1, -1): inds, offsets = nl.get_neighbors(nbatmsd[n][1]) for one, d in zip(inds, offsets): if len(box) - natomsbox < c: if one not in indices and one < ntot and solid[ one].symbol == sym: opos = copy.copy( solid[one].position) solid[one].position = solid[ one].position + numpy.dot( d, solid.get_cell()) dist = solid.get_distance( nbatmsd[n][1], one) solid[one].position = opos if dist <= rcutoff * 5.0: box.append(solid[one]) indices.append(one) else: raise StopIteration() for one, d in zip(inds, offsets): if len(box) - natomsbox < c: if one not in indices and one < ntot and solid[ one].symbol == sym: opos = copy.copy( solid[one].position) solid[one].position = solid[ one].position + numpy.dot( d, solid.get_cell()) dist = solid.get_distance( nbatmsd[n][1], one) solid[one].position = opos box.append(solid[one]) indices.append(one) else: raise StopIteration() except StopIteration: pass natomsbox = len(box) #Double check for sanity for sym, c, m, u in atomlistcheck: symsbox = [one for one in box if one.symbol == sym] if len(symsbox) != c: stro += 'WARNING!!!! : FAILURE IN FIND_DEFECTS TO MATCH PROVIDED ATOMLIST. DEBUG!!!!\n' # If atomlistcheck is False then use all the atoms in the given cutoff distance else: for a in nbatmsd: box.append(solid[a[1]]) indices.append(a[1]) # Add remaining atoms in defect to defected bulk atoms object for one in range(len(solid)): if one not in indices and one < ntot: bulki.append(solid[one]) #Check for accidental vacancy admissions #checklist=[atm for atm in box if atm.symbol=='X'] #checklist.extend([atm for atm in bulki if atm.symbol=='X']) #Set up new individual indiv = box.copy() bulki.set_cell(bulko.get_cell()) indiv.set_cell(bulko.get_cell()) bulki.set_pbc(True) indiv.set_pbc(True) stro += 'Atomlist check = {0}\n'.format(atomlistcheck) stro += 'Bulko = {0}\n'.format(bulko) stro += 'New individual ({0} atoms) : {1}\n'.format(len(indiv), indiv) stro += 'New bulki ({0} atoms) : {1}\n'.format(len(bulki), bulki) #Debug: write new indiv to file if debug: b = indiv.copy() write_xyz(debug, b, 'Find Ints: New Individual') #Debug: write new bulki to file b = bulki.copy() write_xyz(debug, b, 'Find Ints: New Bulki') debug.flush() print len(bulko) return indiv, bulki, vacant, swaps, stro
def find_defects(solid, bulko, rcutoff, atomlistcheck=False, trackvacs=False, trackswaps=False, debug=False, dcheck = 0.6): """Function to find interstitials, vacancies, and substitutional atoms (swaps) in a defected structure. Identifies species by comparison to perfect structure. Inputs: solid = ASE atoms class for defected structure bulko = ASE atoms class for perfect structure rcutoff = float value of distance to surrounding atoms to include atomlistcheck = False/list of atom types and concentrations according to atomlist format trackvacs = True/False whether or not to identify vacancies in defect trackswaps = True/False whether or not to identify substitutional defects debug = False/file object to write debug structures""" # Combine perfect and defect structures together b = bulko.copy() b.extend(solid) b.set_pbc(True) #Debug: Write solid and bulko to file if debug: print len(bulko) write_xyz(debug,b,'Find Ints: Solid and Bulko') # Identify nearest neighbor atoms for each atom in perfect structure ntot = len(bulko) ctoff1 = [1.2 for one in b] nl = NeighborList(ctoff1, bothways=True, self_interaction=False) nl.update(b) slist = [] blist = [] wlist = [] #Loop over each atom in perfect structure for one in range(ntot): indices, offsets = nl.get_neighbors(one) for index, d in zip(indices,offsets): index = int(index) if index >= ntot: pos = b[index].position + numpy.dot(d,bulko.get_cell()) natm1 = Atom(position=pos) dist, dx, dy, dz = calc_dist(b[one],natm1) if dist <= dcheck: #Assume atoms closer than 0.6 Angstroms to be equivalent slist.append(index-ntot) blist.append(one) if b[one].symbol == b[index].symbol: wlist.append(index-ntot) #Identify those atoms corresponding to interstitials, vacancies, and substitutions oslist = [atm.index for atm in solid if atm.index not in slist] vlist = [atm.index for atm in bulko if atm.index not in blist] swlist = [atm.index for atm in solid if atm.index not in wlist and atm.index not in oslist] # Create Atoms objects for each identified defect ntot = len(solid) cluster = Atoms() for one in oslist: cluster.append(solid[one]) vacant = Atoms() if trackvacs==True: for one in vlist: vacant.append(Atom(symbol=bulko[one].symbol, position=bulko[one].position)) solid.append(Atom(symbol='X', position=bulko[one].position)) oslist.append(len(solid)-1) stro = 'Cluster Identified with length = {0}\nIdentified {1} vacancies\n'.format(len(cluster),len(vlist)) swaps = Atoms() if trackswaps==True: for one in swlist: swaps.append(solid[one]) oslist.append(one) stro = 'Cluster Identified with length = {0}\nIdentified {1} swaps\n'.format(len(cluster),len(swlist)) else: stro = 'Cluster Identified with length = {0}\n'.format(len(cluster)) #Debug: write cluster to file if debug: b = cluster.copy() write_xyz(debug,b,'Find Ints: Cluster') debug.flush() print 'Found cluster size = ',len(b) # Identify atoms surrounding the identified defects in the defected structure box=Atoms() bulki=Atoms() if rcutoff != 0: if rcutoff > 2.0: cutoffs = [rcutoff for one in solid] else: cutoffs = [2.0 for one in solid] solid.set_pbc(True) nl = NeighborList(cutoffs,bothways=True,self_interaction=False) nl.update(solid) nbatmsd = [] repinds = [] for one in oslist: if one not in repinds: if one < ntot: nbatmsd.append((0,one)) repinds.append(one) indices, offsets = nl.get_neighbors(one) for index,d in zip(indices,offsets): index = int(index) if index not in repinds and index < ntot: opos = copy.copy(solid[index].position) solid[index].position = solid[index].position + numpy.dot(d,solid.get_cell()) dist = solid.get_distance(one,index) solid[index].position = opos if dist <= rcutoff: nbatmsd.append((dist,index)) repinds.append(index) else: nbatmsd = [] repinds = [] for one in oslist: if one not in repinds: if one < ntot: nbatmsd.append((0,one)) repinds.append(one) nbatmsd=sorted(nbatmsd, key=lambda one:one[0], reverse=True) indices=[] i=0 # Select only atoms closest to defects that satisfy concentrations specified by atomlist given in atomlistcheck if atomlistcheck: natomsbox=sum([c for sym,c,m,u in atomlistcheck]) if len(nbatmsd) > natomsbox: while i<natomsbox: a=nbatmsd.pop() box.append(solid[a[1]]) indices.append(a[1]) i+=1 elif len(nbatmsd) <= natomsbox: for a in nbatmsd: box.append(solid[a[1]]) indices.append(a[1]) i+=1 if len(box) < natomsbox: try: while True: for n in range(len(nbatmsd)-1,-1,-1): inds, offsets=nl.get_neighbors(nbatmsd[n][1]) for one,d in zip(inds,offsets): if len(box) < natomsbox: if one not in indices and one < ntot: opos = copy.copy(solid[one].position) solid[one].position = solid[one].position + numpy.dot(d,solid.get_cell()) dist = solid.get_distance(nbatmsd[n][1],one) solid[one].position = opos if dist <= rcutoff*5.0: box.append(solid[one]) indices.append(one) else: raise StopIteration() for one,d in zip(inds,offsets): if len(box) < natomsbox: if one not in indices and one < ntot: opos = copy.copy(solid[one].position) solid[one].position = solid[one].position + numpy.dot(d,solid.get_cell()) dist = solid.get_distance(nbatmsd[n][1],one) solid[one].position = opos box.append(solid[one]) indices.append(one) else: raise StopIteration() except StopIteration: pass # If atomlistcheck is False then use all the atoms in the given cutoff distance else: for a in nbatmsd: box.append(solid[a[1]]) indices.append(a[1]) # Add remaining atoms in defect to defected bulk atoms object for one in range(len(solid)): if one not in indices and one < ntot: bulki.append(solid[one]) #Check for accidental vacancy admissions #checklist=[atm for atm in box if atm.symbol=='X'] #checklist.extend([atm for atm in bulki if atm.symbol=='X']) #Set up new individual indiv=box.copy() bulki.set_cell(bulko.get_cell()) indiv.set_cell(bulko.get_cell()) bulki.set_pbc(True) indiv.set_pbc(True) stro+='New individual ({0} atoms) : {1}\n'.format(len(indiv), indiv) stro+='New bulki ({0} atoms) : {1}\n'.format(len(bulki), bulki) #Debug: write new indiv to file if debug: b=indiv.copy() write_xyz(debug,b,'Find Ints: New Individual') #Debug: write new bulki to file b=bulki.copy() write_xyz(debug,b,'Find Ints: New Bulki') debug.flush() print len(bulko) return indiv,bulki,vacant,swaps,stro
def BestInds(pop, bests, Optimizer, writefile=False, fname=None): """Function to keep track of the best individuals throughout an optimization Inputs: pop = list of Individual class structures to be compared bests = list of previously obtained best structures Optimizer = Optimizer class structure that contains key parameters writefile = True/False boolean to tell function whether or not to output structures fname = filename to output structures Outputs: bests = list of Individual class structures updated with new options """ #logger = initialize_logger(Optimizer.loggername) logger = logging.getLogger(Optimizer.loggername) logger.info( 'best_inds_list recieved population with length = {0} and best list with length = {1} for generation {2}' .format(len(pop), len(bests), Optimizer.generation)) pop = sorted(pop, key=attrgetter('fitness')) tol = Optimizer.demin if len(bests) != 0: bfits = [ind.fitness for ind in bests] #Identify the fitnesses in the population popfits = [ind.fitness for ind in pop] #Initialize a list for individuals to not be added to best list indices = [] for i in range(len(popfits)): for j in range(len(bfits)): if popfits[i] == bfits[j]: indices.append(i) if popfits[i] < bfits[j]: diff = abs(bfits[j] - popfits[i]) diff2 = abs(bfits[j - 1] - popfits[i]) if diff > tol: if diff2 > tol: if i not in indices: bests.append(pop[i]) logger.info( 'Best list found new structure for List HI = {0}' .format(pop[i].history_index)) indices.append(i) b = bfits[0:j] b.append(pop[i].fitness) b.extend(bfits[j::]) bfits = b else: indices.append(i) bests = sorted(bests, key=attrgetter('fitness')) if len(bests) < Optimizer.number_of_bests: bmax = bests[len(bests) - 1].fitness for i in range(len(popfits)): if popfits[i] > bmax: diff = abs(popfits[i] - bmax) if diff > tol: bests.append(pop[i]) logger.info( 'Appending best list with lower energy structure') bmax = pop[i].fitness else: logger.info('Removing extra {0} structures from best list'.format( len(bests) - Optimizer.number_of_bests)) bests = bests[0:Optimizer.number_of_bests] bfits = [ind.fitness for ind in bests] else: bests = [] bfits = [] for one in pop: fit = one.fitness if len(bfits) == 0: bests.append(one) logger.info( 'Adding new structure to best list HI = {0}'.format( one.history_index)) bfits.append(fit) else: diff = abs(bfits[-1] - fit) if diff > tol: bests.append(one) bfits.append(fit) if len(bests) > Optimizer.number_of_bests: logger.info('Removing extra {0} structures from best list'.format( len(bests) - Optimizer.number_of_bests)) bests = bests[0:Optimizer.number_of_bests] if writefile == True: if fname == None: try: rank = MPI.COMM_WORLD.Get_rank() except: rank = 0 path = os.path.join(os.getcwd(), '{0}-rank{1}'.format(Optimizer.filename, rank)) logger.info('Writing Best lists to {0}'.format(path)) fxyzname = os.path.join(path, 'Bests-{0}.xyz'.format(Optimizer.filename)) ffitname = os.path.join( path, 'Bests-fitnesses-{0}.txt'.format(Optimizer.filename)) else: fxyzname = '{0}.xyz'.format(fname) ffitname = '{0}-fitnesses.txt'.format(fname) bestfile = open(fxyzname, 'w') bestfitfile = open(ffitname, 'w') for one in bests: if Optimizer.structure == 'Defect': cbulk = Atoms() cbulk.extend(one[0]) cbulk.extend(one.bulki) write_xyz(bestfile, cbulk, one.energy) else: write_xyz(bestfile, one[0], one.energy) bestfitfile.write(repr(one.fitness) + '\n') bestfile.close() bestfitfile.close() return bests
def write_individual(individ, indivfile): """Function to write the data of an individual class object to a flat file Input: individ = Individual class object to be written indivfile = String or fileobject for file to be written to Output: No output returned. Information is written to file """ if isinstance(indivfile, str): indivfile = open(indivfile, 'a') #Write break indivfile.write('----------\n') #Write structure information indivfile.write('Structure information\n') write_xyz(indivfile, individ[0]) indivfile.write('structure cell = {0}\n'.format(get_atom_cell(individ[0]))) #Write additional information indivfile.write('fitness = {0}\n'.format(individ.fitness)) indivfile.write('index = {0}\n'.format(individ.index)) indivfile.write('history_index = {0}\n'.format(individ.index)) indivfile.write('energy = {0}\n'.format(individ.energy)) indivfile.write('tenergymx = {0}\n'.format(individ.tenergymx)) indivfile.write('tenergymin = {0}\n'.format(individ.tenergymin)) indivfile.write('pressure = {0}\n'.format(individ.pressure)) indivfile.write('volume = {0}\n'.format(individ.volume)) indivfile.write('force = {0}\n'.format(individ.force)) indivfile.write('purebulkenpa = {0}\n'.format(individ.purebulkenpa)) indivfile.write('natomsbulk = {0}\n'.format(individ.natomsbulk)) indivfile.write('fingerprint = {0}\n'.format(individ.fingerprint)) indivfile.write('swaplist = {0}\n'.format(individ.swaplist)) #Write additional structure information indivfile.write('bulki\n') write_xyz(indivfile, individ.bulki) indivfile.write('bulki cell = {0}\n'.format(get_atom_cell(individ.bulki))) indivfile.write('bulko\n') write_xyz(indivfile, individ.bulko) indivfile.write('bulko cell = {0}\n'.format(get_atom_cell(individ.bulko))) indivfile.write('box\n') write_xyz(indivfile, individ.box) indivfile.write('box cell = {0}\n'.format(get_atom_cell(individ.box))) indivfile.write('vacancies\n') write_xyz(indivfile, individ.vacancies) indivfile.write('vacancies cell = {0}\n'.format( get_atom_cell(individ.vacancies))) indivfile.write('swaps\n') write_xyz(indivfile, individ.swaps) indivfile.write('swaps cell = {0}\n'.format(get_atom_cell(individ.swaps))) indivfile.write('Finish') indivfile.close() return
def formationenergy(indiv, Optimizer): """Function to calculate formation energy fitness of individual. Input: indiv = structopt Individual class object to be evaluated Optimizer = structopt Optimizer class object Output: indiv = structopt Individual class object with new fitness. """ if Optimizer.structure != 'Defect': if Optimizer.generation <1: print 'WARNING: Formation Energy fitness calculator only available for Defect structure simulation.' print ' Using total energy fitness calculator instead' indiv = totalenfit(indiv,Optimizer) stro = '' else: logger = logging.getLogger(Optimizer.loggername) #logger = initialize_logger(Optimizer.loggername) starting = indiv.duplicate() cwd = os.getcwd() try: outs = eval_energy(Optimizer,indiv) except Exception, e: logger.warn('Error in energy evaluation: {0}'.format(e), exc_info=True) stro = 'ERROR: Problem in Energy Evaluation' print stro print e stro += '\n' + repr(e) os.chdir(cwd) f=open('problem-structures.xyz','a') totalsol = indiv[0].copy() totalsol.extend(indiv.bulki) write_xyz(f,totalsol,data='Starting structure hindex={0}'.format(indiv.history_index)) 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.energy = outs[0] stro=outs[3] indiv.bulki = outs[1] #fit = (indiv.purebulkenpa*(indiv[0].get_number_of_atoms()+indiv.bulki.get_number_of_atoms()) - indiv.energy)/(indiv[0].get_number_of_atoms()+indiv.bulki.get_number_of_atoms()-indiv.natomsbulk) solid=Atoms() solid.extend(indiv[0]) solid.extend(indiv.bulki) fit=indiv.energy passflag = True if abs(fit) > Optimizer.energy_cutoff_factor*(len(indiv[0])+len(indiv.bulki)): fit=10000 message = 'Warning: Found oddly large energy from Lammps in structure HI={0}'.format(indiv.history_index) logger.warn(message) print message print ' Setting fitness to 10000' passflag=False if math.isnan(fit): logger.warn('Found NAN energy structure HI={0}'.format(indiv.history_index)) fit=10000 passflag=False indiv.energy = 10000 if passflag: for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in solid if atm.symbol==sym]) fit-= float(nc)*float(u) indiv.fitness=fit
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
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
def BestInds(pop, bests, Optimizer, writefile=False, fname=None): """Function to keep track of the best individuals throughout an optimization Inputs: pop = list of Individual class structures to be compared bests = list of previously obtained best structures Optimizer = Optimizer class structure that contains key parameters writefile = True/False boolean to tell function whether or not to output structures fname = filename to output structures Outputs: bests = list of Individual class structures updated with new options """ #logger = initialize_logger(Optimizer.loggername) logger = logging.getLogger(Optimizer.loggername) logger.info('best_inds_list recieved population with length = {0} and best list with length = {1} for generation {2}'.format( len(pop),len(bests),Optimizer.generation)) pop = sorted(pop, key=attrgetter('fitness')) tol=Optimizer.demin if len(bests)!=0: bfits=[ind.fitness for ind in bests] #Identify the fitnesses in the population popfits=[ind.fitness for ind in pop] #Initialize a list for individuals to not be added to best list indices=[] for i in range(len(popfits)): for j in range(len(bfits)): if popfits[i]==bfits[j]: indices.append(i) if popfits[i] < bfits[j]: diff = abs(bfits[j] - popfits[i]) diff2 = abs(bfits[j-1] - popfits[i]) if diff > tol: if diff2 > tol: if i not in indices: bests.append(pop[i]) logger.info('Best list found new structure for List HI = {0}'.format(pop[i].history_index)) indices.append(i) b=bfits[0:j] b.append(pop[i].fitness) b.extend(bfits[j::]) bfits=b else: indices.append(i) bests = sorted(bests, key=attrgetter('fitness')) if len(bests) < Optimizer.number_of_bests: bmax = bests[len(bests)-1].fitness for i in range(len(popfits)): if popfits[i] > bmax: diff = abs(popfits[i]-bmax) if diff > tol: bests.append(pop[i]) logger.info('Appending best list with lower energy structure') bmax = pop[i].fitness else: logger.info('Removing extra {0} structures from best list'.format(len(bests)-Optimizer.number_of_bests)) bests = bests[0:Optimizer.number_of_bests] bfits=[ind.fitness for ind in bests] else: bests = [] bfits = [] for one in pop: fit = one.fitness if len(bfits) == 0: bests.append(one) logger.info('Adding new structure to best list HI = {0}'.format(one.history_index)) bfits.append(fit) else: diff = abs(bfits[-1]-fit) if diff > tol: bests.append(one) bfits.append(fit) if len(bests) > Optimizer.number_of_bests: logger.info('Removing extra {0} structures from best list'.format(len(bests)-Optimizer.number_of_bests)) bests = bests[0:Optimizer.number_of_bests] if Optimizer.generation % 10 == 0: if writefile==True: if fname==None: try: rank = MPI.COMM_WORLD.Get_rank() except: rank = 0 path = os.path.join(os.getcwd(),'{0}-rank{1}'.format(Optimizer.filename,rank)) logger.info('Writing Best lists to {0}'.format(path)) fxyzname=os.path.join(path,'Bests-{0}.xyz'.format(Optimizer.filename)) ffitname=os.path.join(path,'Bests-fitnesses-{0}.txt'.format(Optimizer.filename)) else: fxyzname='{0}.xyz'.format(fname) ffitname='{0}-fitnesses.txt'.format(fname) bestfile=open(fxyzname,'w') bestfitfile=open(ffitname,'w') for one in bests: if Optimizer.structure=='Defect': cbulk=Atoms() cbulk.extend(one[0]) cbulk.extend(one.bulki) write_xyz(bestfile,cbulk,one.energy) else: write_xyz(bestfile,one[0],one.energy) bestfitfile.write(repr(one.fitness)+'\n') bestfile.close() bestfitfile.close() return bests