Exemplo n.º 1
0
    def ArgumentParser(self, p=None, *args, **kwargs):
        """ Returns the arguments that is available for this Sile """
        #limit_args = kwargs.get('limit_arguments', True)
        short = kwargs.get('short', False)

        def opts(*args):
            if short:
                return args
            return [args[0]]

        # We limit the import to occur here
        import argparse

        # The first thing we do is adding the geometry to the NameSpace of the
        # parser.
        # This will enable custom actions to interact with the geometry in a
        # straight forward manner.
        d = {
            "_bands": self.read_data(),
            "_Emap": None,
        }
        namespace = default_namespace(**d)

        # Energy grabs
        class ERange(argparse.Action):
            def __call__(self, parser, ns, value, option_string=None):
                ns._Emap = strmap(float, value)[0]

        p.add_argument(
            '--energy',
            '-E',
            action=ERange,
            help=
            'Denote the sub-section of energies that are plotted: "-1:0,1:2" [eV]'
        )

        class BandsPlot(argparse.Action):
            def __call__(self, parser, ns, value, option_string=None):
                import matplotlib.pyplot as plt
                # Decide whether this is BandLines or BandPoints
                if len(ns._bands) == 2:
                    # We do not plot "points"
                    raise ValueError(
                        "The bands file only contains points in the BZ, not a bandstructure."
                    )
                lbls, k, b = ns._bands
                b = b.T
                # Extract to tick-marks and names
                xlbls, lbls = lbls

                def myplot(ax, title, x, y, E):
                    ax.set_title(title)
                    for ib in range(y.shape[0]):
                        ax.plot(x, y[ib, :])
                    ax.set_ylabel('E-Ef [eV]')
                    ax.set_xlim(x.min(), x.max())
                    if not E is None:
                        ax.set_ylim(E[0], E[1])

                if b.shape[1] == 2:
                    _, ax = plt.subplots(2, 1)
                    ax[0].set_xticks(xlbls)
                    ax[0].set_xticklabels([''] * len(xlbls))
                    ax[1].set_xticks(xlbls)
                    ax[1].set_xticklabels(lbls, rotation=45)
                    # We must plot spin-up/down separately
                    for i, ud in enumerate(['UP', 'DOWN']):
                        myplot(ax[i], 'Bandstructure SPIN-' + ud, k,
                               b[:, i, :], ns._Emap)
                else:
                    plt.figure()
                    ax = plt.gca()
                    ax.set_xticks(xlbls)
                    ax.set_xticklabels(lbls, rotation=45)
                    myplot(ax, 'Bandstructure', k, b[:, 0, :], ns._Emap)
                if value is None:
                    plt.show()
                else:
                    plt.savefig(value)

        p.add_argument(
            *opts('--plot', '-p'),
            action=BandsPlot,
            nargs='?',
            metavar='FILE',
            help=
            'Plot the bandstructure from the .bands file, possibly saving to a file.'
        )

        return p, namespace
