Skip to content

Commit 06becb7

Browse files
committed
Merge branch 'develop' of github.com:abinit/abipy into factories
pull trunk develop
2 parents 88a2550 + ad859c4 commit 06becb7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1939
-607
lines changed

README.rst

+5-13
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,8 @@ The installation process is greatly simplified if you install the required
7474
python packages through `Anaconda <https://continuum.io/downloads>`_ (or conda).
7575
See `Installing conda`_ to install conda itself.
7676
We routinely use conda_ to test new developments with multiple Python versions and multiple virtual environments.
77-
The anaconda distribution already provides the most critical dependencies (matplotlib_, scipy_, numpy_, netcdf4-python_)
78-
in the form of pre-compiled packages that can be easily installed with e.g.::
7977

80-
conda install numpy scipy netcdf4
81-
82-
Create a new conda_ environment (let's call it ``abienv``) with::
78+
Create a new conda_ environment based on python 3.11 (let's call it ``abienv``) with::
8379

8480
conda create --name abienv python=3.11
8581

@@ -89,15 +85,11 @@ and activate it with::
8985

9086
You should see the name of the conda environment in the shell prompt.
9187

92-
Now add ``conda-forge`` to your conda channels with::
93-
94-
conda config --add channels conda-forge
95-
96-
This is the channel from which we will download pymatgen, abipy and abinit.
97-
9888
Finally, install AbiPy with::
9989

100-
conda install abipy
90+
conda install abipy -c conda-forge
91+
92+
Please note that, at present, conda-forge does not provide executables
10193

10294
Additional information on the steps required to install AbiPy with anaconda are available
10395
in the `anaconda howto <http://abinit.github.io/abipy/installation#anaconda-howto>`_.
@@ -199,7 +191,6 @@ Otherwise, follow the usual abinit installation instructions, and make sure abin
199191

200192
abinit --version
201193

202-
203194
Configuration files for Abipy
204195
=============================
205196

@@ -379,6 +370,7 @@ The following scripts can be invoked directly from the terminal:
379370
* ``abirun.py`` Execute AbiPy flow from terminal.
380371
* ``abidoc.py`` Document Abinit input variables and Abipy configuration files.
381372
* ``abinp.py`` Build input files (simplified interface for the AbiPy factory functions).
373+
* ``abipsp.py`` Download pseudopotential tables from the PseudoDojo.
382374

383375
Use ``SCRIPT --help`` to get the list of supported commands and
384376
``SCRIPT COMMAND --help`` to get the documentation for ``COMMAND``.

abipy/abilab.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
from abipy.flowtk import Pseudo, PseudoTable, Mrgscr, Mrgddb, Flow, Work, TaskManager, AbinitBuild, flow_main
2929
from abipy.core.release import __version__, min_abinit_version
3030
from abipy.core.globals import enable_notebook, in_notebook, disable_notebook
31-
#from abipy.core import restapi
3231
from abipy.core.structure import (Lattice, Structure, StructureModifier, dataframes_from_structures,
3332
mp_match_structure, mp_search, cod_search, display_structure)
3433
from abipy.core.mixins import TextFile, JsonFile, CubeFile
@@ -67,6 +66,7 @@
6766
from abipy.eph.a2f import A2fFile, A2fRobot
6867
from abipy.eph.sigeph import SigEPhFile, SigEPhRobot
6968
from abipy.eph.cumulant import CumulantEPhFile
69+
from abipy.eph.varpeq import VarpeqFile
7070
from abipy.eph.eph_plotter import EphPlotter
7171
from abipy.eph.v1sym import V1symFile
7272
from abipy.eph.gkq import GkqFile, GkqRobot
@@ -181,6 +181,7 @@ def _straceback():
181181
("V1QAVG.nc", V1qAvgFile),
182182
("ABIWAN.nc", AbiwanFile),
183183
("EPH_CUMULANT.nc", CumulantEPhFile),
184+
("VARPEQ.nc", VarpeqFile),
184185
])
185186

