Example #1
0
def gen_solid(solidfile, solidcell, outfilename, calc=False, calcmeth=None):
    """Function to load a bulk solid from a file for use in Defect structure optimization
    Inputs:
        solidfile=String of filename to load
        solidcell=List/Matrix of cell parameters for ASE Atoms class
        outfilename=String of filename to write solid
        calc=False/calculator object for evaluating energy of solid
        calcmeth='VASP' or other method for calculating the energy of the solid
    Outputs:
        solid as ASE Atoms class
        energy and string if calc is not false
    """
    try:
        sol = read_xyz(solidfile)
    except Exception as e1:
        try:
            sol = read(solidfile)
        except Exception as e2:
            raise RuntimeError('Encountered errror:' + repr(e1) + ' ' +
                               repr(e2) +
                               ' While trying to read solid file given as:' +
                               repr(solidfile))
    cell = solidcell
    sol.set_cell(cell)
    sol.set_pbc(True)
    #Evaluate pure Bulk structure
    if calc:
        cwd = os.getcwd()
        sol.set_calculator(calc)
        stro = ''
        try:
            if calcmeth == 'VASP':
                en = sol.get_potential_energy()
                calcb = Vasp(restart=True)
                sol = calcb.get_atoms()
                PureBulkEnpa = en / sol.get_number_of_atoms()
            else:
                OUT = sol.calc.calculate(sol)
                PureBulkEnpa = OUT['thermo'][-1][
                    'pe'] / sol.get_number_of_atoms()
                sol = OUT['atoms']
                sol.set_pbc(True)
        except:
            stro = 'WARNING: Unable to calculate energy of pure bulk solid'
            PureBulkEnpa = 0
        os.chdir(cwd)
        # Write bulk file to directory
        write_xyz(outfilename, sol, PureBulkEnpa)
        return sol, PureBulkEnpa, stro
    else:
        # Write bulk file to directory
        write_xyz(outfilename, sol, 'Pure Bulk')
        return sol
Example #2
0
def gen_solid(solidfile,solidcell,outfilename,calc=False,calcmeth=None):
    """Function to load a bulk solid from a file for use in Defect structure optimization
    Inputs:
        solidfile=String of filename to load
        solidcell=List/Matrix of cell parameters for ASE Atoms class
        outfilename=String of filename to write solid
        calc=False/calculator object for evaluating energy of solid
        calcmeth='VASP' or other method for calculating the energy of the solid
    Outputs:
        solid as ASE Atoms class
        energy and string if calc is not false
    """
    try:
        sol = read_xyz(solidfile)
    except Exception as e1:
        try:
            sol = read(solidfile)
        except Exception as e2:
            raise RuntimeError('Encountered errror:'+repr(e1)+' '+repr(e2)+
                ' While trying to read solid file given as:'+repr(solidfile))
    cell = solidcell
    sol.set_cell(cell)
    sol.set_pbc(True)
    #Evaluate pure Bulk structure
    if calc:
        cwd = os.getcwd()
        sol.set_calculator(calc)
        stro = ''
        try:
            if calcmeth == 'VASP':
                en = sol.get_potential_energy()
                calcb = Vasp(restart=True)
                sol = calcb.get_atoms()
                PureBulkEnpa = en/sol.get_number_of_atoms()
            else:
                OUT = sol.calc.calculate(sol)
                PureBulkEnpa = OUT['thermo'][-1]['pe']/sol.get_number_of_atoms()
                sol = OUT['atoms']
                sol.set_pbc(True)
        except:
            stro = 'WARNING: Unable to calculate energy of pure bulk solid'
            PureBulkEnpa = 0
        os.chdir(cwd)
        # Write bulk file to directory
        write_xyz(outfilename,sol,PureBulkEnpa)
        return sol, PureBulkEnpa, stro
    else:
        # Write bulk file to directory
        write_xyz(outfilename,sol,'Pure Bulk')
        return sol
Example #3
0
 def initialize_structures(self):
     global logger
     self.output.write('\n----Initialize Structures----\n')
     #self.logger.info('Initializing Structures')
     # Initialize Population - Generate a list of ncluster individuals
     # Set bulk and index atributes
     if self.restart:
         logger.info('Loading previous population')
         pop = generate.get_restart_population(self)
     else:
         logger.info('Generating new population')
         pop = generate.get_population(self)
     if 'MA' in self.debug: 
         inp_out.write_xyz(self.debugfile,pop[0][0],'First Generated Individual')
     #Use if concentration of interstitials is unknown
     if self.swaplist:
         mutlist=self.mutation_options
         self.mutation_options=['IntSwapLocal']
         for i in range(len(pop)):
             one = pop[i]
             one.swaplist=copy.deepcopy(swaplist)
             if random.random() < 0.25:
                 pop[i], opt = switches.moves_switch(one,self)
         self.mutation_options=mutlist
     # Write Initial structures to files
     self.output.write('\n---Starting Structures---\n')
     inp_out.write_pop(self, pop)
     #Print number of atoms to Summary file
     if self.structure=='Defect' or self.structure=='Surface':
         natstart=len(pop[0][0])+len(pop[0].bulki)
     else:
         natstart=len(pop[0][0])
     if not self.restart:
         if self.structure=='Defect':
             self.summary.write('Defect Run Pure Bulk Energy per Atom : '+repr(self.purebulkenpa)+'\n')
         else:
             self.summary.write(self.structure+' Run : '+repr(0)+'\n')
         self.summary.write('Natoms '+repr(natstart)+ '\n')
         #Print data headers to summary file
         self.summary.write('Generation Fitmin Fitavg Fitmedium Fitmax std time \n')
     offspring=pop
     #pop=[]
     #BESTS=[]
     return offspring
Example #4
0
 def algorithm_serial(self):
     """Subprogram to run the optimizer in serial"""
     global logger
     self.algorithm_initialize()
     logger.info('Beginning main algorithm loop')
     #Begin main algorithm loop
     while not self.convergence:
         logger.info('Setup calculator for generation {0}'.format(self.generation))
         pop = self.population
         logger.info('Setup population')
         offspring = self.generation_set(pop)
         # Identify the individuals with an invalid fitness
         invalid_ind = [ind for ind in offspring if ind.energy==0]
         #DEBUG: Write first invalid ind
         if 'MA' in self.debug:
             logger.info('Identified {0} structures with energy=0'.format(len(invalid_ind)))
             inp_out.write_xyz(self.debugfile,invalid_ind[0][0],\
             'First from Invalid_ind list '+repr(invalid_ind[0].energy))
             #DEBUG: Write first invalid ind in solid
             if self.structure=='Defect' or self.structure=='Surface':
                 sols = invalid_ind[0][0].copy()
                 sols.extend(invalid_ind[0].bulki)
                 inp_out.write_xyz(self.debugfile,sols,'First from Invalid-ind + Bulki')
                 sols = invalid_ind[0][0].copy()
                 sols.extend(invalid_ind[0].bulko)
                 inp_out.write_xyz(self.debugfile,sols,'First from Invalid-ind + Bulko')
         self.output.write('\n--Evaluate Structures--\n')
         logger.info('Evaluating fitness of structures')
         for i in range(len(invalid_ind)):
             ind = invalid_ind[i]
             if 'MA' in self.debug:
                 write_xyz(self.debugfile,ind[0],'Individual to fitness_switch')
             outs = switches.fitness_switch([self,ind])
             self.output.write(outs[1])
             invalid_ind[i] = outs[0]
         pop.extend(invalid_ind)
         logger.info('Eval Population')
         pop = self.generation_eval(pop)
         self.write()
         
     logger.info('Run algorithm stats')
     end_signal = self.algorithm_stats(self.population)
     return end_signal    
Example #5
0
 def generation_set(self,pop):
     global logger
     self.calc = tools.setup_calculator(self) #Set up calculator for atomic structures
     #Set up calculator for fixed region calculations
     if self.fixed_region:
         self.static_calc = self.calc #May need to copy this
         self.calc = tools.setup_fixed_region_calculator(self)
     self.output.write('\n-------- Generation '+repr(self.generation)+' --------\n')
     self.files[self.nindiv].write('Generation '+str(self.generation)+'\n')
     if len(pop) == 0:
         logger.info('Initializing structures')
         offspring = self.initialize_structures()
         self.population = offspring
     else:
         for i in range(len(pop)):
             # Reset History index
             pop[i].history_index=repr(pop[i].index)
         # Select the next generation individuals
         offspring = switches.selection_switch(pop, self.nindiv,
                     self.selection_scheme, self)
         # Clone the selected individuals
         offspring=[off1.duplicate() for off1 in offspring]
         # Apply crossover to the offspring
         self.output.write('\n--Applying Crossover--\n')
         cxattempts = 0
         for child1, child2 in zip(offspring[::2], offspring[1::2]):
             if random.random() < self.cxpb:
                 child1,child2 = switches.crossover_switch(child1, child2, self)
                 cxattempts+=2
         self.cxattempts=cxattempts
         #DEBUG: Write first child
         if 'MA' in self.debug: 
             inp_out.write_xyz(self.debugfile,offspring[0][0],'First Child '+
                 repr(offspring[0].history_index))
         # Apply mutation to the offspring
         self.output.write('\n--Applying Mutation--\n')
         mutattempts = []
         muts = []
         for mutant in offspring:
             if random.random() < self.mutpb:
                 if self.mutant_add:
                     mutant = mutant.duplicate()
                 mutant, optsel = switches.moves_switch(mutant,self)
                 mutattempts.append([mutant.history_index,optsel])
                 if self.mutant_add:
                     muts.append(mutant)
         if self.mutant_add:
             offspring.extend(muts)
         self.mutattempts=mutattempts
         #DEBUG: Write first offspring
         if 'MA' in self.debug: 
             inp_out.write_xyz(self.debugfile,muts[0][0],'First Mutant '+\
             repr(muts[0].history_index))
     if 'stem' in self.fitness_scheme:
         if self.stem_coeff==None:
             logger.info('Setting STEM coeff (alpha)')
             ind = offspring.pop()
             from MAST.structopt.tools.StemCalc import find_stem_coeff
             outs = find_stem_coeff(self,ind)
             ind = outs[1]
             ind.fitness = 0
             ind.energy = 0
             self.stem_coeff = outs[0]
             logger.info('STEM Coeff = {0}'.format(self.stem_coeff))
             self.output.write('stem_coeff Calculated to be: '+repr(self.stem_coeff)+'\n')
             offspring.append(ind)
               
     return offspring
