Ejemplo n.º 1
0
    def plot_bandstructure(self,
                           filename=None,
                           filepath=None,
                           max_min_e=None,
                           show=False,
                           save=True,
                           show_vbm_cbm=True):
        if 'bands' in self:
            from structure import get_kpath
            if filename == None:
                filename = 'band_structure.pdf'
            if filepath == None:
                filepath = os.path.join(self.abspath, filename)
            else:
                filepath = os.path.join(filepath, filename)
            #end if
            try:
                import matplotlib
                gui_envs = ['GTKAgg', 'TKAgg', 'agg', 'Qt4Agg', 'WXAgg']
                for gui in gui_envs:
                    try:
                        matplotlib.use(gui, warn=False, force=True)
                        from matplotlib import pyplot
                        success = True
                        break
                    except:
                        continue
                    #end try
                #end for
                from matplotlib.pyplot import figure, plot, xlabel, ylabel, title, show, ylim, legend, xlim, rcParams, rc, savefig, gca, xticks, axvline, scatter
                params = {
                    'legend.fontsize': 14,
                    'figure.facecolor': 'white',
                    'figure.subplot.hspace': 0.,
                    'axes.labelsize': 16,
                    'xtick.labelsize': 14,
                    'ytick.labelsize': 14
                }
                rcParams.update(params)
            except (ImportError, RuntimeError):
                success = False
            if not success:
                figure, plot, xlabel, ylabel, title, show, ylim, legend, xlim, rcParams, savefig, bar, xticks, subplot, grid, setp, errorbar, loglog, semilogx, semilogy, text = unavailable(
                    'matplotlib.pyplot', 'figure', 'plot', 'xlabel', 'ylabel',
                    'title', 'show', 'ylim', 'legend', 'xlim', 'rcParams',
                    'savefig', 'bar', 'xticks', 'subplot', 'grid', 'setp',
                    'errorbar', 'loglog', 'semilogx', 'semilogy', 'text')
            #end if
            fig = figure()
            ax = gca()
            kpath = get_kpath(structure=self.input_structure,
                              check_standard=False)
            x = kpath['explicit_path_linearcoords']
            labels = kpath['explicit_kpoints_labels']
            nbands = self.input.system.nbnd
            for nb in range(nbands):
                y = []
                for bi in self.bands.up:
                    y.append(bi['eigs'][nb])
                #end for
                y = array(y) - self.bands.vbm.energy
                plot(x, y, 'k')
                if len(self.bands.down) > 0:
                    y = []
                    for bi in self.bands.down:
                        y.append(bi['eigs'][nb])
                    #end for
                    y = array(y) - self.bands.vbm.energy
                    plot(x, y, 'r')
                #end if
            #end for
            for ln, li in enumerate(labels):
                if li is not '':
                    axvline(x[ln], ymin=-100, ymax=100, linewidth=3, color='k')
                    if li == 'GAMMA':
                        labels[ln] = r'$\Gamma$'
                    elif li is not '':
                        labels[ln] = '${0}$'.format(li)
                    #end if
                    if labels[ln - 1] is not '' and ln > 0:
                        labels[ln] = labels[ln - 1] + '|' + labels[ln]
                        labels[ln - 1] = ''
                    #end if
                #end if
            #end for

            xlim([min(x), max(x)])
            if max_min_e is None:
                ylim(-5, +5)
            else:
                ylim(max_min_e[0], max_min_e[1])
            #end if
            ylabel('Energy (eV)')
            xticks(x, labels)
            ax.tick_params(axis='x', which='both', length=0)
            ax.tick_params(axis='x', which='both', pad=10)
        #end if
        if show_vbm_cbm:
            vbm = self.bands.vbm
            cbm = self.bands.cbm
            for kn, ki in enumerate(self.bands.up):
                if (vbm.kpoint_rel == ki['kpoint_rel']).all():
                    scatter(x[kn], 0, c='green', s=100)
                #end if
                if (cbm.kpoint_rel == ki['kpoint_rel']).all():
                    scatter(x[kn], cbm.energy - vbm.energy, c='r', s=100)
                #end if
            #end for
        #end if
        if save:
            savefig(filename, format='pdf', bbox_inches='tight')
        #end if
        if show:
            show()
