TB2J 0.9.0__py3-none-any.whl → 0.9.0.1__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.
TB2J/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.9.0"
1
+ __version__ = "0.9.0.1"
TB2J/exchange.py CHANGED
@@ -345,7 +345,7 @@ class ExchangeNCL(Exchange):
345
345
  self.norb = self.G.norb
346
346
  self.nbasis = self.G.nbasis
347
347
  # self.rho = np.zeros((self.nbasis, self.nbasis), dtype=complex)
348
- self.rho = self.G.get_density_matrix().real
348
+ self.rho = self.G.get_density_matrix()
349
349
  self.A_ijR_list = defaultdict(lambda: [])
350
350
  self.A_ijR = defaultdict(lambda: np.zeros((4, 4), dtype=complex))
351
351
  self.A_ijR_orb = dict()
@@ -1,12 +1,10 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: TB2J
3
- Version: 0.9.0
3
+ Version: 0.9.0.1
4
4
  Summary: TB2J: First principle to Heisenberg exchange J using tight-binding Green function method
5
- Home-page: UNKNOWN
6
5
  Author: Xu He
7
6
  Author-email: mailhexu@gmail.com
8
7
  License: BSD-2-clause
9
- Platform: UNKNOWN
10
8
  Classifier: Development Status :: 3 - Alpha
11
9
  Classifier: Programming Language :: Python :: 3
12
10
  Classifier: Operating System :: OS Independent
@@ -16,14 +14,13 @@ Classifier: Topic :: Scientific/Engineering :: Physics
16
14
  Classifier: License :: OSI Approved :: BSD License
17
15
  Requires-Python: >=3.6
18
16
  License-File: LICENSE
19
- Requires-Dist: ase (>=3.19)
17
+ Requires-Dist: numpy >1.16.5
18
+ Requires-Dist: scipy
20
19
  Requires-Dist: matplotlib
21
- Requires-Dist: numpy (>1.16.5)
22
- Requires-Dist: packaging (>=20.0)
20
+ Requires-Dist: ase >=3.19
21
+ Requires-Dist: tqdm
23
22
  Requires-Dist: pathos
23
+ Requires-Dist: packaging >=20.0
24
24
  Requires-Dist: pre-commit
25
- Requires-Dist: scipy
26
- Requires-Dist: tqdm
27
25
 
28
26
  TB2J is a Python package aimed to compute automatically the magnetic interactions (superexchange and Dzyaloshinskii-Moriya) between atoms of magnetic crystals from DFT Hamiltonian based on Wannier functions or Linear combination of atomic orbitals. It uses the Green's function method and take the local rigid spin rotation as a perturbation. The package can take the output from Wannier90, which is interfaced with many density functional theory codes or from codes based on localised orbitals. A minimal user input is needed, which allows for an easily integration into a high-throughput workflows.
29
-
@@ -2,14 +2,13 @@ TB2J/Jdownfolder.py,sha256=Nw2ixvn2Uq-o1wficz6rdaYHjfRN3U_kQCvrNJGNb68,6980
2
2
  TB2J/Jtensor.py,sha256=0fhfOcfVQGu75gytEnApKWTJZfg9ksKJ0anJgco5wRQ,3179
3
3
  TB2J/Oiju.py,sha256=cNGv8N5uH_swGq7cnAt2OyiDfqtjLlLrwseGu0E4iaM,3383
4
4
  TB2J/Oiju_epc.py,sha256=oytM3NYW7nWmklrGgNlqwIpI_JYv_hb7ZnR4o9nYNog,6809
5
- TB2J/__init__.py,sha256=H9NWRZb7NbeRRPLP_V1fARmLNXranorVM-OOY-8_2ug,22
5
+ TB2J/__init__.py,sha256=hcEWkag_UvLm1ZSbjsgcTWkGVlR3Bwmzg1QYAwsvf-g,24
6
6
  TB2J/basis.py,sha256=DFo6_QUwjBwisP6zGxvoO0lpGTMDPAOkiL9giNCjOjA,1558
7
7
  TB2J/citation.py,sha256=gcQeyJZaT1Qrtsl8Y3s4neOH3-vvgmIcCvXeV2o3vj0,2891
8
8
  TB2J/contour.py,sha256=aw8LX6wVFCRPhcpkzuI0jGnHisvk4cezvUhkF_6Yx94,2633
9
- TB2J/cut_cell.py,sha256=kr9WeQhBQLm8QXL2B3NcsSYmSw-OAtJk3f9wksAOZbs,2952
10
9
  TB2J/density_matrix.py,sha256=D5k8Oe21OCiLVORNYbo4TZOFG0slrQSbj91kJ3TMFjs,1514
11
10
  TB2J/epc.py,sha256=zLbtqZJhDr8DnnGN6YENcXwrMb3Qxu6KB08mLy9Pw20,3474
12
- TB2J/exchange.py,sha256=Xg2fuUZbj-Icpqc65Ictllxvdvct8Ec4KQPAmEyo0oM,29586
11
+ TB2J/exchange.py,sha256=dsXQhlxXaBurxa7z3YkBjqmEFFtfEy1xaHf0VT3eKZE,29581
13
12
  TB2J/exchangeCL2.py,sha256=TIr-d2X56AiGe4qEhyXyZhRuwXvQG6clJMwDmjnTOaE,10985
14
13
  TB2J/exchange_pert.py,sha256=jmFMtQbYa_uczM4VAeS6TijkIHRFIqEzZJswzE9Wfuo,8523
15
14
  TB2J/exchange_qspace.py,sha256=ZL68qBGFUaQ9BsSPsJaaoWOr9RssPiqX34R_9I3nk_8,8436
@@ -28,7 +27,6 @@ TB2J/plot.py,sha256=AnFIFWE2vlmj7Z6f_7-dX_O1stJN-qbuiurPj43dUCM,4104
28
27
  TB2J/rotate_atoms.py,sha256=Dwptn-wdDW4zYzjYb95yxTzuZOe9WPuLjh3d3-YcSs0,3277
29
28
  TB2J/rotate_siestaDM.py,sha256=eR97rspdrRaK9YTwQwUKfobI0S9UnEcbEZ2f5IgR7Tk,1070
30
29
  TB2J/sisl_wrapper.py,sha256=A5x1-tt8efUSPeGY5wM5m6-pJYQFXTCzQHVqD6RBa2g,14792
