def get_structure_info(self): path = os.path.join(self.maindir, 'sgroup.out') if not os.path.isfile(path): return self.structure.mainfile = path cellpar = self.structure.get('cellpar', None) sym_pos = self.structure.get('sym_pos', {}) sym = sym_pos.get('symbols', None) pos = sym_pos.get('positions', None) if cellpar is None or sym is None or pos is None: return structure = Atoms(cell=cellpar, scaled_positions=pos, symbols=sym, pbc=True) positions = structure.get_positions() positions = positions * ureg.angstrom cell = structure.get_cell() cell = cell * ureg.angstrom return sym, positions, cell
def view_atoms_classifier(image, mg_label, mn_label, o_label, view=True): x = image.reshape(-1, 3) mg = x[2:10, :] mn = x[10:18, :] o = x[18:, :] l = x[0, :] * 30 a = x[1, :] * 180 c = np.hstack((l, a)) atoms = Atoms('H') atoms.set_cell(c) cell = atoms.get_cell() t = np.isnan(cell) tt = np.sum(t) isnan = False if not tt == 0: isnan = True print(cell) print(l) print(a) _, mg_index = torch.max(mg_label, dim=1) _, mn_index = torch.max(mn_label, dim=1) _, o_index = torch.max(o_label, dim=1) mg_index = mg_index.reshape(8, ).detach().cpu().numpy() mn_index = mn_index.reshape(8, ).detach().cpu().numpy() o_index = o_index.reshape(12, ).detach().cpu().numpy() mg_pos = mg[np.where(mg_index)] mn_pos = mn[np.where(mn_index)] o_pos = o[np.where(o_index)] n_mg = len(mg_pos) n_mn = len(mn_pos) n_o = len(o_pos) if n_mg == 0: mg_pos = np.array([0.1667, 0.1667, 0.1667]).reshape(1, 3) n_mg = 1 if n_mn == 0: mn_pos = np.array([0.1667, 0.1667, 0.1667]).reshape(1, 3) n_mn = 1 if n_o == 0: o_pos = np.array([0.1667, 0.1667, 0.1667]).reshape(1, 3) n_o = 1 pos = np.vstack((mg_pos, mn_pos, o_pos)) scaled_pos = back_to_10_cell(pos, n_mg, n_mn, n_o) atoms = back_to_real_cell(scaled_pos, cell, n_mg, n_mn, n_o) atoms.set_pbc([1, 1, 1]) if view: atoms.edit() return atoms, x, isnan
def sphere(atomlist, cell, fill_factor=0.74, radius=None): """Generates a random sphere of particles given an atomlist and radius. Parameters ---------- atomlist : list A list of [sym, n] pairs where sym is the chemical symbol and n is the number of of sym's to include in the individual cell : list The x, y, and z dimensions of the cell which holds the particle. fill_factor : float How densely packed the sphere should be. Ranges from 0 to 1. radius : float The radius of the sphere. If None, estimated from the atomic radii """ if radius is None: radius = get_particle_radius(atomlist, fill_factor) # Create a list of random order of the atoms chemical_symbols = [] for atom in atomlist: chemical_symbols += [atom[0]] * atom[1] random.shuffle(chemical_symbols) unit_vec = np.array([random_three_vector() for i in range(len(chemical_symbols))]) D = radius * np.random.sample(size=len(chemical_symbols)) ** (1.0/3.0) positions = np.array([D]).T * unit_vec indiv = Atoms(symbols=chemical_symbols, positions=positions) if cell is not None: indiv.set_cell(cell) cell_center = np.sum(indiv.get_cell(), axis=1) / 2.0 indiv.translate(indiv.get_center_of_mass() + cell_center) indiv.set_pbc(True) return indiv
d_bond = 1.1 d_disp = 0.04 # Timestep and expected oscillatory period in attoseconds timestep = 5.0 period = 1.414e4 # ~292.4 meV cf. CRC Handbook of Phys. & Chem. #09_08_91 ndiv = int(np.ceil(0.1e3 / timestep)) # update stats every 0.1 fs niter = ndiv * int(np.ceil(2 * period / (ndiv * timestep))) if __name__ == '__main__': if not os.path.isfile(name + '_gs.gpw'): atoms = Atoms('N2', positions=[(0, 0, 0), (0, 0, d_bond + d_disp)]) atoms.set_pbc(False) atoms.center(vacuum=6.0) cell_c = np.sum(atoms.get_cell()**2, axis=1)**0.5 N_c = 8 * np.round(cell_c / (0.2 * 8)) calc = GPAW(gpts=N_c, nbands=5, basis='dzp', txt=name + '_gs.txt', eigensolver='rmm-diis') atoms.set_calculator(calc) atoms.get_potential_energy() calc.write(name + '_gs.gpw', mode='all') del atoms, calc time.sleep(10) while not os.path.isfile(name + '_gs.gpw'): print('Node %d waiting for file...' % world.rank) time.sleep(10) world.barrier() tdcalc = TDDFT(name + '_gs.gpw', txt=name + '_td.txt', propagator='EFSICN')
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() 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: 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: 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)) indi1.rotate(rax,a=-1*rang,center=rpos, rotate_cell=False) indi2.rotate(rax,a=-1*rang,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
u = 0.3 # internal degree of freedom! #primitive vectors a1 = a * np.array([1.0, 0.0, 0.0]) a2 = a * np.array([0.0, 1.0, 0.0]) a3 = c * np.array([0.0, 0.0, 1.0]) atoms = Atoms([ Atom('Ti', [0., 0., 0.]), Atom('Ti', 0.5 * a1 + 0.5 * a2 + 0.5 * a3), Atom('O', u * a1 + u * a2), Atom('O', -u * a1 - u * a2), Atom('O', (0.5 + u) * a1 + (0.5 - u) * a2 + 0.5 * a3), Atom('O', (0.5 - u) * a1 + (0.5 + u) * a2 + 0.5 * a3) ], cell=[a1, a2, a3]) v0 = atoms.get_volume() cell0 = atoms.get_cell() factors = [0.9, 0.95, 1.0, 1.05, 1.1] #to change volume by energies, volumes = [], [] ready = True for f in factors: v1 = f * v0 cell_factor = (v1 / v0)**(1. / 3.) atoms.set_cell(cell0 * cell_factor, scale_atoms=True) calc = Vasp( 'bulk/tio2/step1-{0:1.2f}'.format(f), encut=520, kpts=[5, 5, 5], isif=2, # relax internal degrees of freedom ibrion=1, nsw=50, xc='PBE',
def get_system_type(atoms: ase.Atoms) -> str: """ Helpful docstring """ ############################################################################ # Parameters #------------ cutoff = 6 # A # Preprocessing atoms.center() # In case dealing with Nerds Rope & Co. minx, miny, minz, maxx, maxy, maxz = 1000, 1000, 1000, -1000, -1000, -1000 for a in atoms: if a.position[0] < minx: minx = a.position[0] if a.position[1] < miny: miny = a.position[1] if a.position[2] < minz: minz = a.position[2] if a.position[0] > maxx: maxx = a.position[0] if a.position[1] > maxy: maxy = a.position[1] if a.position[2] > maxz: maxz = a.position[2] cell_abc = list(map(np.linalg.norm, atoms.get_cell()[:3])) thickness = [maxx - minx, maxy - miny, maxz - minz] pbc = [cell_abc[i] - thickness[i] < cutoff for i in range(3)] if all(pbc): return 'bulk' elif any(pbc): return 'surface' else: return 'molecule'
def traj_to_json(atoms : ase.Atoms) -> str: """ Serialize an Atoms object in a human readable way """ def rounder(y : float)->float: return round(y,3) + 0 #+0 turns -0 into 0 atomdata = [] const = atoms.constraints if const: const_list = const[0].get_indices().tolist() else: const_list = [] for a in atoms: atomdata.append({'number' : int(a.number) ,'x' : rounder(a.x) ,'y' : rounder(a.y) ,'z' : rounder(a.z) ,'magmom' : rounder(a.magmom) ,'tag' : int(a.tag) ,'constrained' : int(a.index in const_list) ,'index' : int(a.index)}) out = {'cell': [[rounder(x) for x in xx] for xx in atoms.get_cell().tolist()] ,'atomdata':atomdata} return json.dumps(out)
def test_electrostatics(self): """Tests that the results are consistent with the electrostatic interpretation. Each matrix [i, j] element should correspond to the Coulomb energy of a system consisting of the pair of atoms i, j. """ system = H2O n_atoms = len(system) a = 0.5 desc = EwaldSumMatrix(n_atoms_max=3, permutation="none", flatten=False) # The Ewald matrix contains the electrostatic interaction between atoms # i and j. Here we construct the total electrostatic energy for a # system consisting of atoms i and j. matrix = desc.create(system, a=a, rcut=rcut, gcut=gcut) energy_matrix = np.zeros(matrix.shape) for i in range(n_atoms): for j in range(n_atoms): if i == j: energy_matrix[i, j] = matrix[i, j] else: energy_matrix[i, j] = matrix[i, j] + matrix[i, i] + matrix[j, j] # Converts unit of q*q/r into eV conversion = 1e10 * scipy.constants.e / (4 * math.pi * scipy.constants.epsilon_0) energy_matrix *= conversion # The value in each matrix element should correspond to the Coulomb # energy of a system with with only those atoms. Here the energies from # the Ewald matrix are compared against the Ewald energy calculated # with pymatgen. positions = system.get_positions() atomic_num = system.get_atomic_numbers() for i in range(n_atoms): for j in range(n_atoms): if i == j: pos = [positions[i]] sym = [atomic_num[i]] else: pos = [positions[i], positions[j]] sym = [atomic_num[i], atomic_num[j]] i_sys = Atoms( cell=system.get_cell(), positions=pos, symbols=sym, pbc=True, ) structure = Structure( lattice=i_sys.get_cell(), species=i_sys.get_atomic_numbers(), coords=i_sys.get_scaled_positions(), ) structure.add_oxidation_state_by_site(i_sys.get_atomic_numbers()) ewald = EwaldSummation(structure, eta=a, real_space_cut=rcut, recip_space_cut=gcut) energy = ewald.total_energy # Check that the energy given by the pymatgen implementation is # the same as given by the descriptor self.assertTrue(np.allclose(energy_matrix[i, j], energy, atol=0.00001, rtol=0))
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 _compute_rdf_1frame(box, posis, atype, sel_type=[None, None], max_r=5, nbins=100): all_types = list(set(list(np.sort(atype)))) if sel_type[0] is None: sel_type[0] = all_types if sel_type[1] is None: sel_type[1] = all_types if type(sel_type[0]) is not list: sel_type[0] = [sel_type[0]] if type(sel_type[1]) is not list: sel_type[1] = [sel_type[1]] natoms = len(posis) from ase import Atoms import ase.neighborlist atoms = Atoms(positions=posis, cell=box, pbc=[1, 1, 1]) nlist = ase.neighborlist.NeighborList( max_r, self_interaction=False, bothways=True, primitive=ase.neighborlist.NewPrimitiveNeighborList) nlist.update(atoms) stat = np.zeros(nbins) hh = max_r / float(nbins) for ii in range(natoms): # atom "0" if atype[ii] in sel_type[0]: indices, offsets = nlist.get_neighbors(ii) for jj, os in zip(indices, offsets): # atom "1" if atype[jj] in sel_type[1]: posi_jj = atoms.positions[jj] + np.dot( os, atoms.get_cell()) diff = posi_jj - atoms.positions[ii] dr = np.linalg.norm(diff) # if (np.linalg.norm(diff- diff_1)) > 1e-12 : # raise RuntimeError si = int(dr / hh) if si < nbins: stat[si] += 1 # count the number of atom1 c0 = 0 for ii in sel_type[0]: c0 += np.sum(atype == ii) # count the number of atom1 c1 = 0 for ii in sel_type[1]: c1 += np.sum(atype == ii) rho1 = c1 / np.linalg.det(box) # compute rdf for ii in range(nbins): vol = 4. / 3. * np.pi * (((ii + 1) * hh)**3 - ((ii) * hh)**3) rho = stat[ii] / vol stat[ii] = rho / rho1 / c0 xx = np.arange(0, max_r - 1e-12, hh) return xx, stat
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 test_k2_weights_and_geoms_periodic(self): """Tests that the values of the weight and geometry functions are correct for the k=2 term in periodic systems. """ atoms = Atoms( cell=[ [10, 0, 0], [10, 10, 0], [10, 0, 10], ], symbols=["H", "C"], scaled_positions=[ [0.1, 0.5, 0.5], [0.9, 0.5, 0.5], ] ) mbtr = MBTR( [1, 6], k=[2], grid=default_grid, periodic=True, weighting={ "k2": { "function": "exponential", "scale": 0.8, "cutoff": 1e-3 }, }, ) mbtr.create(atoms) weights = mbtr._k2_weights geoms = mbtr._k2_geoms # Test against the assumed geometry values pos = atoms.get_positions() distances = np.array([ np.linalg.norm(pos[0] - pos[1]), np.linalg.norm(pos[0] - pos[1] + atoms.get_cell()[0, :]), np.linalg.norm(pos[1] - pos[0] - atoms.get_cell()[0, :]) ]) assumed_geoms = { (0, 1): 1/distances } self.dict_comparison(geoms, assumed_geoms) # Test against the assumed weights weight_list = np.exp(-0.8*distances) # The periodic distances are halved weight_list[1:3] /= 2 assumed_weights = { (0, 1): weight_list } self.dict_comparison(weights, assumed_weights)
def test_change_cell_dimensions_and_pbc(factory, dimer_params, lj_epsilons): """Ensure that post_change_box commands are actually executed after changing the dimensions of the cell or its periodicity. This is done by setting up an isolated dimer with a Lennard-Jones potential and a set of post_changebox_cmds that specify the same potential but with a rescaled energy (epsilon) parameter. The energy is then computed twice, once before changing the cell dimensions and once after, and the values are compared to the expected values based on the two different epsilons to ensure that the modified LJ potential is used for the second calculation. The procedure is repeated but where the periodicity of the cell boundaries is changed rather than the cell dimensions. """ # Make a dimer in a large nonperiodic box dimer = Atoms(**dimer_params) spec, a = extract_dimer_species_and_separation(dimer) # Ensure LJ cutoff is large enough to encompass the dimer lj_cutoff = 3 * a calc_params = calc_params_lj_changebox(spec, lj_cutoff, **lj_epsilons) dimer.calc = factory.calc(**calc_params) energy_orig = dimer.get_potential_energy() # Shrink the box slightly to invalidate cached energy and force change_box # to be issued. This shouldn't actually affect the energy in and of itself # since our dimer has non-periodic boundaries. cell_orig = dimer.get_cell() dimer.set_cell(cell_orig * 1.01, scale_atoms=False) energy_modified = dimer.get_potential_energy() eps_scaling_factor = lj_epsilons["eps_modified"] / lj_epsilons["eps_orig"] assert energy_modified == pytest.approx(eps_scaling_factor * energy_orig, rel=1e-4) # Reset dimer cell. Also, create and attach new calculator so that # previous post_changebox_cmds won't be in effect. dimer.set_cell(cell_orig, scale_atoms=False) dimer.calc = factory.calc(**calc_params) # Compute energy of original configuration again so that a change_box will # be triggered on the next calculation after we change the pbcs energy_orig = dimer.get_potential_energy() # Change the periodicity of the cell along one direction. This shouldn't # actually affect the energy in and of itself since the cell is large # relative to the dimer dimer.set_pbc([False, True, False]) energy_modified = dimer.get_potential_energy() assert energy_modified == pytest.approx(eps_scaling_factor * energy_orig, rel=1e-4)
def test_emt(): import numpy as np from ase.calculators.emt import EMT from ase import Atoms a = 3.60 b = a / 2 cu = Atoms('Cu', positions=[(0, 0, 0)], cell=[(0, b, b), (b, 0, b), (b, b, 0)], pbc=1, calculator=EMT()) e0 = cu.get_potential_energy() print(e0) cu.set_cell(cu.get_cell() * 1.001, scale_atoms=True) e1 = cu.get_potential_energy() V = a**3 / 4 B = 2 * (e1 - e0) / 0.003**2 / V * 160.2 print(B) for i in range(4): x = 0.001 * i A = np.array([(x, b, b + x), (b, 0, b), (b, b, 0)]) cu.set_cell(A, scale_atoms=True) e = cu.get_potential_energy() - e0 if i == 0: print(i, e) else: print(i, e, e / x**2) A = np.array([(0, b, b), (b, 0, b), (6 * b, 6 * b, 0)]) R = np.zeros((2, 3)) for i in range(1, 2): R[i] = i * A[2] / 6 print((Atoms('Cu2', positions=R, pbc=1, cell=A, calculator=EMT()).get_potential_energy() - 2 * e0) / 2) A = np.array([(0, b, b), (b, 0, b), (10 * b, 10 * b, 0)]) R = np.zeros((3, 3)) for i in range(1, 3): R[i] = i * A[2] / 10 print((Atoms('Cu3', positions=R, pbc=1, cell=A, calculator=EMT()).get_potential_energy() - 3 * e0) / 2) A = np.array([(0, b, b), (b, 0, b), (b, b, 0)]) R = np.zeros((3, 3)) for i in range(1, 3): R[i] = i * A[2] print((Atoms('Cu3', positions=R, pbc=(1, 1, 0), cell=A, calculator=EMT()).get_potential_energy() - 3 * e0) / 2)
def _get_reduced_indices(atoms: Atoms, tol: float = 1e-5) -> List[int]: """Get a list of the reduced atomic indices using spglib. Note: Does no checks to see if spglib is installed. :param atoms: ase Atoms object to reduce :param tol: ``float``, numeric tolerance for positional comparisons """ import spglib # Create input for spglib spglib_cell = (atoms.get_cell(), atoms.get_scaled_positions(), atoms.numbers) symmetry_data = spglib.get_symmetry_dataset(spglib_cell, symprec=tol) return list(set(symmetry_data['equivalent_atoms']))
def _preprocess_atoms(self, atoms: Atoms) -> Dict[str, Optional[Tensor]]: pos = torch.tensor( atoms.get_positions(), device=self.device, dtype=self.dtype, requires_grad=True ) Z = torch.tensor(atoms.get_atomic_numbers(), device=self.device) if any(atoms.pbc): cell = torch.tensor( atoms.get_cell(), device=self.device, dtype=self.dtype, requires_grad=True ) else: cell = None pbc = torch.tensor(atoms.pbc, device=self.device) edge_index, S = self._calc_edge_index(pos, cell, pbc) input_dicts = dict(pos=pos, Z=Z, cell=cell, pbc=pbc, edge_index=edge_index, shift=S) return input_dicts
def prepare_ga(dbfile='godb.db', N=20): ''' This method creates a database with the desired number of randomly generated structures. ''' blocks = [('Si', 7)] # the building blocks l = [list(Atoms(block).numbers) * count for block, count in blocks] stoichiometry = [int(item) for sublist in l for item in sublist] atom_numbers = list(set(stoichiometry)) # This dictionary will be used to check that the shortest # Si-Si distances are above a certain threshold # (here 1.5 Angstrom): blmin = {(14, 14): 1.5} # This defines the cubic simulation cell: slab = Atoms('', positions=np.zeros((0, 3)), cell=[16] * 3) # This defines the smaller box in which the # initial coordinates are allowed to vary density = 0.12 # in atoms per cubic Angstrom aspect_ratios = np.array([1.0, 1.0, 1.0]) v = len(stoichiometry) / density l = np.cbrt(v / np.product(aspect_ratios)) cell = np.identity(3) * aspect_ratios * l p0 = 0.5 * (np.diag(slab.get_cell() - cell)) box = [p0, cell] # Seed the random number generators using the system time, # to ensure that no two runs produce the same results: np.random.seed() seed() # Generate the random structures and add them to the database: sg = StartGenerator(slab=slab, atom_numbers=stoichiometry, closest_allowed_distances=blmin, box_to_place_in=box) da = PrepareDB(db_file_name=dbfile, simulation_cell=slab, stoichiometry=stoichiometry) for i in range(N): a = sg.get_new_candidate() da.add_unrelaxed_candidate(a) return
def create_water_region(cell): """Creates a region of water for the cell specified. The density is assumed to be that of normal water at 1atm and 300K. Internally, this first creates a grid of Ne atoms, and then rattle them very slightly (std = 1/10 of a H2O molecule size). The Ne atoms are then replaced with H2O molecules centered on Ne. Be _very_ careful that the atoms are not out of bounds. It can happen after some rotations. Recommend to put in a slightly smaller cell to give some margins. Parameters: cell: list | numpy array Returns: H2O_bulk: Atoms | list of Atom """ aq_cell = cell H2O_volume = (1e+27)/(1000/18 * units.mol) Atoms_grid = Atoms('Ne', pbc=True, cell=[H2O_volume**(1/3)]*3) Atoms_grid = Atoms_grid.repeat( tuple([int(x/(H2O_volume**(1/3))) for x in aq_cell])) Atoms_grid.set_cell(aq_cell) Atoms_grid.center() Atoms_grid.rattle(stdev=H2O_volume**(1/3)/10) H2O_bulk = molecule('H2O') H2O_bulk.euler_rotate(rand()*360, rand()*360, rand()*360, center="COM") H2O_bulk.translate(Atoms_grid.get_positions()[0]) H2O_bulk.set_cell(Atoms_grid.get_cell()) H2O_bulk.set_pbc(True) for new_pos in Atoms_grid.get_positions()[1:]: new_molecule = molecule('H2O') new_molecule.euler_rotate( rand()*360, rand()*360, rand()*360, center="COM") new_molecule.translate(new_pos) H2O_bulk += new_molecule.copy() H2O_bulk.center() return H2O_bulk
def is_cell_hexagonal(atoms: Atoms): """ Function to check whether the cell of an ASE atoms object is hexagonal. Parameters ---------- atoms : ASE atoms object The atoms that should be checked. """ cell = atoms.get_cell() a = np.linalg.norm(cell[0], axis=0) b = np.linalg.norm(cell[1], axis=0) c = np.linalg.norm(cell[2], axis=0) angle = np.arccos(np.dot(cell[0], cell[1]) / (a * b)) return np.isclose(a, b) & (np.isclose(angle, np.pi / 3) | np.isclose( angle, 2 * np.pi / 3)) & (c == cell[2, 2])
def ase_to_quip(ase_atoms: ase.Atoms, quip_atoms=None): """ Converter to put the info from an ase atoms object into a quip atoms object. Copies everything to make sure there is not linking back. Checks if the :param ase_atoms: :param quip_atoms: :return: """ lattice = ase_atoms.get_cell().T.copy() if quip_atoms is not None: if isinstance(quip_atoms, quippy.atoms_types_module.Atoms): # check if the length matches, otherwise make a new one in place of that if len(ase_atoms) != quip_atoms.n: # need to regenerate the quip atoms object quip_atoms = quippy.atoms_types_module.Atoms(len(ase_atoms), lattice) else: # but the cell needs to be set anyways quip_atoms.set_lattice(lattice, scale_positions=False) else: # raise an error for the wrong object given raise TypeError('quip_atoms argument is not of valid type, cannot work with it') else: # need to regenerate the quip atoms object quip_atoms = quippy.atoms_types_module.Atoms(len(ase_atoms), lattice) quip_atoms.pos[:] = ase_atoms.get_positions().T.copy() quip_atoms.is_periodic[:] = ase_atoms.get_pbc() quip_atoms.z[:] = ase_atoms.numbers quip_atoms.set_atoms(quip_atoms.z) # set species and mass if ase_atoms.has('momenta'): # if ase atoms has momenta then add velocities to the quip object # workaround for the interfaces not behaving properly in the wrapped code, see f90wrap issue #86 _quippy.f90wrap_atoms_add_property_real_2da(this=quip_atoms._handle, name='velo', value=velocities_ase_to_quip(ase_atoms.get_velocities())) # go through all properties return quip_atoms
def get_charge(self): q, ecoul, eself, evdw = [], [], [], [] print('- get charges by QEq ... \n') A = Atoms(symbols=self.atom_name, positions=self.x[0], cell=self.cell, pbc=(1, 1, 1)) Qe = qeq(p=self.p, atoms=A) for nf in range(self.batch): # print('* get charges of batch {0}/{1} ...\r'.format(nf,self.batch),end='\r') A = Atoms(symbols=self.atom_name, positions=self.x[nf], cell=self.cell, pbc=(1, 1, 1)) positions = A.get_positions() cell = A.get_cell() Qe.calc(cell, positions) q.append(Qe.q[:-1]) self.q = np.array(q)
def standardize_cell(atoms: Atoms, tol: float = 1e-12): """ Standardize the cell of an ASE atoms object. The atoms are rotated so one of the lattice vectors in the xy-plane aligns with the x-axis, then all of the lattice vectors are made positive. Parameters ---------- atoms : ASE atoms object The atoms that should be standardized tol : float Components of the lattice vectors below this value are considered to be zero. Returns ------- atoms : ASE atoms object The standardized atoms. """ cell = np.array(atoms.cell) vertical_vector = np.where(np.all(np.abs(cell[:, :2]) < tol, axis=1))[0] if len(vertical_vector) != 1: raise RuntimeError('Invalid cell: no vertical lattice vector') cell[[vertical_vector[0], 2]] = cell[[2, vertical_vector[0]]] r = np.arctan2(atoms.cell[0, 1], atoms.cell[0, 0]) / np.pi * 180 atoms.set_cell(cell) if r != 0.: atoms.rotate(-r, 'z', rotate_cell=True) if not is_cell_valid(atoms, tol): raise RuntimeError( 'This cell cannot be made orthogonal using currently implemented methods.' ) atoms.set_cell(np.abs(atoms.get_cell())) atoms.wrap() return atoms
def test(): """Simple test function to test atoms2json and json2atoms function""" from ase import Atoms teststructure = Atoms('N2', [(0, 0, 0), (0, 0, 1.1)]) teststring = atoms2json(teststructure, additional_information={"abc": "def" }) #convert to the string newstructure = json2atoms(teststring) #and convert back assert (newstructure.get_atomic_numbers() == teststructure.get_atomic_numbers()).all() assert ( newstructure.get_positions() == teststructure.get_positions()).all() assert (newstructure.get_cell() == teststructure.get_cell()).all() assert (newstructure.get_pbc() == teststructure.get_pbc()).all() assert newstructure.info["key_value_pairs"]["abc"] == "def" print("JSON Conversion in both directions: apparently no issue")
for i in range(2): equal(p[i, 1], 0, 1e-10) equal(p[i, 2], 0, 1e-10) # rotate the nuclear axis to the direction (1,1,1) CO.rotate(p[1] - p[0], (1, 1, 1)) q = CO.positions.copy() for c in range(3): equal(q[0, c], p[0, 0] / sqrt(3), 1e-10) equal(q[1, c], p[1, 0] / sqrt(3), 1e-10) # minimal box b=4.0 CO = Cluster([Atom('C', (1, 0, 0)), Atom('O', (1, 0, R))]) CO.minimal_box(b) cc = CO.get_cell() for c in range(3): width = 2*b if c==2: width += R equal(cc[c, c], width, 1e-10) # minimal box, ensure multiple of 4 h = .13 b = [2, 3, 4] CO.minimal_box(b, h=h) cc = CO.get_cell() for c in range(3): # print "cc[c,c], cc[c,c] / h % 4 =", cc[c, c], cc[c, c] / h % 4 for a in CO: print(a.symbol, b[c], a.position[c], cc[c, c] - a.position[c])
atoms=atoms) as calc: atoms = calc.get_atoms() x, y, z, cd = calc.get_charge_density() mlab.figure(bgcolor=(1, 1, 1)) # plot the atoms as spheres for atom in atoms: mlab.points3d(atom.x, atom.y, atom.z, scale_factor=vdw_radii[atom.number]/5., resolution=20, # a tuple is required for the color color=tuple(cpk_colors[atom.number]), scale_mode='none') # draw the unit cell - there are 8 corners, and 12 connections a1, a2, a3 = atoms.get_cell() origin = [0, 0, 0] cell_matrix = [[origin, a1], [origin, a2], [origin, a3], [a1, a1 + a2], [a1, a1 + a3], [a2, a2 + a1], [a2, a2 + a3], [a3, a1 + a3], [a3, a2 + a3], [a1 + a2, a1 + a2 + a3], [a2 + a3, a1 + a2 + a3], [a1 + a3, a1 + a3 + a2]] for p1, p2 in cell_matrix: mlab.plot3d([p1[0], p2[0]], # x-positions
#PBS -q medium -l nodes=1:ppn=8:xeon5570 -m abe -V # Takes 30 mins with 8 cores in domain-parallel (memory ~500mb, max 1.5gb) import numpy as np from ase import Atom, Atoms from gpaw import GPAW, MixerDif, mpi from gpaw.lrtddft import LrTDDFT from gpaw.pes.dos import DOSPES from gpaw.pes.tddft import TDDFTPES atoms = Atoms([Atom('C', (7.666263598984184, 7.637780850431168, 8.289450797111844)), Atom('O', (8.333644370007132, 8.362384430165646, 7.710230973847514))]) atoms.center(vacuum=8) h = 0.15 N_c = np.round(atoms.get_cell().diagonal() / h / 16) * 16 m_c = GPAW(gpts=N_c, nbands=6, mixer=MixerDif(0.1, 5, weight=100.0), #convergence={'bands':10}, parallel={'domain': mpi.size}, xc='PBE', txt='CO-m.txt', spinpol=True) m = atoms.copy() m.set_initial_magnetic_moments([-1,1]) m.set_calculator(m_c) m.get_potential_energy() d_c = GPAW(gpts=N_c, nbands=16, mixer=MixerDif(0.1, 5, weight=100.0), convergence={'bands':10}, parallel={'domain': mpi.size}, xc='PBE', txt='CO-d.txt', spinpol=True)
def gen_pop_box(atomlist,size,crystal=False): """Function to generate a random structure of atoms. Inputs: atomlist = List of tuples with structure of atoms and quantity [('Sym1',int(concentration1), float(mass1),float(chempotential1)), ('Sym2',int(concentration2), float(mass2),float(chempotential2)),...] size = Float of length of side of cube within which to generate atoms crystal = False/List of crystal cell shape options list('cubic','orthorhombic','tetragonal','hexagonal','monoclinic','triclinic') cell shape will be adjusted accordingly Outputs: Returns individual of class Atoms (see ase manual for info on Atoms class) and if crystal list provided also outputs combined string with output information """ indiv=Atoms() indiv.set_cell([size,size,size]) # Get list of atom types for all atoms in cluster for s,c,m,u in atomlist: if c > 0: for i in range(c): pos = [random.uniform(0,size) for j in range(3)] at=Atom(symbol=s,position=pos) indiv.append(at) if crystal: stro='' natoms=sum([c for s,c,m,u in atomlist]) pos=indiv.get_scaled_positions() structure=random.choice(crystal) cello=indiv.get_cell() if structure=='cubic': #Set to cubic shape an,bn,cn = [numpy.linalg.norm(v) for v in cello] a=(an+bn+cn)/3.0 celln=numpy.array([[a,0,0],[0,a,0],[0,0,a]]) stro+='Setting cell to cubic\n' elif structure=='orthorhombic': #Set to orthorhombic a=random.uniform(2,natoms**0.3333*size) b=random.uniform(2,natoms**0.3333*size) c=random.uniform(2,natoms**0.3333*size) celln=numpy.array([[a,0,0],[0,b,0],[0,0,c]]) stro+='Setting cell to orthorhombic\n' elif structure=='tetragonal': #Set to tetragonal shape an,bn,cn = [numpy.linalg.norm(v) for v in cello] a=(an+bn)/2.0 c=cn if c==a: c=random.uniform(1,natoms**0.3333*size) celln=numpy.array([[a,0,0],[0,a,0],[0,0,c]]) stro+='Setting cell to tetragonal\n' elif structure=='hexagonal': #Set to hexagonal shape an,bn,cn = [numpy.linalg.norm(v) for v in cello] a=(an+bn)/2.0 c=cn if c<=a: c=random.uniform(a+1,natoms**0.3333*size) trans=numpy.array([[1,0,0],[-0.5,(3.0**0.5)/2.0,0],[0,0,1]]) trans[0]=[a*i for i in trans[0]] trans[1]=[a*i for i in trans[1]] trans[2]=[c*i for i in trans[2]] celln=trans stro+='Setting cell to Hexagonal\n' elif structure=='monoclinic': #Set to monoclinic a,b,c = [numpy.linalg.norm(v) for v in cello] if a==b: b=random.uniform(1,natoms**0.3333*size) trans=numpy.array([(1+random.random())*c, 0, (1+random.random())*c]) celln=numpy.array([[a,0,0],[0,b,0],[0,0,0]]) celln[2]=trans stro+='Setting cell to monoclinic\n' elif structure=='triclinic': #Set to triclinic a,b,c = [numpy.linalg.norm(v) for v in cello] celln=numpy.array([[a,0,0],[(1+random.random())*b,(1+random.random())*b,0],[(1+random.random())*c,0,(1+random.random())*c]]) stro+='Setting cell to triclinic\n' indiv.set_cell(celln) indiv.set_scaled_positions(pos) stro+=repr(indiv.get_cell())+'\n' return indiv, stro return indiv
from ase.calculators.emt import EMT from ase import Atoms a = 3.60 b = a / 2 cu = Atoms('Cu', positions=[(0, 0, 0)], cell=[(0, b, b), (b, 0, b), (b, b, 0)], pbc=1, calculator=EMT()) e0 = cu.get_potential_energy() print e0 cu.set_cell(cu.get_cell() * 1.001, scale_atoms=True) e1 = cu.get_potential_energy() V = a**3 / 4 B = 2 * (e1 - e0) / 0.003**2 / V * 160.2 print B for i in range(4): x = 0.001 * i A = np.array([(x, b, b+x), (b, 0, b), (b, b, 0)]) cu.set_cell(A, scale_atoms=True) e = cu.get_potential_energy() - e0 if i == 0: print i, e else:
def read_pmd(fname='pmd0000',specorder=[],fmvs=[(True,True,True),]): """ Import pmd format file. fname Name of the file to be read. specorder Order of species appeared in pmd file. fmvs Constraints of motion in bool of x,y,z direction. e.g., fmv = ((True,True,True),(True,True,False),) True means fix and False means free. """ f = open(fname,'r') # 1st line: lattice_constant lattice_constant = float(f.readline().split()[0]) # 2-4 lines: lattice vectors a = [] for ii in range(3): s = f.readline().split() floatvect = float(s[0]), float(s[1]), float(s[2]) a.append(floatvect) basis_vectors = np.array(a) * lattice_constant # 5-7 lines: velocities of lattice vectors tmp = f.readline() tmp = f.readline() tmp = f.readline() natm = int(f.readline().split()[0]) positions = np.zeros((natm,3),dtype=float) symbols = [] ifmvs = np.zeros((natm),dtype=int) maxifmv = 0 for ia in range(natm): data = f.readline().split() tag = float(data[0]) for ii in range(3): positions[ia,ii] = float(data[ii+1]) sid,symbol,ifmv,aid = decode_tag(tag,specorder) symbols.append(symbol) ifmvs[ia] = ifmv maxifmv = max(maxifmv,ifmv) f.close() if maxifmv > len(fmvs)+1: raise ValueError('Length of fmvs are too short.') atoms = Atoms(symbols=symbols,cell=basis_vectors,pbc=True) atoms.set_scaled_positions(positions) #set constraints constraints = [] indices = [] for ia in range(natm): if ifmvs[ia] == 0: indices.append(ia) else: ifmv = ifmvs[ia] fmv = fmvs[ifmv-1] if all(fmv): indices.append(ia) elif any(fmv): constraints.append(FixScaled(atoms.get_cell(),ia,fmv)) if indices: constraints.append(FixAtoms(indices)) if constraints: atoms.set_constraint(constraints) return atoms
calc = GPAW(h=0.15, width=0.1, xc='LDA', nbands=-4, txt='-', basis='dzp', convergence={'energy': 1e-5, 'density': 1e-5}) # Calculate potential energy per atom for orthogonal unitcell atoms = hcp0001('C', a=a/sqrt(3), vacuum=d, size=(3,2,1), orthogonal=True) del atoms[[1,-1]] atoms.center(axis=0) atoms.set_calculator(calc) kpts_c = np.ceil(50 / np.sum(atoms.get_cell()**2, axis=1)**0.5).astype(int) kpts_c[~atoms.get_pbc()] = 1 calc.set(kpts=kpts_c) eppa1 = atoms.get_potential_energy() / len(atoms) F1_av = atoms.get_forces() equal(np.abs(F1_av).max(), 0, 5e-3) # Redo calculation with non-orthogonal unitcell atoms = Atoms(symbols='C2', pbc=(True,True,False), positions=[(a/2,-sqrt(3)/6*a,d), (a/2,sqrt(3)/6*a,d)], cell=[(a/2,-sqrt(3)/2*a,0), (a/2,sqrt(3)/2*a,0), (0,0,2*d)]) atoms.set_calculator(calc) kpts_c = np.ceil(50 / np.sum(atoms.get_cell()**2, axis=1)**0.5).astype(int) kpts_c[~atoms.get_pbc()] = 1 calc.set(kpts=kpts_c) eppa2 = atoms.get_potential_energy() / len(atoms) F2_av = atoms.get_forces() equal(np.abs(F2_av).max(), 0, 5e-3) equal(eppa1, eppa2, 1e-3)
import numpy as np from ase import Atom, Atoms from ase.optimize import BFGS from ase.parallel import parprint from ase.units import Hartree import gpaw.mpi as mpi from gpaw import GPAW from gpaw.test import equal from gpaw.lrtddft.kssingle import KSSingles Be = Atoms('Be') Be.center(vacuum=6) if 1: # introduce a sligth non-orthgonality cell = Be.get_cell() cell[1] += 0.001 * cell[0] Be.set_cell(cell) txt = None #txt='-' eigensolver = None #eigensolver = 'rmm-diis' #modes = ['lcao', 'fd'] modes = ['fd'] for mode in modes: energy = {} osz = {} for pbc in [False, True]:
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()
import numpy as np from ase import Atom,Atoms from ase.io import write atoms = Atoms('Ni4', positions= [(0, 0, 0), (0.45, 0, 0), (0, 0.5, 0), (0.5, 0.5, 0),]) atoms[1].x = 0.5 a = 3.55 cell = [(2 / np.sqrt(2.0) * a, 0, 0), (1 / np.sqrt(2.0) * a, np.sqrt(3.0 / 2.0) * a, 0), (0, 0, 10 * np.sqrt(3.0) / 3.0 * a)] atoms.set_cell(cell, scale_atoms=True) write('a1.png', atoms, rotation='-73x', show_unit_cell=2) a = atoms.repeat((3, 3, 2)) a.set_cell(atoms.get_cell()) write('a2.png', a, rotation='-73x', show_unit_cell=True) xyzcell = np.identity(3) # The 3x3 unit matrix atoms.set_cell(xyzcell, scale_atoms=True) # Set the unit cell and rescale atoms.append(Atom('Ni', (1/6., 1/6., .1))) atoms.set_cell(cell, scale_atoms=True) # Set the unit cell and scale back a = atoms.repeat((3, 3, 1)) a.set_cell(atoms.get_cell()) write('a3.png', a, show_unit_cell=True)
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()
from ase import Atoms from ase.lattice import bulk from ase.optimize.bfgs import BFGS from ase.constraints import UnitCellFilter from gpaw import GPAW from gpaw import PW import numpy as np cell = bulk('Si', 'fcc', a=6.0).get_cell() # Experimental Lattice constant is a=5.421 A a = Atoms('Si2', cell=cell, pbc=True, scaled_positions=((0,0,0), (0.25,0.25,0.25))) calc = GPAW(xc='PBE', mode=PW(400), #mode=PW(400, cell=a.get_cell()), # fix no of planewaves! kpts=(4,4,4), #convergence={'eigenstates': 1.e-10}, # converge tightly! txt='stress.txt') a.set_calculator(calc) uf = UnitCellFilter(a) relax = BFGS(uf) relax.run(fmax=0.05) # Consider much tighter fmax! a = np.dot(a.get_cell()[0], a.get_cell()[0])**0.5 * 2**0.5 print 'Relaxed lattice parameter: a = %s A' % a
from ase import Atom, Atoms # http://cst-www.nrl.navy.mil/lattice/struk/c5.html B = 'Ti'; X = 'O'; a = 3.7842; c = 2*4.7573; z = 0.0831; a1 = a * np.array([1.0, 0.0, 0.0]) a2 = a * np.array([0.0, 1.0, 0.0]) a3 = np.array([0.5 * a, 0.5 * a, 0.5 * c]) atoms = Atoms([Atom(B, -0.125 * a1 + 0.625 * a2 + 0.25 * a3), Atom(B, 0.125 * a1 + 0.375 * a2 + 0.75 * a3), Atom(X, -z*a1 + (0.25-z)*a2 + 2.*z*a3), Atom(X, -(0.25+z)*a1 + (0.5-z)*a2 + (0.5+2*z)*a3), Atom(X, z*a1 - (0.25 - z)*a2 + (1-2*z)*a3), Atom(X, (0.25 + z)*a1 + (0.5 + z)*a2 + (0.5-2*z)*a3)], cell=[a1,a2,a3]) nTiO2 = len(atoms) / 3. v0 = atoms.get_volume() cell0 = atoms.get_cell() volumes = [30., 33., 35., 37., 39.] #vol of one TiO2 for v in volumes: atoms.set_cell(cell0 * ((nTiO2*v/v0)**(1./3.)), scale_atoms=True) with jasp('bulk/TiO2/anatase/anatase-{0}'.format(v), encut=350, kpts=(6, 6, 6), xc='PBE', ismear=0, sigma=0.001, isif=2, ibrion=2, nsw=20, atoms=atoms) as calc: try:
def write_cell_params(fh, a, p): ''' Write the specification of the cell using a traditional A,B,C, alpha, beta, gamma scheme. The symmetry and parameters are determined from the atoms (a) object. The atoms object is translated into a primitive unit cell but *not* converted. This is just an internal procedure. If you wish to work with primitive unit cells in ASE, you need to make a conversion yourself. The cell params are in angstrom. Input ----- fh file handle of the opened pw.in file a atoms object p parameters dictionary Output ------ Primitive cell tuple of arrays: (lattice, atoms, atomic numbers) ''' assert(p['use_symmetry']) # Get a spacegroup name and number for the a sg,sgn=spglib.get_spacegroup(a).split() # Extract the number sgn=int(sgn[1:-1]) # Extract the lattice type ltyp=sg[0] # Find a primitive unit cell for the system # puc is a tuple of (lattice, atoms, atomic numbers) puc=spglib.find_primitive(a) cell=puc[0] apos=puc[1] anum=puc[2] icell=a.get_cell() A=norm(icell[0]) B=norm(icell[1]) C=norm(icell[2]) # Select appropriate ibrav if sgn >= 195 : # Cubic lattice if ltyp=='P': p['ibrav']=1 # Primitive qepc=array([[1,0,0],[0,1,0],[0,0,1]]) elif ltyp=='F': p['ibrav']=2 # FCC qepc=array([[-1,0,1],[0,1,1],[-1,1,0]])/2.0 elif ltyp=='I': p['ibrav']=3 # BCC qepc=array([[1,1,1],[-1,1,1],[-1,-1,1]])/2.0 else : print 'Impossible lattice symmetry! Contact the author!' raise NotImplementedError #a=sqrt(2)*norm(cell[0]) qepc=A*qepc fh.write(' A = %f,\n' % (A,)) elif sgn >= 143 : # Hexagonal and trigonal if ltyp=='P' : p['ibrav']=4 # Primitive qepc=array([[1,0,0],[-1/2,sqrt(3)/2,0],[0,0,C/A]]) elif ltyp=='R' : p['ibrav']=5 # Trigonal rhombohedral raise NotImplementedError else : print 'Impossible lattice symmetry! Contact the author!' raise NotImplementedError qepc=A*qepc fh.write(' A = %f,\n' % (A,)) fh.write(' C = %f,\n' % (C,)) elif sgn >= 75 : raise NotImplementedError elif sgn ==1 : # P1 symmetry - no special primitive cell signal to the caller p['ibrav']=0 return None else : raise NotImplementedError cp=Atoms(cell=puc[0], scaled_positions=puc[1], numbers=puc[2], pbc=True) qepc=Atoms(cell=qepc, positions=cp.get_positions(), numbers=cp.get_atomic_numbers(), pbc=True) return qepc.get_cell(), qepc.get_scaled_positions(), qepc.get_atomic_numbers()
return ed if __name__ == '__main__': import matplotlib.pyplot as plt from ase import Atoms from ase.visualize import view from ase.cluster import FaceCenteredCubic import ase.io as aseio # atoms = Atoms('Pt', [(0, 0, 0)]) atoms = Atoms( FaceCenteredCubic('Pt', [[1, 0, 0], [1, 1, 0], [1, 1, 1]], (2, 3, 2))) # atoms = atoms[[atom.index for atom in atoms if atom.position[2]< 1.5]] view(atoms) atoms.set_cell(atoms.get_cell() * 1.2) atoms.center() cell = atoms.get_cell() print(cell, len(atoms)) resolution = .3 * np.ones(3) c = np.diagonal(cell) v = tuple(np.int32(np.ceil(c / resolution))) voxels = np.zeros(v) ed = np.zeros(v) i = 0 for atom in atoms: print(i) ed += get_atomic_electron_density(atom, voxels, resolution) i += 1 print(ed[:, :, 0]) plt.imshow(np.sum(ed, axis=2), cmap='viridis')
[-3.68163760377696e+00, -5.94997793843316e+00, +1.14910098375475e+01]], [[+1.13578166916005e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.62236725820948e+00, +1.28309672640153e+01, +0.00000000000000e+00], [-3.36772471669551e+00, -6.41548363200768e+00, +1.15542200082913e+01]], [[+1.18321595661992e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.71877792223422e+00, +1.29511827614560e+01, +0.00000000000000e+00], [-3.55669082198251e+00, -6.47559138072800e+00, +1.16368667031408e+01]], [[+4.81947971142972e-03, +0.00000000000000e+00, +0.00000000000000e+00], [+4.12397039845618e-03, +4.86743859122682e+01, +0.00000000000000e+00], [+4.62732595971025e-03, +1.13797841621313e+01, +6.81149615940608e+01]], [[+1.43683914413843e-01, +0.00000000000000e+00, +0.00000000000000e+00], [+4.73841211849216e-02, +8.02075186538656e+00, +0.00000000000000e+00], [+9.29303317118020e-03, +8.28854375915883e-01, +1.93660401476964e+01]], [[+5.02420000000000e+00, +0.00000000000000e+00, +0.00000000000000e+00], [-2.40035596861745e+00, +1.25083680303996e+01, +0.00000000000000e+00], [-2.37319883118274e+00, -5.49894680458153e+00, +2.86098306766757e+01]], [[+5.02419976114664e+00, +0.00000000000000e+00, +0.00000000000000e+00], [-2.40036499209593e+00, +1.25083662987906e+01, +0.00000000000000e+00], [-2.37320481266200e+00, -5.49892622854049e+00, +2.86097847514890e+01]], ]) conf = Atoms(pbc=True) for i, cell in enumerate(cells_in): conf.set_cell(cell) niggli_reduce(conf) cell = conf.get_cell() diff = np.linalg.norm(cell - cells_out[i]) assert diff < 1e-5, \ 'Difference between unit cells is too large! ({0})'.format(diff)
calc.set(kpts=(20, 20, 7), fixdensity=True) atoms.get_potential_energy() # The result should also be converged with respect to bands: calc.diagonalize_full_hamiltonian(nbands=60) calc.write('graphite.gpw', 'all') # Part 2: Spectra calculations f = paropen('graphite_q_list', 'w') # write q for i in range(1, 6): # loop over different q df = DielectricFunction(calc='graphite.gpw', domega0=0.01, eta=0.2, # Broadening parameter. ecut=100, # write different output for different q: txt='out_df_%d.txt' % i) q_c = [i / 20.0, 0.0, 0.0] # Gamma - M excitation df.get_eels_spectrum(q_c=q_c, filename='graphite_EELS_%d' % i) # Calculate cartesian momentum vector: cell_cv = atoms.get_cell() bcell_cv = 2 * np.pi * np.linalg.inv(cell_cv).T q_v = np.dot(q_c, bcell_cv) print(sqrt(np.inner(q_v, q_v)), file=f) f.close()
def rotct_rand_defect(ind1, ind2, Optimizer): """Rotate atoms cut and splice Translates atoms to center of positions first Rotates atoms randomly around center of mass and cuts with xy plane Maintains number of atoms Maintains concentration of atoms Returns individuals to standard positions at end (un-rotates) """ if "CX" in Optimizer.debug: debug = True else: debug = False Optimizer.output.write( "Random Rotate Cut/Splice Cx for defects between individual " + repr(ind1.index) + " and individual " + repr(ind2.index) + "\n" ) # Perserve starting conditions of individual indi1 = ind1[0].copy() indi2 = ind2[0].copy() # Translate individuals so COP is at (0,0,0) if Optimizer.structure == "Defect": # Identify center of positions for defect structure indi1c, indi1b, vacant1, swap1, stro1 = find_defects(indi1, Optimizer.solidbulk, 0) com1 = position_average(indi1c) indi1 = shift_atoms(indi1, com1) # Do the same for second individual indi2c, indi2b, vacant2, swap2, stro2 = find_defects(indi2, Optimizer.solidbulk, 0) com2 = position_average(indi2c) indi2 = shift_atoms(indi2, com2) else: com1 = indi1.get_center_of_mass() indi1.translate(-1 * com1) com2 = indi2.get_center_of_mass() indi2.translate(-1 * com2) # Select random axis, random angle, and random position and rotate individuals cmax = [ min(numpy.maximum.reduce(indi1.get_positions())[i], numpy.maximum.reduce(indi2.get_positions())[i]) for i in range(3) ] cmin = [ min(numpy.minimum.reduce(indi1.get_positions())[i], numpy.minimum.reduce(indi2.get_positions())[i]) for i in range(3) ] n = 0 while n < 10: rax = random.choice(["x", "-x", "y", "-y", "z", "-z"]) rang = random.random() * 90 rpos = [random.uniform(cmin[i] * 0.8, cmax[i] * 0.8) for i in range(3)] indi1.rotate(rax, a=rang, center=rpos, rotate_cell=False) # Search for atoms in individual 1 that are above the xy plane group1 = Atoms(cell=ind1[0].get_cell(), pbc=ind1[0].get_pbc()) indices1 = [] for one in indi1: if one.position[2] >= 0: group1.append(one) indices1.append(one.index) if len(group1) > 2 and len(group1) < len(indi1): break else: n += 1 indi1.rotate(rax, a=-1 * rang, center=rpos, rotate_cell=False) indi2.rotate(rax, a=rang, center=rpos, rotate_cell=False) if debug: print "Group1 size = ", len(group1) print "Position = ", rpos print "Angle = ", rang print "Axis = ", rax print "Number of tries = ", n if len(group1) != 0: # Apply concentration forcing if needed group2 = Atoms(cell=ind2[0].get_cell(), pbc=ind2[0].get_pbc()) indices2 = [] dellist = [] for one in indi2: if one.position[2] >= 0: group2.append(one) indices2.append(one.index) if Optimizer.forcing == "Concentration": symlist = list(set(indi1.get_chemical_symbols())) seplist = [[atm for atm in group2 if atm.symbol == sym] for sym in symlist] group2n = Atoms(cell=group2.get_cell(), pbc=group2.get_pbc()) indices2n = [] dellist = [] for one in group1: sym1 = one.symbol listpos = [i for i, s in enumerate(symlist) if s == sym1][0] if len(seplist[listpos]) > 0: pos = random.choice(range(len(seplist[listpos]))) group2n.append(seplist[listpos][pos]) indices2n.append(indices2[seplist[listpos][pos].index]) del seplist[listpos][pos] else: dellist.append(one.index) if len(dellist) != 0: dellist.sort(reverse=True) for one in dellist: del group1[one] del indices1[one] indices2 = indices2n group2 = group2n.copy() else: dellist = [] while len(group2) < len(group1) - len(dellist): # Too many atoms in group 1 dellist.append(random.choice(group1).index) if len(dellist) != 0: dellist.sort(reverse=True) for one in dellist: del group1[one] del indices1[one] dellist = [] while len(group1) < len(group2) - len(dellist): # Too many atoms in group 2 dellist.append(random.choice(group2).index) if len(dellist) != 0: dellist.sort(reverse=True) for one in dellist: del group2[one] del indices2[one] other2 = Atoms(cell=ind2[0].get_cell(), pbc=ind2[0].get_pbc()) for one in indi2: if one.index not in indices2: other2.append(one) other1 = Atoms(cell=ind1[0].get_cell(), pbc=ind1[0].get_pbc()) for one in indi1: if one.index not in indices1: other1.append(one) indi1 = group2.copy() indi1.extend(other1) indi2 = group1.copy() indi2.extend(other2) # DEBUG: Write crossover to file if debug: write_xyz(Optimizer.debugfile, group1, "group1") write_xyz(Optimizer.debugfile, other1, "other1") write_xyz(Optimizer.debugfile, group2, "group2") write_xyz(Optimizer.debugfile, other2, "other2") print "Length of group1 = ", len(group1), "Length of group2", len(group2) # DEBUG: Check structure of atoms exchanged for sym, c, m, u in Optimizer.atomlist: nc = len([atm for atm in indi1 if atm.symbol == sym]) Optimizer.output.write( "CX RANDROTCT_Defect: Individual 1 contains " + repr(nc) + " " + repr(sym) + " atoms\n" ) nc = len([atm for atm in indi2 if atm.symbol == sym]) Optimizer.output.write( "CX RANDROTCT_Defect: Individual 2 contains " + repr(nc) + " " + repr(sym) + " atoms\n" ) if Optimizer.forcing != "Concentration": for i in range(len(Optimizer.atomlist)): atms1 = [inds for inds in indi1 if inds.symbol == Optimizer.atomlist[i][0]] atms2 = [inds for inds in indi2 if inds.symbol == Optimizer.atomlist[i][0]] if len(atms1) == 0: if len(atms2) == 0: indi1[random.randint(0, len(indi1) - 1)].symbol == Optimizer.atomlist[i][0] indi2[random.randint(0, len(indi2) - 1)].symbol == Optimizer.atomlist[i][0] else: indi1.append(atms2[random.randint(0, len(atms2) - 1)]) indi1.pop(random.randint(0, len(indi1) - 2)) else: if len(atms2) == 0: indi2.append(atms1[random.randint(0, len(atms1) - 1)]) indi2.pop(random.randint(0, len(indi2) - 2)) indi1.rotate(rax, a=-1 * rang, center=rpos, rotate_cell=False) indi2.rotate(rax, a=-1 * rang, center=rpos, rotate_cell=False) if Optimizer.structure == "Defect": indi1 = shift_atoms(indi1, [-p for p in com1]) indi2 = shift_atoms(indi2, [-p for p in com2]) else: indi1.translate(com1) indi2.translate(com2) # DEBUG: Check structure and number of atoms in crystal if Optimizer.structure == "Defect": solid1 = Atoms() solid1.extend(indi1) solid1.extend(ind1.bulki) solid2 = Atoms() solid2.extend(indi2) solid2.extend(ind2.bulki) for sym, c, m, u in Optimizer.atomlist: nc = len([atm for atm in solid1 if atm.symbol == sym]) Optimizer.output.write( "CX RANDROTCT_Defect: Defect 1 configuration contains " + repr(nc) + " " + repr(sym) + " atoms\n" ) nc = len([atm for atm in solid2 if atm.symbol == sym]) Optimizer.output.write( "CX RANDROTCT_Defect: Defect 2 configuration contains " + repr(nc) + " " + repr(sym) + " atoms\n" ) if debug: Optimizer.output.flush() # pdb.set_trace() ind1[0] = indi1 ind2[0] = indi2 return ind1, ind2
def 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
# Takes 30 mins with 8 cores in domain-parallel (memory ~500mb, max 1.5gb) import numpy as np from ase import Atom, Atoms from gpaw import GPAW, MixerDif, mpi from gpaw.lrtddft import LrTDDFT from gpaw.pes.dos import DOSPES from gpaw.pes.tddft import TDDFTPES atoms = Atoms([Atom('C', (7.666263598984184, 7.637780850431168, 8.289450797111844)), Atom('O', (8.333644370007132, 8.362384430165646, 7.710230973847514))]) atoms.center(vacuum=8) h = 0.15 N_c = np.round(atoms.get_cell().diagonal() / h / 16) * 16 m_c = GPAW(gpts=N_c, nbands=6, mixer=MixerDif(0.1, 5, weight=100.0), #convergence={'bands':10}, parallel={'domain': mpi.size}, xc='PBE', txt='CO-m.txt', spinpol=True) m = atoms.copy() m.set_initial_magnetic_moments([-1,1]) m.set_calculator(m_c) m.get_potential_energy() d_c = GPAW(gpts=N_c, nbands=16, mixer=MixerDif(0.1, 5, weight=100.0), convergence={'bands':10}, parallel={'domain': mpi.size}, xc='PBE', txt='CO-d.txt', spinpol=True)
import numpy as np from ase import Atoms from ase.io.trajectory import PickleTrajectory from ase.calculators.emt import EMT a = 4.0 # approximate lattice constant b = a / 2 ag = Atoms('Ag', cell=[(0,b,b), (b,0,b), (b,b,0)], pbc=1, calculator=EMT()) # use EMT potential cell = ag.get_cell() traj = PickleTrajectory('Ag.traj', 'w') for x in np.linspace(0.95, 1.05, 5): ag.set_cell(cell * x, scale_atoms=True) traj.write(ag)
# Calculate potential energy per atom for orthogonal unitcell atoms = hcp0001('C', a=a / sqrt(3), vacuum=d, size=(3, 2, 1), orthogonal=True) del atoms[[1, -1]] atoms.center(axis=0) atoms.set_calculator(calc) kpts_c = np.ceil(50 / np.sum(atoms.get_cell()**2, axis=1)**0.5).astype(int) kpts_c[~atoms.get_pbc()] = 1 calc.set(kpts=kpts_c) eppa1 = atoms.get_potential_energy() / len(atoms) F1_av = atoms.get_forces() equal(np.abs(F1_av).max(), 0, 5e-3) # Redo calculation with non-orthogonal unitcell atoms = Atoms(symbols='C2', pbc=(True, True, False), positions=[(a / 2, -sqrt(3) / 6 * a, d), (a / 2, sqrt(3) / 6 * a, d)], cell=[(a / 2, -sqrt(3) / 2 * a, 0), (a / 2, sqrt(3) / 2 * a, 0), (0, 0, 2 * d)]) atoms.set_calculator(calc) kpts_c = np.ceil(50 / np.sum(atoms.get_cell()**2, axis=1)**0.5).astype(int) kpts_c[~atoms.get_pbc()] = 1 calc.set(kpts=kpts_c) eppa2 = atoms.get_potential_energy() / len(atoms) F2_av = atoms.get_forces() equal(np.abs(F2_av).max(), 0, 5e-3) equal(eppa1, eppa2, 1e-3)
def read_vasp(filename='CONTCAR'): """Import POSCAR/CONTCAR type file. Reads unitcell, atom positions and constraints from the POSCAR/CONTCAR file and tries to read atom types from POSCAR/CONTCAR header, if this fails the atom types are read from OUTCAR or POTCAR file. """ from ase import Atoms, Atom from ase.constraints import FixAtoms, FixScaled from ase.data import chemical_symbols import numpy as np if isinstance(filename, str): f = open(filename) else: # Assume it's a file-like object f = filename # First line should contain the atom symbols , eg. "Ag Ge" in # the same order # as later in the file (and POTCAR for the full vasp run) atomtypes = f.readline().split() # Sometimes the first line in POSCAR/CONTCAR is of the form # "CoP3_In-3.pos". Check for this case and extract atom types if len(atomtypes) == 1 and '_' in atomtypes[0]: atomtypes = get_atomtypes_from_formula(atomtypes[0]) lattice_constant = float(f.readline().split()[0]) # Now the lattice vectors a = [] for ii in range(3): s = f.readline().split() floatvect = float(s[0]), float(s[1]), float(s[2]) a.append(floatvect) basis_vectors = np.array(a) * lattice_constant # Number of atoms. Again this must be in the same order as # in the first line # or in the POTCAR or OUTCAR file atom_symbols = [] numofatoms = f.readline().split() #vasp5.1 has an additional line which gives the atom types #the following try statement skips this line try: int(numofatoms[0]) except ValueError: numofatoms = f.readline().split() # check for comments in numofatoms line and get rid of them if necessary commentcheck = np.array(['!' in s for s in numofatoms]) if commentcheck.any(): # only keep the elements up to the first including a '!': numofatoms = numofatoms[:np.arange(len(numofatoms))[commentcheck][0]] numsyms = len(numofatoms) if len(atomtypes) < numsyms: # First line in POSCAR/CONTCAR didn't contain enough symbols. atomtypes = atomtypes_outpot(f.name, numsyms) else: try: for atype in atomtypes[:numsyms]: if not atype in chemical_symbols: raise KeyError except KeyError: atomtypes = atomtypes_outpot(f.name, numsyms) for i, num in enumerate(numofatoms): numofatoms[i] = int(num) [atom_symbols.append(atomtypes[i]) for na in xrange(numofatoms[i])] # Check if Selective dynamics is switched on sdyn = f.readline() selective_dynamics = sdyn[0].lower() == "s" # Check if atom coordinates are cartesian or direct if selective_dynamics: ac_type = f.readline() else: ac_type = sdyn cartesian = ac_type[0].lower() == "c" or ac_type[0].lower() == "k" tot_natoms = sum(numofatoms) atoms_pos = np.empty((tot_natoms, 3)) if selective_dynamics: selective_flags = np.empty((tot_natoms, 3), dtype=bool) for atom in xrange(tot_natoms): ac = f.readline().split() atoms_pos[atom] = (float(ac[0]), float(ac[1]), float(ac[2])) if selective_dynamics: curflag = [] for flag in ac[3:6]: curflag.append(flag == 'F') selective_flags[atom] = curflag # Done with all reading if type(filename) == str: f.close() if cartesian: atoms_pos *= lattice_constant atoms = Atoms(symbols = atom_symbols, cell = basis_vectors, pbc = True) if cartesian: atoms.set_positions(atoms_pos) else: atoms.set_scaled_positions(atoms_pos) if selective_dynamics: constraints = [] indices = [] for ind, sflags in enumerate(selective_flags): if sflags.any() and not sflags.all(): constraints.append(FixScaled(atoms.get_cell(), ind, sflags)) elif sflags.all(): indices.append(ind) if indices: constraints.append(FixAtoms(indices)) if constraints: atoms.set_constraint(constraints) return atoms
def gen_pop_plate(atomlist, sizeinput, dir_par=[1,-1,0], dir_per=[1,1,1], crystal=False): ''' Last edited by Hyunseok Ko on 10-15-2014 Function to generate defects in a plate. The center of plate is equal to the center of mass of the bulk structure. -- Plate orientation can be specified by following parameters:: dir_par and dir_per is a directional vector (do not necessarily be a unit vector) which sets the axis of the plate -- Plate dimension can be chosen (Needs development. Manual setup for now) by setting 'size' in this module. ''' # Setup axis vectors for plate size=[sizeinput, sizeinput, 3] #print 'HKK :: plate vector', size # Set unit vectors for plate dir_crs=numpy.cross(dir_par, dir_per) uvec_par=[x/((dir_par[0]**2+dir_par[1]**2+dir_par[2]**2)**0.5) for x in dir_par] uvec_crs=[x/((dir_crs[0]**2+dir_crs[1]**2+dir_crs[2]**2)**0.5) for x in dir_crs] uvec_per=[x/((dir_per[0]**2+dir_per[1]**2+dir_per[2]**2)**0.5) for x in dir_per] #print 'Unit vectors of new xyz axis' #print uvec_par, uvec_crs, uvec_per # Set vectors for plate vec_par=[x*size[0] for x in uvec_par] vec_crs=[x*size[1] for x in uvec_crs] vec_per=[x*size[2] for x in uvec_per] # Compute rotation angles from primary axis to axis for plate (If loop to avoid floating error) temp=[-uvec_per[1]/((1-uvec_per[2]**2)**0.5), uvec_per[2],uvec_crs[2]/((1-uvec_per[2]**2)**0.5)] if [temp[x] for x in range(3)] >=1: temp[x]=1 alpha=numpy.arccos(temp[0]) beta=numpy.arccos(temp[1]) gamma=numpy.arccos(temp[2]) # Get list of atom types for all atoms in cluster indiv=Atoms() indiv.set_cell(size) for s,c,m,u in atomlist: if c > 0: for i in range(c): temppos = [random.uniform(0,size[j]) for j in range(3)] # Rotating the defect position to the plate pos = rot_vec(temppos,alpha,beta,gamma) at=Atom(symbol=s,position=pos) indiv.append(at) if crystal: stro='' natoms=sum([c for s,c,m,u in atomlist]) pos=indiv.get_scaled_positions() structure=random.choice(crystal) cello=indiv.get_cell() if structure=='cubic': #Set to cubic shape an,bn,cn = [numpy.linalg.norm(v) for v in cello] a=(an+bn+cn)/3.0 celln=numpy.array([[a,0,0],[0,a,0],[0,0,a]]) stro+='Setting cell to cubic\n' elif structure=='orthorhombic': #Set to orthorhombic a=random.uniform(2,natoms**0.3333*size) b=random.uniform(2,natoms**0.3333*size) c=random.uniform(2,natoms**0.3333*size) celln=numpy.array([[a,0,0],[0,b,0],[0,0,c]]) stro+='Setting cell to orthorhombic\n' elif structure=='tetragonal': #Set to tetragonal shape an,bn,cn = [numpy.linalg.norm(v) for v in cello] a=(an+bn)/2.0 c=cn if c==a: c=random.uniform(1,natoms**0.3333*size) celln=numpy.array([[a,0,0],[0,a,0],[0,0,c]]) stro+='Setting cell to tetragonal\n' elif structure=='hexagonal': #Set to hexagonal shape an,bn,cn = [numpy.linalg.norm(v) for v in cello] a=(an+bn)/2.0 c=cn if c<=a: c=random.uniform(a+1,natoms**0.3333*size) trans=numpy.array([[1,0,0],[-0.5,(3.0**0.5)/2.0,0],[0,0,1]]) trans[0]=[a*i for i in trans[0]] trans[1]=[a*i for i in trans[1]] trans[2]=[c*i for i in trans[2]] celln=trans stro+='Setting cell to Hexagonal\n' elif structure=='monoclinic': #Set to monoclinic a,b,c = [numpy.linalg.norm(v) for v in cello] if a==b: b=random.uniform(1,natoms**0.3333*size) trans=numpy.array([(1+random.random())*c, 0, (1+random.random())*c]) celln=numpy.array([[a,0,0],[0,b,0],[0,0,0]]) celln[2]=trans stro+='Setting cell to monoclinic\n' elif structure=='triclinic': #Set to triclinic a,b,c = [numpy.linalg.norm(v) for v in cello] celln=numpy.array([[a,0,0],[(1+random.random())*b,(1+random.random())*b,0],[(1+random.random())*c,0,(1+random.random())*c]]) stro+='Setting cell to triclinic\n' indiv.set_cell(celln) indiv.set_scaled_positions(pos) stro+=repr(indiv.get_cell())+'\n' return indiv, stro return indiv
from ase import Atoms, Atom import numpy as np b = 7.1 atoms = Atoms([Atom('C', [0., 0., 0.]), Atom('O', [1.1, 0., 0.])], cell=[[b, b, 0.], [b, 0., b], [0., b, b]]) # get unit cell vectors and their lengths (a1, a2, a3) = atoms.get_cell() print '|a1| = {0:1.2f} Ang'.format(np.sum(a1**2)**0.5) print '|a2| = {0:1.2f} Ang'.format(np.linalg.norm(a2)) print '|a3| = {0:1.2f} Ang'.format(np.sum(a3**2)**0.5)
def test_chain_operators(seed): from ase.ga.startgenerator import StartGenerator from ase.ga.cutandsplicepairing import CutAndSplicePairing from ase.ga.standardmutations import StrainMutation from ase.ga.utilities import (closest_distances_generator, atoms_too_close, CellBounds) import numpy as np from ase import Atoms # set up the random number generator rng = np.random.RandomState(seed) slab = Atoms('', cell=(0, 16, 16), pbc=[True, False, False]) blocks = ['C'] * 8 n_top = 8 use_tags = False num_vcv = 1 box_volume = 8. * n_top blmin = closest_distances_generator(atom_numbers=[6], ratio_of_covalent_radii=0.6) cellbounds = CellBounds( bounds={ 'phi': [0.1 * 180., 0.9 * 180.], 'chi': [0.1 * 180., 0.9 * 180.], 'psi': [0.1 * 180., 0.9 * 180.], 'a': [1, 6] }) box_to_place_in = [[None, 6., 6.], [None, [0., 4., 0.], [0., 0., 4.]]] sg = StartGenerator(slab, blocks, blmin, box_volume=box_volume, splits=None, box_to_place_in=box_to_place_in, number_of_variable_cell_vectors=num_vcv, cellbounds=cellbounds, test_too_far=True, test_dist_to_slab=False, rng=rng) parents = [] for i in range(2): a = None while a is None: a = sg.get_new_candidate() a.info['confid'] = i parents.append(a) assert len(a) == n_top assert len(np.unique(a.get_tags())) == 8 assert np.allclose(a.get_pbc(), slab.get_pbc()) p = a.get_positions() assert np.min(p[:, 1:]) > 6. assert np.max(p[:, 1:]) < 6. + 4. assert not atoms_too_close(a, blmin, use_tags=use_tags) c = a.get_cell() assert np.allclose(c[1:], slab.get_cell()[1:]) assert cellbounds.is_within_bounds(c) v = a.get_volume() * (4. / 16.)**2 assert abs(v - box_volume) < 1e-5 # Test cut-and-splice pairing and strain mutation pairing = CutAndSplicePairing(slab, n_top, blmin, number_of_variable_cell_vectors=num_vcv, p1=1., p2=0., minfrac=0.15, cellbounds=cellbounds, use_tags=use_tags, rng=rng) strainmut = StrainMutation(blmin, cellbounds=cellbounds, number_of_variable_cell_vectors=num_vcv, use_tags=use_tags, rng=rng) strainmut.update_scaling_volume(parents) for operator in [pairing, strainmut]: child = None while child is None: child, desc = operator.get_new_individual(parents) assert not atoms_too_close(child, blmin, use_tags=use_tags) cell = child.get_cell() assert cellbounds.is_within_bounds(cell) assert np.allclose(cell[1:], slab.get_cell()[1:])
from ase.optimize import QuasiNewton, FIRE from ase.constraints import FixAtoms from ase.neb import NEB from ase.io import write, PickleTrajectory from ase.calculators.emt import ASAP # Distance between Cu atoms on a (100) surface: d = 2.74 h1 = d * sqrt(3) / 2 h2 = d * sqrt(2.0 / 3) initial = Atoms(symbols='Pt', positions=[(0, 0, 0)],#(1.37,0.79,2.24),(2.74,1.58,4.48),(0,0,6.72),(1.37,0.79,8.96),(2.74,1.58,11.2)], cell=([(d,0,0),(d/2,h1,0),(d/2,h1/3,-h2)]), pbc=(True, True, True)) initial *= (7, 8, 6) # 5x5 (100) surface-cell cell = initial.get_cell() cell[2] = (0, 0, 22) initial.set_cell(cell) #initial.set_pbc((True,True,False)) # Approximate height of Ag atom on Cu(100) surfece: h0 = 2.2373 initial += Atom('Pt', (10.96, 11.074, h0)) initial += Atom('Pt', (13.7, 11.074, h0)) initial += Atom('Pt', (9.59, 8.701, h0)) initial += Atom('Pt', (12.33, 8.701, h0)) initial += Atom('Pt', (15.07, 8.701, h0)) initial += Atom('Pt', (10.96, 6.328, h0)) initial += Atom('Pt', (13.7, 6.328, h0)) if 0: view(initial)
for opt in OPTIONS: a0 = 3.554 * opt / np.sqrt(2) # c0 = np.sqrt(8 / 3.0) * a0 c0= 1.585 * a0 atoms = Atoms('Fe2', scaled_positions=[(0, 0, 0), (1./3., 1./3., 1./2.)], cell = [[1./2.,sqrt(3)/2.,0],[-1./2., sqrt(3)/2., 0] ,[0,0,1]], pbc=(1,1,1)) # atoms.set_cell([[1/2, sqrt(3)/2, 0],[-1/2, sqrt(3)/2, 0] ,[0,0,1]]) scale = [[a0,0,0],[0,a0,0],[0,0,c0]] atoms.set_cell(np.dot( atoms.get_cell(), scale), scale_atoms=True) atoms.set_tags([1, 1]) atoms = atoms*(1,1,2) print atoms.get_cell() print atoms.positions alloys = [] alloys.append(Alloy(1, 'Fe', fe, 0.0)) alloys.append(Alloy(1, 'Cr', cr, 0.0)) calc = EMTO() calc.set(dir='{0}/calc/{1}/opt-{2:0.3f}'.format(temp_dir, name, opt), lat=9,
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
def read_vasp(filename='CONTCAR'): """Import POSCAR/CONTCAR type file. Reads unitcell, atom positions and constraints from the POSCAR/CONTCAR file and tries to read atom types from POSCAR/CONTCAR header, if this fails the atom types are read from OUTCAR or POTCAR file. """ from ase import Atoms, Atom from ase.constraints import FixAtoms, FixScaled from ase.data import chemical_symbols import numpy as np if isinstance(filename, str): f = open(filename) else: # Assume it's a file-like object f = filename # The first line is in principle a comment line, however in VASP # 4.x a common convention is to have it contain the atom symbols, # eg. "Ag Ge" in the same order as later in the file (and POTCAR # for the full vasp run). In the VASP 5.x format this information # is found on the fifth line. Thus we save the first line and use # it in case we later detect that we're reading a VASP 4.x format # file. line1 = f.readline() lattice_constant = float(f.readline().split()[0]) # Now the lattice vectors a = [] for ii in range(3): s = f.readline().split() floatvect = float(s[0]), float(s[1]), float(s[2]) a.append(floatvect) basis_vectors = np.array(a) * lattice_constant # Number of atoms. Again this must be in the same order as # in the first line # or in the POTCAR or OUTCAR file atom_symbols = [] numofatoms = f.readline().split() # Check whether we have a VASP 4.x or 5.x format file. If the # format is 5.x, use the fifth line to provide information about # the atomic symbols. vasp5 = False try: int(numofatoms[0]) except ValueError: vasp5 = True atomtypes = numofatoms numofatoms = f.readline().split() # check for comments in numofatoms line and get rid of them if necessary commentcheck = np.array(['!' in s for s in numofatoms]) if commentcheck.any(): # only keep the elements up to the first including a '!': numofatoms = numofatoms[:np.arange(len(numofatoms))[commentcheck][0]] if not vasp5: atomtypes = line1.split() numsyms = len(numofatoms) if len(atomtypes) < numsyms: # First line in POSCAR/CONTCAR didn't contain enough symbols. # Sometimes the first line in POSCAR/CONTCAR is of the form # "CoP3_In-3.pos". Check for this case and extract atom types if len(atomtypes) == 1 and '_' in atomtypes[0]: atomtypes = get_atomtypes_from_formula(atomtypes[0]) else: atomtypes = atomtypes_outpot(f.name, numsyms) else: try: for atype in atomtypes[:numsyms]: if atype not in chemical_symbols: raise KeyError except KeyError: atomtypes = atomtypes_outpot(f.name, numsyms) for i, num in enumerate(numofatoms): numofatoms[i] = int(num) [atom_symbols.append(atomtypes[i]) for na in range(numofatoms[i])] # Check if Selective dynamics is switched on sdyn = f.readline() selective_dynamics = sdyn[0].lower() == 's' # Check if atom coordinates are cartesian or direct if selective_dynamics: ac_type = f.readline() else: ac_type = sdyn cartesian = ac_type[0].lower() == 'c' or ac_type[0].lower() == 'k' tot_natoms = sum(numofatoms) atoms_pos = np.empty((tot_natoms, 3)) if selective_dynamics: selective_flags = np.empty((tot_natoms, 3), dtype=bool) for atom in range(tot_natoms): ac = f.readline().split() atoms_pos[atom] = (float(ac[0]), float(ac[1]), float(ac[2])) if selective_dynamics: curflag = [] for flag in ac[3:6]: curflag.append(flag == 'F') selective_flags[atom] = curflag # Done with all reading if isinstance(filename, str): f.close() if cartesian: atoms_pos *= lattice_constant atoms = Atoms(symbols=atom_symbols, cell=basis_vectors, pbc=True) if cartesian: atoms.set_positions(atoms_pos) else: atoms.set_scaled_positions(atoms_pos) if selective_dynamics: constraints = [] indices = [] for ind, sflags in enumerate(selective_flags): if sflags.any() and not sflags.all(): constraints.append(FixScaled(atoms.get_cell(), ind, sflags)) elif sflags.all(): indices.append(ind) if indices: constraints.append(FixAtoms(indices)) if constraints: atoms.set_constraint(constraints) return atoms
pass else: w += ['png', 'eps'] for format in w: print format, 'O', fname1 = 'io-test.1.' + format fname2 = 'io-test.2.' + format write(fname1, atoms, format=format) if format not in ['cube', 'png', 'eps', 'cfg', 'struct', 'etsf', 'gen']: write(fname2, images, format=format) if format in r: print 'I' a1 = read(fname1) assert np.all(np.abs(a1.get_positions() - atoms.get_positions()) < 1e-6) if format in ['traj', 'cube', 'cfg', 'struct', 'gen']: assert np.all(np.abs(a1.get_cell() - atoms.get_cell()) < 1e-6) if format in ['cfg']: assert np.all(np.abs(a1.get_array('extra') - atoms.get_array('extra')) < 1e-6) if format not in ['cube', 'png', 'eps', 'cfg', 'struct', 'etsf', 'gen']: a2 = read(fname2) a3 = read(fname2, index=0) a4 = read(fname2, index=slice(None)) assert len(a4) == 2 else: print
def read_vasp(filename='CONTCAR'): """Import POSCAR/CONTCAR type file. Reads unitcell, atom positions and constraints from the POSCAR/CONTCAR file and tries to read atom types from POSCAR/CONTCAR header, if this fails the atom types are read from OUTCAR or POTCAR file. """ from ase import Atoms from ase.constraints import FixAtoms, FixScaled from ase.data import chemical_symbols import numpy as np if isinstance(filename, basestring): f = open(filename) else: # Assume it's a file-like object f = filename # The first line is in principle a comment line, however in VASP # 4.x a common convention is to have it contain the atom symbols, # eg. "Ag Ge" in the same order as later in the file (and POTCAR # for the full vasp run). In the VASP 5.x format this information # is found on the fifth line. Thus we save the first line and use # it in case we later detect that we're reading a VASP 4.x format # file. line1 = f.readline() lattice_constant = float(f.readline().split()[0]) # Now the lattice vectors a = [] for ii in range(3): s = f.readline().split() floatvect = float(s[0]), float(s[1]), float(s[2]) a.append(floatvect) basis_vectors = np.array(a) * lattice_constant # Number of atoms. Again this must be in the same order as # in the first line # or in the POTCAR or OUTCAR file atom_symbols = [] numofatoms = f.readline().split() # Check whether we have a VASP 4.x or 5.x format file. If the # format is 5.x, use the fifth line to provide information about # the atomic symbols. vasp5 = False try: int(numofatoms[0]) except ValueError: vasp5 = True atomtypes = numofatoms numofatoms = f.readline().split() # check for comments in numofatoms line and get rid of them if necessary commentcheck = np.array(['!' in s for s in numofatoms]) if commentcheck.any(): # only keep the elements up to the first including a '!': numofatoms = numofatoms[:np.arange(len(numofatoms))[commentcheck][0]] if not vasp5: atomtypes = line1.split() numsyms = len(numofatoms) if len(atomtypes) < numsyms: # First line in POSCAR/CONTCAR didn't contain enough symbols. # Sometimes the first line in POSCAR/CONTCAR is of the form # "CoP3_In-3.pos". Check for this case and extract atom types if len(atomtypes) == 1 and '_' in atomtypes[0]: atomtypes = get_atomtypes_from_formula(atomtypes[0]) else: atomtypes = atomtypes_outpot(f.name, numsyms) else: try: for atype in atomtypes[:numsyms]: if atype not in chemical_symbols: raise KeyError except KeyError: atomtypes = atomtypes_outpot(f.name, numsyms) for i, num in enumerate(numofatoms): numofatoms[i] = int(num) [atom_symbols.append(atomtypes[i]) for na in range(numofatoms[i])] # Check if Selective dynamics is switched on sdyn = f.readline() selective_dynamics = sdyn[0].lower() == 's' # Check if atom coordinates are cartesian or direct if selective_dynamics: ac_type = f.readline() else: ac_type = sdyn cartesian = ac_type[0].lower() == 'c' or ac_type[0].lower() == 'k' tot_natoms = sum(numofatoms) atoms_pos = np.empty((tot_natoms, 3)) if selective_dynamics: selective_flags = np.empty((tot_natoms, 3), dtype=bool) for atom in range(tot_natoms): ac = f.readline().split() atoms_pos[atom] = (float(ac[0]), float(ac[1]), float(ac[2])) if selective_dynamics: curflag = [] for flag in ac[3:6]: curflag.append(flag == 'F') selective_flags[atom] = curflag # Done with all reading if isinstance(filename, basestring): f.close() if cartesian: atoms_pos *= lattice_constant atoms = Atoms(symbols=atom_symbols, cell=basis_vectors, pbc=True) if cartesian: atoms.set_positions(atoms_pos) else: atoms.set_scaled_positions(atoms_pos) if selective_dynamics: constraints = [] indices = [] for ind, sflags in enumerate(selective_flags): if sflags.any() and not sflags.all(): constraints.append(FixScaled(atoms.get_cell(), ind, sflags)) elif sflags.all(): indices.append(ind) if indices: constraints.append(FixAtoms(indices)) if constraints: atoms.set_constraint(constraints) return atoms
def sphere(atomlist, fill_factor=0.74, radius=None, cell=None): """Generates a random sphere of particles given an atomlist and radius. If radius is None, one is automatically estimated. min_dist and tries_b4_expand are parameters that govern how stricly the proximity of atoms are enforced. """ if radius is None: radius = get_particle_radius(atomlist, fill_factor) # Create a list of random order of the atoms chemical_symbols = [] for atom in atomlist: chemical_symbols += [atom[0]] * atom[1] random.shuffle(chemical_symbols) unit_vec = np.array([random_three_vector() for i in range(len(chemical_symbols))]) D = radius * np.random.sample(size=len(chemical_symbols)) ** (1.0/3.0) positions = np.array([D]).T * unit_vec indiv = Atoms(symbols=chemical_symbols, positions=positions) if cell is not None: indiv.set_cell(cell) cell_center = np.sum(indiv.get_cell(), axis=1) / 2.0 indiv.translate(indiv.get_center_of_mass() + cell_center) indiv.set_pbc(True) return indiv
def eval_energy(input): """Function to evaluate energy of an individual Inputs: input = [Optimizer class object with parameters, Individual class structure to be evaluated] Outputs: energy, bul, individ, signal energy = energy of Individual evaluated bul = bulk structure of Individual if simulation structure is Defect individ = Individual class structure evaluated signal = string of information about evaluation """ if input[0]==None: energy=0 bul=0 individ=0 rank = MPI.COMM_WORLD.Get_rank() signal='Evaluated none individual on '+repr(rank)+'\n' else: [Optimizer, individ]=input if Optimizer.calc_method=='MAST': energy = individ.energy bul = individ.energy signal = 'Recieved MAST structure\n' else: if Optimizer.parallel: rank = MPI.COMM_WORLD.Get_rank() if not Optimizer.genealogy: STR='----Individual ' + str(individ.index)+ ' Optimization----\n' else: STR='----Individual ' + str(individ.history_index)+ ' Optimization----\n' indiv=individ[0] if 'EE' in Optimizer.debug: debug = True else: debug = False if debug: write_xyz(Optimizer.debugfile,indiv,'Recieved by eval_energy') Optimizer.debugfile.flush() if Optimizer.structure=='Defect': indi=indiv.copy() if Optimizer.alloy==True: bulk=individ.bulki else: bulk=individ.bulko nat=indi.get_number_of_atoms() csize=bulk.get_cell() totalsol=Atoms(cell=csize, pbc=True) totalsol.extend(indi) totalsol.extend(bulk) for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in totalsol if atm.symbol==sym]) STR+='Defect configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n' elif Optimizer.structure=='Surface': totalsol=Atoms() totalsol.extend(indiv) nat=indiv.get_number_of_atoms() totalsol.extend(individ.bulki) for sym,c,m,u in Optimizer.atomlist: nc=len([atm for atm in totalsol if atm.symbol==sym]) STR+='Surface-Bulk configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n' cell=numpy.maximum.reduce(indiv.get_cell()) totalsol.set_cell([cell[0],cell[1],500]) totalsol.set_pbc([True,True,False]) if Optimizer.constrain_position: ts = totalsol.copy() indc,indb,vacant,swap,stro = find_defects(ts,Optimizer.solidbulk,0) sbulk = Optimizer.solidbulk.copy() bcom = sbulk.get_center_of_mass() #totalsol.translate(-bulkcom) #indc.translate(-bulkcom) #totalsol.append(Atom(position=[0,0,0])) # for one in indc: # index = [atm.index for atm in totalsol if atm.position[0]==one.position[0] and atm.position[1]==one.position[1] and atm.position[2]==one.position[2]][0] # if totalsol.get_distance(-1,index) > Optimizer.sf: # r = random.random() # totalsol.set_distance(-1,index,Optimizer.sf*r,fix=0) # totalsol.pop() # totalsol.translate(bulkcom) com = indc.get_center_of_mass() dist = (sum((bcom[i] - com[i])**2 for i in range(3)))**0.5 if dist > Optimizer.sf: STR+='Shifting structure to within region\n' r = random.random()*Optimizer.sf comv = numpy.linalg.norm(com) ncom = [one*r/comv for one in com] trans = [ncom[i]-com[i] for i in range(3)] indices = [] for one in indc: id = [atm.index for atm in totalsol if atm.position[0]==one.position[0] and atm.position[1]==one.position[1] and atm.position[2]==one.position[2]][0] totalsol[id].position += trans # Check for atoms that are too close min_len=0.7 #pdb.set_trace() if not Optimizer.fixed_region: if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': cutoffs=[2.0 for one in totalsol] nl=NeighborList(cutoffs,bothways=True,self_interaction=False) nl.update(totalsol) for one in totalsol[0:nat]: nbatoms=Atoms() nbatoms.append(one) indices, offsets=nl.get_neighbors(one.index) for index, d in zip(indices,offsets): index = int(index) sym=totalsol[index].symbol pos=totalsol[index].position + numpy.dot(d,totalsol.get_cell()) at=Atom(symbol=sym,position=pos) nbatoms.append(at) while True: dflag=False for i in range(1,len(nbatoms)): d=nbatoms.get_distance(0,i) if d < min_len: nbatoms.set_distance(0,i,min_len+.01,fix=0.5) STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n' dflag=True if dflag==False: break for i in range(len(indices)): totalsol[indices[i]].position=nbatoms[i+1].position totalsol[one.index].position=nbatoms[0].position nl.update(totalsol) if debug: write_xyz(Optimizer.debugfile,totalsol,'After minlength check') Optimizer.debugfile.flush() else: for i in range(len(indiv)): for j in range(len(indiv)): if i != j: d=indiv.get_distance(i,j) if d < min_len: indiv.set_distance(i,j,min_len,fix=0.5) STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n' if debug: write_xyz(Optimizer.debugfile,indiv,'After minlength check') Optimizer.debugfile.flush() # Set calculator to use to get forces/energies if Optimizer.parallel: calc = setup_calculator(Optimizer) if Optimizer.fixed_region: pms=copy.deepcopy(calc.parameters) try: pms['mass'][len(pms['mass'])-1] += '\ngroup RO id >= '+repr(nat)+'\nfix freeze RO setforce 0.0 0.0 0.0\n' except KeyError: pms['pair_coeff'][0] += '\ngroup RO id >= '+repr(nat)+'\nfix freeze RO setforce 0.0 0.0 0.0\n' calc = LAMMPS(parameters=pms, files=calc.files, keep_tmp_files=calc.keep_tmp_files, tmp_dir=calc.tmp_dir) lmin = copy.copy(Optimizer.lammps_min) Optimizer.lammps_min = None Optimizer.static_calc = setup_calculator(Optimizer) Optimizer.lammps_min = lmin else: calc=Optimizer.calc if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': totalsol.set_calculator(calc) totalsol.set_pbc(True) else: indiv.set_calculator(calc) indiv.set_pbc(True) #Current bug in ASE optimizer-Lammps prevents pbc=false if Optimizer.structure=='Cluster': indiv.set_cell([500,500,500]) indiv.translate([250,250,250]) cwd=os.getcwd() # Perform Energy Minimization if not Optimizer.parallel: Optimizer.output.flush() if Optimizer.ase_min == True: try: if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': dyn=BFGS(totalsol) else: dyn=BFGS(indiv) dyn.run(fmax=Optimizer.ase_min_fmax, steps=Optimizer.ase_min_maxsteps) except OverflowError: STR+='--- Error: Infinite Energy Calculated - Implement Random ---\n' box=Atoms() indiv=gen_pop_box(Optimizer.natoms, Optimizer.atomlist, Optimizer.size) indiv.set_calculator(calc) dyn=BFGS(indiv) dyn.run(fmax=fmax, steps=steps) except numpy.linalg.linalg.LinAlgError: STR+='--- Error: Singular Matrix - Implement Random ---\n' indiv=gen_pop_box(Optimizer.natoms, Optimizer.atomlist, Optimizer.size) indiv.set_calculator(calc) dyn=BFGS(indiv) dyn.run(fmax=fmax, steps=steps) # Get Energy of Minimized Structure if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': en=totalsol.get_potential_energy() #force=numpy.maximum.reduce(abs(totalsol.get_forces())) if Optimizer.fitness_scheme == 'enthalpyfit': pressure=totalsol.get_isotropic_pressure(totalsol.get_stress()) cell_max=numpy.maximum.reduce(totalsol.get_positions()) cell_min=numpy.minimum.reduce(totalsol.get_positions()) cell=cell_max-cell_min volume=cell[0]*cell[1]*cell[2] else: pressure=0 volume=0 na=totalsol.get_number_of_atoms() ena=en/na energy=en individ[0]=totalsol[0:nat] bul=totalsol[(nat):len(totalsol)] STR+='Number of positions = '+repr(len(bul)+len(individ[0]))+'\n' individ[0].set_cell(csize) indiv=individ[0] else: en=indiv.get_potential_energy() if Optimizer.fitness_scheme == 'enthalpyfit': pressure=indiv.get_isotropic_pressure(indiv.get_stress()) cell_max=numpy.maximum.reduce(indiv.get_positions()) cell_min=numpy.minimum.reduce(indiv.get_positions()) cell=cell_max-cell_min volume=cell[0]*cell[1]*cell[2] else: pressure=0 volume=0 na=indiv.get_number_of_atoms() ena=en/na energy=ena individ[0]=indiv bul=0 else: if Optimizer.structure=='Defect' or Optimizer.structure=='Surface': if Optimizer.calc_method=='VASP': en=totalsol.get_potential_energy() calcb=Vasp(restart=True) totalsol=calcb.get_atoms() stress=calcb.read_stress() else: try: totcop=totalsol.copy() if debug: write_xyz(Optimizer.debugfile,totcop,'Individual sent to lammps') OUT=totalsol.calc.calculate(totalsol) totalsol=OUT['atoms'] totalsol.set_pbc(True) if Optimizer.fixed_region: if debug: print 'Energy of fixed region calc = ', OUT['thermo'][-1]['pe'] totalsol.set_calculator(Optimizer.static_calc) OUT=totalsol.calc.calculate(totalsol) totalsol=OUT['atoms'] totalsol.set_pbc(True) if debug: print 'Energy of static calc = ', OUT['thermo'][-1]['pe'] en=OUT['thermo'][-1]['pe'] stress=numpy.array([OUT['thermo'][-1][i] for i in ('pxx','pyy','pzz','pyz','pxz','pxy')])*(-1e-4*GPa) #force=numpy.maximum.reduce(abs(totalsol.get_forces())) if debug: write_xyz(Optimizer.debugfile,totalsol,'After Lammps Minimization') Optimizer.debugfile.flush() except Exception, e: os.chdir(cwd) STR+='WARNING: Exception during energy eval:\n'+repr(e)+'\n' f=open('problem-structures.xyz','a') write_xyz(f,totcop,data='Starting structure hindex='+individ.history_index) write_xyz(f,totalsol,data='Lammps Min structure') en=10 stress=0 f.close() if Optimizer.fitness_scheme == 'enthalpyfit': pressure=totalsol.get_isotropic_pressure(stress) cell_max=numpy.maximum.reduce(totalsol.get_positions()) cell_min=numpy.minimum.reduce(totalsol.get_positions()) cell=cell_max-cell_min volume=cell[0]*cell[1]*cell[2] else: pressure=totalsol.get_isotropic_pressure(stress) volume=0 na=totalsol.get_number_of_atoms() ena=en/na energy=en if Optimizer.structure=='Defect': if Optimizer.fixed_region==True or Optimizer.finddefects==False: individ[0]=totalsol[0:nat] bul=totalsol[(nat):len(totalsol)] individ[0].set_cell(csize) else: if 'FI' in Optimizer.debug: outt=find_defects(totalsol,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=Optimizer.debugfile) else: outt=find_defects(totalsol,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=False) individ[0]=outt[0] bul=outt[1] individ.vacancies = outt[2] individ.swaps = outt[3] STR += outt[4] indiv=individ[0] else: top,bul=find_top_layer(totalsol,Optimizer.surftopthick) indiv=top.copy() individ[0]=top.copy() else: