spintensor 0.1.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.
- spintensor-0.1.0/LICENSE +21 -0
- spintensor-0.1.0/MANIFEST.in +6 -0
- spintensor-0.1.0/PKG-INFO +343 -0
- spintensor-0.1.0/README.md +317 -0
- spintensor-0.1.0/examples/examples.py +728 -0
- spintensor-0.1.0/examples/verify_requirements.py +151 -0
- spintensor-0.1.0/pyproject.toml +39 -0
- spintensor-0.1.0/requirements.txt +1 -0
- spintensor-0.1.0/setup.cfg +4 -0
- spintensor-0.1.0/src/spintensor/__init__.py +65 -0
- spintensor-0.1.0/src/spintensor/core.py +1253 -0
- spintensor-0.1.0/src/spintensor.egg-info/PKG-INFO +343 -0
- spintensor-0.1.0/src/spintensor.egg-info/SOURCES.txt +17 -0
- spintensor-0.1.0/src/spintensor.egg-info/dependency_links.txt +1 -0
- spintensor-0.1.0/src/spintensor.egg-info/requires.txt +1 -0
- spintensor-0.1.0/src/spintensor.egg-info/top_level.txt +1 -0
- spintensor-0.1.0/tests/__init__.py +0 -0
- spintensor-0.1.0/tests/conftest.py +11 -0
- spintensor-0.1.0/tests/test_core.py +2902 -0
spintensor-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Connor1y
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: spintensor
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Build linear constraints for tensors under transformations using Kronecker products
|
|
5
|
+
Author: Connor1y
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Connor1y/spintensor
|
|
8
|
+
Project-URL: Repository, https://github.com/Connor1y/spintensor
|
|
9
|
+
Project-URL: Issues, https://github.com/Connor1y/spintensor/issues
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Requires-Python: >=3.7
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: numpy>=1.19.0
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# SpinTensor
|
|
28
|
+
|
|
29
|
+
A Python library for constructing linear constraints on tensors under transformations using Kronecker products. Supports operation-dependent T-parity, P-parity, and index-permutation symmetries, with automatic nullspace computation via SVD and LaTeX output.
|
|
30
|
+
|
|
31
|
+
## Overview
|
|
32
|
+
|
|
33
|
+
This library constructs linear constraints for order-r tensors in dimension n under spin-group operations `(Rs, Rr)` of the form:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Tᵢ₁…ᵢᵣ = sign_T · sign_P · Rrᵢ₁ⱼ₁ … Rrᵢᵣⱼᵣ Tⱼ₁…ⱼᵣ
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
where the **per-operation sign factors** are computed from matrix determinants:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
sign_T = det(Rs) ** T_constraint
|
|
43
|
+
sign_P = det(Rr) ** P_constraint
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- `Rs` is the **spin-space matrix**: `det(Rs) = -1` contributes an effective time-reversal sign for T-odd tensors (`T_constraint = 1`).
|
|
47
|
+
- `Rr` is the **real-space matrix** applied to every tensor axis: `det(Rr) = -1` contributes a parity sign for P-odd tensors (`P_constraint = 1`).
|
|
48
|
+
- The real-space action `Rr ⊗ Rr ⊗ ... ⊗ Rr` always drives the tensor transformation; `Rs` only contributes a sign.
|
|
49
|
+
|
|
50
|
+
The library builds constraint matrices, computes their nullspace using SVD (not row reduction), and outputs readable LaTeX relations with automatic index-to-symbol mapping.
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install spintensor
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Or install in development mode:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install -e .
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Features
|
|
65
|
+
|
|
66
|
+
- **Operation-Dependent Sign Logic**: Per-operation sign factors `sign_T = det(Rs)**T_constraint` and `sign_P = det(Rr)**P_constraint` (not global fixed values)
|
|
67
|
+
- **Kronecker Product Transformations**: Efficiently build transformation matrices using Kronecker products of the real-space matrix `Rr`
|
|
68
|
+
- **T-parity and P-parity**: Support for time reversal and spatial parity symmetries
|
|
69
|
+
- **Index Permutation Symmetries**: Handle symmetric, antisymmetric, and general permutation symmetries
|
|
70
|
+
- **SVD-based Nullspace**: Numerically stable nullspace computation using Singular Value Decomposition
|
|
71
|
+
- **LaTeX Output**: Automatic generation of readable constraint relations with smart index notation
|
|
72
|
+
|
|
73
|
+
## Quick Start
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import numpy as np
|
|
77
|
+
from spintensor import solve_tensor_constraints
|
|
78
|
+
|
|
79
|
+
# Define operations in [Rs, Rr] format
|
|
80
|
+
# Rs: spin-space matrix; Rr: real-space matrix
|
|
81
|
+
n = 3 # dimension
|
|
82
|
+
r = 2 # tensor rank
|
|
83
|
+
|
|
84
|
+
# Spin reflection (det(Rs) = -1) in spin space, identity in real space
|
|
85
|
+
Rs = np.diag([1., 1., -1.]) # det = -1
|
|
86
|
+
Rr = np.eye(3) # det = +1
|
|
87
|
+
|
|
88
|
+
# T-odd tensor: sign_T = det(Rs)**1 = -1
|
|
89
|
+
A, nullspace, relations, components = solve_tensor_constraints(
|
|
90
|
+
[[Rs, Rr]], n, r, T_constraint=1, P_constraint=0
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
print(f"Independent components: {nullspace.shape[1]}")
|
|
94
|
+
for rel in relations:
|
|
95
|
+
print(f" {rel}")
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Input Formats
|
|
99
|
+
|
|
100
|
+
All transformation formats are supported. The `[Rs, Rr]` format is the primary API for the new per-operation sign convention:
|
|
101
|
+
|
|
102
|
+
### Format 1: `[Rs, Rr]` (recommended)
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
# Each entry is [spin_matrix, real_space_matrix]
|
|
106
|
+
transformations = [
|
|
107
|
+
[Rs1, Rr1], # sign_T = det(Rs1)**T_constraint, sign_P = det(Rr1)**P_constraint
|
|
108
|
+
[Rs2, Rr2],
|
|
109
|
+
]
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
With `spin_axes` set, `Rs` is also applied to the specified tensor axes.
|
|
113
|
+
|
|
114
|
+
### Format 2: `[Tflag, Rr]` (explicit anti-unitary flag)
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
# Tflag=True means the operation is anti-unitary (contributes sign_T=-1 when T_constraint=1)
|
|
118
|
+
transformations = [
|
|
119
|
+
[False, Rr_unitary], # sign_T = +1
|
|
120
|
+
[True, Rr_antiunitary], # sign_T = -1
|
|
121
|
+
]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Format 3: `Rr` only (no spin component)
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
# Single numpy array: treated as Rs = identity (det=+1, no T sign)
|
|
128
|
+
transformations = [Rr1, Rr2] # sign_T = +1 always
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Format 4: Legacy `(R, s_T, s_P)` tuple
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
# Explicit parity values (backward compatible)
|
|
135
|
+
transformations = [(R, s_T, s_P)]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## API Reference
|
|
139
|
+
|
|
140
|
+
### Main Function
|
|
141
|
+
|
|
142
|
+
#### `solve_tensor_constraints(transformations, n, r, symmetries=None, antisymmetries=None, tol=1e-10, spin_axes=None, T_constraint=0, det_tol=1e-6, symbol='\\sigma', extra_constraints=None, P_constraint=0)`
|
|
143
|
+
|
|
144
|
+
Complete solver for tensor constraints.
|
|
145
|
+
|
|
146
|
+
**Parameters:**
|
|
147
|
+
- `transformations`: List of transformations in any supported format
|
|
148
|
+
- `n`: int, dimension of the tensor space
|
|
149
|
+
- `r`: int, order (rank) of the tensor
|
|
150
|
+
- `symmetries`: list of tuples, optional index permutations for symmetric constraints (T_perm = T)
|
|
151
|
+
- `antisymmetries`: list of tuples, optional index permutations for antisymmetric constraints (T_perm = -T)
|
|
152
|
+
- `tol`: float, tolerance for numerical operations
|
|
153
|
+
- `spin_axes`: optional tuple of axis indices for spin axes (used with [Rs, Rr] format)
|
|
154
|
+
- `T_constraint`: int, exponent for time-reversal sign. `sign_T = det(Rs)**T_constraint`. Use `1` for T-odd tensors (default `0`)
|
|
155
|
+
- `P_constraint`: int, exponent for parity sign. `sign_P = det(Rr)**P_constraint`. Use `1` for P-odd/axial tensors (default `0`)
|
|
156
|
+
- `det_tol`: float, tolerance for determinant comparison to ±1
|
|
157
|
+
|
|
158
|
+
**Returns:**
|
|
159
|
+
- `constraint_matrix`: numpy array, full constraint matrix
|
|
160
|
+
- `nullspace_basis`: numpy array, columns are basis vectors
|
|
161
|
+
- `latex_relations`: list of strings, formatted LaTeX relations
|
|
162
|
+
- `tensor_components`: nested list of component expressions
|
|
163
|
+
|
|
164
|
+
### Convenience Functions
|
|
165
|
+
|
|
166
|
+
#### `solve_qmd(transformations, n=3, tol=1e-10)`
|
|
167
|
+
|
|
168
|
+
Solve for QMD (quadrupole moment derivative) tensors: T-odd, rank-3, with last-two-index symmetry.
|
|
169
|
+
|
|
170
|
+
#### `solve_imd(transformations, n=3, tol=1e-10)`
|
|
171
|
+
|
|
172
|
+
Solve for IMD tensors: T-odd, rank-3, with both last-two and first-two index symmetry.
|
|
173
|
+
|
|
174
|
+
#### `solve_bcd(transformations, n=3, tol=1e-10, use_cyclic_constraint=True)`
|
|
175
|
+
|
|
176
|
+
Solve for BCD (Berry curvature dipole) tensors: T-even, rank-3, with last-two-index symmetry and optional cyclic sum constraint.
|
|
177
|
+
|
|
178
|
+
### Core Functions
|
|
179
|
+
|
|
180
|
+
#### `build_constraint_matrix(transformations, n, r, ...)`
|
|
181
|
+
|
|
182
|
+
Build the full constraint matrix from transformations and symmetries.
|
|
183
|
+
|
|
184
|
+
#### `compute_nullspace_svd(A, tol=1e-10)`
|
|
185
|
+
|
|
186
|
+
Compute nullspace of matrix A using SVD.
|
|
187
|
+
|
|
188
|
+
#### `format_latex_relations(nullspace, n, r, tol=1e-10)`
|
|
189
|
+
|
|
190
|
+
Format nullspace basis vectors as readable LaTeX relations.
|
|
191
|
+
|
|
192
|
+
## Examples
|
|
193
|
+
|
|
194
|
+
### Example 1: AHE Conductivity (T-odd, polar, rank-2)
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
import numpy as np
|
|
198
|
+
from spintensor import solve_tensor_constraints
|
|
199
|
+
|
|
200
|
+
# Operations in [Rs, Rr] format
|
|
201
|
+
# T-odd tensor: sign_T = det(Rs)**1
|
|
202
|
+
|
|
203
|
+
ops = [
|
|
204
|
+
[np.diag([1., 1., 1.]), np.diag([1., 1., 1.])], # identity
|
|
205
|
+
[np.diag([1., 1., -1.]), np.diag([1., 1.,-1.])], # z-mirror: det(Rs)=-1 → s_T=-1
|
|
206
|
+
]
|
|
207
|
+
|
|
208
|
+
A, nullspace, relations, comps = solve_tensor_constraints(
|
|
209
|
+
ops, n=3, r=2, T_constraint=1, P_constraint=0
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
print(f"Independent components: {nullspace.shape[1]}")
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Example 2: QMD Tensor with Spin-Group Operations
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
import numpy as np
|
|
219
|
+
from spintensor import solve_qmd
|
|
220
|
+
|
|
221
|
+
# Operations in [Rs, Rr] format
|
|
222
|
+
# Mirror op: det(Rs) = -1 → T-odd sign applies
|
|
223
|
+
s = np.sqrt(3) / 2
|
|
224
|
+
ops = [
|
|
225
|
+
[np.eye(3), np.eye(3)],
|
|
226
|
+
[np.array([[-0.5, s, 0], [s, 0.5, 0], [0, 0, 1]]),
|
|
227
|
+
np.array([[-0.5, s, 0], [s, 0.5, 0], [0, 0, 1]])],
|
|
228
|
+
# ... more operations
|
|
229
|
+
]
|
|
230
|
+
|
|
231
|
+
A, nullspace, relations, comps = solve_qmd(ops)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Example 3: P-odd (Axial) Tensor
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
import numpy as np
|
|
238
|
+
from spintensor import solve_tensor_constraints
|
|
239
|
+
|
|
240
|
+
# P_constraint=1: sign_P = det(Rr)**1
|
|
241
|
+
# For a reflection with det(Rr)=-1, this adds a -1 sign factor
|
|
242
|
+
R_reflect = np.diag([1., 1., -1.])
|
|
243
|
+
|
|
244
|
+
A, nullspace, relations, comps = solve_tensor_constraints(
|
|
245
|
+
[[np.eye(3), R_reflect]], n=3, r=2,
|
|
246
|
+
T_constraint=0, P_constraint=1
|
|
247
|
+
)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Example 4: Legacy Format (Backward Compatible)
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
import numpy as np
|
|
254
|
+
from spintensor import solve_tensor_constraints
|
|
255
|
+
|
|
256
|
+
R_z = np.array([[-1, 0, 0], [0, -1, 0], [0, 0, 1]])
|
|
257
|
+
|
|
258
|
+
# Legacy tuple format: (R, s_T, s_P) — explicit parity values
|
|
259
|
+
transformations = [(R_z, 1.0, 1.0)]
|
|
260
|
+
A, nullspace, relations, comps = solve_tensor_constraints(
|
|
261
|
+
transformations, n=3, r=2, symmetries=[(1, 0)]
|
|
262
|
+
)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Mathematical Background
|
|
266
|
+
|
|
267
|
+
### Operation-Dependent Sign Logic
|
|
268
|
+
|
|
269
|
+
For each operation `(Rs, Rr)`, the transformation matrix acting on the flattened tensor is:
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
M = sign_T · sign_P · (Rr ⊗ Rr ⊗ ... ⊗ Rr)
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
where:
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
sign_T = det(Rs) ** T_constraint
|
|
279
|
+
sign_P = det(Rr) ** P_constraint
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
The constraint for a symmetry-invariant tensor is `(M - I) · T = 0`.
|
|
283
|
+
|
|
284
|
+
**Physical interpretation:**
|
|
285
|
+
- `det(Rs) = -1`: The spin-space operation flips the spin (effective time-reversal character). For T-odd tensors (`T_constraint=1`), this contributes a factor of `-1`.
|
|
286
|
+
- `det(Rr) = -1`: The real-space operation is an improper rotation (parity-odd). For P-odd/axial tensors (`P_constraint=1`), this contributes a factor of `-1`.
|
|
287
|
+
- These factors are **per-operation** — each operation in the symmetry group can independently flip or not flip each parity sign.
|
|
288
|
+
|
|
289
|
+
### Index Symmetries
|
|
290
|
+
|
|
291
|
+
Index permutation symmetries impose additional constraints:
|
|
292
|
+
```
|
|
293
|
+
(P_perm - I) · T = 0 (symmetric)
|
|
294
|
+
(P_perm + I) · T = 0 (antisymmetric)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Nullspace Computation
|
|
298
|
+
|
|
299
|
+
The solution space consists of all tensors satisfying the constraints. This is the nullspace of the combined constraint matrix A, computed via SVD:
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
A = U · Σ · Vᵀ
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
The nullspace is spanned by columns of V corresponding to zero singular values. The basis is further reduced to RREF form for clean, canonical coefficients.
|
|
306
|
+
|
|
307
|
+
## Output Format
|
|
308
|
+
|
|
309
|
+
Relations are output in LaTeX format with automatic index notation:
|
|
310
|
+
- For n ≤ 4: uses letters (x, y, z, w)
|
|
311
|
+
- For n > 4: uses numbers (1, 2, 3, ...)
|
|
312
|
+
|
|
313
|
+
Example output:
|
|
314
|
+
```
|
|
315
|
+
\sigma_{xxy} = \sigma_{xyx} = \sigma_{yxx} = -\sigma_{yyy}
|
|
316
|
+
\sigma_{xyz} = \sigma_{xzy} = -\sigma_{yxz} = -\sigma_{yzx}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Requirements
|
|
320
|
+
|
|
321
|
+
- Python ≥ 3.7
|
|
322
|
+
- NumPy ≥ 1.19.0
|
|
323
|
+
|
|
324
|
+
## License
|
|
325
|
+
|
|
326
|
+
MIT License
|
|
327
|
+
|
|
328
|
+
## Contributing
|
|
329
|
+
|
|
330
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
331
|
+
|
|
332
|
+
## Citation
|
|
333
|
+
|
|
334
|
+
If you use this library in your research, please cite:
|
|
335
|
+
|
|
336
|
+
```bibtex
|
|
337
|
+
@software{spintensor,
|
|
338
|
+
title = {SpinTensor: Linear Constraints for Tensors Under Transformations},
|
|
339
|
+
author = {Connor1y},
|
|
340
|
+
year = {2026},
|
|
341
|
+
url = {https://github.com/Connor1y/spintensor}
|
|
342
|
+
}
|
|
343
|
+
```
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# SpinTensor
|
|
2
|
+
|
|
3
|
+
A Python library for constructing linear constraints on tensors under transformations using Kronecker products. Supports operation-dependent T-parity, P-parity, and index-permutation symmetries, with automatic nullspace computation via SVD and LaTeX output.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This library constructs linear constraints for order-r tensors in dimension n under spin-group operations `(Rs, Rr)` of the form:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Tᵢ₁…ᵢᵣ = sign_T · sign_P · Rrᵢ₁ⱼ₁ … Rrᵢᵣⱼᵣ Tⱼ₁…ⱼᵣ
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
where the **per-operation sign factors** are computed from matrix determinants:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
sign_T = det(Rs) ** T_constraint
|
|
17
|
+
sign_P = det(Rr) ** P_constraint
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- `Rs` is the **spin-space matrix**: `det(Rs) = -1` contributes an effective time-reversal sign for T-odd tensors (`T_constraint = 1`).
|
|
21
|
+
- `Rr` is the **real-space matrix** applied to every tensor axis: `det(Rr) = -1` contributes a parity sign for P-odd tensors (`P_constraint = 1`).
|
|
22
|
+
- The real-space action `Rr ⊗ Rr ⊗ ... ⊗ Rr` always drives the tensor transformation; `Rs` only contributes a sign.
|
|
23
|
+
|
|
24
|
+
The library builds constraint matrices, computes their nullspace using SVD (not row reduction), and outputs readable LaTeX relations with automatic index-to-symbol mapping.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install spintensor
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Or install in development mode:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install -e .
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- **Operation-Dependent Sign Logic**: Per-operation sign factors `sign_T = det(Rs)**T_constraint` and `sign_P = det(Rr)**P_constraint` (not global fixed values)
|
|
41
|
+
- **Kronecker Product Transformations**: Efficiently build transformation matrices using Kronecker products of the real-space matrix `Rr`
|
|
42
|
+
- **T-parity and P-parity**: Support for time reversal and spatial parity symmetries
|
|
43
|
+
- **Index Permutation Symmetries**: Handle symmetric, antisymmetric, and general permutation symmetries
|
|
44
|
+
- **SVD-based Nullspace**: Numerically stable nullspace computation using Singular Value Decomposition
|
|
45
|
+
- **LaTeX Output**: Automatic generation of readable constraint relations with smart index notation
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
import numpy as np
|
|
51
|
+
from spintensor import solve_tensor_constraints
|
|
52
|
+
|
|
53
|
+
# Define operations in [Rs, Rr] format
|
|
54
|
+
# Rs: spin-space matrix; Rr: real-space matrix
|
|
55
|
+
n = 3 # dimension
|
|
56
|
+
r = 2 # tensor rank
|
|
57
|
+
|
|
58
|
+
# Spin reflection (det(Rs) = -1) in spin space, identity in real space
|
|
59
|
+
Rs = np.diag([1., 1., -1.]) # det = -1
|
|
60
|
+
Rr = np.eye(3) # det = +1
|
|
61
|
+
|
|
62
|
+
# T-odd tensor: sign_T = det(Rs)**1 = -1
|
|
63
|
+
A, nullspace, relations, components = solve_tensor_constraints(
|
|
64
|
+
[[Rs, Rr]], n, r, T_constraint=1, P_constraint=0
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
print(f"Independent components: {nullspace.shape[1]}")
|
|
68
|
+
for rel in relations:
|
|
69
|
+
print(f" {rel}")
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Input Formats
|
|
73
|
+
|
|
74
|
+
All transformation formats are supported. The `[Rs, Rr]` format is the primary API for the new per-operation sign convention:
|
|
75
|
+
|
|
76
|
+
### Format 1: `[Rs, Rr]` (recommended)
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
# Each entry is [spin_matrix, real_space_matrix]
|
|
80
|
+
transformations = [
|
|
81
|
+
[Rs1, Rr1], # sign_T = det(Rs1)**T_constraint, sign_P = det(Rr1)**P_constraint
|
|
82
|
+
[Rs2, Rr2],
|
|
83
|
+
]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
With `spin_axes` set, `Rs` is also applied to the specified tensor axes.
|
|
87
|
+
|
|
88
|
+
### Format 2: `[Tflag, Rr]` (explicit anti-unitary flag)
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
# Tflag=True means the operation is anti-unitary (contributes sign_T=-1 when T_constraint=1)
|
|
92
|
+
transformations = [
|
|
93
|
+
[False, Rr_unitary], # sign_T = +1
|
|
94
|
+
[True, Rr_antiunitary], # sign_T = -1
|
|
95
|
+
]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Format 3: `Rr` only (no spin component)
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
# Single numpy array: treated as Rs = identity (det=+1, no T sign)
|
|
102
|
+
transformations = [Rr1, Rr2] # sign_T = +1 always
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Format 4: Legacy `(R, s_T, s_P)` tuple
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
# Explicit parity values (backward compatible)
|
|
109
|
+
transformations = [(R, s_T, s_P)]
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## API Reference
|
|
113
|
+
|
|
114
|
+
### Main Function
|
|
115
|
+
|
|
116
|
+
#### `solve_tensor_constraints(transformations, n, r, symmetries=None, antisymmetries=None, tol=1e-10, spin_axes=None, T_constraint=0, det_tol=1e-6, symbol='\\sigma', extra_constraints=None, P_constraint=0)`
|
|
117
|
+
|
|
118
|
+
Complete solver for tensor constraints.
|
|
119
|
+
|
|
120
|
+
**Parameters:**
|
|
121
|
+
- `transformations`: List of transformations in any supported format
|
|
122
|
+
- `n`: int, dimension of the tensor space
|
|
123
|
+
- `r`: int, order (rank) of the tensor
|
|
124
|
+
- `symmetries`: list of tuples, optional index permutations for symmetric constraints (T_perm = T)
|
|
125
|
+
- `antisymmetries`: list of tuples, optional index permutations for antisymmetric constraints (T_perm = -T)
|
|
126
|
+
- `tol`: float, tolerance for numerical operations
|
|
127
|
+
- `spin_axes`: optional tuple of axis indices for spin axes (used with [Rs, Rr] format)
|
|
128
|
+
- `T_constraint`: int, exponent for time-reversal sign. `sign_T = det(Rs)**T_constraint`. Use `1` for T-odd tensors (default `0`)
|
|
129
|
+
- `P_constraint`: int, exponent for parity sign. `sign_P = det(Rr)**P_constraint`. Use `1` for P-odd/axial tensors (default `0`)
|
|
130
|
+
- `det_tol`: float, tolerance for determinant comparison to ±1
|
|
131
|
+
|
|
132
|
+
**Returns:**
|
|
133
|
+
- `constraint_matrix`: numpy array, full constraint matrix
|
|
134
|
+
- `nullspace_basis`: numpy array, columns are basis vectors
|
|
135
|
+
- `latex_relations`: list of strings, formatted LaTeX relations
|
|
136
|
+
- `tensor_components`: nested list of component expressions
|
|
137
|
+
|
|
138
|
+
### Convenience Functions
|
|
139
|
+
|
|
140
|
+
#### `solve_qmd(transformations, n=3, tol=1e-10)`
|
|
141
|
+
|
|
142
|
+
Solve for QMD (quadrupole moment derivative) tensors: T-odd, rank-3, with last-two-index symmetry.
|
|
143
|
+
|
|
144
|
+
#### `solve_imd(transformations, n=3, tol=1e-10)`
|
|
145
|
+
|
|
146
|
+
Solve for IMD tensors: T-odd, rank-3, with both last-two and first-two index symmetry.
|
|
147
|
+
|
|
148
|
+
#### `solve_bcd(transformations, n=3, tol=1e-10, use_cyclic_constraint=True)`
|
|
149
|
+
|
|
150
|
+
Solve for BCD (Berry curvature dipole) tensors: T-even, rank-3, with last-two-index symmetry and optional cyclic sum constraint.
|
|
151
|
+
|
|
152
|
+
### Core Functions
|
|
153
|
+
|
|
154
|
+
#### `build_constraint_matrix(transformations, n, r, ...)`
|
|
155
|
+
|
|
156
|
+
Build the full constraint matrix from transformations and symmetries.
|
|
157
|
+
|
|
158
|
+
#### `compute_nullspace_svd(A, tol=1e-10)`
|
|
159
|
+
|
|
160
|
+
Compute nullspace of matrix A using SVD.
|
|
161
|
+
|
|
162
|
+
#### `format_latex_relations(nullspace, n, r, tol=1e-10)`
|
|
163
|
+
|
|
164
|
+
Format nullspace basis vectors as readable LaTeX relations.
|
|
165
|
+
|
|
166
|
+
## Examples
|
|
167
|
+
|
|
168
|
+
### Example 1: AHE Conductivity (T-odd, polar, rank-2)
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
import numpy as np
|
|
172
|
+
from spintensor import solve_tensor_constraints
|
|
173
|
+
|
|
174
|
+
# Operations in [Rs, Rr] format
|
|
175
|
+
# T-odd tensor: sign_T = det(Rs)**1
|
|
176
|
+
|
|
177
|
+
ops = [
|
|
178
|
+
[np.diag([1., 1., 1.]), np.diag([1., 1., 1.])], # identity
|
|
179
|
+
[np.diag([1., 1., -1.]), np.diag([1., 1.,-1.])], # z-mirror: det(Rs)=-1 → s_T=-1
|
|
180
|
+
]
|
|
181
|
+
|
|
182
|
+
A, nullspace, relations, comps = solve_tensor_constraints(
|
|
183
|
+
ops, n=3, r=2, T_constraint=1, P_constraint=0
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
print(f"Independent components: {nullspace.shape[1]}")
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Example 2: QMD Tensor with Spin-Group Operations
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
import numpy as np
|
|
193
|
+
from spintensor import solve_qmd
|
|
194
|
+
|
|
195
|
+
# Operations in [Rs, Rr] format
|
|
196
|
+
# Mirror op: det(Rs) = -1 → T-odd sign applies
|
|
197
|
+
s = np.sqrt(3) / 2
|
|
198
|
+
ops = [
|
|
199
|
+
[np.eye(3), np.eye(3)],
|
|
200
|
+
[np.array([[-0.5, s, 0], [s, 0.5, 0], [0, 0, 1]]),
|
|
201
|
+
np.array([[-0.5, s, 0], [s, 0.5, 0], [0, 0, 1]])],
|
|
202
|
+
# ... more operations
|
|
203
|
+
]
|
|
204
|
+
|
|
205
|
+
A, nullspace, relations, comps = solve_qmd(ops)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Example 3: P-odd (Axial) Tensor
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
import numpy as np
|
|
212
|
+
from spintensor import solve_tensor_constraints
|
|
213
|
+
|
|
214
|
+
# P_constraint=1: sign_P = det(Rr)**1
|
|
215
|
+
# For a reflection with det(Rr)=-1, this adds a -1 sign factor
|
|
216
|
+
R_reflect = np.diag([1., 1., -1.])
|
|
217
|
+
|
|
218
|
+
A, nullspace, relations, comps = solve_tensor_constraints(
|
|
219
|
+
[[np.eye(3), R_reflect]], n=3, r=2,
|
|
220
|
+
T_constraint=0, P_constraint=1
|
|
221
|
+
)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Example 4: Legacy Format (Backward Compatible)
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
import numpy as np
|
|
228
|
+
from spintensor import solve_tensor_constraints
|
|
229
|
+
|
|
230
|
+
R_z = np.array([[-1, 0, 0], [0, -1, 0], [0, 0, 1]])
|
|
231
|
+
|
|
232
|
+
# Legacy tuple format: (R, s_T, s_P) — explicit parity values
|
|
233
|
+
transformations = [(R_z, 1.0, 1.0)]
|
|
234
|
+
A, nullspace, relations, comps = solve_tensor_constraints(
|
|
235
|
+
transformations, n=3, r=2, symmetries=[(1, 0)]
|
|
236
|
+
)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Mathematical Background
|
|
240
|
+
|
|
241
|
+
### Operation-Dependent Sign Logic
|
|
242
|
+
|
|
243
|
+
For each operation `(Rs, Rr)`, the transformation matrix acting on the flattened tensor is:
|
|
244
|
+
|
|
245
|
+
```
|
|
246
|
+
M = sign_T · sign_P · (Rr ⊗ Rr ⊗ ... ⊗ Rr)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
where:
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
sign_T = det(Rs) ** T_constraint
|
|
253
|
+
sign_P = det(Rr) ** P_constraint
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
The constraint for a symmetry-invariant tensor is `(M - I) · T = 0`.
|
|
257
|
+
|
|
258
|
+
**Physical interpretation:**
|
|
259
|
+
- `det(Rs) = -1`: The spin-space operation flips the spin (effective time-reversal character). For T-odd tensors (`T_constraint=1`), this contributes a factor of `-1`.
|
|
260
|
+
- `det(Rr) = -1`: The real-space operation is an improper rotation (parity-odd). For P-odd/axial tensors (`P_constraint=1`), this contributes a factor of `-1`.
|
|
261
|
+
- These factors are **per-operation** — each operation in the symmetry group can independently flip or not flip each parity sign.
|
|
262
|
+
|
|
263
|
+
### Index Symmetries
|
|
264
|
+
|
|
265
|
+
Index permutation symmetries impose additional constraints:
|
|
266
|
+
```
|
|
267
|
+
(P_perm - I) · T = 0 (symmetric)
|
|
268
|
+
(P_perm + I) · T = 0 (antisymmetric)
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Nullspace Computation
|
|
272
|
+
|
|
273
|
+
The solution space consists of all tensors satisfying the constraints. This is the nullspace of the combined constraint matrix A, computed via SVD:
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
A = U · Σ · Vᵀ
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
The nullspace is spanned by columns of V corresponding to zero singular values. The basis is further reduced to RREF form for clean, canonical coefficients.
|
|
280
|
+
|
|
281
|
+
## Output Format
|
|
282
|
+
|
|
283
|
+
Relations are output in LaTeX format with automatic index notation:
|
|
284
|
+
- For n ≤ 4: uses letters (x, y, z, w)
|
|
285
|
+
- For n > 4: uses numbers (1, 2, 3, ...)
|
|
286
|
+
|
|
287
|
+
Example output:
|
|
288
|
+
```
|
|
289
|
+
\sigma_{xxy} = \sigma_{xyx} = \sigma_{yxx} = -\sigma_{yyy}
|
|
290
|
+
\sigma_{xyz} = \sigma_{xzy} = -\sigma_{yxz} = -\sigma_{yzx}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Requirements
|
|
294
|
+
|
|
295
|
+
- Python ≥ 3.7
|
|
296
|
+
- NumPy ≥ 1.19.0
|
|
297
|
+
|
|
298
|
+
## License
|
|
299
|
+
|
|
300
|
+
MIT License
|
|
301
|
+
|
|
302
|
+
## Contributing
|
|
303
|
+
|
|
304
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
305
|
+
|
|
306
|
+
## Citation
|
|
307
|
+
|
|
308
|
+
If you use this library in your research, please cite:
|
|
309
|
+
|
|
310
|
+
```bibtex
|
|
311
|
+
@software{spintensor,
|
|
312
|
+
title = {SpinTensor: Linear Constraints for Tensors Under Transformations},
|
|
313
|
+
author = {Connor1y},
|
|
314
|
+
year = {2026},
|
|
315
|
+
url = {https://github.com/Connor1y/spintensor}
|
|
316
|
+
}
|
|
317
|
+
```
|