31
- TB2J/supercell.py,sha256=4hgLGPBLRUDhtD-eF29v46ex7fHdkH-OENjS2wGLFww,19588
32
30
  TB2J/tensor_rotate.py,sha256=4-DfT_Mg5e40fbd74M5W0D5DqmUq-kVOOLDkkkI834A,8083
33
31
  TB2J/utest.py,sha256=z_ahi7tpHQF9WlHNQihcQ7qzfezRJQXQt28eB1X_z64,3897
34
32
  TB2J/utils.py,sha256=_ARYKAeWfP1p5w0mEl-d7KwNfXoqC85TveYl0iCBD3c,9880
@@ -46,7 +44,6 @@ TB2J/external/p_tqdm.py,sha256=ug1jy3-43r8iW7bC37xzPSIe0EjYKH_GUluGzMiQiDw,5831
46
44
  TB2J/io_exchange/__init__.py,sha256=KfGHum7B8E4G_KKfillqw0lErtoyKEuFUUttHLs-mg4,32
47
45
  TB2J/io_exchange/io_exchange.py,sha256=RxCZ7OOxhiIzGrIidCOqxNbgLsrHUfCqDVinMvrPdmI,19354
48
46
  TB2J/io_exchange/io_multibinit.py,sha256=8PDmWxzGuv-GwJosj2ZTmiyNY_duFVWJ4ekCuSqGdd8,6739
49
- TB2J/io_exchange/io_pickle.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
47
  TB2J/io_exchange/io_tomsasd.py,sha256=NqkAC1Fl-CUnFA21eBzSy_S5F_oeQFJysw4UukQbN8o,4173
51
48
  TB2J/io_exchange/io_txt.py,sha256=BMr1eSILlKpgtjvDx7uw2VMAkEKSvGEPNxpaT_zev0I,10547
52
49
  TB2J/io_exchange/io_uppasd.py,sha256=bI4iPEgnK4TvCZNvb6x2xYXgjW7pEehCqmcizy2pqFU,3301
@@ -54,10 +51,8 @@ TB2J/io_exchange/io_vampire.py,sha256=UllC4twf06_q2vBCnAYFzEDGvS8mSefwQXDquBuyc0
54
51
  TB2J/spinham/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
52
  TB2J/spinham/base_parser.py,sha256=oQRHvFE_BlUtTaTZykKgvicu40oXcbICB-D1aAt-qlA,2196
56
53
  TB2J/spinham/constants.py,sha256=y4-hRyl5EAR42k24Oa5XhAsUQtKVn1MAgyqNf-p3PrM,762
57
- TB2J/spinham/h_matrix.py,sha256=MfHIz6RViKkEB3Mu-WcwNx5uk7A5sjAlbqVG9wYA4xk,2784
58
54
  TB2J/spinham/hamiltonian.py,sha256=OfsjlGIgFwpXaohopZcgPamSfjm3X46_zc245eyTr_A,16607
59
55
  TB2J/spinham/hamiltonian_terms.py,sha256=7e84tfEjvAfZltUkrSWi1sUEiW_itLKy83lxi5iBpcQ,9714
60
- TB2J/spinham/obtain_J.py,sha256=sg8tiCRRLEN57Olb3MHIuqkDhAkmu-w87AkM00ylXtA,2401
61
56
  TB2J/spinham/plot.py,sha256=tLLNqFAATVrP1kmSVLPKzn686i-CUyqu4qgOcs-okHI,6599
62
57
  TB2J/spinham/qsolver.py,sha256=Sr9I3aGfVNYn5wzwPx1QonHe6ZZUXBAujWRa7nTA5u4,4986
63
58
  TB2J/spinham/spin_api.py,sha256=oN3AKg1WQl0YzR4f5ealcJOaVoAy8d7HodIwrbXvQeY,2219
@@ -66,18 +61,18 @@ TB2J/spinham/supercell.py,sha256=y17uUC6r3gQb278FhxIW4CABihfLTvKFj6flyXrCPR8,122
66
61
  TB2J/wannier/__init__.py,sha256=7ojCbM84PYv1X1Tbo4NHI-d3gWmQsZB_xiYqbfxVV1E,80
67
62
  TB2J/wannier/w90_parser.py,sha256=dbd63LuKyv2DVUzqRINGsbDzEsOxsQyE8_Ear_LQIRg,4620
68
63
  TB2J/wannier/w90_tb_parser.py,sha256=qt8pnuprmPp9iIAYwPkPbmEzk6ZPgMq2xognoQp7vwc,4610