Example #6
0
 def generation_eval(self, pop):
     global logger
     emx = max(ind.energy for ind in pop)
     emn = min(ind.energy for ind in pop)
     for ind in pop:
         ind.tenergymx = emx
         ind.tenergymin = emn
     #DEBUG: Write relaxed individual
     if 'MA' in self.debug:
         if self.generation > 0: 
             inp_out.write_xyz(self.debugfile,pop[self.nindiv][0],\
             'First Relaxed Offspring '+repr(pop[self.nindiv-1].energy))    
             #DEBUG: Write relaxed ind in solid
             if self.structure=='Defect' or self.structure=='Surface':
                 inp_out.write_xyz(self.debugfile,pop[self.nindiv].bulki,\
                 'First Relaxed bulki '+repr(pop[self.nindiv-1].energy))    
                 sols = pop[self.nindiv][0].copy()
                 sols.extend(pop[self.nindiv].bulki)
                 inp_out.write_xyz(self.debugfile,sols,'First from Invalid-ind + Bulki '+\
                 repr(pop[self.nindiv].energy))
                 sols = pop[self.nindiv][0].copy()
                 sols.extend(pop[self.nindiv].bulko)
                 inp_out.write_xyz(self.debugfile,sols,\
                 'First from Invalid-ind + Bulko '+repr(pop[self.nindiv].energy))
     if self.generation==0:
         logger.info('Initializing Bests list')
         self.BESTS = list()
     if self.best_inds_list:
         self.BESTS = tools.BestInds(pop,self.BESTS,self,writefile=True)
     # Determine survival based on fitness predator
     if 'lambda,mu' not in self.algorithm_type:
         pop = tools.get_best(pop, len(pop))
     if self.fingerprinting:
         logger.info('Writing fingerprint files')
         for one in pop:
             self.fpfile.write(repr(fingerprinting.fingerprint_dist(
                 pop[0].fingerprint,one.fingerprint))+' '+repr(one.energy)+' ')
         self.fpfile.write('\n')
         self.fpminfile.write(repr(pop[0].fingerprint)+'\n')
         self.fpminfile.write(repr(pop[0].energy)+'\n')
     nevals = len(pop)/2
     if self.generation !=0:
         logger.info('Applying predator')
         pop = predator_switch(pop,self)
     else:
         self.genrep = 0
         self.minfit = 0
     # Evaluate population
     logger.info('Checking population for convergence')
     self.check_pop(pop)
     #Update general output tracking
     if self.generation !=0:
         histlist = []
         for ind in pop:
             histlist.append(ind.history_index)
         self.Runtimes.append(time.time())
         self.Evaluations.append(nevals)
         cxsuccess = 0
         mutsuccess = []
         for one in histlist:
             if '+' in one:
                 cxsuccess +=1
             if 'm' in one:
                 mutsuccess.append(one)
         self.CXs.append((self.cxattempts,cxsuccess))
         mutslist = [[0,0] for one in self.mutation_options]
         for one in mutsuccess:
             for two, opt in self.mutattempts:
                 if one==two:
                     index = [ind for ind,value in enumerate(
                         self.mutation_options) if value==opt][0]
                     mutslist[index][1]+=1
         for one,opt in self.mutattempts:
             index = [ind for ind,value in enumerate(
             self.mutation_options) if value==opt][0]
             mutslist[index][0]+=1
         self.Muts.append(mutslist)
         self.output.write('\n----- Generation Stats -----\n')
         self.output.write('Attempted Crossovers: ' + repr(self.cxattempts)+'\n')
         self.output.write('Successful Crossovers: ' + repr(cxsuccess)+'\n')
         self.output.write('Mutations:\n')
         i=0
         for opt in self.mutation_options:
             self.output.write('    Attempted ' + opt + ' : ' + repr(mutslist[i][0]) + '\n')
             self.output.write('    Successful ' + opt + ' : ' + repr(mutslist[i][1]) + '\n')
             i+=1
     self.generation += 1
     # Set new index values
     index1 = 0
     for ind in pop:
         ind.index = index1
         index1+=1
     index1 = 0
     if not self.convergence:
         try:
             self.calc.clean()
             if self.fixed_region:
                 self.static_calc.clean()
         except:
             pass
         if self.lammps_keep_files:
             try:
                 if self.parallel and ('Island_Method' not in self.algorithm_type):
                     nproc = MPI.COMM_WORLD.Get_size()
                     lmpfilepath = os.path.dirname(self.calc.tmp_dir)
                     for proc in range(nproc):
                         pth = os.path.join(lmpfilepath,'rank-{0}'.format(proc))
                         fls = [fl for fl in os.listdir(pth) if '.' not in fl]
                         for one in fls:
                             os.remove(pth+'/'+one)
                 else:
                     fls = [fl for fl in os.listdir(self.calc.tmp_dir) if '.' not in fl]
                     for one in fls:
                         os.remove(self.calc.tmp_dir+'/'+one)
             except Exception, e:
                 logger.error('Print issue in removing files {0}.'.format(e),exc_info=True)
                 print str(e)
                 pass
