def test_bader(): import os from ase.build import molecule from ase.io.bader import attach_charges fname = 'ACF.dat' f = open(fname, 'w') print(""" # X Y Z CHARGE MIN DIST ---------------------------------------------------------------- 1 7.0865 8.5038 9.0672 9.0852 1.3250 2 7.0865 9.9461 7.9403 0.4574 0.3159 3 7.0865 7.0615 7.9403 0.4574 0.3159 ---------------------------------------------------------------- NUMBER OF ELECTRONS: 9.99999 """, file=f) f.close() atoms = molecule('H2O') atoms.set_cell([7.5, 9, 9]) atoms.center() attach_charges(atoms) attach_charges(atoms, fname) os.remove(fname) for atom in atoms: print('Atom', atom.symbol, 'Bader charge', atom.charge) # O is negatively charged assert (atoms[0].charge < -1 and atoms[0].charge > -2)
def print_bader(dir_path = '.', atoms_file = 'CONTCAR'): #Prints the bader charges using the atoms_file (usually CONTCAR) and ACF.dat atoms = read('%s/%s' % (dir_path, atoms_file)) attach_charges(atoms, '%s/ACF.dat' % dir_path) buf = [] print "i\tSymbol\tCharge\tx\ty\tz" print "-"*30 for atom in atoms: print "%d\t%s\t%f\t%f\t%f\t%f" % (atom.index, atom.symbol, atom.charge, atom.x, atom.y, atom.z) buf = buf.append((atom.index, atom.symbol, atom.charge, atom.x, atom.y, atom.z)) dtype = [('i', int), ('symbol', str) ('x', float), ('y', float), ('z', float)] data = np.array(buf, dtype = dtype) return data
def get_bader_charge(self, inpfile=None): ''' ''' from ase.io.bader import attach_charges if not inpfile: inpfile = '%s.cube' % self.prefix command = 'bader %s' % inpfile print(command) try: proc = subprocess.Popen(command, shell=True, cwd=self.directory) except OSError as err: msg = 'Failed to execute "{}"'.format(command) raise EnvironmentError(msg) from err acf = os.path.join(self.directory, 'ACF.dat') attach_charges(self.results['atoms'], acf)
def compare_bader(dir1, dir2): #Uses the CONTCARs located in dir1 and dir2 and takes the difference between the two charges atoms1 = read('%s/CONTCAR' % dir1) attach_charges(atoms1, '%s/ACF.dat' % dir1) atoms2 = read('%s/CONTCAR' % dir2) attach_charges(atoms2, '%s/ACF.dat' % dir2) max_len = max([len(atoms1, atoms2)]) len1 = len(atom1) len2 = len(atom2) if len1 >= len2: print("Using properties of atom1.") max_len = len1 atoms_long = atoms1 atoms_short = atoms2 else: print("Using properties of atom2 since it is longer.") max_len = len2 atoms_long = atoms2 atoms_short = atoms1 print("i\tSymbol\tCharge 1\t Charge 2\t ΔCharge") for i in range(max_len): try: atom_short = atoms_short[i] except IndexError: print(("%d\t%s\t%f\t%f\t%f" % (atom1.index, atom1.symbol, atom1.charge, atom2.charge, atom2.charge - atom1.charge))) else: print(("%d\t%s\t%f\t%f\t%f" % (atom1.index, atom1.symbol, atom1.charge, atom2.charge, atom2.charge - atom1.charge))) buf = buf.append((atom1.index, atom1.symbol, atom1.charge, atom1.x, atom1.y, atom1.z)) if atom1.symbol != atom2.symbol: print("Symbol mismatch!") dtype = [('i', int), ('symbol', str)('x', float), ('y', float), ('z', float)] data = np.array(buf, dtype=dtype) return data
def test_bader(): fname = 'ACF.dat' Path(fname).write_text(""" # X Y Z CHARGE MIN DIST ---------------------------------------------------------------- 1 7.0865 8.5038 9.0672 9.0852 1.3250 2 7.0865 9.9461 7.9403 0.4574 0.3159 3 7.0865 7.0615 7.9403 0.4574 0.3159 ---------------------------------------------------------------- NUMBER OF ELECTRONS: 9.99999 """) atoms = molecule('H2O') atoms.set_cell([7.5, 9, 9]) atoms.center() attach_charges(atoms) attach_charges(atoms, fname) for atom in atoms: print('Atom', atom.symbol, 'Bader charge', atom.charge) # O is negatively charged assert (atoms[0].charge < -1 and atoms[0].charge > -2)
sx, sy, sz = a.cell.diagonal() a.set_cell([[sx, 0, 0], [0, sy, 0], [dx, dy, sz]], scale_atoms=False) if opt.cell is not None: cell = map(float, opt.cell.split(',')) a.set_cell(cell) if opt.cellfn is not None: io.read_cyc(a, opt.cellfn) if opt.center is not None: if opt.center: a.center() if opt.acf is not None: attach_charges(a, opt.acf) if convlen is not None: a.set_cell(a.get_cell() * convlen, scale_atoms=True) if opt.wrap_to_cell: a.set_scaled_positions(a.get_scaled_positions()) if opt.clear_velocities: a.set_momenta(None) if opt.supercell is not None: supercell = map(int, opt.supercell.split(',')) a *= supercell d = {}
from ase.build import molecule from ase.io.bader import attach_charges fname = 'ACF.dat' f = open(fname, 'w') print(""" # X Y Z CHARGE MIN DIST ---------------------------------------------------------------- 1 7.0865 8.5038 9.0672 9.0852 1.3250 2 7.0865 9.9461 7.9403 0.4574 0.3159 3 7.0865 7.0615 7.9403 0.4574 0.3159 ---------------------------------------------------------------- NUMBER OF ELECTRONS: 9.99999 """, file=f) f.close() atoms = molecule('H2O') atoms.set_cell([7.5, 9, 9]) atoms.center() attach_charges(atoms) attach_charges(atoms, fname) os.remove(fname) for atom in atoms: print('Atom', atom.symbol, 'Bader charge', atom.charge) # O is negatively charged assert (atoms[0].charge < -1 and atoms[0].charge > -2)
def get_bader_charges(atoms, calc, charge_source="all-electron", gridrefinement=4): """This function uses an external Bader charge calculator from http://theory.cm.utexas.edu/henkelman/code/bader/. This tool is provided also in pysic/tools. Before using this function the bader executable directory has to be added to PATH. Parameters: atoms: ASE Atoms The structure from which we want to calculate the charges from. calc: ASE calculator charge_source: string Indicates the electron density that is used in charge calculation. Can be "pseudo" or "all-electron". gridrefinement: int The factor by which the calculation grid is densified in charge calculation. Returns: numpy array of the atomic charges """ # First check that the bader executable is in PATH if spawn.find_executable("bader") is None: error(( "Cannot find the \"bader\" executable in PATH. The bader " "executable is provided in the pysic/tools folder, or it can be " "downloaded from http://theory.cm.utexas.edu/henkelman/code/bader/. " "Ensure that the executable is named \"bader\", place it in any " "directory you want and then add that directory to your system" "PATH.")) atoms_copy = atoms.copy() calc.set_atoms(atoms_copy) if charge_source == "pseudo": try: density = np.array(calc.get_pseudo_density()) except AttributeError: error("The calculator doesn't provide pseudo density.") if charge_source == "all-electron": try: density = np.array(calc.get_all_electron_density(gridrefinement=gridrefinement)) except AttributeError: error("The calculator doesn't provide all electron density.") wrk_dir = os.getcwd()+"/.BADERTEMP" dir_created = False # Write the density in bader supported units and format if rank == 0: # Create temporary folder for calculations if not os.path.exists(wrk_dir): os.makedirs(wrk_dir) dir_created = True else: error("Tried to create a temporary folder in " + wrk_dir + ", but the folder already existed. Please remove it manually first.") rho = density * Bohr**3 write(wrk_dir + '/electron_density.cube', atoms, data=rho) # Run the bader executable in terminal. The bader executable included # int pysic/tools has to be in the PATH/PYTHONPATH command = "cd " + wrk_dir + "; bader electron_density.cube" subprocess.check_output(command, shell=True) #os.system("gnome-terminal --disable-factory -e '"+command+"'") # Wait for the main process to write the file barrier() # ASE provides an existing function for attaching the charges to the # atoms (safe because using a copy). Although we don't want to actually # attach the charges to anything, we use this function and extract the # charges later. bader.attach_charges(atoms_copy, wrk_dir + "/ACF.dat") # The call for charges was changed between # ASE 3.6 and 3.7 try: bader_charges = np.array(atoms_copy.get_initial_charges()) except: bader_charges = np.array(atoms_copy.get_charges()) # Remove the temporary files if rank == 0: if dir_created: shutil.rmtree(wrk_dir) return bader_charges
def get_bader_charges(atoms, calc, charge_source="all-electron", gridrefinement=4): """This function uses an external Bader charge calculator from http://theory.cm.utexas.edu/henkelman/code/bader/. This tool is provided also in pysic/tools. Before using this function the bader executable directory has to be added to PATH. Parameters: atoms: ASE Atoms The structure from which we want to calculate the charges from. calc: ASE calculator charge_source: string Indicates the electron density that is used in charge calculation. Can be "pseudo" or "all-electron". gridrefinement: int The factor by which the calculation grid is densified in charge calculation. Returns: numpy array of the atomic charges """ # First check that the bader executable is in PATH if spawn.find_executable("bader") is None: error(( "Cannot find the \"bader\" executable in PATH. The bader " "executable is provided in the pysic/tools folder, or it can be " "downloaded from http://theory.cm.utexas.edu/henkelman/code/bader/. " "Ensure that the executable is named \"bader\", place it in any " "directory you want and then add that directory to your system" "PATH.")) atoms_copy = atoms.copy() calc.set_atoms(atoms_copy) if charge_source == "pseudo": try: density = np.array(calc.get_pseudo_density()) except AttributeError: error("The calculator doesn't provide pseudo density.") if charge_source == "all-electron": try: density = np.array( calc.get_all_electron_density(gridrefinement=gridrefinement)) except AttributeError: error("The calculator doesn't provide all electron density.") wrk_dir = os.getcwd() + "/.BADERTEMP" dir_created = False # Write the density in bader supported units and format if rank == 0: # Create temporary folder for calculations if not os.path.exists(wrk_dir): os.makedirs(wrk_dir) dir_created = True else: error( "Tried to create a temporary folder in " + wrk_dir + ", but the folder already existed. Please remove it manually first." ) rho = density * Bohr**3 write(wrk_dir + '/electron_density.cube', atoms, data=rho) # Run the bader executable in terminal. The bader executable included # int pysic/tools has to be in the PATH/PYTHONPATH command = "cd " + wrk_dir + "; bader electron_density.cube" subprocess.check_output(command, shell=True) #os.system("gnome-terminal --disable-factory -e '"+command+"'") # Wait for the main process to write the file barrier() # ASE provides an existing function for attaching the charges to the # atoms (safe because using a copy). Although we don't want to actually # attach the charges to anything, we use this function and extract the # charges later. bader.attach_charges(atoms_copy, wrk_dir + "/ACF.dat") # The call for charges was changed between # ASE 3.6 and 3.7 try: bader_charges = np.array(atoms_copy.get_initial_charges()) except: bader_charges = np.array(atoms_copy.get_charges()) # Remove the temporary files if rank == 0: if dir_created: shutil.rmtree(wrk_dir) return bader_charges
from __future__ import print_function import os from ase.structure import molecule from ase.io.bader import attach_charges fname = 'ACF.dat' f = open(fname, 'w') print(""" # X Y Z CHARGE MIN DIST ---------------------------------------------------------------- 1 7.0865 8.5038 9.0672 9.0852 1.3250 2 7.0865 9.9461 7.9403 0.4574 0.3159 3 7.0865 7.0615 7.9403 0.4574 0.3159 ---------------------------------------------------------------- NUMBER OF ELECTRONS: 9.99999 """, file=f) f.close() atoms = molecule('H2O') atoms.set_cell([7.5, 9, 9]) atoms.center() attach_charges(atoms) attach_charges(atoms, fname) os.remove(fname) for atom in atoms: print('Atom', atom.symbol, 'Bader charge', atom.charge)
sx, sy, sz = a.cell.diagonal() a.set_cell([[sx,0,0],[0,sy,0],[dx,dy,sz]], scale_atoms=False) if opt.cell is not None: cell = map(float, opt.cell.split(',')) a.set_cell(cell) if opt.cellfn is not None: io.read_cyc(a, opt.cellfn) if opt.center is not None: if opt.center: a.center() if opt.acf is not None: attach_charges(a, opt.acf) if convlen is not None: a.set_cell(a.get_cell()*convlen, scale_atoms=True) if opt.wrap_to_cell: a.set_scaled_positions(a.get_scaled_positions()) if opt.clear_velocities: a.set_momenta(None) if opt.supercell is not None: supercell = map(int, opt.supercell.split(',')) a *= supercell d = { }
from jasp import * from ase.io.bader import attach_charges from ase.units import Bohr with jasp("molecules/h2o-bader") as calc: atoms = calc.get_atoms() symbols = np.array(atoms.get_chemical_symbols())[calc.sort] pos = atoms.positions[calc.sort] * Bohr newatoms = Atoms(symbols, positions=pos, cell=atoms.get_cell()) attach_charges(newatoms, "ACF.dat") print("#+tblname: bader") print("#+caption: Bader charges for a water molecule") print("| atom | Bader charge|") print("|-") for atom in newatoms: print("|{0} | {1} |".format(atom.symbol, atom.charge))
''' import os from ase.io import read from ase.io.bader import attach_charges from glob import glob try: a = read(glob('*.STRUCT_OUT')[0]) except IndexError: try: a = read(glob('siesta.XSF')[0]) except IndexError: print('need either STRUCT_OUT or siesta.XSF from xv2xsf script!') exit() attach_charges(a, displacement=0.1) elms = [x for x in os.listdir() if x.endswith('psf')] elm = [] chg = [] for i in elms: with open(i) as f: t = 0 for line in f: if t == 0: elm.append(line.split()[0]) elif t == 3: chg.append(line.split()[-1]) elif t > 3: break t += 1
from jasp import * from ase.io.bader import attach_charges from ase.units import Bohr with jasp('molecules/h2o-bader') as calc: atoms = calc.get_atoms() symbols = np.array(atoms.get_chemical_symbols())[calc.sort] pos = atoms.positions[calc.sort] * Bohr newatoms = Atoms(symbols, positions=pos, cell=atoms.get_cell()) attach_charges(newatoms, 'ACF.dat') print '#+tblname: bader' print '#+caption: Bader charges for a water molecule' print '| atom | Bader charge|' print '|-' for atom in newatoms: print '|{0} | {1} |'.format(atom.symbol, atom.charge)
print(' ',i,total_charge[i],end='') print(' sum {}'.format(sum(total_charge.values()))) exit() if not exists: # if the data has not been multipled by Bohr**3, uncomment the following. # data, atoms = read_cube_data(sys.argv[1]) # density = data * Bohr**3 # write('density-temp.cube', atoms, data=density) # sys.argv[1] = 'density-temp.cube' # res = subprocess.check_output(["bader", sys.argv[1]]) x = 3 atoms = read(sys.argv[1]) attach_charges(atoms) elm_set = set(atoms.get_chemical_symbols()) elm = dict.fromkeys(elm_set, 0) total_charge = elm.copy() with open(sys.argv[2]) as f: for line in f: if "-setup:" in line: x = line.split('-')[0] elif " Z: " in line: elm[x] = int(line.split()[-1]) for i in atoms: i.charge = elm[i.symbol] - i.charge
#!/usr/bin/env python from jasp import * from ase.io.bader import attach_charges from ase.units import Bohr with jasp('molecules/h2o-bader') as calc: atoms = calc.get_atoms() symbols = np.array(atoms.get_chemical_symbols())[calc.sort] pos = atoms.positions[calc.sort] * Bohr newatoms = Atoms(symbols, positions=pos, cell=atoms.get_cell()) attach_charges(newatoms, 'ACF.dat') print('#+tblname: bader') print('#+caption: Bader charges for a water molecule') print('| atom | Bader charge|') print('|-') for atom in newatoms: print('|{0} | {1} |'.format(atom.symbol, atom.charge))
#!/usr/bin/env python3 ''' This script attach charges calculated with bader charge program to xyz for visualizing it with ovito. This requires CONTCAR OUTACR ACF.dat files. ''' from ase.io import read from ase.io.bader import attach_charges import numpy as np a = read('CONTCAR') attach_charges(a) elm = [] # get the elements (elm) and their initial # of electron (chg) with open('OUTCAR') as f: for line in f: if len(line.split()) > 2 and line.split()[0] == 'ZVAL': chg = line.split()[2:] if len(line.split()) > 1 and line.split()[0] == 'VRHFIN': elm.append(line.split()[1].strip('=').strip(':')) elm.append('total') ech = [0] * len(elm) all_chg = dict(zip(elm, ech)) print('ZVAL from the OUTACR:', chg) # calculate the rest charge