예제 #1
0
    def __init__(self, filename):
        """
        Constructor.

        filename -- filename to get info from, either Gaussian (out, g03) or netCDF file (nc)
        """
        self.file = filename
        if os.path.exists(filename):
            ext = filename.split('.')[-1]
            self.complex = filename.split('.')[-2]
            #print ext
            if ext == 'nc':
                self.type = 'nc'
                # read directly from nc to avoid calculation
                #self.data = netCDF(filename,'r')
                self.data = Jacapo.read_atoms(filename)
            elif ext == 'out' or ext == 'g03' or ext == 'log':
                gout = Gaussian(filename)
                gout.logger.setLevel(logging.ERROR)
                self.type = 'gau'
                self.data = gout.parse()
        else:
            raise Exception, 'File is not of identifiable format'
예제 #2
0
class BandStructure:
    '''outline of class to facilitate band structure calculations
    '''
    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()

    def plot(self):
        '''
        Make an interactive band-structure plot.

        clicking on a band will make it thicker and print which band was selected.
        '''

        # kpoints = self.calc.get_ibz_kpoints()

        eigenvalues = self.calc.get_all_eigenvalues() - self.ef
        #eigenvalues = np.array([self.calc.get_eigenvalues(kpt=i)-self.ef
        #                        for i in range(len(kpoints))])

        self.handles = []  #used to get band indexes from plot

        fig = plt.figure()
        #plot DOS in figure
        ax = fig.add_subplot(122)
        ax.plot(self.dos_dos, self.dos_energies)
        plt.title('self-consistent Total DOS')
        ax.set_xticks([])
        ax.set_yticks([])
        ax.set_ylim([-20, 20])

        ax = fig.add_subplot(121)
        ax.set_title('Band structure')

        def onpick(event):
            'make picked line bolder, set oldline back to regular thickness'
            self.lastartist.set_linewidth(1)
            self.lastartist = thisline = event.artist
            thisline.set_linewidth(5)
            plt.draw()  #needed to update linewidth

            print('Band %i selected' % self.handles.index(thisline))
            #you could insert code here to plot wavefunction, etc...

        fig.canvas.mpl_connect('pick_event', onpick)

        #we use indices for x. the tick labels are not shown and the distance
        #appears unimportant
        xdata = list(range(len(eigenvalues)))

        nkpts, nbands = eigenvalues.shape
        for i in range(nbands):
            #eigenvalues has shape(nkpts,nbands)
            #note the comma after line_handle
            line_handle, = ax.plot(xdata,
                                   eigenvalues[:, i],
                                   '.-',
                                   ms=1,
                                   picker=2)
            self.handles.append(line_handle)

        self.lastartist = self.handles[-1]

        #plot Fermi level
        ax.plot([0, len(self.kpts)], [0, 0], 'k--', label='$E_f$')

        plt.xlabel('|k|')
        plt.ylabel('$E-E_f$ (eV)')

        #set xtick locations and labels
        xtick_locs = np.zeros(len(self.kpt_path))
        try:
            #this means the npoints is a list
            # i_npt = self.npoints[0]
            for j, npt in enumerate(1, self.npoints):
                xtick_locs[j] = xtick_locs[j - 1] + npt
        except TypeError:
            #npoints is a single number
            for j in range(1, len(self.labels)):
                xtick_locs[j] = xtick_locs[j - 1] + self.npoints

        #the last location is off by one, so we fix it.
        xtick_locs[-1] -= 1

        ax.set_xlim([xtick_locs[0], xtick_locs[-1]])
        ax.set_xticks(xtick_locs)
        ax.set_xticklabels(self.labels)

        #this seems reasonable to avoid very deep energy states and high energy states
        ax.set_ylim([-20, 20])

        plt.show()

        return fig
예제 #3
0
    mol = 'NH3'
    atoms = Atoms(mol, positions=molecules.data[mol]['positions'])

    sg = SYMMOL(atoms)
    print(sg.get_point_group())
    print(sg.get_moments_of_inertia())
    print(atoms.get_moments_of_inertia())
    print(sg.get_symmetry_operators())