Example #7
0
def rotct_rand(ind1, ind2, Optimizer):
    """Rotate atoms cut and splice
    Rotates atoms randomly around center of mass and cuts with xy plane
    Maintains number of atoms
    Maintains concentration of atoms
    Returns individuals to standard positions at end (un-rotates)
    """
    if 'CX' in Optimizer.debug:
        debug = True
    else:
        debug = False
    Optimizer.output.write('Random Rotate Cut/Splice Cx between individual '+repr(ind1.index)+' and individual '+repr(ind2.index)+'\n')
    
    #Perserve starting conditions of individual
    indi1 = ind1[0].copy()
    if Optimizer.forcing != 'FreeNatom':
       rax = random.choice(['x', '-x','y','-y','z','-z'])
    else:
       rax = 'z'
    rang=random.random()*math.pi
    indi1.rotate(rax,a=rang,center='COM',rotate_cell=False)
    indi2 =ind2[0].copy()
    #Translate individuals so COM is at (0,0,0)
    com1 = indi1.get_center_of_mass()
    indi1.translate(-1*com1)
    com2 = indi2.get_center_of_mass()
    indi2.translate(-1*com2)
    #Select random axis, random angle, and random position and rotate individuals
    cmax = [min(numpy.maximum.reduce(indi1.get_positions())[i],numpy.maximum.reduce(indi2.get_positions())[i]) for i in range(3)]
    cmin = [min(numpy.minimum.reduce(indi1.get_positions())[i],numpy.minimum.reduce(indi2.get_positions())[i]) for i in range(3)]
    n=0
    while n<10:
        if Optimizer.forcing != 'FreeNatom':
           rax = random.choice(['x', '-x','y','-y','z','-z'])
           rang = random.random()* math.pi/2.0
           rpos = [random.uniform(cmin[i]*0.8,cmax[i]*0.8) for i in range(3)]
           indi1.rotate(rax,a=rang,center=rpos,rotate_cell=False)
        else: 
           rax = random.choice(['x','-x','y','-y'])
           rangz = random.uniform(0,90)/180.0*math.pi
           rang = math.pi/2.0
           rpos = [random.uniform(cmin[i]*0.7,cmax[i]*0.7) for i in range(3)]
           indi1.rotate('z',a=rangz,center=rpos,rotate_cell=False)
           indi1.rotate(rax,a=rang,center=rpos,rotate_cell=False)
        #Search for atoms in individual 1 that are above the xy plane
        group1 = Atoms(cell=ind1[0].get_cell(),pbc=ind1[0].get_pbc())
        indices1=[]
        for one in indi1:
            if one.position[2] >= 0:
                group1.append(one)
                indices1.append(one.index)
        if len(group1) > 2 and len(group1) < len(indi1):
            break
        else:
            n+=1
            if Optimizer.forcing != 'FreeNatom':
               indi1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False)
            else:
               indi1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False)
               indi1.rotate('z',a=-1*rangz,center=rpos,rotate_cell=False)
    if Optimizer.forcing != 'FreeNatom':
       indi2.rotate(rax,a=rang,center=rpos,rotate_cell=False)
    else:
       indi2.rotate('z',a=rangz,center=rpos,rotate_cell=False)
       indi2.rotate(rax,a=rang,center=rpos,rotate_cell=False)
    if debug: 
        print 'Group1 size = ', len(group1)
        print 'Position = ', rpos
        print 'Angle = ', rang
        print 'Axis = ', rax
        print 'Number of tries = ', n
    if len(group1) != 0:
        #Apply concentration forcing if needed
        group2 = Atoms(cell=ind2[0].get_cell(),pbc=ind2[0].get_pbc())
        indices2 = []
        dellist = []
        for one in indi2:
            if one.position[2] >= 0:
                group2.append(one)
                indices2.append(one.index)
        if Optimizer.forcing=='Concentration':
            symlist = list(set(indi1.get_chemical_symbols()))
            seplist = [[atm for atm in group2 if atm.symbol == sym] for sym in symlist]
            group2n=Atoms(cell=group2.get_cell(),pbc=group2.get_pbc())
            indices2n = []
            dellist = []
            for one in group1:
                sym1=one.symbol
                listpos=[i for i,s in enumerate(symlist) if s==sym1][0]
                if len(seplist[listpos]) > 0:
                    pos = random.choice(range(len(seplist[listpos])))
                    group2n.append(seplist[listpos][pos])
                    indices2n.append(indices2[seplist[listpos][pos].index])
                    del seplist[listpos][pos]
                else:
                    dellist.append(one.index)
            if len(dellist) != 0:
                dellist.sort(reverse=True)
                for one in dellist:
                    del group1[one]
                    del indices1[one]
            indices2=indices2n
            group2=group2n.copy()
        elif Optimizer.forcing != 'FreeNatom':
            dellist = []
            while len(group2) < len(group1)-len(dellist):
                #Too many atoms in group 1
                dellist.append(random.choice(group1).index)
            if len(dellist) != 0:
                dellist.sort(reverse=True)
                for one in dellist:
                    del group1[one]
                    del indices1[one]
            dellist = []
            while len(group1) < len(group2)-len(dellist):
                #Too many atoms in group 2
                dellist.append(random.choice(group2).index)
            if len(dellist) != 0:
                dellist.sort(reverse=True)
                for one in dellist:
                    del group2[one]
                    del indices2[one]
    
        other2 = Atoms(cell=ind2[0].get_cell(),pbc=ind2[0].get_pbc())
        for one in indi2:
            if one.index not in indices2:
                other2.append(one)
        other1 = Atoms(cell=ind1[0].get_cell(),pbc=ind1[0].get_pbc())
        for one in indi1:
            if one.index not in indices1:
                other1.append(one)
        indi1 = group2.copy()
        indi1.extend(other1)
        indi2 = group1.copy()
        indi2.extend(other2)
    
        #DEBUG: Write crossover to file
        if debug: 
            write_xyz(Optimizer.debugfile, group1,'group1')
            write_xyz(Optimizer.debugfile, other1,'other1')
            write_xyz(Optimizer.debugfile, group2,'group2')
            write_xyz(Optimizer.debugfile, other2,'other2')
            print 'Length of group1 = ',len(group1),'Length of group2',len(group2)
    
        #DEBUG: Check structure of atoms exchanged
        for sym,c,m,u in Optimizer.atomlist:
            nc=len([atm for atm in indi1 if atm.symbol==sym])
            Optimizer.output.write('CX RANDROTCT: Individual 1 contains '+repr(nc)+' '+repr(sym)+' atoms\n')
            nc=len([atm for atm in indi2 if atm.symbol==sym])
            Optimizer.output.write('CX RANDROTCT: Individual 2 contains '+repr(nc)+' '+repr(sym)+' atoms\n')
        if Optimizer.forcing !='Concentration':
            for i in range(len(Optimizer.atomlist)):
                atms1=[inds for inds in indi1 if inds.symbol==Optimizer.atomlist[i][0]]
                atms2=[inds for inds in indi2 if inds.symbol==Optimizer.atomlist[i][0]]
                if len(atms1)==0:
                    if len(atms2)==0:
                        indi1[random.randint(0,len(indi1)-1)].symbol==Optimizer.atomlist[i][0]
                        indi2[random.randint(0,len(indi2)-1)].symbol==Optimizer.atomlist[i][0]
                    else:
                        indi1.append(atms2[random.randint(0,len(atms2)-1)])
                        indi1.pop(random.randint(0,len(indi1)-2))
                else:
                    if len(atms2)==0:
                        indi2.append(atms1[random.randint(0,len(atms1)-1)])
                        indi2.pop(random.randint(0,len(indi2)-2))	
        if Optimizer.forcing != 'FreeNatom':
           indi1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False)
           indi2.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False)
        else:
           indi1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False)
           indi1.rotate('z',a=-1*rangz,center=rpos,rotate_cell=False)
           indi2.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False)
           indi2.rotate('z',a=-1*rangz,center=rpos,rotate_cell=False)
        indi1.translate(com1)
        indi2.translate(com2)
    
    #DEBUG: Check structure and number of atoms in crystal
    if Optimizer.structure=='Defect':
        solid1=Atoms()
        solid1.extend(indi1)
        solid1.extend(ind1.bulki)
        solid2=Atoms()
        solid2.extend(indi2)
        solid2.extend(ind2.bulki)
        for sym,c,m,u in Optimizer.atomlist:
            nc=len([atm for atm in solid1 if atm.symbol==sym])
            Optimizer.output.write('CX RANDROTCT: Defect 1 configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n')
            nc=len([atm for atm in solid2 if atm.symbol==sym])
            Optimizer.output.write('CX RANDROTCT: Defect 2 configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n')
    if debug: Optimizer.output.flush()
    #pdb.set_trace()
    ind1[0]=indi1
    ind2[0]=indi2
    
    return ind1, ind2
Example #8
0
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
Example #9
0
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
Example #10
0
def rotct_defect(ind1, ind2, Optimizer):
    """Rotate atoms cut and splice
    Translates atoms to center of positions first
    Rotates atoms randomly around center of mass and cuts with xy plane
    Maintains number of atoms
    Maintains concentration of atoms
    Returns individuals to standard positions at end (un-rotates)
    """
    if 'CX' in Optimizer.debug:
        debug = True
    else:
        debug = False
    Optimizer.output.write('Rotate Cut/Splice Cx for defects between individual '+repr(ind1.index)+' and individual '+repr(ind2.index)+'\n')
    
    #Perserve starting conditions of individual
    indi1 = ind1[0].copy()
    indi2 =ind2[0].copy()
    #Translate individuals so COP is at (0,0,0)
    if Optimizer.structure=='Defect':
        #Identify center of positions for defect structure
        indi1c,indi1b,vacant1,swap1,stro1 = find_defects(indi1,Optimizer.solidbulk,0)
        com1 = position_average(indi1c)
        indi1 = shift_atoms(indi1, com1)
        trans = [-p for p in numpy.maximum.reduce(indi1.get_cell())]
        indi1.translate(trans)
        #Do the same for second individual
        indi2c,indi2b,vacant2,swap2,stro2 = find_defects(indi2,Optimizer.solidbulk,0)
        com2 = position_average(indi2c)
        indi2 = shift_atoms(indi2, com2)
        indi2.translate(trans)
    else:
        com1 = indi1.get_center_of_mass()
        indi1.translate(-1*com1)
        com2 = indi2.get_center_of_mass()
        indi2.translate(-1*com2)
    #Select random axis, random angle, and random position and rotate individuals
    n=0
    while n<10:
        rax = random.choice(['x', '-x','y','-y','z','-z'])
        rang = random.random()*90
        indi1.rotate(rax,a=rang,center=[0,0,0],rotate_cell=False)
        #Search for atoms in individual 1 that are above the xy plane
        group1 = Atoms(cell=ind1[0].get_cell(),pbc=ind1[0].get_pbc())
        indices1=[]
        for one in indi1:
            if one.position[2] >= 0:
                group1.append(one)
                indices1.append(one.index)
        if len(group1) > 2 and len(group1) < len(indi1):
            break
        else:
            n+=1
            indi1.rotate(rax,a=-1*rang,center=[0,0,0], rotate_cell=False)
    indi2.rotate(rax,a=rang,center=[0,0,0],rotate_cell=False)
    if debug: 
        print 'Group1 size = ', len(group1)
        print 'Position = ', [0,0,0]
        print 'Angle = ', rang
        print 'Axis = ', rax
        print 'Number of tries = ', n+1
    if len(group1) != 0:
        #Apply concentration forcing if needed
        group2 = Atoms(cell=ind2[0].get_cell(),pbc=ind2[0].get_pbc())
        indices2 = []
        dellist = []
        for one in indi2:
            if one.position[2] >= 0:
                group2.append(one)
                indices2.append(one.index)
        if Optimizer.forcing=='Concentration':
            symlist = list(set(indi1.get_chemical_symbols()))
            seplist = [[atm for atm in group2 if atm.symbol == sym] for sym in symlist]
            group2n=Atoms(cell=group2.get_cell(),pbc=group2.get_pbc())
            indices2n = []
            dellist = []
            for one in group1:
                sym1=one.symbol
                listpos=[i for i,s in enumerate(symlist) if s==sym1][0]
                if len(seplist[listpos]) > 0:
                    pos = random.choice(range(len(seplist[listpos])))
                    group2n.append(seplist[listpos][pos])
                    indices2n.append(indices2[seplist[listpos][pos].index])
                    del seplist[listpos][pos]
                else:
                    dellist.append(one.index)
            if len(dellist) != 0:
                dellist.sort(reverse=True)
                for one in dellist:
                    del group1[one]
                    del indices1[one]
            indices2=indices2n
            group2=group2n.copy()
        else:
            dellist = []
            while len(group2) < len(group1)-len(dellist):
                #Too many atoms in group 1
                dellist.append(random.choice(group1).index)
            if len(dellist) != 0:
                dellist.sort(reverse=True)
                for one in dellist:
                    del group1[one]
                    del indices1[one]
            dellist = []
            while len(group1) < len(group2)-len(dellist):
                #Too many atoms in group 2
                dellist.append(random.choice(group2).index)
            if len(dellist) != 0:
                dellist.sort(reverse=True)
                for one in dellist:
                    del group2[one]
                    del indices2[one]
    
        other2 = Atoms(cell=ind2[0].get_cell(),pbc=ind2[0].get_pbc())
        for one in indi2:
            if one.index not in indices2:
                other2.append(one)
        other1 = Atoms(cell=ind1[0].get_cell(),pbc=ind1[0].get_pbc())
        for one in indi1:
            if one.index not in indices1:
                other1.append(one)
        indi1 = group2.copy()
        indi1.extend(other1)
        indi2 = group1.copy()
        indi2.extend(other2)
    
        #DEBUG: Write crossover to file
        if debug: 
            write_xyz(Optimizer.debugfile, group1,'group1')
            write_xyz(Optimizer.debugfile, other1,'other1')
            write_xyz(Optimizer.debugfile, group2,'group2')
            write_xyz(Optimizer.debugfile, other2,'other2')
            print 'Length of group1 = ',len(group1),'Length of group2',len(group2)
    
        #DEBUG: Check structure of atoms exchanged
        for sym,c,m,u in Optimizer.atomlist:
            nc=len([atm for atm in indi1 if atm.symbol==sym])
            Optimizer.output.write('CX ROTCT_Defect: Individual 1 contains '+repr(nc)+' '+repr(sym)+' atoms\n')
            nc=len([atm for atm in indi2 if atm.symbol==sym])
            Optimizer.output.write('CX ROTCT_Defect: Individual 2 contains '+repr(nc)+' '+repr(sym)+' atoms\n')
        if Optimizer.forcing !='Concentration':
            for i in range(len(Optimizer.atomlist)):
                atms1=[inds for inds in indi1 if inds.symbol==Optimizer.atomlist[i][0]]
                atms2=[inds for inds in indi2 if inds.symbol==Optimizer.atomlist[i][0]]
                if len(atms1)==0:
                    if len(atms2)==0:
                        indi1[random.randint(0,len(indi1)-1)].symbol==Optimizer.atomlist[i][0]
                        indi2[random.randint(0,len(indi2)-1)].symbol==Optimizer.atomlist[i][0]
                    else:
                        indi1.append(atms2[random.randint(0,len(atms2)-1)])
                        indi1.pop(random.randint(0,len(indi1)-2))
                else:
                    if len(atms2)==0:
                        indi2.append(atms1[random.randint(0,len(atms1)-1)])
                        indi2.pop(random.randint(0,len(indi2)-2))	
        indi1.rotate(rax,a=-1*rang,center=[0,0,0], rotate_cell=False)
        indi2.rotate(rax,a=-1*rang,center=[0,0,0], rotate_cell=False)
        if Optimizer.structure=='Defect':
            trans = [-p for p in trans]
            indi1.translate(trans)
            indi2.translate(trans)
            indi1 = shift_atoms(indi1, [-p for p in com1])
            indi2 = shift_atoms(indi2, [-p for p in com2])
        else:
            indi1.translate(com1)
            indi2.translate(com2)
        
        #DEBUG: Check structure and number of atoms in crystal
        if Optimizer.structure=='Defect':
            solid1=Atoms()
            solid1.extend(indi1)
            solid1.extend(ind1.bulki)
            solid2=Atoms()
            solid2.extend(indi2)
            solid2.extend(ind2.bulki)
            for sym,c,m,u in Optimizer.atomlist:
                nc=len([atm for atm in solid1 if atm.symbol==sym])
                Optimizer.output.write('CX ROTCT_Defect: Defect 1 configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n')
                nc=len([atm for atm in solid2 if atm.symbol==sym])
                Optimizer.output.write('CX ROTCT_Defect: Defect 2 configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n')
        if debug: Optimizer.output.flush()
        #pdb.set_trace()
        ind1[0]=indi1
        ind2[0]=indi2
    
    return ind1, ind2
