photokinetics 2.0.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Cogito Lin
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,178 @@
1
+ Metadata-Version: 2.4
2
+ Name: photokinetics
3
+ Version: 2.0.0
4
+ Summary: Photokinetics V2.0 — 可微光学物理引擎 (Differentiable Optics Engine in PyTorch)
5
+ Author-email: Cogito Lin <noreply@example.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/XxLCFLXx/photokinetics
8
+ Project-URL: Repository, https://github.com/XxLCFLXx/photokinetics
9
+ Project-URL: Documentation, https://github.com/XxLCFLXx/photokinetics#readme
10
+ Project-URL: Bug Tracker, https://github.com/XxLCFLXx/photokinetics/issues
11
+ Project-URL: Online Calculator, https://xxlcflxx.github.io/photokinetics/calculator/photokinetics_calculator.html
12
+ Keywords: optics,photonics,photothermal,differentiable-physics,pytorch,ai-for-science,laser,optical-tweezer,physics-engine
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Topic :: Scientific/Engineering :: Physics
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Operating System :: OS Independent
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: torch>=1.10.0
28
+ Requires-Dist: numpy>=1.20.0
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=7.0; extra == "dev"
31
+ Requires-Dist: build>=0.8.0; extra == "dev"
32
+ Requires-Dist: twine>=4.0.0; extra == "dev"
33
+ Provides-Extra: examples
34
+ Requires-Dist: matplotlib>=3.5.0; extra == "examples"
35
+ Dynamic: license-file
36
+
37
+ # Photokinetics V2.0
38
+
39
+ **可微光学物理引擎 (Differentiable Optics Engine in PyTorch)**
40
+
41
+ 基于光子动能传递的光学统一计算框架,使用 PyTorch 实现,天然支持自动微分、批量计算和逆向设计。
42
+
43
+ ## 核心特性
44
+
45
+ - **可微分** — 所有公式返回 `torch.Tensor`,支持 `requires_grad=True` 自动求导
46
+ - **批量化** — 参数可以是张量,自动向量化(如批量光强扫描)
47
+ - **纯解析** — 没有数值积分,没有训练数据,直接公式计算
48
+ - **极速** — 比 1D-FDTD 快 10²~10³x,比 3D-FDTD 理论快 10⁶~10⁹x
49
+ - **统一框架** — 8 个光学模块从同一套光子动能传递公设推导
50
+
51
+ ## 安装
52
+
53
+ ```bash
54
+ pip install photokinetics
55
+ ```
56
+
57
+ ## 快速开始
58
+
59
+ ### 基本计算
60
+
61
+ ```python
62
+ from photokinetics import calc_photothermal
63
+
64
+ # 计算水在 1064nm 激光下的温升
65
+ result = calc_photothermal(
66
+ n=1.33, kappa=0.00012, wavelength_nm=1064,
67
+ I0=1e7, rho=1000, Cp=4186, depth_mm=1.0, time_s=1.0
68
+ )
69
+ print(f"温升: {result['dT'].item():.2f} K")
70
+ # 输出: 温升: 877.02 K
71
+ ```
72
+
73
+ ### 自动微分
74
+
75
+ ```python
76
+ import torch
77
+ from photokinetics import calc_photothermal
78
+
79
+ I0 = torch.tensor(1e7, requires_grad=True)
80
+ result = calc_photothermal(1.33, 0.00012, 1064, I0, 1000, 4186, 1.0, 1.0)
81
+ result['dT'].backward()
82
+
83
+ print(f"d(ΔT)/d(I₀) = {I0.grad.item():.2e}")
84
+ # 输出: 8.77e-05
85
+ ```
86
+
87
+ ### 逆向设计(梯度下降求光强)
88
+
89
+ ```python
90
+ import torch
91
+ from photokinetics import calc_photothermal
92
+
93
+ target_dT = 100.0
94
+ I0 = torch.tensor(1e5, requires_grad=True)
95
+ optimizer = torch.optim.Adam([I0], lr=5e4)
96
+
97
+ for i in range(100):
98
+ optimizer.zero_grad()
99
+ result = calc_photothermal(1.33, 0.00012, 1064, I0, 1000, 4186, 1.0, 1.0)
100
+ loss = (result['dT'] - target_dT) ** 2
101
+ loss.backward()
102
+ optimizer.step()
103
+
104
+ print(f"I₀ = {I0.item():.2e}, ΔT = {result['dT'].item():.2f} K")
105
+ # 输出: I₀ = 1.15e+06, ΔT = 100.52 K
106
+ ```
107
+
108
+ ### 批量计算
109
+
110
+ ```python
111
+ import torch
112
+ from photokinetics import calc_photothermal
113
+
114
+ I0_batch = torch.logspace(4, 8, 1000) # 1000 个光强
115
+ result = calc_photothermal(1.33, 0.00012, 1064, I0_batch, 1000, 4186, 1.0, 1.0)
116
+ print(result['dT'].shape) # torch.Size([1000])
117
+ ```
118
+
119
+ ## 8 个模块速查表
120
+
121
+ | 模块 | 函数 | 核心参数 |
122
+ |------|------|---------|
123
+ | 光电效应 | `calc_photoelectric(phi_ev, lambda_nm)` | 逸出功, 波长 |
124
+ | 黑体辐射 | `calc_blackbody(T, lambda_nm=None)` | 温度, 波长 |
125
+ | 康普顿散射 | `calc_compton(E0_keV, theta_deg)` | 入射能量, 散射角 |
126
+ | 多普勒效应 | `calc_doppler(nu0, v_km_s, receding)` | 频率, 速度 |
127
+ | 引力红移 | `calc_gravitational_redshift(M, r1, r2)` | 质量, 半径 |
128
+ | **光热模型** | `calc_photothermal(n, kappa, λ, I0, ρ, Cp, z, t)` | 8 个参数 |
129
+ | 非线性光学 | `calc_nonlinear_order(Eg_eV, lambda_nm)` | 禁带, 波长 |
130
+ | 光镊力 | `calc_tweezer_force(a, n_p, n_m, λ, grad_I)` | 半径, 折射率 |
131
+
132
+ ## 物理常数
133
+
134
+ 所有常数使用 CODATA 2018 推荐值,定义为 `torch.tensor`。
135
+
136
+ ## 性能对比
137
+
138
+ 与 1D-FDTD 数值仿真对比(绝热近似适用域内):
139
+
140
+ | 材料 | ΔT 误差 | 加速比 |
141
+ |------|---------|--------|
142
+ | 水 @ 1064nm | 3.49% | 1125x |
143
+ | 硅 @ 532nm | 0.98% | 97x |
144
+ | 锗 @ 532nm | 1.15% | 385x |
145
+
146
+ 详见 [benchmarks/](https://github.com/XxLCFLXx/photokinetics/tree/main/benchmarks)。
147
+
148
+ ## 应用场景
149
+
150
+ - **AI for Science** — 嵌入 PyTorch 做物理驱动机器学习
151
+ - **逆向设计** — 已知目标温升,梯度下降反推光强/波长
152
+ - **灵敏度分析** — 计算各参数对输出的梯度
153
+ - **参数扫描** — 批量计算数千组参数
154
+ - **实时仿真** — 解析公式微秒级计算
155
+ - **教学/科普** — 在线计算器 [在线体验](https://xxlcflxx.github.io/photokinetics/calculator/photokinetics_calculator.html)
156
+
157
+ ## 限制
158
+
159
+ - 光热模型采用绝热近似,适用条件 `t ≪ L²/D`
160
+ - 目前支持平面波入射 + 均匀介质
161
+ - 光镊力使用瑞利近似(小颗粒,a ≪ λ)
162
+
163
+ ## 引用
164
+
165
+ 如果本项目对您的研究有帮助,请引用:
166
+
167
+ ```bibtex
168
+ @misc{photokinetics2026,
169
+ title={Photokinetics V2.0: A Differentiable Optics Engine},
170
+ author={Cogito Lin},
171
+ year={2026},
172
+ url={https://github.com/XxLCFLXx/photokinetics}
173
+ }
174
+ ```
175
+
176
+ ## License
177
+
178
+ MIT
@@ -0,0 +1,142 @@
1
+ # Photokinetics V2.0
2
+
3
+ **可微光学物理引擎 (Differentiable Optics Engine in PyTorch)**
4
+
5
+ 基于光子动能传递的光学统一计算框架,使用 PyTorch 实现,天然支持自动微分、批量计算和逆向设计。
6
+
7
+ ## 核心特性
8
+
9
+ - **可微分** — 所有公式返回 `torch.Tensor`,支持 `requires_grad=True` 自动求导
10
+ - **批量化** — 参数可以是张量,自动向量化(如批量光强扫描)
11
+ - **纯解析** — 没有数值积分,没有训练数据,直接公式计算
12
+ - **极速** — 比 1D-FDTD 快 10²~10³x,比 3D-FDTD 理论快 10⁶~10⁹x
13
+ - **统一框架** — 8 个光学模块从同一套光子动能传递公设推导
14
+
15
+ ## 安装
16
+
17
+ ```bash
18
+ pip install photokinetics
19
+ ```
20
+
21
+ ## 快速开始
22
+
23
+ ### 基本计算
24
+
25
+ ```python
26
+ from photokinetics import calc_photothermal
27
+
28
+ # 计算水在 1064nm 激光下的温升
29
+ result = calc_photothermal(
30
+ n=1.33, kappa=0.00012, wavelength_nm=1064,
31
+ I0=1e7, rho=1000, Cp=4186, depth_mm=1.0, time_s=1.0
32
+ )
33
+ print(f"温升: {result['dT'].item():.2f} K")
34
+ # 输出: 温升: 877.02 K
35
+ ```
36
+
37
+ ### 自动微分
38
+
39
+ ```python
40
+ import torch
41
+ from photokinetics import calc_photothermal
42
+
43
+ I0 = torch.tensor(1e7, requires_grad=True)
44
+ result = calc_photothermal(1.33, 0.00012, 1064, I0, 1000, 4186, 1.0, 1.0)
45
+ result['dT'].backward()
46
+
47
+ print(f"d(ΔT)/d(I₀) = {I0.grad.item():.2e}")
48
+ # 输出: 8.77e-05
49
+ ```
50
+
51
+ ### 逆向设计(梯度下降求光强)
52
+
53
+ ```python
54
+ import torch
55
+ from photokinetics import calc_photothermal
56
+
57
+ target_dT = 100.0
58
+ I0 = torch.tensor(1e5, requires_grad=True)
59
+ optimizer = torch.optim.Adam([I0], lr=5e4)
60
+
61
+ for i in range(100):
62
+ optimizer.zero_grad()
63
+ result = calc_photothermal(1.33, 0.00012, 1064, I0, 1000, 4186, 1.0, 1.0)
64
+ loss = (result['dT'] - target_dT) ** 2
65
+ loss.backward()
66
+ optimizer.step()
67
+
68
+ print(f"I₀ = {I0.item():.2e}, ΔT = {result['dT'].item():.2f} K")
69
+ # 输出: I₀ = 1.15e+06, ΔT = 100.52 K
70
+ ```
71
+
72
+ ### 批量计算
73
+
74
+ ```python
75
+ import torch
76
+ from photokinetics import calc_photothermal
77
+
78
+ I0_batch = torch.logspace(4, 8, 1000) # 1000 个光强
79
+ result = calc_photothermal(1.33, 0.00012, 1064, I0_batch, 1000, 4186, 1.0, 1.0)
80
+ print(result['dT'].shape) # torch.Size([1000])
81
+ ```
82
+
83
+ ## 8 个模块速查表
84
+
85
+ | 模块 | 函数 | 核心参数 |
86
+ |------|------|---------|
87
+ | 光电效应 | `calc_photoelectric(phi_ev, lambda_nm)` | 逸出功, 波长 |
88
+ | 黑体辐射 | `calc_blackbody(T, lambda_nm=None)` | 温度, 波长 |
89
+ | 康普顿散射 | `calc_compton(E0_keV, theta_deg)` | 入射能量, 散射角 |
90
+ | 多普勒效应 | `calc_doppler(nu0, v_km_s, receding)` | 频率, 速度 |
91
+ | 引力红移 | `calc_gravitational_redshift(M, r1, r2)` | 质量, 半径 |
92
+ | **光热模型** | `calc_photothermal(n, kappa, λ, I0, ρ, Cp, z, t)` | 8 个参数 |
93
+ | 非线性光学 | `calc_nonlinear_order(Eg_eV, lambda_nm)` | 禁带, 波长 |
94
+ | 光镊力 | `calc_tweezer_force(a, n_p, n_m, λ, grad_I)` | 半径, 折射率 |
95
+
96
+ ## 物理常数
97
+
98
+ 所有常数使用 CODATA 2018 推荐值,定义为 `torch.tensor`。
99
+
100
+ ## 性能对比
101
+
102
+ 与 1D-FDTD 数值仿真对比(绝热近似适用域内):
103
+
104
+ | 材料 | ΔT 误差 | 加速比 |
105
+ |------|---------|--------|
106
+ | 水 @ 1064nm | 3.49% | 1125x |
107
+ | 硅 @ 532nm | 0.98% | 97x |
108
+ | 锗 @ 532nm | 1.15% | 385x |
109
+
110
+ 详见 [benchmarks/](https://github.com/XxLCFLXx/photokinetics/tree/main/benchmarks)。
111
+
112
+ ## 应用场景
113
+
114
+ - **AI for Science** — 嵌入 PyTorch 做物理驱动机器学习
115
+ - **逆向设计** — 已知目标温升,梯度下降反推光强/波长
116
+ - **灵敏度分析** — 计算各参数对输出的梯度
117
+ - **参数扫描** — 批量计算数千组参数
118
+ - **实时仿真** — 解析公式微秒级计算
119
+ - **教学/科普** — 在线计算器 [在线体验](https://xxlcflxx.github.io/photokinetics/calculator/photokinetics_calculator.html)
120
+
121
+ ## 限制
122
+
123
+ - 光热模型采用绝热近似,适用条件 `t ≪ L²/D`
124
+ - 目前支持平面波入射 + 均匀介质
125
+ - 光镊力使用瑞利近似(小颗粒,a ≪ λ)
126
+
127
+ ## 引用
128
+
129
+ 如果本项目对您的研究有帮助,请引用:
130
+
131
+ ```bibtex
132
+ @misc{photokinetics2026,
133
+ title={Photokinetics V2.0: A Differentiable Optics Engine},
134
+ author={Cogito Lin},
135
+ year={2026},
136
+ url={https://github.com/XxLCFLXx/photokinetics}
137
+ }
138
+ ```
139
+
140
+ ## License
141
+
142
+ MIT
@@ -0,0 +1,40 @@
1
+ """
2
+ Photokinetics V2.0 — 可微光学物理引擎 (Differentiable Optics Engine)
3
+
4
+ 基于光子动能传递的光学统一计算框架,使用 PyTorch 实现,天然支持自动微分。
5
+
6
+ 8个核心模块:
7
+ - 光电效应 (photoelectric)
8
+ - 黑体辐射 (blackbody)
9
+ - 康普顿散射 (compton)
10
+ - 多普勒效应 (doppler)
11
+ - 引力红移 (gravitational)
12
+ - 光热模型 (photothermal) — 核心应用
13
+ - 非线性光学 (nonlinear)
14
+ - 光镊力 (tweezer)
15
+
16
+ 快速开始:
17
+ >>> import torch
18
+ >>> from photokinetics import calc_photothermal
19
+ >>> I0 = torch.tensor(1e7, requires_grad=True)
20
+ >>> result = calc_photothermal(1.33, 0.00012, 1064, I0, 1000, 4186, 1.0, 1.0)
21
+ >>> result['dT'].backward()
22
+ >>> print(I0.grad) # d(ΔT)/d(I₀)
23
+ """
24
+
25
+ from photokinetics.constants import *
26
+ from photokinetics.utils import *
27
+ from photokinetics.modules.photoelectric import calc_photoelectric
28
+ from photokinetics.modules.blackbody import calc_blackbody
29
+ from photokinetics.modules.compton import calc_compton
30
+ from photokinetics.modules.doppler import calc_doppler
31
+ from photokinetics.modules.gravitational import calc_gravitational_redshift
32
+ from photokinetics.modules.photothermal import calc_photothermal
33
+ from photokinetics.modules.nonlinear import calc_nonlinear_order
34
+ from photokinetics.modules.tweezer import calc_tweezer_force
35
+
36
+ __version__ = "2.0.0"
37
+ __description__ = "Photokinetics V2.0 - Differentiable optics simulation in PyTorch"
38
+ __author__ = "Cogito Lin"
39
+ __email__ = "noreply@example.com"
40
+ __license__ = "MIT"
@@ -0,0 +1,19 @@
1
+ import torch
2
+
3
+ # CODATA 2018 推荐值
4
+ H = torch.tensor(6.62607015e-34) # 普朗克常数 (J·s) — 精确值
5
+ H_EV = torch.tensor(4.135667696e-15) # 普朗克常数 (eV·s)
6
+ C = torch.tensor(2.99792458e8) # 真空光速 (m/s) — 精确值
7
+ K_B = torch.tensor(1.380649e-23) # 玻尔兹曼常数 (J/K) — 精确值
8
+ SIGMA = torch.tensor(5.670374419e-8) # 斯特藩-玻尔兹曼常数 W/(m²·K⁴)
9
+ B_WIEN = torch.tensor(2.897771955e-3) # 维恩位移常数 (m·K)
10
+ E_C = torch.tensor(1.602176634e-19) # 电子电荷 (C) — 精确值
11
+ M_E = torch.tensor(9.1093837015e-31) # 电子静止质量 (kg)
12
+ EPSILON_0 = torch.tensor(8.8541878128e-12) # 真空介电常数 (F/m)
13
+ G = torch.tensor(6.67430e-11) # 万有引力常数 m³/(kg·s²)
14
+ M_EARTH = torch.tensor(5.9722e24) # 地球质量 (kg)
15
+ R_EARTH = torch.tensor(6.371e6) # 地球平均半径 (m)
16
+
17
+ # 常用组合常数
18
+ HC_EV_NM = torch.tensor(1239.841984) # hc (eV·nm)
19
+ LAMBDA_C = torch.tensor(2.4263102389e-12) # 电子康普顿波长 λ_c = h/(m_e·c) (m)
@@ -0,0 +1 @@
1
+ """Photokinetics 物理模块集合。"""
@@ -0,0 +1,38 @@
1
+ """黑体辐射模块。"""
2
+ import torch
3
+ from photokinetics.constants import B_WIEN, SIGMA, H, C, K_B
4
+
5
+
6
+ def calc_blackbody(T, lambda_nm=None):
7
+ """
8
+ 黑体辐射计算。
9
+
10
+ 公式:
11
+ 维恩位移定律: λ_max·T = b → λ_max = b/T
12
+ 斯特藩-玻尔兹曼定律: j = σ·T⁴
13
+ 普朗克公式(光谱辐射出射度):
14
+ B(λ,T) = (2πhc²/λ⁵) / [exp(hc/(λkT)) − 1]
15
+
16
+ 参数:
17
+ T — 黑体温度 (K), scalar or tensor
18
+ lambda_nm — 指定波长 (nm), scalar or tensor, optional
19
+
20
+ 返回: (λ_max, j, B_lambda) — 全部为 torch.Tensor
21
+ """
22
+ T = torch.as_tensor(T, dtype=torch.float32)
23
+
24
+ lambda_max_m = B_WIEN / T
25
+ lambda_max_nm = lambda_max_m * 1e9
26
+
27
+ j = SIGMA * T**4
28
+
29
+ B_lambda = None
30
+ if lambda_nm is not None:
31
+ lam = torch.as_tensor(lambda_nm, dtype=torch.float32) * 1e-9
32
+ exponent = H * C / (lam * K_B * T)
33
+ safe_exp = torch.where(exponent > 500, torch.tensor(500.0), exponent)
34
+ numerator = 2.0 * torch.pi * H * C**2 / lam**5
35
+ denominator = torch.exp(safe_exp) - 1.0
36
+ B_lambda = numerator / denominator
37
+
38
+ return lambda_max_nm, j, B_lambda
@@ -0,0 +1,39 @@
1
+ """康普顿散射模块。"""
2
+ import torch
3
+ from photokinetics.constants import H, C, E_C, LAMBDA_C
4
+
5
+
6
+ def calc_compton(E0_keV, theta_deg):
7
+ """
8
+ 康普顿散射计算。
9
+
10
+ 公式:
11
+ 波长位移: Δλ = λ_c (1 − cosθ), λ_c = h/(m_e·c) ≈ 2.426 pm
12
+ 入射波长: λ₀ = hc/E₀
13
+ 散射波长: λ' = λ₀ + Δλ
14
+ 散射光子能量: E' = hc/λ'
15
+ 电子反冲动能: E_e = E₀ − E'
16
+
17
+ 参数:
18
+ E0_keV — 入射光子能量 (keV), scalar or tensor
19
+ theta_deg — 散射角 (度), scalar or tensor
20
+
21
+ 返回: (delta_lambda_pm, E_prime_keV, E_electron_keV) — 全部为 torch.Tensor
22
+ """
23
+ E0 = torch.as_tensor(E0_keV, dtype=torch.float32)
24
+ theta = torch.as_tensor(theta_deg, dtype=torch.float32)
25
+
26
+ theta_rad = torch.deg2rad(theta)
27
+ delta_lambda = LAMBDA_C * (1.0 - torch.cos(theta_rad))
28
+ delta_lambda_pm = delta_lambda * 1e12
29
+
30
+ E0_J = E0 * 1e3 * E_C
31
+ lambda_0 = H * C / E0_J
32
+
33
+ lambda_prime = lambda_0 + delta_lambda
34
+ E_prime_J = H * C / lambda_prime
35
+ E_prime_keV = E_prime_J / (1e3 * E_C)
36
+
37
+ E_electron_keV = E0 - E_prime_keV
38
+
39
+ return delta_lambda_pm, E_prime_keV, E_electron_keV
@@ -0,0 +1,41 @@
1
+ """多普勒效应模块。"""
2
+ import torch
3
+ from photokinetics.constants import C
4
+
5
+
6
+ def calc_doppler(nu0, v_km_s, receding=True):
7
+ """
8
+ 多普勒效应计算(同时给出经典与相对论结果)。
9
+
10
+ 公式:
11
+ β = v/c
12
+ 经典: ν_obs = ν₀(1 ± v/c) (+靠近, −远离)
13
+ 相对论: ν_obs = ν₀ √((1∓β)/(1±β)) (+靠近用+, −远离用−)
14
+ 红移参数: z = ν₀/ν_obs − 1 (天文标准定义, 远离为正)
15
+
16
+ 参数:
17
+ nu0 — 光源静止频率 (Hz), scalar or tensor
18
+ v_km_s — 光源速度 (km/s), scalar or tensor
19
+ receding — True=远离, False=靠近
20
+
21
+ 返回: (nu_classical, nu_relativistic, z_classical, z_relativistic)
22
+ """
23
+ nu0 = torch.as_tensor(nu0, dtype=torch.float32)
24
+ v = torch.as_tensor(v_km_s, dtype=torch.float32) * 1e3
25
+ beta = v / C
26
+
27
+ if receding:
28
+ nu_cl = nu0 * (1.0 - beta)
29
+ nu_rel = nu0 * torch.sqrt((1.0 - beta) / (1.0 + beta))
30
+ else:
31
+ nu_cl = nu0 * (1.0 + beta)
32
+ nu_rel = nu0 * torch.sqrt((1.0 + beta) / (1.0 - beta))
33
+
34
+ z_cl = (nu_cl - nu0) / nu0
35
+
36
+ if receding:
37
+ z_rel = (nu0 - nu_rel) / nu_rel
38
+ else:
39
+ z_rel = (nu_rel - nu0) / nu0
40
+
41
+ return nu_cl, nu_rel, z_cl, z_rel
@@ -0,0 +1,27 @@
1
+ """引力红移模块。"""
2
+ import torch
3
+ from photokinetics.constants import G, C
4
+
5
+
6
+ def calc_gravitational_redshift(M, r1, r2):
7
+ """
8
+ 引力红移计算(广义相对论)。
9
+
10
+ 公式:
11
+ Δν/ν₀ = GM(1/r₁ - 1/r₂)/c²
12
+
13
+ 参数:
14
+ M — 质量 (kg), scalar or tensor
15
+ r1 — 发射半径 (m), scalar or tensor
16
+ r2 — 观测半径 (m), scalar or tensor
17
+
18
+ 返回: (delta_nu_over_nu0, z) — 相对频移和红移参数
19
+ """
20
+ M = torch.as_tensor(M, dtype=torch.float32)
21
+ r1 = torch.as_tensor(r1, dtype=torch.float32)
22
+ r2 = torch.as_tensor(r2, dtype=torch.float32)
23
+
24
+ delta_nu_over_nu0 = G * M * (1.0 / r1 - 1.0 / r2) / C**2
25
+ z = delta_nu_over_nu0
26
+
27
+ return delta_nu_over_nu0, z
@@ -0,0 +1,27 @@
1
+ """非线性光学模块。"""
2
+ import torch
3
+ from photokinetics.constants import HC_EV_NM
4
+
5
+
6
+ def calc_nonlinear_order(Eg_eV, wavelength_nm):
7
+ """
8
+ 非线性光学多光子吸收阶数判定。
9
+
10
+ 公式:
11
+ N = ceil(Eg / hν)
12
+ 其中 hν = hc/λ (eV)
13
+
14
+ 参数:
15
+ Eg_eV — 禁带宽度 (eV), scalar or tensor
16
+ wavelength_nm — 入射波长 (nm), scalar or tensor
17
+
18
+ 返回: (N, hv_eV) — 吸收阶数和光子能量
19
+ """
20
+ Eg = torch.as_tensor(Eg_eV, dtype=torch.float32)
21
+ lam = torch.as_tensor(wavelength_nm, dtype=torch.float32)
22
+
23
+ hv_eV = HC_EV_NM / lam
24
+ N = torch.ceil(Eg / hv_eV)
25
+ N = torch.clamp(N, min=1)
26
+
27
+ return N, hv_eV
@@ -0,0 +1,29 @@
1
+ """光电效应模块。"""
2
+ import torch
3
+ from photokinetics.constants import HC_EV_NM
4
+
5
+
6
+ def calc_photoelectric(phi_ev, lambda_nm):
7
+ """
8
+ 光电效应计算(爱因斯坦光电方程)。
9
+
10
+ 公式:
11
+ hν = hc / λ 光子能量
12
+ E_k = hν - Φ 最大动能(发生光电效应时)
13
+ V_s = E_k / e 遏止电压(数值上等于 E_k(eV))
14
+
15
+ 参数:
16
+ phi_ev — 材料逸出功 Φ (eV), scalar or tensor
17
+ lambda_nm — 入射波长 λ (nm), scalar or tensor
18
+
19
+ 返回: (hν, occurs, E_k, V_s) — 全部为 torch.Tensor
20
+ """
21
+ phi = torch.as_tensor(phi_ev, dtype=torch.float32)
22
+ lam = torch.as_tensor(lambda_nm, dtype=torch.float32)
23
+
24
+ hv = HC_EV_NM / lam
25
+ occurs = hv > phi
26
+ ek = torch.where(occurs, hv - phi, torch.tensor(0.0))
27
+ vs = ek
28
+
29
+ return hv, occurs, vs, ek
@@ -0,0 +1,42 @@
1
+ """光热模型模块(光动论四步解析模型)。"""
2
+ import torch
3
+ from photokinetics.constants import C
4
+
5
+
6
+ def calc_photothermal(n, kappa, wavelength_nm, I0, rho, Cp, depth_mm, time_s):
7
+ """
8
+ 光动论四步光热解析模型(绝热近似)。
9
+
10
+ 公式:
11
+ Step 1: α = 4πκ / (nλ) 吸收系数
12
+ Step 2: I(z) = I₀·exp(-αz) 光强衰减
13
+ Step 3: q(z) = α·I(z) 热源密度
14
+ Step 4: ΔT = q·t / (ρCp) 温升(绝热近似)
15
+
16
+ 参数:
17
+ n — 折射率, scalar or tensor
18
+ kappa — 消光系数, scalar or tensor
19
+ wavelength_nm — 波长 (nm), scalar or tensor
20
+ I0 — 入射光强 (W/m²), scalar or tensor
21
+ rho — 密度 (kg/m³), scalar or tensor
22
+ Cp — 比热 (J/(kg·K)), scalar or tensor
23
+ depth_mm — 深度 (mm), scalar or tensor
24
+ time_s — 照射时间 (s), scalar or tensor
25
+
26
+ 返回: dict with keys: alpha, I_z, q_z, dT
27
+ """
28
+ n = torch.as_tensor(n, dtype=torch.float32)
29
+ kappa = torch.as_tensor(kappa, dtype=torch.float32)
30
+ lam = torch.as_tensor(wavelength_nm, dtype=torch.float32) * 1e-9
31
+ I0 = torch.as_tensor(I0, dtype=torch.float32)
32
+ rho = torch.as_tensor(rho, dtype=torch.float32)
33
+ Cp = torch.as_tensor(Cp, dtype=torch.float32)
34
+ z = torch.as_tensor(depth_mm, dtype=torch.float32) * 1e-3
35
+ time_s = torch.as_tensor(time_s, dtype=torch.float32)
36
+
37
+ alpha = 4.0 * torch.pi * kappa / (n * lam)
38
+ I_z = I0 * torch.exp(-alpha * z)
39
+ q_z = alpha * I_z
40
+ dT = q_z * time_s / (rho * Cp)
41
+
42
+ return {'alpha': alpha, 'I_z': I_z, 'q_z': q_z, 'dT': dT}
@@ -0,0 +1,37 @@
1
+ """光镊力模块(瑞利近似)。"""
2
+ import torch
3
+ from photokinetics.constants import C
4
+
5
+
6
+ def calc_tweezer_force(a_m, n_particle, n_medium, wavelength_nm, grad_I):
7
+ """
8
+ 光镊力计算(瑞利近似)。
9
+
10
+ 公式:
11
+ α = 4πa³ (m²-1)/(m²+2) 极化率, m = n_particle/n_medium
12
+ F_grad = n_medium · α · ∇I / c 梯度力
13
+ F_scat = n_medium · α · ∇I / (2c) 散射力(近似)
14
+
15
+ 参数:
16
+ a_m — 颗粒半径 (m), scalar or tensor
17
+ n_particle — 颗粒折射率, scalar or tensor
18
+ n_medium — 介质折射率, scalar or tensor
19
+ wavelength_nm — 波长 (nm), scalar or tensor
20
+ grad_I — 光强梯度 (W/m³), scalar or tensor
21
+
22
+ 返回: dict with keys: alpha, F_grad, F_scat, F_total
23
+ """
24
+ a = torch.as_tensor(a_m, dtype=torch.float32)
25
+ n_p = torch.as_tensor(n_particle, dtype=torch.float32)
26
+ n_m = torch.as_tensor(n_medium, dtype=torch.float32)
27
+ grad_I = torch.as_tensor(grad_I, dtype=torch.float32)
28
+
29
+ m = n_p / n_m
30
+ m2 = m**2
31
+
32
+ alpha = 4.0 * torch.pi * a**3 * (m2 - 1.0) / (m2 + 2.0)
33
+ F_grad = n_m * alpha * grad_I / C
34
+ F_scat = n_m * alpha * grad_I / (2.0 * C)
35
+ F_total = F_grad + F_scat
36
+
37
+ return {'alpha': alpha, 'F_grad': F_grad, 'F_scat': F_scat, 'F_total': F_total}
@@ -0,0 +1,27 @@
1
+ """Photokinetics 工具函数。"""
2
+ import torch
3
+
4
+
5
+ def fmt_sci(value, sig=4):
6
+ """将数值格式化为科学计数法字符串。"""
7
+ if isinstance(value, torch.Tensor):
8
+ value = value.item()
9
+ if value == 0:
10
+ return "0"
11
+ return "{:.{}e}".format(value, sig - 1)
12
+
13
+
14
+ def fmt_fix(value, sig=4):
15
+ """将数值格式化为定点数。"""
16
+ if isinstance(value, torch.Tensor):
17
+ value = value.item()
18
+ if abs(value) < 1e-4 or abs(value) >= 1e6:
19
+ return fmt_sci(value, sig)
20
+ return "{:.{}g}".format(value, sig)
21
+
22
+
23
+ def to_tensor(x, dtype=torch.float32, device=None):
24
+ """将输入转换为 torch.Tensor。"""
25
+ if isinstance(x, torch.Tensor):
26
+ return x.to(dtype=dtype, device=device)
27
+ return torch.tensor(x, dtype=dtype, device=device)
@@ -0,0 +1,178 @@
1
+ Metadata-Version: 2.4
2
+ Name: photokinetics
3
+ Version: 2.0.0
4
+ Summary: Photokinetics V2.0 — 可微光学物理引擎 (Differentiable Optics Engine in PyTorch)
5
+ Author-email: Cogito Lin <noreply@example.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/XxLCFLXx/photokinetics
8
+ Project-URL: Repository, https://github.com/XxLCFLXx/photokinetics
9
+ Project-URL: Documentation, https://github.com/XxLCFLXx/photokinetics#readme
10
+ Project-URL: Bug Tracker, https://github.com/XxLCFLXx/photokinetics/issues
11
+ Project-URL: Online Calculator, https://xxlcflxx.github.io/photokinetics/calculator/photokinetics_calculator.html
12
+ Keywords: optics,photonics,photothermal,differentiable-physics,pytorch,ai-for-science,laser,optical-tweezer,physics-engine
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Topic :: Scientific/Engineering :: Physics
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Operating System :: OS Independent
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: torch>=1.10.0
28
+ Requires-Dist: numpy>=1.20.0
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=7.0; extra == "dev"
31
+ Requires-Dist: build>=0.8.0; extra == "dev"
32
+ Requires-Dist: twine>=4.0.0; extra == "dev"
33
+ Provides-Extra: examples
34
+ Requires-Dist: matplotlib>=3.5.0; extra == "examples"
35
+ Dynamic: license-file
36
+
37
+ # Photokinetics V2.0
38
+
39
+ **可微光学物理引擎 (Differentiable Optics Engine in PyTorch)**
40
+
41
+ 基于光子动能传递的光学统一计算框架,使用 PyTorch 实现,天然支持自动微分、批量计算和逆向设计。
42
+
43
+ ## 核心特性
44
+
45
+ - **可微分** — 所有公式返回 `torch.Tensor`,支持 `requires_grad=True` 自动求导
46
+ - **批量化** — 参数可以是张量,自动向量化(如批量光强扫描)
47
+ - **纯解析** — 没有数值积分,没有训练数据,直接公式计算
48
+ - **极速** — 比 1D-FDTD 快 10²~10³x,比 3D-FDTD 理论快 10⁶~10⁹x
49
+ - **统一框架** — 8 个光学模块从同一套光子动能传递公设推导
50
+
51
+ ## 安装
52
+
53
+ ```bash
54
+ pip install photokinetics
55
+ ```
56
+
57
+ ## 快速开始
58
+
59
+ ### 基本计算
60
+
61
+ ```python
62
+ from photokinetics import calc_photothermal
63
+
64
+ # 计算水在 1064nm 激光下的温升
65
+ result = calc_photothermal(
66
+ n=1.33, kappa=0.00012, wavelength_nm=1064,
67
+ I0=1e7, rho=1000, Cp=4186, depth_mm=1.0, time_s=1.0
68
+ )
69
+ print(f"温升: {result['dT'].item():.2f} K")
70
+ # 输出: 温升: 877.02 K
71
+ ```
72
+
73
+ ### 自动微分
74
+
75
+ ```python
76
+ import torch
77
+ from photokinetics import calc_photothermal
78
+
79
+ I0 = torch.tensor(1e7, requires_grad=True)
80
+ result = calc_photothermal(1.33, 0.00012, 1064, I0, 1000, 4186, 1.0, 1.0)
81
+ result['dT'].backward()
82
+
83
+ print(f"d(ΔT)/d(I₀) = {I0.grad.item():.2e}")
84
+ # 输出: 8.77e-05
85
+ ```
86
+
87
+ ### 逆向设计(梯度下降求光强)
88
+
89
+ ```python
90
+ import torch
91
+ from photokinetics import calc_photothermal
92
+
93
+ target_dT = 100.0
94
+ I0 = torch.tensor(1e5, requires_grad=True)
95
+ optimizer = torch.optim.Adam([I0], lr=5e4)
96
+
97
+ for i in range(100):
98
+ optimizer.zero_grad()
99
+ result = calc_photothermal(1.33, 0.00012, 1064, I0, 1000, 4186, 1.0, 1.0)
100
+ loss = (result['dT'] - target_dT) ** 2
101
+ loss.backward()
102
+ optimizer.step()
103
+
104
+ print(f"I₀ = {I0.item():.2e}, ΔT = {result['dT'].item():.2f} K")
105
+ # 输出: I₀ = 1.15e+06, ΔT = 100.52 K
106
+ ```
107
+
108
+ ### 批量计算
109
+
110
+ ```python
111
+ import torch
112
+ from photokinetics import calc_photothermal
113
+
114
+ I0_batch = torch.logspace(4, 8, 1000) # 1000 个光强
115
+ result = calc_photothermal(1.33, 0.00012, 1064, I0_batch, 1000, 4186, 1.0, 1.0)
116
+ print(result['dT'].shape) # torch.Size([1000])
117
+ ```
118
+
119
+ ## 8 个模块速查表
120
+
121
+ | 模块 | 函数 | 核心参数 |
122
+ |------|------|---------|
123
+ | 光电效应 | `calc_photoelectric(phi_ev, lambda_nm)` | 逸出功, 波长 |
124
+ | 黑体辐射 | `calc_blackbody(T, lambda_nm=None)` | 温度, 波长 |
125
+ | 康普顿散射 | `calc_compton(E0_keV, theta_deg)` | 入射能量, 散射角 |
126
+ | 多普勒效应 | `calc_doppler(nu0, v_km_s, receding)` | 频率, 速度 |
127
+ | 引力红移 | `calc_gravitational_redshift(M, r1, r2)` | 质量, 半径 |
128
+ | **光热模型** | `calc_photothermal(n, kappa, λ, I0, ρ, Cp, z, t)` | 8 个参数 |
129
+ | 非线性光学 | `calc_nonlinear_order(Eg_eV, lambda_nm)` | 禁带, 波长 |
130
+ | 光镊力 | `calc_tweezer_force(a, n_p, n_m, λ, grad_I)` | 半径, 折射率 |
131
+
132
+ ## 物理常数
133
+
134
+ 所有常数使用 CODATA 2018 推荐值,定义为 `torch.tensor`。
135
+
136
+ ## 性能对比
137
+
138
+ 与 1D-FDTD 数值仿真对比(绝热近似适用域内):
139
+
140
+ | 材料 | ΔT 误差 | 加速比 |
141
+ |------|---------|--------|
142
+ | 水 @ 1064nm | 3.49% | 1125x |
143
+ | 硅 @ 532nm | 0.98% | 97x |
144
+ | 锗 @ 532nm | 1.15% | 385x |
145
+
146
+ 详见 [benchmarks/](https://github.com/XxLCFLXx/photokinetics/tree/main/benchmarks)。
147
+
148
+ ## 应用场景
149
+
150
+ - **AI for Science** — 嵌入 PyTorch 做物理驱动机器学习
151
+ - **逆向设计** — 已知目标温升,梯度下降反推光强/波长
152
+ - **灵敏度分析** — 计算各参数对输出的梯度
153
+ - **参数扫描** — 批量计算数千组参数
154
+ - **实时仿真** — 解析公式微秒级计算
155
+ - **教学/科普** — 在线计算器 [在线体验](https://xxlcflxx.github.io/photokinetics/calculator/photokinetics_calculator.html)
156
+
157
+ ## 限制
158
+
159
+ - 光热模型采用绝热近似,适用条件 `t ≪ L²/D`
160
+ - 目前支持平面波入射 + 均匀介质
161
+ - 光镊力使用瑞利近似(小颗粒,a ≪ λ)
162
+
163
+ ## 引用
164
+
165
+ 如果本项目对您的研究有帮助,请引用:
166
+
167
+ ```bibtex
168
+ @misc{photokinetics2026,
169
+ title={Photokinetics V2.0: A Differentiable Optics Engine},
170
+ author={Cogito Lin},
171
+ year={2026},
172
+ url={https://github.com/XxLCFLXx/photokinetics}
173
+ }
174
+ ```
175
+
176
+ ## License
177
+
178
+ MIT
@@ -0,0 +1,21 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ photokinetics/__init__.py
5
+ photokinetics/constants.py
6
+ photokinetics/utils.py
7
+ photokinetics.egg-info/PKG-INFO
8
+ photokinetics.egg-info/SOURCES.txt
9
+ photokinetics.egg-info/dependency_links.txt
10
+ photokinetics.egg-info/requires.txt
11
+ photokinetics.egg-info/top_level.txt
12
+ photokinetics/modules/__init__.py
13
+ photokinetics/modules/blackbody.py
14
+ photokinetics/modules/compton.py
15
+ photokinetics/modules/doppler.py
16
+ photokinetics/modules/gravitational.py
17
+ photokinetics/modules/nonlinear.py
18
+ photokinetics/modules/photoelectric.py
19
+ photokinetics/modules/photothermal.py
20
+ photokinetics/modules/tweezer.py
21
+ tests/test_all.py
@@ -0,0 +1,10 @@
1
+ torch>=1.10.0
2
+ numpy>=1.20.0
3
+
4
+ [dev]
5
+ pytest>=7.0
6
+ build>=0.8.0
7
+ twine>=4.0.0
8
+
9
+ [examples]
10
+ matplotlib>=3.5.0
@@ -0,0 +1 @@
1
+ photokinetics
@@ -0,0 +1,66 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "photokinetics"
7
+ version = "2.0.0"
8
+ description = "Photokinetics V2.0 — 可微光学物理引擎 (Differentiable Optics Engine in PyTorch)"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.8"
12
+ authors = [
13
+ {name = "Cogito Lin", email = "noreply@example.com"}
14
+ ]
15
+ keywords = [
16
+ "optics",
17
+ "photonics",
18
+ "photothermal",
19
+ "differentiable-physics",
20
+ "pytorch",
21
+ "ai-for-science",
22
+ "laser",
23
+ "optical-tweezer",
24
+ "physics-engine"
25
+ ]
26
+ classifiers = [
27
+ "Development Status :: 4 - Beta",
28
+ "Intended Audience :: Science/Research",
29
+ "Topic :: Scientific/Engineering :: Physics",
30
+ "License :: OSI Approved :: MIT License",
31
+ "Programming Language :: Python :: 3",
32
+ "Programming Language :: Python :: 3.8",
33
+ "Programming Language :: Python :: 3.9",
34
+ "Programming Language :: Python :: 3.10",
35
+ "Programming Language :: Python :: 3.11",
36
+ "Programming Language :: Python :: 3.12",
37
+ "Operating System :: OS Independent",
38
+ ]
39
+ dependencies = [
40
+ "torch>=1.10.0",
41
+ "numpy>=1.20.0",
42
+ ]
43
+
44
+ [project.optional-dependencies]
45
+ dev = [
46
+ "pytest>=7.0",
47
+ "build>=0.8.0",
48
+ "twine>=4.0.0",
49
+ ]
50
+ examples = [
51
+ "matplotlib>=3.5.0",
52
+ ]
53
+
54
+ [project.urls]
55
+ Homepage = "https://github.com/XxLCFLXx/photokinetics"
56
+ Repository = "https://github.com/XxLCFLXx/photokinetics"
57
+ Documentation = "https://github.com/XxLCFLXx/photokinetics#readme"
58
+ "Bug Tracker" = "https://github.com/XxLCFLXx/photokinetics/issues"
59
+ "Online Calculator" = "https://xxlcflxx.github.io/photokinetics/calculator/photokinetics_calculator.html"
60
+
61
+ [tool.setuptools.packages.find]
62
+ where = ["."]
63
+ include = ["photokinetics*"]
64
+
65
+ [tool.setuptools.package-data]
66
+ photokinetics = ["*.md", "*.txt"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,77 @@
1
+ """Photokinetics 单元测试。"""
2
+ import torch
3
+ from photokinetics import (
4
+ calc_photoelectric,
5
+ calc_blackbody,
6
+ calc_compton,
7
+ calc_doppler,
8
+ calc_gravitational_redshift,
9
+ calc_photothermal,
10
+ calc_nonlinear_order,
11
+ calc_tweezer_force,
12
+ )
13
+
14
+
15
+ def test_photoelectric():
16
+ phi = torch.tensor(2.28, requires_grad=True)
17
+ lam = torch.tensor(400.0, requires_grad=True)
18
+ hv, occurs, vs, ek = calc_photoelectric(phi, lam)
19
+ ek.backward()
20
+ assert torch.isclose(hv, torch.tensor(3.0996), rtol=1e-4)
21
+ assert occurs.item() == True
22
+ assert torch.isclose(vs, torch.tensor(0.8196), rtol=1e-4)
23
+
24
+
25
+ def test_blackbody():
26
+ T = torch.tensor(5778.0, requires_grad=True)
27
+ lambda_max, j, _ = calc_blackbody(T, 500.0)
28
+ j.backward()
29
+ assert torch.isclose(lambda_max, torch.tensor(501.52), rtol=1e-3)
30
+ assert torch.isclose(j, torch.tensor(6.312e7), rtol=1e-2)
31
+
32
+
33
+ def test_compton():
34
+ E0 = torch.tensor(17.4, requires_grad=True)
35
+ dl, Ep, Ee = calc_compton(E0, 90.0)
36
+ Ee.backward()
37
+ assert torch.isclose(dl, torch.tensor(2.426), rtol=1e-3)
38
+
39
+
40
+ def test_doppler():
41
+ nu0 = torch.tensor(5e14, requires_grad=True)
42
+ _, _, _, z_rel = calc_doppler(nu0, 30000.0, receding=True)
43
+ z_rel.backward()
44
+ assert torch.isclose(z_rel, torch.tensor(0.1056), rtol=1e-3)
45
+
46
+
47
+ def test_gravitational():
48
+ r1 = torch.tensor(6.371e6, requires_grad=True)
49
+ dnu, z = calc_gravitational_redshift(5.9722e24, r1, 1e9)
50
+ z.backward()
51
+ assert torch.isclose(dnu, torch.tensor(6.95e-10), rtol=1e-2)
52
+
53
+
54
+ def test_photothermal():
55
+ I0 = torch.tensor(1e7, requires_grad=True)
56
+ result = calc_photothermal(1.33, 0.00012, 1064, I0, 1000, 4186, 1.0, 1.0)
57
+ result['dT'].backward()
58
+ assert torch.isclose(result['dT'], torch.tensor(877.02), rtol=1e-2)
59
+
60
+
61
+ def test_nonlinear():
62
+ N, hv = calc_nonlinear_order(1.12, 800.0)
63
+ assert N.item() == 1
64
+
65
+
66
+ def test_tweezer():
67
+ a = torch.tensor(1e-6, requires_grad=True)
68
+ result = calc_tweezer_force(a, 1.59, 1.33, 1064.0, 5e17)
69
+ result['F_grad'].backward()
70
+ assert a.grad is not None
71
+
72
+
73
+ def test_batch():
74
+ I0_batch = torch.tensor([1e6, 1e7, 1e8], requires_grad=True)
75
+ result = calc_photothermal(1.33, 0.00012, 1064, I0_batch, 1000, 4186, 1.0, 1.0)
76
+ result['dT'].sum().backward()
77
+ assert I0_batch.grad is not None