coordinate-system 7.0.0__cp313-cp313-win_amd64.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.
- coordinate_system/__init__.py +324 -0
- coordinate_system/complex_geometric_physics.py +519 -0
- coordinate_system/coordinate_system.cp313-win_amd64.pyd +0 -0
- coordinate_system/curve_interpolation.py +507 -0
- coordinate_system/differential_geometry.py +986 -0
- coordinate_system/spectral_geometry.py +1602 -0
- coordinate_system/u3_frame.py +885 -0
- coordinate_system/visualization.py +1069 -0
- coordinate_system-7.0.0.dist-info/LICENSE +9 -0
- coordinate_system-7.0.0.dist-info/METADATA +312 -0
- coordinate_system-7.0.0.dist-info/RECORD +13 -0
- coordinate_system-7.0.0.dist-info/WHEEL +5 -0
- coordinate_system-7.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1602 @@
|
|
|
1
|
+
"""
|
|
2
|
+
傅里叶标架场与希尔伯特空间谱几何 (Fourier Frame Field & Hilbert Space Spectral Geometry)
|
|
3
|
+
================================================================================
|
|
4
|
+
|
|
5
|
+
基于希尔伯特空间的傅里叶标架与谱分析框架。
|
|
6
|
+
|
|
7
|
+
核心思想:
|
|
8
|
+
- 傅里叶标架 = FourierFrame * e^{iθ} (相位旋转,傅里叶变换)
|
|
9
|
+
- 共形变换 = FourierFrame * λ (λ ∈ ℝ⁺, 缩放)
|
|
10
|
+
- 内禀梯度算子 G_μ = d/dx^μ log FourierFrame(x)
|
|
11
|
+
- 曲率 R_{μν} = [G_μ, G_ν]
|
|
12
|
+
- Berry相位 γ = ∮ G_μ dx^μ (几何相位,平行输运)
|
|
13
|
+
- 陈数 c₁ = (1/2π) ∬ R_{μν} dS (拓扑不变量)
|
|
14
|
+
|
|
15
|
+
数学框架:
|
|
16
|
+
- 希尔伯特空间:L²(M) 上的傅里叶分析
|
|
17
|
+
- 谱理论:拉普拉斯算子的本征值问题
|
|
18
|
+
- 纤维丛理论:FourierFrame 作为标架丛的局部截面
|
|
19
|
+
- 李群李代数:内禀梯度算子构成李代数
|
|
20
|
+
- 热核展开:几何不变量的提取
|
|
21
|
+
|
|
22
|
+
群论对应:
|
|
23
|
+
- FourierFrame ↔ GL(1,ℂ) = ℂ× = U(1) × ℝ⁺
|
|
24
|
+
- Phase e^{iθ} ↔ U(1) (单位圆)
|
|
25
|
+
- Magnitude |Q| ↔ ℝ⁺ (正实缩放)
|
|
26
|
+
|
|
27
|
+
Author: Quantum Frame Theory
|
|
28
|
+
Date: 2025-12-04
|
|
29
|
+
Version: 6.0.3
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
__version__ = '6.0.3'
|
|
33
|
+
|
|
34
|
+
import numpy as np
|
|
35
|
+
from typing import List, Tuple, Dict, Optional, Union, Any, Callable
|
|
36
|
+
from dataclasses import dataclass
|
|
37
|
+
import warnings
|
|
38
|
+
|
|
39
|
+
# 导入坐标系统
|
|
40
|
+
try:
|
|
41
|
+
from .coordinate_system import coord3, vec3, quat
|
|
42
|
+
except ImportError:
|
|
43
|
+
try:
|
|
44
|
+
from coordinate_system import coord3, vec3, quat
|
|
45
|
+
except ImportError:
|
|
46
|
+
# 延迟导入,允许独立使用
|
|
47
|
+
coord3 = None
|
|
48
|
+
vec3 = None
|
|
49
|
+
quat = None
|
|
50
|
+
|
|
51
|
+
# 物理常数
|
|
52
|
+
HBAR = 1.0 # 约化普朗克常数(自然单位)
|
|
53
|
+
|
|
54
|
+
# GPU 可用性检查
|
|
55
|
+
try:
|
|
56
|
+
import cupy as cp
|
|
57
|
+
import cupyx.scipy.fft as cufft
|
|
58
|
+
GPU_AVAILABLE = True
|
|
59
|
+
except ImportError:
|
|
60
|
+
GPU_AVAILABLE = False
|
|
61
|
+
cp = None
|
|
62
|
+
cufft = None
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# ============================================================
|
|
66
|
+
# 傅里叶标架代数 (Fourier Frame Algebra)
|
|
67
|
+
# ============================================================
|
|
68
|
+
|
|
69
|
+
class FourierFrame:
|
|
70
|
+
"""
|
|
71
|
+
傅里叶标架 - 希尔伯特空间上的频谱分析核心对象
|
|
72
|
+
|
|
73
|
+
数学结构:
|
|
74
|
+
-----------
|
|
75
|
+
FourierFrame 对应 GL(1,ℂ) = ℂ× = U(1) × ℝ⁺ 群
|
|
76
|
+
|
|
77
|
+
- Q ∈ ℂ× (非零复数)
|
|
78
|
+
- Q = |Q| · e^{iθ}
|
|
79
|
+
- Phase e^{iθ} ∈ U(1): 傅里叶变换(相位旋转)
|
|
80
|
+
- Magnitude |Q| ∈ ℝ⁺: 共形变换(缩放)
|
|
81
|
+
|
|
82
|
+
核心属性:
|
|
83
|
+
----------
|
|
84
|
+
- base_coord: 基础坐标系 (coord3 对象)
|
|
85
|
+
- Q: 复标度因子 Q ∈ ℂ×,编码相位与缩放
|
|
86
|
+
|
|
87
|
+
关键变换:
|
|
88
|
+
----------
|
|
89
|
+
- FourierFrame * e^{iθ} = 傅里叶变换 (θ=π/2 为标准 90° 旋转)
|
|
90
|
+
- FourierFrame * λ = 共形变换 (λ ∈ ℝ⁺,纯缩放)
|
|
91
|
+
- FourierFrame * FourierFrame = 标架复合
|
|
92
|
+
|
|
93
|
+
希尔伯特空间意义:
|
|
94
|
+
-----------------
|
|
95
|
+
- L²(M) 空间上的傅里叶基
|
|
96
|
+
- 内禀梯度算子 G_μ = d/dx^μ log Q(x)
|
|
97
|
+
- 谱分解:Δφ_n = -λ_n φ_n
|
|
98
|
+
- 热核:K(x,y,t) = Σ_n e^{-λ_n t} φ_n(x) φ_n*(y)
|
|
99
|
+
|
|
100
|
+
几何意义:
|
|
101
|
+
----------
|
|
102
|
+
- 作为标架丛 F(M) 的局部截面
|
|
103
|
+
- 内禀梯度算子 G_μ 描述局部旋转
|
|
104
|
+
- 曲率 R_{μν} = [G_μ, G_ν] 描述非交换性
|
|
105
|
+
- Berry 相位 γ = ∮ G_μ dx^μ (平行输运)
|
|
106
|
+
|
|
107
|
+
与 U3Frame 的关系:
|
|
108
|
+
------------------
|
|
109
|
+
- FourierFrame: GL(1,ℂ) 群,1个复数自由度
|
|
110
|
+
- U3Frame: U(3) 群,9个实自由度
|
|
111
|
+
- U(3) ⊃ U(1) as global phase subgroup
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
def __init__(self, base_coord=None, q_factor=1.0+0j):
|
|
115
|
+
"""
|
|
116
|
+
初始化傅里叶标架
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
base_coord: 基础坐标系 (coord3 对象),None 时使用单位标架
|
|
120
|
+
q_factor: 复标度因子 Q ∈ ℂ× = GL(1,ℂ)
|
|
121
|
+
Q = |Q| · e^{iθ}
|
|
122
|
+
- 相位 e^{iθ}: 傅里叶变换
|
|
123
|
+
- 模 |Q|: 共形缩放
|
|
124
|
+
"""
|
|
125
|
+
if base_coord is None:
|
|
126
|
+
if coord3 is not None:
|
|
127
|
+
self.base = coord3.identity()
|
|
128
|
+
else:
|
|
129
|
+
self.base = None
|
|
130
|
+
else:
|
|
131
|
+
self.base = base_coord
|
|
132
|
+
|
|
133
|
+
self.Q = complex(q_factor) # 确保是复数
|
|
134
|
+
self.dim = 3
|
|
135
|
+
|
|
136
|
+
# -------------------- 复标架属性 --------------------
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def o(self):
|
|
140
|
+
"""复位置向量"""
|
|
141
|
+
if self.base is None:
|
|
142
|
+
return None
|
|
143
|
+
o_base = self.base.o
|
|
144
|
+
# 复扩展:实部为原位置,虚部编码相位信息
|
|
145
|
+
return vec3(
|
|
146
|
+
o_base.x * self.Q.real + 1j * o_base.x * self.Q.imag,
|
|
147
|
+
o_base.y * self.Q.real + 1j * o_base.y * self.Q.imag,
|
|
148
|
+
o_base.z * self.Q.real + 1j * o_base.z * self.Q.imag
|
|
149
|
+
) if vec3 else None
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def s(self):
|
|
153
|
+
"""复缩放向量: s_Q = s_base · Q"""
|
|
154
|
+
if self.base is None:
|
|
155
|
+
return None
|
|
156
|
+
s_base = self.base.s
|
|
157
|
+
return vec3(
|
|
158
|
+
s_base.x * self.Q.real + 1j * s_base.x * self.Q.imag,
|
|
159
|
+
s_base.y * self.Q.real + 1j * s_base.y * self.Q.imag,
|
|
160
|
+
s_base.z * self.Q.real + 1j * s_base.z * self.Q.imag
|
|
161
|
+
) if vec3 else None
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def phase(self):
|
|
165
|
+
"""相位 arg(Q)"""
|
|
166
|
+
return np.angle(self.Q)
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def magnitude(self):
|
|
170
|
+
"""模 |Q|"""
|
|
171
|
+
return np.abs(self.Q)
|
|
172
|
+
|
|
173
|
+
@property
|
|
174
|
+
def det(self):
|
|
175
|
+
"""
|
|
176
|
+
行列式: Det(Frame)
|
|
177
|
+
|
|
178
|
+
用于路径积分测度 ∫ Dφ · Det[Frame] · exp(iS/ħ)
|
|
179
|
+
"""
|
|
180
|
+
if self.base is None:
|
|
181
|
+
return self.Q ** 3 # 3维标架
|
|
182
|
+
s = self.base.s
|
|
183
|
+
det_s = s.x * s.y * s.z
|
|
184
|
+
return det_s * (self.Q ** 3)
|
|
185
|
+
|
|
186
|
+
# -------------------- 标架运算 --------------------
|
|
187
|
+
|
|
188
|
+
def __mul__(self, other):
|
|
189
|
+
"""
|
|
190
|
+
标架乘法 - 核心变换操作
|
|
191
|
+
|
|
192
|
+
支持:
|
|
193
|
+
- Frame * complex: 相位旋转/缩放 (傅里叶/共形变换)
|
|
194
|
+
- Frame * Frame: 标架复合 (路径积分复合)
|
|
195
|
+
- Frame * vec3: 向量变换
|
|
196
|
+
"""
|
|
197
|
+
if isinstance(other, (int, float, complex)):
|
|
198
|
+
# 标量乘法实现傅里叶/共形变换
|
|
199
|
+
new_Q = self.Q * other
|
|
200
|
+
return FourierFrame(self.base, new_Q)
|
|
201
|
+
|
|
202
|
+
elif isinstance(other, FourierFrame):
|
|
203
|
+
# 标架复合
|
|
204
|
+
if self.base is not None and other.base is not None:
|
|
205
|
+
new_base = self.base * other.base
|
|
206
|
+
else:
|
|
207
|
+
new_base = self.base or other.base
|
|
208
|
+
new_Q = self.Q * other.Q
|
|
209
|
+
return FourierFrame(new_base, new_Q)
|
|
210
|
+
|
|
211
|
+
elif vec3 is not None and isinstance(other, vec3):
|
|
212
|
+
# 向量变换
|
|
213
|
+
return vec3(
|
|
214
|
+
other.x * self.Q.real,
|
|
215
|
+
other.y * self.Q.real,
|
|
216
|
+
other.z * self.Q.real
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
return NotImplemented
|
|
220
|
+
|
|
221
|
+
def __rmul__(self, other):
|
|
222
|
+
"""右乘法"""
|
|
223
|
+
return self.__mul__(other)
|
|
224
|
+
|
|
225
|
+
def __truediv__(self, other):
|
|
226
|
+
"""标架除法 - 逆变换"""
|
|
227
|
+
if isinstance(other, (int, float, complex)):
|
|
228
|
+
return FourierFrame(self.base, self.Q / other)
|
|
229
|
+
elif isinstance(other, FourierFrame):
|
|
230
|
+
if self.base is not None and other.base is not None:
|
|
231
|
+
new_base = self.base / other.base
|
|
232
|
+
else:
|
|
233
|
+
new_base = self.base
|
|
234
|
+
return FourierFrame(new_base, self.Q / other.Q)
|
|
235
|
+
return NotImplemented
|
|
236
|
+
|
|
237
|
+
def __pow__(self, n):
|
|
238
|
+
"""幂运算: 对应多次变换"""
|
|
239
|
+
if isinstance(n, (int, float, complex)):
|
|
240
|
+
return FourierFrame(self.base, self.Q ** n)
|
|
241
|
+
return NotImplemented
|
|
242
|
+
|
|
243
|
+
def __eq__(self, other):
|
|
244
|
+
"""相等比较"""
|
|
245
|
+
if not isinstance(other, FourierFrame):
|
|
246
|
+
return False
|
|
247
|
+
return np.isclose(self.Q, other.Q)
|
|
248
|
+
|
|
249
|
+
def __repr__(self):
|
|
250
|
+
if self.base is not None:
|
|
251
|
+
return f"FourierFrame(Q={self.Q:.4f}, o={self.base.o})"
|
|
252
|
+
return f"FourierFrame(Q={self.Q:.4f})"
|
|
253
|
+
|
|
254
|
+
# -------------------- 傅里叶变换 --------------------
|
|
255
|
+
|
|
256
|
+
def fourier_transform(self, theta: float = np.pi/2) -> 'FourierFrame':
|
|
257
|
+
"""
|
|
258
|
+
傅里叶变换: F_θ[FourierFrame] = FourierFrame · e^{iθ}
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
theta: 旋转角度,π/2 为标准傅里叶变换
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
变换后的 FourierFrame
|
|
265
|
+
|
|
266
|
+
性质:
|
|
267
|
+
- F^4 = I (四次变换回到自身)
|
|
268
|
+
- F^2 = P (宇称变换)
|
|
269
|
+
"""
|
|
270
|
+
ft_factor = np.exp(1j * theta)
|
|
271
|
+
return self * ft_factor
|
|
272
|
+
|
|
273
|
+
def inverse_fourier_transform(self, theta: float = np.pi/2) -> 'FourierFrame':
|
|
274
|
+
"""逆傅里叶变换: F^{-1} = F_{-θ}"""
|
|
275
|
+
return self.fourier_transform(-theta)
|
|
276
|
+
|
|
277
|
+
def conformal_transform(self, lambda_factor: float) -> 'FourierFrame':
|
|
278
|
+
"""
|
|
279
|
+
共形变换: FourierFrame → FourierFrame · λ, λ ∈ ℝ⁺
|
|
280
|
+
|
|
281
|
+
实现缩放变换,保持角度不变
|
|
282
|
+
"""
|
|
283
|
+
return self * lambda_factor
|
|
284
|
+
|
|
285
|
+
# -------------------- 经典几何演化 --------------------
|
|
286
|
+
|
|
287
|
+
def diffusion_evolution(self, t: float, kappa: float = 1.0) -> 'FourierFrame':
|
|
288
|
+
"""
|
|
289
|
+
扩散演化算子: e^{tΔ} FourierFrame
|
|
290
|
+
|
|
291
|
+
这是经典热方程 ∂u/∂t = κΔu 的解算子,其中:
|
|
292
|
+
- Δ 是拉普拉斯算子(几何扩散算子)
|
|
293
|
+
- t 是时间参数(实时间,非虚时间)
|
|
294
|
+
- κ 是扩散系数
|
|
295
|
+
|
|
296
|
+
数学形式:
|
|
297
|
+
FourierFrame(x, t) = e^{tκΔ} FourierFrame(x, 0)
|
|
298
|
+
= FourierFrame₀ · e^{-tκ|k|²} (动量空间)
|
|
299
|
+
|
|
300
|
+
物理意义:
|
|
301
|
+
- 描述几何信息在流形上的扩散过程
|
|
302
|
+
- 热核作为基本解:K(x,y,t) = (4πκt)^{-d/2} e^{-|x-y|²/(4κt)}
|
|
303
|
+
- 谱几何中的核心工具,用于提取流形的几何不变量
|
|
304
|
+
|
|
305
|
+
注意:这是**经典几何**的扩散过程,与量子力学的虚时间演化
|
|
306
|
+
在形式上类似,但物理意义完全不同。
|
|
307
|
+
|
|
308
|
+
Args:
|
|
309
|
+
t: 扩散时间(必须 > 0)
|
|
310
|
+
kappa: 扩散系数(默认1.0)
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
扩散演化后的FourierFrame
|
|
314
|
+
|
|
315
|
+
局限性:
|
|
316
|
+
- 简化实现:仅对标度因子Q进行扩散
|
|
317
|
+
- 完整实现需要在标架场上定义拉普拉斯算子
|
|
318
|
+
- 数值实现受网格分辨率限制
|
|
319
|
+
"""
|
|
320
|
+
if t < 0:
|
|
321
|
+
raise ValueError("扩散时间t必须非负")
|
|
322
|
+
|
|
323
|
+
# 简化模型:对Q因子进行衰减(高频抑制)
|
|
324
|
+
# 完整实现需要在标架场的频谱表示中进行
|
|
325
|
+
decay_factor = np.exp(-kappa * t * np.abs(self.Q)**2)
|
|
326
|
+
evolved_Q = self.Q * decay_factor
|
|
327
|
+
|
|
328
|
+
return FourierFrame(self.base, evolved_Q)
|
|
329
|
+
|
|
330
|
+
@staticmethod
|
|
331
|
+
def laplacian_from_field(frame_field: List[List['FourierFrame']],
|
|
332
|
+
i: int, j: int) -> complex:
|
|
333
|
+
"""
|
|
334
|
+
从离散标架场计算拉普拉斯算子
|
|
335
|
+
|
|
336
|
+
Δ log FourierFrame ≈ (∇² log FourierFrame)
|
|
337
|
+
= ∂²/∂x² log Q + ∂²/∂y² log Q
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
frame_field: 离散标架场
|
|
341
|
+
i, j: 网格位置
|
|
342
|
+
|
|
343
|
+
Returns:
|
|
344
|
+
拉普拉斯算子作用结果(复数)
|
|
345
|
+
|
|
346
|
+
数学细节:
|
|
347
|
+
使用五点差分模板计算二阶导数:
|
|
348
|
+
Δf ≈ [f(i+1,j) + f(i-1,j) + f(i,j+1) + f(i,j-1) - 4f(i,j)] / h²
|
|
349
|
+
"""
|
|
350
|
+
ny, nx = len(frame_field), len(frame_field[0])
|
|
351
|
+
|
|
352
|
+
if i <= 0 or i >= ny - 1 or j <= 0 or j >= nx - 1:
|
|
353
|
+
return 0.0 + 0j
|
|
354
|
+
|
|
355
|
+
# 中心点
|
|
356
|
+
log_Q_center = np.log(frame_field[i][j].Q)
|
|
357
|
+
|
|
358
|
+
# 四个邻居
|
|
359
|
+
log_Q_xp = np.log(frame_field[i][j+1].Q)
|
|
360
|
+
log_Q_xm = np.log(frame_field[i][j-1].Q)
|
|
361
|
+
log_Q_yp = np.log(frame_field[i+1][j].Q)
|
|
362
|
+
log_Q_ym = np.log(frame_field[i-1][j].Q)
|
|
363
|
+
|
|
364
|
+
# 五点拉普拉斯模板(假设网格间距h=1)
|
|
365
|
+
laplacian = (log_Q_xp + log_Q_xm + log_Q_yp + log_Q_ym - 4*log_Q_center)
|
|
366
|
+
|
|
367
|
+
return laplacian
|
|
368
|
+
|
|
369
|
+
# -------------------- 谱变换 --------------------
|
|
370
|
+
|
|
371
|
+
@staticmethod
|
|
372
|
+
def spectral_transform_2d(field: np.ndarray, hbar: float = HBAR) -> np.ndarray:
|
|
373
|
+
"""
|
|
374
|
+
二维谱变换:位置空间 → 动量空间
|
|
375
|
+
|
|
376
|
+
数学形式:
|
|
377
|
+
ψ̃(k) = ∫ e^{ikx/ħ} ψ(x) dx / √(2πħ)
|
|
378
|
+
|
|
379
|
+
Args:
|
|
380
|
+
field: 输入场,形状 [ny, nx, ...] 或 [ny, nx]
|
|
381
|
+
hbar: 约化普朗克常数
|
|
382
|
+
|
|
383
|
+
Returns:
|
|
384
|
+
动量空间谱
|
|
385
|
+
"""
|
|
386
|
+
# 确定 FFT 的轴
|
|
387
|
+
if field.ndim >= 2:
|
|
388
|
+
axes = (0, 1)
|
|
389
|
+
else:
|
|
390
|
+
axes = None
|
|
391
|
+
|
|
392
|
+
spectrum = np.fft.fft2(field, axes=axes)
|
|
393
|
+
|
|
394
|
+
# 量子力学归一化
|
|
395
|
+
normalization = 1.0 / np.sqrt(2 * np.pi * hbar)
|
|
396
|
+
return spectrum * normalization
|
|
397
|
+
|
|
398
|
+
@staticmethod
|
|
399
|
+
def inverse_spectral_transform_2d(spectrum: np.ndarray, hbar: float = HBAR) -> np.ndarray:
|
|
400
|
+
"""
|
|
401
|
+
二维逆谱变换:动量空间 → 位置空间
|
|
402
|
+
|
|
403
|
+
Args:
|
|
404
|
+
spectrum: 动量空间谱
|
|
405
|
+
hbar: 约化普朗克常数
|
|
406
|
+
|
|
407
|
+
Returns:
|
|
408
|
+
位置空间场
|
|
409
|
+
"""
|
|
410
|
+
if spectrum.ndim >= 2:
|
|
411
|
+
axes = (0, 1)
|
|
412
|
+
else:
|
|
413
|
+
axes = None
|
|
414
|
+
|
|
415
|
+
denormalization = np.sqrt(2 * np.pi * hbar)
|
|
416
|
+
return np.fft.ifft2(spectrum * denormalization, axes=axes).real
|
|
417
|
+
|
|
418
|
+
@staticmethod
|
|
419
|
+
def spectral_transform_2d_gpu(field: np.ndarray, hbar: float = HBAR) -> np.ndarray:
|
|
420
|
+
"""GPU 加速的二维谱变换"""
|
|
421
|
+
if not GPU_AVAILABLE:
|
|
422
|
+
raise RuntimeError("CuPy 不可用,无法使用 GPU 加速")
|
|
423
|
+
|
|
424
|
+
field_gpu = cp.asarray(field)
|
|
425
|
+
spectrum_gpu = cufft.fft2(field_gpu, axes=(0, 1))
|
|
426
|
+
normalization = 1.0 / np.sqrt(2 * np.pi * hbar)
|
|
427
|
+
spectrum_gpu *= normalization
|
|
428
|
+
return cp.asnumpy(spectrum_gpu)
|
|
429
|
+
|
|
430
|
+
@classmethod
|
|
431
|
+
def from_coord_field(cls, coord_field: List[List], hbar: float = HBAR) -> 'FourierFrameSpectrum':
|
|
432
|
+
"""
|
|
433
|
+
从坐标场创建谱表示
|
|
434
|
+
|
|
435
|
+
将坐标场的各分量进行谱变换
|
|
436
|
+
|
|
437
|
+
Args:
|
|
438
|
+
coord_field: 二维坐标场列表 [[coord3, ...], ...]
|
|
439
|
+
hbar: 约化普朗克常数
|
|
440
|
+
|
|
441
|
+
Returns:
|
|
442
|
+
FourierFrameSpectrum 对象
|
|
443
|
+
"""
|
|
444
|
+
ny = len(coord_field)
|
|
445
|
+
nx = len(coord_field[0]) if ny > 0 else 0
|
|
446
|
+
|
|
447
|
+
# 提取场分量
|
|
448
|
+
tensor_field = np.zeros((ny, nx, 12), dtype=np.float64)
|
|
449
|
+
for i in range(ny):
|
|
450
|
+
for j in range(nx):
|
|
451
|
+
coord = coord_field[i][j]
|
|
452
|
+
tensor_field[i, j, 0:3] = [coord.o.x, coord.o.y, coord.o.z]
|
|
453
|
+
tensor_field[i, j, 3:6] = [coord.ux.x, coord.ux.y, coord.ux.z]
|
|
454
|
+
tensor_field[i, j, 6:9] = [coord.uy.x, coord.uy.y, coord.uy.z]
|
|
455
|
+
tensor_field[i, j, 9:12] = [coord.uz.x, coord.uz.y, coord.uz.z]
|
|
456
|
+
|
|
457
|
+
# 谱变换各分量
|
|
458
|
+
origin_spectrum = cls.spectral_transform_2d(tensor_field[..., 0:3], hbar)
|
|
459
|
+
ux_spectrum = cls.spectral_transform_2d(tensor_field[..., 3:6], hbar)
|
|
460
|
+
uy_spectrum = cls.spectral_transform_2d(tensor_field[..., 6:9], hbar)
|
|
461
|
+
uz_spectrum = cls.spectral_transform_2d(tensor_field[..., 9:12], hbar)
|
|
462
|
+
|
|
463
|
+
# 动量网格
|
|
464
|
+
kx = 2 * np.pi * np.fft.fftfreq(nx) / hbar
|
|
465
|
+
ky = 2 * np.pi * np.fft.fftfreq(ny) / hbar
|
|
466
|
+
|
|
467
|
+
return FourierFrameSpectrum(
|
|
468
|
+
ux_spectrum=ux_spectrum,
|
|
469
|
+
uy_spectrum=uy_spectrum,
|
|
470
|
+
uz_spectrum=uz_spectrum,
|
|
471
|
+
origin_spectrum=origin_spectrum,
|
|
472
|
+
momentum_grid=(kx, ky),
|
|
473
|
+
hbar=hbar
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
# ============================================================
|
|
478
|
+
# 内禀梯度算子 (Intrinsic Gradient Operator)
|
|
479
|
+
# ============================================================
|
|
480
|
+
|
|
481
|
+
class IntrinsicGradient:
|
|
482
|
+
"""
|
|
483
|
+
内禀梯度算子 G_μ = d/dx^μ log FourierFrame(x)
|
|
484
|
+
|
|
485
|
+
几何意义(经典谱几何视角):
|
|
486
|
+
- 描述标架的局部旋转速率(协变导数的对数形式)
|
|
487
|
+
- 对应黎曼几何中的联络1-形式
|
|
488
|
+
- 非交换性 [G_μ, G_ν] 直接给出曲率张量
|
|
489
|
+
|
|
490
|
+
数学性质:
|
|
491
|
+
- δFourierFrame = G_μ FourierFrame δx^μ (无穷小变换)
|
|
492
|
+
- [G_μ, G_ν] = R_{μν} (曲率2-形式)
|
|
493
|
+
- γ = ∮ G_μ dx^μ (几何相位 - parallel transport)
|
|
494
|
+
- Δ = ∇² = ∂_μ ∂^μ (拉普拉斯算子)
|
|
495
|
+
|
|
496
|
+
与量子理论的关系:
|
|
497
|
+
- 形式上类似规范场论中的联络,但这里是**纯几何对象**
|
|
498
|
+
- Berry相位在这里是经典几何相位(平行输运),非量子效应
|
|
499
|
+
- 该理论完全在经典微分几何框架内
|
|
500
|
+
"""
|
|
501
|
+
|
|
502
|
+
def __init__(self, frame_field: Union[Callable, List[List['FourierFrame']]]):
|
|
503
|
+
"""
|
|
504
|
+
初始化内禀梯度算子
|
|
505
|
+
|
|
506
|
+
Args:
|
|
507
|
+
frame_field: 标架场,可以是函数或离散场
|
|
508
|
+
"""
|
|
509
|
+
self.frame_field = frame_field
|
|
510
|
+
self.is_discrete = isinstance(frame_field, list)
|
|
511
|
+
|
|
512
|
+
def compute_at(self, position: Union[Tuple, int],
|
|
513
|
+
direction: int, delta: float = 1e-5) -> complex:
|
|
514
|
+
"""
|
|
515
|
+
计算指定位置和方向的内禀梯度
|
|
516
|
+
|
|
517
|
+
Args:
|
|
518
|
+
position: 位置坐标 (连续) 或索引 (离散)
|
|
519
|
+
direction: 方向索引 (0=x, 1=y, 2=z)
|
|
520
|
+
delta: 有限差分步长
|
|
521
|
+
|
|
522
|
+
Returns:
|
|
523
|
+
G_μ 的复数值
|
|
524
|
+
"""
|
|
525
|
+
if self.is_discrete:
|
|
526
|
+
return self._compute_discrete(position, direction)
|
|
527
|
+
else:
|
|
528
|
+
return self._compute_continuous(position, direction, delta)
|
|
529
|
+
|
|
530
|
+
def _compute_discrete(self, idx: Tuple[int, int], direction: int) -> complex:
|
|
531
|
+
"""离散场的内禀梯度"""
|
|
532
|
+
i, j = idx
|
|
533
|
+
ny, nx = len(self.frame_field), len(self.frame_field[0])
|
|
534
|
+
|
|
535
|
+
# 中心差分
|
|
536
|
+
if direction == 0: # x方向
|
|
537
|
+
if j + 1 < nx and j - 1 >= 0:
|
|
538
|
+
frame_forward = self.frame_field[i][j + 1]
|
|
539
|
+
frame_backward = self.frame_field[i][j - 1]
|
|
540
|
+
frame_center = self.frame_field[i][j]
|
|
541
|
+
|
|
542
|
+
# G_x ≈ (log Q_{j+1} - log Q_{j-1}) / 2
|
|
543
|
+
return (np.log(frame_forward.Q) - np.log(frame_backward.Q)) / 2.0
|
|
544
|
+
|
|
545
|
+
elif direction == 1: # y方向
|
|
546
|
+
if i + 1 < ny and i - 1 >= 0:
|
|
547
|
+
frame_forward = self.frame_field[i + 1][j]
|
|
548
|
+
frame_backward = self.frame_field[i - 1][j]
|
|
549
|
+
|
|
550
|
+
return (np.log(frame_forward.Q) - np.log(frame_backward.Q)) / 2.0
|
|
551
|
+
|
|
552
|
+
return 0.0 + 0j
|
|
553
|
+
|
|
554
|
+
def _compute_continuous(self, pos: Tuple, direction: int, delta: float) -> complex:
|
|
555
|
+
"""连续场的内禀梯度"""
|
|
556
|
+
pos_list = list(pos)
|
|
557
|
+
|
|
558
|
+
# 前向和后向位置
|
|
559
|
+
pos_forward = pos_list.copy()
|
|
560
|
+
pos_backward = pos_list.copy()
|
|
561
|
+
pos_forward[direction] += delta
|
|
562
|
+
pos_backward[direction] -= delta
|
|
563
|
+
|
|
564
|
+
frame_forward = self.frame_field(tuple(pos_forward))
|
|
565
|
+
frame_backward = self.frame_field(tuple(pos_backward))
|
|
566
|
+
|
|
567
|
+
# G_μ = d/dx^μ log Frame
|
|
568
|
+
return (np.log(frame_forward.Q) - np.log(frame_backward.Q)) / (2 * delta)
|
|
569
|
+
|
|
570
|
+
def commutator(self, pos: Union[Tuple, int],
|
|
571
|
+
dir1: int, dir2: int, delta: float = 1e-5) -> complex:
|
|
572
|
+
"""
|
|
573
|
+
计算李括号 [G_μ, G_ν] = 曲率 R_{μν}
|
|
574
|
+
|
|
575
|
+
Args:
|
|
576
|
+
pos: 位置
|
|
577
|
+
dir1, dir2: 两个方向索引
|
|
578
|
+
delta: 有限差分步长
|
|
579
|
+
|
|
580
|
+
Returns:
|
|
581
|
+
曲率分量 R_{μν}
|
|
582
|
+
"""
|
|
583
|
+
G_mu = self.compute_at(pos, dir1, delta)
|
|
584
|
+
G_nu = self.compute_at(pos, dir2, delta)
|
|
585
|
+
|
|
586
|
+
# 简化版本:[G_μ, G_ν] ≈ G_μ G_ν - G_ν G_μ
|
|
587
|
+
# 对于阿贝尔情况(标量Q),交换子为0
|
|
588
|
+
# 完整实现需要考虑标架场的非阿贝尔结构
|
|
589
|
+
return G_mu * G_nu - G_nu * G_mu
|
|
590
|
+
|
|
591
|
+
def laplacian(self, position: Union[Tuple[int, int], int]) -> complex:
|
|
592
|
+
"""
|
|
593
|
+
拉普拉斯算子 Δ = ∇² = ∂²/∂x² + ∂²/∂y²
|
|
594
|
+
|
|
595
|
+
作用于 log FourierFrame:
|
|
596
|
+
Δ log FourierFrame = ∂²/∂x² log Q + ∂²/∂y² log Q
|
|
597
|
+
|
|
598
|
+
这是谱几何的核心算子,其本征值问题:
|
|
599
|
+
Δφ_n = -λ_n φ_n
|
|
600
|
+
|
|
601
|
+
定义了流形的谱(spectrum),从而编码几何信息。
|
|
602
|
+
|
|
603
|
+
Args:
|
|
604
|
+
position: 网格位置 (i, j) 或索引
|
|
605
|
+
|
|
606
|
+
Returns:
|
|
607
|
+
拉普拉斯算子作用结果
|
|
608
|
+
|
|
609
|
+
数学背景:
|
|
610
|
+
- 拉普拉斯算子是黎曼流形上的自然微分算子
|
|
611
|
+
- 其谱{λ_n}包含流形的几何不变量(Weyl律、热核展开)
|
|
612
|
+
- "Can one hear the shape of a drum?" - Kac's问题
|
|
613
|
+
"""
|
|
614
|
+
if not self.is_discrete:
|
|
615
|
+
raise NotImplementedError("连续场的拉普拉斯算子需要额外实现")
|
|
616
|
+
|
|
617
|
+
if isinstance(position, int):
|
|
618
|
+
# 1D情况(简化)
|
|
619
|
+
return 0.0 + 0j
|
|
620
|
+
|
|
621
|
+
# 使用FourierFrame的静态方法
|
|
622
|
+
return FourierFrame.laplacian_from_field(self.frame_field, position[0], position[1])
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
# ============================================================
|
|
626
|
+
# 曲率计算 (Curvature from Frames)
|
|
627
|
+
# ============================================================
|
|
628
|
+
|
|
629
|
+
class CurvatureFromFrame:
|
|
630
|
+
"""
|
|
631
|
+
从标架场计算曲率
|
|
632
|
+
|
|
633
|
+
核心公式:
|
|
634
|
+
- R_{μν} = [G_μ, G_ν] = ∂_μ G_ν - ∂_ν G_μ - [G_μ, G_ν]
|
|
635
|
+
- 高斯曲率 K = -⟨[G_u, G_v] e_v, e_u⟩ / √det(g)
|
|
636
|
+
- 平均曲率 H = (1/2) Tr(R)
|
|
637
|
+
"""
|
|
638
|
+
|
|
639
|
+
def __init__(self, frame_field: List[List['FourierFrame']]):
|
|
640
|
+
"""
|
|
641
|
+
初始化曲率计算器
|
|
642
|
+
|
|
643
|
+
Args:
|
|
644
|
+
frame_field: 离散标架场
|
|
645
|
+
"""
|
|
646
|
+
self.frame_field = frame_field
|
|
647
|
+
self.gradient_op = IntrinsicGradient(frame_field)
|
|
648
|
+
self.ny = len(frame_field)
|
|
649
|
+
self.nx = len(frame_field[0]) if self.ny > 0 else 0
|
|
650
|
+
|
|
651
|
+
def gaussian_curvature(self, i: int, j: int) -> float:
|
|
652
|
+
"""
|
|
653
|
+
计算高斯曲率
|
|
654
|
+
|
|
655
|
+
K = -⟨[G_u, G_v] e_v, e_u⟩ / √det(g)
|
|
656
|
+
|
|
657
|
+
Args:
|
|
658
|
+
i, j: 网格索引
|
|
659
|
+
|
|
660
|
+
Returns:
|
|
661
|
+
高斯曲率值
|
|
662
|
+
"""
|
|
663
|
+
# 计算李括号 [G_x, G_y]
|
|
664
|
+
R_xy = self.gradient_op.commutator((i, j), 0, 1)
|
|
665
|
+
|
|
666
|
+
# 简化版本:K ≈ -Im(R_xy) (对于复标架)
|
|
667
|
+
# 完整实现需要计算度量张量
|
|
668
|
+
return -R_xy.imag
|
|
669
|
+
|
|
670
|
+
def mean_curvature(self, i: int, j: int) -> float:
|
|
671
|
+
"""
|
|
672
|
+
计算平均曲率
|
|
673
|
+
|
|
674
|
+
H = (1/2) Tr(R)
|
|
675
|
+
|
|
676
|
+
Args:
|
|
677
|
+
i, j: 网格索引
|
|
678
|
+
|
|
679
|
+
Returns:
|
|
680
|
+
平均曲率值
|
|
681
|
+
"""
|
|
682
|
+
# 简化实现
|
|
683
|
+
R_xx = self.gradient_op.commutator((i, j), 0, 0)
|
|
684
|
+
R_yy = self.gradient_op.commutator((i, j), 1, 1)
|
|
685
|
+
|
|
686
|
+
return 0.5 * (R_xx.real + R_yy.real)
|
|
687
|
+
|
|
688
|
+
def riemann_curvature_tensor(self, i: int, j: int) -> np.ndarray:
|
|
689
|
+
"""
|
|
690
|
+
计算黎曼曲率张量
|
|
691
|
+
|
|
692
|
+
R_{ijkl} = -√det(g) ⟨[G_i, G_j] e_l, e_k⟩
|
|
693
|
+
|
|
694
|
+
Args:
|
|
695
|
+
i, j: 网格索引
|
|
696
|
+
|
|
697
|
+
Returns:
|
|
698
|
+
曲率张量 (2x2 矩阵,简化2D情况)
|
|
699
|
+
"""
|
|
700
|
+
R = np.zeros((2, 2), dtype=complex)
|
|
701
|
+
|
|
702
|
+
R[0, 0] = self.gradient_op.commutator((i, j), 0, 0)
|
|
703
|
+
R[0, 1] = self.gradient_op.commutator((i, j), 0, 1)
|
|
704
|
+
R[1, 0] = self.gradient_op.commutator((i, j), 1, 0)
|
|
705
|
+
R[1, 1] = self.gradient_op.commutator((i, j), 1, 1)
|
|
706
|
+
|
|
707
|
+
return R
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
# ============================================================
|
|
711
|
+
# 几何相位 (Geometric Phase)
|
|
712
|
+
# ============================================================
|
|
713
|
+
|
|
714
|
+
class BerryPhase:
|
|
715
|
+
"""
|
|
716
|
+
Berry相位计算
|
|
717
|
+
|
|
718
|
+
几何相位公式:
|
|
719
|
+
γ = ∮_C G_μ dx^μ = ∮_C (∂_μ Frame · Frame^{-1}) dx^μ
|
|
720
|
+
|
|
721
|
+
性质:
|
|
722
|
+
- 与路径参数化无关
|
|
723
|
+
- 仅依赖于路径的几何形状
|
|
724
|
+
- 对应曲率的面积分(Stokes定理)
|
|
725
|
+
"""
|
|
726
|
+
|
|
727
|
+
def __init__(self, gradient_operator: IntrinsicGradient):
|
|
728
|
+
"""
|
|
729
|
+
初始化Berry相位计算器
|
|
730
|
+
|
|
731
|
+
Args:
|
|
732
|
+
gradient_operator: 内禀梯度算子
|
|
733
|
+
"""
|
|
734
|
+
self.gradient_op = gradient_operator
|
|
735
|
+
|
|
736
|
+
def compute_along_path(self, path: List[Tuple], closed: bool = True) -> complex:
|
|
737
|
+
"""
|
|
738
|
+
沿路径计算Berry相位
|
|
739
|
+
|
|
740
|
+
γ = ∮_C G_μ dx^μ
|
|
741
|
+
|
|
742
|
+
Args:
|
|
743
|
+
path: 路径点列表 [(i1, j1), (i2, j2), ...]
|
|
744
|
+
closed: 是否闭合路径
|
|
745
|
+
|
|
746
|
+
Returns:
|
|
747
|
+
几何相位(复数)
|
|
748
|
+
"""
|
|
749
|
+
if len(path) < 2:
|
|
750
|
+
return 0.0 + 0j
|
|
751
|
+
|
|
752
|
+
phase = 0.0 + 0j
|
|
753
|
+
|
|
754
|
+
for k in range(len(path) - 1):
|
|
755
|
+
pos_current = path[k]
|
|
756
|
+
pos_next = path[k + 1]
|
|
757
|
+
|
|
758
|
+
# 确定方向
|
|
759
|
+
dx = pos_next[0] - pos_current[0]
|
|
760
|
+
dy = pos_next[1] - pos_current[1]
|
|
761
|
+
|
|
762
|
+
# 计算梯度分量
|
|
763
|
+
if abs(dx) > abs(dy):
|
|
764
|
+
direction = 0 # x方向
|
|
765
|
+
step = dx
|
|
766
|
+
else:
|
|
767
|
+
direction = 1 # y方向
|
|
768
|
+
step = dy
|
|
769
|
+
|
|
770
|
+
# G_μ dx^μ
|
|
771
|
+
G_mu = self.gradient_op.compute_at(pos_current, direction)
|
|
772
|
+
phase += G_mu * step
|
|
773
|
+
|
|
774
|
+
# 闭合路径
|
|
775
|
+
if closed and len(path) > 2:
|
|
776
|
+
pos_last = path[-1]
|
|
777
|
+
pos_first = path[0]
|
|
778
|
+
|
|
779
|
+
dx = pos_first[0] - pos_last[0]
|
|
780
|
+
dy = pos_first[1] - pos_last[1]
|
|
781
|
+
|
|
782
|
+
if abs(dx) > abs(dy):
|
|
783
|
+
direction = 0
|
|
784
|
+
step = dx
|
|
785
|
+
else:
|
|
786
|
+
direction = 1
|
|
787
|
+
step = dy
|
|
788
|
+
|
|
789
|
+
G_mu = self.gradient_op.compute_at(pos_last, direction)
|
|
790
|
+
phase += G_mu * step
|
|
791
|
+
|
|
792
|
+
return phase
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
# ============================================================
|
|
796
|
+
# 陈数 (Chern Number)
|
|
797
|
+
# ============================================================
|
|
798
|
+
|
|
799
|
+
class ChernNumber:
|
|
800
|
+
"""
|
|
801
|
+
第一陈数计算
|
|
802
|
+
|
|
803
|
+
拓扑不变量:
|
|
804
|
+
c₁ = (1/2π) ∬_M R_{μν} dS^{μν}
|
|
805
|
+
= (1/2π) ∬_M Tr([G_μ, G_ν]) dS^{μν}
|
|
806
|
+
|
|
807
|
+
物理意义:
|
|
808
|
+
- 刻画纤维丛的拓扑性质
|
|
809
|
+
- 量子霍尔效应中的拓扑不变量
|
|
810
|
+
- 与Berry相位的关联(Stokes定理)
|
|
811
|
+
"""
|
|
812
|
+
|
|
813
|
+
def __init__(self, curvature_calculator: CurvatureFromFrame):
|
|
814
|
+
"""
|
|
815
|
+
初始化陈数计算器
|
|
816
|
+
|
|
817
|
+
Args:
|
|
818
|
+
curvature_calculator: 曲率计算器
|
|
819
|
+
"""
|
|
820
|
+
self.curvature = curvature_calculator
|
|
821
|
+
|
|
822
|
+
def compute(self) -> float:
|
|
823
|
+
"""
|
|
824
|
+
计算第一陈数
|
|
825
|
+
|
|
826
|
+
c₁ = (1/2π) Σ_{ij} R_{xy}(i,j) ΔS
|
|
827
|
+
|
|
828
|
+
Returns:
|
|
829
|
+
陈数(实数)
|
|
830
|
+
"""
|
|
831
|
+
total = 0.0 + 0j
|
|
832
|
+
|
|
833
|
+
ny, nx = self.curvature.ny, self.curvature.nx
|
|
834
|
+
|
|
835
|
+
for i in range(1, ny - 1):
|
|
836
|
+
for j in range(1, nx - 1):
|
|
837
|
+
# 曲率 R_{xy}
|
|
838
|
+
R_xy = self.curvature.gradient_op.commutator((i, j), 0, 1)
|
|
839
|
+
total += R_xy
|
|
840
|
+
|
|
841
|
+
# 归一化
|
|
842
|
+
c1 = total / (2 * np.pi)
|
|
843
|
+
|
|
844
|
+
# 陈数应为整数(拓扑不变量)
|
|
845
|
+
return round(c1.real)
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
# ============================================================
|
|
849
|
+
# 谱分解 (Spectral Decomposition)
|
|
850
|
+
# ============================================================
|
|
851
|
+
|
|
852
|
+
class SpectralDecomposition:
|
|
853
|
+
"""
|
|
854
|
+
拉普拉斯算子的谱分解(经典几何谱理论)
|
|
855
|
+
|
|
856
|
+
数学框架:
|
|
857
|
+
拉普拉斯本征值问题:
|
|
858
|
+
Δφ_n = -λ_n φ_n
|
|
859
|
+
∫ φ_m φ_n dV = δ_{mn}
|
|
860
|
+
|
|
861
|
+
谱分解定理:
|
|
862
|
+
Δ = -Σ_n λ_n |φ_n⟩⟨φ_n|
|
|
863
|
+
|
|
864
|
+
**FourierFrame作为本征态基础**:
|
|
865
|
+
在我们的框架中,FourierFrame场可展开为本征态的叠加:
|
|
866
|
+
|
|
867
|
+
FourierFrame(x) = Σ_n c_n φ_n(x) FourierFrame_n
|
|
868
|
+
|
|
869
|
+
其中:
|
|
870
|
+
- φ_n(x) 是拉普拉斯算子的标量本征函数
|
|
871
|
+
- FourierFrame_n 是对应的标架本征态
|
|
872
|
+
- c_n = ⟨φ_n | FourierFrame⟩ 是展开系数
|
|
873
|
+
|
|
874
|
+
谱的几何意义:
|
|
875
|
+
- {λ_n} 编码流形的几何信息(形状DNA)
|
|
876
|
+
- 低频模式(小λ)对应大尺度几何特征
|
|
877
|
+
- 高频模式(大λ)对应局部细节
|
|
878
|
+
|
|
879
|
+
Weyl渐近律:
|
|
880
|
+
N(λ) ~ (ω_d / (2π)^d) Vol(M) λ^{d/2}
|
|
881
|
+
|
|
882
|
+
其中 N(λ) 是小于λ的本征值个数。
|
|
883
|
+
|
|
884
|
+
应用:
|
|
885
|
+
- ShapeDNA:谱签名用于形状识别
|
|
886
|
+
- 谱距离:流形间的几何距离度量
|
|
887
|
+
- 多尺度分析:不同频段的几何特征
|
|
888
|
+
- 热核展开:Tr(e^{tΔ}) = Σ_n e^{-tλ_n}
|
|
889
|
+
"""
|
|
890
|
+
|
|
891
|
+
def __init__(self, frame_field: Union[List[List['FourierFrame']], 'FourierFrameSpectrum']):
|
|
892
|
+
"""
|
|
893
|
+
初始化谱分解
|
|
894
|
+
|
|
895
|
+
Args:
|
|
896
|
+
frame_field: FourierFrame场或其频谱表示
|
|
897
|
+
"""
|
|
898
|
+
if isinstance(frame_field, list):
|
|
899
|
+
# 离散标架场
|
|
900
|
+
self.frame_field = frame_field
|
|
901
|
+
self.gradient_op = IntrinsicGradient(frame_field)
|
|
902
|
+
self.ny = len(frame_field)
|
|
903
|
+
self.nx = len(frame_field[0]) if self.ny > 0 else 0
|
|
904
|
+
self.spectrum = None
|
|
905
|
+
else:
|
|
906
|
+
# 频谱表示
|
|
907
|
+
self.spectrum = frame_field
|
|
908
|
+
self.frame_field = None
|
|
909
|
+
self.gradient_op = None
|
|
910
|
+
self.ny, self.nx = frame_field.shape
|
|
911
|
+
|
|
912
|
+
self._eigenvalues = None
|
|
913
|
+
self._eigenvectors = None
|
|
914
|
+
|
|
915
|
+
def compute_eigenspectrum(self) -> Tuple[np.ndarray, Optional[np.ndarray]]:
|
|
916
|
+
"""
|
|
917
|
+
计算拉普拉斯算子的本征谱
|
|
918
|
+
|
|
919
|
+
Returns:
|
|
920
|
+
(eigenvalues, eigenvectors)
|
|
921
|
+
- eigenvalues: λ_n 数组(降序排列)
|
|
922
|
+
- eigenvectors: 本征函数φ_n(简化实现可能为None)
|
|
923
|
+
|
|
924
|
+
数值方法:
|
|
925
|
+
对于频谱表示,本征值对应 k² = |k|²
|
|
926
|
+
对于离散场,需要构造拉普拉斯矩阵并求解
|
|
927
|
+
"""
|
|
928
|
+
if self._eigenvalues is not None:
|
|
929
|
+
return self._eigenvalues, self._eigenvectors
|
|
930
|
+
|
|
931
|
+
if self.spectrum is not None:
|
|
932
|
+
# 频谱表示:本征值 = k²
|
|
933
|
+
kx, ky = self.spectrum.momentum_grid
|
|
934
|
+
k2 = kx[:, None]**2 + ky[None, :]**2
|
|
935
|
+
|
|
936
|
+
# 展平并排序(降序)
|
|
937
|
+
eigenvalues = np.sort(k2.flatten())[::-1]
|
|
938
|
+
|
|
939
|
+
self._eigenvalues = eigenvalues
|
|
940
|
+
self._eigenvectors = None
|
|
941
|
+
|
|
942
|
+
elif self.frame_field is not None:
|
|
943
|
+
# 离散场:估算本征值
|
|
944
|
+
# 完整实现需要构造拉普拉斯矩阵并数值求解
|
|
945
|
+
eigenvalues_list = []
|
|
946
|
+
|
|
947
|
+
for i in range(1, self.ny - 1):
|
|
948
|
+
for j in range(1, self.nx - 1):
|
|
949
|
+
lap = self.gradient_op.laplacian((i, j))
|
|
950
|
+
eigenvalues_list.append(abs(lap))
|
|
951
|
+
|
|
952
|
+
eigenvalues = np.sort(np.array(eigenvalues_list))[::-1]
|
|
953
|
+
self._eigenvalues = eigenvalues
|
|
954
|
+
self._eigenvectors = None
|
|
955
|
+
|
|
956
|
+
return self._eigenvalues, self._eigenvectors
|
|
957
|
+
|
|
958
|
+
def expand_frame_in_eigenbasis(self, frame: 'FourierFrame',
|
|
959
|
+
n_modes: int = 10) -> np.ndarray:
|
|
960
|
+
"""
|
|
961
|
+
将FourierFrame展开到本征态基底
|
|
962
|
+
|
|
963
|
+
FourierFrame = Σ_n c_n FourierFrame_n
|
|
964
|
+
|
|
965
|
+
Args:
|
|
966
|
+
frame: 要展开的FourierFrame
|
|
967
|
+
n_modes: 使用的模式数量
|
|
968
|
+
|
|
969
|
+
Returns:
|
|
970
|
+
展开系数 c_n
|
|
971
|
+
|
|
972
|
+
数学细节:
|
|
973
|
+
c_n = ∫ φ_n*(x) FourierFrame(x) dV
|
|
974
|
+
|
|
975
|
+
简化实现:使用傅里叶系数作为近似
|
|
976
|
+
"""
|
|
977
|
+
eigenvalues, _ = self.compute_eigenspectrum()
|
|
978
|
+
|
|
979
|
+
# 简化:使用FourierFrame的Q因子
|
|
980
|
+
coefficients = np.zeros(n_modes, dtype=complex)
|
|
981
|
+
q_value = frame.Q
|
|
982
|
+
|
|
983
|
+
for n in range(min(n_modes, len(eigenvalues))):
|
|
984
|
+
# 简化投影:c_n ∝ Q / √λ_n
|
|
985
|
+
if eigenvalues[n] > 0:
|
|
986
|
+
coefficients[n] = q_value / np.sqrt(eigenvalues[n])
|
|
987
|
+
|
|
988
|
+
return coefficients
|
|
989
|
+
|
|
990
|
+
def reconstruct_from_modes(self, coefficients: np.ndarray,
|
|
991
|
+
base_frame: 'FourierFrame') -> 'FourierFrame':
|
|
992
|
+
"""
|
|
993
|
+
从本征模式重建FourierFrame
|
|
994
|
+
|
|
995
|
+
FourierFrame = Σ_n c_n FourierFrame_n
|
|
996
|
+
|
|
997
|
+
Args:
|
|
998
|
+
coefficients: 展开系数
|
|
999
|
+
base_frame: 基础标架
|
|
1000
|
+
|
|
1001
|
+
Returns:
|
|
1002
|
+
重建的FourierFrame
|
|
1003
|
+
"""
|
|
1004
|
+
eigenvalues, _ = self.compute_eigenspectrum()
|
|
1005
|
+
|
|
1006
|
+
reconstructed_Q = 0.0 + 0j
|
|
1007
|
+
for n in range(len(coefficients)):
|
|
1008
|
+
if n < len(eigenvalues) and eigenvalues[n] > 0:
|
|
1009
|
+
reconstructed_Q += coefficients[n] * np.sqrt(eigenvalues[n])
|
|
1010
|
+
|
|
1011
|
+
return FourierFrame(base_frame.base, reconstructed_Q)
|
|
1012
|
+
|
|
1013
|
+
def weyl_counting(self, lambda_threshold: float) -> int:
|
|
1014
|
+
"""
|
|
1015
|
+
Weyl渐近计数函数
|
|
1016
|
+
|
|
1017
|
+
N(λ) = #{n : λ_n < λ} (小于λ的本征值个数)
|
|
1018
|
+
|
|
1019
|
+
Weyl律:
|
|
1020
|
+
N(λ) ~ (ω_d / (2π)^d) Vol(M) λ^{d/2} (λ → ∞)
|
|
1021
|
+
|
|
1022
|
+
对于2维流形:N(λ) ~ (1/4π) Area(M) λ
|
|
1023
|
+
|
|
1024
|
+
Args:
|
|
1025
|
+
lambda_threshold: 本征值阈值λ
|
|
1026
|
+
|
|
1027
|
+
Returns:
|
|
1028
|
+
N(λ) - 本征值个数
|
|
1029
|
+
"""
|
|
1030
|
+
eigenvalues, _ = self.compute_eigenspectrum()
|
|
1031
|
+
return int(np.sum(eigenvalues < lambda_threshold))
|
|
1032
|
+
|
|
1033
|
+
def shape_dna(self, n_modes: int = 50) -> np.ndarray:
|
|
1034
|
+
"""
|
|
1035
|
+
形状DNA(ShapeDNA)- 流形的谱签名
|
|
1036
|
+
|
|
1037
|
+
前n个本征值 {λ_1, λ_2, ..., λ_n} 唯一标识流形的几何形状
|
|
1038
|
+
(在同谱异构的情况下)
|
|
1039
|
+
|
|
1040
|
+
这是谱几何中的核心概念:
|
|
1041
|
+
"Can one hear the shape of a drum?" - Mark Kac (1966)
|
|
1042
|
+
|
|
1043
|
+
对于2维流形,谱通常可以听出形状,但存在反例
|
|
1044
|
+
(Gordon-Webb-Wolpert, 1992)
|
|
1045
|
+
|
|
1046
|
+
Args:
|
|
1047
|
+
n_modes: 模式数量(默认50)
|
|
1048
|
+
|
|
1049
|
+
Returns:
|
|
1050
|
+
前n个本征值构成的谱签名
|
|
1051
|
+
|
|
1052
|
+
应用:
|
|
1053
|
+
- 形状识别与检索
|
|
1054
|
+
- 几何相似性度量
|
|
1055
|
+
- 拓扑不变量提取
|
|
1056
|
+
"""
|
|
1057
|
+
eigenvalues, _ = self.compute_eigenspectrum()
|
|
1058
|
+
return eigenvalues[:n_modes]
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
# ============================================================
|
|
1062
|
+
# 热核 (Heat Kernel)
|
|
1063
|
+
# ============================================================
|
|
1064
|
+
|
|
1065
|
+
class HeatKernel:
|
|
1066
|
+
"""
|
|
1067
|
+
热核 - 热方程的基本解(经典几何谱分析)
|
|
1068
|
+
|
|
1069
|
+
数学定义:
|
|
1070
|
+
∂u/∂t = Δu (热方程)
|
|
1071
|
+
K(x, y, t) = 基本解满足: ∂K/∂t = Δ_x K, K(x,y,0) = δ(x-y)
|
|
1072
|
+
|
|
1073
|
+
热核的谱展开:
|
|
1074
|
+
K(x, y, t) = Σ_n e^{-λ_n t} φ_n(x) φ_n(y)
|
|
1075
|
+
|
|
1076
|
+
其中 {λ_n, φ_n} 是拉普拉斯算子 Δφ_n = -λ_n φ_n 的本征系统。
|
|
1077
|
+
|
|
1078
|
+
热核迹的渐近展开(Minakshisundaram-Pleijel):
|
|
1079
|
+
Tr(e^{tΔ}) ~ (4πt)^{-d/2} Σ_k a_k t^k
|
|
1080
|
+
|
|
1081
|
+
热核系数 {a_k} 编码流形的几何不变量:
|
|
1082
|
+
- a₀ = Vol(M) (体积)
|
|
1083
|
+
- a₁ ∝ ∫ R dV (曲率积分)
|
|
1084
|
+
- a₂ ∝ ∫ (R² + 其他曲率不变量) dV
|
|
1085
|
+
|
|
1086
|
+
**FourierFrame作为数学基础**:
|
|
1087
|
+
在我们的框架中,热核作为FourierFrame在扩散过程中的演化算子:
|
|
1088
|
+
|
|
1089
|
+
FourierFrame(x, t) = ∫ K(x, y, t) FourierFrame(y, 0) dy
|
|
1090
|
+
= e^{tΔ} FourierFrame(x, 0)
|
|
1091
|
+
|
|
1092
|
+
这将FourierFrame场视为"温度分布",热核描述其扩散传播。
|
|
1093
|
+
|
|
1094
|
+
**与量子理论的关系及局限性**:
|
|
1095
|
+
- 热核在形式上等价于量子力学的虚时间传播子(Wick旋转)
|
|
1096
|
+
- 但这里是**纯几何**的扩散过程,非量子演化
|
|
1097
|
+
- 不涉及态矢量、算符期望值等量子概念
|
|
1098
|
+
- 适用于经典计算机的数值计算
|
|
1099
|
+
|
|
1100
|
+
应用:
|
|
1101
|
+
- 形状识别(ShapeDNA)
|
|
1102
|
+
- 几何不变量提取
|
|
1103
|
+
- 多尺度几何分析
|
|
1104
|
+
- 流形谱距离
|
|
1105
|
+
"""
|
|
1106
|
+
|
|
1107
|
+
def __init__(self, frame_field: Union[List[List['FourierFrame']], 'FourierFrameSpectrum']):
|
|
1108
|
+
"""
|
|
1109
|
+
初始化热核
|
|
1110
|
+
|
|
1111
|
+
Args:
|
|
1112
|
+
frame_field: FourierFrame场(离散)或其频谱表示
|
|
1113
|
+
"""
|
|
1114
|
+
if isinstance(frame_field, list):
|
|
1115
|
+
# 离散标架场
|
|
1116
|
+
self.frame_field = frame_field
|
|
1117
|
+
self.gradient_op = IntrinsicGradient(frame_field)
|
|
1118
|
+
self.ny = len(frame_field)
|
|
1119
|
+
self.nx = len(frame_field[0]) if self.ny > 0 else 0
|
|
1120
|
+
self.spectrum = None
|
|
1121
|
+
else:
|
|
1122
|
+
# 频谱表示
|
|
1123
|
+
self.spectrum = frame_field
|
|
1124
|
+
self.frame_field = None
|
|
1125
|
+
self.gradient_op = None
|
|
1126
|
+
self.ny, self.nx = frame_field.shape
|
|
1127
|
+
|
|
1128
|
+
def evolution_operator(self, t: float, kappa: float = 1.0) -> Union[np.ndarray, List[List['FourierFrame']]]:
|
|
1129
|
+
"""
|
|
1130
|
+
热核演化算子: e^{tκΔ} FourierFrame
|
|
1131
|
+
|
|
1132
|
+
计算标架场在时间t后的扩散状态。
|
|
1133
|
+
|
|
1134
|
+
Args:
|
|
1135
|
+
t: 扩散时间(>0)
|
|
1136
|
+
kappa: 扩散系数(默认1.0)
|
|
1137
|
+
|
|
1138
|
+
Returns:
|
|
1139
|
+
演化后的标架场
|
|
1140
|
+
|
|
1141
|
+
数学细节:
|
|
1142
|
+
在频域中,热核演化简单地是:
|
|
1143
|
+
FourierFrame(k, t) = e^{-κt|k|²} FourierFrame(k, 0)
|
|
1144
|
+
|
|
1145
|
+
这是高频抑制(低通滤波),对应空间的平滑化。
|
|
1146
|
+
"""
|
|
1147
|
+
if t < 0:
|
|
1148
|
+
raise ValueError("扩散时间必须非负")
|
|
1149
|
+
|
|
1150
|
+
if self.frame_field is not None:
|
|
1151
|
+
# 离散场:逐点演化
|
|
1152
|
+
evolved_field = []
|
|
1153
|
+
for i in range(self.ny):
|
|
1154
|
+
row = []
|
|
1155
|
+
for j in range(self.nx):
|
|
1156
|
+
evolved_frame = self.frame_field[i][j].diffusion_evolution(t, kappa)
|
|
1157
|
+
row.append(evolved_frame)
|
|
1158
|
+
evolved_field.append(row)
|
|
1159
|
+
return evolved_field
|
|
1160
|
+
|
|
1161
|
+
elif self.spectrum is not None:
|
|
1162
|
+
# 频谱表示:频域衰减
|
|
1163
|
+
kx, ky = self.spectrum.momentum_grid
|
|
1164
|
+
k2 = kx[:, None]**2 + ky[None, :]**2
|
|
1165
|
+
|
|
1166
|
+
# e^{-κt k²} 衰减因子
|
|
1167
|
+
decay = np.exp(-kappa * t * k2)
|
|
1168
|
+
|
|
1169
|
+
# 应用到各分量
|
|
1170
|
+
evolved_spectrum = FourierFrameSpectrum(
|
|
1171
|
+
ux_spectrum=self.spectrum.ux_spectrum * decay[..., None],
|
|
1172
|
+
uy_spectrum=self.spectrum.uy_spectrum * decay[..., None],
|
|
1173
|
+
uz_spectrum=self.spectrum.uz_spectrum * decay[..., None],
|
|
1174
|
+
origin_spectrum=self.spectrum.origin_spectrum * decay[..., None],
|
|
1175
|
+
momentum_grid=self.spectrum.momentum_grid,
|
|
1176
|
+
hbar=self.spectrum.hbar
|
|
1177
|
+
)
|
|
1178
|
+
return evolved_spectrum
|
|
1179
|
+
|
|
1180
|
+
else:
|
|
1181
|
+
raise ValueError("需要提供标架场或频谱")
|
|
1182
|
+
|
|
1183
|
+
def trace(self, t: float, kappa: float = 1.0) -> float:
|
|
1184
|
+
"""
|
|
1185
|
+
热核迹:Tr(e^{tκΔ}) = Σ_n e^{-κt λ_n}
|
|
1186
|
+
|
|
1187
|
+
这是几何信息的凝聚,包含流形谱的全部信息。
|
|
1188
|
+
|
|
1189
|
+
Args:
|
|
1190
|
+
t: 扩散时间
|
|
1191
|
+
kappa: 扩散系数
|
|
1192
|
+
|
|
1193
|
+
Returns:
|
|
1194
|
+
热核迹值
|
|
1195
|
+
"""
|
|
1196
|
+
if self.spectrum is not None:
|
|
1197
|
+
# 使用频谱表示
|
|
1198
|
+
density = self.spectrum.spectral_density()
|
|
1199
|
+
kx, ky = self.spectrum.momentum_grid
|
|
1200
|
+
k2 = kx[:, None]**2 + ky[None, :]**2
|
|
1201
|
+
|
|
1202
|
+
# Tr(e^{-κt Δ}) = Σ e^{-κt k²}
|
|
1203
|
+
trace_val = np.sum(np.exp(-kappa * t * k2))
|
|
1204
|
+
return float(trace_val)
|
|
1205
|
+
|
|
1206
|
+
elif self.frame_field is not None:
|
|
1207
|
+
# 简化估计:使用标架场的"能量"
|
|
1208
|
+
total = 0.0
|
|
1209
|
+
for i in range(self.ny):
|
|
1210
|
+
for j in range(self.nx):
|
|
1211
|
+
laplacian = self.gradient_op.laplacian((i, j))
|
|
1212
|
+
# e^{-t λ} ≈ 1 - tλ (小t近似)
|
|
1213
|
+
total += np.exp(-kappa * t * abs(laplacian))
|
|
1214
|
+
return total
|
|
1215
|
+
|
|
1216
|
+
return 0.0
|
|
1217
|
+
|
|
1218
|
+
def asymptotic_expansion(self, t: float, kappa: float = 1.0, order: int = 2) -> float:
|
|
1219
|
+
"""
|
|
1220
|
+
热核迹的渐近展开(Minakshisundaram-Pleijel公式)
|
|
1221
|
+
|
|
1222
|
+
Tr(e^{tκΔ}) ~ (4πκt)^{-d/2} [a₀ + a₁(κt) + a₂(κt)² + ...]
|
|
1223
|
+
|
|
1224
|
+
Args:
|
|
1225
|
+
t: 扩散时间(小t渐近)
|
|
1226
|
+
kappa: 扩散系数
|
|
1227
|
+
order: 展开阶数(默认2)
|
|
1228
|
+
|
|
1229
|
+
Returns:
|
|
1230
|
+
渐近估计值
|
|
1231
|
+
|
|
1232
|
+
几何意义:
|
|
1233
|
+
- a₀ = Vol(M) - 流形体积
|
|
1234
|
+
- a₁ ∝ ∫ R dV - 标量曲率积分
|
|
1235
|
+
- a₂ ∝ ∫ (R² - |Ric|² + ...) dV - 更高阶曲率不变量
|
|
1236
|
+
"""
|
|
1237
|
+
d = 2 # 2维流形
|
|
1238
|
+
prefactor = (4 * np.pi * kappa * t) ** (-d / 2)
|
|
1239
|
+
|
|
1240
|
+
# 估算热核系数
|
|
1241
|
+
a0 = float(self.ny * self.nx) # 体积(网格点数)
|
|
1242
|
+
|
|
1243
|
+
# a₁ 需要曲率信息
|
|
1244
|
+
if self.gradient_op is not None:
|
|
1245
|
+
curvature_sum = 0.0
|
|
1246
|
+
for i in range(1, self.ny - 1):
|
|
1247
|
+
for j in range(1, self.nx - 1):
|
|
1248
|
+
R_xy = self.gradient_op.commutator((i, j), 0, 1)
|
|
1249
|
+
curvature_sum += abs(R_xy)
|
|
1250
|
+
a1 = curvature_sum / 6.0
|
|
1251
|
+
else:
|
|
1252
|
+
a1 = 0.0
|
|
1253
|
+
|
|
1254
|
+
a2 = 0.0 # 简化
|
|
1255
|
+
|
|
1256
|
+
# 渐近级数
|
|
1257
|
+
expansion = a0
|
|
1258
|
+
if order >= 1:
|
|
1259
|
+
expansion += a1 * (kappa * t)
|
|
1260
|
+
if order >= 2:
|
|
1261
|
+
expansion += a2 * (kappa * t)**2
|
|
1262
|
+
|
|
1263
|
+
return prefactor * expansion
|
|
1264
|
+
|
|
1265
|
+
|
|
1266
|
+
# ============================================================
|
|
1267
|
+
# 频率投影 (Frequency Projection)
|
|
1268
|
+
# ============================================================
|
|
1269
|
+
|
|
1270
|
+
class FrequencyProjection:
|
|
1271
|
+
"""
|
|
1272
|
+
几何频率投影算子
|
|
1273
|
+
|
|
1274
|
+
ω_n = √|κ_n| · sign(κ_n)
|
|
1275
|
+
P_Ω = Σ_{n: ω_n ∈ Ω} |Frame_n⟩⟨Frame_n|
|
|
1276
|
+
|
|
1277
|
+
应用:
|
|
1278
|
+
- 频段滤波
|
|
1279
|
+
- 多尺度分析
|
|
1280
|
+
- 频域波函数
|
|
1281
|
+
"""
|
|
1282
|
+
|
|
1283
|
+
def __init__(self, spectral_decomposition: SpectralDecomposition):
|
|
1284
|
+
"""
|
|
1285
|
+
初始化频率投影
|
|
1286
|
+
|
|
1287
|
+
Args:
|
|
1288
|
+
spectral_decomposition: 谱分解
|
|
1289
|
+
"""
|
|
1290
|
+
self.spectral = spectral_decomposition
|
|
1291
|
+
|
|
1292
|
+
def compute_frequencies(self) -> np.ndarray:
|
|
1293
|
+
"""
|
|
1294
|
+
计算几何频率:ω_n = √|κ_n| · sign(κ_n)
|
|
1295
|
+
|
|
1296
|
+
Returns:
|
|
1297
|
+
频率数组
|
|
1298
|
+
"""
|
|
1299
|
+
eigenvalues, _ = self.spectral.compute_eigenspectrum()
|
|
1300
|
+
frequencies = np.sqrt(np.abs(eigenvalues)) * np.sign(eigenvalues)
|
|
1301
|
+
return frequencies
|
|
1302
|
+
|
|
1303
|
+
def project_to_band(self, omega_min: float, omega_max: float) -> 'FrequencyBandState':
|
|
1304
|
+
"""
|
|
1305
|
+
投影到频段 [ω_min, ω_max]
|
|
1306
|
+
|
|
1307
|
+
Args:
|
|
1308
|
+
omega_min, omega_max: 频段范围
|
|
1309
|
+
|
|
1310
|
+
Returns:
|
|
1311
|
+
频段态
|
|
1312
|
+
"""
|
|
1313
|
+
frequencies = self.compute_frequencies()
|
|
1314
|
+
mask = (frequencies >= omega_min) & (frequencies <= omega_max)
|
|
1315
|
+
|
|
1316
|
+
selected_indices = np.where(mask)[0]
|
|
1317
|
+
|
|
1318
|
+
return FrequencyBandState(
|
|
1319
|
+
frequency_range=(omega_min, omega_max),
|
|
1320
|
+
mode_indices=selected_indices,
|
|
1321
|
+
projection_operator=self
|
|
1322
|
+
)
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
@dataclass
|
|
1326
|
+
class FrequencyBandState:
|
|
1327
|
+
"""频段波函数"""
|
|
1328
|
+
frequency_range: Tuple[float, float]
|
|
1329
|
+
mode_indices: np.ndarray
|
|
1330
|
+
projection_operator: FrequencyProjection
|
|
1331
|
+
|
|
1332
|
+
def wavefunction(self, amplitudes: np.ndarray, phases: np.ndarray) -> complex:
|
|
1333
|
+
"""
|
|
1334
|
+
Ψ_Ω = Σ_{n ∈ Ω} a_n Frame_n e^{iθ_n}
|
|
1335
|
+
|
|
1336
|
+
Args:
|
|
1337
|
+
amplitudes: 振幅数组
|
|
1338
|
+
phases: 相位数组
|
|
1339
|
+
|
|
1340
|
+
Returns:
|
|
1341
|
+
波函数值
|
|
1342
|
+
"""
|
|
1343
|
+
psi = 0.0 + 0j
|
|
1344
|
+
for idx, amp, phase in zip(self.mode_indices, amplitudes, phases):
|
|
1345
|
+
psi += amp * np.exp(1j * phase)
|
|
1346
|
+
return psi
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
# ============================================================
|
|
1350
|
+
# ============================================================
|
|
1351
|
+
# 谱数据结构
|
|
1352
|
+
# ============================================================
|
|
1353
|
+
|
|
1354
|
+
@dataclass
|
|
1355
|
+
class FourierFrameSpectrum:
|
|
1356
|
+
"""
|
|
1357
|
+
傅里叶标架谱表示 - 坐标场在动量空间的表示
|
|
1358
|
+
|
|
1359
|
+
存储坐标场各分量的傅里叶谱
|
|
1360
|
+
"""
|
|
1361
|
+
ux_spectrum: np.ndarray # x轴基矢量谱
|
|
1362
|
+
uy_spectrum: np.ndarray # y轴基矢量谱
|
|
1363
|
+
uz_spectrum: np.ndarray # z轴基矢量谱
|
|
1364
|
+
origin_spectrum: np.ndarray # 原点位置谱
|
|
1365
|
+
momentum_grid: Tuple[np.ndarray, np.ndarray] # (kx, ky)
|
|
1366
|
+
hbar: float = HBAR
|
|
1367
|
+
|
|
1368
|
+
def __post_init__(self):
|
|
1369
|
+
"""验证维度一致性"""
|
|
1370
|
+
shapes = [
|
|
1371
|
+
self.ux_spectrum.shape,
|
|
1372
|
+
self.uy_spectrum.shape,
|
|
1373
|
+
self.uz_spectrum.shape,
|
|
1374
|
+
self.origin_spectrum.shape
|
|
1375
|
+
]
|
|
1376
|
+
if not all(s == shapes[0] for s in shapes):
|
|
1377
|
+
raise ValueError("所有谱分量必须具有相同维度")
|
|
1378
|
+
|
|
1379
|
+
@property
|
|
1380
|
+
def shape(self) -> Tuple[int, int]:
|
|
1381
|
+
"""谱的空间形状"""
|
|
1382
|
+
return self.ux_spectrum.shape[:2]
|
|
1383
|
+
|
|
1384
|
+
def total_energy(self) -> float:
|
|
1385
|
+
"""总能量 E = ∫ |ψ̃(k)|² dk"""
|
|
1386
|
+
return float(
|
|
1387
|
+
np.sum(np.abs(self.ux_spectrum)**2) +
|
|
1388
|
+
np.sum(np.abs(self.uy_spectrum)**2) +
|
|
1389
|
+
np.sum(np.abs(self.uz_spectrum)**2) +
|
|
1390
|
+
np.sum(np.abs(self.origin_spectrum)**2)
|
|
1391
|
+
)
|
|
1392
|
+
|
|
1393
|
+
def spectral_density(self) -> np.ndarray:
|
|
1394
|
+
"""谱密度 ρ(k) = Σ_μ |ψ̃_μ(k)|²"""
|
|
1395
|
+
density = (
|
|
1396
|
+
np.abs(self.ux_spectrum)**2 +
|
|
1397
|
+
np.abs(self.uy_spectrum)**2 +
|
|
1398
|
+
np.abs(self.uz_spectrum)**2 +
|
|
1399
|
+
np.abs(self.origin_spectrum)**2
|
|
1400
|
+
)
|
|
1401
|
+
return np.mean(density, axis=-1) if density.ndim > 2 else density
|
|
1402
|
+
|
|
1403
|
+
def radial_average(self) -> Tuple[np.ndarray, np.ndarray]:
|
|
1404
|
+
"""
|
|
1405
|
+
径向平均谱 (ShapeDNA)
|
|
1406
|
+
|
|
1407
|
+
Returns:
|
|
1408
|
+
(k_bins, radial_spectrum)
|
|
1409
|
+
"""
|
|
1410
|
+
kx, ky = self.momentum_grid
|
|
1411
|
+
k_mag = np.sqrt(kx[:, None]**2 + ky[None, :]**2)
|
|
1412
|
+
|
|
1413
|
+
density = self.spectral_density()
|
|
1414
|
+
|
|
1415
|
+
k_max = np.max(k_mag)
|
|
1416
|
+
k_bins = np.linspace(0, k_max, 50)
|
|
1417
|
+
radial_avg = np.zeros(len(k_bins))
|
|
1418
|
+
|
|
1419
|
+
for i in range(len(k_bins) - 1):
|
|
1420
|
+
mask = (k_mag >= k_bins[i]) & (k_mag < k_bins[i + 1])
|
|
1421
|
+
if np.any(mask):
|
|
1422
|
+
radial_avg[i] = np.mean(density[mask])
|
|
1423
|
+
|
|
1424
|
+
return k_bins, radial_avg
|
|
1425
|
+
|
|
1426
|
+
def to_coord_field(self) -> List[List]:
|
|
1427
|
+
"""
|
|
1428
|
+
逆变换:谱 → 坐标场
|
|
1429
|
+
|
|
1430
|
+
Returns:
|
|
1431
|
+
二维坐标场列表
|
|
1432
|
+
"""
|
|
1433
|
+
ny, nx = self.shape
|
|
1434
|
+
|
|
1435
|
+
origin_field = Frame.inverse_spectral_transform_2d(self.origin_spectrum, self.hbar)
|
|
1436
|
+
ux_field = Frame.inverse_spectral_transform_2d(self.ux_spectrum, self.hbar)
|
|
1437
|
+
uy_field = Frame.inverse_spectral_transform_2d(self.uy_spectrum, self.hbar)
|
|
1438
|
+
uz_field = Frame.inverse_spectral_transform_2d(self.uz_spectrum, self.hbar)
|
|
1439
|
+
|
|
1440
|
+
coord_field = []
|
|
1441
|
+
for i in range(ny):
|
|
1442
|
+
row = []
|
|
1443
|
+
for j in range(nx):
|
|
1444
|
+
o = vec3(origin_field[i, j, 0], origin_field[i, j, 1], origin_field[i, j, 2])
|
|
1445
|
+
ux = vec3(ux_field[i, j, 0], ux_field[i, j, 1], ux_field[i, j, 2])
|
|
1446
|
+
uy = vec3(uy_field[i, j, 0], uy_field[i, j, 1], uy_field[i, j, 2])
|
|
1447
|
+
uz = vec3(uz_field[i, j, 0], uz_field[i, j, 1], uz_field[i, j, 2])
|
|
1448
|
+
|
|
1449
|
+
c = coord3(o, quat(1, 0, 0, 0), vec3(1, 1, 1))
|
|
1450
|
+
c.ux, c.uy, c.uz = ux, uy, uz
|
|
1451
|
+
row.append(c)
|
|
1452
|
+
coord_field.append(row)
|
|
1453
|
+
|
|
1454
|
+
return coord_field
|
|
1455
|
+
|
|
1456
|
+
|
|
1457
|
+
# ============================================================
|
|
1458
|
+
# 便利函数
|
|
1459
|
+
# ============================================================
|
|
1460
|
+
|
|
1461
|
+
def spectral_transform(coord_field: List[List],
|
|
1462
|
+
hbar: float = HBAR,
|
|
1463
|
+
use_gpu: bool = False) -> FourierFrameSpectrum:
|
|
1464
|
+
"""
|
|
1465
|
+
坐标场谱变换
|
|
1466
|
+
|
|
1467
|
+
Args:
|
|
1468
|
+
coord_field: 二维坐标场
|
|
1469
|
+
hbar: 约化普朗克常数
|
|
1470
|
+
use_gpu: 是否使用 GPU 加速
|
|
1471
|
+
|
|
1472
|
+
Returns:
|
|
1473
|
+
FourierFrameSpectrum 对象
|
|
1474
|
+
"""
|
|
1475
|
+
return FourierFrame.from_coord_field(coord_field, hbar)
|
|
1476
|
+
|
|
1477
|
+
|
|
1478
|
+
def inverse_spectral_transform(spectrum: FourierFrameSpectrum) -> List[List]:
|
|
1479
|
+
"""
|
|
1480
|
+
逆谱变换
|
|
1481
|
+
|
|
1482
|
+
Args:
|
|
1483
|
+
spectrum: FourierFrameSpectrum 对象
|
|
1484
|
+
|
|
1485
|
+
Returns:
|
|
1486
|
+
重建的坐标场
|
|
1487
|
+
"""
|
|
1488
|
+
return spectrum.to_coord_field()
|
|
1489
|
+
|
|
1490
|
+
|
|
1491
|
+
# ============================================================
|
|
1492
|
+
# 演示
|
|
1493
|
+
# ============================================================
|
|
1494
|
+
|
|
1495
|
+
def demonstrate():
|
|
1496
|
+
"""演示傅里叶标架代数与谱几何"""
|
|
1497
|
+
print("=" * 70)
|
|
1498
|
+
print("傅里叶标架场与量子谱几何 (FourierFrame Field & Spectral Geometry)")
|
|
1499
|
+
print("=" * 70)
|
|
1500
|
+
|
|
1501
|
+
# 1. 创建基础 FourierFrame
|
|
1502
|
+
if coord3 is not None:
|
|
1503
|
+
base_frame = coord3.from_position(vec3(1, 0, 0))
|
|
1504
|
+
frame = FourierFrame(base_frame, q_factor=1.0+0.5j)
|
|
1505
|
+
else:
|
|
1506
|
+
frame = FourierFrame(q_factor=1.0+0.5j)
|
|
1507
|
+
|
|
1508
|
+
print(f"\n1. 基础傅里叶标架: {frame}")
|
|
1509
|
+
print(f" 相位: {frame.phase:.4f} rad")
|
|
1510
|
+
print(f" 模: {frame.magnitude:.4f}")
|
|
1511
|
+
print(f" 行列式: {frame.det:.4f}")
|
|
1512
|
+
|
|
1513
|
+
# 2. 傅里叶变换
|
|
1514
|
+
print(f"\n2. 傅里叶变换:")
|
|
1515
|
+
ft = frame.fourier_transform()
|
|
1516
|
+
print(f" F[FourierFrame] = {ft}")
|
|
1517
|
+
print(f" F^4[FourierFrame] ≈ FourierFrame: {frame.fourier_transform(2*np.pi)}")
|
|
1518
|
+
|
|
1519
|
+
# 3. 共形变换
|
|
1520
|
+
print(f"\n3. 共形变换:")
|
|
1521
|
+
conf = frame.conformal_transform(2.0)
|
|
1522
|
+
print(f" λ=2: {conf}")
|
|
1523
|
+
|
|
1524
|
+
# 4. 标架复合
|
|
1525
|
+
print(f"\n4. 标架复合:")
|
|
1526
|
+
frame2 = FourierFrame(q_factor=0.5+0.5j)
|
|
1527
|
+
composed = frame * frame2
|
|
1528
|
+
print(f" FourierFrame1 * FourierFrame2 = {composed}")
|
|
1529
|
+
|
|
1530
|
+
# 5. 内禀梯度算子
|
|
1531
|
+
print(f"\n5. 内禀梯度算子:")
|
|
1532
|
+
# 创建简单标架场
|
|
1533
|
+
frame_field = [[FourierFrame(q_factor=1.0 + 0.1j*(i+j)) for j in range(5)] for i in range(5)]
|
|
1534
|
+
grad_op = IntrinsicGradient(frame_field)
|
|
1535
|
+
G_x = grad_op.compute_at((2, 2), 0)
|
|
1536
|
+
G_y = grad_op.compute_at((2, 2), 1)
|
|
1537
|
+
print(f" G_x(2,2) = {G_x:.4f}")
|
|
1538
|
+
print(f" G_y(2,2) = {G_y:.4f}")
|
|
1539
|
+
|
|
1540
|
+
# 6. 曲率计算
|
|
1541
|
+
print(f"\n6. 曲率计算:")
|
|
1542
|
+
curvature_calc = CurvatureFromFrame(frame_field)
|
|
1543
|
+
K = curvature_calc.gaussian_curvature(2, 2)
|
|
1544
|
+
H = curvature_calc.mean_curvature(2, 2)
|
|
1545
|
+
print(f" 高斯曲率 K = {K:.6f}")
|
|
1546
|
+
print(f" 平均曲率 H = {H:.6f}")
|
|
1547
|
+
|
|
1548
|
+
# 7. Berry相位
|
|
1549
|
+
print(f"\n7. Berry相位:")
|
|
1550
|
+
berry = BerryPhase(grad_op)
|
|
1551
|
+
path = [(1, 1), (1, 3), (3, 3), (3, 1), (1, 1)]
|
|
1552
|
+
gamma = berry.compute_along_path(path, closed=True)
|
|
1553
|
+
print(f" γ = ∮ G_μ dx^μ = {gamma:.4f}")
|
|
1554
|
+
|
|
1555
|
+
# 8. 陈数
|
|
1556
|
+
print(f"\n8. 陈数:")
|
|
1557
|
+
chern = ChernNumber(curvature_calc)
|
|
1558
|
+
c1 = chern.compute()
|
|
1559
|
+
print(f" 第一陈数 c₁ = {c1}")
|
|
1560
|
+
|
|
1561
|
+
print("\n" + "=" * 70)
|
|
1562
|
+
print("核心公式总结:")
|
|
1563
|
+
print(" • G_μ = d/dx^μ log FourierFrame(x) [内禀梯度]")
|
|
1564
|
+
print(" • R_{μν} = [G_μ, G_ν] [曲率]")
|
|
1565
|
+
print(" • FourierFrame * e^{iθ} = 傅里叶变换")
|
|
1566
|
+
print(" • FourierFrame * λ = 共形变换")
|
|
1567
|
+
print(" • γ = ∮ G_μ dx^μ [Berry相位]")
|
|
1568
|
+
print(" • c₁ = (1/2π) ∬ R_{μν} dS [陈数]")
|
|
1569
|
+
print("=" * 70)
|
|
1570
|
+
|
|
1571
|
+
|
|
1572
|
+
# ============================================================
|
|
1573
|
+
# 导出
|
|
1574
|
+
# ============================================================
|
|
1575
|
+
|
|
1576
|
+
__all__ = [
|
|
1577
|
+
# 核心类
|
|
1578
|
+
'FourierFrame',
|
|
1579
|
+
'FourierFrameSpectrum',
|
|
1580
|
+
|
|
1581
|
+
# 谱几何核心
|
|
1582
|
+
'IntrinsicGradient',
|
|
1583
|
+
'CurvatureFromFrame',
|
|
1584
|
+
'BerryPhase',
|
|
1585
|
+
'ChernNumber',
|
|
1586
|
+
'SpectralDecomposition',
|
|
1587
|
+
'HeatKernel',
|
|
1588
|
+
'FrequencyProjection',
|
|
1589
|
+
'FrequencyBandState',
|
|
1590
|
+
|
|
1591
|
+
# 便利函数
|
|
1592
|
+
'spectral_transform',
|
|
1593
|
+
'inverse_spectral_transform',
|
|
1594
|
+
|
|
1595
|
+
# 常数
|
|
1596
|
+
'HBAR',
|
|
1597
|
+
'GPU_AVAILABLE',
|
|
1598
|
+
]
|
|
1599
|
+
|
|
1600
|
+
|
|
1601
|
+
if __name__ == "__main__":
|
|
1602
|
+
demonstrate()
|