Example #11
0
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
Example #12
0
File: rotct.py Project: m-yu/MAST
def rotct(ind1, ind2, Optimizer):
    """Rotate atoms cut and splice
    Rotates atoms randomly around center of mass and cuts with xy plane
    Maintains number of atoms
    Maintains concentration of atoms
    Returns individuals to standard positions at end (un-rotates)
    """
    if 'CX' in Optimizer.debug:
        debug = True
    else:
        debug = False
    Optimizer.output.write('Rotate Cut/Splice Cx between individual '+repr(ind1.index)+' and individual '+repr(ind2.index)+'\n')
    
    #Perserve starting conditions of individual
    indi1 = ind1[0].copy()
    indi2 = ind2[0].copy()
    
    #Translate individuals so COM is at (0,0,0)
    com1 = indi1.get_center_of_mass()
    indi1.translate(-1*com1)
    com2 = indi2.get_center_of_mass()
    indi2.translate(-1*com2)
    #Select random axis and random angle and rotate individuals
    n=0
    while n<10:
        rax = random.choice(['x', '-x','y','-y','z','-z'])
        rang = random.random()*90
        indi1.rotate(rax,a=rang,center='COM',rotate_cell=False)
        #Search for atoms in individual 1 that are above the xy plane
        group1 = Atoms(cell=ind1[0].get_cell(),pbc=ind1[0].get_pbc())
        indices1=[]
        for one in indi1:
            if one.position[2] >= 0:
                group1.append(one)
                indices1.append(one.index)
        if len(group1) > 2 and len(group1) < len(indi1):
            break
        else:
            indi1.rotate(rax,a=-1*rang,center='COM', rotate_cell=False)
        n+=1
    indi2.rotate(rax,a=rang,center='COM', rotate_cell=False)
    if debug: 
        print 'Group1 size = ', len(group1)
        print 'Position = ', [0,0,0]
        print 'Angle = ', rang
        print 'Axis = ', rax
        print 'Number of tries = ', n+1
    #Apply concentration forcing if needed
    group2 = Atoms(cell=ind2[0].get_cell(),pbc=ind2[0].get_pbc())
    indices2 = []
    dellist = []
    if Optimizer.forcing=='Concentration':
        symlist = list(set(group1.get_chemical_symbols()))
        seplist = [[atm for atm in indi2 if atm.symbol == sym] for sym, count in symlist]
        for one in group1:
            sym1=one.symbol
            listpos=[i for i,s in enumerate(symlist) if s==sym1][0]
            if len(seplist[listpos]) > 0:
                dist=[z for x,y,z in [one.position for one in seplist[listpos]]]
                pos = [i for i,value in enumerate(dist) if value==max(dist)][0]
                group2.append(seplist[listpos][pos])
                indices2.append(seplist[listpos][pos].index)
                del seplist[listpos][pos]
            else:
                dellist.append(one.index)
        if len(dellist) != 0:
            dellist.sort(reverse=True)
            for one in dellist:
                del group1[one]
                del indices1[one]
        #indices2.append(pt2.index)
    else:
        for one in indi2:
            if one.position[2] >= 0:
                group2.append(one)
                indices2.append(one.index)
        while len(group2) < len(group1)-len(dellist):
            #Too many atoms in group 1
            dellist.append(random.choice(group1).index)
        if len(dellist) != 0:
            dellist.sort(reverse=True)
            for one in dellist:
                del group1[one]
                del indices1[one]
        dellist = []
        while len(group1) < len(group2)-len(dellist):
            #Too many atoms in group 2
            dellist.append(random.choice(group2).index)
        if len(dellist) != 0:
            dellist.sort(reverse=True)
            for one in dellist:
                del group2[one]
                del indices2[one]
    
    other1 = Atoms()
    other2 = Atoms()
    other2 = Atoms(cell=ind2[0].get_cell(),pbc=ind2[0].get_pbc())
    for one in indi2:
        if one.index not in indices2:
            other2.append(one)
    other1 = Atoms(cell=ind1[0].get_cell(),pbc=ind1[0].get_pbc())
    for one in indi1:
        if one.index not in indices1:
            other1.append(one)
    

    indi1 = group2.copy()
    indi1.extend(other1)
    indi2 = group1.copy()
    indi2.extend(other2)
    
    #DEBUG: Write crossover to file
    if debug: 
        write_xyz(Optimizer.debugfile, group1,'group1')
        write_xyz(Optimizer.debugfile, other1,'other1')
        write_xyz(Optimizer.debugfile, group2,'group2')
        write_xyz(Optimizer.debugfile, other2,'other2')
        print 'Length of group1 = ',len(group1),'Length of group2',len(group2)
    
    
    #DEBUG: Check structure of atoms exchanged
    for sym,c,m,u in Optimizer.atomlist:
        nc=len([atm for atm in indi1 if atm.symbol==sym])
        Optimizer.output.write('CX ROTCT: Individual 1 contains '+repr(nc)+' '+repr(sym)+' atoms\n')
        nc=len([atm for atm in indi2 if atm.symbol==sym])
        Optimizer.output.write('CX ROTCT: Individual 2 contains '+repr(nc)+' '+repr(sym)+' atoms\n')

    #Need to have at least one atom of each structure in atomlist to prevent Lammps for erroring
    if Optimizer.forcing !='Concentration':
        for i in range(len(Optimizer.atomlist)):
            atms1=[inds for inds in indi1 if inds.symbol==Optimizer.atomlist[i][0]]
            atms2=[inds for inds in indi2 if inds.symbol==Optimizer.atomlist[i][0]]
            if len(atms1)==0:
                if len(atms2)==0:
                    indi1[random.randint(0,len(indi1)-1)].symbol==Optimizer.atomlist[i][0]
                    indi2[random.randint(0,len(indi2)-1)].symbol==Optimizer.atomlist[i][0]
                else:
                    indi1.append(atms2[random.randint(0,len(atms2)-1)])
                    indi1.pop(random.randint(0,len(indi1)-2))
            else:
                if len(atms2)==0:
                    indi2.append(atms1[random.randint(0,len(atms1)-1)])
                    indi2.pop(random.randint(0,len(indi2)-2))	
    indi1.rotate(rax,a=-1*rang,center='COM', rotate_cell=False)
    indi2.rotate(rax,a=-1*rang,center='COM', rotate_cell=False)
    indi1.translate(com1)
    indi2.translate(com2)

    if Optimizer.structure != 'Defect':
        cm = indi1.get_center_of_mass()
        cell = numpy.maximum.reduce(indi1.get_cell())
        cop = [cell[0]/float(2), cell[1]/float(2), cell[2]/float(2)]
        indi1.translate(-1*cm)
        indi1.translate(cop)
        cm = indi2.get_center_of_mass()
        cell = numpy.maximum.reduce(indi2.get_cell())
        cop = [cell[0]/float(2), cell[1]/float(2), cell[2]/float(2)]
        indi2.translate(-1*cm)
        indi2.translate(cop)

    ind1[0]=indi1
    ind2[0]=indi2
    
    #Check structure and number of atoms in crystal
    if Optimizer.structure=='Defect':
        solid1=Atoms()
        solid1.extend(ind1[0])
        solid1.extend(ind1.bulki)
        solid2=Atoms()
        solid2.extend(ind1[0])
        solid2.extend(ind2.bulki)
        for sym,c,m,u in Optimizer.atomlist:
                nc=len([atm for atm in solid1 if atm.symbol==sym])
                Optimizer.output.write('CX ROTCT: CIBS 1 configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n')
                nc=len([atm for atm in solid2 if atm.symbol==sym])
                Optimizer.output.write('CX ROTCT: CIBS 2 configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n')
    return ind1, ind2