Ejemplo n.º 2
0
    def post_analyze(self,analyzer):
        if not self.has_generic_input():
            calctypes = self.input.get_output_info('calctypes')
            opt_run = calctypes!=None and 'opt' in calctypes
            if opt_run:
                opt_file = analyzer.results.optimization.optimal_file
                if opt_file is None:
                    self.failed = True
                #end if
            #end if
            exc_run = 'excitation' in self
            if exc_run:
                exc_failure = False

                edata = self.read_einspline_dat()
                exc_input = self.excitation

                exc_spin,exc_type,exc_spins,exc_types,exc1,exc2 = check_excitation_type(exc_input)

                elns = self.input.get_electron_particle_set()
                
                if exc_type==exc_types.band: 
                    # Band Index 'tw1 band1 tw2 band2'. Eg., '0 45 3 46'
                    # Check that tw1,band1 is no longer in occupied set
                    tw1,bnd1 = exc2.split()[0:2]
                    tw2,bnd2 = exc2.split()[2:4]
                    if exc1 in ('up','down'):
                        spin_channel = exc1
                        dsc = edata[spin_channel]
                        for idx,(tw,bnd) in enumerate(zip(dsc.TwistIndex,dsc.BandIndex)):
                            if tw == int(tw1) and bnd == int(bnd1):
                                # This orbital should no longer be in the set of occupied orbitals
                                if idx<elns.groups[spin_channel[0]].size:
                                    msg  = 'WARNING: You requested \'{}\' excitation of type \'{}\',\n'
                                    msg += '         however, the first orbital \'{} {}\' is still occupied (see einspline file).\n'
                                    msg += '         Please check your input.'
                                    msg = msg.format(spin_channel,exc_input[1],tw1,bnd1)
                                    exc_failure = True
                                #end if
                            elif tw == int(tw2) and bnd == int(bnd2):
                                # This orbital should be in the set of occupied orbitals
                                if idx>=elns.groups[spin_channel[0]].size:
                                    msg  = 'WARNING: You requested \'{}\' excitation of type \'{}\',\n'
                                    msg += '         however, the second orbital \'{} {}\' is not occupied (see einspline file).\n'
                                    msg += '         Please check your input.'
                                    msg = msg.format(spin_channel,exc_input[1],tw2,bnd2)
                                    exc_failure = True
                                #end if
                            #end if
                        #end for
                    else:
                        self.warn('No check for \'{}\' excitation of type \'{}\' was done. When this path is possible, then a check should be written.'.format(exc_input[0],exc_input[1]))
                    #end if
                elif exc_type in (exc_types.energy,exc_types.lowest):
                    # Lowest or Energy Index '-orbindex1 +orbindex2'. Eg., '-4 +5'
                    if exc_type==exc_types.lowest:
                        if exc_spin==exc_spins.down:
                            orb1 = elns.groups.d.size
                        else:
                            orb1 = elns.groups.u.size
                        #end if
                        orb2 = orb1+1 
                    else:
                        orb1 = int(exc_input[1].split()[0][1:])
                        orb2 = int(exc_input[1].split()[1][1:])
                    #end if
                    if exc1 in ('up','down'):

                        spin_channel = exc1
                        nelec = elns.groups[spin_channel[0]].size
                        eigs_spin = edata[spin_channel].Energy

                        # Construct the correct set of occupied orbitals by hand based on
                        # orb1 and orb2 values that were input by the user
                        excited = eigs_spin
                        order = eigs_spin.argsort()
                        ground = excited[order]
                        # einspline orbital ordering for excited state
                        excited = excited[:nelec]
                        # hand-crafted orbital order for excited state

                        # ground can be list or ndarray, but we'll convert it to list
                        # so we can concatenate with list syntax
                        ground = np.asarray(ground).tolist()
                        # After concatenating, convert back to ndarray
                        hc_excited = np.array(ground[:orb1-1]+[ground[orb2-1]]+ground[orb1:nelec])
                            
                        etol = 1e-6
                        if np.abs(hc_excited-excited).max() > etol:
                            msg  = 'WARNING: You requested \'{}\' excitation of type \'{}\',\n'
                            msg += '         however, the second orbital \'{}\' is not occupied (see einspline file).\n'
                            msg += '         Please check your input.'
                            msg = msg.format(spin_channel,exc_input[1],orb1)
                            exc_failure = True
                        #end if

                    elif exc1 in ('singlet','triplet'):
                        wf = self.input.get('wavefunction')
                        occ = wf.determinantset.multideterminant.detlist.csf.occ
                        if occ[int(orb1)-1]!='1':
                            msg  = 'WARNING: You requested \'{}\' excitation of type \'{}\',\n'
                            msg += '         however, this is inconsistent with the occupations in detlist \'{}\'.\n'
                            msg += '         Please check your input.'
                            msg = msg.format(spin_channel,exc_input[1],occ)
                            exc_failure = True
                        #end if
                        if occ[int(orb2)-1]!='1':
                            msg  = 'WARNING: You requested \'{}\' excitation of type \'{}\',\n'
                            msg += '         however, this is inconsistent with the occupations in detlist \'{}\'.\n'
                            msg += '         Please check your input.'
                            msg = msg.format(spin_channel,exc_input[1],occ)
                            exc_failure = True
                        #end if
                    #end if

                else:
                    # The format is: 'gamma vb z cb'
                    if exc1 in ('singlet','triplet'):
                        self.warn('No check for \'{}\' excitation of type \'{}\' was done. When this path is possible, then a check should be written.'.format(exc_input[0],exc_input[1]))
                    else:

                        # assume excitation of form 'gamma vb k cb' or 'gamma vb-1 k cb+1'
                        excitation = exc2.upper().split(' ')
                        k_1, band_1, k_2, band_2 = excitation
                        tilematrix = self.system.structure.tilematrix()
                        
                        wf = self.input.get('wavefunction')
                        if exc_spin==exc_spins.up:
                            sdet =  wf.determinantset.get('updet')
                        else:
                            sdet =  wf.determinantset.get('downdet')
                        #end if
                        from numpy import linalg,where,isclose
                        vb = int(sdet.size / abs(linalg.det(tilematrix))) -1  # Separate for each spin channel
                        cb = vb+1
                        # Convert band_1, band_2 to band indexes
                        bands = [band_1, band_2]
                        for bnum, b in enumerate(bands):
                            b = b.lower()
                            if 'cb' in b:
                                if '-' in b:
                                    b = b.split('-')
                                    bands[bnum] = cb - int(b[1])
                                elif '+' in b:
                                    b = b.split('+')
                                    bands[bnum] = cb + int(b[1])
                                else:
                                    bands[bnum] = cb
                                #end if
                            elif 'vb' in b:
                                if '-' in b:
                                    b = b.split('-')
                                    bands[bnum] = vb - int(b[1])
                                elif '+' in b:
                                    b = b.split('+')
                                    bands[bnum] = vb + int(b[1])
                                else:
                                    bands[bnum] = vb
                                #end if
                            else:
                                QmcpackInput.class_error('{0} in excitation has the wrong formatting'.format(b))
                            #end if
                        #end for
                        band_1, band_2 = bands
                        
                        # Convert k_1 k_2 to wavevector indexes
                        structure = self.system.structure.get_smallest().copy()
                        structure.change_units('A')

                        from structure import get_kpath
                        kpath       = get_kpath(structure=structure)
                        kpath_label = array(kpath['explicit_kpoints_labels'])
                        kpath_rel   = kpath['explicit_kpoints_rel']
                        
                        k1_in = k_1
                        k2_in = k_2
                        if k_1 in kpath_label and k_2 in kpath_label:   
                            k_1 = kpath_rel[where(kpath_label == k_1)][0]
                            k_2 = kpath_rel[where(kpath_label == k_2)][0]

                            kpts = structure.kpoints_unit()
                            found_k1 = False
                            found_k2 = False
                            for knum, k in enumerate(kpts):
                                if isclose(k_1, k).all():
                                    k_1 = knum
                                    found_k1 = True
                                #end if
                                if isclose(k_2, k).all():
                                    k_2 = knum
                                    found_k2 = True
                                #end if
                            #end for
                            if not found_k1 or not found_k2:
                                QmcpackInput.class_error('Requested special kpoint is not in the tiled cell\nRequested "{}", present={}\nRequested "{}", present={}\nAvailable kpoints: {}'.format(k1_in,found_k1,k2_in,found_k2,sorted(set(kpath_label))))
                            #end if
                        else:
                            QmcpackInput.class_error('Excitation wavevectors are not found in the kpath\nlabels requested: {} {}\nlabels present: {}'.format(k_1,k_2,sorted(set(kpath_label))))
                        #end if

                        tw1,bnd1 = (k_1,band_1)
                        tw2,bnd2 = (k_2,band_2)
                        spin_channel = exc1
                        dsc = edata[spin_channel]
                        for idx,(tw,bnd) in enumerate(zip(dsc.TwistIndex,dsc.BandIndex)):
                            if tw == int(tw1) and bnd == int(bnd1):
                                # This orbital should no longer be in the set of occupied orbitals
                                if idx<elns.groups[spin_channel[0]].size:
                                    msg  = 'WARNING: You requested \'{}\' excitation of type \'{}\',\n'
                                    msg += '         however, the first orbital \'{} {}\' is still occupied (see einspline file).\n'
                                    msg += '         Please check your input.'
                                    msg = msg.format(spin_channel,exc_input[1],tw1,bnd1)
                                    exc_failure = True
                                #end if
                            elif tw == int(tw2) and bnd == int(bnd2):
                                # This orbital should be in the set of occupied orbitals
                                if idx>=elns.groups[spin_channel[0]].size:
                                    msg  = 'WARNING: You requested \'{}\' excitation of type \'{}\',\n'
                                    msg += '         however, the second orbital \'{} {}\' is not occupied (see einspline file).\n'
                                    msg += '         Please check your input.'
                                    msg = msg.format(spin_channel,exc_input[1],tw2,bnd2)
                                    exc_failure = True
                                #end if
                            #end if
                        #end for

                #end if

                if exc_failure:
                    self.failed = True
                    self.warn(msg)
                    filename = self.identifier+'_errors.txt'
                    open(os.path.join(self.locdir,filename),'w').write(msg)