irrep 3.2.0__tar.gz → 3.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {irrep-3.2.0 → irrep-3.3.0}/PKG-INFO +1 -1
- {irrep-3.2.0 → irrep-3.3.0}/irrep/_version.py +3 -3
- {irrep-3.2.0 → irrep-3.3.0}/irrep/altermagnetic_transformer.py +17 -8
- {irrep-3.2.0 → irrep-3.3.0}/irrep/bandstructure.py +19 -4
- {irrep-3.2.0 → irrep-3.3.0}/irrep/kpoint.py +1 -1
- {irrep-3.2.0 → irrep-3.3.0}/irrep/kpoint_gpaw.py +20 -8
- {irrep-3.2.0 → irrep-3.3.0}/irrep/spacegroup.py +22 -1
- irrep-3.3.0/irrep/storage.py +69 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/symmetry_operation.py +4 -1
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_gpaw.py +30 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_spacegroup.py +21 -1
- {irrep-3.2.0 → irrep-3.3.0}/irrep/utility.py +11 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep.egg-info/PKG-INFO +1 -1
- {irrep-3.2.0 → irrep-3.3.0}/irrep.egg-info/SOURCES.txt +1 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep.egg-info/scm_file_list.json +1 -0
- irrep-3.3.0/irrep.egg-info/scm_version.json +8 -0
- irrep-3.2.0/irrep.egg-info/scm_version.json +0 -8
- {irrep-3.2.0 → irrep-3.3.0}/.github/workflows/python-publish.yml +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/.github/workflows/tests.yml +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/.gitignore +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/INSTALL +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/LICENSE +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/MANIFEST.in +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/README.md +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/__init__.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/cli.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/data/msg_numbers.data +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/ebrs.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/gvectors.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/or_solutions_obtainer.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/parsers/__init__.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/parsers/abinit.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/parsers/common.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/parsers/espresso.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/parsers/gpaw.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/parsers/parse_files_bandstructure.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/parsers/vasp.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/parsers/wannier90.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/spacegroup_irreps.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/__init__.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/conftest.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/ref_data/Fe_qe_dmn_TR=False.pkl +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/ref_data/Fe_qe_dmn_TR=False_irred.pkl +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/ref_data/Fe_qe_dmn_TR=True.pkl +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/ref_data/Fe_qe_dmn_TR=True_irred.pkl +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/ref_data/magmom_Fe_qe_dmn.txt +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/ref_data/spacegroup_Te_TR.npz +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/ref_data/spacegroup_Te_TR_product.npz +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/ref_data/spacegroup_Te_noTR.npz +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/ref_data/spacegroup_Te_noTR_product.npz +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/ref_data/symm_matrix_block.npz +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/ref_data/symm_matrix_full.npz +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_abinit_scalar.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_abinit_spinor.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_altermagnetic.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_dmn.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_ebr_decomposition.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_espresso_hdf5.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_espresso_spinor.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_espresso_spinpol.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_paw.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_refUC.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_symmetry_indicators.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_symsep.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_vasp_scalar.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_vasp_spinor.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_wannier_scalar.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep/tests/test_wannier_spinor.py +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep.egg-info/dependency_links.txt +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep.egg-info/entry_points.txt +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep.egg-info/requires.txt +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/irrep.egg-info/top_level.txt +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/pyproject.toml +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/setup.cfg +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi/POSCAR +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi/README.md +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi/WAVECAR +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi/images/bands.png +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi/images/checktopomat.png +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi/inputs_maxK/INCAR +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi/inputs_maxK/KPOINTS +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi/inputs_maxK/POSCAR +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi/inputs_maxK/POTCAR +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi/inputs_scf/INCAR +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi/inputs_scf/KPOINTS +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi/inputs_scf/POSCAR +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi/inputs_scf/POTCAR +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/README.md +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/images/bands.png +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/images/checktopomat.png +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/inputs/Bi.txt +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/inputs/Se.txt +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/inputs/bands.in +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/inputs/nscf_IrRep.in +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/inputs/pp.bands.in +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/inputs/scf.in +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/out/Bi2Se3.save/charge-density.dat +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/out/Bi2Se3.save/data-file-schema.xml +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/out/Bi2Se3.save/paw.txt +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/out/Bi2Se3.save/wfc1.dat +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/out/Bi2Se3.save/wfc2.dat +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/out/Bi2Se3.save/wfc3.dat +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/out/Bi2Se3.save/wfc4.dat +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/Bi2Se3/out/Bi2Se3.xml +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/SnTe/README.md +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/SnTe/images/bands.png +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/SnTe/images/checktopomat.png +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/SnTe/images/refUC.png +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/SnTe/inputs/Sn.xml +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/SnTe/inputs/Te.xml +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/SnTe/inputs/parameters.in +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/tutorial/SnTe/maxK_WFK +0 -0
- {irrep-3.2.0 → irrep-3.3.0}/uploadpypi.sh +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: irrep
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: A tool to get symmetry proberties of ab-initio wavefunctions, irreduible representations and more.
|
|
5
5
|
Author-email: "Stepan S. Tsirkin" <stepan.tsirkin@ehu.eus>
|
|
6
6
|
License: GNU General Public License v3 (GPLv3)
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '3.
|
|
22
|
-
__version_tuple__ = version_tuple = (3,
|
|
21
|
+
__version__ = version = '3.3.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (3, 3, 0)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g4f43f138d'
|
|
@@ -42,27 +42,29 @@ class AltermagneticTransformer:
|
|
|
42
42
|
raise RuntimeError(f"No corresponding k-point found for R({kpt_red})={kpt_red_before_transform} out of \n{symmetrizer_up.kpoints_all} under the altermagnetic symmetry operation.")
|
|
43
43
|
|
|
44
44
|
@classmethod
|
|
45
|
-
def from_gpaw(cls, calculator, symmetrizer_up, nskip_symmetries=0):
|
|
45
|
+
def from_gpaw(cls, calculator, symmetrizer_up, nskip_symmetries=0, tol_magmom=1e-4):
|
|
46
46
|
symop = find_altermagnetic_symmetry(lattice=calculator.atoms.cell,
|
|
47
47
|
positions=calculator.atoms.get_scaled_positions(),
|
|
48
48
|
typat=calculator.atoms.get_atomic_numbers(),
|
|
49
49
|
magmom=calculator.get_magnetic_moments(),
|
|
50
|
-
nskip=nskip_symmetries
|
|
50
|
+
nskip=nskip_symmetries,
|
|
51
|
+
tol=tol_magmom)
|
|
51
52
|
return cls(calculator, symmetrizer_up, rotation_latt=symop.rotation, translation_latt=symop.translation)
|
|
52
53
|
|
|
53
54
|
def get_kpoint_down(self, ikirr, kpoints_up):
|
|
54
55
|
ik_origin = self.alter_map[ikirr]
|
|
55
56
|
KPtransformed = kpoints_up[ik_origin].get_transformed_copy(
|
|
56
57
|
symmetry_operation=self.symmetry_operations[ikirr],
|
|
57
|
-
k_new=self.k_intermediate[ikirr])
|
|
58
|
+
k_new=self.k_intermediate[ikirr], store=False)
|
|
58
59
|
KPtransformed = KPtransformed.get_transformed_copy(
|
|
59
60
|
symmetry_operation=self.alter_symop,
|
|
60
|
-
k_new=kpoints_up[ikirr].k)
|
|
61
|
+
k_new=kpoints_up[ikirr].k, store=False)
|
|
61
62
|
# TODO : unify the transformations, using just their product
|
|
62
63
|
return KPtransformed
|
|
63
64
|
|
|
64
65
|
|
|
65
|
-
def find_altermagnetic_symmetry(lattice, positions, typat, magmom, nskip=0
|
|
66
|
+
def find_altermagnetic_symmetry(lattice, positions, typat, magmom, nskip=0,
|
|
67
|
+
all=False, tol=1e-4):
|
|
66
68
|
magmom = np.array(magmom)
|
|
67
69
|
assert magmom.ndim == 1, "Magnetic moments must be a 1D array."
|
|
68
70
|
positions = np.array(positions)
|
|
@@ -76,15 +78,22 @@ def find_altermagnetic_symmetry(lattice, positions, typat, magmom, nskip=0):
|
|
|
76
78
|
if nskip >= len(spacegroup_nomag.symmetries) // 2:
|
|
77
79
|
raise ValueError(f"nskip={nskip} is too large for the number of symmetries={len(spacegroup_nomag.symmetries)}.")
|
|
78
80
|
cnt = 0
|
|
81
|
+
if all:
|
|
82
|
+
symop_list = []
|
|
79
83
|
for symop in spacegroup_nomag.symmetries:
|
|
80
84
|
atommap, T = get_atom_map(symop, positions)
|
|
81
85
|
# print (f"Checking symmetry operation: {symop}, {atommap=}, {T=}")
|
|
82
86
|
assert np.all(typat[atommap] == typat), "Atom types must match under symmetry operation."
|
|
83
87
|
magmom_transformed = magmom[atommap]
|
|
84
|
-
print(f"{magmom_transformed=}, {atommap=},")
|
|
85
|
-
if np.allclose(magmom_transformed, -magmom):
|
|
88
|
+
print(f"{magmom_transformed=}, {atommap=}, m-transformed={magmom_transformed + magmom}")
|
|
89
|
+
if np.allclose(magmom_transformed, -magmom, atol=tol):
|
|
86
90
|
cnt += 1
|
|
87
91
|
if cnt > nskip:
|
|
88
|
-
|
|
92
|
+
if all:
|
|
93
|
+
symop_list.append(symop)
|
|
94
|
+
else:
|
|
95
|
+
return symop
|
|
96
|
+
if all:
|
|
97
|
+
return symop_list
|
|
89
98
|
else:
|
|
90
99
|
raise ValueError("No altermagnetic symmetry operation found for the given magnetic moments.")
|
|
@@ -29,7 +29,7 @@ from .spacegroup import SpaceGroup
|
|
|
29
29
|
from .spacegroup_irreps import SpaceGroupIrreps
|
|
30
30
|
from .gvectors import sortIG, calc_gvectors
|
|
31
31
|
from .utility import get_block_indices, get_mapping_irr, grid_from_kpoints, log_message, UniqueListMod1, restore_full_grid, select_irreducible
|
|
32
|
-
|
|
32
|
+
from .storage import DummyStorage
|
|
33
33
|
try:
|
|
34
34
|
from irreptables.ebrs import load_ebr_data
|
|
35
35
|
except ImportError:
|
|
@@ -181,9 +181,10 @@ class BandStructure:
|
|
|
181
181
|
efermi=0.0,
|
|
182
182
|
Ecut=None,
|
|
183
183
|
kwargs_kpoint=None,
|
|
184
|
+
storage=None,
|
|
184
185
|
**kwargs_parser):
|
|
185
186
|
if len(kwargs_parser) > 0:
|
|
186
|
-
raise ValueError(f"the following kwargs are not recognized by BandStructure-__init__(): {list(kwargs_parser.keys())}, please use BandStructure.from_???() class methods to parse files instead of calling BandStructure.__init__() directly.")
|
|
187
|
+
raise ValueError(f"the following kwargs are not recognized by BandStructure-__init__(): {list(kwargs_parser.keys())}, \n If you meant the old API, please use BandStructure.from_???() class methods to parse files instead of calling BandStructure.__init__() directly.")
|
|
187
188
|
self.kpoints = kpoints
|
|
188
189
|
if kpoints_paw is not None:
|
|
189
190
|
self.kpoints_paw = kpoints_paw
|
|
@@ -193,6 +194,9 @@ class BandStructure:
|
|
|
193
194
|
self.efermi = efermi
|
|
194
195
|
self.Ecut = Ecut
|
|
195
196
|
self.kwargs_kpoint = kwargs_kpoint
|
|
197
|
+
if storage is None:
|
|
198
|
+
storage = DummyStorage()
|
|
199
|
+
self.storage = storage
|
|
196
200
|
self.kpoint_getter = kpoint_getter
|
|
197
201
|
self.kpoint_getter_paw = kpoint_getter_paw
|
|
198
202
|
self.kplist = kplist
|
|
@@ -525,6 +529,8 @@ class BandStructure:
|
|
|
525
529
|
spacegroup=None,
|
|
526
530
|
read_kpoints=True,
|
|
527
531
|
read_paw=False,
|
|
532
|
+
store_paw=True,
|
|
533
|
+
storage="tmp_irrep_storage",
|
|
528
534
|
**kwargs
|
|
529
535
|
):
|
|
530
536
|
|
|
@@ -542,6 +548,13 @@ class BandStructure:
|
|
|
542
548
|
verbosity=verbosity
|
|
543
549
|
)
|
|
544
550
|
if read_paw:
|
|
551
|
+
if isinstance(storage, str):
|
|
552
|
+
if store_paw:
|
|
553
|
+
from .storage import Storage
|
|
554
|
+
storage = Storage(storage)
|
|
555
|
+
else:
|
|
556
|
+
from .storage import DummyStorage
|
|
557
|
+
storage = DummyStorage()
|
|
545
558
|
spacegroup.set_gpaw(calculator=parser.calculator)
|
|
546
559
|
from irrep.kpoint_gpaw import OverlapPAW
|
|
547
560
|
overlap_paw = OverlapPAW(calc=parser.calculator)
|
|
@@ -574,7 +587,8 @@ class BandStructure:
|
|
|
574
587
|
from irrep.kpoint_gpaw import KpointGPAW
|
|
575
588
|
kp_gpaw = KpointGPAW.from_gpaw(calc=calculator_gpaw, ibz_index=ik, ispin=spin_channel,
|
|
576
589
|
RecLattice=spacegroup.reciprocal_lattice,
|
|
577
|
-
IBstart=IBstart, IBend=IBend
|
|
590
|
+
IBstart=IBstart, IBend=IBend,
|
|
591
|
+
storage=storage)
|
|
578
592
|
return kp_gpaw
|
|
579
593
|
else:
|
|
580
594
|
get_kpoint_paw = None
|
|
@@ -582,7 +596,8 @@ class BandStructure:
|
|
|
582
596
|
bandstr = cls(kplist=kplist_noskip, spacegroup=spacegroup, Ecut=Ecut, mp_grid=mp_grid, efermi=efermi,
|
|
583
597
|
overlap_paw=overlap_paw if read_paw else None,
|
|
584
598
|
kpoint_getter_paw=get_kpoint_paw,
|
|
585
|
-
kpoint_getter=get_kpoint
|
|
599
|
+
kpoint_getter=get_kpoint,
|
|
600
|
+
storage=storage)
|
|
586
601
|
if read_kpoints:
|
|
587
602
|
bandstr.read_all_kpoints()
|
|
588
603
|
if read_paw:
|
|
@@ -751,7 +751,7 @@ class Kpoint(KpointAbstract):
|
|
|
751
751
|
|
|
752
752
|
|
|
753
753
|
|
|
754
|
-
def get_transformed_copy(self, symmetry_operation, k_new=None):
|
|
754
|
+
def get_transformed_copy(self, symmetry_operation, k_new=None, store=False):
|
|
755
755
|
"""
|
|
756
756
|
Get a copy of the k-point transformed by a symmetry operation.
|
|
757
757
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import numpy as np
|
|
2
|
+
|
|
3
|
+
from irrep.storage import DummyStorage
|
|
2
4
|
from .kpoint import KpointAbstract
|
|
3
5
|
from .utility import cached_einsum
|
|
4
6
|
from .parsers import ParserGPAW
|
|
@@ -24,14 +26,15 @@ class KpointGPAW(KpointAbstract):
|
|
|
24
26
|
RecLattice=None,
|
|
25
27
|
atom_positions=None):
|
|
26
28
|
super().__init__(kpt=kpt, num_bands=nbands, RecLattice=RecLattice)
|
|
27
|
-
self.
|
|
29
|
+
self._wavefunction = wavefunction
|
|
28
30
|
self.proj = proj
|
|
29
31
|
self.nbands = nbands
|
|
30
32
|
self.atom_positions = atom_positions
|
|
31
33
|
|
|
32
34
|
@classmethod
|
|
33
35
|
def from_gpaw(self, calc, ibz_index, ispin, RecLattice,
|
|
34
|
-
IBstart, IBend
|
|
36
|
+
IBstart, IBend,
|
|
37
|
+
storage
|
|
35
38
|
):
|
|
36
39
|
ispin = ParserGPAW.spin_channels[ispin]
|
|
37
40
|
kpt = calc.wfs.kpt_qs[ibz_index][ispin]
|
|
@@ -46,13 +49,16 @@ class KpointGPAW(KpointAbstract):
|
|
|
46
49
|
|
|
47
50
|
wavefunction = np.array([calc.wfs.get_wave_function_array(n, ibz_index, ispin, periodic=True)
|
|
48
51
|
for n in range(IBstart, IBend)])
|
|
52
|
+
wavefunction = storage.store_array(wavefunction)
|
|
53
|
+
|
|
49
54
|
return KpointGPAW(kpt=k, wavefunction=wavefunction, proj=proj, nbands=nbands,
|
|
50
55
|
RecLattice=RecLattice,
|
|
51
56
|
atom_positions=atom_positions)
|
|
52
57
|
|
|
58
|
+
def get_wavefunction(self):
|
|
59
|
+
return self._wavefunction.get()
|
|
53
60
|
|
|
54
|
-
|
|
55
|
-
def get_transformed_copy(self, symmetry_operation, k_new):
|
|
61
|
+
def get_transformed_copy(self, symmetry_operation, k_new, store=False):
|
|
56
62
|
"""Get a transformed copy of the KpointGPAW object according to the given symmetry operation.
|
|
57
63
|
|
|
58
64
|
Args:
|
|
@@ -62,10 +68,16 @@ class KpointGPAW(KpointAbstract):
|
|
|
62
68
|
Returns:
|
|
63
69
|
KpointGPAW: Transformed copy of the KpointGPAW object.
|
|
64
70
|
"""
|
|
65
|
-
new_wavefunction = symmetry_operation.rotate_pseudo_wavefunction(psi_n_grid=self.
|
|
71
|
+
new_wavefunction = symmetry_operation.rotate_pseudo_wavefunction(psi_n_grid=self.get_wavefunction(), k_origin=self.k, k_target=k_new)
|
|
66
72
|
new_proj = symmetry_operation.rotate_projection(self.proj, self.k, k_new)
|
|
73
|
+
if store:
|
|
74
|
+
storage = self._wavefunction.storage
|
|
75
|
+
else:
|
|
76
|
+
storage = DummyStorage()
|
|
77
|
+
new_wavefunction = storage.store_array(new_wavefunction)
|
|
67
78
|
return KpointGPAW(kpt=k_new, wavefunction=new_wavefunction, proj=new_proj, nbands=self.nbands,
|
|
68
|
-
RecLattice=self.RecLattice, atom_positions=self.atom_positions
|
|
79
|
+
RecLattice=self.RecLattice, atom_positions=self.atom_positions,
|
|
80
|
+
)
|
|
69
81
|
|
|
70
82
|
|
|
71
83
|
class OverlapPAW:
|
|
@@ -96,9 +108,9 @@ class OverlapPAW:
|
|
|
96
108
|
include_pseudo=True,
|
|
97
109
|
bk=None,
|
|
98
110
|
):
|
|
99
|
-
wf1 = KP1.
|
|
111
|
+
wf1 = KP1.get_wavefunction()
|
|
100
112
|
proj1 = KP1.proj
|
|
101
|
-
wf2 = KP2.
|
|
113
|
+
wf2 = KP2.get_wavefunction()
|
|
102
114
|
proj2 = KP2.proj
|
|
103
115
|
assert wf1.ndim == 4
|
|
104
116
|
assert wf2.ndim == 4
|
|
@@ -24,7 +24,7 @@ import spglib
|
|
|
24
24
|
from irrep.parsers import ParserAbinit, ParserEspresso, ParserVasp, ParserW90
|
|
25
25
|
|
|
26
26
|
from .symmetry_operation import SymmetryOperation
|
|
27
|
-
from .utility import BOHR, group_numbers, log_message, select_irreducible
|
|
27
|
+
from .utility import BOHR, clean_np_load, group_numbers, log_message, select_irreducible
|
|
28
28
|
from packaging import version
|
|
29
29
|
import os
|
|
30
30
|
|
|
@@ -226,6 +226,27 @@ class SpaceGroup:
|
|
|
226
226
|
dic[key] = val
|
|
227
227
|
return dic
|
|
228
228
|
|
|
229
|
+
@classmethod
|
|
230
|
+
def from_dict(cls, dic):
|
|
231
|
+
"""
|
|
232
|
+
Create a SpaceGroup object from a dictionary.
|
|
233
|
+
"""
|
|
234
|
+
dic_clean = clean_np_load(dic)
|
|
235
|
+
return cls(**dic_clean)
|
|
236
|
+
|
|
237
|
+
@classmethod
|
|
238
|
+
def from_npz(cls, file_path):
|
|
239
|
+
"""
|
|
240
|
+
Create a SpaceGroup object from a .npz file.
|
|
241
|
+
"""
|
|
242
|
+
return cls.from_dict(np.load(file_path, allow_pickle=True))
|
|
243
|
+
|
|
244
|
+
def to_npz(self, file_path):
|
|
245
|
+
"""
|
|
246
|
+
Save the SpaceGroup object to a .npz file.
|
|
247
|
+
"""
|
|
248
|
+
np.savez(file_path, **self.as_dict())
|
|
249
|
+
|
|
229
250
|
@property
|
|
230
251
|
def size(self):
|
|
231
252
|
"""
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import numpy as np
|
|
3
|
+
from warnings import warn
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Storage:
|
|
7
|
+
|
|
8
|
+
def __init__(self, path):
|
|
9
|
+
self.path = path
|
|
10
|
+
os.makedirs(path, exist_ok=True)
|
|
11
|
+
self.files = os.listdir(path)
|
|
12
|
+
|
|
13
|
+
def generate_name(self, name=None):
|
|
14
|
+
"""generates a unique name for storing an array"""
|
|
15
|
+
if name is None:
|
|
16
|
+
name = "array"
|
|
17
|
+
existing_files = set(self.files)
|
|
18
|
+
i = 0
|
|
19
|
+
while True:
|
|
20
|
+
name_loc = f"{name}{f"_{i}" if i > 0 else ''}.npy"
|
|
21
|
+
if name_loc not in existing_files:
|
|
22
|
+
return name_loc
|
|
23
|
+
i += 1
|
|
24
|
+
|
|
25
|
+
def store_array(self, array, name=None, ignore_existing=False):
|
|
26
|
+
name = self.generate_name(name)
|
|
27
|
+
if os.name in self.files and not ignore_existing:
|
|
28
|
+
warn(f"File {name} already exists in storage {self.path}. Overwriting.")
|
|
29
|
+
path = os.path.join(self.path, name)
|
|
30
|
+
np.save(path, array)
|
|
31
|
+
self.files.append(name)
|
|
32
|
+
return StoredArray(name=name, storage=self)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_array(self, name):
|
|
36
|
+
if name not in self.files:
|
|
37
|
+
raise FileNotFoundError(f"File {name} not found in storage {self.path}.")
|
|
38
|
+
return np.load(os.path.join(self.path, name))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class DummyStorage(Storage):
|
|
42
|
+
|
|
43
|
+
def __init__(self, path=None):
|
|
44
|
+
self.arrays = {}
|
|
45
|
+
self.files = []
|
|
46
|
+
|
|
47
|
+
def store_array(self, array, name=None, ignore_existing=False):
|
|
48
|
+
if name is None:
|
|
49
|
+
name = f"array_{len(self.arrays)}"
|
|
50
|
+
if name in self.arrays and not ignore_existing:
|
|
51
|
+
warn(f"Array {name} already exists in storage. Overwriting.")
|
|
52
|
+
self.arrays[name] = array
|
|
53
|
+
self.files.append(name)
|
|
54
|
+
return StoredArray(name=name, storage=self)
|
|
55
|
+
|
|
56
|
+
def get_array(self, name):
|
|
57
|
+
if name not in self.arrays:
|
|
58
|
+
raise KeyError(f"Array {name} not found in storage.")
|
|
59
|
+
return self.arrays[name]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class StoredArray:
|
|
63
|
+
|
|
64
|
+
def __init__(self, name, storage):
|
|
65
|
+
self.name = name
|
|
66
|
+
self.storage = storage
|
|
67
|
+
|
|
68
|
+
def get(self):
|
|
69
|
+
return self.storage.get_array(self.name)
|
|
@@ -280,8 +280,11 @@ class SymmetryOperation():
|
|
|
280
280
|
|
|
281
281
|
@cached_property
|
|
282
282
|
def is_identity(self):
|
|
283
|
-
return
|
|
283
|
+
return self.is_identity_space and not self.time_reversal
|
|
284
284
|
|
|
285
|
+
@cached_property
|
|
286
|
+
def is_identity_space(self):
|
|
287
|
+
return np.allclose(self.rotation, np.eye(3)) and np.allclose(self.translation, 0)
|
|
285
288
|
|
|
286
289
|
def _get_operation_type(self):
|
|
287
290
|
"""
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import pickle
|
|
2
|
+
|
|
1
3
|
from gpaw import GPAW
|
|
2
4
|
import numpy as np
|
|
3
5
|
import pytest
|
|
@@ -66,3 +68,31 @@ def test_gpaw_spinorbit(spinor):
|
|
|
66
68
|
for k in irr:
|
|
67
69
|
if abs(irr[k]) > 1e-3:
|
|
68
70
|
assert k in irref, f"at energy {E}, extra irrep {k}({irr[k]}) found in calculated irreps {irr}, not in reference {irref}"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_gpaw_storage():
|
|
75
|
+
calc = GPAW(f"{TEST_FILES_PATH}/gpaw/Bi-gamma.gpw")
|
|
76
|
+
|
|
77
|
+
print("Fermi level", calc.get_fermi_level())
|
|
78
|
+
bandstructure = BandStructure.from_gpaw(calculator_gpaw=calc,
|
|
79
|
+
IBstart=10,
|
|
80
|
+
IBend=15,
|
|
81
|
+
Ecut=50,
|
|
82
|
+
degen_thresh=2e-4,
|
|
83
|
+
calculate_traces=True,
|
|
84
|
+
irreps=True,
|
|
85
|
+
read_paw=True,
|
|
86
|
+
search_cell=True,
|
|
87
|
+
store_paw=True,
|
|
88
|
+
kplist=[0])
|
|
89
|
+
output_file = f"{TEST_FILES_PATH}/gpaw/Bi-gamma_bandstructure_tmp.pickle"
|
|
90
|
+
bandstructure.pickle(output_file)
|
|
91
|
+
bandstructure2 = pickle.load(open(output_file, "rb"))
|
|
92
|
+
assert len(bandstructure.kpoints_paw) == len(bandstructure2.kpoints_paw), "Number of k-points in bandstructure and loaded bandstructure do not match."
|
|
93
|
+
assert len(bandstructure.kpoints) > 0, "No k-points found in bandstructure."
|
|
94
|
+
for kp1, kp2 in zip(bandstructure.kpoints_paw, bandstructure2.kpoints_paw):
|
|
95
|
+
assert np.allclose(kp1.get_wavefunction(), kp2.get_wavefunction()), f"Wavefunctions differ for k-point {kp1.k} and {kp2.k}"
|
|
96
|
+
assert np.allclose(kp1.proj, kp2.proj), f"Projections differ for k-point {kp1.k} and {kp2.k}"
|
|
97
|
+
bandstructure.spacegroup.show()
|
|
98
|
+
bandstructure.identify_irreps(kpnames=["GM"], verbosity=0)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from irrep.spacegroup import SpaceGroup
|
|
2
2
|
import numpy as np
|
|
3
|
+
import pytest
|
|
3
4
|
|
|
4
5
|
from irrep.tests.test_dmn import REF_FILES_PATH, TMP_FILES_PATH
|
|
5
6
|
|
|
@@ -167,7 +168,7 @@ def test_wyckoff_positions_2():
|
|
|
167
168
|
# checking correct parsing of the symbolic strings
|
|
168
169
|
assert MnTe_wyckoffs[4].split(',')[1] == '2.0*x'
|
|
169
170
|
return
|
|
170
|
-
|
|
171
|
+
|
|
171
172
|
|
|
172
173
|
def test_implicit_multiplication_parsing():
|
|
173
174
|
"""test lines 1060-1061 of spacegroup.py, which use parse_expr with implicit multiplication"""
|
|
@@ -176,3 +177,22 @@ def test_implicit_multiplication_parsing():
|
|
|
176
177
|
assert parse_expr('2x', transformations=_TRANSFORMS) == 2 * x
|
|
177
178
|
assert parse_expr('-2x+1', transformations=_TRANSFORMS) == -2 * x + 1
|
|
178
179
|
assert parse_expr('2x-y', transformations=_TRANSFORMS) == 2 * x - y
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
@pytest.mark.parametrize("include_TR", [True, False])
|
|
183
|
+
def test_spacegroup_save_load(include_TR):
|
|
184
|
+
spacegroup_Te = SpaceGroup.from_cell(**struct_param_Te,
|
|
185
|
+
include_TR=include_TR)
|
|
186
|
+
tmp_file_path = TMP_DATA_PATH / "spacegroup_Te_TR={}.npz".format(include_TR)
|
|
187
|
+
print(f"spinor : {spacegroup_Te.spinor}, include_TR: {include_TR}")
|
|
188
|
+
np.savez(tmp_file_path, **spacegroup_Te.as_dict())
|
|
189
|
+
spacegroup_Te_loaded = SpaceGroup.from_npz(tmp_file_path)
|
|
190
|
+
for key in spacegroup_Te.__dict__:
|
|
191
|
+
type_key = type(spacegroup_Te.__dict__[key])
|
|
192
|
+
assert type_key == type(spacegroup_Te_loaded.__dict__[key]), f"Type mismatch in attribute {key}, saved {type(getattr(spacegroup_Te, key))}, loaded {type(getattr(spacegroup_Te_loaded, key))}"
|
|
193
|
+
if key in ['real_lattice', 'positions', 'typat', 'magmom', 'number', 'number_str']:
|
|
194
|
+
if type_key == np.ndarray:
|
|
195
|
+
assert np.allclose(getattr(spacegroup_Te, key), getattr(spacegroup_Te_loaded, key)), f"Value mismatch in attribute {key}, saved {getattr(spacegroup_Te, key)}, loaded {getattr(spacegroup_Te_loaded, key)}"
|
|
196
|
+
else:
|
|
197
|
+
assert getattr(spacegroup_Te, key) == getattr(spacegroup_Te_loaded, key), f"Value mismatch in attribute {key}, saved {getattr(spacegroup_Te, key)}, loaded {getattr(spacegroup_Te_loaded, key)}"
|
|
198
|
+
assert spacegroup_Te.equals(spacegroup_Te_loaded), "Loaded spacegroup is not equal to the original"
|
|
@@ -798,3 +798,14 @@ class DummyMethodTables(DummyMethod):
|
|
|
798
798
|
message = f"{method_name} requires irreptables package to be installed. " \
|
|
799
799
|
f"Please install irreptables>=3.0.0 via pip: pip install irreptables"
|
|
800
800
|
super().__init__(message)
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
def clean_np_load(dict):
|
|
804
|
+
"""converts zero-dimensional np.ndarray to python scalars"""
|
|
805
|
+
dict_new = {}
|
|
806
|
+
for key, val in dict.items():
|
|
807
|
+
if isinstance(val, np.ndarray) and val.ndim == 0:
|
|
808
|
+
dict_new[key] = val.item()
|
|
809
|
+
else:
|
|
810
|
+
dict_new[key] = val
|
|
811
|
+
return dict_new
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: irrep
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: A tool to get symmetry proberties of ab-initio wavefunctions, irreduible representations and more.
|
|
5
5
|
Author-email: "Stepan S. Tsirkin" <stepan.tsirkin@ehu.eus>
|
|
6
6
|
License: GNU General Public License v3 (GPLv3)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|