Example #13
0
def rotct(ind1, ind2, Optimizer):
    """Rotate atoms cut and splice
    Rotates atoms randomly around center of mass and cuts with xy plane
    Maintains number of atoms
    Maintains concentration of atoms
    Returns individuals to standard positions at end (un-rotates)
    """
    if 'CX' in Optimizer.debug:
        debug = True
    else:
        debug = False
    Optimizer.output.write('Rotate Cut/Splice Cx between individual ' +
                           repr(ind1.index) + ' and individual ' +
                           repr(ind2.index) + '\n')

    #Perserve starting conditions of individual
    indi1 = ind1[0].copy()
    indi2 = ind2[0].copy()

    #Translate individuals so COM is at (0,0,0)
    com1 = indi1.get_center_of_mass()
    indi1.translate(-1 * com1)
    com2 = indi2.get_center_of_mass()
    indi2.translate(-1 * com2)
    #Select random axis and random angle and rotate individuals
    n = 0
    while n < 10:
        rax = random.choice(['x', '-x', 'y', '-y', 'z', '-z'])
        rang = random.random() * 90
        indi1.rotate(rax, a=rang, center='COM', rotate_cell=False)
        #Search for atoms in individual 1 that are above the xy plane
        group1 = Atoms(cell=ind1[0].get_cell(), pbc=ind1[0].get_pbc())
        indices1 = []
        for one in indi1:
            if one.position[2] >= 0:
                group1.append(one)
                indices1.append(one.index)
        if len(group1) > 2 and len(group1) < len(indi1):
            break
        else:
            indi1.rotate(rax, a=-1 * rang, center='COM', rotate_cell=False)
        n += 1
    indi2.rotate(rax, a=rang, center='COM', rotate_cell=False)
    if debug:
        print 'Group1 size = ', len(group1)
        print 'Position = ', [0, 0, 0]
        print 'Angle = ', rang
        print 'Axis = ', rax
        print 'Number of tries = ', n + 1
    #Apply concentration forcing if needed
    group2 = Atoms(cell=ind2[0].get_cell(), pbc=ind2[0].get_pbc())
    indices2 = []
    dellist = []
    if Optimizer.forcing == 'Concentration':
        symlist = list(set(group1.get_chemical_symbols()))
        seplist = [[atm for atm in indi2 if atm.symbol == sym]
                   for sym, count in symlist]
        for one in group1:
            sym1 = one.symbol
            listpos = [i for i, s in enumerate(symlist) if s == sym1][0]
            if len(seplist[listpos]) > 0:
                dist = [
                    z
                    for x, y, z in [one.position for one in seplist[listpos]]
                ]
                pos = [
                    i for i, value in enumerate(dist) if value == max(dist)
                ][0]
                group2.append(seplist[listpos][pos])
                indices2.append(seplist[listpos][pos].index)
                del seplist[listpos][pos]
            else:
                dellist.append(one.index)
        if len(dellist) != 0:
            dellist.sort(reverse=True)
            for one in dellist:
                del group1[one]
                del indices1[one]
        #indices2.append(pt2.index)
    else:
        for one in indi2:
            if one.position[2] >= 0:
                group2.append(one)
                indices2.append(one.index)
        while len(group2) < len(group1) - len(dellist):
            #Too many atoms in group 1
            dellist.append(random.choice(group1).index)
        if len(dellist) != 0:
            dellist.sort(reverse=True)
            for one in dellist:
                del group1[one]
                del indices1[one]
        dellist = []
        while len(group1) < len(group2) - len(dellist):
            #Too many atoms in group 2
            dellist.append(random.choice(group2).index)
        if len(dellist) != 0:
            dellist.sort(reverse=True)
            for one in dellist:
                del group2[one]
                del indices2[one]

    other1 = Atoms()
    other2 = Atoms()
    other2 = Atoms(cell=ind2[0].get_cell(), pbc=ind2[0].get_pbc())
    for one in indi2:
        if one.index not in indices2:
            other2.append(one)
    other1 = Atoms(cell=ind1[0].get_cell(), pbc=ind1[0].get_pbc())
    for one in indi1:
        if one.index not in indices1:
            other1.append(one)

    indi1 = group2.copy()
    indi1.extend(other1)
    indi2 = group1.copy()
    indi2.extend(other2)

    #DEBUG: Write crossover to file
    if debug:
        write_xyz(Optimizer.debugfile, group1, 'group1')
        write_xyz(Optimizer.debugfile, other1, 'other1')
        write_xyz(Optimizer.debugfile, group2, 'group2')
        write_xyz(Optimizer.debugfile, other2, 'other2')
        print 'Length of group1 = ', len(group1), 'Length of group2', len(
            group2)

    #DEBUG: Check structure of atoms exchanged
    for sym, c, m, u in Optimizer.atomlist:
        nc = len([atm for atm in indi1 if atm.symbol == sym])
        Optimizer.output.write('CX ROTCT: Individual 1 contains ' + repr(nc) +
                               ' ' + repr(sym) + ' atoms\n')
        nc = len([atm for atm in indi2 if atm.symbol == sym])
        Optimizer.output.write('CX ROTCT: Individual 2 contains ' + repr(nc) +
                               ' ' + repr(sym) + ' atoms\n')

    #Need to have at least one atom of each structure in atomlist to prevent Lammps for erroring
    if Optimizer.forcing != 'Concentration':
        for i in range(len(Optimizer.atomlist)):
            atms1 = [
                inds for inds in indi1
                if inds.symbol == Optimizer.atomlist[i][0]
            ]
            atms2 = [
                inds for inds in indi2
                if inds.symbol == Optimizer.atomlist[i][0]
            ]
            if len(atms1) == 0:
                if len(atms2) == 0:
                    indi1[random.randint(0,
                                         len(indi1) -
                                         1)].symbol == Optimizer.atomlist[i][0]
                    indi2[random.randint(0,
                                         len(indi2) -
                                         1)].symbol == Optimizer.atomlist[i][0]
                else:
                    indi1.append(atms2[random.randint(0, len(atms2) - 1)])
                    indi1.pop(random.randint(0, len(indi1) - 2))
            else:
                if len(atms2) == 0:
                    indi2.append(atms1[random.randint(0, len(atms1) - 1)])
                    indi2.pop(random.randint(0, len(indi2) - 2))
    indi1.rotate(rax, a=-1 * rang, center='COM', rotate_cell=False)
    indi2.rotate(rax, a=-1 * rang, center='COM', rotate_cell=False)
    indi1.translate(com1)
    indi2.translate(com2)

    if Optimizer.structure != 'Defect':
        cm = indi1.get_center_of_mass()
        cell = numpy.maximum.reduce(indi1.get_cell())
        cop = [cell[0] / float(2), cell[1] / float(2), cell[2] / float(2)]
        indi1.translate(-1 * cm)
        indi1.translate(cop)
        cm = indi2.get_center_of_mass()
        cell = numpy.maximum.reduce(indi2.get_cell())
        cop = [cell[0] / float(2), cell[1] / float(2), cell[2] / float(2)]
        indi2.translate(-1 * cm)
        indi2.translate(cop)

    ind1[0] = indi1
    ind2[0] = indi2

    #Check structure and number of atoms in crystal
    if Optimizer.structure == 'Defect':
        solid1 = Atoms()
        solid1.extend(ind1[0])
        solid1.extend(ind1.bulki)
        solid2 = Atoms()
        solid2.extend(ind1[0])
        solid2.extend(ind2.bulki)
        for sym, c, m, u in Optimizer.atomlist:
            nc = len([atm for atm in solid1 if atm.symbol == sym])
            Optimizer.output.write('CX ROTCT: CIBS 1 configuration contains ' +
                                   repr(nc) + ' ' + repr(sym) + ' atoms\n')
            nc = len([atm for atm in solid2 if atm.symbol == sym])
            Optimizer.output.write('CX ROTCT: CIBS 2 configuration contains ' +
                                   repr(nc) + ' ' + repr(sym) + ' atoms\n')
    return ind1, ind2