Exemplo n.º 2
0
    def ArgumentParser(self, p=None, *args, **kwargs):
        """ Returns the arguments that is available for this Sile """
        #limit_args = kwargs.get('limit_arguments', True)
        short = kwargs.get('short', False)

        def opts(*args):
            if short:
                return args
            return [args[0]]

        # We limit the import to occur here
        import argparse

        # The first thing we do is adding the geometry to the NameSpace of the
        # parser.
        # This will enable custom actions to interact with the geometry in a
        # straight forward manner.
        d = {
            "_eigs": self.read_data(),
            "_Emap": None,
        }
        namespace = default_namespace(**d)

        # Energy grabs
        class ERange(argparse.Action):
            def __call__(self, parser, ns, value, option_string=None):
                ns._Emap = strmap(float, value)[0]

        p.add_argument(
            '--energy',
            '-E',
            action=ERange,
            help=
            'Denote the sub-section of energies that are plotted: "-1:0,1:2" [eV]'
        )

        # k-point weights
        class KP(argparse.Action):
            def __call__(self, parser, ns, value, option_string=None):
                ns._weights = kpSileSiesta(value[0]).read_data()[1]

        p.add_argument(
            '--kp-file',
            '-kp',
            nargs=1,
            metavar='FILE',
            action=KP,
            help=
            'The k-point file from which to read the band-weights (only applicable to --dos option)'
        )

        class EIGPlot(argparse.Action):
            def __call__(self, parser, ns, value, option_string=None):
                import matplotlib.pyplot as plt
                E = ns._eigs
                #Emin = np.min(E)
                #Emax = np.max(E)
                #n = E.shape[1]
                # We need to setup a relatively good size of the scatter
                # plots
                s = 10  #20. / max(Emax - Emin, n)

                def myplot(ax, title, y, E, s):
                    ax.set_title(title)
                    for ib in range(y.shape[0]):
                        ax.scatter(np.ones(y.shape[1]) * ib, y[ib, :], s=s)
                    ax.set_xlabel('k-index')
                    ax.set_xlim(-0.5, len(y) + 0.5)
                    if not E is None:
                        ax.set_ylim(E[0], E[1])

                if E.shape[0] == 2:
                    _, ax = plt.subplots(1, 2)
                    ax[0].set_ylabel('E-Ef [eV]')

                    # We must plot spin-up/down separately
                    for i, ud in enumerate(['UP', 'DOWN']):
                        myplot(ax[i], 'Eigenspectrum SPIN-' + ud, E[i, :, :],
                               ns._Emap, s)
                else:
                    plt.figure()
                    ax = plt.gca()
                    ax.set_ylabel('E-Ef [eV]')
                    myplot(ax, 'Eigenspectrum', E[0, :, :], ns._Emap, s)
                if value is None:
                    plt.show()
                else:
                    plt.savefig(value)

        p.add_argument(
            *opts('--plot', '-p'),
            action=EIGPlot,
            nargs='?',
            metavar='FILE',
            help=
            'Plot the eigenvalues from the .EIG file, possibly saving plot to a file.'
        )

        # Energy grabs
        class DOSPlot(argparse.Action):
            def __call__(dos_self, parser, ns, value, option_string=None):
                import matplotlib.pyplot as plt
                if not hasattr(ns, '_weight'):
                    # Try and read in the k-point-weights
                    ns._weight = kpSileSiesta(
                        str(self.file).replace('EIG', 'KP')).read_data()[1]

                if ns._Emap is None:
                    # We will plot the DOS in the entire energy window
                    ns._Emap = [ns._eigs.min(), ns._eigs.max()]

                if len(ns._weight) != ns._eigs.shape[1]:
                    raise SileError(
                        str(self) +
                        ' --dos the number of k-points for the eigenvalues and k-point weights '
                        'are different, please use --weight correctly.')

                # Specify default settings
                dE = 0.005  # 5 meV
                kT = units('K', 'eV') * 300
                distr = get_distribution('gaussian', smearing=kT)
                out = None
                if len(value) > 0:
                    i = 0
                    try:
                        dE = float(value[i])
                        i += 1
                    except:
                        pass
                    try:
                        kT = float(value[i])
                        i += 1
                    except:
                        pass
                    try:
                        distr = get_distribution(value[i], smearing=kT)
                        i += 1
                    except:
                        pass
                    try:
                        out = value[i]
                    except:
                        pass

                # Now we are ready to process
                E = np.arange(ns._Emap[0] - kT * 4, ns._Emap[1] + kT * 4, dE)

                def myplot(ax, legend, E, eig, w):
                    DOS = np.zeros(len(E))
                    for ib in range(eig.shape[0]):
                        for e in eig[ib, :]:
                            DOS += distr(E - e) * w[ib]
                    ax.plot(E, DOS, label=legend)
                    ax.set_ylim(0, None)

                plt.figure()
                ax = plt.gca()
                ax.set_title('DOS kT={:.1f} K'.format(kT * units('eV', 'K')))
                ax.set_xlabel('E - Ef [eV]')
                ax.set_xlim(E.min(), E.max())
                ax.set_ylabel('DOS [1/eV]')
                if ns._eigs.shape[0] == 2:
                    for i, ud in enumerate(['up', 'down']):
                        myplot(ax, ud, E, ns._eigs[i, :, :], ns._weight)
                    plt.legend()
                else:
                    myplot(ax, '', E, ns._eigs[0, :, :], ns._weight)
                if out is None:
                    plt.show()
                else:
                    plt.savefig(out)

        p.add_argument(
            '--dos',
            action=DOSPlot,
            nargs='*',
            metavar='dE,kT,DIST,FILE',
            help='Plot the density of states from the .EIG file, '
            'dE = energy separation, kT = smearing, DIST = distribution function (Gaussian) possibly saving plot to a file.'
        )

        return p, namespace
