def __init__(self, atoms, BZpath=[], npoints=10, outnc='harris.nc'): """Headline here ... XXX. atoms is an ase.Atoms object with calculator attached. Presumably the self-consistent charge density has already been calculated, otherwise, it will be. BZpath is a list of tuples describing the path through the Brillouin zone. The tuples have the form (label, kpt), e.g. :: [('$\Gamma$',[0.0, 0.0, 0.0]), ('X',[0.0, 0.5, 0.5]), ('L',[0.5, 0.0, 0.0]), ('$\Gamma$',[0.0, 0.0, 0.0])] the label is used in the figure and can include latex markup. npoints is the number of points on each segment. It can either be a constant, which is used for every segment, or a list of integers that is an integer for each segment. """ self.atoms = atoms self.calc = atoms.get_calculator() #first, we make sure the charge density is up to date. self.calc.get_charge_density() self.ef = self.calc.get_ef() #self-consistent fermi level self.labels = [x[0] for x in BZpath] self.kpt_path = [np.array(x[1], dtype=np.float) for x in BZpath] self.npoints = npoints #first, setup the kpt path kpts = [] #start at second kpt and go to second to last segment nsegments = len(self.kpt_path) - 1 for i in range(nsegments - 1): #get number of points on path. this counts the first point try: i_npt = npoints[i] except TypeError: i_npt = npoints #this is the vector connecting the two endpoint kpts of a segment kdiff = self.kpt_path[i + 1] - self.kpt_path[i] #make a vector of evenly spaced intervals, one longer than needed #because we chop off the last entry. for j in np.linspace(0, 1, i_npt + 1)[0:-1]: k = self.kpt_path[i] + j * kdiff #shift by small random amount to break symmetry and #prevent time-inversion reduction krand = (1. + np.random.random(3)) / 1.e4 k += krand kpts.append(k) #now fill in the last segment, and end on the last point try: i_npt = npoints[-1] except TypeError: i_npt = npoints kdiff = self.kpt_path[-1] - self.kpt_path[-2] for j in np.linspace(0, 1, i_npt + 1)[1:]: k = self.kpt_path[-2] + j * kdiff #shift by small random amount to break symmetry and #prevent time-inversion reduction krand = (1. + np.random.random(3)) / 1.e4 k += krand kpts.append(k) #these are now the points needed for the Harris calculation. self.kpts = kpts self.dos = DOS(self.calc) self.dos_energies = self.dos.get_energies() self.dos_dos = self.dos.get_dos() #try to avoid rerunning the calculation if it is already done! if os.path.exists(outnc): self.calc = Jacapo(outnc) else: print('calculation of harris required') self.calc.set_nc(outnc) #self.calc.debug=10 #save some time by not calculating stress self.calc.set_stress(False) #this seems to be necessary sometimes self.calc.delete_ncattdimvar(outnc, ncdims=['number_plane_waves']) #this has to come after removing number_of_planewaves self.calc.set_kpts(self.kpts) #freeze charge density self.calc.set_charge_mixing(updatecharge='No') #and, run calculation self.calc.calculate()
'ScientificPython version 2.8 or greater is required') except (ImportError, NotAvailable): print "No Scientific python found. Check your PYTHONPATH" raise NotAvailable('ScientificPython version 2.8 or greater is required') if not (os.system('which dacapo.run') == 0): print "No Dacapo Fortran executable (dacapo.run) found. Check your path settings." raise NotAvailable( 'dacapo.run is not installed on this machine or not in the path') # Now Scientific 2.8 and dacapo.run should both be available from ase import Atoms, Atom from ase.calculators.jacapo import Jacapo atoms = Atoms([Atom('H', [0, 0, 0])], cell=(2, 2, 2)) calc = Jacapo('Jacapo-test.nc', pw=200, nbands=2, kpts=(1, 1, 1), spinpol=False, dipole=False, symmetry=False, ft=0.01) atoms.set_calculator(calc) print atoms.get_potential_energy() os.system('rm -f Jacapo-test.nc Jacapo-test.txt')