def view_vibrational_modes(outcar, frequency_index="all", wrap_center=[0.3, 0.3, 0.8]): '''views the Vibrational modes of an OUTCAR file in the "-", "0" and "+" states "''' from ase.visualize import view from ase.io import read from ase.geometry import wrap_positions from ase import Atoms import ase import numpy as np import os if frequency_index == "all": output_file_name = "sample" write_xyz(outcar, output_file_name) atoms = read(output_file_name + ".xyz@:") #print(atoms) a = [] for atom in atoms: atom.wrap(center=wrap_center) a.append(atom) view(atoms) os.remove(output_file_name + ".xyz") elif frequency_index != "all": # for a list of frequency index output_file_name = "sample" new_df = read_vibrational_modes(outcar) Atoms = read(outcar) elements = Atoms.get_chemical_symbols() for index in frequency_index: start = index * 3 * (len(elements) + 2) end = 3 * (len(elements) + 2) df = new_df[start:start + end] File = output_file_name + ".xyz" df.drop(df.columns[4], axis=1).drop(df.columns[5], axis=1).to_csv(File, header=None, index=None, sep=' ', mode='a') atoms = read(output_file_name + ".xyz@:") a = [] for atom in atoms: atom.wrap(center=wrap_center) a.append(atom) view(a) os.remove(output_file_name + ".xyz")
def test_compute_bonds_filter_element_pairs(): """Test filtering of bonds by element pairs.""" atoms = Atoms( symbols=["H", "He", "Mg"], positions=[[0, 0, 0], [0.2, 0.2, 0.2], [0.5, 0.5, 0.5]], cell=np.eye(3), pbc=False, ) atom_radii = np.array([0.4, 0.4, 0.4]) bonds = draw_utils.compute_bonds(atoms, atom_radii) allowed = [("H", "Mg")] allowed = set([(a, b) for a, b in allowed] + [(b, a) for a, b in allowed]) symbols = atoms.get_chemical_symbols() bonds = bonds[[(symbols[i], symbols[j]) in allowed for i, j in bonds[:, 0:2]]] # print(bonds.tolist()) assert np.allclose(bonds, [[0, 2, 0, 0, 0]])
def vib_analysis(model): ''' Returns a list displacemet of bonds/atoms in a trajectory. Parameters: model: Atoms object e.g trajectory file to calculate bond displacement TODO: - Resolve for periodic systems - functionally currently doesn't work ''' atot = Atoms.get_chemical_symbols(self=read(model)) traj = Trajectory(model) for i in range(len(atot) - 1): for j in range(i + 1, len(atot)): distances = [] for atoms in traj: dist = atoms.get_distances(i, j) distances.append(float(dist)) dist_list = distances return dist_list
def get_observable(self, structure: Atoms) -> Dict[str, List[float]]: """ Returns the site occupation factors for a given atomic configuration. Parameters ---------- structure input atomic structure. """ chemical_symbols = np.array(structure.get_chemical_symbols()) sofs = {} for site, indices in self._sites.items(): counts = {species: 0 for species in self._allowed_species[site]} symbols, sym_counts = np.unique(chemical_symbols[indices], return_counts=True) for sym, count in zip(symbols, sym_counts): counts[sym] += count for species in counts.keys(): key = 'sof_{}_{}'.format(site, species) sofs[key] = float(counts[species]) / len(indices) return sofs
def get_energy_correction(symbols, counts): atoms = Atoms(formula) full_symbols = atoms.get_chemical_symbols() symbols = list(set(atoms.get_chemical_symbols())) with open(corrections) as f: d = yaml.load(f) anion = None if 'S' in symbols: anion = 'S' elif 'F' in symbols: anion = 'F' elif 'O' in symbols: anion = 'O' corr_energy = 0 if anion is not None: metal_keys = list(d['Advanced']['UCorrections'][anion].keys()) for i, m in enumerate(symbols): if m in metal_keys: corr_energy += counts[i] * \ d['Advanced']['UCorrections'][anion][m] if anion == 'O': i = symbols.index('O') corr_energy += counts[i] * d['OxideCorrections']['oxide'] return corr_energy
def run_md(self, f, Tmax, steps, n_steps, nmfile=None, displacement=0, min_steps=0, sig=0.34, t=0.1, nm=0, record=False): X, S, Na, cm = hdt.readxyz2(f) if nmfile != None: mode=self.get_mode(nmfile, Na, mn=nm) X=X+mode*np.random.uniform(-displacement,displacement) X=X[0] mol=Atoms(symbols=S, positions=X) mol.set_calculator(ANIENS(self.net,sdmx=20000000.0)) f=os.path.basename(f) T_eff = float(random.randrange(5, Tmax, 1)) # random T (random velocities) from 0K to TK minstep_eff = float(random.randrange(1, min_steps, 1)) # random T (random velocities) from 0K to TK dyn = Langevin(mol, t * units.fs, T_eff * units.kB, 0.01) MaxwellBoltzmannDistribution(mol, T_eff * units.kB) # steps=10000 #10000=1picosecond #Max number of steps to run # n_steps = 1 #Number of steps to run for before checking the standard deviation hsdt_Na=[] evkcal=hdt.evtokcal if record==True: #Records the coordinates at every step of the dynamics fname = f + '_record_' + str(T_eff) + 'K' + '.xyz' #name of file to store coodinated in def printenergy(name=fname, a=mol): """Function to print the potential, kinetic and total energy.""" fil= open(name,'a') Na=a.get_number_of_atoms() c = a.get_positions(wrap=True) fil.write('%s \n comment \n' %Na) for j, i in zip(a, c): fil.write(str(j.symbol) + ' ' + str(i[0]) + ' ' + str(i[1]) + ' ' + str(i[2]) + '\n') fil.close() dyn.attach(printenergy, interval=1) e=mol.get_potential_energy() #Calculate the energy of the molecule. Must be done to get the standard deviation s=mol.calc.stddev stddev = 0 tot_steps = 0 failed = False while (tot_steps <= steps): if stddev > sig and tot_steps > minstep_eff: #Check the standard deviation self.hstd.append(stddev) c = mol.get_positions() s = mol.get_chemical_symbols() Na=mol.get_number_of_atoms() self.Na_train.append(Na) self.coor_train.append(c) self.S_train.append(s) failed=True break else: #if the standard deviation is low, run dynamics, then check it again tot_steps = tot_steps + n_steps dyn.run(n_steps) stddev = evkcal*mol.calc.stddev c = mol.get_positions() s = mol.get_chemical_symbols() e=mol.get_potential_energy() #print("{0:.2f}".format(tot_steps*t),':',"{0:.2f}".format(stddev),':',"{0:.2f}".format(evkcal*e)) return c, s, tot_steps*t, stddev, failed, T_eff
def compare_structures(s1: Atoms, s2: Atoms) -> bool: if len(s1) != len(s2): return False if not np.all(np.isclose(s1.cell, s2.cell)): return False if not np.all( np.isclose(s1.get_scaled_positions(), s2.get_scaled_positions())): return False if not np.all( s1.get_chemical_symbols() == s2.get_chemical_symbols()): return False return True
def get_e_above_hull(formula, energy): atoms = Atoms(formula) full_symbols = atoms.get_chemical_symbols() symbols, counts = np.unique(full_symbols, return_counts=True) # list(set(atoms.get_chemical_symbols())) with MPRester() as m: data = m.get_entries_in_chemsys(symbols, compatible_only=True, property_data=[ 'energy_per_atom', 'unit_cell_formula', 'pretty_formula' ]) PDentries = [] for d in data: d = d.as_dict() PDentries += [PDEntry(d['data']['unit_cell_formula'], d['energy'])] print(d['data']['pretty_formula'], d['energy']) PD = PhaseDiagram(PDentries) # Need to apply MP corrections to +U calculations # MP advanced correction + anion correction #print(energy * 2, energy * 2 + corr_energy * 2) PDE0 = PDEntry(formula, energy) e_hull = PD.get_e_above_hull(PDE0) return e_hull
def random_structure(stoichio, amin, amax, dmin, iwrite=0): # returns pure random structure (ase Atoms) struct = Atoms(stoichio) cell = random_cell(amin, amax) struct.set_cell(cell) symbols = struct.get_chemical_symbols() Nat = len(symbols) flag = 0 niter = 0 while flag == 0: positions = [] for i in range(Nat): pos = [uniform(0., 0.90), uniform(0., 0.90), uniform(-0.2, 0.2)] positions.append(pos) struct.set_scaled_positions(positions) struct2x2x1 = struct * (2, 2, 1) positions_ang = struct2x2x1.get_positions() flag = check_dist(Nat * 2 * 2, positions_ang, dmin) niter = niter + 1 if flag == 1 and iwrite == 1: write(filename="POSCAR", images=struct, format="vasp") write(filename="POSCAR.in", images=struct, format="espresso-in") return struct
def test_struc_from_ase(): from ase import Atoms from ase.calculators.singlepoint import SinglePointCalculator results = { "forces": np.random.randn(20, 3), "energy": np.random.rand(), "stress": np.random.randn(6), } uc = Atoms( ["Pd" for i in range(10)] + ["Ag" for i in range(10)], positions=np.random.rand(20, 3), cell=np.random.rand(3, 3), ) calculator = SinglePointCalculator(uc, **results) uc.set_calculator(calculator) new_struc = Structure.from_ase_atoms(uc) assert np.all(new_struc.species_labels == uc.get_chemical_symbols()) assert np.all(new_struc.positions == uc.get_positions()) assert np.all(new_struc.cell == uc.get_cell()) assert np.all(new_struc.forces == results["forces"]) assert np.all(new_struc.energy == results["energy"]) assert np.all(new_struc.stress == results["stress"])
def assert_structure_compatibility(self, structure: Atoms, vol_tol: float = 1e-5) -> None: """ Raises error if structure is not compatible with ClusterSpace. Todo ---- Add check for if structure is relaxed. Parameters ---------- structure structure to check if compatible with ClusterSpace """ # check volume prim = self.primitive_structure vol1 = prim.get_volume() / len(prim) vol2 = structure.get_volume() / len(structure) if abs(vol1 - vol2) > vol_tol: raise ValueError('Volume per atom of structure does not match the volume of ' 'ClusterSpace.primitive_structure') # check occupations sublattices = self.get_sublattices(structure) sublattices.assert_occupation_is_allowed(structure.get_chemical_symbols()) # check pbc if not all(structure.pbc): raise ValueError('Input structure must have periodic boundary conditions')
def get_pointgroup(atoms: ase.Atoms) -> str: """ uses pymatgen.symmetry.analyzer """ atoms.center() symbs = atoms.get_chemical_symbols() pos = atoms.get_positions() mol = pmg.Molecule(symbs, pos) return pysym.PointGroupAnalyzer(mol).sch_symbol
def test_struc_from_ase(): from ase import Atoms uc = Atoms(['Pd' for i in range(10)] + ['Ag' for i in range(10)], positions=np.random.rand(20, 3), cell=np.random.rand(3, 3)) new_struc = Structure.from_ase_atoms(uc) assert np.all(new_struc.species_labels == uc.get_chemical_symbols()) assert np.all(new_struc.positions == uc.get_positions()) assert np.all(new_struc.cell == uc.get_cell())
def set_up_calculation(db, subdir, syms, AB_stacking, soc, vacuum_dist, D, xc, pp): # Choose separation between layers as if the system was a bulk system # where all layers are the same as the first layer here. # TODO -- is there a better strategy for this? c_sep = get_c_sep(db, syms[0]) latvecs, at_syms, cartpos = make_cell(db, syms, c_sep, vacuum_dist, AB_stacking) system = Atoms(symbols=at_syms, positions=cartpos, cell=latvecs, pbc=True) system.center(axis=2) wann_valence, num_wann = get_wann_valence(system.get_chemical_symbols(), soc) num_bands = get_num_bands(num_wann) holes_per_cell = None qe_config = make_qe_config(system, D, holes_per_cell, soc, num_bands, xc, pp) prefix = make_prefix(syms) work = _get_work(subdir, prefix) wannier_dir = os.path.join(work, "wannier") if not os.path.exists(wannier_dir): os.makedirs(wannier_dir) bands_dir = os.path.join(work, "bands") if not os.path.exists(bands_dir): os.makedirs(bands_dir) dirs = {'scf': wannier_dir, 'nscf': wannier_dir, 'bands': bands_dir} qe_input = {} for calc_type in ['scf', 'nscf', 'bands']: qe_input[calc_type] = build_qe(system, prefix, calc_type, qe_config) _write_qe_input(prefix, dirs[calc_type], qe_input, calc_type) pw2wan_input = build_pw2wan(prefix, soc) pw2wan_path = os.path.join(wannier_dir, "{}.pw2wan.in".format(prefix)) with open(pw2wan_path, 'w') as fp: fp.write(pw2wan_input) bands_post_input = build_bands(prefix) bands_post_path = os.path.join(bands_dir, "{}.bands_post.in".format(prefix)) with open(bands_post_path, 'w') as fp: fp.write(bands_post_input) wannier_input = Winfile(system, qe_config, wann_valence, num_wann) win_path = os.path.join(wannier_dir, "{}.win".format(prefix)) with open(win_path, 'w') as fp: fp.write(wannier_input) return prefix
def get_symbols(chem_sym, stoich): Nat = len(chem_sym) chem_form = "" for i in range(Nat): chem_form = chem_form + chem_sym[i] + str(stoich[i]) atm = Atoms(chem_sym) symbols = atm.get_chemical_symbols() return symbols
def tuple_from_ase(asecell: ase.Atoms): """ Convert an ase cell to a structure tuple. """ cell = asecell.cell.tolist() # Wrap=False to preserve the absolute positions of atoms rel_pos = asecell.get_scaled_positions(wrap=False).tolist() numbers = [ ase.atom.atomic_numbers[symbol] for symbol in asecell.get_chemical_symbols() ] return (cell, rel_pos, numbers)
def createMeta(self, name=None, title=None, authors=None, notes=None, signal_type=None, elements=None, model=None): """ Generate and organize info into a matadata dictionary recognized by hyperspy :returns: nested dictionary of information """ if not name: name = "Unnamed_simulation" if not title: title = name if elements: symbol = Atoms.get_chemical_symbols() for i in range(elements): elements[i] = symbol[i] description = "Simulated material system\n See 'system' for further information." description += "Fermi energy:{}".format(self.fermiEnergy) metadata = {} metadata['General'] = {} metadata['General']['name'] = name metadata['General']['title'] = title metadata['General']['authors'] = authors metadata['General']['notes'] = notes metadata['Signal'] = {} metadata['Signal']['binned'] = True metadata['Signal']['signal_type'] = signal_type metadata['Sample'] = {} metadata['Sample']['elements'] = self.cell.getAtomNumbers() metadata['Sample']['system'] = {} metadata['Sample']['system']['cell'] = {} axes = ['a', 'b', 'c'] for i in range(len(self.cell.lattice)): metadata['Sample']['system']['cell'][ axes[i]] = self.cell.lattice[i] metadata['Sample']['system']['fermiEnergy'] = self.fermiEnergy metadata['Sample']['system']['temperature'] = self.temperature metadata['Sample']['system']['bands'] = self.bands metadata['Sample']['description'] = description return metadata
def test_build(): import numpy as np from ase import Atoms, Atom a = Atoms([Atom('Cu')]) a.positions[:] += 1.0 print(a.get_positions(), a.positions) a = a + a a += a a.append(Atom('C')) a += Atoms([]) a += Atom('H', magmom=1) print(a.get_initial_magnetic_moments()) print(a[0].number) print(a[[0, 1]].get_atomic_numbers()) print(a[np.array([1, 1, 0, 0, 1, 0], bool)].get_atomic_numbers()) print(a[::2].get_atomic_numbers()) print(a.get_chemical_symbols()) del a[2] print(a.get_chemical_symbols()) del a[-2:] print(a.get_chemical_symbols())
def _structure_from_atoms(self, conf: Atoms): """ Returns the input configuration as an icet Structure object. Parameters ---------- conf input configuration Returns ------- atomic configuration """ return self(conf.positions, conf.get_chemical_symbols(), conf.cell, conf.pbc.tolist())
def testRMSE(self): datafile = os.path.join(path, 'test_data/NeuroChemOptimized/all') with open(datafile, 'rb') as f: all_atoms = pickle.load(f) for atoms in all_atoms: # reconstructing Atoms object. # ASE does not support loading pickled object from older version atoms = Atoms(atoms.get_chemical_symbols(), positions=atoms.get_positions()) old_coordinates = copy.deepcopy(atoms.get_positions()) old_coordinates = torch.from_numpy(old_coordinates) atoms.set_calculator(self.calculator) opt = BFGS(atoms) opt.run() coordinates = atoms.get_positions() self.assertEqual(old_coordinates, coordinates)
def test(): # Test that atoms object agrees with calculator calc = Vasp('atom-order-test') atoms = calc.get_atoms() atoms0 = Atoms( [Atom('O', [4, 5, 5]), Atom('C', [5, 5, 5]), Atom('O', [6, 5, 5])], cell=(10, 10, 10)) # Check the atom order if not atoms.get_chemical_symbols() == \ atoms0.get_chemical_symbols(): raise Exception('Atom order not conserved') # Now call the calculator without assigning atoms calc2 = Vasp('atom-order-test') atoms = calc2.get_atoms() # Check the atom order if not atoms.get_chemical_symbols() == \ atoms0.get_chemical_symbols(): raise Exception('Atom order not conserved')
def variable_stoichiometry_generator(symbols, stoichiometry, clean=False, fu=None, mindis=None, nstr=None, maxatomn=None, cspd_file=None, lw=None, format=None, sgn=None, to_primitive=None): tpstru = Atoms(symbols) smbl = [] for smb in tpstru.get_chemical_symbols(): if not (smb in smbl): smbl.append(smb) for stc in stoichiometry: cc = '' for i, n in enumerate(stc): cc += smbl[i] + '{}'.format(n) atomic_structure_generator( symbols=cc, fu=fu, mindis=mindis, nstr=nstr, maxatomn=maxatomn, cspd_file=cspd_file, lw=lw, format=format, clean=clean, sgn=sgn, to_primitive=to_primitive) pass
def test_qe_config(self): syms = ["WSe2", "WSe2", "WSe2"] soc = True vacuum_dist = 20.0 # Angstrom D = 0.5 # V/nm AB_stacking = True xc = 'lda' pp = 'nc' db_path = os.path.join(_base_dir(), "c2dm.db") db = ase.db.connect(db_path) c_sep = get_c_sep(db, syms[0]) latvecs, at_syms, cartpos = make_cell(db, syms, c_sep, vacuum_dist, AB_stacking) system = Atoms(symbols=at_syms, positions=cartpos, cell=latvecs, pbc=True) system.center(axis=2) wann_valence, num_wann = get_wann_valence( system.get_chemical_symbols(), soc) num_bands = get_num_bands(num_wann) qe_config = make_qe_config(system, D, soc, num_bands, xc, pp) #with open('test_build_qe_config_new.json', 'w') as fp: # json.dump(qe_config, fp) with open('test_build_qe_config.json', 'r') as fp: qe_config_expected = json.load(fp) check_qe_config(self, qe_config, qe_config_expected, soc, xc, pp) prefix = 'test' qe_input = build_qe(system, prefix, 'scf', qe_config) #with open('test_build_qe_input_new', 'w') as fp: # fp.write(qe_input) with open('test_build_qe_input', 'r') as fp: qe_input_expected = fp.read() check_qe_input(self, qe_input, qe_input_expected, soc, xc, pp)
def _get_atom_count(self, structure: Atoms) -> Dict[str, float]: """Returns atom counts for each species relative its sublattice. Parameters ---------- structure the configuration that will be analyzed """ occupation = np.array(structure.get_chemical_symbols()) counts = {} for sublattice in self._sublattices: if len(sublattice.chemical_symbols) == 1: continue for symbol in sublattice.chemical_symbols: symbol_count = occupation[sublattice.indices].tolist().count( symbol) counts[symbol] = symbol_count return counts
def get_g2_map(atoms: Atoms, rc: float, nij_max: int, interactions: list, vap: VirtualAtomMap, offsets: np.ndarray, for_prediction=False, print_time=False): if for_prediction: iaxis = 0 else: iaxis = 1 g2_map = np.zeros((nij_max, iaxis + 2), dtype=np.int32) tlist = np.zeros(nij_max, dtype=np.int32) symbols = atoms.get_chemical_symbols() tic = time.time() ilist, jlist, n1 = neighbor_list('ijS', atoms, rc) if print_time: print(f"* ASE neighbor time: {time.time() - tic}") nij = len(ilist) tlist.fill(0) for i in range(nij): symboli = symbols[ilist[i]] symbolj = symbols[jlist[i]] tlist[i] = interactions.index('{}{}'.format(symboli, symbolj)) ilist = np.pad(ilist + 1, (0, nij_max - nij), 'constant') jlist = np.pad(jlist + 1, (0, nij_max - nij), 'constant') n1 = np.pad(n1, ((0, nij_max - nij), (0, 0)), 'constant') n1 = n1.astype(np.float32) for count in range(len(ilist)): if ilist[count] == 0: break ilist[count] = vap.index_map[ilist[count]] jlist[count] = vap.index_map[jlist[count]] g2_map[:, iaxis + 0] = ilist g2_map[:, iaxis + 1] = offsets[tlist] return { "g2.v2g_map": g2_map, "g2.ilist": ilist, "g2.jlist": jlist, "g2.shift": n1 }
def __init__(self, structure: Atoms, calculator: BaseCalculator, temperature: float, user_tag: str = None, boltzmann_constant: float = kB, random_seed: int = None, dc_filename: str = None, data_container: str = None, data_container_write_period: float = 600, ensemble_data_write_interval: int = None, trajectory_write_interval: int = None, sublattice_probabilities: List[float] = None) -> None: self._ensemble_parameters = dict(temperature=temperature) # add species count to ensemble parameters symbols = set([symbol for sub in calculator.sublattices for symbol in sub.chemical_symbols]) for symbol in symbols: key = 'n_atoms_{}'.format(symbol) count = structure.get_chemical_symbols().count(symbol) self._ensemble_parameters[key] = count super().__init__( structure=structure, calculator=calculator, user_tag=user_tag, random_seed=random_seed, data_container=data_container, dc_filename=dc_filename, data_container_class=DataContainer, data_container_write_period=data_container_write_period, ensemble_data_write_interval=ensemble_data_write_interval, trajectory_write_interval=trajectory_write_interval, boltzmann_constant=boltzmann_constant) if sublattice_probabilities is None: self._swap_sublattice_probabilities = self._get_swap_sublattice_probabilities() else: self._swap_sublattice_probabilities = sublattice_probabilities
def create_new_unit_cell(atom_config, mol_ids, cell_lengths, cell_angles, num_cells=[1, 1, 1], filename=None): cell_lengths = [a * b for a, b in zip(cell_lengths, num_cells)] cell_cop = get_center_of_cell(cell_lengths, cell_angles) atom_config_new = copy.deepcopy(atom_config) atom_config_new.translate(cell_cop) convert_to_fractional(atom_config_new, cell_lengths, cell_angles, degrees=True) atoms_to_keep = [] atoms_to_remove = [] mol_ids_new = [] all_xyz = atom_config_new.get_positions() for i in range(len(all_xyz)): pos = all_xyz[i] if np.min(pos) < 0 or np.max(pos) > 1: atoms_to_remove.extend([i]) else: atoms_to_keep.extend([i]) mol_ids_new.extend([mol_ids[i]]) atom_config_new = Atoms( [atom for atom in atom_config_new if atom.index in atoms_to_keep]) config_as_crystal = ase.spacegroup.crystal( atom_config_new.get_chemical_symbols(), atom_config_new.get_positions(), spacegroup='P1', cellpar=cell_lengths + cell_angles) if filename != None: ase.io.write(filename, config_as_crystal) return atom_config_new, mol_ids_new
def visualize(renWin_disp,ren_disp, *args): #renders the result of MOF creation and optimization ren_disp.RemoveAllViewProps() ren_disp.ResetCamera() T= var_topo.get().split('.') C = var_center.get().split('.') L = var_linker.get().split('.') F = var_func.get().split('.') MOFname = '{0}-{1}-{2}'.format(T[0], C[0], L[0]) CIFfile = '{0}-opti.cif'.format(MOFname) CIFfile_func ='{0}-func-{1}-opti.cif'.format(MOFname, F[0] ) XYZfile = '{0}.xyz'.format(MOFname) XYZfile_func = '{0}-func-{1}.xyz'.format(MOFname, F[0] ) if exists(CIFfile_func) and exists(XYZfile_func): MOF = ase.io.read(CIFfile_func) print 'CIF FUNC' elif exists(XYZfile_func) and not exists(CIFfile_func): MOF = ase.io.read(XYZfile_func) print 'XYZ FUNC' elif exists(CIFfile) and exists(XYZfile): MOF = ase.io.read(CIFfile) print 'CIF' elif exists(XYZfile) and not exists(CIFfile): MOF = ase.io.read(XYZfile) print 'XYZ' else: tkMessageBox.showerror('Error', 'No files found for {0}. Please create it.'.format(MOFname)) MOF = Atoms('H', positions=[(0,0,0)], cell=(1,1,1)) i = 0 elements = MOF.get_chemical_symbols() for coordinates in MOF.get_positions(): scaled_coordinates = (5 * coordinates) element_data = elements_dict[elements[i]] radius = (element_data[0]/25) color= element_data[1] sphereActor = makeSphere(radius, scaled_coordinates,color) sphereActor.GetProperty().SetEdgeColor(float('0.'+str(i)),0,0) ren_disp.AddActor(sphereActor) i += 1 ren_disp.ResetCamera() renWin_disp.Render()
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
#~ f = 24 * epsilon * ((2 * c12 - c6) / d2)[:, np.newaxis] * D #~ F1 -= f.sum(0) #~ mmforces[mask] += f #~ return energy, qmforces, mmforces if __name__ == '__main__': from ase import Atoms from ase.cluster.cubic import FaceCenteredCubic from ase.structure import graphene_nanoribbon from ase.visualize import view surfaces = [(1,0,0), (1,1,0)] layers = [3,2] nano = Atoms(FaceCenteredCubic('Pt', surfaces, layers, 4.0)) symbols = nano.get_chemical_symbols() symbols[0] = 'Cu' symbols[12] = 'Cu' nano.set_chemical_symbols(symbols) nano.pop(6) support = graphene_nanoribbon(8, 6, type='armchair', saturated=False) support.translate([-8,-2,-8]) nano.extend(support) support.translate([0,-3.0,0]) nano.extend(support) nano.center(vacuum=10) #~ view(nano) calc = Hybrid() nano.set_calculator(calc) # check subsystems selection from ase.io import write
class Onetep(FileIOCalculator): """Implements the calculator for the onetep linear scaling DFT code. Recomended ASE_ONETEP_COMMAND format is "onetep_executable_name PREFIX.dat > PREFIX.out 2> PREFIX.err" """ implemented_properties = ['energy', 'forces'] # Used to indicate 'parameters' which shouldn't be written to # the onetep input file in the standard <key> : <value> format # for example the NGWF radius is used in the species block and isn't # written elsewhere in the input file _dummy_parameters = ['ngwf_radius', 'xc', 'species_ngwf_radius', 'species_ngwf_number', 'species_solver'] default_parameters = {'cutoff_energy': '1000 eV', 'kernel_cutoff': '1000 bohr', 'ngwf_radius': 12.0} name = 'onetep' def __init__(self, restart=None, ignore_bad_restart_file=False, label=None, command=None, atoms=None, **kwargs): FileIOCalculator.__init__(self, restart, ignore_bad_restart_file, label, atoms, command, **kwargs) self.species = [] self.species_cond = [] self.pseudos = [] self.restart = False self.prefix = label self.directory = '.' def read(self, label): """Read a onetep .out file into the current instance.""" FileIOCalculator.read(self, label) onetep_file = self.label + '.out' warnings = [] try: out = paropen(onetep_file, 'r') except IOError: raise ReadError('Could not open output file "%s"' % onetep_file) # keep track of what we've read in read_lattice = False read_species = False read_positions = False line = out.readline() if self.atoms is None: self.atoms = Atoms() self.atoms.calc = self while line: clean_line = line.strip().lower() if '%block lattice_cart' in clean_line: self._read_lattice(out) read_lattice = True elif '%block species_pot' in clean_line: self._read_species_pot(out) elif '%block species' in clean_line: self._read_species(out) read_species = True elif '%block positions_abs' in clean_line: self._read_positions(out) read_positions = True elif '%block species_cond' in clean_line: self._read_species_cond(out) elif 'warn' in line.lower(): warnings.append(line) line = out.readline() out.close() if warnings: warn('WARNING: %s contains warnings' % onetep_file) for warning in warnings: warn(warning) if not (read_lattice and read_species and read_positions): raise ReadError('Failed to read in essential calculation' ' data from output file "%s"' % onetep_file) self.read_results(label) def read_results(self): FileIOCalculator.read_results(self) onetep_file = self.label + '.out' warnings = [] try: out = paropen(onetep_file, 'r') except IOError: raise ReadError('Could not open output file "%s"' % onetep_file) line = out.readline() while line: if '| Total' in line: self.results['energy'] = Hartree * float(line.split()[-2]) elif ('Element Atom Cartesian components (Eh/a)' in line): self._read_forces(out) elif 'warn' in line.lower(): warnings.append(line) line = out.readline() if warnings: warn('WARNING: %s contains warnings' % onetep_file) for warning in warnings: warn(warning) def _read_lattice(self, out): """ read the lattice parameters out of a onetep .out formatted file stream""" axes = [] l = out.readline() # onetep assumes lengths are in atomic units by default conv_fac = Bohr if 'ang' in l: l = out.readline() conv_fac = 1.0 elif 'bohr' in l: l = out.readline() for _ in range(0, 3): l = l.strip() p = l.split() if len(p) != 3: raise ReadError('Malfromed Lattice block line "%s"' % l) try: axes.append([conv_fac * float(comp) for comp in p[0:3]]) except ValueError: raise ReadError("Can't parse line \"%s\" in axes block" % l) l = out.readline() self.atoms.set_cell(axes) def _read_positions(self, out): """Read the contents of a positions_abs block into the calculator's atoms object, setting both species and positions. Tries to strip out comment lines and is aware of angstom vs. bohr""" line = out.readline() # onetep assumes lengths are in atomic units by default conv_fac = Bohr if 'ang' in line: line = out.readline() conv_fac = 1.0 elif 'bohr' in line: line = out.readline() symbols = [] positions = [] while '%endblock' not in line.lower(): line = line.strip() if line[0] != '#': atom, suffix = line.split(None, 1) pos = suffix.split(None, 3)[0:3] try: pos = [conv_fac * float(p) for p in pos] except ValueError: raise ReadError('Malformed position line "%s"', line) symbols.append(atom) positions.append(pos) line = out.readline() self.atoms.set_chemical_symbols(symbols) self.atoms.set_positions(positions) def _read_species(self, out): """ Read in species block from a onetep output file""" line = out.readline().strip() species = [] while '%endblock' not in line.lower(): atom, element, z, nngwf, ngwf_radius = line.split(None, 5) z = int(z) nngwf = int(nngwf) ngwf_radius = float(ngwf_radius) species.append((atom, element, z, nngwf, ngwf_radius,)) line = out.readline().strip() self.set_species(species) def _read_species_pot(self, out): """ Read in pseudopotential information from a onetep output file""" line = out.readline().strip() pots = [] while '%endblock' not in line.lower() and len(line) > 0: atom, suffix = line.split(None, 1) filename = suffix.split('#', 1)[0].strip() filename = filename.replace('"', '') # take out quotes filename = filename.replace("'", '') pots.append((atom, filename,)) line = out.readline().strip() if len(line) == 0: raise ReadError('End of file while reading potential block') self.set_pseudos(pots) def _read_species_cond(self, out): """ Read in conduction species block from a onetep output file""" line = out.readline().strip() species_cond = [] while '%endblock' not in line.lower(): atom, element, z, nngwf, ngwf_radius = line.split(None, 5) z = int(z) nngwf = int(nngwf) ngwf_radius = float(ngwf_radius) species_cond.append((atom, element, z, nngwf, ngwf_radius, )) line = out.readline().strip() self.set_species_cond(species_cond) def _read_forces(self, out): """ Extract the computed forces from a onetep output file""" forces = [] atomic2ang = Hartree / Bohr while True: line = out.readline() fields = line.split() if len(fields) > 6: break while len(fields) == 7: force = [float(fcomp) * atomic2ang for fcomp in fields[-4:-1]] forces.append(force) line = out.readline() fields = line.split() self.results['forces'] = array(forces) def _generate_species_block(self): """Create a default onetep species block, use -1 for the NGWF number to trigger automatic NGWF number assigment using onetep's internal routines.""" # check if we need to do anything. if len(self.species) == len(self.atoms.get_chemical_symbols()): return parameters = self.parameters self.species = [] atoms = self.atoms default_ngwf_radius = self.parameters['ngwf_radius'] for sp in set(zip(atoms.get_atomic_numbers(), atoms.get_chemical_symbols())): try: ngrad = parameters['species_ngwf_radius'][sp[1]] except KeyError: ngrad = default_ngwf_radius try: ngnum = parameters['species_ngwf_number'][sp[1]] except KeyError: ngnum = -1 self.species.append((sp[1], sp[1], sp[0], ngnum, ngrad)) def set_pseudos(self, pots): """ Sets the pseudopotential files used in this dat file TODO: add some verification - do the psuedos imply the same functional as we're using?""" self.pseudos = deepcopy(pots) def set_atoms(self, atoms): self.atoms = atoms def set_species(self, sp): """ Sets the species in the current dat instance, in onetep this includes both atomic number information as well as NGWF parameters like number and cut off radius""" self.species = deepcopy(sp) def set_species_cond(self, spc): """ Sets the conduction species in the current dat instance, in onetep this includes both atomic number information as well as NGWF parameters like number and cut off radius""" self.species_cond = deepcopy(spc) def write_input(self, atoms, properties=None, system_changes=None): """Only writes the input .dat file and return This can be useful if one quickly needs to prepare input files for a cluster where no python or ASE is available. One can than upload the file manually and read out the results using Onetep().read(). """ if atoms is None: atoms = self.atoms if self.restart: self.parameters['read_tightbox_ngwfs'] = True self.parameters['read_denskern'] = True self._generate_species_block() self._write_dat() def get_forces(self, atoms=None): self.parameters['write_forces'] = True return FileIOCalculator.get_forces(self, atoms) def _write_dat(self, force_write=True): """This export function write minimal information to a .dat file. If the atoms object is a trajectory, it will take the last image. """ filename = self.label + '.dat' if self.atoms is None: raise Exception('No associated atoms object.') atoms = self.atoms parameters = self.parameters if isfile(filename) and not force_write: raise Exception('Target input file already exists.') if 'xc' in parameters and 'xc_functional' in parameters \ and parameters['xc'] != parameters['xc_functional']: raise Exception('Conflicting functionals defined! %s vs. %s' % (parameters['xc'], parameters['xc_functional'])) fd = open(filename, 'w') fd.write('######################################################\n') fd.write('#ONETEP .dat file: %s\n' % filename) fd.write('#Created using the Atomic Simulation Environment (ASE)\n') fd.write('######################################################\n\n') fd.write('%BLOCK LATTICE_CART\n') fd.write('ang\n') for line in atoms.get_cell(): fd.write(' %.10f %.10f %.10f\n' % tuple(line)) fd.write('%ENDBLOCK LATTICE_CART\n\n\n') keyword = 'POSITIONS_ABS' positions = atoms.get_positions() pos_block = [('%s %8.6f %8.6f %8.6f' % (x, y[0], y[1], y[2])) for (x, y) in zip(atoms.get_chemical_symbols(), positions)] fd.write('%%BLOCK %s\n' % keyword) fd.write('ang\n') for line in pos_block: fd.write(' %s\n' % line) fd.write('%%ENDBLOCK %s\n\n' % keyword) keyword = 'SPECIES' sp_block = [('%s %s %d %d %8.6f' % sp) for sp in self.species] fd.write('%%BLOCK %s\n' % keyword) for line in sp_block: fd.write(' %s\n' % line) fd.write('%%ENDBLOCK %s\n\n' % keyword) keyword = 'SPECIES_POT' fd.write('%%BLOCK %s\n' % keyword) for sp in self.pseudos: fd.write(' %s "%s"\n' % (sp[0], sp[1])) fd.write('%%ENDBLOCK %s\n\n' % keyword) keyword = 'SPECIES_ATOMIC_SET' fd.write('%%BLOCK %s\n' % keyword) for sym in set(self.atoms.get_chemical_symbols()): try: atomic_string = parameters['species_solver'][sym] except KeyError: atomic_string = 'SOLVE' fd.write(' %s "%s"\n' % (sym, atomic_string)) fd.write('%%ENDBLOCK %s\n\n' % keyword) for p in parameters: if parameters[p] is not None and \ p.lower() not in self._dummy_parameters: fd.write('%s : %s\n' % (p, parameters[p])) if p.upper() == 'XC': # Onetep calls XC something else... fd.write('xc_functional : %s\n' % parameters[p]) fd.close() def __repr__(self): """Returns generic, fast to capture representation of ONETEP settings along with atoms object. """ expr = '' expr += '-----------------Atoms--------------------\n' if self.atoms is not None: expr += str('%20s\n' % self.atoms) else: expr += 'None\n' expr += '\n-----------------Species---------------------\n' expr += str(self.species) expr += '\n-----------------Pseudos---------------------\n' expr += str(self.pseudos) expr += '\n-----------------Options------------\n' for key in self.parameters: expr += '%20s : %s\n' % (key, self.parameters[key]) return expr def set_label(self, label): """The label is part of each seed, which in turn is a prefix in each ONETEP related file. """ self.label = label self.prefix = label
def write_pw_in(d,a,p): if 'iofile' in p.keys() : # write special varians of the pw input fh=open(os.path.join(d,p['iofile']+'.in'),'w') else : # write standard pw input fh=open(os.path.join(d,'pw.in'),'w') # ---------------------------------------------------------- # CONTROL section # ---------------------------------------------------------- fh.write(' &CONTROL\n') fh.write(" calculation = '%s',\n" % p['calc']) pwin_k=['tstress', 'tprnfor','nstep','pseudo_dir','outdir', 'wfcdir', 'prefix','forc_conv_thr', 'etot_conv_thr'] write_section_params(fh, pwin_k, p) fh.write(' /\n') # ---------------------------------------------------------- # SYSTEM section # ---------------------------------------------------------- fh.write(' &SYSTEM\n') if p['use_symmetry'] : # Need to use symmetry properly # create a dummy atoms object for primitive cell primcell=write_cell_params(fh,a,p) if primcell : # primitive cell has been found - let us use it cr=Atoms(cell=primcell[0],scaled_positions=primcell[1],numbers=primcell[2],pbc=True) else : # no primitive cell found - drop the symmetry cr=a else : cr=a p['ibrav']=0 fh.write(" nat = %d,\n" % (cr.get_number_of_atoms())) fh.write(" ntyp = %d,\n" % (len(set(cr.get_atomic_numbers())))) pwin_k=['ecutwfc','ibrav','nbnd','occupations','degauss','smearing','ecutrho','nbnd'] # must also take into account degauss and smearing write_section_params(fh, pwin_k, p) fh.write(' /\n') # ---------------------------------------------------------- # ELECTRONS section # ---------------------------------------------------------- fh.write(' &ELECTRONS\n') # must also take into account mixing_beta mixing_mode and diagonalization pwin_k=['conv_thr','mixing_beta','mixing_mode','diagonalization', 'mixing_ndim','electron_maxstep'] write_section_params(fh, pwin_k, p) fh.write(' /\n') # ---------------------------------------------------------- # | IONS section # ---------------------------------------------------------- if p['calc'] in ['vc-relax', 'vc-md', 'md', 'relax']: fh.write(' &IONS\n') pwin_k=['ion_dynamics','ion_positions', 'phase_space', 'pot_extrapolation'] write_section_params(fh, pwin_k, p) fh.write(' /\n') # ---------------------------------------------------------- # | CELL section # ---------------------------------------------------------- if p['calc'] in ['vc-relax', 'vc-md']: fh.write('&CELL\n') pwin_k=['cell_dynamics','press', 'cell_dofree'] write_section_params(fh, pwin_k, p) fh.write('/\n') # ---------------------------------------------------------- # Card: ATOMIC_SPECIES # ---------------------------------------------------------- fh.write('ATOMIC_SPECIES\n') xc=p['xc'] pp_type=p['pp_type'] pp_format=p['pp_format'] # we check if the desired potential exists. Get the PP locations if 'ESPRESSO_PSEUDO' in os.environ: pppaths = os.environ['ESPRESSO_PSEUDO'] else: pppaths = p['pseudo_dir'] # default pppaths = pppaths.split(':') # search for element PP in each location (in principle with QE only one location) for nm, mass in set(zip(cr.get_chemical_symbols(),cr.get_masses())): name = "%s_%s_%s.%s" % (nm, xc, pp_type, pp_format) found = False for path in pppaths: filename = os.path.join(path, name) match = glob.glob(filename) if match: # the exact name as expected found = True name = match[0] if not found: # a more permissive name with element.*.format name = "%s.*.%s" % (nm, pp_format) filename = os.path.join(path, name) match = glob.glob(filename) if match: found = True name = match[0] # the first match if not found: # a more permissive name with element_*.format name = "%s_*.%s" % (nm, pp_format) filename = os.path.join(path, name) match = glob.glob(filename) if match: found = True name = match[0] # the first match if not found: # a more permissive name with just the element_* name = "%s_*" % (nm) filename = os.path.join(path, name) match = glob.glob(filename) if match: found = True name = match[0] # the first match if not found: # a more permissive name with just the element.* name = "%s.*" % (nm) filename = os.path.join(path, name) match = glob.glob(filename) if match: found = True name = match[0] # the first match if not found: raise RuntimeError('Espresso: No pseudopotential for %s. Aborting.' % nm) fh.write(" %s %g %s \n" % (nm, mass, os.path.basename(name))) # ---------------------------------------------------------- # Card: ATOMIC_POSITIONS # ---------------------------------------------------------- fh.write('ATOMIC_POSITIONS crystal\n') # Now we can write it out for n,v in zip(cr.get_chemical_symbols(),cr.get_scaled_positions()): fh.write(" %s %g %g %g\n" % (n, v[0], v[1], v[2])) # ---------------------------------------------------------- # Card: CELL_PARAMETERS # ---------------------------------------------------------- # Write out only if ibrav==0 - no symmetry used if not p['use_symmetry'] or p['ibrav']==0: fh.write('CELL_PARAMETERS angstrom\n') for v in cr.get_cell(): fh.write(' %f %f %f\n' % tuple(v)) # ---------------------------------------------------------- # Card: K_POINTS # ---------------------------------------------------------- if p['kpt_type'] in ['automatic','edos'] : fh.write('K_POINTS %s\n' % 'automatic') else : fh.write('K_POINTS %s\n' % p['kpt_type']) if p['kpt_type'] is 'automatic': fh.write(' %d %d %d %d %d %d\n' % (tuple(p['kpts'])+tuple(p['kpt_shift']))) elif p['kpt_type'] is 'edos': fh.write(' %d %d %d %d %d %d\n' % (tuple(p['nkdos'])+tuple([0,0,0]))) elif not p['kpt_type'] is 'gamma': write_q_path(fh,p['qpath'],p['points']) fh.close()
import numpy as np from ase import Atoms, Atom a = Atoms([Atom('Cu')]) a.positions[:] += 1.0 print a.get_positions(), a.positions a=a+a a+=a a.append(Atom('C')) a += Atoms([]) a += Atom('H', magmom=1) print a.get_initial_magnetic_moments() print a[0].number print a[[0,1]].get_atomic_numbers() print a[np.array([1,1,0,0,1], bool)].get_atomic_numbers() print a[::2].get_atomic_numbers() print a.get_chemical_symbols() del a[2] print a.get_chemical_symbols() del a[-2:] print a.get_chemical_symbols()
def rotate(individual1, individual2, conserve_composition=True): """Rotates the two individuals around their centers of mass, splits them in half at the xy-plane, then splices them together. Maintains number of atoms. Args: individual1 (Individual): The first parent individual2 (Individual): The second parent conserve_composition (bool): default True. If True, conserves composition. Returns: Individual: The first child Individual: The second child The children are returned without indicies. """ # Preserve starting conditions of individual ind1c = individual1.copy() ind2c = individual2.copy() # Translate individuals so COM is at (0, 0, 0) com1 = ind1c.get_center_of_mass() ind1c.translate(-1 * com1) com2 = ind2c.get_center_of_mass() ind2c.translate(-1 * com2) # Select random axis and random angle and rotate individuals for _ in range(0, 10): rax = random.choice(['x', '-x', 'y', '-y', 'z', '-z']) rang = random.random() * 90 ind1c.rotate(rax, a=rang, center='COM', rotate_cell=False) # Search for atoms in individual 1 that are above the xy plane above_xy_plane1 = Atoms(cell=individual1.get_cell(), pbc=individual1.get_pbc()) indices1 = [] for atom in ind1c: if atom.z >= 0: above_xy_plane1.append(atom) indices1.append(atom.index) if len(above_xy_plane1) < 2 or len(above_xy_plane1) > len(ind1c): # Try again; unrotate ind1c ind1c.rotate(rax, a=-1*rang, center='COM', rotate_cell=False) else: break ind2c.rotate(rax, a=rang, center='COM', rotate_cell=False) # Generate `above_xy_plane2`, with the same concentration as `above_xy_plane1` if needed above_xy_plane2 = Atoms(cell=individual2.get_cell(), pbc=individual2.get_pbc()) indices2 = [] dellist = [] if conserve_composition: symbols = list(set(above_xy_plane1.get_chemical_symbols())) # The below list contains atoms from ind2c, whereas `above_xy_plane1` contains atoms from ind1c atoms_by_symbol = {sym: [atm for atm in ind2c if atm.symbol == sym] for sym in symbols} for atom in above_xy_plane1: if len(atoms_by_symbol[atom.symbol]) > 0: # Get the atom from `atoms_by_symbol` that has the same type as `atom` and the largest `z` value dist = [atom.z for atom in atoms_by_symbol[atom.symbol]] pos = dist.index(max(dist)) above_xy_plane2.append(atoms_by_symbol[atom.symbol][pos]) indices2.append(atoms_by_symbol[atom.symbol][pos].index) del atoms_by_symbol[atom.symbol][pos] else: dellist.append(atom.index) if dellist: dellist.sort(reverse=True) for atom_index in dellist: del above_xy_plane1[atom_index] del indices1[atom_index] else: for atom in ind2c: if atom.z >= 0: above_xy_plane2.append(atom) indices2.append(atom.index) while len(above_xy_plane2) < len(above_xy_plane1)-len(dellist): # Too many atoms in above_xy_plane1 dellist.append(random.choice(above_xy_plane1).index) if dellist: dellist.sort(reverse=True) for atom in dellist: del above_xy_plane1[atom] del indices1[atom] dellist = [] while len(above_xy_plane1) < len(above_xy_plane2)-len(dellist): # Too many atoms in above_xy_plane2 dellist.append(random.choice(above_xy_plane2).index) if dellist: dellist.sort(reverse=True) for atom in dellist: del above_xy_plane2[atom] del indices2[atom] below_xy_plane1 = Atoms() below_xy_plane2 = Atoms() below_xy_plane2 = Atoms(cell=individual2.get_cell(), pbc=individual2.get_pbc()) for atom in ind2c: if atom.index not in indices2: below_xy_plane2.append(atom) below_xy_plane1 = Atoms(cell=individual1.get_cell(), pbc=individual1.get_pbc()) for atom in ind1c: if atom.index not in indices1: below_xy_plane1.append(atom) child1 = above_xy_plane2.copy() child1.extend(below_xy_plane1) child2 = above_xy_plane1.copy() child2.extend(below_xy_plane2) # Need to have at least one atom of each specie in atomlist to prevent LAMMPS from erroring if not conserve_composition: for i in range(len(individual1)): atoms1 = [atom for atom in child1 if atom.symbol == individual1[i]] atoms2 = [atom for atom in child2 if atom.symbol == individual1[i]] if len(atoms1) == 0 and len(atoms2) == 0: random.choice(child1).symbol = individual1[i].symbol random.choice(child2).symbol = individual1[i].symbol elif len(atoms1) == 0 and len(atoms2) != 0: del child1[random.randint(0, len(child1))] child1.append(random.choice(atoms2)) elif len(atoms1) != 0 and len(atoms2) == 0: del child2[random.randint(0, len(child2))] child2.append(random.choice(atoms1)) # Unrotate and untranslate the children child1.rotate(rax, a=-1*rang, center='COM', rotate_cell=False) child2.rotate(rax, a=-1*rang, center='COM', rotate_cell=False) child1.translate(com1) child2.translate(com2) full_child1 = individual1.copy() full_child1.clear() full_child1.extend(child1) full_child2 = individual2.copy() full_child2.clear() full_child2.extend(child2) return full_child1, full_child2
def write_pw_in(d,a,p): if 'iofile' in p.keys() : # write special varians of the pw input fh=open(os.path.join(d,p['iofile']+'.in'),'w') else : # write standard pw input fh=open(os.path.join(d,'pw.in'),'w') # ---------------------------------------------------------- # CONTROL section # ---------------------------------------------------------- fh.write(' &CONTROL\n') fh.write(" calculation = '%s',\n" % p['calc']) pwin_k=['tstress', 'tprnfor','nstep','pseudo_dir','outdir', 'wfcdir', 'prefix','forc_conv_thr', 'etot_conv_thr'] write_section_params(fh, pwin_k, p) fh.write(' /\n') # ---------------------------------------------------------- # SYSTEM section # ---------------------------------------------------------- fh.write(' &SYSTEM\n') if p['use_symmetry'] : # Need to use symmetry properly # create a dummy atoms object for primitive cell primcell=write_cell_params(fh,a,p) if primcell : # primitive cell has been found - let us use it cr=Atoms(cell=primcell[0],scaled_positions=primcell[1],numbers=primcell[2],pbc=True) else : # no primitive cell found - drop the symmetry cr=a else : cr=a p['ibrav']=0 fh.write(" nat = %d,\n" % (cr.get_number_of_atoms())) fh.write(" ntyp = %d,\n" % (len(set(cr.get_atomic_numbers())))) pwin_k=['ecutwfc','ibrav','nbnd','occupations'] write_section_params(fh, pwin_k, p) fh.write(' /\n') # ---------------------------------------------------------- # ELECTRONS section # ---------------------------------------------------------- fh.write(' &ELECTRONS\n') fh.write(' /\n') # ---------------------------------------------------------- # | IONS section # ---------------------------------------------------------- if p['calc'] in ['vc-relax', 'vc-md', 'md', 'relax']: fh.write(' &IONS\n') pwin_k=['ion_dynamics','ion_positions', 'phase_space', 'pot_extrapolation'] write_section_params(fh, pwin_k, p) fh.write(' /\n') # ---------------------------------------------------------- # | CELL section # ---------------------------------------------------------- if p['calc'] in ['vc-relax', 'vc-md']: fh.write('&CELL\n') pwin_k=['cell_dynamics','press', 'cell_dofree'] write_section_params(fh, pwin_k, p) fh.write('/\n') # ---------------------------------------------------------- # Card: ATOMIC_SPECIES # ---------------------------------------------------------- fh.write('ATOMIC_SPECIES\n') xc=p['xc'] pp_type=p['pp_type'] pp_format=p['pp_format'] for nm, mass in set(zip(cr.get_chemical_symbols(),cr.get_masses())): fh.write(" %s %g %s_%s_%s.%s \n" % (nm, mass, nm, xc, pp_type, pp_format)) # ---------------------------------------------------------- # Card: ATOMIC_POSITIONS # ---------------------------------------------------------- fh.write('ATOMIC_POSITIONS crystal\n') # Now we can write it out for n,v in zip(cr.get_chemical_symbols(),cr.get_scaled_positions()): fh.write(" %s %g %g %g\n" % (n, v[0], v[1], v[2])) # ---------------------------------------------------------- # Card: CELL_PARAMETERS # ---------------------------------------------------------- # Write out only if ibrav==0 - no symmetry used if not p['use_symmetry'] or p['ibrav']==0: fh.write('CELL_PARAMETERS angstrom\n') for v in cr.get_cell(): fh.write(' %f %f %f\n' % tuple(v)) # ---------------------------------------------------------- # Card: K_POINTS # ---------------------------------------------------------- if p['kpt_type'] in ['automatic','edos'] : fh.write('K_POINTS %s\n' % 'automatic') else : fh.write('K_POINTS %s\n' % p['kpt_type']) if p['kpt_type'] is 'automatic': fh.write(' %d %d %d %d %d %d\n' % (tuple(p['kpts'])+tuple(p['kpt_shift']))) elif p['kpt_type'] is 'edos': fh.write(' %d %d %d %d %d %d\n' % (tuple(p['nkdos'])+tuple([0,0,0]))) elif not p['kpt_type'] is 'gamma': write_q_path(fh,p['qpath'],p['points']) fh.close()
syms = a4.get_chemical_symbols() assert len(set([i for i in syms if i in anions])) == 2 from ase.ga.element_mutations import MoveDownMutation from ase.ga.element_mutations import MoveUpMutation from ase.ga.element_mutations import MoveRightMutation from ase.ga.element_mutations import MoveLeftMutation a1 = Atoms('SrSrClClClCl') a1.info['confid'] = 1 op = MoveDownMutation(cations, 2, .5) a2, desc = op.get_new_individual([a1]) a2.info['confid'] = 2 syms = a2.get_chemical_symbols() assert 'Ba' in syms assert len(set(syms)) == 3 op = MoveUpMutation(cations, 1, 1.) a3, desc = op.get_new_individual([a2]) syms = a3.get_chemical_symbols() assert 'Ba' not in syms assert len(set(syms)) == 2 cations = ['Co', 'Ni', 'Cu'] a1 = Atoms('NiNiBrBr') a1.info['confid'] = 1 op = MoveRightMutation(cations, 1, 1.) a2, desc = op.get_new_individual([a1]) a2.info['confid'] = 2
import numpy as np from ase import Atoms, Atom a = Atoms([Atom('Cu')]) a.positions[:] += 1.0 print(a.get_positions(), a.positions) a=a+a a+=a a.append(Atom('C')) a += Atoms([]) a += Atom('H', magmom=1) print(a.get_initial_magnetic_moments()) print(a[0].number) print(a[[0,1]].get_atomic_numbers()) print(a[np.array([1,1,0,0,1], bool)].get_atomic_numbers()) print(a[::2].get_atomic_numbers()) print(a.get_chemical_symbols()) del a[2] print(a.get_chemical_symbols()) del a[-2:] print(a.get_chemical_symbols())
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 {} and individual {}'.format(repr(ind1.index), repr(ind2.index))) # 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 = {}'.format(pt1.position)) print('DEBUG CX: Point two = {}'.format(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 = {}'.format(repr(r))) print('Position in solid1 = {}'.format(repr(pt1.position))) print('Position in solid2 = {}'.format(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 {} {} atoms'.format(repr(nc), repr(sym))) 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 {} and {} atoms'.format(repr(nc), repr(sym))) 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
class Polycrystal(OrthoBox): def __init__(self, boxsize, numcrystallites, crystallitenames, crystallitecenters): super().__init__(boxsize) self.numcrystallites = numcrystallites self.crystaltype = crystallitenames self.crystallitecenters = crystallitecenters self.crystallites = [Atoms() for n in range(numcrystallites)] self.crystalliteids = [[i] for i in range(numcrystallites)] def setgraintypes(self, typemap): self.graintypes = typemap def embedatoms(self, maskcrystal, grainid, keepatoms, compress=True): crystal = maskcrystal.copy() slicecrystal = crystal[keepatoms] natoms = slicecrystal.get_global_number_of_atoms() self.crystalliteids[grainid] = [grainid for i in range(natoms)] self.crystallites[grainid] = slicecrystal def compress(self): polycrystalbox = self.sidelens + self.angles self.polycrystal = Atoms(cell=polycrystalbox, pbc=True) for i, c in enumerate(self.crystallites): cids = self.crystalliteids[i] c.set_tags(cids) self.polycrystal += c self.natoms = self.polycrystal.get_global_number_of_atoms() chemsym = set(self.polycrystal.get_chemical_symbols()) self.chemmap = {c: i + 1 for i, c in enumerate(chemsym)} self.nspecies = len(chemsym) def pruneoverlap(self, criteria=0.5, verbose=False): ''' TODO: remove atoms overlapping assume PBC conditions''' print( "NOTICE: The pruning routine does not accoutn for stoichiometry restrictions." ) cutoff = neighborlist.natural_cutoffs(self.polycrystal) neighbors = neighborlist.NeighborList(cutoff, self_interaction=False, bothways=False) neighbors.update(self.polycrystal) isremoved = [] for a in self.polycrystal: ineigh = neighbors.get_neighbors(a.index) for j in ineigh[0]: r = self.polycrystal.get_distance(a.index, j, mic=True) if r < criteria and j not in isremoved: isremoved.append(j) if verbose: print("Atom ID %i removed due to overlap!" % (j)) del self.polycrystal[isremoved] self.natoms = self.polycrystal.get_global_number_of_atoms()
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