diff --git a/abipy/core/abinit_units.py b/abipy/core/abinit_units.py index d8588f74..2feff284 100644 --- a/abipy/core/abinit_units.py +++ b/abipy/core/abinit_units.py @@ -4,52 +4,57 @@ This module defines constants and conversion factors matching those present in a it is important to preserve consistency with the results produced by abinit. """ from __future__ import print_function, division, unicode_literals, absolute_import + import numpy as np # taken from abinit/10_defs/defs_basis.F90 # 1 Bohr, in Angstrom -Bohr_Ang=0.52917720859 +Bohr_Ang = 0.52917720859 # 1 Hartree, in cm^-1 -Ha_cmm1=219474.6313705 +Ha_cmm1 = 219474.6313705 # 1 Hartree, in eV -Ha_eV=27.21138386 +Ha_eV = 27.21138386 # 1 eV in Hartree -eV_Ha=1./Ha_eV +eV_Ha = 1. / Ha_eV # 1 Hartree, in meV -Ha_meV=Ha_eV*1000 -# 1Hartree, in Kelvin -Ha_K=315774.65 +Ha_meV = Ha_eV * 1000 +# 1 Hartree, in Kelvin +Ha_K = 315774.65 +# 1 eV, in Kelvin +eV_to_K = eV_Ha * Ha_K # 1 Hartree, in THz -Ha_THz=6579.683920722 +Ha_THz = 6579.683920722 # 1 eV, in THz -eV_to_THz=eV_Ha*Ha_THz -#1 Hartree, in J -Ha_J=4.35974394e-18 +eV_to_THz = eV_Ha * Ha_THz +# 1 eV, in cm-1 +eV_to_cm1 = 8065.5440044136285 +# 1 Hartree, in J +Ha_J = 4.35974394e-18 # minus the electron charge, in Coulomb -e_Cb=1.602176487e-19 +e_Cb = 1.602176487e-19 # Boltzmann constant in eV/K and Ha/K -kb_eVK=8.617343e-5 +kb_eVK = 8.617343e-5 kb_HaK = kb_eVK / Ha_eV # 1 atomic mass unit, in electronic mass -amu_emass=1.660538782e-27/9.10938215e-31 +amu_emass = 1.660538782e-27 / 9.10938215e-31 # 1 Ha/Bohr^3, in GPa -HaBohr3_GPa=Ha_eV/Bohr_Ang**3*e_Cb*1.0e+21 +HaBohr3_GPa = Ha_eV / Bohr_Ang**3 * e_Cb * 1.0e+21 # per mole -Avogadro=6.02214179e23 +Avogadro = 6.02214179e23 # 1 Ohm.cm in atomic units -Ohmcm=2*np.pi*Ha_THz*10/9 -eps0=1/(4*np.pi*0.0000001*299792458.0**2) -AmuBohr2_Cm2=e_Cb*1.0e20/(Bohr_Ang*Bohr_Ang) +Ohmcm = 2 * np.pi * Ha_THz * 10 / 9 +eps0 = 1 / (4*np.pi*0.0000001*299792458.0**2) +AmuBohr2_Cm2 = e_Cb * 1.0e20 / (Bohr_Ang * Bohr_Ang) # Inverse of fine structure constant -InvFineStruct=137.035999679 +InvFineStruct = 137.035999679 # speed of light in SI -Sp_Lt_SI=2.99792458e8 +Sp_Lt_SI = 2.99792458e8 # speed of light in atomic units -Sp_Lt=Sp_Lt_SI/2.1876912633e6 -# Atomic unit of time, in seconds -Time_Sec=2.418884326505e-17 +Sp_Lt = Sp_Lt_SI / 2.1876912633e6 +# Atomic unit of time, in seconds +Time_Sec = 2.418884326505e-17 # Tesla in a.u. -BField_Tesla=4.254383e-6 +BField_Tesla = 4.254383e-6 # Debye unit in a.u. -dipole_moment_debye=0.393430307 \ No newline at end of file +dipole_moment_debye = 0.393430307 diff --git a/abipy/data/runs/run_eph_al.py b/abipy/data/runs/run_eph_al.py index 255d0578..3d2ab005 100755 --- a/abipy/data/runs/run_eph_al.py +++ b/abipy/data/runs/run_eph_al.py @@ -84,6 +84,7 @@ def build_flow(options): eph_task = eph_work.register_eph_task(eph_inp, deps=eph_deps) flow.allocate() + flow.use_smartio() # EPH does not support autoparal (yet) #eph_task.with_fixed_mpi_omp(1, 1) diff --git a/abipy/data/runs/run_si_ebands.py b/abipy/data/runs/run_si_ebands.py index 509eb846..103086ac 100755 --- a/abipy/data/runs/run_si_ebands.py +++ b/abipy/data/runs/run_si_ebands.py @@ -54,7 +54,7 @@ def build_flow(options): # Working directory (default is the name of the script with '.py' removed and "run_" replaced by "flow_") workdir = options.workdir if not options.workdir: - workdir = os.pathbasename(__file__).replace(".py", "").replace("run_", "flow_") + workdir = os.path.basename(__file__).replace(".py", "").replace("run_", "flow_") # Get the SCF and the NSCF input. scf_input, nscf_input = make_scf_nscf_inputs() diff --git a/abipy/dfpt/phonons.py b/abipy/dfpt/phonons.py index 23734abe..3ac53033 100644 --- a/abipy/dfpt/phonons.py +++ b/abipy/dfpt/phonons.py @@ -42,33 +42,54 @@ def factor_ev2units(units): """ Return conversion factor eV --> units (case-insensitive) """ - eV_to_cm1 = 8065.5440044136285 d = {"ev": 1, "mev": 1000, "ha": eV_to_Ha, - "cm-1": eV_to_cm1, 'cm^-1': eV_to_cm1, "thz": abu.eV_to_THz, + "cm-1": abu.eV_to_cm1, 'cm^-1': abu.eV_to_cm1, + "thz": abu.eV_to_THz, } try: - return d[units.lower()] + return d[units.lower().strip()] except KeyError: raise KeyError('Value for units `{}` unknown\nPossible values are:\n {}'.format(units, list(d.keys()))) def unit_tag(units): + """ + Return latex string for `units`. + """ d = {"ev": "[eV]", "mev": "[meV]", "ha": '[Ha]', "cm-1": "[cm$^{-1}$]", 'cm^-1': "[cm$^{-1}$]", "thz": '[Thz]', } try: - return d[units.lower()] + return d[units.lower().strip()] + except KeyError: + raise KeyError('Value for units `{}` unknown\nPossible values are:\n {}'.format(units, list(d.keys()))) + + +def wlabel_from_units(units): + """ + Return latex string for frequencies in `units`. + """ + d = {'ev': 'Energy [eV]', 'mev': 'Energy [meV]', 'ha': 'Energy [Ha]', + 'cm-1': r'Frequency [cm$^{-1}$]', + 'cm^-1': r'Frequency [cm$^{-1}$]', + 'thz': r'Frequency [Thz]', + } + try: + return d[units.lower().strip()] except KeyError: raise KeyError('Value for units `{}` unknown\nPossible values are:\n {}'.format(units, list(d.keys()))) def dos_label_from_units(units): + """ + Return latex string for phonon DOS values in `units`. + """ d = {"ev": "[states/eV]", "mev": "[states/meV]", "ha": '[states/Ha]', "cm-1": "[states/cm$^{-1}$]", 'cm^-1': "[states/cm$^{-1}$]", "thz": '[states/Thz]', } try: - return d[units.lower()] + return d[units.lower().strip()] except KeyError: raise KeyError('Value for units `{}` unknown\nPossible values are:\n {}'.format(units, list(d.keys()))) @@ -842,21 +863,8 @@ class PhononBands(object): ax.grid(True) # Handle conversion factor. - # TODO: Encapsulate this part. - units = units.lower() - if units == 'ev': - ax.set_ylabel('Energy [eV]') - elif units == 'mev': - ax.set_ylabel('Energy [meV]') - elif units == 'ha': - ax.set_ylabel('Energy [Ha]') - elif units in ('cm-1', 'cm^-1'): - ax.set_ylabel(r'Frequency [cm$^{-1}$]') - elif units == 'thz': - ax.set_ylabel(r'Frequency [Thz]') - else: - if units: - raise ValueError('Value for units `{}` unknown'.format(units)) + if units: + ax.set_ylabel(wlabel_from_units(units)) # Set ticks and labels. ticks, labels = self._make_ticks_and_labels(kwargs.pop("qlabels", None)) diff --git a/abipy/dfpt/tests/test_phonons.py b/abipy/dfpt/tests/test_phonons.py index ddf3d411..bf2525c4 100644 --- a/abipy/dfpt/tests/test_phonons.py +++ b/abipy/dfpt/tests/test_phonons.py @@ -10,7 +10,7 @@ import abipy.data as abidata from abipy import abilab from abipy.dfpt.phonons import (PhononBands, PhononDos, PhdosFile, InteratomicForceConstants, phbands_gridplot, PhononBandsPlotter, PhononDosPlotter, dataframe_from_phbands) -from abipy.dfpt.phonons import factor_ev2units, unit_tag, dos_label_from_units +from abipy.dfpt.phonons import factor_ev2units, unit_tag, dos_label_from_units, wlabel_from_units from abipy.dfpt.ddb import DdbFile from abipy.core.testing import AbipyTest @@ -21,9 +21,10 @@ class TestUnitTools(AbipyTest): def test_units_api(self): for units in ["ev", "meV" ,"ha", "cm-1", "cm^-1", "Thz"]: - factor_ev2units(units) - unit_tag(units) - dos_label_from_units(units) + assert factor_ev2units(units) + assert unit_tag(units) + assert dos_label_from_units(units) + assert wlabel_from_units(units) for func in [factor_ev2units, unit_tag, dos_label_from_units]: with self.assertRaises(KeyError): diff --git a/abipy/electrons/ebands.py b/abipy/electrons/ebands.py index 1815b2d0..dafab13c 100644 --- a/abipy/electrons/ebands.py +++ b/abipy/electrons/ebands.py @@ -2794,8 +2794,8 @@ class ElectronDos(object): def to_string(self, verbose=0): """String representation.""" lines = []; app = lines.append - app("nsppol=%d, nelect=%s" % (self.nsppol, self.nelect)) - app("Fermi energy: %s (recomputed from nelect):" % self.fermie) + app("nsppol: %d, nelect: %s" % (self.nsppol, self.nelect)) + app("Fermi energy: %s [eV] (recomputed from nelect):" % self.fermie) return "\n".join(lines) @classmethod diff --git a/abipy/eph/eph.py b/abipy/eph/eph.py index e50e6cdb..75b9fd3d 100644 --- a/abipy/eph/eph.py +++ b/abipy/eph/eph.py @@ -9,6 +9,7 @@ from __future__ import print_function, division, unicode_literals, absolute_impo import numpy as np import pymatgen.core.units as units +import abipy.core.abinit_units as abu from collections import OrderedDict from scipy.integrate import cumtrapz, simps @@ -19,7 +20,7 @@ from abipy.core.kpoints import Kpath from abipy.tools.plotting import add_fig_kwargs, get_ax_fig_plt, set_axlims from abipy.electrons.ebands import ElectronsReader, ElectronDos, RobotWithEbands from abipy.dfpt.phonons import (PhononBands, PhononDos, RobotWithPhbands, - factor_ev2units, unit_tag, dos_label_from_units) + factor_ev2units, unit_tag, dos_label_from_units, wlabel_from_units) from abipy.abio.robots import Robot @@ -88,9 +89,11 @@ class A2f(object): app("Mesh from %.4f to %.4f [eV] with %d points" % ( self.mesh[0], self.mesh[-1], len(self.mesh))) - app("lambda_iso: %.3f, omega_log %s" % (self.lambda_iso, self.omega_log)) - for mustar in [0.8, 0.6]: - app("For mustar %s: McMillan Tc: %s [K]" % (mustar, self.get_mcmillan_tc(mustar))) + # TODO: Add ElectronDos + app("Isotropic lambda: %.3f" % (self.lambda_iso)) + app("Omega_log: %s [eV], %s [K]" % (self.omega_log, self.omega_log * abu.eV_to_K)) + for mustar in (0.1, 0.2): + app("\tFor mustar %s: McMillan Tc: %s [K]" % (mustar, self.get_mcmillan_tc(mustar))) if verbose: # $\int dw [a2F(w)/w] w^n$ @@ -107,13 +110,24 @@ class A2f(object): @lazy_property def omega_log(self): r""" - Get log moment of alpha^2F. - exp((2/\lambda) \int dw a2F(w) ln(w)/w) + Get log moment of alpha^2F: exp((2/\lambda) \int dw a2F(w) ln(w)/w) """ - wmesh, a2fw = self.mesh[self.iw0+1:], self.values[self.iw0+1:] - wmesh = wmesh * units.eV_to_Ha - integral = simps(a2fw * (np.log(wmesh) / wmesh), x=wmesh) - return np.exp(2.0 * integral / self.lambda_iso) * units.Ha_to_eV + #return 270 / abu.eV_to_K + iw = self.iw0 + 1 + #iw = self.iw0 + 100 + wmesh, a2fw = self.mesh[iw:], self.values[iw:] + #wmesh = wmesh * units.eV_to_Ha + #wmesh = wmesh * abu.eV_to_THz + + #ax, fig, plt = get_ax_fig_plt(ax=None) + #ax.plot(wmesh, a2fw / wmesh * np.log(wmesh)) + #plt.show() + + integral = simps(a2fw / wmesh * np.log(wmesh), x=wmesh) + + #return np.exp(2.0 / self.lambda_iso * integral) * units.Ha_to_eV + #return np.exp(2.0 / self.lambda_iso * integral) / abu.eV_to_THz + return np.exp(2.0 / self.lambda_iso * integral) #/ abu.eV_to_THz def get_moment(self, n, spin=None, cumulative=False): r""" @@ -153,15 +167,17 @@ class A2f(object): """ Computes the critical temperature with the McMillan equation and the input mustar. """ - tc = self.omega_log / 1.2 * np.exp((-1.04 * (1.0 + self.lambda_iso)) / (self.lambda_iso - mustar * (1.0 + 0.62 * self.lambda_iso))) - eV_to_K = 11604.5250061657 - return tc * eV_to_K + tc = (self.omega_log / 1.2) * \ + np.exp(-1.04 * (1.0 + self.lambda_iso) / (self.lambda_iso - mustar * (1.0 + 0.62 * self.lambda_iso))) + return tc * abu.eV_to_K - #def get_mustar_from_tc(self, tc): - # """ - # Return the value of mustar that gives the critical temperature tc in McMillan equation - # """ - # return 0 + def get_mustar_from_tc(self, tc): + """ + Return the value of mustar that gives the critical temperature tc in K in the McMillan equation. + """ + l = self.lambda_iso + num = l + (1.04 * (1 + l) / np.log(1.2 * abu.kb_eVK * tc / self.omega_log)) + return num / (1 + 0.62 * l) @add_fig_kwargs def plot(self, units="eV", with_lambda=True, exchange_xy=False, ax=None, @@ -171,8 +187,8 @@ class A2f(object): contributions due to the phonon branches. Args: - units: Units for phonon plots. Possible values in ("eV", "meV", "Ha", "cm-1", "Thz"). - Case-insensitive. + units: Units for phonon plots. Possible values in + ("eV", "meV", "Ha", "cm-1", "Thz"). Case-insensitive. with_lambda: exchange_xy: True to exchange x-y axes. ax: matplotlib :class:`Axes` or None if a new figure should be created. @@ -186,6 +202,8 @@ class A2f(object): """"" ax, fig, plt = get_ax_fig_plt(ax=ax) + wfactor = factor_ev2units(units) + # TODO Better handling of styles style = dict( linestyle=kwargs.pop("linestyle", "-"), @@ -194,7 +212,7 @@ class A2f(object): ) # Plot a2f(w) - xx, yy = self.mesh, self.values + xx, yy = self.mesh * wfactor, self.values if exchange_xy: xx, yy = yy, xx ax.plot(xx, yy, label=label, **style) @@ -202,7 +220,7 @@ class A2f(object): if with_lambda: lambda_w = self.get_moment(n=0, cumulative=True) l_ax = ax.twinx() - xx, yy = self.mesh, lambda_w + xx, yy = self.mesh * wfactor, lambda_w if exchange_xy: xx, yy = yy, xx l_ax.plot(xx, yy, label=label, **style) l_ax.set_ylabel(r"$\lambda(\omega)$") @@ -210,11 +228,12 @@ class A2f(object): if self.nsppol == 2: # Plot spin resolved a2f(w). for spin in range(self.nsppol): - xx, yy = self.mesh, self.values_spin[spin] + xx, yy = self.mesh * wfactor, self.values_spin[spin] if exchange_xy: xx, yy = yy, xx ax_plot(xx, yy, marker=self.marker_spin[spin], **style) - xlabel, ylabel = r"$\omega$ [eV]", r"$\alpha^2F(\omega)$" + xlabel = wlabel_from_units(units) + ylabel = r"$\alpha^2F(\omega)$" if exchange_xy: xlabel, ylabel = ylabel, xlabel ax.set_xlabel(xlabel) ax.set_ylabel(ylabel) @@ -253,6 +272,9 @@ class A2f(object): axmat = np.reshape(axmat, (self.natom, 3)) fig = plt.gcf() + wfactor = factor_ev2units(units) + wvals = self.mesh * wfactor + if with_lambda: lax_nu = [ax.twinx() for ax in axmat.flat] # Share axis after creation. Based on @@ -288,18 +310,18 @@ class A2f(object): #ax.set_yticks([]) if iatom == self.natom -1: - ax.set_xlabel(r"$\omega$ [eV]") + ax.set_xlabel(wlabel_from_units(units)) #set_axlims(ax, xlims, "x") #set_axlims(ax, ylims, "y") # Plot total a2f(w) - ax.plot(self.mesh, self.values_nu[nu], **a2f_style) + ax.plot(wvals, self.values_nu[nu], **a2f_style) # Plot lambda(w) if with_lambda: lambdaw_nu = self.get_moment_nu(n=0, nu=nu, cumulative=True) lax = lax_nu[nu] - lax.plot(self.mesh, lambdaw_nu, **lambda_style) + lax.plot(wvals, lambdaw_nu, **lambda_style) if idir == 2: lax.set_ylabel(r"$\lambda_{\nu}(\omega)$", color=lambda_style["color"]) @@ -313,12 +335,21 @@ class A2f(object): @add_fig_kwargs def plot_a2(self, phdos, atol=1e-12, **kwargs): - """grid with 3 plots (a2F, F, a2F).""" + """ + Grid with 3 plots (a2F, F, a2F). + + Args: + phdos: + atol: + + Returns: + `matplotlib` figure + """ phdos = PhononDos.as_phdos(phdos) import matplotlib.pyplot as plt fig, ax_list = plt.subplots(nrows=3, ncols=1, sharex=True, sharey=False, squeeze=True) - # Spline phdos onto a2f mesh and compute a2F / F + # Spline phdos onto a2f mesh and compute a2F(w) / F(w) f = phdos.spline(self.mesh) f = self.values / np.where(np.abs(f) > atol, f, atol) ax = ax_list[0] @@ -337,6 +368,33 @@ class A2f(object): return fig + @add_fig_kwargs + def plot_tc_vs_mustar(self, start=0.1, stop=0.5, num=50, ax=None, **kwargs): + """ + Plot Tc(mustar) + + Args: + start: The starting value of the sequence. + stop: The end value of the sequence + num: int, optional + Number of samples to generate. Default is 50. Must be non-negative. + ax: matplotlib :class:`Axes` or None if a new figure should be created. + + Returns: + `matplotlib` figure + """ + mustar_values = np.linspace(start, stop, num=num) + tc_vals = [self.get_mcmillan_tc(mustar) for mustar in mustar_values] + + ax, fig, plt = get_ax_fig_plt(ax=ax) + ax.plot(mustar_values, tc_vals, **kwargs) + ax.set_yscale("log") + ax.grid(True) + ax.set_xlabel(r"$\mu^*$") + ax.set_ylabel(r"$T_c [K]$") + + return fig + class A2Ftr(object): @@ -373,7 +431,7 @@ class A2Ftr(object): class EphFile(AbinitNcFile, Has_Structure, Has_ElectronBands, NotebookWriter): """ This file contains the phonon linewidths, EliashbergFunction, the phonon bands, - the ElectronBands on the k-mesh. + the `ElectronBands` and `ElectronDos` on the k-mesh. Provides methods to plot results. Usage example: @@ -626,6 +684,23 @@ class EphFile(AbinitNcFile, Has_Structure, Has_ElectronBands, NotebookWriter): set_axlims(ax, ylims, "y") return fig + @add_fig_kwargs + def plot_a2f_interpol(self, units="eV", ax=None, ylims=None, **kwargs): + """ + Plot + """ + ax, fig, plt = get_ax_fig_plt(ax=ax) + #linestyle_qsamp = dict(qcoarse="--", qintp="-") + for qsamp in ["qcoarse", "qintp"]: + a2f = self.get_a2f_qsamp(qsamp) + a2f.plot(units=units, ylims=ylims, ax=ax, with_lambda=False, show=False) + #ax.yaxis.set_ticks_position("right") + #ax.yaxis.set_label_position("right") + #ax.tick_params(labelbottom='off') + #ax.set_ylabel("") + + return fig + @add_fig_kwargs def plot_with_a2f(self, units="eV", qsamp="qintp", phdos=None, ylims=None, **kwargs): """ @@ -660,9 +735,6 @@ class EphFile(AbinitNcFile, Has_Structure, Has_ElectronBands, NotebookWriter): self.plot(units=units, ylims=ylims, ax=ax_phbands, show=False) # Plot a2F(w) - #a2f = self.a2f_qcoarse - #a2f.plot(units=units, exchange_xy=True, ylims=ylims, ax=ax, show=False) - a2f = self.get_a2f_qsamp(qsamp) ax = ax_doses[0] a2f.plot(units=units, exchange_xy=True, ylims=ylims, ax=ax, with_lambda=False, show=False) @@ -707,7 +779,7 @@ class EphFile(AbinitNcFile, Has_Structure, Has_ElectronBands, NotebookWriter): nbv.new_code_cell("print(ncfile)"), nbv.new_code_cell("ncfile.ebands.plot();"), nbv.new_code_cell("ncfile.plot();"), - nbv.new_code_cell("ncfile.plot_phlinewidths();"), + #nbv.new_code_cell("ncfile.plot_phlinewidths();"), nbv.new_code_cell("ncfile.plot_with_a2f();"), nbv.new_code_cell("ncfile.a2f.plot();"), ]) @@ -973,7 +1045,7 @@ class EphReader(ElectronsReader): assert qsamp in ("qcoarse", "qintp") mesh = self.read_value("a2f_mesh_" + qsamp) * units.Ha_to_eV # C shape [nsppol, natom + 1, nomega] - data = self.read_value("a2f_values_" + qsamp) #/ units.Ha_to_eV + data = self.read_value("a2f_values_" + qsamp) # * 0.25 values_spin = data[:, 0, :].copy() values_spin_nu = data[:, 1:, :].copy() return A2f(mesh, values_spin, values_spin_nu) diff --git a/abipy/eph/tests/test_eph.py b/abipy/eph/tests/test_eph.py index 51502dbc..c32ea0f2 100644 --- a/abipy/eph/tests/test_eph.py +++ b/abipy/eph/tests/test_eph.py @@ -44,10 +44,11 @@ class EphFileTest(AbipyTest): #self.assert_almost_equal(m1/2, a2f.get_moment(n=1, spin=0)) #self.assert_almost_equal(self.lambda_iso, ) #self.assert_almost_equal(self.omega_log, ) - #self.assert_almost_equal(a2f.get_mcmillan_Tc(mustar=0.8), ) - #tc = 10 - #mustar = a2f.get_mustar_from_tc(tc) - #self.assert_almost_equal(a2f.get_mcmillan_Tc(mustar), tc) + tc = a2f.get_mcmillan_tc(mustar=0.1) + #self.assert_almost_equal(tc, ) + mustar = a2f.get_mustar_from_tc(tc) + self.assert_almost_equal(mustar, 0.1) + #self.assert_almost_equal(a2f.get_mcmillan_tc(mustar), tc) assert not ncfile.has_a2ftr assert ncfile.a2ftr_qcoarse is None @@ -58,6 +59,7 @@ class EphFileTest(AbipyTest): if self.has_matplotlib(): # Test A2f plot methods assert ncfile.a2f_qcoarse.plot(show=False) + assert ncfile.a2f_qcoarse.plot_tc_vs_mustar(show=False) assert ncfile.a2f_qintp.plot_a2(phdos_path, show=False) assert ncfile.a2f_qintp.plot_nuterms(show=False) diff --git a/abipy/integration_tests/TODO b/abipy/integration_tests/TODO index 5a112bd0..082020be 100644 --- a/abipy/integration_tests/TODO +++ b/abipy/integration_tests/TODO @@ -1,4 +1,6 @@ TODO LIST: + + # Check PJDOS in abinit@gitlab # Use angdeg instead of rprimd in structure_to_abivars if hex or rhomboedral lattice. @@ -54,4 +56,5 @@ TODO LIST: # Add option max_num_launchers in scheduler.yml - # Add extra metadata to netcdf files (try to propagate info on space group from parser to crystal_t) + # Add extra metadata to netcdf files (try to propagate info on space group from parser to crystal_t + as well as Abinit input as string) diff --git a/abipy/scripts/abirun.py b/abipy/scripts/abirun.py index 3d20a3f1..1af88f69 100755 --- a/abipy/scripts/abirun.py +++ b/abipy/scripts/abirun.py @@ -662,8 +662,10 @@ def get_parser(with_epilog=False): # Subparser for single command. p_single = subparsers.add_parser('single', parents=[copts_parser], help="Run single task and exit.") - # Subparser for rapidfire command. + # Subparser for rapid command. p_rapid = subparsers.add_parser('rapid', parents=[copts_parser], help="Run all tasks in rapidfire mode.") + p_rapid.add_argument('-m', '--max-nlaunch', default=10, type=int, + help="Maximum number of launches. default: 10. Use -1 for no limit.") # Subparser for scheduler command. p_scheduler = subparsers.add_parser('scheduler', parents=[copts_parser], @@ -706,8 +708,6 @@ def get_parser(with_epilog=False): # Subparser for reset command. p_reset = subparsers.add_parser('reset', parents=[copts_parser, flow_selector_parser], help="Reset the tasks of the flow with the specified status.") - p_reset.add_argument("--relaunch", action="store_true", default=False, - help="Relaunch tasks in rapid mode after reset.") # Subparser for move command. p_move = subparsers.add_parser('move', parents=[copts_parser], @@ -1080,13 +1080,13 @@ def main(): elif options.command == "single": nlaunch = flow.single_shot() - print("Number of tasks launched: %d" % nlaunch) if nlaunch: flow.show_status() + cprint("Number of tasks launched: %d" % nlaunch, "yellow") elif options.command == "rapid": - nlaunch = flow.rapidfire() - print("Number of tasks launched: %d" % nlaunch) + nlaunch = flow.rapidfire(max_nlaunch=options.max_nlaunch, max_loops=1, sleep_time=5) if nlaunch: flow.show_status() + cprint("Number of tasks launched: %d" % nlaunch, "yellow") elif options.command == "scheduler": # Check that the env on the local machine is properly configured before starting the scheduler. @@ -1204,19 +1204,12 @@ def main(): count += 1 cprint("%d tasks have been reset" % count, "blue") - # Try to relaunch - nlaunch = 0 - if options.relaunch: - nlaunch = flow.rapidfire() - cprint("Number of tasks launched: %d" % nlaunch, "magenta") - flow.show_status() - if nlaunch == 0: - g = flow.find_deadlocks() - #print("deadlocked:", gdeadlocked, "\nrunnables:", grunnables, "\nrunning:", g.running) - if g.deadlocked and not (g.runnables or g.running): - cprint("*** Flow is deadlocked ***", "red") + g = flow.find_deadlocks() + #print("deadlocked:", gdeadlocked, "\nrunnables:", grunnables, "\nrunning:", g.running) + if g.deadlocked and not (g.runnables or g.running): + cprint("*** Flow is deadlocked ***", "red") flow.pickle_dump()