TB2J 0.9.10.1__py3-none-any.whl → 0.9.12.17__py3-none-any.whl
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.
Potentially problematic release.
This version of TB2J might be problematic. Click here for more details.
- TB2J/.gitignore +5 -0
- TB2J/Jdownfolder.py +43 -19
- TB2J/MAEGreen.py +78 -60
- TB2J/__init__.py +3 -1
- TB2J/anisotropy.py +2 -2
- TB2J/basis.py +0 -3
- TB2J/contour.py +3 -2
- TB2J/exchange.py +335 -48
- TB2J/exchangeCL2.py +289 -51
- TB2J/exchange_params.py +25 -1
- TB2J/gpaw_wrapper.py +0 -3
- TB2J/green.py +58 -33
- TB2J/interfaces/wannier90_interface.py +4 -4
- TB2J/io_exchange/io_espins.py +276 -0
- TB2J/io_exchange/io_exchange.py +53 -12
- TB2J/io_exchange/io_txt.py +9 -8
- TB2J/io_exchange/io_uppasd.py +0 -1
- TB2J/io_exchange/io_vampire.py +3 -1
- TB2J/magnon/magnon3.py +76 -28
- TB2J/magnon/plot_magnon_dos_cli.py +115 -3
- TB2J/myTB.py +11 -11
- TB2J/pauli.py +32 -2
- TB2J/plot.py +8 -7
- TB2J/rotate_atoms.py +10 -7
- TB2J/scripts/TB2J_downfold.py +97 -0
- TB2J/scripts/TB2J_eigen.py +49 -0
- TB2J/scripts/TB2J_magnon.py +117 -0
- TB2J/scripts/TB2J_magnon2.py +78 -0
- TB2J/scripts/TB2J_magnon_dos.py +5 -0
- TB2J/scripts/TB2J_merge.py +49 -0
- TB2J/scripts/TB2J_plot_magnon_bands.py +22 -0
- TB2J/scripts/TB2J_rotate.py +29 -0
- TB2J/scripts/TB2J_rotateDM.py +21 -0
- TB2J/scripts/__init__.py +0 -0
- TB2J/scripts/abacus2J.py +61 -0
- TB2J/scripts/siesta2J.py +78 -0
- TB2J/scripts/wann2J.py +101 -0
- TB2J/spinham/hamiltonian.py +0 -1
- TB2J/symmetrize_J.py +2 -2
- TB2J/tensor_rotate.py +1 -2
- TB2J/versioninfo.py +3 -0
- TB2J/wannier/w90_tb_parser.py +0 -2
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/METADATA +7 -7
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/RECORD +48 -33
- tb2j-0.9.12.17.dist-info/entry_points.txt +15 -0
- tb2j-0.9.10.1.dist-info/entry_points.txt +0 -16
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/WHEEL +0 -0
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/licenses/LICENSE +0 -0
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/top_level.txt +0 -0
TB2J/magnon/magnon3.py
CHANGED
|
@@ -31,6 +31,7 @@ class MagnonParameters:
|
|
|
31
31
|
Q: Optional[List[float]] = None
|
|
32
32
|
uz_file: Optional[str] = None
|
|
33
33
|
n: Optional[List[float]] = None
|
|
34
|
+
spin_conf_file: Optional[str] = None
|
|
34
35
|
show: bool = False
|
|
35
36
|
|
|
36
37
|
@classmethod
|
|
@@ -57,6 +58,8 @@ class MagnonParameters:
|
|
|
57
58
|
# Convert path to absolute path if uz_file is relative to it
|
|
58
59
|
if self.uz_file and not Path(self.uz_file).is_absolute():
|
|
59
60
|
self.uz_file = str(Path(self.path) / self.uz_file)
|
|
61
|
+
if self.spin_conf_file and not Path(self.spin_conf_file).is_absolute():
|
|
62
|
+
self.spin_conf_file = str(Path(self.path) / self.spin_conf_file)
|
|
60
63
|
|
|
61
64
|
|
|
62
65
|
@dataclass
|
|
@@ -76,7 +79,7 @@ class Magnon:
|
|
|
76
79
|
_n: np.ndarray
|
|
77
80
|
pbc: tuple = (True, True, True)
|
|
78
81
|
|
|
79
|
-
def set_reference(self, Q, uz, n):
|
|
82
|
+
def set_reference(self, Q, uz, n, magmoms=None):
|
|
80
83
|
"""
|
|
81
84
|
Set reference propagation vector and quantization axis
|
|
82
85
|
|
|
@@ -92,6 +95,8 @@ class Magnon:
|
|
|
92
95
|
self.set_propagation_vector(Q)
|
|
93
96
|
self._uz = np.array(uz, dtype=float)
|
|
94
97
|
self._n = np.array(n, dtype=float)
|
|
98
|
+
if magmoms is not None:
|
|
99
|
+
self.magmom = np.array(magmoms, dtype=float)
|
|
95
100
|
|
|
96
101
|
def set_propagation_vector(self, Q):
|
|
97
102
|
"""Set propagation vector"""
|
|
@@ -653,26 +658,40 @@ def plot_magnon_bands_from_TB2J(
|
|
|
653
658
|
)
|
|
654
659
|
|
|
655
660
|
# Set reference vectors if provided
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
661
|
+
Q = [0, 0, 0] if params.Q is None else params.Q
|
|
662
|
+
n = [0, 0, 1] if params.n is None else params.n
|
|
663
|
+
|
|
664
|
+
# Handle quantization axes
|
|
665
|
+
if params.uz_file is not None:
|
|
666
|
+
uz = np.loadtxt(params.uz_file)
|
|
667
|
+
if uz.shape[1] != 3:
|
|
668
|
+
raise ValueError(
|
|
669
|
+
f"Quantization axes file should contain a natom×3 array. Got shape {uz.shape}"
|
|
670
|
+
)
|
|
671
|
+
if uz.shape[0] != magnon.nspin:
|
|
672
|
+
raise ValueError(
|
|
673
|
+
f"Number of spins in uz file ({uz.shape[0]}) does not match the system ({magnon.nspin})"
|
|
674
|
+
)
|
|
675
|
+
else:
|
|
676
|
+
# Default: [0, 0, 1] for all spins
|
|
677
|
+
# uz = np.array([[0.0, 0.0, 1.0] for _ in range(magnon.nspin)])
|
|
678
|
+
uz = np.array([[0, 0, 1]], dtype=float)
|
|
679
|
+
|
|
680
|
+
print(params)
|
|
681
|
+
if params.spin_conf_file is not None:
|
|
682
|
+
magmoms = np.loadtxt(params.spin_conf_file)
|
|
683
|
+
if magmoms.shape[1] != 3:
|
|
684
|
+
raise ValueError(
|
|
685
|
+
f"Spin configuration file should contain a nspin×3 array. Got shape {magmoms.shape}"
|
|
686
|
+
)
|
|
687
|
+
if magmoms.shape[0] != magnon.nspin:
|
|
688
|
+
raise ValueError(
|
|
689
|
+
f"Number of spins in spin configuration file ({magmoms.shape[0]}) does not match the system ({magnon.nspin})"
|
|
690
|
+
)
|
|
691
|
+
else:
|
|
692
|
+
magmoms = None
|
|
674
693
|
|
|
675
|
-
|
|
694
|
+
magnon.set_reference(Q, uz, n, magmoms)
|
|
676
695
|
|
|
677
696
|
# Get band structure data
|
|
678
697
|
print(f"\nCalculating bands along path {params.kpath}...")
|
|
@@ -714,10 +733,25 @@ def plot_magnon_bands_from_TB2J(
|
|
|
714
733
|
return magnon
|
|
715
734
|
|
|
716
735
|
|
|
717
|
-
def
|
|
718
|
-
"""Command line interface for plotting magnon bands from TB2J results."""
|
|
736
|
+
def plot_magnon_bands_cli():
|
|
719
737
|
import argparse
|
|
720
|
-
|
|
738
|
+
import warnings
|
|
739
|
+
|
|
740
|
+
warnings.warn(
|
|
741
|
+
"""
|
|
742
|
+
# !!!!!!!!!!!!!!!!!! WARNING: =============================
|
|
743
|
+
#
|
|
744
|
+
# This functionality is under development and should not be used in production.
|
|
745
|
+
# It is provided for testing and development purposes only.
|
|
746
|
+
# Please use with caution and report any issues to the developers.
|
|
747
|
+
#
|
|
748
|
+
# This warning will be removed in future releases.
|
|
749
|
+
# =====================================
|
|
750
|
+
|
|
751
|
+
""",
|
|
752
|
+
UserWarning,
|
|
753
|
+
stacklevel=2,
|
|
754
|
+
)
|
|
721
755
|
parser = argparse.ArgumentParser(
|
|
722
756
|
description="Plot magnon band structure from TB2J results"
|
|
723
757
|
)
|
|
@@ -737,27 +771,32 @@ def main():
|
|
|
737
771
|
|
|
738
772
|
# Command line arguments (used if no config file is provided)
|
|
739
773
|
parser.add_argument(
|
|
774
|
+
"-p",
|
|
740
775
|
"--path",
|
|
741
776
|
default="TB2J_results",
|
|
742
777
|
help="Path to TB2J results directory (default: TB2J_results)",
|
|
743
778
|
)
|
|
744
779
|
parser.add_argument(
|
|
780
|
+
"-k",
|
|
745
781
|
"--kpath",
|
|
746
782
|
default=None,
|
|
747
783
|
help="k-path specification (default: auto-detected from type of cell)",
|
|
748
784
|
)
|
|
749
785
|
parser.add_argument(
|
|
786
|
+
"-n",
|
|
750
787
|
"--npoints",
|
|
751
788
|
type=int,
|
|
752
789
|
default=300,
|
|
753
790
|
help="Number of k-points along the path (default: 300)",
|
|
754
791
|
)
|
|
755
792
|
parser.add_argument(
|
|
793
|
+
"-o",
|
|
756
794
|
"--output",
|
|
757
795
|
default="magnon_bands.png",
|
|
758
796
|
help="Output file name (default: magnon_bands.png)",
|
|
759
797
|
)
|
|
760
798
|
parser.add_argument(
|
|
799
|
+
"-j",
|
|
761
800
|
"--Jiso",
|
|
762
801
|
action="store_true",
|
|
763
802
|
default=True,
|
|
@@ -770,18 +809,21 @@ def main():
|
|
|
770
809
|
help="Exclude isotropic exchange interactions",
|
|
771
810
|
)
|
|
772
811
|
parser.add_argument(
|
|
812
|
+
"-a",
|
|
773
813
|
"--Jani",
|
|
774
814
|
action="store_true",
|
|
775
815
|
default=False,
|
|
776
816
|
help="Include anisotropic exchange interactions (default: False)",
|
|
777
817
|
)
|
|
778
818
|
parser.add_argument(
|
|
819
|
+
"-d",
|
|
779
820
|
"--DMI",
|
|
780
821
|
action="store_true",
|
|
781
822
|
default=False,
|
|
782
823
|
help="Include Dzyaloshinskii-Moriya interactions (default: False)",
|
|
783
824
|
)
|
|
784
825
|
parser.add_argument(
|
|
826
|
+
"-q",
|
|
785
827
|
"--Q",
|
|
786
828
|
nargs=3,
|
|
787
829
|
type=float,
|
|
@@ -789,11 +831,19 @@ def main():
|
|
|
789
831
|
help="Propagation vector [Qx, Qy, Qz] (default: [0, 0, 0])",
|
|
790
832
|
)
|
|
791
833
|
parser.add_argument(
|
|
834
|
+
"-u",
|
|
792
835
|
"--uz-file",
|
|
793
836
|
type=str,
|
|
794
|
-
help="Path to file containing quantization axes for each spin (
|
|
837
|
+
help="Path to file containing quantization axes for each spin (nspin×3 array)",
|
|
838
|
+
)
|
|
839
|
+
parser.add_argument(
|
|
840
|
+
"-c",
|
|
841
|
+
"--spin-conf-file",
|
|
842
|
+
type=str,
|
|
843
|
+
help="Path to file containing magnetic moments for each spin (nspin×3 array)",
|
|
795
844
|
)
|
|
796
845
|
parser.add_argument(
|
|
846
|
+
"-v",
|
|
797
847
|
"--n",
|
|
798
848
|
nargs=3,
|
|
799
849
|
type=float,
|
|
@@ -802,6 +852,7 @@ def main():
|
|
|
802
852
|
)
|
|
803
853
|
|
|
804
854
|
parser.add_argument(
|
|
855
|
+
"-s",
|
|
805
856
|
"--show",
|
|
806
857
|
action="store_true",
|
|
807
858
|
default=False,
|
|
@@ -833,6 +884,7 @@ def main():
|
|
|
833
884
|
DMI=args.DMI,
|
|
834
885
|
Q=args.Q if args.Q is not None else None,
|
|
835
886
|
uz_file=args.uz_file,
|
|
887
|
+
spin_conf_file=args.spin_conf_file,
|
|
836
888
|
n=args.n if args.n is not None else None,
|
|
837
889
|
show=args.show,
|
|
838
890
|
)
|
|
@@ -840,10 +892,6 @@ def main():
|
|
|
840
892
|
plot_magnon_bands_from_TB2J(params)
|
|
841
893
|
|
|
842
894
|
|
|
843
|
-
if __name__ == "__main__":
|
|
844
|
-
main()
|
|
845
|
-
|
|
846
|
-
|
|
847
895
|
class MagnonASEWrapper:
|
|
848
896
|
def __init__(self, magnon: Magnon):
|
|
849
897
|
self.magnon = magnon
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
import argparse
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
7
9
|
from TB2J.magnon.magnon3 import Magnon
|
|
8
10
|
from TB2J.magnon.magnon_dos import plot_magnon_dos
|
|
9
11
|
|
|
@@ -13,6 +15,7 @@ def main():
|
|
|
13
15
|
description="Calculate and plot magnon DOS from TB2J results"
|
|
14
16
|
)
|
|
15
17
|
parser.add_argument(
|
|
18
|
+
"-p",
|
|
16
19
|
"--path",
|
|
17
20
|
default="TB2J_results",
|
|
18
21
|
help="Path to TB2J results directory (default: TB2J_results)",
|
|
@@ -51,26 +54,135 @@ def main():
|
|
|
51
54
|
help="Number of energy points (default: 401)",
|
|
52
55
|
)
|
|
53
56
|
parser.add_argument(
|
|
57
|
+
"-o",
|
|
54
58
|
"--output",
|
|
55
59
|
default="magnon_dos.png",
|
|
56
60
|
help="Output filename for plot (default: magnon_dos.png)",
|
|
57
61
|
)
|
|
58
62
|
parser.add_argument(
|
|
59
|
-
"-
|
|
63
|
+
"-s",
|
|
64
|
+
"--show",
|
|
60
65
|
action="store_true",
|
|
61
66
|
dest="show",
|
|
62
67
|
help="Show plot window",
|
|
63
68
|
)
|
|
64
69
|
|
|
70
|
+
# Exchange interaction options (same as in magnon bands)
|
|
71
|
+
parser.add_argument(
|
|
72
|
+
"-j",
|
|
73
|
+
"--Jiso",
|
|
74
|
+
action="store_true",
|
|
75
|
+
default=True,
|
|
76
|
+
help="Include isotropic exchange interactions (default: True)",
|
|
77
|
+
)
|
|
78
|
+
parser.add_argument(
|
|
79
|
+
"--no-Jiso",
|
|
80
|
+
action="store_false",
|
|
81
|
+
dest="Jiso",
|
|
82
|
+
help="Exclude isotropic exchange interactions",
|
|
83
|
+
)
|
|
84
|
+
parser.add_argument(
|
|
85
|
+
"-a",
|
|
86
|
+
"--Jani",
|
|
87
|
+
action="store_true",
|
|
88
|
+
default=False,
|
|
89
|
+
help="Include anisotropic exchange interactions (default: False)",
|
|
90
|
+
)
|
|
91
|
+
parser.add_argument(
|
|
92
|
+
"-d",
|
|
93
|
+
"--DMI",
|
|
94
|
+
action="store_true",
|
|
95
|
+
default=False,
|
|
96
|
+
help="Include Dzyaloshinskii-Moriya interactions (default: False)",
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Reference vector options (same as in magnon bands)
|
|
100
|
+
parser.add_argument(
|
|
101
|
+
"-q",
|
|
102
|
+
"--Q",
|
|
103
|
+
nargs=3,
|
|
104
|
+
type=float,
|
|
105
|
+
metavar=("Qx", "Qy", "Qz"),
|
|
106
|
+
help="Propagation vector [Qx, Qy, Qz] (default: [0, 0, 0])",
|
|
107
|
+
)
|
|
108
|
+
parser.add_argument(
|
|
109
|
+
"-u",
|
|
110
|
+
"--uz-file",
|
|
111
|
+
type=str,
|
|
112
|
+
help="Path to file containing quantization axes for each spin (nspin×3 array)",
|
|
113
|
+
)
|
|
114
|
+
parser.add_argument(
|
|
115
|
+
"-c",
|
|
116
|
+
"--spin-conf-file",
|
|
117
|
+
type=str,
|
|
118
|
+
help="Path to file containing magnetic moments for each spin (nspin×3 array)",
|
|
119
|
+
)
|
|
120
|
+
parser.add_argument(
|
|
121
|
+
"-v",
|
|
122
|
+
"--n",
|
|
123
|
+
nargs=3,
|
|
124
|
+
type=float,
|
|
125
|
+
metavar=("nx", "ny", "nz"),
|
|
126
|
+
help="Normal vector for rotation [nx, ny, nz] (default: [0, 0, 1])",
|
|
127
|
+
)
|
|
128
|
+
|
|
65
129
|
args = parser.parse_args()
|
|
66
130
|
|
|
67
131
|
# Check if TB2J results exist
|
|
68
132
|
if not Path(args.path).exists():
|
|
69
133
|
raise FileNotFoundError(f"TB2J results not found at {args.path}")
|
|
70
134
|
|
|
71
|
-
# Load magnon calculator
|
|
135
|
+
# Load magnon calculator with exchange interaction options
|
|
72
136
|
print(f"Loading exchange parameters from {args.path}...")
|
|
73
|
-
magnon = Magnon.from_TB2J_results(
|
|
137
|
+
magnon = Magnon.from_TB2J_results(
|
|
138
|
+
path=args.path, Jiso=args.Jiso, Jani=args.Jani, DMI=args.DMI
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Set reference vectors if provided (same logic as in magnon bands)
|
|
142
|
+
Q = [0, 0, 0] if args.Q is None else args.Q
|
|
143
|
+
n = [0, 0, 1] if args.n is None else args.n
|
|
144
|
+
|
|
145
|
+
# Handle quantization axes
|
|
146
|
+
if args.uz_file is not None:
|
|
147
|
+
# Make path relative to TB2J results if not absolute
|
|
148
|
+
uz_file = args.uz_file
|
|
149
|
+
if not Path(uz_file).is_absolute():
|
|
150
|
+
uz_file = str(Path(args.path) / uz_file)
|
|
151
|
+
|
|
152
|
+
uz = np.loadtxt(uz_file)
|
|
153
|
+
if uz.shape[1] != 3:
|
|
154
|
+
raise ValueError(
|
|
155
|
+
f"Quantization axes file should contain a nspin×3 array. Got shape {uz.shape}"
|
|
156
|
+
)
|
|
157
|
+
if uz.shape[0] != magnon.nspin:
|
|
158
|
+
raise ValueError(
|
|
159
|
+
f"Number of spins in uz file ({uz.shape[0]}) does not match the system ({magnon.nspin})"
|
|
160
|
+
)
|
|
161
|
+
else:
|
|
162
|
+
# Default: [0, 0, 1] for all spins
|
|
163
|
+
uz = np.array([[0, 0, 1]], dtype=float)
|
|
164
|
+
|
|
165
|
+
# Handle spin configuration
|
|
166
|
+
if args.spin_conf_file is not None:
|
|
167
|
+
# Make path relative to TB2J results if not absolute
|
|
168
|
+
spin_conf_file = args.spin_conf_file
|
|
169
|
+
if not Path(spin_conf_file).is_absolute():
|
|
170
|
+
spin_conf_file = str(Path(args.path) / spin_conf_file)
|
|
171
|
+
|
|
172
|
+
magmoms = np.loadtxt(spin_conf_file)
|
|
173
|
+
if magmoms.shape[1] != 3:
|
|
174
|
+
raise ValueError(
|
|
175
|
+
f"Spin configuration file should contain a nspin×3 array. Got shape {magmoms.shape}"
|
|
176
|
+
)
|
|
177
|
+
if magmoms.shape[0] != magnon.nspin:
|
|
178
|
+
raise ValueError(
|
|
179
|
+
f"Number of spins in spin configuration file ({magmoms.shape[0]}) does not match the system ({magnon.nspin})"
|
|
180
|
+
)
|
|
181
|
+
else:
|
|
182
|
+
magmoms = None
|
|
183
|
+
|
|
184
|
+
# Set reference configuration
|
|
185
|
+
magnon.set_reference(Q, uz, n, magmoms)
|
|
74
186
|
|
|
75
187
|
# Convert window from meV to eV if provided
|
|
76
188
|
window = None
|
TB2J/myTB.py
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import numpy as np
|
|
3
1
|
import copy
|
|
4
|
-
|
|
5
|
-
from scipy.sparse import csr_matrix
|
|
6
|
-
from scipy.io import netcdf_file
|
|
2
|
+
import os
|
|
7
3
|
from collections import defaultdict
|
|
8
4
|
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
9
7
|
# from tbmodels import Model
|
|
10
8
|
from ase.atoms import Atoms
|
|
9
|
+
from scipy.io import netcdf_file
|
|
10
|
+
from scipy.linalg import eigh
|
|
11
|
+
from scipy.sparse import csr_matrix
|
|
12
|
+
|
|
11
13
|
from TB2J.utils import auto_assign_basis_name
|
|
12
|
-
from TB2J.wannier import
|
|
14
|
+
from TB2J.wannier import parse_atoms, parse_ham, parse_tb, parse_xyz
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
class AbstractTB:
|
|
@@ -187,9 +189,7 @@ class MyTB(AbstractTB):
|
|
|
187
189
|
if os.path.exists(tb_fname):
|
|
188
190
|
xcart, nbasis, data, R_degens = parse_tb(fname=tb_fname)
|
|
189
191
|
else:
|
|
190
|
-
nbasis, data, R_degens = parse_ham(
|
|
191
|
-
fname=os.path.join(path, prefix + "_hr.dat")
|
|
192
|
-
)
|
|
192
|
+
nbasis, data, R_degens = parse_ham(fname=hr_fname)
|
|
193
193
|
xcart, _, _ = parse_xyz(fname=os.path.join(path, prefix + "_centres.xyz"))
|
|
194
194
|
|
|
195
195
|
if atoms is None:
|
|
@@ -237,7 +237,7 @@ class MyTB(AbstractTB):
|
|
|
237
237
|
return m
|
|
238
238
|
|
|
239
239
|
def gen_ham(self, k, convention=2):
|
|
240
|
-
"""
|
|
240
|
+
r"""
|
|
241
241
|
generate hamiltonian matrix at k point.
|
|
242
242
|
H_k( i, j)=\sum_R H_R(i, j)^phase.
|
|
243
243
|
There are two conventions,
|
|
@@ -451,7 +451,7 @@ class MyTB(AbstractTB):
|
|
|
451
451
|
nbasis = root.dimensions["nbasis"]
|
|
452
452
|
nspin = root.dimensions["nspin"]
|
|
453
453
|
ndim = root.dimensions["ndim"]
|
|
454
|
-
|
|
454
|
+
_natom = root.dimensions["natom"]
|
|
455
455
|
Rlist = root.variables["R"][:]
|
|
456
456
|
mdata_real = root.variables["data_real"][:]
|
|
457
457
|
mdata_imag = root.variables["data_imag"][:]
|
TB2J/pauli.py
CHANGED
|
@@ -59,7 +59,7 @@ def pauli_decomp2(M):
|
|
|
59
59
|
)
|
|
60
60
|
|
|
61
61
|
|
|
62
|
-
def
|
|
62
|
+
def pauli_sigma_norm_old(M):
|
|
63
63
|
MI, Mx, My, Mz = pauli_decomp2(M)
|
|
64
64
|
return np.linalg.norm([Mx, My, Mz])
|
|
65
65
|
|
|
@@ -134,7 +134,7 @@ def pauli_block(M, idim):
|
|
|
134
134
|
return tmp
|
|
135
135
|
|
|
136
136
|
|
|
137
|
-
def
|
|
137
|
+
def pauli_block_all_old(M):
|
|
138
138
|
MI = (M[::2, ::2] + M[1::2, 1::2]) / 2.0
|
|
139
139
|
Mx = (M[::2, 1::2] + M[1::2, ::2]) / 2.0
|
|
140
140
|
# Note that this is not element wise product with sigma_y but dot product
|
|
@@ -143,6 +143,28 @@ def pauli_block_all(M):
|
|
|
143
143
|
return MI, Mx, My, Mz
|
|
144
144
|
|
|
145
145
|
|
|
146
|
+
def pauli_block_all(array):
|
|
147
|
+
A00 = array[..., ::2, ::2]
|
|
148
|
+
A01 = array[..., ::2, 1::2]
|
|
149
|
+
A10 = array[..., 1::2, ::2]
|
|
150
|
+
A11 = array[..., 1::2, 1::2]
|
|
151
|
+
n2 = array.shape[-1] // 2
|
|
152
|
+
|
|
153
|
+
out_dtype = np.result_type(array.dtype, np.complex64)
|
|
154
|
+
block = np.empty((*array.shape[:-2], 4, n2, n2), dtype=out_dtype)
|
|
155
|
+
|
|
156
|
+
np.add(A00, A11, out=block[..., 0, :, :])
|
|
157
|
+
block[..., 0, :, :] *= 0.5
|
|
158
|
+
np.add(A01, A10, out=block[..., 1, :, :])
|
|
159
|
+
block[..., 1, :, :] *= 0.5
|
|
160
|
+
np.subtract(A01, A10, out=block[..., 2, :, :])
|
|
161
|
+
block[..., 2, :, :] *= 0.5j
|
|
162
|
+
np.subtract(A00, A11, out=block[..., 3, :, :])
|
|
163
|
+
block[..., 3, :, :] *= 0.5
|
|
164
|
+
|
|
165
|
+
return block
|
|
166
|
+
|
|
167
|
+
|
|
146
168
|
def gather_pauli_blocks(MI, Mx, My, Mz, coeffs=[1.0, 1.0, 1.0, 1.0]):
|
|
147
169
|
"""
|
|
148
170
|
Gather the I, x, y, z component of a matrix.
|
|
@@ -212,3 +234,11 @@ def pauli_block_sigma_norm(M):
|
|
|
212
234
|
evec = np.array((ex, ey, ez))
|
|
213
235
|
evec = evec / np.linalg.norm(evec)
|
|
214
236
|
return Mx * evec[0] + My * evec[1] + Mz * evec[2]
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def pauli_sigma_norm(array):
|
|
240
|
+
block = pauli_block_all(array)[..., 1:, :, :]
|
|
241
|
+
E = np.trace(block, axis1=-2, axis2=-1)
|
|
242
|
+
E /= np.linalg.norm(E, axis=-1, keepdims=True)
|
|
243
|
+
np.multiply(block, E[..., None, None], out=block)
|
|
244
|
+
return block.sum(axis=-3)
|
TB2J/plot.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import os
|
|
3
|
+
|
|
1
4
|
import matplotlib.pyplot as plt
|
|
2
|
-
from TB2J.spinham.spin_api import SpinModel
|
|
3
|
-
from TB2J.io_exchange.io_exchange import SpinIO
|
|
4
5
|
import numpy as np
|
|
5
|
-
|
|
6
|
+
|
|
7
|
+
from TB2J.io_exchange.io_exchange import SpinIO
|
|
6
8
|
from TB2J.spinham.qsolver import QSolverASEWrapper
|
|
7
|
-
import
|
|
8
|
-
import os
|
|
9
|
+
from TB2J.spinham.spin_api import SpinModel
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
def write_eigen(qmesh, gamma=True, path="./", output_fname="EigenJq.txt", **kwargs):
|
|
@@ -25,7 +26,7 @@ def plot_magnon_band(
|
|
|
25
26
|
Jq=False,
|
|
26
27
|
kpath_fname="exchange_kpth.txt",
|
|
27
28
|
ax=None,
|
|
28
|
-
**kwargs
|
|
29
|
+
**kwargs,
|
|
29
30
|
):
|
|
30
31
|
m = SpinModel(fname=fname, sc_matrix=None)
|
|
31
32
|
m.set_ham(**kwargs)
|
|
@@ -57,7 +58,7 @@ def plot_magnon_dos(
|
|
|
57
58
|
txt_filename="magnon_dos.txt",
|
|
58
59
|
Jq=False,
|
|
59
60
|
ax=None,
|
|
60
|
-
**kwargs
|
|
61
|
+
**kwargs,
|
|
61
62
|
):
|
|
62
63
|
ffname = os.path.join(path, "exchange.xml")
|
|
63
64
|
if not (os.path.exists(ffname) and os.path.isfile(ffname)):
|
TB2J/rotate_atoms.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
import copy
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
import numpy as np
|
|
5
|
-
from
|
|
5
|
+
from ase.io import read, write
|
|
6
|
+
from TB2J.tensor_rotate import Rzx, Rzy, Rzz
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def rotate_atom_xyz(atoms, noncollinear=False):
|
|
@@ -15,14 +16,16 @@ def rotate_atom_xyz(atoms, noncollinear=False):
|
|
|
15
16
|
will be generated.
|
|
16
17
|
"""
|
|
17
18
|
|
|
19
|
+
yield atoms
|
|
18
20
|
rotation_axes = [(1, 0, 0), (0, 1, 0)]
|
|
19
21
|
if noncollinear:
|
|
20
22
|
rotation_axes += [(1, 1, 0), (1, 0, 1), (0, 1, 1)]
|
|
21
|
-
|
|
23
|
+
|
|
22
24
|
for axis in rotation_axes:
|
|
23
25
|
rotated_atoms = copy.deepcopy(atoms)
|
|
24
26
|
rotated_atoms.rotate(90, axis, rotate_cell=True)
|
|
25
27
|
yield rotated_atoms
|
|
28
|
+
yield atoms
|
|
26
29
|
|
|
27
30
|
|
|
28
31
|
def rotate_atom_spin_one_rotation(atoms, Rotation):
|
|
@@ -109,7 +112,7 @@ def rotate_xyz(fname, ftype="xyz", noncollinear=False):
|
|
|
109
112
|
rotated = rotate_atom_xyz(atoms, noncollinear=noncollinear)
|
|
110
113
|
|
|
111
114
|
for i, rotated_atoms in enumerate(rotated):
|
|
112
|
-
write(f"atoms_{i
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
115
|
+
write(f"atoms_{i}.{ftype}", rotated_atoms)
|
|
116
|
+
print(
|
|
117
|
+
f"The output has been written to the atoms_i.{ftype} files. atoms_0.{ftype} contains the reference structure."
|
|
118
|
+
)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import argparse
|
|
3
|
+
|
|
4
|
+
from TB2J.Jdownfolder import JDownfolder_pickle
|
|
5
|
+
from TB2J.versioninfo import print_license
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main():
|
|
9
|
+
parser = argparse.ArgumentParser(
|
|
10
|
+
description="TB2J_downfold: Downfold the exchange parameter with ligand spin as independent variable to that only with metal site spin as independent variables."
|
|
11
|
+
)
|
|
12
|
+
parser.add_argument(
|
|
13
|
+
"--inpath",
|
|
14
|
+
"-i",
|
|
15
|
+
type=str,
|
|
16
|
+
help="The path of the input TB2J results before the downfolding.",
|
|
17
|
+
default="TB2J_results",
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
parser.add_argument(
|
|
21
|
+
"--outpath",
|
|
22
|
+
"-o",
|
|
23
|
+
type=str,
|
|
24
|
+
help="The path of the output TB2J results path after the downfolding",
|
|
25
|
+
default="TB2J_results_downfolded",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
parser.add_argument(
|
|
29
|
+
"--metals",
|
|
30
|
+
"-m",
|
|
31
|
+
type=str,
|
|
32
|
+
help="List of magnetic cation elements",
|
|
33
|
+
nargs="+",
|
|
34
|
+
default=[],
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
parser.add_argument(
|
|
38
|
+
"--ligands",
|
|
39
|
+
"-l",
|
|
40
|
+
type=str,
|
|
41
|
+
help="List of ligand elements",
|
|
42
|
+
nargs="+",
|
|
43
|
+
default=[],
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
parser.add_argument(
|
|
47
|
+
"--qmesh",
|
|
48
|
+
help="kmesh in the format of kx ky kz",
|
|
49
|
+
type=int,
|
|
50
|
+
nargs="*",
|
|
51
|
+
default=[5, 5, 5],
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
parser.add_argument(
|
|
55
|
+
"--iso_only",
|
|
56
|
+
help="whether to downfold only the isotropic part. The other parts will be neglected.",
|
|
57
|
+
action="store_true",
|
|
58
|
+
default=False,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
parser.add_argument(
|
|
62
|
+
"--method",
|
|
63
|
+
help="The method to downfold the exchange parameter. Options are Lowdin and PWF (projected Wannier function). ",
|
|
64
|
+
type=str,
|
|
65
|
+
default="Lowdin",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
args = parser.parse_args()
|
|
69
|
+
|
|
70
|
+
if len(args.metals) == []:
|
|
71
|
+
print("List of magnetic cation elements cannot be empty")
|
|
72
|
+
|
|
73
|
+
if len(args.ligands) == []:
|
|
74
|
+
print("List of ligand elements cannot be empty")
|
|
75
|
+
|
|
76
|
+
print_license()
|
|
77
|
+
print("Input path:", args.inpath)
|
|
78
|
+
print("Output path:", args.outpath)
|
|
79
|
+
print("Magnetic cation elements:", args.metals)
|
|
80
|
+
print("Ligand elements:", args.ligands)
|
|
81
|
+
print("k-mesh:", args.qmesh)
|
|
82
|
+
print("Downfolding method:", args.method)
|
|
83
|
+
print("Downfolding only isotropic part:", args.iso_only)
|
|
84
|
+
print("Begining downfolding the exchange parameters:")
|
|
85
|
+
JDownfolder_pickle(
|
|
86
|
+
inpath=args.inpath,
|
|
87
|
+
metals=args.metals,
|
|
88
|
+
ligands=args.ligands,
|
|
89
|
+
outpath=args.outpath,
|
|
90
|
+
qmesh=args.qmesh,
|
|
91
|
+
iso_only=args.iso_only,
|
|
92
|
+
method=args.method,
|
|
93
|
+
)
|
|
94
|
+
print("Downfolding finished. Results are saved in:", args.outpath)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
main()
|