if __name__ == '__main__':
    from ase.calculators.jacapo import Jacapo
    from optparse import OptionParser

    parser = OptionParser(usage='symmol.py ncfile', version='0.1')

    parser.add_option('-f', nargs=0, help='print full output')

    parser.add_option('-o', nargs=1, help='save output in filename')

    options, args = parser.parse_args()

    for ncfile in args:

        sy = SYMMOL(Jacapo.read_atoms(ncfile), outfile=options.o)

        print('Point group = ', sy.get_point_group())
        print('Moments of inertia = ', sy.get_moments_of_inertia())
        print('Symmetry operators = ', sy.get_symmetry_operators())
        if options.f is not None:
            print(sy)
예제 #4
0
    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()
예제 #5
0
        cmd = 'bader -p all_atom %s' % (self.densityfile)
        print(cmd)
        os.system(cmd)

    def write_all_bader(self):
        '''
        -p all_bader Write all Bader volumes (containing charge above
        threshold of 0.0001) to a file. The charge distribution in
        each volume is written to a separate file, named
        Bvolxxxx.dat. It will either be of a CHGCAR format or a CUBE
        file format, depending on the format of the initial charge
        density file. These files can be quite large, so this option
        should be used with caution.
        '''
        cmd = 'bader -p all_bader %s' % (self.densityfile)
        print(cmd)
        os.system(cmd)


if __name__ == '__main__':

    from ase.calculators.jacapo import Jacapo

    atoms = Jacapo.read_atoms('ethylene.nc')

    b = Bader(atoms)

    print(b.get_bader_charges())
    print(b.get_bader_volumes())
    b.write_atom_volume([3, 4])
예제 #6
0
파일: jacapo.py 프로젝트: slabanja/ase
            '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')
예제 #7
0
        return string.join(self.output)

    def get_space_group(self):
        regexp = re.compile('^Space Group')

        for line in self.output:
            if regexp.search(line):
                return line


if __name__ == '__main__':
    from ase.calculators.jacapo import Jacapo
    from optparse import OptionParser

    parser = OptionParser(usage='findsym.py ncfile', version='0.1')

    parser.add_option('-f', nargs=0, help='print full output')

    parser.add_option('-o', nargs=1, help='save output in filename')

    options, args = parser.parse_args()

    for ncfile in args:

        sg = FINDSYM(Jacapo.read_atoms(ncfile), outfile=options.o)

        print(sg.get_space_group())

        if options.f is not None:
            print(sg)
예제 #8
0
파일: bader.py 프로젝트: PHOTOX/fuase
        '''
        cmd = 'bader -p all_atom %s' % (self.densityfile)
        print cmd
        os.system(cmd)

    def write_all_bader(self):
        '''
        -p all_bader Write all Bader volumes (containing charge above
        threshold of 0.0001) to a file. The charge distribution in
        each volume is written to a separate file, named
        Bvolxxxx.dat. It will either be of a CHGCAR format or a CUBE
        file format, depending on the format of the initial charge
        density file. These files can be quite large, so this option
        should be used with caution.
        '''
        cmd = 'bader -p all_bader %s' % (self.densityfile)
        print cmd
        os.system(cmd)
        
if __name__ == '__main__':

    from ase.calculators.jacapo import Jacapo

    atoms = Jacapo.read_atoms('ethylene.nc')

    b = Bader(atoms)

    print b.get_bader_charges()
    print b.get_bader_volumes()
    b.write_atom_volume([3, 4])
예제 #9
0
            index += 5

            symmetry_operators.append(temparray)
            taus.append(array(temptau))

        return symmetry_operators, taus


if __name__ == '__main__':
    from ase.calculators.jacapo import Jacapo
    from optparse import OptionParser

    parser = OptionParser(usage='sgroup.py ncfile', version='0.1')

    parser.add_option('-f', nargs=0, help='print full output')

    parser.add_option('-o', nargs=1, help='save output in filename')

    options, args = parser.parse_args()

    #print options

    for ncfile in args:

        sg = SGROUP(Jacapo.read_atoms(ncfile), outfile=options.o)

        print(sg.get_space_group())

        if options.f is not None:
            print(sg)