Exemplo n.º 3
0
    def ArgumentParser(self, p=None, *args, **kwargs):
        """ Returns the arguments that is available for this Sile """
        import argparse

        # We must by-pass this fdf-file for importing
        import sisl.io.siesta as sis

        # The fdf parser is more complicated

        # It is based on different settings based on the

        sp = p.add_subparsers(
            help=
            "Determine which part of the fdf-file that should be processed.")

        # Get the label which retains all the sub-modules
        label = self._tofile(self.get('SystemLabel', default='siesta'))

        # The default on all sub-parsers are the retrieval and setting

        d = {
            '_fdf': self,
            '_fdf_first': True,
        }
        namespace = default_namespace(**d)

        ep = sp.add_parser(
            'edit', help='Change or read and print data from the fdf file')

        # As the fdf may provide additional stuff, we do not add EVERYTHING from
        # the Geometry class.
        class FDFAdd(argparse.Action):
            def __call__(self, parser, ns, values, option_string=None):
                key = values[0]
                val = values[1]
                if ns._fdf_first:
                    # Append to the end of the file
                    with ns._fdf as fd:
                        fd.write('\n\n# SISL added keywords\n')
                    setattr(ns, '_fdf_first', False)
                ns._fdf.set(key, val)

        ep.add_argument(
            '--set',
            '-s',
            nargs=2,
            metavar=('KEY', 'VALUE'),
            action=FDFAdd,
            help=
            'Add a key to the FDF file. If it already exists it will be overwritten'
        )

        class FDFGet(argparse.Action):
            def __call__(self, parser, ns, value, option_string=None):
                # Retrieve the value in standard units
                # Currently, we write out the unit "as-is"
                val = ns._fdf.get(value[0], with_unit=True)
                if val is None:
                    print('# {} is currently not in the FDF file '.format(
                        value[0]))
                    return

                if isinstance(val, tuple):
                    print(ns._fdf.print(value[0], '{} {}'.format(*val)))
                else:
                    print(ns._fdf.print(value[0], val))

        ep.add_argument(
            '--get',
            '-g',
            nargs=1,
            metavar='KEY',
            action=FDFGet,
            help='Print (to stdout) the value of the key in the FDF file.')

        # If the XV file exists, it has precedence
        # of the contained geometry (we will issue
        # a warning in that case)
        f = label + '.XV'
        try:
            geom = self.read_geometry(True)

            tmp_p = sp.add_parser(
                'geom', help="Edit the contained geometry in the file")
            tmp_p, tmp_ns = geom.ArgumentParser(tmp_p, *args, **kwargs)
            namespace = merge_instances(namespace, tmp_ns)
        except:
            # Allowed pass due to pythonic reading
            pass

        f = label + '.bands'
        if isfile(f):
            tmp_p = sp.add_parser(
                'band',
                help="Manipulate bands file from the Siesta simulation")
            tmp_p, tmp_ns = sis.bandsSileSiesta(f).ArgumentParser(
                tmp_p, *args, **kwargs)
            namespace = merge_instances(namespace, tmp_ns)

        f = label + '.PDOS.xml'
        if isfile(f):
            tmp_p = sp.add_parser(
                'pdos',
                help="Manipulate PDOS.xml file from the Siesta simulation")
            tmp_p, tmp_ns = pdosSileSiesta(f).ArgumentParser(
                tmp_p, *args, **kwargs)
            namespace = merge_instances(namespace, tmp_ns)

        f = label + '.EIG'
        if isfile(f):
            tmp_p = sp.add_parser(
                'eig', help="Manipulate EIG file from the Siesta simulation")
            tmp_p, tmp_ns = sis.eigSileSiesta(f).ArgumentParser(
                tmp_p, *args, **kwargs)
            namespace = merge_instances(namespace, tmp_ns)

        f = label + '.TBT.nc'
        if isfile(f):
            tmp_p = sp.add_parser('tbt', help="Manipulate tbtrans output file")
            tmp_p, tmp_ns = sis.tbtncSileSiesta(f).ArgumentParser(
                tmp_p, *args, **kwargs)
            namespace = merge_instances(namespace, tmp_ns)

        f = label + '.TBT.Proj.nc'
        if isfile(f):
            tmp_p = sp.add_parser(
                'tbt-proj', help="Manipulate tbtrans projection output file")
            tmp_p, tmp_ns = sis.tbtprojncSileSiesta(f).ArgumentParser(
                tmp_p, *args, **kwargs)
            namespace = merge_instances(namespace, tmp_ns)

        f = label + '.PHT.nc'
        if isfile(f):
            tmp_p = sp.add_parser('pht',
                                  help="Manipulate the phtrans output file")
            tmp_p, tmp_ns = sis.phtncSileSiesta(f).ArgumentParser(
                tmp_p, *args, **kwargs)
            namespace = merge_instances(namespace, tmp_ns)

        f = label + '.PHT.Proj.nc'
        if isfile(f):
            tmp_p = sp.add_parser(
                'pht-proj', help="Manipulate phtrans projection output file")
            tmp_p, tmp_ns = sis.phtprojncSileSiesta(f).ArgumentParser(
                tmp_p, *args, **kwargs)
            namespace = merge_instances(namespace, tmp_ns)

        f = label + '.nc'
        if isfile(f):
            tmp_p = sp.add_parser('nc',
                                  help="Manipulate Siesta NetCDF output file")
            tmp_p, tmp_ns = sis.ncSileSiesta(f).ArgumentParser(
                tmp_p, *args, **kwargs)
            namespace = merge_instances(namespace, tmp_ns)

        return p, namespace