69
- TB2J-0.9.0.data/scripts/TB2J_downfold.py,sha256=F9oImXFysejCMP7eIBjbCX2jdHFOCvDW5beF1sG-UM8,1854
70
- TB2J-0.9.0.data/scripts/TB2J_eigen.py,sha256=Qs9v2hnMm2Tpfoa4h53muUKty2dZjwx8948MBoQooNg,1128
71
- TB2J-0.9.0.data/scripts/TB2J_magnon.py,sha256=q7UwAmorRcFNk4tfE7gl_ny05l6p7pbD9Wm_LkIpKEw,3101
72
- TB2J-0.9.0.data/scripts/TB2J_magnon_dos.py,sha256=TMXQvD2dIbO5FZ4tUMmxJgCgH2O2hDAPUNfEKO4z-x4,110
73
- TB2J-0.9.0.data/scripts/TB2J_merge.py,sha256=y834SF4rIRn1L1ptkhczvavQpC-8Px6DTmDOOSaq_DE,1854
74
- TB2J-0.9.0.data/scripts/TB2J_rotate.py,sha256=zgiDFuYZNmzKK0rwDmTaYD2OpRlmKA_VGeBx83w2Xwc,873
75
- TB2J-0.9.0.data/scripts/TB2J_rotateDM.py,sha256=kCvF7gotuqAX1VnJ06cwfVm7RrhrdtiV5v7d9P2Pn_E,567
76
- TB2J-0.9.0.data/scripts/abacus2J.py,sha256=M4B07lvTCDczTPTqvnDh_PERzCARAd09TLKv4aIdSQM,4408
77
- TB2J-0.9.0.data/scripts/siesta2J.py,sha256=hBzS7ZgoHM3oXlTCQd-xVA07Ks2FiIwyRpQWUFITRPE,4303
78
- TB2J-0.9.0.data/scripts/wann2J.py,sha256=2t2hWwyELskYCwkGDziCgiIAnfr6odLLJ6cQBJ2RQwQ,5714
79
- TB2J-0.9.0.dist-info/LICENSE,sha256=CbZI-jyRTjiqIcWa244cRSHJdjjtUNqGR4HeJkgEwJw,1332
80
- TB2J-0.9.0.dist-info/METADATA,sha256=4ooTIlcMyCl-axTuL5PI9qfK4i7k5zFEoHFl-CiYXOc,1462
81
- TB2J-0.9.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
82
- TB2J-0.9.0.dist-info/top_level.txt,sha256=whYa5ByLYhl5XnTPBHSWr-IGD6VWmr5Ql2bye2qwV_s,5
83
- TB2J-0.9.0.dist-info/RECORD,,
64
+ TB2J-0.9.0.1.data/scripts/TB2J_downfold.py,sha256=F9oImXFysejCMP7eIBjbCX2jdHFOCvDW5beF1sG-UM8,1854
65
+ TB2J-0.9.0.1.data/scripts/TB2J_eigen.py,sha256=Qs9v2hnMm2Tpfoa4h53muUKty2dZjwx8948MBoQooNg,1128
66
+ TB2J-0.9.0.1.data/scripts/TB2J_magnon.py,sha256=q7UwAmorRcFNk4tfE7gl_ny05l6p7pbD9Wm_LkIpKEw,3101
67
+ TB2J-0.9.0.1.data/scripts/TB2J_magnon_dos.py,sha256=TMXQvD2dIbO5FZ4tUMmxJgCgH2O2hDAPUNfEKO4z-x4,110
68
+ TB2J-0.9.0.1.data/scripts/TB2J_merge.py,sha256=y834SF4rIRn1L1ptkhczvavQpC-8Px6DTmDOOSaq_DE,1854
69
+ TB2J-0.9.0.1.data/scripts/TB2J_rotate.py,sha256=zgiDFuYZNmzKK0rwDmTaYD2OpRlmKA_VGeBx83w2Xwc,873
70
+ TB2J-0.9.0.1.data/scripts/TB2J_rotateDM.py,sha256=kCvF7gotuqAX1VnJ06cwfVm7RrhrdtiV5v7d9P2Pn_E,567
71
+ TB2J-0.9.0.1.data/scripts/abacus2J.py,sha256=M4B07lvTCDczTPTqvnDh_PERzCARAd09TLKv4aIdSQM,4408
72
+ TB2J-0.9.0.1.data/scripts/siesta2J.py,sha256=hBzS7ZgoHM3oXlTCQd-xVA07Ks2FiIwyRpQWUFITRPE,4303
73
+ TB2J-0.9.0.1.data/scripts/wann2J.py,sha256=2t2hWwyELskYCwkGDziCgiIAnfr6odLLJ6cQBJ2RQwQ,5714
74
+ TB2J-0.9.0.1.dist-info/LICENSE,sha256=CbZI-jyRTjiqIcWa244cRSHJdjjtUNqGR4HeJkgEwJw,1332
75
+ TB2J-0.9.0.1.dist-info/METADATA,sha256=ky_ng24tVY8IC_GQn9420M7jzPnCpUiNcp-QtFkUbsk,1420
76
+ TB2J-0.9.0.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
77
+ TB2J-0.9.0.1.dist-info/top_level.txt,sha256=whYa5ByLYhl5XnTPBHSWr-IGD6VWmr5Ql2bye2qwV_s,5
78
+ TB2J-0.9.0.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: bdist_wheel (0.42.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
TB2J/cut_cell.py DELETED
@@ -1,82 +0,0 @@
1
- import numpy as np
2
- from TB2J.supercell import find_primitive_cell, map_to_primitive
3
- from TB2J.io_exchange.io_exchange import SpinIO, gen_distance_dict
4
-
5
-
6
- def cut_cell(path, output_path, sc_matrix, origin_atom_id, thr=1e-5):
7
- """
8
- Cut the exchange parameters
9
- :param path: the original TB2J_results path
10
- :param output_path: the output path.
11
- :param sc_matrix: the matrix which maps the primitive cell to supercell.
12
- :param origin: the origin of the primitive cell.
13
- :param thr: the atoms which the reduced position is within -thr to 1.0+thr are considered as inside the primitive atoms
14
- :returns:
15
- """
16
- sc_matrix = np.asarray(sc_matrix, dtype=int)
17
- sc_excparams = SpinIO.load_pickle(path=path, fname='TB2J.pickle')
18
- sc_atoms = sc_excparams.atoms
19
- uc_atoms, ids = find_primitive_cell(sc_atoms,
20
- sc_matrix,
21
- origin_atom_id=origin_atom_id,
22
- thr=thr,
23
- perfect=False)
24
- uc_charges = sc_excparams.charges[ids]
25
- uc_spinat = sc_excparams.spinat[ids]
26
- indmap, Rmap = map_to_primitive(sc_atoms, uc_atoms)
27
-
28
- # TODO index_spin: {iatom: ispin}
29
-
30
- # list of iatom for each spin index.
31
- uc_index_spin = [sc_excparams.index_spin[i] for i in ids]
32
-
33
- uc_ind_atoms = {}
34
- for iatom, ispin in enumerate(uc_index_spin):
35
- if ispin >= 0:
36
- uc_ind_atoms[ispin] = iatom
37
-
38
- uc_Jdict = {}
39
- uc_Rset = set()
40
- for key, val in sc_excparams.exchange_Jdict.items():
41
- R, ispin, jspin = key
42
- iatom = sc_excparams.ind_atoms[ispin]
43
- jatom = sc_excparams.ind_atoms[jspin]
44
- uc_ispin = uc_index_spin[indmap[iatom]]
45
- uc_jspin = uc_index_spin[indmap[jatom]]
46
- uc_R = R @ sc_matrix + Rmap[jatom] - Rmap[iatom]
47
- uc_R = tuple(uc_R)
48
- if iatom in ids:
49
- #print(f"{iatom=}, {indmap[iatom]=},{uc_ispin=}, {uc_jspin=}, {uc_R=} ")
50
- uc_Jdict[(uc_R, uc_ispin, uc_jspin)] = val
51
- uc_Rset.add(uc_R)
52
-
53
- uc_distance_dict = gen_distance_dict(uc_ind_atoms, uc_atoms, list(uc_Rset))
54
-
55
- assert sc_excparams.colinear, "Cut supercell for non-collinear spin is not yet implemented."
56
-
57
- uc_exc = SpinIO(uc_atoms,
58
- spinat=uc_spinat,
59
- charges=uc_charges,
60
- index_spin=uc_index_spin,
61
- colinear=sc_excparams.colinear,
62
- distance_dict=uc_distance_dict,
63
- exchange_Jdict=uc_Jdict,
64
- description="Cutted")
65
-
66
- uc_exc.write_all(output_path)
67
-
68
-
69
- def run_cut_cell(
70
- path="TB2J_results",
71
- output_path="./TB2J_cutted",
72
- sc_matrix=np.array([[1, 1, 0], [-1, 1, 0], [0, 0, 2]]),
73
- ):
74
- cut_cell(path,
75
- output_path,
76
- np.array(sc_matrix),
77
- origin_atom_id=0,
78
- thr=1e-19)
79
-
80
-
81
- if __name__ == "__main__":
82
- run_cut_cell()
File without changes
TB2J/spinham/h_matrix.py DELETED
@@ -1,68 +0,0 @@
1
- import numpy as np
2
- import matplotlib.pyplot as plt
3
- import aiida
4
- from aiida_tb2j.data import ExchangeData
5
-
6
- def plot_dispersion(bands, kpoint_labels, color='blue', title=None):
7
-
8
- fig, axs = plt.subplots(1, 1, constrained_layout=True)
9
- fig.set_size_inches(6, 6/1.618)
10
-
11
- '''
12
- Plot the bands
13
- '''
14
- kpoints = np.arange(len(bands))
15
- axs.plot(kpoints, bands, color=color, linewidth=1.5)
16
-
17
- '''
18
- Plot the symmetry points
19
- '''
20
- bmin = bands.min(); bmax = bands.max()
21
- ymin = bmin - 0.05*np.abs(bmin-bmax); ymax = bmax + 0.05*np.abs(bmax-bmin);
22
- axs.set_xticks(kpoint_labels[0], kpoint_labels[1], fontsize=10)
23
- axs.vlines(x=kpoint_labels[0], ymin=ymin, ymax=ymax, color='black', linewidth=0.5)
24
- axs.set_xlim([0, len(kpoints)])
25
- axs.set_ylim([ymin, ymax])
26
-
27
- if title is not None:
28
- plt.title(title, fontsize=10)
29
-
30
- plt.show()
31
-
32
-
33
- if __name__ == "__main__":
34
-
35
- from argparse import ArgumentParser
36
-
37
- parser = ArgumentParser()
38
- parser.add_argument('-f', '--pickle_filename', type=str, help="Path of the 'TB2J.pickle' file.", required=True)
39
- args = parser.parse_args()
40
-
41
- '''
42
- Right now the implementation depends on AiiDA and so we must create and load an AiiDA profile,
43
- even if we do not store any information on a data base.
44
- '''
45
- aiida.load_profile()
46
- '''
47
- Create an ExchangeData object with the informations from the TB2J.pickle file
48
- '''
49
- exchange = ExchangeData.load_tb2j(pickle_file=args.pickle_filename, isotropic=False, pbc=(True, True, True))
50
- '''
51
- Compute the magnon band structure along a high symmetry path generated with
52
- the ASE package. The informations is stored in an AiiDA BandsData object.
53
- Here tol is the symmetry tolerance to determine the space group of the system.
54
- They are in units of eV
55
- '''
56
- magnon_data = exchange.get_magnon_bands(npoints=300, tol=1e-1, with_DMI=True, with_Jani=True)
57
- magnon_bands = 1000*magnon_data.get_bands() # Convert to meV
58
- raw_labels = [(k, '$\Gamma$') if s == 'GAMMA' else (k, s) for k, s in magnon_data.labels]
59
- kpoint_labels = list( zip( *raw_labels ) )
60
- plot_dispersion(magnon_bands, kpoint_labels, color='blue', title='Magnon Bands')
61
- '''
62
- We can also obtain the dynamical matrix h instead of the actual magnon bands. The result
63
- is stored in a numpy array with shape (number of kpoints, 2*natoms, 2*natoms)
64
- '''
65
- kpoints = magnon_data.get_kpoints() # The shape of the kpoints must be (nkpoints, 3)
66
- h_matrix = 1000*exchange._H_matrix(kpoints, with_DMI=True, with_Jani=True) # Convert to meV
67
- h_dispersion = np.linalg.eigvalsh(h_matrix) # We can also get the eigenvectors with np.linalg.eigh
68
- plot_dispersion(h_dispersion, kpoint_labels, color='red', title='h matrix dispersion')
TB2J/spinham/obtain_J.py DELETED
@@ -1,79 +0,0 @@
1
- import numpy as np
2
- from aiida_tb2j.data import ExchangeData
3
- from aiida_tb2j.data.exchange import get_rotation_arrays
4
- from itertools import combinations_with_replacement
5
-
6
- ux, uy, uz = np.eye(3).reshape((3, 1, 3))
7
-
8
- def combine_arrays(u, v):
9
-
10
- return np.concatenate([u*v, np.roll(u, -1, axis=-1)*v, np.roll(v, -1, axis=-1)*u], axis=-1)
11
-
12
- def get_coefficients(magmoms, indices):
13
-
14
- i, j = indices
15
-
16
- U, V = zip(*[get_rotation_arrays(magmoms, u=u) for u in [ux, uy, uz]])
17
- U = np.stack(U).swapaxes(0, 1)
18
- V = np.stack(V).swapaxes(0, 1)
19
-
20
- uc = combine_arrays(U[i], U[j].conj())
21
- ur = combine_arrays(U[i], U[j])
22
- uc2 = combine_arrays(U[i].conj(), U[j])
23
- u = np.concatenate([uc, ur, uc2], axis=1)
24
-
25
- return u, V
26
-
27
- def get_C(H0, u, V):
28
-
29
- n = int(H0.shape[-1]/2)
30
- upi = np.triu_indices(n)
31
- dig = np.diag_indices(n)
32
-
33
- i, j = upi
34
- AB0 = H0[:, [i, i, i+n], [j, j+n, j+n]]
35
- AB0 = np.swapaxes(AB0, 0, 2).reshape(len(i), 9)
36
- J0_flat = np.linalg.solve(u, AB0)
37
-
38
- J0 = np.empty((n, n, 3, 3), dtype=complex)
39
- J0[*upi] = J0_flat[:, [0, 6, 5, 3, 1, 7, 8, 4, 2]].reshape(-1, 3, 3)
40
- J0 += J0.swapaxes(0, 1)
41
- J0[*dig] = 0.0
42
-
43
- C = np.array([np.diag(a) for a in np.einsum('imx,ijxy,jmy->mi', V, 2*J0, V)])
44
-
45
- return C
46
-
47
- def get_J(H, kpoints, exchange):
48
-
49
- n = int(H.shape[-1]/2)
50
- upi = np.triu_indices(n)
51
- dig = np.diag_indices(n)
52
- i, j = upi
53
-
54
- magmoms = exchange.magmoms()[np.unique(exchange.pairs)]
55
- magmoms /= np.linalg.norm(magmoms, axis=-1).reshape(-1, 1)
56
- u, V = get_coefficients(magmoms, indices=upi)
57
-
58
- H0 = np.stack([1000*exchange._H_matrix(kpoints=np.zeros((1, 3)), with_DMI=True, with_Jani=True, u=u) for u in [ux, uy, uz]])[:, 0, :, :]
59
- C = get_C(H0, u, V)
60
- H[:, :, :n, :n] += C.reshape(3, 1, n, n)
61
- H[:, :, n:, n:] += C.reshape(3, 1, n, n)
62
-
63
- AB = H[:, :, [i, i, i+n], [j, j+n, j+n]]
64
- AB[:, :, 2, :] = AB[:, ::-1, 2, :]
65
- AB = np.moveaxis(AB, [2, 3], [1, 0]).reshape(len(i), 9, -1)
66
-
67
- vectors = exchange.get_vectors()
68
- exp_summand = np.exp( -2j*np.pi*vectors @ kpoints.T )
69
- nAB = np.einsum('nik,ndk->nid', AB, exp_summand) / len(kpoints)
70
-
71
- ii = np.where(i == j)
72
- i0 = np.where(np.linalg.norm(vectors, axis=-1) == 0.0)
73
- J = np.linalg.solve(u, nAB).swapaxes(1, 2)
74
- J = J[:, :, [0, 6, 5, 3, 1, 7, 8, 4, 2]].reshape(len(i), -1, 3, 3)
75
- J *= -1
76
- J[ii] *= 2
77
- J[i0] *= 0
78
-
79
- return J
TB2J/supercell.py DELETED
@@ -1,532 +0,0 @@
1
- """
2
- A helper class for building supercells
3
- """
4
- import numpy as np
5
- from collections import OrderedDict, defaultdict
6
- from itertools import product
7
- from functools import lru_cache
8
- from ase.build import make_supercell
9
- from ase.atoms import Atoms
10
-
11
-
12
- def close_to_int(x, tol=1e-4):
13
- return np.allclose(x, np.round(x), atol=tol)
14
-
15
-
16
- class SupercellMaker(object):
17
-
18
- def __init__(self, sc_matrix, center=False):
19
- """
20
- a helper class for making supercells.
21
- sc_matrix, supercell matrix. sc_matrix .dot. unitcell = supercell
22
- """
23
- sc_matrix = np.array(sc_matrix, dtype=int)
24
- if len(sc_matrix.flatten()) == 3:
25
- sc_matrix = np.diag(sc_matrix)
26
- elif sc_matrix.shape == (3, 3):
27
- pass
28
- else:
29
- raise ValueError('sc_matrix should be 3 or 3*3 matrix')
30
- self.sc_matrix = sc_matrix
31
- self.center = center
32
- if center:
33
- self.shift = np.array([0.5, 0.5, 0.5])
34
- else:
35
- self.shift = np.zeros(3, dtype=float)
36
- self.inv_scmat = np.linalg.inv(self.sc_matrix.T)
37
- self.build_sc_vec()
38
- self.ncell = int(round(abs(np.linalg.det(sc_matrix))))
39
-
40
- def to_red_sc(self, x):
41
- return np.dot(self.inv_scmat, x) + self.shift
42
-
43
- def build_sc_vec(self):
44
- eps_shift = np.sqrt(
45
- 2.0) * 1.0E-8 # shift of the grid, so to avoid double counting
46
- #max_R = np.max(np.abs(self.sc_matrix)) * 3
47
- if self.center:
48
- minr = -0.5
49
- maxr = 0.5
50
- else:
51
- minr = 0.0
52
- maxr = 1.0
53
- sc_vec = []
54
- newcell = self.sc_matrix
55
- scorners_newcell = np.array([[0., 0., 0.], [0., 0., 1.], [0., 1., 0.],
56
- [0., 1., 1.], [1., 0., 0.], [1., 0., 1.],
57
- [1., 1., 0.], [1., 1., 1.]])
58
- corners = np.dot(scorners_newcell - self.shift, newcell)
59
- scorners = corners
60
- #rep = np.ceil(scorners.ptp(axis=0)).astype('int') + 1
61
- minrep = np.ceil(np.min(scorners, axis=0)).astype('int')
62
- maxrep = np.ceil(np.max(scorners, axis=0)).astype('int') + 1
63
-
64
- # sc_vec: supercell vector (map atom from unit cell to supercell)
65
- # for vec in product(range(rep[0]), range(rep[1]), range(rep[2])):
66
- for vec in product(range(minrep[0], maxrep[0]),
67
- range(minrep[1], maxrep[1]),
68
- range(minrep[2], maxrep[2])):
69
- # compute reduced coordinates of this candidate vector in the super-cell frame
70
- tmp_red = self.to_red_sc(vec)
71
- # check if in the interior
72
- if (not (tmp_red <= -eps_shift).any()) and (
73
- not (tmp_red > 1.0 - eps_shift).any()):
74
- sc_vec.append(np.array(vec))
75
-
76
- # number of times unit cell is repeated in the super-cell
77
- num_sc = len(sc_vec)
78
-
79
- # check that found enough super-cell vectors
80
- if int(round(np.abs(np.linalg.det(self.sc_matrix)))) != num_sc:
81
- raise Exception(
82
- "\n\nSuper-cell generation failed! Wrong number of super-cell vectors found."
83
- )
84
-
85
- sc_vec = np.array(sc_vec)
86
- self.sc_vec = np.array(sc_vec)
87
- svtuple = (tuple(s) for s in sc_vec)
88
- self.sc_vec_dict = dict(zip(svtuple, range(sc_vec.shape[0])))
89
-
90
- def get_R(self):
91
- return self.sc_vec
92
-
93
- @property
94
- def R_sc(self):
95
- return self.sc_vec
96
-
97
- def sc_cell(self, cell):
98
- cell = np.array(cell)
99
- if len(cell.flatten()) == 3:
100
- cell = np.diag(cell)
101
- return np.dot(self.sc_matrix, cell)
102
-
103
- def sc_pos(self, positions, return_R=False):
104
- """
105
- pos -> pos in supercell (reduced.)
106
- """
107
- sc_pos = []
108
- sc_R = []
109
- for cur_sc_vec in self.sc_vec: # go over all super-cell vectors
110
- for pos in positions:
111
- # shift orbital and compute coordinates in
112
- # reduced coordinates of super-cell
113
- sc_pos.append(self.to_red_sc(pos + cur_sc_vec))
114
- sc_R.append(cur_sc_vec)
115
- if return_R:
116
- return sc_pos, sc_R
117
- else:
118
- return sc_pos
119
-
120
- def sc_trans_invariant(self, q, return_R=False):
121
- """
122
- translation invariant quantities. Like on-site energy of tight binding,
123
- chemical symbols, magnetic moments of spin.
124
- """
125
- sc_q = []
126
- sc_R = [] # supercell R
127
- for cur_sc_vec in self.sc_vec: # go over all super-cell vectors
128
- for qitem in q:
129
- sc_q.append(qitem)
130
- sc_R.append(cur_sc_vec)
131
- if return_R:
132
- return sc_q, sc_R
133
- else:
134
- return sc_q
135
-
136
- def sc_trans_kvector(self, x, kpt, phase=0.0, real=False):
137
- """
138
- x is a vector of quantities inside the primitive cell.
139
- qpoint is the wavevector
140
- phase
141
- x_sc= x * exp(i(qR + phase))
142
-
143
- Note: if x is a 2D m*n array, the first m*n block is the primitive cell.
144
- [block1, block2, block3, ... block_ncell]
145
- """
146
- factor = self.phase_factor(kpt, phase=phase)
147
- ret = np.kron(factor, x)
148
- if real:
149
- ret = np.real(ret)
150
- return ret
151
-
152
- def Rvector_for_each_element(self, n_ind=1):
153
- """
154
- repeat the R_sc vectors.
155
- """
156
- return np.kron(self.sc_vec, np.ones((n_ind, 1)))
157
-
158
- def sc_index(self, indices, n_ind=None):
159
- """
160
- Note that the number of indices could be inequal to the repeat period.
161
- e.g. for n_orb of orbitals, the indices of atoms iatom for each orbital.
162
- In that case, in the second unit cell (c=1 here), iatom-> iatom+n_ind,
163
- where n_ind=natoms in primitive cell.
164
- """
165
- sc_ind = []
166
- if n_ind is None:
167
- n_ind = len(indices)
168
- for c, cur_sc_vec in enumerate(
169
- self.sc_vec): # go over all super-cell vectors
170
- for ind in indices:
171
- sc_ind.append(ind + c * n_ind)
172
- return sc_ind
173
-
174
- @lru_cache(maxsize=5000)
175
- def _sc_R_to_pair_ind(self, R_plus_Rv):
176
- """
177
- R: initial R vector (e.g. R in (i, jR) pair)
178
- Rv: translation vector. (e.g. for Rv in self.sc_vec)
179
-
180
- Returns:
181
- sc_part: R in
182
- pair_ind:
183
- """
184
- R_plus_Rv = np.asarray(R_plus_Rv)
185
- sc_part = np.floor(self.to_red_sc(R_plus_Rv)) # round down!
186
- sc_part = np.array(sc_part, dtype=int)
187
- # find remaining vector in the original reduced coordinates
188
- orig_part = R_plus_Rv - np.dot(sc_part, self.sc_matrix)
189
- pair_ind1 = self.sc_vec_dict[tuple(orig_part)]
190
- return sc_part, pair_ind1
191
-
192
- def sc_jR_to_scjR(self, j, R, Rv, n_basis):
193
- """
194
- (j, R) in primitive cell to (j', R') in supercell.
195
- """
196
- Rprim, pair_ind = self._sc_R_to_pair_ind(
197
- tuple(np.array(R) + np.array(Rv)))
198
- return j + pair_ind * n_basis, tuple(Rprim)
199
-
200
- def sc_i_to_sci(self, i, ind_Rv, n_basis):
201
- return i + ind_Rv * n_basis
202
-
203
- def sc_ijR_only(self, i, j, R, n_basis):
204
- ret = []
205
- for c, cur_sc_vec in enumerate(
206
- self.sc_vec): # go over all super-cell vectors
207
- sc_part, pair_ind = self._sc_R_to_pair_ind(tuple(R + cur_sc_vec))
208
- sc_i = i + c * n_basis
209
- sc_j = j + pair_ind * n_basis
210
- ret.append((sc_i, sc_j, tuple(sc_part)))
211
- return ret
212
-
213
- def sc_jR(self, jlist, Rjlist, n_basis):
214
- sc_jlist = []
215
- sc_Rjlist = []
216
- for c, cur_sc_vec in enumerate(
217
- self.sc_vec): # go over all super-cell vectors
218
- # for i , j, ind_R, val in
219
- for j, Rj in zip(jlist, Rjlist):
220
- sc_part, pair_ind = self._sc_R_to_pair_ind(
221
- tuple(Rj + cur_sc_vec))
222
- sc_j = j + pair_ind * n_basis
223
- sc_jlist.append(sc_j)
224
- sc_Rjlist.append(tuple(sc_part))
225
- return sc_jlist, sc_Rjlist
226
-
227
- def sc_ijR(self, terms, n_basis):
228
- """
229
- # TODO very slow when supercell is large, should improve it.
230
- map Val(i, j, R) which is a funciton of (R+rj-ri) to supercell.
231
- e.g. hopping in Tight binding. exchange in heisenberg model,...
232
- Args:
233
- ========================
234
- terms: either list of [i, j, R, val] or dict{(i,j, R): val}
235
- pos: reduced positions in the unit cell.
236
- Returns:
237
- =======================
238
- """
239
- ret_dict = OrderedDict()
240
- for c, cur_sc_vec in enumerate(
241
- self.sc_vec): # go over all super-cell vectors
242
- # for i , j, ind_R, val in
243
- for (i, j, ind_R), val in terms.items():
244
- sc_part, pair_ind = self._sc_R_to_pair_ind(
245
- tuple(ind_R + cur_sc_vec))
246
- # index of "from" and "to" hopping indices
247
- sc_i = i + c * n_basis
248
- sc_j = j + pair_ind * n_basis
249
-
250
- # hi = self._hoppings[h][1] + c * self._norb
251
- # hj = self._hoppings[h][2] + pair_ind * self._norb
252
- ret_dict[(sc_i, sc_j, tuple(sc_part))] = val
253
- return ret_dict
254
-
255
- def sc_Rlist_HR(self, Rlist, HR, n_basis):
256
- """
257
- terms: H[R][i,j] = val
258
- ========================
259
- terms: either list of [i, j, R, val] or dict{(i,j, R): val}
260
- pos: reduced positions in the unit cell.
261
- Returns:
262
- =======================
263
- """
264
- sc_Rlist = []
265
- sc_HR = []
266
- for c, cur_sc_vec in enumerate(
267
- self.sc_vec): # go over all super-cell vectors
268
- # for i , j, ind_R, val in
269
- for iR, R in enumerate(Rlist):
270
- H = HR[iR]
271
- sc_part, pair_ind = self._sc_R_to_pair_ind(
272
- tuple(R + cur_sc_vec))
273
- sc_Rlist.append(sc_part)
274
- sc_val = np.zeros((n_basis * self.ncell, n_basis * self.ncell),
275
- dtype=HR.dtype)
276
- for i in range(n_basis):
277
- for j in range(n_basis):
278
- sc_i = i + c * n_basis
279
- sc_j = j + pair_ind * n_basis
280
- sc_val[sc_i, sc_j] = H[i, j]
281
- sc_HR.append(sc_val)
282
- return np.array(sc_Rlist, dtype=int), np.array(sc_HR)
283
-
284
- def sc_RHdict(self, RHdict, n_basis):
285
- """
286
- terms: H[R][i,j] = val
287
- ========================
288
- terms: either list of [i, j, R, val] or dict{(i,j, R): val}
289
- pos: reduced positions in the unit cell.
290
- Returns:
291
- =======================
292
- """
293
- sc_RHdict = defaultdict(lambda: np.zeros(
294
- (n_basis * self.ncell, n_basis * self.ncell), dtype=H.dtype))
295
- for c, cur_sc_vec in enumerate(
296
- self.sc_vec): # go over all super-cell vectors
297
- for R, H in RHdict.items():
298
- sc_part, pair_ind = self._sc_R_to_pair_ind(
299
- tuple(R + cur_sc_vec))
300
- ii = c * n_basis
301
- jj = pair_ind * n_basis
302
- sc_RHdict[tuple(sc_part)][ii:ii + n_basis,
303
- jj:jj + n_basis] += H
304
- return sc_RHdict
305
-
306
- def sc_RHdict_notrans(self, RHdict, n_basis, Rshift=(0, 0, 0)):
307
- sc_RHdict = defaultdict(lambda: np.zeros(
308
- (n_basis * self.ncell, n_basis * self.ncell), dtype=H.dtype))
309
- cur_sc_vec = np.array(Rshift)
310
- for R, H in RHdict.items():
311
- sc_part, pair_ind = self._sc_R_to_pair_ind(
312
- tuple(np.array(R) + cur_sc_vec))
313
- c = self.sc_vec_dict[Rshift]
314
- ii = c * n_basis
315
- jj = pair_ind * n_basis
316
- sc_RHdict[tuple(sc_part)][ii:ii + n_basis, jj:jj + n_basis] += H
317
- return sc_RHdict
318
-
319
- def sc_H_RpRk_notrans(self, Rplist, Rklist, n_basis, Rpprime, H):
320
- """
321
- For a given perturbation at Rp',
322
- <Rm|Rp'=Rp+Rm|Rk+Rm>
323
- =H(Rp,Rk)=<0|Rp|Rk> is a matrix of nbasis*nbasis
324
- First: Rm = Rp'-Rp, Rk+Rm = Rp'-Rp+Rm
325
- Input: Rplist, Rklist, H
326
- H: [iRg, iRk, ibasis, ibasis]
327
- """
328
- sc_RHdict = defaultdict(lambda: np.zeros(
329
- (n_basis * self.ncell, n_basis * self.ncell), dtype=H.dtype))
330
- for iRp, Rp in enumerate(Rplist):
331
- Rm = np.array(Rpprime) - np.array(Rp)
332
-
333
- sc_part_i, pair_ind_i = self._sc_R_to_pair_ind(tuple(np.array(Rm)))
334
- ii = pair_ind_i * n_basis
335
- if tuple(sc_part_i) == (0, 0, 0):
336
- for iRk, Rk in enumerate(Rklist):
337
- sc_part_j, pair_ind_j = self._sc_R_to_pair_ind(
338
- tuple(np.array(Rk) + np.array(Rm)))
339
- jj = pair_ind_j * n_basis
340
- sc_RHdict[tuple(sc_part_j)][ii:ii + n_basis, jj:jj +
341
- n_basis] += H[iRp, iRk, :, :]
342
- # elif tuple(sc_part_j) == (0, 0, 0):
343
- # sc_RHdict[tuple(-sc_part_j)][jj:jj + n_basis,
344
- # ii:ii + n_basis] += H[iRp, iRk, :, :].T.conj()
345
-
346
- return sc_RHdict
347
-
348
- def sc_atoms(self, atoms):
349
- """
350
- This function is compatible with ase.build.make_supercell.
351
- They should produce the same result.
352
- """
353
- sc_cell = self.sc_cell(atoms.get_cell())
354
- sc_pos = self.sc_pos(atoms.get_scaled_positions())
355
- sc_numbers = self.sc_trans_invariant(atoms.get_atomic_numbers())
356
- sc_magmoms = self.sc_trans_invariant(
357
- atoms.get_initial_magnetic_moments())
358
- return Atoms(cell=sc_cell,
359
- scaled_positions=sc_pos,
360
- numbers=sc_numbers,
361
- magmoms=sc_magmoms)
362
-
363
- def phase_factor(self, qpoint, phase=0, real=True):
364
- f = np.exp(2j * np.pi * np.einsum('i, ji -> j', qpoint, self.sc_vec) +
365
- 1j * phase)
366
- if real:
367
- f = np.real(f)
368
- return f
369
-
370
- def modulation_function_R(self, func):
371
- return [func(R) for R in self.R_sc]
372
-
373
- def _make_translate_maps(positions, basis, sc_mat, tol_r=1e-4):
374
- """
375
- find the mapping between supercell and translated cell.
376
- Returns:
377
- ===============
378
- A N * nbasis array.
379
- index[i] is the mapping from supercell to translated supercell so that
380
- T(r_i) psi = psi[indices[i]].
381
-
382
- """
383
- a1 = Atoms(symbols='H', positions=[(0, 0, 0)], cell=[1, 1, 1])
384
- sc = make_supercell(a1, self._scmat)
385
- rs = sc.get_scaled_positions()
386
-
387
- indices = np.zeros([len(rs), len(positions)], dtype='int32')
388
- for i, ri in enumerate(rs):
389
- inds = []
390
- Tpositions = positions + np.array(ri)
391
- for i_basis, pos in enumerate(positions):
392
- for j_basis, Tpos in enumerate(Tpositions):
393
- dpos = Tpos - pos
394
- if close_to_int(dpos, tol_r) and (self._basis[i_basis]
395
- == self._basis[j_basis]):
396
- indices[i, j_basis] = i_basis
397
-
398
- self._trans_rs = rs
399
- self._trans_indices = indices
400
-
401
-
402
- def smod(x):
403
- x = np.mod(x, 1)
404
- return x if x < 0.5 else x - 1
405
-
406
-
407
- smod = np.vectorize(smod)
408
-
409
-
410
- def map_to_primitive(atoms, primitive_atoms, offset=(0, 0, 0)):
411
- """
412
- Find the mapping of a supercell to a primitive cell.
413
- :param atoms: the positions of atoms
414
- :param primitive_atoms:
415
- :param offset:
416
- :param 0:
417
- :param 0):
418
-
419
- """
420
- ilist = []
421
- Rlist = []
422
- offset = np.array(offset, dtype=float)
423
- ppos = primitive_atoms.get_positions()
424
- pos = atoms.get_positions()
425
- cell = primitive_atoms.get_cell()
426
- for p in pos:
427
- found = False
428
- for i, pp in enumerate(ppos):
429
- res0 = np.linalg.solve(cell.T, p - pp)
430
- res = smod(res0)
431
- if np.linalg.norm(res) < 0.01:
432
- found = True
433
- R = res0 - res
434
- ilist.append(i)
435
- Rlist.append(R)
436
- break
437
- if not found:
438
- print("Not found")
439
- ilist.append(-1)
440
- Rlist.append([-999, -999, -999])
441
- return np.array(ilist, dtype=int), np.array(Rlist, dtype=int)
442
-
443
-
444
- def find_primitive_cell(atoms,
445
- sc_matrix,
446
- origin_atom_id=None,
447
- thr=1e-5,
448
- perfect=True):
449
- """
450
- Find a primitive cell atoms from the supercell atom structure.
451
- :param atoms: the supercell structure.
452
- :param sc_matrix: the matrix which maps the primitive cell to supercell.
453
- :param origin: the origin of the primitive cell.
454
- :param thr: the atoms which the reduced position is within -thr to 1.0+thr are considered as inside the primitive atoms
455
- :params perfect: True|False, whether the primitive cell should contains the same number of atoms .
456
- :returns: (patoms, selected)
457
- patoms: the primitive cell atoms
458
- selected: the selected indices of the atoms in the supercell.
459
- """
460
- scell = atoms.get_cell().array
461
- inv_scmat = np.linalg.inv(sc_matrix)
462
- pcell = scell@inv_scmat
463
- print(f"{inv_scmat=}")
464
-
465
- xcart = atoms.get_positions()
466
- xred = atoms.get_scaled_positions()
467
- print(xred)
468
- if origin_atom_id is not None:
469
- origin = xred[origin_atom_id]
470
- else:
471
- origin = np.zeros(3)
472
- # check if some atom is exactly at the origin.
473
- # if so, shift the positions by thr so that this atom is inside the cell
474
- # if np.any(np.linalg.norm(xred - origin[None, :], axis=1) < thr):
475
- # xred += thr
476
- #xred += 0.05
477
-
478
- sc_xred = xred@sc_matrix
479
- print(sc_xred)
480
- #np.all(sc_xred<1 and sc_xred>=0.0)
481
- # print(sc_xred<1)
482
- x = np.logical_and(sc_xred < 1+thr, sc_xred >= -thr)
483
- print(np.all(x, axis=1))
484
- selected = np.where(np.all(x, axis=1))[0]
485
- print(selected)
486
- symbols = atoms.get_chemical_symbols()
487
- psymbols = [symbols[i] for i in selected]
488
- patoms = Atoms(symbols=psymbols, positions=xcart[selected], cell=pcell)
489
- ncell = abs(np.linalg.det(sc_matrix))
490
- natom = len(atoms)
491
- if perfect:
492
- assert len(symbols) == int(
493
- natom/ncell), "The number of atoms in the found primitive cell does not equal to natom in the supercell divided by the size of the cell"
494
- return patoms, selected
495
-
496
-
497
- def test_find_primitive_cell():
498
- atoms = Atoms('HO', positions=[[0, 0, 0], [0, 0.2, 0]], cell=[1, 1, 1])
499
- sc_matrix = np.diag([1, 1, 3])
500
- atoms2 = make_supercell(atoms, sc_matrix)
501
- patoms = find_primitive_cell(atoms2, sc_matrix)
502
-
503
-
504
- def test():
505
- sc_mat = np.diag([1, 1, 3])
506
- #sc_mat[0, 1] = 2
507
- spm = SupercellMaker(sc_matrix=sc_mat, center=False)
508
- print("sc_vec", spm.sc_vec)
509
- print(spm.sc_cell([1, 1, 1]))
510
- print(spm.sc_pos([[0.5, 1, 1]]))
511
- print(spm.sc_pos([[0.5, 1, 0.5]]))
512
- print(spm.sc_trans_invariant(['Fe']))
513
- print(spm.sc_ijR({
514
- (0, 0, (0, 0, 1)): 1.2,
515
- (1, 1, (0, 0, 1)): 1.2,
516
- }, 2))
517
- print(spm.sc_index(indices=(1, 2)))
518
- print(spm.sc_index(indices=(1, 2), n_ind=4))
519
- from ase.atoms import Atoms
520
- atoms = Atoms('HO', positions=[[0, 0, 0], [0, 0.2, 0]], cell=[1, 1, 1])
521
- from ase.build import make_supercell
522
- atoms2 = make_supercell(atoms, sc_mat)
523
- atoms3 = spm.sc_atoms(atoms)
524
- # print(atoms2.get_positions())
525
- # print(atoms3.get_positions())
526
- assert (atoms2 == atoms3)
527
- assert (atoms2.get_positions() == atoms3.get_positions()).all()
528
-
529
-
530
- if __name__ == '__main__':
531
- # test()
532
- test_find_primitive_cell()
File without changes
File without changes