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
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
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
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
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