Exemplo n.º 4
0
Arquivo: basis.py Projeto: juijan/sisl
    def ArgumentParser(self, p=None, *args, **kwargs):
        """ Returns the arguments that is available for this Sile """
        #limit_args = kwargs.get('limit_arguments', True)
        short = kwargs.get('short', False)

        def opts(*args):
            if short:
                return args
            return [args[0]]

        # We limit the import to occur here
        import argparse

        Bohr2Ang = unit_convert('Bohr', 'Ang')
        Ry2eV = unit_convert('Bohr', 'Ang')

        # The first thing we do is adding the geometry to the NameSpace of the
        # parser.
        # This will enable custom actions to interact with the geometry in a
        # straight forward manner.
        # convert netcdf file to a dictionary
        ion_nc = PropertyDict()
        ion_nc.n = self._variable('orbnl_n')[:]
        ion_nc.l = self._variable('orbnl_l')[:]
        ion_nc.zeta = self._variable('orbnl_z')[:]
        ion_nc.pol = self._variable('orbnl_ispol')[:]
        ion_nc.orbital = self._variable('orb')[:]

        # this gets converted later
        delta = self._variable('delta')[:]
        r = aranged(ion_nc.orbital.shape[1]).reshape(1, -1) * delta.reshape(-1, 1)
        ion_nc.orbital *= r ** ion_nc.l.reshape(-1, 1) / Bohr2Ang * (3./2.)
        ion_nc.r = r * Bohr2Ang
        ion_nc.kb = PropertyDict()
        ion_nc.kb.n = self._variable('pjnl_n')[:]
        ion_nc.kb.l = self._variable('pjnl_l')[:]
        ion_nc.kb.e = self._variable('pjnl_ekb')[:] * Ry2eV
        ion_nc.kb.proj = self._variable('proj')[:]
        delta = self._variable('kbdelta')[:]
        r = aranged(ion_nc.kb.proj.shape[1]).reshape(1, -1) * delta.reshape(-1, 1)
        ion_nc.kb.proj *= r ** ion_nc.kb.l.reshape(-1, 1) / Bohr2Ang * (3./2.)
        ion_nc.kb.r = r * Bohr2Ang

        vna = self._variable('vna')
        r = aranged(vna[:].size) * vna.Vna_delta
        ion_nc.vna = PropertyDict()
        ion_nc.vna.v = vna[:] * Ry2eV * r / Bohr2Ang ** 3
        ion_nc.vna.r = r * Bohr2Ang

        # this is charge (not 1/sqrt(charge))
        chlocal = self._variable('chlocal')
        r = aranged(chlocal[:].size) * chlocal.Chlocal_delta
        ion_nc.chlocal = PropertyDict()
        ion_nc.chlocal.v = chlocal[:] * r / Bohr2Ang ** 3
        ion_nc.chlocal.r = r * Bohr2Ang

        vlocal = self._variable('reduced_vlocal')
        r = aranged(vlocal[:].size) * vlocal.Reduced_vlocal_delta
        ion_nc.vlocal = PropertyDict()
        ion_nc.vlocal.v = vlocal[:] * r / Bohr2Ang ** 3
        ion_nc.vlocal.r = r * Bohr2Ang

        if "core" in self.variables:
            # this is charge (not 1/sqrt(charge))
            core = self._variable('core')
            r = aranged(core[:].size) * core.Core_delta
            ion_nc.core = PropertyDict()
            ion_nc.core.v = core[:] * r / Bohr2Ang ** 3
            ion_nc.core.r = r * Bohr2Ang

        d = {
            "_data": ion_nc,
            "_kb_proj": False,
            "_l": True,
            "_n": True,
        }
        namespace = default_namespace(**d)

        # l-quantum number
        class lRange(argparse.Action):

            def __call__(self, parser, ns, value, option_string=None):
                value = (value
                         .replace("s", 0)
                         .replace("p", 1)
                         .replace("d", 2)
                         .replace("f", 3)
                         .replace("g", 4)
                )
                ns._l = strmap(int, value)[0]
        p.add_argument('-l',
                       action=lRange,
                       help='Denote the sub-section of l-shells that are plotted: "s,f"')

        # n quantum number
        class nRange(argparse.Action):

            def __call__(self, parser, ns, value, option_string=None):
                ns._n = strmap(int, value)[0]
        p.add_argument('-n',
                       action=nRange,
                       help='Denote the sub-section of n quantum numbers that are plotted: "2-4,6"')

        class Plot(argparse.Action):

            def __call__(self, parser, ns, value, option_string=None):
                import matplotlib.pyplot as plt

                # Retrieve values
                data = ns._data

                # We have these plots:
                #  - orbitals
                #  - projectors
                #  - chlocal
                #  - vna
                #  - vlocal
                #  - core (optional)

                # We'll plot them like this:
                #  orbitals | projectors
                #  vna + vlocal | chlocal + core
                #
                # Determine different n, l
                fig, axs = plt.subplots(2, 2)

                # Now plot different orbitals
                for n, l, zeta, pol, r, orb in zip(data.n, data.l, data.zeta,
                                                   data.pol, data.r, data.orbital):
                    if pol == 1:
                        pol = 'P'
                    else:
                        pol = ''
                    axs[0][0].plot(r, orb, label=f"n{n}l{l}Z{zeta}{pol}")
                axs[0][0].set_title("Orbitals")
                axs[0][0].set_xlabel("Distance [Ang]")
                axs[0][0].set_ylabel("Value [a.u.]")
                axs[0][0].legend()

                # plot projectors
                for n, l, e, r, proj in zip(
                        data.kb.n, data.kb.l, data.kb.e, data.kb.r, data.kb.proj):
                    axs[0][1].plot(r, proj, label=f"n{n}l{l} e={e:.5f}")
                axs[0][1].set_title("KB projectors")
                axs[0][1].set_xlabel("Distance [Ang]")
                axs[0][1].set_ylabel("Value [a.u.]")
                axs[0][1].legend()

                axs[1][0].plot(data.vna.r, data.vna.v, label='Vna')
                axs[1][0].plot(data.vlocal.r, data.vlocal.v, label='Vlocal')
                axs[1][0].set_title("Potentials")
                axs[1][0].set_xlabel("Distance [Ang]")
                axs[1][0].set_ylabel("Potential [eV]")
                axs[1][0].legend()

                axs[1][1].plot(data.chlocal.r, data.chlocal.v, label='Chlocal')
                if "core" in data:
                    axs[1][1].plot(data.core.r, data.core.v, label='core')
                axs[1][1].set_title("Charge")
                axs[1][1].set_xlabel("Distance [Ang]")
                axs[1][1].set_ylabel("Charge [Ang^3]")
                axs[1][1].legend()

                if value is None:
                    plt.show()
                else:
                    plt.savefig(value)
        p.add_argument(*opts('--plot', '-p'), action=Plot, nargs='?', metavar='FILE',
                       help='Plot the content basis set file, possibly saving plot to a file.')

        return p, namespace