Example #14
0
File: newclus.py Project: m-yu/MAST
def newclus(ind1, ind2, Optimizer):
    """Select a box in the cluster configuration"""
    if 'CX' in Optimizer.debug:
        debug = True
    else:
        debug = False
    Optimizer.output.write('Box Cluster Cx between individual '+repr(ind1.index)+' and individual '+repr(ind2.index)+'\n')
    
    #Perserve starting conditions of individual
    solid1 = ind1[0].copy()
    solid2 = ind2[0].copy()
    cello1 = ind1[0].get_cell()
    cello2 = ind2[0].get_cell()
    cell1 = numpy.maximum.reduce(solid1.get_positions())
    cell1m = numpy.minimum.reduce(solid1.get_positions())
    cell2 = numpy.maximum.reduce(solid2.get_positions())
    cell2m = numpy.minimum.reduce(solid2.get_positions())
    cell = numpy.minimum(cell1,cell2)
    pbc1 = solid1.get_pbc()
    pbc2 = solid2.get_pbc()
    #Get starting concentrations and number of atoms
    nat1 = len(solid1)
    nat2 = len(solid2)

    # Pick a origin point for box in the cell
    pt1 = random.choice(solid1)
    pt1f = [(pt1.position[i]-cell1m[i])/cell1[i] for i in range(3)]
    pt2 = [pt1f[i]*cell2[i]+cell2m[i] for i in range(3)]
    solid2.append(Atom(position=pt2))
    pt2=solid2[len(solid2)-1]
    #Find max neighborsize of circle cut
    r = random.uniform(0,min(nat1,nat2)/5.0)
    if debug:
        print 'DEBUG CX: Point one =', pt1.position
        print 'DEBUG CX: Point two =', pt2.position
    #Find atoms within sphere of neighborsize r for both individuals
    #Make sure that crossover is only selection of atoms not all
    while True:
        ctoff = [r for on in solid1]
        nl = NeighborList(ctoff, bothways=True, self_interaction=False)
        nl.update(solid1)
        indices1, offsets = nl.get_neighbors(pt1.index)
        if len(indices1)==0:
            r = r*1.2
        elif len(indices1) < nat1*.75:
            break
        else:
            r = r*0.8
    if debug:
        print 'Neighborsize of box = '+repr(r)+'\nPosition in solid1 = '+repr(pt1.position)+'\nPosition in solid2 = '+repr(pt2.position)
    group1 = Atoms(cell=solid1.get_cell(),pbc=solid1.get_pbc())
    group1.append(pt1)
    indices1a=[pt1.index]
    for index, d in zip(indices1,offsets):
        if index not in indices1a:
            index = int(index)
            pos = solid1[index].position + numpy.dot(d,solid1.get_cell())
            group1.append(Atom(symbol=solid1[index].symbol,position=pos))
            indices1a.append(index)
    indices1=indices1a
    ctoff = [r for on in solid2]
    nl = NeighborList(ctoff, bothways=True, self_interaction=False)
    nl.update(solid2)
    indices2, offsets = nl.get_neighbors(pt2.index)
    group2 = Atoms(cell=solid2.get_cell(),pbc=solid2.get_pbc())
    indices2a = []
    for index, d in zip(indices2,offsets):
        if index not in indices2a:
            index = int(index)
            pos = solid2[index].position + numpy.dot(d,solid2.get_cell())
            group2.append(Atom(symbol=solid2[index].symbol,position=pos))
            indices2a.append(index)
    indices2=indices2a
    if len(indices2)==0:
        for one in group1:
            while True:
                sel = random.choice(solid2)
                if sel.symbol==one.symbol:
                    if sel.index not in indices2:
                        group2.append(sel)
                        indices2.append(sel.index)
                        break

    if Optimizer.forcing=='Concentration':
        symlist = list(set(group1.get_chemical_symbols()))
        seplist = [[atm for atm in group2 if atm.symbol == sym] for sym in symlist]
        group2n=Atoms(cell=group2.get_cell(),pbc=group2.get_pbc())
        indices2n = []
        dellist = []
        for one in group1:
            sym1=one.symbol
            listpos=[i for i,s in enumerate(symlist) if s==sym1][0]
            if len(seplist[listpos]) > 0:
                pos = random.choice(range(len(seplist[listpos])))
                group2n.append(seplist[listpos][pos])
                indices2n.append(indices2[seplist[listpos][pos].index])
                del seplist[listpos][pos]
            else:
                dellist.append(one.index)
        if len(dellist) != 0:
            dellist.sort(reverse=True)
            for one in dellist:
                del group1[one]
                del indices1[one]
        indices2n.append(pt2.index)
        indices2=indices2n
        group2=group2n.copy()
    else:
        dellist = []
        while len(group2) < len(group1)-len(dellist):
            #Too many atoms in group 1
            dellist.append(random.choice(group1).index)
        if len(dellist) != 0:
            dellist.sort(reverse=True)
            for one in dellist:
                del group1[one]
                del indices1[one]
        dellist = []
        while len(group1) < len(group2)-len(dellist):
            #Too many atoms in group 2
            dellist.append(random.choice(group2).index)
        if len(dellist) != 0:
            dellist.sort(reverse=True)
            for one in dellist:
                del group2[one]
                del indices2[one]
            
    other2 = Atoms(cell=solid2.get_cell(),pbc=solid2.get_pbc())
    for one in solid2:
        if one.index not in indices2:
            other2.append(one)
    other1 = Atoms(cell=solid1.get_cell(),pbc=solid1.get_pbc())
    for one in solid1:
        if one.index not in indices1:
            other1.append(one)

    #Exchange atoms in sphere and build new solids
    nsolid1 = other1.copy()
    nsolid1.extend(group2.copy())
    nsolid2 = other2.copy()
    nsolid2.extend(group1.copy())

    #DEBUG: Write crossover to file
    if debug: 
        write_xyz(Optimizer.debugfile, nsolid1,'CX(randalloybx):nsolid1')
        write_xyz(Optimizer.debugfile, nsolid2,'CX(randalloybx):nsolid2')


    #DEBUG: Check structure of atoms exchanged
    for sym,c,m,u in Optimizer.atomlist:
        if Optimizer.structure=='Defect':
            nc=len([atm for atm in nsolid1 if atm.symbol==sym])
            nc+=len([atm for atm in ind1.bulki if atm.symbol==sym])
            oc=len([atm for atm in solid1 if atm.symbol==sym])
            oc+=len([atm for atm in ind1.bulki if atm.symbol==sym])
        else:
            nc=len([atm for atm in nsolid1 if atm.symbol==sym])
            oc=len([atm for atm in solid1 if atm.symbol==sym])
        Optimizer.output.write('CX(clustbx):New solid1 contains '+repr(nc)+' '+repr(sym)+' atoms\n')
        if debug: print 'DEBUG CX: New solid1 contains '+repr(nc)+' '+repr(sym)+' atoms'
        if oc != nc:
            #pdb.set_trace()
            print 'CX: Issue in maintaining atom concentration\n Dropping new individual'
            Optimizer.output.write('CX: Issue in maintaining atom concentration\n Dropping new individual 1\n')
            nsolid1 = solid1
    for sym,c,m,u in Optimizer.atomlist:
        if Optimizer.structure=='Defect':
            nc=len([atm for atm in nsolid2 if atm.symbol==sym])
            nc+=len([atm for atm in ind2.bulki if atm.symbol==sym])
            oc=len([atm for atm in solid2 if atm.symbol==sym])
            oc+=len([atm for atm in ind2.bulki if atm.symbol==sym])
        else:
            nc=len([atm for atm in nsolid2 if atm.symbol==sym])
            oc=len([atm for atm in solid2 if atm.symbol==sym])
        Optimizer.output.write('CX(clustbx):New solid2 contains '+repr(nc)+' '+repr(sym)+' atoms\n')
        if debug: print 'DEBUG CX: New solid2 contains '+repr(nc)+' '+repr(sym)+' atoms'
        if oc != nc:
            #pdb.set_trace()
            print 'CX: Issue in maintaining atom concentration\n Dropping new individual'
            Optimizer.output.write('CX: Issue in maintaining atom concentration\n Dropping new individual 2\n')
            solid2.pop()
            nsolid2 = solid2
    if Optimizer.forcing !='Concentration':
        for i in range(len(Optimizer.atomlist)):
            atms1=[inds for inds in nsolid1 if inds.symbol==Optimizer.atomlist[i][0]]
            atms2=[inds for inds in nsolid2 if inds.symbol==Optimizer.atomlist[i][0]]
            if len(atms1)==0:
                if len(atms2)==0:
                    nsolid1[random.randint(0,len(indi1)-1)].symbol==Optimizer.atomlist[i][0]
                    nsolid2[random.randint(0,len(indi2)-1)].symbol==Optimizer.atomlist[i][0]
                else:
                    nsolid1.append(atms2[random.randint(0,len(atms2)-1)])
                    nsolid1.pop(random.randint(0,len(nsolid1)-2))
            else:
                if len(atms2)==0:
                    nsolid2.append(atms1[random.randint(0,len(atms1)-1)])
                    nsolid2.pop(random.randint(0,len(nsolid2)-2))	

    nsolid1.set_cell(cello1)
    nsolid2.set_cell(cello2)
    nsolid1.set_pbc(pbc1)
    nsolid2.set_pbc(pbc2)
    
    ind1[0]=nsolid1.copy()
    ind2[0]=nsolid2.copy()

    return ind1, ind2