186187

abipy/abio/robots.py

+81-51
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from monty.json import MontyEncoder
2222
from abipy.tools.serialization import pmg_serialize
2323
from abipy.tools.iotools import make_executable
24+
from abipy.core.structure import Structure
2425
from abipy.core.mixins import NotebookWriter
2526
from abipy.tools.numtools import sort_and_groupby
2627
from abipy.tools import duck
@@ -333,6 +334,30 @@ def from_flow(cls, flow, outdirs="all", nids=None, ext=None, task_class=None) ->
333334

334335
return robot
335336

337+
338+
def __len__(self):
339+
return len(self._abifiles)
340+
341+
#def __iter__(self):
342+
# return iter(self._abifiles)
343+
344+
def __getitem__(self, key):
345+
# self[key]
346+
return self._abifiles.__getitem__(key)
347+
348+
def __enter__(self):
349+
return self
350+
351+
def __exit__(self, exc_type, exc_val, exc_tb):
352+
"""Activated at the end of the with statement."""
353+
self.close()
354+
355+
def keys(self):
356+
return self._abifiles.keys()
357+
358+
def items(self):
359+
return self._abifiles.items()
360+
336361
def add_extfile_of_node(self, node, nids=None, task_class=None) -> None:
337362
"""
338363
Add the file produced by this node to the robot.
@@ -547,32 +572,6 @@ def exceptions(self) -> list:
547572
"""List of exceptions."""
548573
return self._exceptions
549574

550-
def __len__(self):
551-
return len(self._abifiles)
552-
553-
#def __iter__(self):
554-
# return iter(self._abifiles)
555-
556-
#def __contains__(self, item):
557-
# return item in self._abifiles
558-
559-
def __getitem__(self, key):
560-
# self[key]
561-
return self._abifiles.__getitem__(key)
562-
563-
def __enter__(self):
564-
return self
565-
566-
def __exit__(self, exc_type, exc_val, exc_tb):
567-
"""Activated at the end of the with statement."""
568-
self.close()
569-
570-
def keys(self):
571-
return self._abifiles.keys()
572-
573-
def items(self):
574-
return self._abifiles.items()
575-
576575
@property
577576
def labels(self) -> list[str]:
578577
"""
@@ -614,6 +613,24 @@ def _repr_html_(self) -> str:
614613
"""Integration with jupyter_ notebooks."""
615614
return '<ol start="0">\n{}\n</ol>'.format("\n".join("<li>%s</li>" % label for label, abifile in self.items()))
616615

616+
def getattr_alleq(self, aname : str):
617+
"""
618+
Return the value of attribute aname.
619+
Raises ValueError if value is not the same across all the files in the robot.
620+
"""
621+
val1 = getattr(self.abifiles[0], aname)
622+
623+
for abifile in self.abifiles[1:]:
624+
val2 = getattr(abifile, aname)
625+
if isinstance(val1, (str, int, float)):
626+
eq = val1 == val2
627+
elif isinstance(val1, np.ndarray):
628+
eq = np.allclose(val1, val2)
629+
if not eq:
630+
raise ValueError(f"Different values of {aname=}, {val1=}, {val2=}")
631+
632+
return val1
633+
617634
@property
618635
def abifiles(self) -> list:
619636
"""List of netcdf files."""
@@ -639,22 +656,45 @@ def has_different_structures(self, rtol=1e-05, atol=1e-08) -> str:
639656

640657
return "\n".join(lines)
641658

642-
#def apply(self, func_or_string, args=(), **kwargs):
643-
# """
644-
# Applies function to all ``abifiles`` available in the robot.
659+
def _get_ref_abifile_from_basename(self, ref_basename: str | None):
660+
"""
661+
Find reference abifile. If None, the first file in the robot is used.
662+
"""
663+
ref_file = self.abifiles[0]
664+
if ref_basename is None:
665+
return ref_file
645666