Exemplo n.º 5
0
    def ArgumentParser(self, p=None, *args, **kwargs):
        """ Returns the arguments that is available for this Sile """
        #limit_args = kwargs.get('limit_arguments', True)
        short = kwargs.get('short', False)

        def opts(*args):
            if short:
                return args
            return [args[0]]

        # We limit the import to occur here
        import argparse

        # The first thing we do is adding the geometry to the NameSpace of the
        # parser.
        # This will enable custom actions to interact with the geometry in a
        # straight forward manner.
        d = {
            "_eigs": self.read_data(),
            "_Emap": None,
        }
        namespace = default_namespace(**d)

        # Energy grabs
        class ERange(argparse.Action):
            def __call__(self, parser, ns, value, option_string=None):
                ns._Emap = strmap(float, value)[0]

        p.add_argument(
            '--energy',
            '-E',
            action=ERange,
            help=
            'Denote the sub-section of energies that are plotted: "-1:0,1:2" [eV]'
        )

        class EIGPlot(argparse.Action):
            def __call__(self, parser, ns, value, option_string=None):
                import matplotlib.pyplot as plt
                E = ns._eigs
                #Emin = np.min(E)
                #Emax = np.max(E)
                #n = E.shape[1]
                # We need to setup a relatively good size of the scatter
                # plots
                s = 10  #20. / max(Emax - Emin, n)

                def myplot(ax, title, y, E, s):
                    ax.set_title(title)
                    for ib in range(y.shape[0]):
                        ax.scatter(np.ones(y.shape[1]) * ib, y[ib, :], s=s)
                    ax.set_xlabel('k-index')
                    ax.set_xlim(-0.5, len(y) + 0.5)
                    if not E is None:
                        ax.set_ylim(E[0], E[1])

                if E.shape[0] == 2:
                    _, ax = plt.subplots(1, 2)
                    ax[0].set_ylabel('E-Ef [eV]')

                    # We must plot spin-up/down separately
                    for i, ud in enumerate(['UP', 'DOWN']):
                        myplot(ax[i], 'Eigenspectrum SPIN-' + ud, E[i, :, :],
                               ns._Emap, s)
                else:
                    plt.figure()
                    ax = plt.gca()
                    ax.set_ylabel('E-Ef [eV]')
                    myplot(ax, 'Eigenspectrum', E[0, :, :], ns._Emap, s)
                if value is None:
                    plt.show()
                else:
                    plt.savefig(value)

        p.add_argument(
            *opts('--plot', '-p'),
            action=EIGPlot,
            nargs='?',
            metavar='FILE',
            help=
            'Plot the eigenvalues from the .EIG file, possibly saving plot to a file.'
        )

        return p, namespace