def test_water(): from ase.calculators.gaussian import Gaussian from ase.atoms import Atoms from ase.optimize.lbfgs import LBFGS from ase.io import read # First test to make sure Gaussian works calc = Gaussian(xc='pbe', chk='water.chk', label='water') calc.clean() water = Atoms('OHH', positions=[(0, 0, 0), (1, 0, 0), (0, 1, 0)], calculator=calc) opt = LBFGS(water) opt.run(fmax=0.05) forces = water.get_forces() energy = water.get_potential_energy() positions = water.get_positions() # Then test the IO routines water2 = read('water.log') forces2 = water2.get_forces() energy2 = water2.get_potential_energy() positions2 = water2.get_positions() # Compare distances since positions are different in standard orientation. dist = water.get_all_distances() dist2 = read('water.log', index=-1).get_all_distances() assert abs(energy - energy2) < 1e-7 assert abs(forces - forces2).max() < 1e-9 assert abs(positions - positions2).max() < 1e-6 assert abs(dist - dist2).max() < 1e-6
def write_dftb(filename, atoms): """Method to write atom structure in DFTB+ format (gen format) """ import numpy as np #sort atoms.set_masses() masses = atoms.get_masses() indexes = np.argsort(masses) atomsnew = Atoms() for i in indexes: atomsnew = atomsnew + atoms[i] if isinstance(filename, str): myfile = open(filename, 'w') else: # Assume it's a 'file-like object' myfile = filename ispbc = atoms.get_pbc() box = atoms.get_cell() if (any(ispbc)): myfile.write('%8d %2s \n' %(len(atoms), 'S')) else: myfile.write('%8d %2s \n' %(len(atoms), 'C')) chemsym = atomsnew.get_chemical_symbols() allchem = '' for i in chemsym: if i not in allchem: allchem = allchem + i + ' ' myfile.write(allchem+' \n') coords = atomsnew.get_positions() itype = 1 for iatom, coord in enumerate(coords): if iatom > 0: if chemsym[iatom] != chemsym[iatom-1]: itype = itype+1 myfile.write('%5i%5i %19.16f %19.16f %19.16f \n' \ %(iatom+1, itype, coords[iatom][0], coords[iatom][1], coords[iatom][2])) # write box if (any(ispbc)): #dftb dummy myfile.write(' %19.16f %19.16f %19.16f \n' %(0, 0, 0)) myfile.write(' %19.16f %19.16f %19.16f \n' %( box[0][0], box[0][1], box[0][2])) myfile.write(' %19.16f %19.16f %19.16f \n' %( box[1][0], box[1][1], box[1][2])) myfile.write(' %19.16f %19.16f %19.16f \n' %( box[2][0], box[2][1], box[2][2])) if type(filename) == str: myfile.close()
def write_dftb(filename, atoms): """Method to write atom structure in DFTB+ format (gen format) """ import numpy as np #sort atoms.set_masses() masses = atoms.get_masses() indexes = np.argsort(masses) atomsnew = Atoms() for i in indexes: atomsnew = atomsnew + atoms[i] if isinstance(filename, str): myfile = open(filename, 'w') else: # Assume it's a 'file-like object' myfile = filename ispbc = atoms.get_pbc() box = atoms.get_cell() if (any(ispbc)): myfile.write('%8d %2s \n' % (len(atoms), 'S')) else: myfile.write('%8d %2s \n' % (len(atoms), 'C')) chemsym = atomsnew.get_chemical_symbols() allchem = '' for i in chemsym: if i not in allchem: allchem = allchem + i + ' ' myfile.write(allchem + ' \n') coords = atomsnew.get_positions() itype = 1 for iatom, coord in enumerate(coords): if iatom > 0: if chemsym[iatom] != chemsym[iatom - 1]: itype = itype + 1 myfile.write('%5i%5i %19.16f %19.16f %19.16f \n' \ %(iatom+1, itype, coords[iatom][0], coords[iatom][1], coords[iatom][2])) # write box if (any(ispbc)): #dftb dummy myfile.write(' %19.16f %19.16f %19.16f \n' % (0, 0, 0)) myfile.write(' %19.16f %19.16f %19.16f \n' % (box[0][0], box[0][1], box[0][2])) myfile.write(' %19.16f %19.16f %19.16f \n' % (box[1][0], box[1][1], box[1][2])) myfile.write(' %19.16f %19.16f %19.16f \n' % (box[2][0], box[2][1], box[2][2])) if isinstance(filename, str): myfile.close()
def read_gen(fileobj): """Read structure in GEN format (refer to DFTB+ manual). Multiple snapshot are not allowed. """ if isinstance(fileobj, str): fileobj = open(fileobj) image = Atoms() lines = fileobj.readlines() line = lines[0].split() natoms = int(line[0]) pb_flag = line[1] if line[1] not in ['C', 'F', 'S']: raise IOError( 'Error in line #1: only C (Cluster), S (Supercell) or F (Fraction)' + 'are valid options') # Read atomic symbols line = lines[1].split() # Define a dictionary with symbols-id symboldict = dict() symbolid = 1 for symb in line: symboldict[symbolid] = symb symbolid += 1 # Read atoms (GEN format supports only single snapshot) del lines[:2] positions = [] symbols = [] for line in lines[:natoms]: dummy, symbolid, x, y, z = line.split()[:5] symbols.append(symboldict[int(symbolid)]) positions.append([float(x), float(y), float(z)]) image = Atoms(symbols=symbols, positions=positions) del lines[:natoms] # If Supercell, parse periodic vectors. # If Fraction, translate into Supercell. if pb_flag == 'C': return image else: # Dummy line: line after atom positions is not uniquely defined # in gen implementations, and not necessary in DFTB package del lines[:1] image.set_pbc([True, True, True]) p = [] for i in range(3): x, y, z = lines[i].split()[:3] p.append([float(x), float(y), float(z)]) image.set_cell([(p[0][0], p[0][1], p[0][2]), (p[1][0], p[1][1], p[1][2]), (p[2][0], p[2][1], p[2][2])]) if pb_flag == 'F': frac_positions = image.get_positions() image.set_scaled_positions(frac_positions) return image
def test_co_kernel_derivative(self): direction = np.array([1., 2., 3.]) direction /= np.linalg.norm(direction) atoms = Atoms(['C', 'O'], positions=np.array([-0.5 * direction, 0.5 * direction])) atoms.set_calculator(EMT()) def to_radius(x): xyzs = x.get_positions() r = np.sqrt(np.sum((xyzs[1, :] - xyzs[0, :])**2)) dr = np.zeros((1, 6)) dr[0, 0] = (xyzs[0, 0] - xyzs[1, 0]) / r dr[0, 1] = (xyzs[0, 1] - xyzs[1, 1]) / r dr[0, 2] = (xyzs[0, 2] - xyzs[1, 2]) / r dr[0, 3] = (xyzs[1, 0] - xyzs[0, 0]) / r dr[0, 4] = (xyzs[1, 1] - xyzs[0, 1]) / r dr[0, 5] = (xyzs[1, 2] - xyzs[0, 2]) / r return [r], dr kernel = RBFKernel(constant=100.0, length_scale=0.23) calc = NCGPRCalculator(input_transform=to_radius, kernel=kernel, C1=1e8, C2=1e8, opt_restarts=0) calc.add_data(atoms) K = calc.build_kernel_matrix() K_num = np.zeros_like(K) # kernel value is not tested: K_num[0, 0] = K[0, 0] x0 = atoms.get_positions() dx = 1e-4 def K_fun(x, y): a = np.array([to_radius(Atoms(['C', 'O'], positions=x))[0]]) b = np.array([to_radius(Atoms(['C', 'O'], positions=y))[0]]) return calc.kernel(a, b, dx=True, dy=True)[0, 0] for i in range(6): dxi = np.zeros(6) dxi[i] = dx dxi = dxi.reshape((2, 3)) # Test first derivative K_num[1 + i, 0] = self.num_dx_forth_order(K_fun, x0, x0, dxi) for j in range(6): dxj = np.zeros(6) dxj[j] = dx dxj = dxj.reshape((2, 3)) K_num[1 + i, 1 + j] = self.num_dxdy_forth_order( K_fun, x0, x0, dxi, dxj) # Test symmetry of derivatives K_num[0, 1 + i] = self.num_dy_forth_order(K_fun, x0, x0, dxi) np.testing.assert_allclose(K, K_num, atol=1E-5)
def read_geometry(filename, dir='.'): fh = open(os.path.join(dir, filename), 'rb') lines = list(filter(read_geometry_filter, fh.readlines())) # return geometry in ASE format geometry = [] for line in lines: sline = line.split() # find chemical symbol (the symbols in the file are lowercase) symbol = sline[-1] for s in chemical_symbols: if symbol == s.lower(): symbol = s break geometry.append(Atom(symbol=symbol, position=sline[:-1])) fh.close() atoms = Atoms(geometry) atoms.set_positions(atoms.get_positions()*Bohr) # convert to Angstrom return atoms
def unf(phonon, sc_mat, qpoints, knames=None, x=None, xpts=None): prim = phonon.get_primitive() prim = Atoms(symbols=prim.get_chemical_symbols(), cell=prim.get_cell(), positions=prim.get_positions()) #vesta_view(prim) sc_qpoints = np.array([np.dot(q, sc_mat) for q in qpoints]) phonon.set_qpoints_phonon(sc_qpoints, is_eigenvectors=True) freqs, eigvecs = phonon.get_qpoints_phonon() uf = phonon_unfolder(atoms=prim, supercell_matrix=sc_mat, eigenvectors=eigvecs, qpoints=sc_qpoints, phase=False) weights = uf.get_weights() #ax=plot_band_weight([list(x)]*freqs.shape[1],freqs.T*8065.6,weights[:,:].T*0.98+0.01,xticks=[knames,xpts],style='alpha') ax = plot_band_weight([list(x)] * freqs.shape[1], freqs.T * 33.356, weights[:, :].T * 0.99 + 0.001, xticks=[knames, xpts], style='alpha') return ax
def test_fix_symmetry_shuffle_indices(): atoms = Atoms('AlFeAl6', cell=[6] * 3, positions=[[0, 0, 0], [2.9, 2.9, 2.9], [0, 0, 3], [0, 3, 0], [0, 3, 3], [3, 0, 0], [3, 0, 3], [3, 3, 0]], pbc=True) atoms.set_constraint(FixSymmetry(atoms)) at_permut = atoms[[0, 2, 3, 4, 5, 6, 7, 1]] pos0 = atoms.get_positions() def perturb(atoms, pos0, at_i, dpos): positions = pos0.copy() positions[at_i] += dpos atoms.set_positions(positions) new_p = atoms.get_positions() return pos0[at_i] - new_p[at_i] dp1 = perturb(atoms, pos0, 1, (0.0, 0.1, -0.1)) dp2 = perturb(atoms, pos0, 2, (0.0, 0.1, -0.1)) pos0 = at_permut.get_positions() permut_dp1 = perturb(at_permut, pos0, 7, (0.0, 0.1, -0.1)) permut_dp2 = perturb(at_permut, pos0, 1, (0.0, 0.1, -0.1)) assert np.max(np.abs(dp1 - permut_dp1)) < 1.0e-10 assert np.max(np.abs(dp2 - permut_dp2)) < 1.0e-10
force='force', nproc=1, chk='water.chk', label='water') calc.clean() water = Atoms('OHH', positions=[(0, 0, 0), (1, 0, 0), (0, 1, 0)], calculator=calc) opt = LBFGS(water) opt.run(fmax=0.05) forces = water.get_forces() energy = water.get_potential_energy() positions = water.get_positions() # Then test the IO routines from ase.io import read water2 = read('water.log') forces2 = water2.get_forces() energy2 = water2.get_potential_energy() positions2 = water2.get_positions() #compare distances since positions are different in standard orientation dist = water.get_all_distances() dist2 = read('water.log', quantity='structures')[-1].get_all_distances() assert abs(energy - energy2) < 1e-7 assert abs(forces - forces2).max() < 1e-9 assert abs(positions - positions2).max() < 1e-6 assert abs(dist - dist2).max() < 1e-6
class ifc_parser(): def __init__(self, symbols, fname='abinit_ifc.out', primitive_atoms=None, cell=np.eye(3)): with open(fname) as myfile: self.lines = myfile.readlines() self.R = [] self.G = [] self.ifc = [] self.atom_positions = [] self.split() self.read_info() self.read_lattice() self.atoms = Atoms(symbols, positions=self.atom_positions, cell=self.R) self.primitive_atoms = primitive_atoms self.atoms.set_positions(self.atom_positions) self.read_ifc() self.map_ifc_to_primitive_cell() self.make_model() def split(self): lines = self.lines self.info_lines = [] self.lattice_lines = [] self.ifc_lines = {} inp_block = False lat_block = False ifc_block = False for iline, line in enumerate(lines): # input variables if line.strip().startswith("-outvars_anaddb:"): inp_block = True if line.strip().startswith("========="): inp_block = False if inp_block: self.info_lines.append(line.strip()) # lattice vectors if line.strip().startswith("read the DDB information"): lat_block = True if line.strip().startswith("========="): lat_block = False if lat_block: self.lattice_lines.append(line.strip()) # IFC block if line.strip().startswith( "Calculation of the interatomic forces"): ifc_block = True if line.strip().startswith("========="): ifc_block = False if ifc_block: if line.strip().startswith('generic atom number'): iatom = int(line.split()[-1]) atom_position = map(float, lines[iline + 1].split()[-3:]) self.atom_positions.append(np.array(atom_position) * Bohr) if line.find('interaction with atom') != -1: jinter = int(line.split()[0]) self.ifc_lines[(iatom, jinter)] = lines[iline:iline + 15] def read_info(self): self.invars = {} keys = ('asr', 'chneut', 'dipdip', 'ifcflag', 'ifcana', 'ifcout', 'natifc', 'brav') lines = self.info_lines for line in lines: for key in keys: val = read_value(line, key) if val: self.invars[key] = int(val) #print(self.invars) def read_lattice(self): lines = self.lattice_lines #print lines for line in lines: if line.startswith('R('): self.R.append(np.array((map(float, line.split()[1:4]))) * Bohr) self.G.append(np.array((map(float, line.split()[5:8]))) / Bohr) #print(self.R) def read_ifc_elem(self, iatom, iinter): lines = self.ifc_lines[(iatom, iinter)] w = lines[0].strip().split() jatom = int(w[-3]) jcell = int(w[-1]) pos_j = [float(x) * Bohr for x in lines[1].strip().split()[-3:]] distance = float(lines[2].strip().split()[-1]) * Bohr # check distance # Fortran format F9.5: some values are not seperated by whitespaces. # Maybe better fit that in abinit code. #ifc0= map(float, lines[3].strip().split()[0:3]) #ifc1= map(float, lines[4].strip().split()[0:3]) #ifc2= map(float, lines[5].strip().split()[0:3]) #ifc=np.array([ifc0, ifc1, ifc2]).T * Hartree / Bohr**2 #print lines[3] ifc0 = map(float, [lines[3][i * 9 + 1:i * 9 + 9 + 1] for i in range(3)]) ifc1 = map(float, [lines[4][i * 9 + 1:i * 9 + 9 + 1] for i in range(3)]) ifc2 = map(float, [lines[5][i * 9 + 1:i * 9 + 9 + 1] for i in range(3)]) ifc = np.array([ifc0, ifc1, ifc2]).T * Hartree / Bohr**2 #ifc = np.array([ifc0, ifc1, ifc2]) * Hartree / Bohr**2 if not ('dipdip' in self.invars and self.invars['dipdip'] == 1): ifc_ewald = None ifc_sr = None else: ifc0 = map( float, [lines[3][i * 9 + 2:i * 9 + 9 + 2] for i in range(3, 6)]) ifc1 = map( float, [lines[4][i * 9 + 2:i * 9 + 9 + 2] for i in range(3, 6)]) ifc2 = map( float, [lines[5][i * 9 + 2:i * 9 + 9 + 2] for i in range(3, 6)]) #ifc0= map(float, lines[3].strip().split()[3:6]) #ifc1= map(float, lines[4].strip().split()[3:6]) #ifc2= map(float, lines[5].strip().split()[3:6]) ifc_ewald = np.array([ifc0, ifc1, ifc2]) ifc0 = map( float, [lines[3][i * 9 + 3:i * 9 + 9 + 3] for i in range(6, 9)]) ifc1 = map( float, [lines[4][i * 9 + 3:i * 9 + 9 + 3] for i in range(6, 9)]) ifc2 = map( float, [lines[5][i * 9 + 3:i * 9 + 9 + 3] for i in range(6, 9)]) #ifc0= map(float, lines[3].strip().split()[6:9]) #ifc1= map(float, lines[4].strip().split()[6:9]) #ifc2= map(float, lines[5].strip().split()[6:9]) ifc_sr = np.array([ifc0, ifc1, ifc2]) # sanity check poses = self.atoms.get_positions() jpos = pos_j ipos = poses[iatom - 1] np.array(jpos) if not np.abs(np.linalg.norm(np.array(jpos) - ipos) - distance) < 1e-5: print "Warning: distance wrong", "iatom: ", iatom, ipos, "jatom", jatom, jpos return { "iatom": iatom, "jatom": jatom, "jcell": jcell, "jpos": pos_j, "distance": distance, "ifc": ifc, "ifc_ewald": ifc_ewald, "ifc_sr": ifc_sr } def read_ifc(self): natom, niteraction = sorted(self.ifc_lines.keys())[-1] for iatom in range(1, natom + 1): for iint in range(1, niteraction + 1): self.ifc.append(self.read_ifc_elem(iatom, iint)) def map_ifc_to_primitive_cell(self): if self.primitive_atoms is None: return pcell = self.primitive_atoms.get_cell() new_ifc = [] for ifce in self.ifc: # remove atoms outside of primitive cell if ifce['iatom'] <= len(self.primitive_atoms): jpos = ifce['jpos'] for i, pos in enumerate(self.primitive_atoms.get_positions()): dis = jpos - pos R = np.linalg.solve(pcell, dis) if np.all( np.isclose( np.mod(R + 1e-4, [1, 1, 1]), [0, 0, 0], atol=1e-3)): jatom = i + 1 #print "Found: " ,jatom break ifce['jatom'] = jatom new_ifc.append(ifce) self.ifc = new_ifc def make_model2(self): pass def make_model(self): if self.primitive_atoms is not None: atoms = self.primitive_atoms else: atoms = self.atoms lat = atoms.get_cell() apos = atoms.get_scaled_positions() masses = atoms.get_masses() orb = [] for pos in apos: for i in range(3): orb.append(pos) #print orb model = mytb(3, 3, lat=lat, orb=orb) self.tbmodel = pythtb.tbmodel(3, 3, lat=lat, orb=orb) #model = self.tbmodel atom_positions = atoms.get_positions() hopdict = {} for ifce in self.ifc: #print ifce iatom = ifce['iatom'] jatom = ifce['jatom'] jpos = ifce['jpos'] Ri = atom_positions[iatom - 1] Rj = atom_positions[jatom - 1] dis = jpos - Rj #print self.atoms.get_cell() R = np.linalg.solve(atoms.get_cell(), dis) #print R R = [int(round(x)) for x in R] if not np.isclose( np.dot(atoms.get_cell(), R) + atom_positions[jatom - 1], jpos, atol=1e-4).all(): print("Warning: Not equal", np.dot(atoms.get_cell(), R) + atom_positions[jatom - 1], jpos) #if not np.isclose(np.linalg.norm(jpos-Ri),ifce['distance']): # print("Warning: Not equal to distance", np.linalg.norm(jpos-Ri), ifce['distance']) #print R for a in range(3): for b in range(3): i = 3 * (iatom - 1) + a j = 3 * (jatom - 1) + b val = ifce['ifc'][a, b] / np.sqrt(masses[iatom - 1] * masses[jatom - 1]) #print i,j,R if iatom == jatom and a == b and R == [0, 0, 0]: model.set_onsite(val, ind_i=i) else: if (np.abs(val)) > 0.00000001: model.set_hop( val, i, j, R, allow_conjugate_pair=True) R = tuple(R) hopdict[( i, j, R, )] = val #model.set_hop_dis(val,i,j,jpos-Ri) #print self.atoms.get_positions() self.model = model #print(len(hopdict)) for hop in hopdict: i, j, R = hop mR = tuple(-np.array(R)) if ( j, i, mR, ) not in hopdict: print "Warning: ", (j, i, mR), "not in IFC" delta = np.abs(hopdict[( i, j, R, )] - hopdict[( j, i, mR, )]) if delta > 0.000001: print "Warning: ", (j, i, mR), "differ, delta=", delta def solve_model(self, output_figure=None, show=False): my_model = self.model # generate k-point path and labels path = np.array([[0.0, 0.0, 0.0], [0.5, 0.0, 0.0], [0.5, 0.5, 0.0], [0, 0, 0], [0.5, 0.5, 0.5], [.5, 0, 0]]) label = (r'$\Gamma $', r'$X$', r'$M$', r'$\Gamma$', r'$R$', r'X') (k_vec, k_dist, k_node) = self.tbmodel.k_path(path, 301) print('---------------------------------------') print('starting calculation') print('---------------------------------------') print('Calculating bands...') # solve for eigenenergies of hamiltonian on # the set of k-points from above evals = my_model.solve_all(k_vec) s = np.sign(evals) v = np.sqrt(s * evals) #v = np.sqrt(np.abs(evals.real)) * np.sign(evals.real) evals = s * v * 15.633302 * 33.256 # plotting of band structure print('Plotting bandstructure...') # First make a figure object fig, ax = plt.subplots() # specify horizontal axis details ax.set_xlim([0, k_node[-1]]) ax.set_xticks(k_node) ax.set_xticklabels(label) ax.axhline(y=0, linestyle='--') for n in range(len(k_node)): ax.axvline(x=k_node[n], linewidth=0.5, color='k') # plot bands for n in range(evals.shape[0]): ax.plot(k_dist, evals[n]) # put title ax.set_title("band structure") ax.set_xlabel("Path in k-space") ax.set_ylabel("Band energy") # make an PDF figure of a plot fig.tight_layout() if output_figure is not None: fig.savefig(output_figure) if show: plt.show() print('Done.\n')
def __init__(self, geometry=None, **kwargs) -> None: if geometry == None: atoms = Atoms(**kwargs) elif type(geometry) == ase.atoms.Atoms: atoms = geometry.copy() elif Path(geometry).is_file(): if str(Path(geometry).parts[-1]) == "geometry.in.next_step": atoms = ase.io.read(geometry, format="aims") else: try: atoms = ase.io.read(geometry) except Exception as excpt: logger.error(str(excpt)) raise Exception( "ASE was not able to recognize the file format, e.g., a non-standard cif-format." ) elif Path(geometry).is_dir(): raise Exception( "You specified a directory as input. The geometry must be a file." ) else: atoms = None assert type(atoms) == ase.atoms.Atoms, "Atoms not read correctly." # Get data from another Atoms object: numbers = atoms.get_atomic_numbers() positions = atoms.get_positions() cell = atoms.get_cell() celldisp = atoms.get_celldisp() pbc = atoms.get_pbc() constraint = [c.copy() for c in atoms.constraints] masses = atoms.get_masses() magmoms = None charges = None momenta = None if atoms.has("initial_magmoms"): magmoms = atoms.get_initial_magnetic_moments() if atoms.has("initial_charges"): charges = atoms.get_initial_charges() if atoms.has("momenta"): momenta = atoms.get_momenta() self.arrays = {} super().__init__( numbers=numbers, positions=positions, cell=cell, celldisp=celldisp, pbc=pbc, constraint=constraint, masses=masses, magmoms=magmoms, charges=charges, momenta=momenta, ) self._is_1d = None self._is_2d = None self._is_3d = None self._periodic_axes = None self._check_lattice_vectors() try: self.sg = ase.spacegroup.get_spacegroup(self, symprec=1e-2) except: self.sg = ase.spacegroup.Spacegroup(1) self.lattice = self.cell.get_bravais_lattice().crystal_family
from ase.atoms import Atoms from ase.optimize.lbfgs import LBFGS # First test to make sure Gaussian works calc = Gaussian(method='pbepbe', basis='sto-3g', force='force', nproc=1, chk='water.chk', label='water') calc.clean() water = Atoms('OHH', positions=[(0., 0. ,0. ), (1. ,0. ,0. ), (0. ,1. ,0. )], calculator=calc) opt = LBFGS(water) opt.run(fmax=0.05) forces = water.get_forces() energy = water.get_potential_energy() positions = water.get_positions() # Then test the IO routines from ase.io import read water2 = read('water/water.log') forces2 = water2.get_forces() energy2 = water2.get_potential_energy() positions2 = water2.get_positions() assert (energy - energy2) < 1e-14 assert (forces.all() - forces2.all()) < 1e-14 assert (positions.all() - positions2.all()) < 1e-14