Example #15
0
def clustbx(ind1, ind2, Optimizer):
    """Select a box in the cluster configuration
    """
    if 'CX' in Optimizer.debug:
        debug = True
    else:
        debug = False
    Optimizer.output.write('Box Cluster Cx between individual ' +
                           repr(ind1.index) + ' and individual ' +
                           repr(ind2.index) + '\n')

    #Perserve starting conditions of individual
    solid1 = ind1[0].copy()
    solid2 = ind2[0].copy()
    cello1 = ind1[0].get_cell()
    cello2 = ind2[0].get_cell()
    cell1 = numpy.maximum.reduce(
        solid1.get_positions())  #-numpy.minimum.reduce(solid1.get_positions())
    cell2 = numpy.maximum.reduce(
        solid2.get_positions())  #-numpy.minimum.reduce(solid2.get_positions())
    cell = numpy.minimum(cell1, cell2)
    pbc1 = solid1.get_pbc()
    pbc2 = solid2.get_pbc()

    #Get starting concentrations and number of atoms
    nat1 = len(solid1)
    nat2 = len(solid2)

    if Optimizer.alloy == False:
        #Atomlist-based
        concent1 = [c for sym, c, m, u in Optimizer.atomlist]
        concent2 = [c for sym, c, m, u in Optimizer.atomlist]
        symlist = [sym for sym, c, m, u in Optimizer.atomlist]
    else:
        symlist = list(set(solid1.get_chemical_symbols()))
        #Assumes same types of atoms in both solid1 and solid2
        concent1 = []
        for one in symlist:
            atmss = [atm for atm in solid1 if atm.symbol == one]
            concent1.append(len(atmss))
        concent2 = []
        for one in symlist:
            atmss = [atm for atm in solid2 if atm.symbol == one]
            concent2.append(len(atmss))

    # Pick a origin point for box in the cell
    #pt=[random.uniform(0,cell[0]),random.uniform(0,cell[1]),random.uniform(0,cell[2])]
    pt1 = random.choice(solid1).position
    pt2 = random.choice(solid2).position

    #Find max radius of circle cut
    r1 = min([
        min(cell1[0] - pt1[0], pt1[0]),
        min(cell1[1] - pt1[1], pt1[1]),
        min(cell1[2] - pt1[2], pt1[2])
    ])
    r2 = min([
        min(cell2[0] - pt2[0], pt2[0]),
        min(cell2[1] - pt2[1], pt2[1]),
        min(cell2[2] - pt2[2], pt2[2])
    ])
    r = min(r1, r2)
    mcell = min(cell)
    if r > mcell * 0.125:
        r = mcell * 0.125
    elif r == 0.0:
        r = 1.0
    if debug:
        print 'Radius of box = ' + repr(r) + '\nPosition in solid1 = ' + repr(
            pt1) + '\nPosition in solid2 = ' + repr(pt2)

    #Find atoms within sphere of radius r
    solid1.append(Atom(position=pt1))
    dist1 = []
    blist1 = []
    for i in range(len(solid1) - 1):
        d = solid1.get_distance(i, len(solid1) - 1)
        if d < r:
            dist1.append((d, solid1[i]))
        else:
            blist1.append((d, solid1[i]))
    solid1.pop()

    solid2.append(Atom(position=pt2))
    dist2 = []
    blist2 = []
    for i in range(len(solid2) - 1):
        d = solid2.get_distance(i, len(solid2) - 1)
        if d < r:
            dist2.append((d, solid2[i]))
        else:
            blist2.append((d, solid2[i]))
    solid2.pop()

    #Translate spheres to opposite location
    dats1 = Atoms()
    for d, atm in dist1:
        dats1.append(atm)
    dats1.translate(-pt1)
    dats1.translate(pt2)
    dats2 = Atoms()
    for d, atm in dist2:
        dats2.append(atm)
    dats2.translate(-pt2)
    dats2.translate(pt1)

    #Exchange atoms in sphere and build new solids
    nsolid1 = dats2.copy()
    for d, atm in blist1:
        nsolid1.append(atm)
    nsolid2 = dats1.copy()
    for d, atm in blist2:
        nsolid2.append(atm)

    #Identify new number of atoms
    nnat1 = len(nsolid1)
    nnat2 = len(nsolid2)

    if nnat1 > nat1:
        ds = []
        #More atoms in new solid1 means solid2 has less atoms
        #Need to transfer atoms from solid1 to solid2
        #Find atoms that are too close
        for i in range(len(dist2)):
            for j in range(len(dist2), len(nsolid1)):
                ds.append((nsolid1.get_distance(i, j), i))
        #Sort distances by longest to shortest
        ds = sorted(ds, key=lambda one: one[0])
        diff = nnat1 - nat1
        exchangeindices = []
        while len(exchangeindices) < diff:
            #Grab shortest distance in ds list
            d, index = ds.pop()
            if index not in exchangeindices:
                exchangeindices.append(index)
        nnsolid1 = Atoms()
        for i in range(len(nsolid1)):
            if i not in exchangeindices:
                nnsolid1.append(nsolid1[i])
        nnsolid2 = nsolid2.copy()
        for i in exchangeindices:
            #for j in range(3):
            #	position[j]=nsolid2[i].position[j]-pt1[j]+pt2[j]
            position = [
                random.uniform(pt2[0] - r / (2**0.5), pt2[0] + r / (2**0.5)),
                random.uniform(pt2[1] - r / (2**0.5), pt2[1] + r / (2**0.5)),
                random.uniform(pt2[2] - r / (2**0.5), pt2[2] + r / (2**0.5))
            ]
            nnsolid2.append(Atom(symbol=nsolid1[i].symbol, position=position))
        nsolid1 = nnsolid1.copy()
        nsolid2 = nnsolid2.copy()

    elif nnat1 < nat1:
        ds = []
        #More atoms in new solid2 means solid1 has less atoms
        #Need to transfer atoms from solid2 to solid1
        #Find atoms that are too close
        for i in range(len(dist1)):
            for j in range(len(dist1), len(nsolid2)):
                ds.append((nsolid2.get_distance(i, j), i))
        #Sort distances by longest to shortest
        ds = sorted(ds, key=lambda one: one[0])
        diff = nnat2 - nat2
        exchangeindices = []
        while len(exchangeindices) < diff:
            #Grab shortest distance in ds list
            d, index = ds.pop()
            if index not in exchangeindices:
                exchangeindices.append(index)
        nnsolid2 = Atoms()
        for i in range(len(nsolid2)):
            if i not in exchangeindices:
                nnsolid2.append(nsolid2[i])
        nnsolid1 = nsolid1.copy()
        for i in exchangeindices:
            #for j in range(3):
            #	position[j]=nsolid2[i].position[j]-pt1[j]+pt2[j]
            position = [
                random.uniform(pt1[0] - r / (2**0.5), pt1[0] + r / (2**0.5)),
                random.uniform(pt1[1] - r / (2**0.5), pt1[1] + r / (2**0.5)),
                random.uniform(pt1[2] - r / (2**0.5), pt1[2] + r / (2**0.5))
            ]
            nnsolid1.append(Atom(symbol=nsolid2[i].symbol, position=position))
        nsolid1 = nnsolid1.copy()
        nsolid2 = nnsolid2.copy()

    #Number of atoms in each individual should now be preserved
    try:
        if Optimizer.forcing == 'Concentration':
            #Need to check concentrations
            nconcent1 = []
            for one in symlist:
                atmss = [atm for atm in nsolid1 if atm.symbol == one]
                nconcent1.append(len(atmss))
            nconcent2 = []
            for one in symlist:
                atmss = [atm for atm in nsolid2 if atm.symbol == one]
                nconcent2.append(len(atmss))
            #Let's assume a random perturbation to concentration in order to correct this issue
            posd = []
            negd = []
            for i in range(len(nconcent1)):
                diff = nconcent1[i] - concent1[i]
                if diff > 0:
                    posd.append((diff, symlist[i]))
                elif diff < 0:
                    negd.append((diff, symlist[i]))
            for c, sym in negd:
                while c != 0:
                    symr = posd[0][1]
                    rlist = [
                        atm.index for atm in nsolid1 if atm.symbol == symr
                    ]
                    index1 = random.choice(rlist)
                    nsolid1[index1].symbol = sym
                    c += 1
                    posd[0] = (posd[0][0] - 1, posd[0][1])
                    if posd[0][0] == 0:
                        posd = posd[1::]
            #Do the same for solid2
            posd = []
            negd = []
            for i in range(len(nconcent2)):
                diff = nconcent2[i] - concent2[i]
                if diff > 0:
                    posd.append((diff, symlist[i]))
                elif diff < 0:
                    negd.append((diff, symlist[i]))
            for c, sym in negd:
                while c != 0:
                    symr = posd[0][1]
                    rlist = [
                        atm.index for atm in nsolid2 if atm.symbol == symr
                    ]
                    index1 = random.choice(rlist)
                    nsolid2[index1].symbol = sym
                    c += 1
                    posd[0] = (posd[0][0] - 1, posd[0][1])
                    if posd[0][0] == 0:
                        posd = posd[1::]
    except:
        f = open('problem-structures.xyz', 'a')
        write_xyz(f,
                  nsolid1,
                  data='Failed - CX(randalloybx):nsolid1 ' +
                  ind1.history_index)
        write_xyz(f,
                  nsolid2,
                  data='Failed - CX(randalloybx):nsolid2 ' +
                  ind2.history_index)
        nsolid1 = ind1[0].copy()
        nsolid2 = ind2[0].copy()
        f.close()
    #DEBUG: Write crossover to file
    if debug:
        write_xyz(Optimizer.debugfile, nsolid1, 'CX(randalloybx):nsolid1')
        write_xyz(Optimizer.debugfile, nsolid2, 'CX(randalloybx):nsolid2')

    #DEBUG: Check structure of atoms exchanged
    for sym, c, m, u in Optimizer.atomlist:
        nc = len([atm for atm in nsolid1 if atm.symbol == sym])
        Optimizer.output.write('CX(clustbx):New solid1 contains ' + repr(nc) +
                               ' ' + repr(sym) + ' atoms\n')
        nc = len([atm for atm in nsolid2 if atm.symbol == sym])
        Optimizer.output.write('CX(clustbx):New solid2 contains ' + repr(nc) +
                               ' ' + repr(sym) + ' atoms\n')
    if Optimizer.forcing != 'Concentration':
        for i in range(len(Optimizer.atomlist)):
            atms1 = [
                inds for inds in nsolid1
                if inds.symbol == Optimizer.atomlist[i][0]
            ]
            atms2 = [
                inds for inds in nsolid2
                if inds.symbol == Optimizer.atomlist[i][0]
            ]
            if len(atms1) == 0:
                if len(atms2) == 0:
                    nsolid1[random.randint(
                        0,
                        len(indi1) - 1)].symbol == Optimizer.atomlist[i][0]
                    nsolid2[random.randint(
                        0,
                        len(indi2) - 1)].symbol == Optimizer.atomlist[i][0]
                else:
                    nsolid1.append(atms2[random.randint(0, len(atms2) - 1)])
                    nsolid1.pop(random.randint(0, len(nsolid1) - 2))
            else:
                if len(atms2) == 0:
                    nsolid2.append(atms1[random.randint(0, len(atms1) - 1)])
                    nsolid2.pop(random.randint(0, len(nsolid2) - 2))

    nsolid1.set_cell(cello1)
    nsolid2.set_cell(cello2)
    nsolid1.set_pbc(pbc1)
    nsolid2.set_pbc(pbc2)

    ind1[0] = nsolid1.copy()
    ind2[0] = nsolid2.copy()

    return ind1, ind2
Example #16
0
def newclus(ind1, ind2, Optimizer):
    """Select a box in the cluster configuration"""
    if 'CX' in Optimizer.debug:
        debug = True
    else:
        debug = False
    Optimizer.output.write('Box Cluster Cx between individual ' +
                           repr(ind1.index) + ' and individual ' +
                           repr(ind2.index) + '\n')

    #Perserve starting conditions of individual
    solid1 = ind1[0].copy()
    solid2 = ind2[0].copy()
    cello1 = ind1[0].get_cell()
    cello2 = ind2[0].get_cell()
    cell1 = numpy.maximum.reduce(solid1.get_positions())
    cell1m = numpy.minimum.reduce(solid1.get_positions())
    cell2 = numpy.maximum.reduce(solid2.get_positions())
    cell2m = numpy.minimum.reduce(solid2.get_positions())
    cell = numpy.minimum(cell1, cell2)
    pbc1 = solid1.get_pbc()
    pbc2 = solid2.get_pbc()
    #Get starting concentrations and number of atoms
    nat1 = len(solid1)
    nat2 = len(solid2)

    # Pick a origin point for box in the cell
    pt1 = random.choice(solid1)
    pt1f = [(pt1.position[i] - cell1m[i]) / cell1[i] for i in range(3)]
    pt2 = [pt1f[i] * cell2[i] + cell2m[i] for i in range(3)]
    solid2.append(Atom(position=pt2))
    pt2 = solid2[len(solid2) - 1]
    #Find max neighborsize of circle cut
    r = random.uniform(0, min(nat1, nat2) / 5.0)
    if debug:
        print 'DEBUG CX: Point one =', pt1.position
        print 'DEBUG CX: Point two =', pt2.position
    #Find atoms within sphere of neighborsize r for both individuals
    #Make sure that crossover is only selection of atoms not all
    while True:
        ctoff = [r for on in solid1]
        nl = NeighborList(ctoff, bothways=True, self_interaction=False)
        nl.update(solid1)
        indices1, offsets = nl.get_neighbors(pt1.index)
        if len(indices1) == 0:
            r = r * 1.2
        elif len(indices1) < nat1 * .75:
            break
        else:
            r = r * 0.8
    if debug:
        print 'Neighborsize of box = ' + repr(
            r) + '\nPosition in solid1 = ' + repr(
                pt1.position) + '\nPosition in solid2 = ' + repr(pt2.position)
    group1 = Atoms(cell=solid1.get_cell(), pbc=solid1.get_pbc())
    group1.append(pt1)
    indices1a = [pt1.index]
    for index, d in zip(indices1, offsets):
        if index not in indices1a:
            index = int(index)
            pos = solid1[index].position + numpy.dot(d, solid1.get_cell())
            group1.append(Atom(symbol=solid1[index].symbol, position=pos))
            indices1a.append(index)
    indices1 = indices1a
    ctoff = [r for on in solid2]
    nl = NeighborList(ctoff, bothways=True, self_interaction=False)
    nl.update(solid2)
    indices2, offsets = nl.get_neighbors(pt2.index)
    group2 = Atoms(cell=solid2.get_cell(), pbc=solid2.get_pbc())
    indices2a = []
    for index, d in zip(indices2, offsets):
        if index not in indices2a:
            index = int(index)
            pos = solid2[index].position + numpy.dot(d, solid2.get_cell())
            group2.append(Atom(symbol=solid2[index].symbol, position=pos))
            indices2a.append(index)
    indices2 = indices2a
    if len(indices2) == 0:
        for one in group1:
            while True:
                sel = random.choice(solid2)
                if sel.symbol == one.symbol:
                    if sel.index not in indices2:
                        group2.append(sel)
                        indices2.append(sel.index)
                        break

    if Optimizer.forcing == 'Concentration':
        symlist = list(set(group1.get_chemical_symbols()))
        seplist = [[atm for atm in group2 if atm.symbol == sym]
                   for sym in symlist]
        group2n = Atoms(cell=group2.get_cell(), pbc=group2.get_pbc())
        indices2n = []
        dellist = []
        for one in group1:
            sym1 = one.symbol
            listpos = [i for i, s in enumerate(symlist) if s == sym1][0]
            if len(seplist[listpos]) > 0:
                pos = random.choice(range(len(seplist[listpos])))
                group2n.append(seplist[listpos][pos])
                indices2n.append(indices2[seplist[listpos][pos].index])
                del seplist[listpos][pos]
            else:
                dellist.append(one.index)
        if len(dellist) != 0:
            dellist.sort(reverse=True)
            for one in dellist:
                del group1[one]
                del indices1[one]
        indices2n.append(pt2.index)
        indices2 = indices2n
        group2 = group2n.copy()
    else:
        dellist = []
        while len(group2) < len(group1) - len(dellist):
            #Too many atoms in group 1
            dellist.append(random.choice(group1).index)
        if len(dellist) != 0:
            dellist.sort(reverse=True)
            for one in dellist:
                del group1[one]
                del indices1[one]
        dellist = []
        while len(group1) < len(group2) - len(dellist):
            #Too many atoms in group 2
            dellist.append(random.choice(group2).index)
        if len(dellist) != 0:
            dellist.sort(reverse=True)
            for one in dellist:
                del group2[one]
                del indices2[one]

    other2 = Atoms(cell=solid2.get_cell(), pbc=solid2.get_pbc())
    for one in solid2:
        if one.index not in indices2:
            other2.append(one)
    other1 = Atoms(cell=solid1.get_cell(), pbc=solid1.get_pbc())
    for one in solid1:
        if one.index not in indices1:
            other1.append(one)

    #Exchange atoms in sphere and build new solids
    nsolid1 = other1.copy()
    nsolid1.extend(group2.copy())
    nsolid2 = other2.copy()
    nsolid2.extend(group1.copy())

    #DEBUG: Write crossover to file
    if debug:
        write_xyz(Optimizer.debugfile, nsolid1, 'CX(randalloybx):nsolid1')
        write_xyz(Optimizer.debugfile, nsolid2, 'CX(randalloybx):nsolid2')

    #DEBUG: Check structure of atoms exchanged
    for sym, c, m, u in Optimizer.atomlist:
        if Optimizer.structure == 'Defect':
            nc = len([atm for atm in nsolid1 if atm.symbol == sym])
            nc += len([atm for atm in ind1.bulki if atm.symbol == sym])
            oc = len([atm for atm in solid1 if atm.symbol == sym])
            oc += len([atm for atm in ind1.bulki if atm.symbol == sym])
        else:
            nc = len([atm for atm in nsolid1 if atm.symbol == sym])
            oc = len([atm for atm in solid1 if atm.symbol == sym])
        Optimizer.output.write('CX(clustbx):New solid1 contains ' + repr(nc) +
                               ' ' + repr(sym) + ' atoms\n')
        if debug:
            print 'DEBUG CX: New solid1 contains ' + repr(nc) + ' ' + repr(
                sym) + ' atoms'
        if oc != nc:
            #pdb.set_trace()
            print 'CX: Issue in maintaining atom concentration\n Dropping new individual'
            Optimizer.output.write(
                'CX: Issue in maintaining atom concentration\n Dropping new individual 1\n'
            )
            nsolid1 = solid1
    for sym, c, m, u in Optimizer.atomlist:
        if Optimizer.structure == 'Defect':
            nc = len([atm for atm in nsolid2 if atm.symbol == sym])
            nc += len([atm for atm in ind2.bulki if atm.symbol == sym])
            oc = len([atm for atm in solid2 if atm.symbol == sym])
            oc += len([atm for atm in ind2.bulki if atm.symbol == sym])
        else:
            nc = len([atm for atm in nsolid2 if atm.symbol == sym])
            oc = len([atm for atm in solid2 if atm.symbol == sym])
        Optimizer.output.write('CX(clustbx):New solid2 contains ' + repr(nc) +
                               ' ' + repr(sym) + ' atoms\n')
        if debug:
            print 'DEBUG CX: New solid2 contains ' + repr(nc) + ' ' + repr(
                sym) + ' atoms'
        if oc != nc:
            #pdb.set_trace()
            print 'CX: Issue in maintaining atom concentration\n Dropping new individual'
            Optimizer.output.write(
                'CX: Issue in maintaining atom concentration\n Dropping new individual 2\n'
            )
            solid2.pop()
            nsolid2 = solid2
    if Optimizer.forcing != 'Concentration':
        for i in range(len(Optimizer.atomlist)):
            atms1 = [
                inds for inds in nsolid1
                if inds.symbol == Optimizer.atomlist[i][0]
            ]
            atms2 = [
                inds for inds in nsolid2
                if inds.symbol == Optimizer.atomlist[i][0]
            ]
            if len(atms1) == 0:
                if len(atms2) == 0:
                    nsolid1[random.randint(
                        0,
                        len(indi1) - 1)].symbol == Optimizer.atomlist[i][0]
                    nsolid2[random.randint(
                        0,
                        len(indi2) - 1)].symbol == Optimizer.atomlist[i][0]
                else:
                    nsolid1.append(atms2[random.randint(0, len(atms2) - 1)])
                    nsolid1.pop(random.randint(0, len(nsolid1) - 2))
            else:
                if len(atms2) == 0:
                    nsolid2.append(atms1[random.randint(0, len(atms1) - 1)])
                    nsolid2.pop(random.randint(0, len(nsolid2) - 2))

    nsolid1.set_cell(cello1)
    nsolid2.set_cell(cello2)
    nsolid1.set_pbc(pbc1)
    nsolid2.set_pbc(pbc2)

    ind1[0] = nsolid1.copy()
    ind2[0] = nsolid2.copy()

    return ind1, ind2