646-
# Args:
647-
# func_or_string: If callable, the output of func_or_string(abifile, ...) is used.
648-
# If string, the output of getattr(abifile, func_or_string)(...)
649-
# args (tuple): Positional arguments to pass to function in addition to the array/series
650-
# kwargs: Additional keyword arguments will be passed as keywords to the function
667+
for i, abifile in enumerate(self.abifiles):
668+
if abifile.basename == ref_basename:
669+
return abifile
651670

652-
# Return: List of results
653-
# """
654-
# if callable(func_or_string):
655-
# return [func_or_string(abifile, *args, *kwargs) for abifile in self.abifiles]
656-
# else:
657-
# return [duck.getattrd(abifile, func_or_string)(*args, **kwargs) for abifile in self.abifiles]
671+
raise ValueError(f"Cannot find {ref_basename=}")
672+
673+
@staticmethod
674+
def _compare_attr_name(aname: str, ref_abifile, other_abifile) -> None:
675+
"""
676+
Compare the value of attribute `aname` in two files.
677+
"""
678+
# Get attributes in abifile first, then in abifile.r, else raise.
679+
if hasattr(ref_abifile, aname):
680+
val1, val2 = getattr(ref_abifile, aname), getattr(other_abifile, aname)
681+
682+
elif hasattr(ref_abifile , "r") and hasattr(ref_abifile.r, aname):
683+
val1, val2 = getattr(ref_abifile.r, aname), getattr(other_abifile.r, aname)
684+
685+
else:
686+
raise AttributeError(f"Cannot find attribute `{aname =}`")
687+
688+
# Now compare val1 and val2 taking into account the type.
689+
if isinstance(val1, (str, int, float, Structure)):
690+
eq = val1 == val2
691+
elif isinstance(val1, np.ndarray):
692+
eq = np.allclose(val1, val2)
693+
else:
694+
raise TypeError(f"Don't know how to handle comparison for type: {type(val1)}")
695+
696+
if not eq:
697+
raise ValueError(f"Different values of {aname=}, {val1=}, {val2=}")
658698

659699
def is_sortable(self, aname: str, raise_exc: bool = False) -> bool:
660700
"""
@@ -812,16 +852,6 @@ def close(self) -> None:
812852
print("Exception while closing: ", abifile.filepath)
813853
print(exc)
814854

815-
#def get_attributes(self, attr_name, obj=None, retdict=False):
816-
# od = OrderedDict()
817-
# for label, abifile in self.items():
818-
# obj = abifile if obj is None else getattr(abifile, obj)
819-
# od[label] = getattr(obj, attr_name)
820-
# if retdict:
821-
# return od
822-
# else:
823-
# return list(od.values())
824-
825855
def _exec_funcs(self, funcs, arg) -> dict:
826856
"""
827857
Execute list of callable functions. Each function receives arg as argument.
@@ -1236,7 +1266,7 @@ def plot_abs_conv(ax1, ax2, xs, yvals, abs_conv, xlabel, fontsize, hatch, **kwar
12361266
"""
12371267
y_xmax = yvals[-1]
12381268
span_style = dict(alpha=0.2, color="green", hatch=hatch)
1239-
ax1.axhspan(y_xmax - abs_conv, y_xmax + abs_conv, label=r"$|y-y(x_{max})}| \leq %s$" % abs_conv, **span_style)
1269+
ax1.axhspan(y_xmax - abs_conv, y_xmax + abs_conv, label=r"$|y-y(x_{max})| \leq %s$" % abs_conv, **span_style)
12401270

12411271
# Plot |y - y_xmax| in log scale on ax2.
12421272
ax2.plot(xs, np.abs(yvals - y_xmax), **kwargs)

abipy/core/atom.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111
from monty.functools import lazy_property
1212
from monty.string import marquee # is_string, list_strings,
1313
from scipy.interpolate import UnivariateSpline
14-
from scipy.integrate import cumtrapz
14+
try :
15+
from scipy.integrate import cumulative_trapezoid as cumtrapz
16+
except ImportError:
17+
from scipy.integrate import cumtrapz
18+
1519
from abipy.data import nist_database
1620
from abipy.tools.serialization import pmg_serialize
1721

abipy/core/func1d.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,11 @@ def integral(self, start=0, stop=None) -> Function1D:
282282
"""
283283
if stop is None: stop = len(self.values) + 1
284284
x, y = self.mesh[start:stop], self.values[start:stop]
285-
from scipy.integrate import cumtrapz
285+
try :
286+
from scipy.integrate import cumulative_trapezoid as cumtrapz
287+
except ImportError:
288+
from scipy.integrate import cumtrapz
289+
286290
integ = cumtrapz(y, x=x, initial=0.0)
287291

288292
return self.__class__(x, integ)

abipy/core/kpoints.py

+35-2
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,39 @@ def map_kpoints(other_kpoints, other_lattice, ref_lattice, ref_kpoints, ref_symr
406406
# #return irred_map
407407

408408

409+
def kpoints_indices(frac_coords, ngkpt, check_mesh=0) -> np.ndarray:
410+
"""
411+
This function is used when we need to insert k-dependent quantities in a (nx, ny, nz) array.
412+
It compute the indices of the k-points assuming these points belong to
413+
a mesh with ngkpt divisions.
414+
415+
Args:
416+
frac_coords
417+
ngkpt:
418+
check_mesh
419+
"""
420+
# Transforms kpt in its corresponding reduced number in the interval [0,1[
421+
k_indices = [np.round((kpt % 1) * ngkpt) for kpt in frac_coords]
422+
423+
k_indices = np.array(k_indices, dtype=int)
424+
#k_indices = np.array(list(map(tuple, k_indices)))
425+
#k_indices = list(map(tuple, k_indices))
426+
427+
if check_mesh:
428+
print(f"kpoints_indices: Testing whether k-points belong to the {ngkpt =} mesh")
429+
ierr = 0
430+
for kpt, inds in zip(frac_coords, k_indices):
431+
#print("kpt:", kpt, "inds:", inds)
432+
same_k = np.array((inds[0]/ngkpt[0], inds[1]/ngkpt[1], inds[2]/ngkpt[2]))
433+
if not issamek(kpt, same_k):
434+
ierr += 1; print(kpt, "-->", same_k)
435+
if ierr:
436+
raise ValueError("Wrong mapping")
437+
print("Check succesful!")
438+
439+
return k_indices
440+
441+
409442
def find_irred_kpoints_generic(structure, kfrac_coords, verbose=1):
410443
"""
411444
Remove the k-points that are connected to each other by one of the
@@ -948,7 +981,7 @@ def __eq__(self, other):
948981
def __ne__(self, other):
949982
return not (self == other)
950983

951-
def index(self, kpoint):
984+
def index(self, kpoint) -> int:
952985
"""
953986
Returns: the first index of kpoint in self.
954987
@@ -971,7 +1004,7 @@ def get_all_kindices(self, kpoint):
9711004
if k == k0: kinds.append(ik)
9721005
return np.array(kinds)
9731006

974-
def find(self, kpoint):
1007+
def find(self, kpoint) -> int:
9751008
"""
9761009
Returns: first index of kpoint. -1 if not found
9771010
"""

abipy/core/skw.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,12 @@ def get_edos(self, kmesh, is_shift=None, method="gaussian", step=0.1, width=0.2,
217217
values[spin] += wtk * gaussian(wmesh, width, center=eigens[spin, ik, band])
218218

219219
# Compute IDOS
220-
integral = scipy.integrate.cumtrapz(values, x=wmesh, initial=0.0)
220+
try :
221+
from scipy.integrate import cumulative_trapezoid as cumtrapz
222+
except ImportError:
223+
from scipy.integrate import cumtrapz
224+
225+
integral = cumtrapz(values, x=wmesh, initial=0.0)
221226

222227
else:
223228
raise ValueError("Method %s is not supported" % method)

0 commit comments

Comments
 (0)