pulsus-spec 0.1.1__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.
- pulsus_spec-0.1.1/LICENSE +30 -0
- pulsus_spec-0.1.1/PKG-INFO +652 -0
- pulsus_spec-0.1.1/README.md +626 -0
- pulsus_spec-0.1.1/pyproject.toml +59 -0
- pulsus_spec-0.1.1/setup.cfg +4 -0
- pulsus_spec-0.1.1/src/pulsus/__init__.py +133 -0
- pulsus_spec-0.1.1/src/pulsus/linear.py +518 -0
- pulsus_spec-0.1.1/src/pulsus/liouville.py +213 -0
- pulsus_spec-0.1.1/src/pulsus/plotting.py +192 -0
- pulsus_spec-0.1.1/src/pulsus/pulses.py +211 -0
- pulsus_spec-0.1.1/src/pulsus/resolvents.py +74 -0
- pulsus_spec-0.1.1/src/pulsus/response.py +872 -0
- pulsus_spec-0.1.1/src/pulsus/spectra.py +594 -0
- pulsus_spec-0.1.1/src/pulsus/system.py +115 -0
- pulsus_spec-0.1.1/src/pulsus/time_domain.py +798 -0
- pulsus_spec-0.1.1/src/pulsus_spec.egg-info/PKG-INFO +652 -0
- pulsus_spec-0.1.1/src/pulsus_spec.egg-info/SOURCES.txt +31 -0
- pulsus_spec-0.1.1/src/pulsus_spec.egg-info/dependency_links.txt +1 -0
- pulsus_spec-0.1.1/src/pulsus_spec.egg-info/requires.txt +7 -0
- pulsus_spec-0.1.1/src/pulsus_spec.egg-info/top_level.txt +1 -0
- pulsus_spec-0.1.1/tests/test_conjugation_symmetry.py +93 -0
- pulsus_spec-0.1.1/tests/test_finite_pulse_rwa.py +171 -0
- pulsus_spec-0.1.1/tests/test_linear.py +357 -0
- pulsus_spec-0.1.1/tests/test_liouville.py +100 -0
- pulsus_spec-0.1.1/tests/test_notebook01_regression.py +245 -0
- pulsus_spec-0.1.1/tests/test_notebook04_regression.py +499 -0
- pulsus_spec-0.1.1/tests/test_plotting.py +172 -0
- pulsus_spec-0.1.1/tests/test_pulses.py +241 -0
- pulsus_spec-0.1.1/tests/test_resolvents.py +71 -0
- pulsus_spec-0.1.1/tests/test_response.py +402 -0
- pulsus_spec-0.1.1/tests/test_spectra.py +731 -0
- pulsus_spec-0.1.1/tests/test_system.py +321 -0
- pulsus_spec-0.1.1/tests/test_time_domain.py +449 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Alfonso Castillo-Gonzalez
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
10
|
+
this list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
23
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
24
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
25
|
+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
26
|
+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
27
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
28
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
29
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
30
|
+
POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,652 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pulsus-spec
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Pulse-dressed Liouvillian Spectroscopy Using Superoperators
|
|
5
|
+
Author: Alfonso Castillo-Gonzalez
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
Keywords: spectroscopy,nonlinear spectroscopy,quantum dynamics,open quantum systems,Liouville space,superoperators
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: numpy
|
|
20
|
+
Requires-Dist: scipy
|
|
21
|
+
Requires-Dist: matplotlib
|
|
22
|
+
Requires-Dist: qutip
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest; extra == "dev"
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# PULSUS
|
|
28
|
+
|
|
29
|
+
**PULSUS**: **PU**lse-dressed **L**iouvillian **S**pectroscopy **U**sing **S**uperoperators.
|
|
30
|
+
|
|
31
|
+
PULSUS is a Python package for direct frequency-domain spectroscopy of open quantum systems using Liouville-space superoperators.
|
|
32
|
+
|
|
33
|
+
PULSUS `v0.1.1` focuses on linear and third-order spectroscopy with time-independent Markovian Liouvillian dynamics, including finite Gaussian pulses, impulsive limits, rotating-wave approximations, arbitrary field-sign sectors, and complementary impulsive time-domain calculations.
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
## Core idea
|
|
37
|
+
|
|
38
|
+
For a field-free Liouvillian
|
|
39
|
+
|
|
40
|
+
\[
|
|
41
|
+
\mathcal{L},
|
|
42
|
+
\]
|
|
43
|
+
|
|
44
|
+
PULSUS evaluates frequency-domain propagation using resolvent actions
|
|
45
|
+
|
|
46
|
+
\[
|
|
47
|
+
G_\eta(\omega)
|
|
48
|
+
=
|
|
49
|
+
\left[
|
|
50
|
+
(\eta-i\omega)I-\mathcal{L}
|
|
51
|
+
\right]^{-1},
|
|
52
|
+
\]
|
|
53
|
+
|
|
54
|
+
without explicitly constructing the matrix inverse.
|
|
55
|
+
|
|
56
|
+
Finite Gaussian pulses are represented by Liouvillian dressing operators. For example,
|
|
57
|
+
|
|
58
|
+
\[
|
|
59
|
+
F_1^{(s)}
|
|
60
|
+
=
|
|
61
|
+
C e^{is\Phi}
|
|
62
|
+
\exp\left[
|
|
63
|
+
\frac{\sigma^2}{2}
|
|
64
|
+
\left(
|
|
65
|
+
\mathcal{L}
|
|
66
|
+
+i(\omega_1-s\omega_L)I
|
|
67
|
+
\right)^2
|
|
68
|
+
\right].
|
|
69
|
+
\]
|
|
70
|
+
|
|
71
|
+
The production finite-pulse implementation uses the physical field-free Liouvillian inside the pulse dressing,
|
|
72
|
+
|
|
73
|
+
\[
|
|
74
|
+
F_j = F_j(\mathcal{L}),
|
|
75
|
+
\]
|
|
76
|
+
|
|
77
|
+
while the resolvents may use a small positive broadening parameter \(\eta\).
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
## Standard finite-pulse assumption
|
|
81
|
+
|
|
82
|
+
The standard finite-pulse formulation assumes that the state immediately before the pulse sequence is stationary under the field-free Liouvillian,
|
|
83
|
+
|
|
84
|
+
\[
|
|
85
|
+
\mathcal{L}|\rho_0\rangle\rangle = 0.
|
|
86
|
+
\]
|
|
87
|
+
|
|
88
|
+
For dissipative systems this is typically the stationary state of the Liouvillian.
|
|
89
|
+
|
|
90
|
+
PULSUS can also accept explicitly supplied initial density matrices for calculations where this assumption is not desired.
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
## Third-order spectroscopy
|
|
94
|
+
|
|
95
|
+
PULSUS currently provides four principal third-order models:
|
|
96
|
+
|
|
97
|
+
| Function | Pulse treatment | Light-matter interaction |
|
|
98
|
+
| --- | --- | --- |
|
|
99
|
+
| `finite_pulse_spectrum` | finite Gaussian pulses | full interaction |
|
|
100
|
+
| `impulsive_spectrum` | impulsive | full interaction |
|
|
101
|
+
| `short_pulse_rwa_spectrum` | Gaussian spectral envelopes | RWA |
|
|
102
|
+
| `impulsive_rwa_spectrum` | impulsive | RWA |
|
|
103
|
+
|
|
104
|
+
The impulsive approximation and the rotating-wave approximation are treated as distinct approximations.
|
|
105
|
+
|
|
106
|
+
In particular,
|
|
107
|
+
|
|
108
|
+
\[
|
|
109
|
+
\sigma \rightarrow 0
|
|
110
|
+
\]
|
|
111
|
+
|
|
112
|
+
for the full finite-pulse theory approaches the impulsive **full-interaction** response, not automatically the impulsive RWA response.
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
## Linear spectroscopy
|
|
116
|
+
|
|
117
|
+
The corresponding linear-response calculations are available through:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
pulsus.finite_pulse_linear_spectrum
|
|
121
|
+
pulsus.impulsive_linear_spectrum
|
|
122
|
+
pulsus.short_pulse_linear_rwa_spectrum
|
|
123
|
+
pulsus.impulsive_linear_rwa_spectrum
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
## Installation
|
|
128
|
+
|
|
129
|
+
Install the released package from PyPI with:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
pip install pulsus-spec
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The PyPI distribution is named `pulsus-spec`, while the Python package is imported as:
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
import pulsus
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
For development from the repository source:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
python -m venv .venv
|
|
145
|
+
source .venv/bin/activate
|
|
146
|
+
python -m pip install -e ".[dev]"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Run the test suite with:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
pytest -q
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Basic usage
|
|
156
|
+
|
|
157
|
+
A spectroscopy model is defined using `SpectroscopySystem`:
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
import pulsus
|
|
161
|
+
|
|
162
|
+
system = pulsus.SpectroscopySystem(
|
|
163
|
+
H=H,
|
|
164
|
+
dipole=mu,
|
|
165
|
+
collapse_ops=collapse_ops,
|
|
166
|
+
)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The stationary state can be obtained from:
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
rho_ss = system.stationary_state()
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
A Gaussian pulse is specified by its carrier frequency, temporal width, amplitude, and phase:
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
pulse = pulsus.GaussianPulse(
|
|
179
|
+
omega_L=1.10,
|
|
180
|
+
sigma=1.25,
|
|
181
|
+
E0=1.0,
|
|
182
|
+
phase=0.0,
|
|
183
|
+
)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
A finite-pulse nonrephasing spectrum can then be evaluated directly:
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
import numpy as np
|
|
190
|
+
|
|
191
|
+
omega1 = np.linspace(0.7, 1.5, 81)
|
|
192
|
+
omega3 = np.linspace(0.7, 1.5, 81)
|
|
193
|
+
|
|
194
|
+
S_NR = pulsus.finite_pulse_spectrum(
|
|
195
|
+
system=system,
|
|
196
|
+
pulse1=pulse,
|
|
197
|
+
pulse2=pulse,
|
|
198
|
+
pulse3=pulse,
|
|
199
|
+
omega1=omega1,
|
|
200
|
+
omega3=omega3,
|
|
201
|
+
T=20.0,
|
|
202
|
+
eta=0.02,
|
|
203
|
+
pathway="NR",
|
|
204
|
+
)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The returned complex array has shape:
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
(len(omega3), len(omega1))
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
with convention
|
|
214
|
+
|
|
215
|
+
\[
|
|
216
|
+
S[j,i]
|
|
217
|
+
=
|
|
218
|
+
S(\omega_{3,j},\omega_{1,i}).
|
|
219
|
+
\]
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
## Rephasing and nonrephasing convention
|
|
223
|
+
|
|
224
|
+
PULSUS uses signed first-coherence frequencies.
|
|
225
|
+
|
|
226
|
+
For the nonrephasing sector,
|
|
227
|
+
|
|
228
|
+
\[
|
|
229
|
+
\omega_1>0,
|
|
230
|
+
\]
|
|
231
|
+
|
|
232
|
+
with field-sign signature
|
|
233
|
+
|
|
234
|
+
\[
|
|
235
|
+
(+,-,+).
|
|
236
|
+
\]
|
|
237
|
+
|
|
238
|
+
For the rephasing sector,
|
|
239
|
+
|
|
240
|
+
\[
|
|
241
|
+
\omega_1<0,
|
|
242
|
+
\]
|
|
243
|
+
|
|
244
|
+
with field-sign signature
|
|
245
|
+
|
|
246
|
+
\[
|
|
247
|
+
(-,+,+).
|
|
248
|
+
\]
|
|
249
|
+
|
|
250
|
+
For example:
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
omega1_NR = np.linspace(0.7, 1.5, 81)
|
|
254
|
+
omega1_R = -omega1_NR
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
The rephasing spectrum may be displayed against the positive spectroscopic excitation coordinate `-omega1_R`, but the calculation itself uses signed negative first-coherence frequencies.
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
## Arbitrary field-sign sectors
|
|
261
|
+
|
|
262
|
+
PULSUS is not restricted to R and NR pathways.
|
|
263
|
+
|
|
264
|
+
Any third-order signature
|
|
265
|
+
|
|
266
|
+
\[
|
|
267
|
+
(s_1,s_2,s_3),
|
|
268
|
+
\qquad
|
|
269
|
+
s_j=\pm1,
|
|
270
|
+
\]
|
|
271
|
+
|
|
272
|
+
can be supplied explicitly.
|
|
273
|
+
|
|
274
|
+
For example:
|
|
275
|
+
|
|
276
|
+
```python
|
|
277
|
+
signature = (+1, +1, +1)
|
|
278
|
+
|
|
279
|
+
S = pulsus.finite_pulse_spectrum(
|
|
280
|
+
system=system,
|
|
281
|
+
pulse1=pulse,
|
|
282
|
+
pulse2=pulse,
|
|
283
|
+
pulse3=pulse,
|
|
284
|
+
omega1=omega1,
|
|
285
|
+
omega3=omega3,
|
|
286
|
+
T=20.0,
|
|
287
|
+
eta=0.02,
|
|
288
|
+
signature=signature,
|
|
289
|
+
)
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
The aliases
|
|
293
|
+
|
|
294
|
+
```python
|
|
295
|
+
pathway="NR"
|
|
296
|
+
pathway="R"
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
remain available for the standard nonrephasing and rephasing sectors.
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
## Sign-reversed conjugation symmetry
|
|
303
|
+
|
|
304
|
+
For the tested coupled-dimer model, the field-sign sectors satisfy
|
|
305
|
+
|
|
306
|
+
\[
|
|
307
|
+
S_{(-s_1,-s_2,-s_3)}
|
|
308
|
+
(-\omega_1,-\omega_3)
|
|
309
|
+
=
|
|
310
|
+
S_{(s_1,s_2,s_3)}
|
|
311
|
+
(\omega_1,\omega_3)^*
|
|
312
|
+
\]
|
|
313
|
+
|
|
314
|
+
to floating-point precision.
|
|
315
|
+
|
|
316
|
+
This groups the eight possible signatures into four sign-reversed conjugate pairs.
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
## Full interaction and RWA
|
|
320
|
+
|
|
321
|
+
Full-interaction calculations require only the total dipole operator
|
|
322
|
+
|
|
323
|
+
\[
|
|
324
|
+
\mu.
|
|
325
|
+
\]
|
|
326
|
+
|
|
327
|
+
RWA calculations additionally require a decomposition
|
|
328
|
+
|
|
329
|
+
\[
|
|
330
|
+
\mu = \mu_+ + \mu_-.
|
|
331
|
+
\]
|
|
332
|
+
|
|
333
|
+
For example:
|
|
334
|
+
|
|
335
|
+
```python
|
|
336
|
+
system = pulsus.SpectroscopySystem(
|
|
337
|
+
H=H,
|
|
338
|
+
dipole=mu,
|
|
339
|
+
collapse_ops=collapse_ops,
|
|
340
|
+
dipole_plus=mu_plus,
|
|
341
|
+
dipole_minus=mu_minus,
|
|
342
|
+
)
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
PULSUS currently requires this decomposition to be supplied explicitly rather than inferring it automatically.
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
## Time-domain calculations
|
|
349
|
+
|
|
350
|
+
PULSUS also provides impulsive time-domain response functions.
|
|
351
|
+
|
|
352
|
+
For linear spectroscopy:
|
|
353
|
+
|
|
354
|
+
```python
|
|
355
|
+
R_t = pulsus.impulsive_linear_rwa_time_signal(
|
|
356
|
+
system=system,
|
|
357
|
+
times=times,
|
|
358
|
+
sign=+1,
|
|
359
|
+
)
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
For third-order spectroscopy:
|
|
363
|
+
|
|
364
|
+
```python
|
|
365
|
+
R_t3_t1 = pulsus.impulsive_third_order_rwa_time_signal(
|
|
366
|
+
system=system,
|
|
367
|
+
t1=t1,
|
|
368
|
+
t3=t3,
|
|
369
|
+
T=20.0,
|
|
370
|
+
pathway="NR",
|
|
371
|
+
)
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
These provide a complementary time-domain representation of the same impulsive Liouvillian dynamics used in the direct frequency-domain formulation.
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
## Pathway polarization in laboratory time
|
|
378
|
+
|
|
379
|
+
A selected RWA pathway can also be followed through the sequence of three impulsive interactions:
|
|
380
|
+
|
|
381
|
+
```python
|
|
382
|
+
P, components = pulsus.impulsive_pathway_polarization(
|
|
383
|
+
system=system,
|
|
384
|
+
times=times,
|
|
385
|
+
pulse_times=(5.0, 15.0, 35.0),
|
|
386
|
+
signature=(+1, -1, +1),
|
|
387
|
+
return_components=True,
|
|
388
|
+
)
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
The resulting polarization is piecewise associated with the perturbative state active between pulses:
|
|
392
|
+
|
|
393
|
+
\[
|
|
394
|
+
P_{\mathrm{path}}(t)
|
|
395
|
+
=
|
|
396
|
+
\begin{cases}
|
|
397
|
+
0,
|
|
398
|
+
& t<\tau_1,\\
|
|
399
|
+
P^{(1)}(t),
|
|
400
|
+
& \tau_1\le t<\tau_2,\\
|
|
401
|
+
P^{(2)}(t),
|
|
402
|
+
& \tau_2\le t<\tau_3,\\
|
|
403
|
+
P^{(3)}(t),
|
|
404
|
+
& t\ge\tau_3.
|
|
405
|
+
\end{cases}
|
|
406
|
+
\]
|
|
407
|
+
|
|
408
|
+
This is the polarization of the **selected pathway**, not the total physical polarization from all perturbative orders and all field-sign sectors.
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
## Complex spectra and plotting
|
|
412
|
+
|
|
413
|
+
PULSUS retains the complete complex response.
|
|
414
|
+
|
|
415
|
+
A spectrum can be plotted with:
|
|
416
|
+
|
|
417
|
+
```python
|
|
418
|
+
pulsus.plot_spectrum(
|
|
419
|
+
omega1=omega1,
|
|
420
|
+
omega3=omega3,
|
|
421
|
+
spectrum=S_NR,
|
|
422
|
+
component="imag",
|
|
423
|
+
normalize=True,
|
|
424
|
+
)
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Supported displayed components are:
|
|
428
|
+
|
|
429
|
+
- `"real"`
|
|
430
|
+
- `"imag"`
|
|
431
|
+
- `"abs"`
|
|
432
|
+
|
|
433
|
+
Normalization is optional and disabled by default.
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
## Numerical implementation
|
|
437
|
+
|
|
438
|
+
Two-dimensional spectrum calculations exploit the separable dependence on the excitation and detection frequencies.
|
|
439
|
+
|
|
440
|
+
For a third-order response, the grid can be written schematically as
|
|
441
|
+
|
|
442
|
+
\[
|
|
443
|
+
S_{ji}=L_jR_i,
|
|
444
|
+
\]
|
|
445
|
+
|
|
446
|
+
where \(R_i\) contains the \(\omega_1\)-dependent operations and \(L_j\) contains the \(\omega_3\)-dependent operations.
|
|
447
|
+
|
|
448
|
+
This avoids repeating expensive matrix exponentials and resolvent solves independently at every pair
|
|
449
|
+
|
|
450
|
+
\[
|
|
451
|
+
(\omega_1,\omega_3).
|
|
452
|
+
\]
|
|
453
|
+
|
|
454
|
+
The optimized implementation reproduces the original point-by-point calculations to floating-point precision.
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
## Validation
|
|
458
|
+
|
|
459
|
+
PULSUS is tested against independently validated coupled-dimer calculations, frozen reference spectra, and explicit time-domain propagation.
|
|
460
|
+
|
|
461
|
+
For the finite-pulse development benchmark at
|
|
462
|
+
|
|
463
|
+
\[
|
|
464
|
+
\sigma=1.25,
|
|
465
|
+
\qquad
|
|
466
|
+
T=20,
|
|
467
|
+
\qquad
|
|
468
|
+
\eta=0.02,
|
|
469
|
+
\]
|
|
470
|
+
|
|
471
|
+
the production finite-pulse calculation gives complex spectral-shape discrepancies relative to an explicit finite-pulse time-domain ODE calculation of approximately
|
|
472
|
+
|
|
473
|
+
\[
|
|
474
|
+
0.61\%
|
|
475
|
+
\quad \text{(NR)}
|
|
476
|
+
\]
|
|
477
|
+
|
|
478
|
+
and
|
|
479
|
+
|
|
480
|
+
\[
|
|
481
|
+
0.64\%
|
|
482
|
+
\quad \text{(R)}.
|
|
483
|
+
\]
|
|
484
|
+
|
|
485
|
+
For comparison:
|
|
486
|
+
|
|
487
|
+
| Model | NR error | R error |
|
|
488
|
+
| --- | ---: | ---: |
|
|
489
|
+
| Finite-width PULSUS | 0.61% | 0.64% |
|
|
490
|
+
| Short-pulse RWA | 5.51% | 5.81% |
|
|
491
|
+
| Impulsive RWA | 9.60% | 9.83% |
|
|
492
|
+
|
|
493
|
+
These values characterize this development benchmark and are not universal accuracy bounds.
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
## Time-domain versus frequency-domain validation
|
|
497
|
+
|
|
498
|
+
For impulsive linear RWA response, numerical time propagation followed by an FFT agrees with the direct frequency-domain resolvent calculation with a relative complex error of approximately
|
|
499
|
+
|
|
500
|
+
\[
|
|
501
|
+
0.0035\%.
|
|
502
|
+
\]
|
|
503
|
+
|
|
504
|
+
For impulsive third-order NR response, two-dimensional time propagation followed by a 2D FFT agrees with the direct frequency-domain result with a relative complex error of approximately
|
|
505
|
+
|
|
506
|
+
\[
|
|
507
|
+
0.015\%.
|
|
508
|
+
\]
|
|
509
|
+
|
|
510
|
+
These comparisons independently validate the time/frequency sign and transform conventions used in PULSUS.
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
## Test suite
|
|
514
|
+
|
|
515
|
+
The current test suite contains **63 passing unit and regression tests** covering:
|
|
516
|
+
|
|
517
|
+
- Liouville-space vectorization and superoperators
|
|
518
|
+
- Lindblad Liouvillian construction
|
|
519
|
+
- stationary states
|
|
520
|
+
- resolvent actions
|
|
521
|
+
- Gaussian pulse dressing
|
|
522
|
+
- pulse-integral identities
|
|
523
|
+
- linear response
|
|
524
|
+
- third-order response
|
|
525
|
+
- R and NR sign conventions
|
|
526
|
+
- arbitrary field-sign signatures
|
|
527
|
+
- finite-pulse, impulsive, short-pulse, and RWA models
|
|
528
|
+
- two-dimensional spectrum construction
|
|
529
|
+
- optimized versus point-by-point evaluation
|
|
530
|
+
- plotting and array orientation
|
|
531
|
+
- frozen finite-pulse regression data
|
|
532
|
+
- impulsive time-domain propagation
|
|
533
|
+
- time-domain pathway polarization
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
## Examples
|
|
537
|
+
|
|
538
|
+
The `examples/` directory contains the current development and validation examples.
|
|
539
|
+
|
|
540
|
+
### Main examples
|
|
541
|
+
|
|
542
|
+
`01_finite_pulse_dimer.py`
|
|
543
|
+
|
|
544
|
+
Builds the coupled dimer and calculates finite-pulse NR and R spectra through the PULSUS API.
|
|
545
|
+
|
|
546
|
+
`03_reproduce_figure6.py`
|
|
547
|
+
|
|
548
|
+
Compares finite-pulse, short-pulse RWA, and impulsive RWA spectra.
|
|
549
|
+
|
|
550
|
+
`06_all_third_order_signatures.py`
|
|
551
|
+
|
|
552
|
+
Calculates all eight third-order field-sign sectors and checks the sign-reversed conjugation relation.
|
|
553
|
+
|
|
554
|
+
`09_linear_td_fft_vs_fd.py`
|
|
555
|
+
|
|
556
|
+
Validates impulsive linear time-domain propagation and FFT against the direct frequency-domain resolvent calculation.
|
|
557
|
+
|
|
558
|
+
`10_third_order_td_fft_vs_fd.py`
|
|
559
|
+
|
|
560
|
+
Validates third-order NR time-domain propagation and a 2D FFT against the direct frequency-domain calculation.
|
|
561
|
+
|
|
562
|
+
`11_impulsive_polarization_traces.py`
|
|
563
|
+
|
|
564
|
+
Visualizes the selected impulsive pathway in laboratory time and separates first-, second-, and third-order polarization stages.
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
### Validation and diagnostic examples
|
|
568
|
+
|
|
569
|
+
`02_compare_notebook04.py`
|
|
570
|
+
|
|
571
|
+
Compares the production finite-pulse implementation with frozen explicit-ODE validation data.
|
|
572
|
+
|
|
573
|
+
`04_linear_response_comparison.py`
|
|
574
|
+
|
|
575
|
+
Compares full-interaction and RWA linear spectra.
|
|
576
|
+
|
|
577
|
+
`05_linear_rwa_quadratures.py`
|
|
578
|
+
|
|
579
|
+
Examines real and imaginary quadratures of the linear full-interaction and RWA responses.
|
|
580
|
+
|
|
581
|
+
`07_full_vs_rwa_signatures.py`
|
|
582
|
+
|
|
583
|
+
Compares finite-pulse full-interaction and short-pulse RWA results across third-order signatures.
|
|
584
|
+
|
|
585
|
+
`08_approximation_ladder.py`
|
|
586
|
+
|
|
587
|
+
Separates the effects of the full-interaction, RWA, short-pulse, and impulsive approximations.
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
## Current scope
|
|
591
|
+
|
|
592
|
+
PULSUS `v0.1.1` assumes:
|
|
593
|
+
|
|
594
|
+
- finite-dimensional quantum systems
|
|
595
|
+
- time-independent Liouvillian dynamics
|
|
596
|
+
- Markovian Lindblad evolution
|
|
597
|
+
- electric-dipole light-matter coupling
|
|
598
|
+
- Gaussian finite-duration pulses for the finite-pulse frequency-domain formulation
|
|
599
|
+
- temporally ordered, separated pulses
|
|
600
|
+
- linear and third-order response
|
|
601
|
+
- full-interaction and RWA calculations
|
|
602
|
+
- arbitrary third-order field-sign signatures
|
|
603
|
+
- impulsive time-domain propagation
|
|
604
|
+
|
|
605
|
+
Finite-duration driven time-domain propagation is not currently part of the public production API.
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
## Public API philosophy
|
|
609
|
+
|
|
610
|
+
The principal user-facing objects and functions are:
|
|
611
|
+
|
|
612
|
+
```python
|
|
613
|
+
pulsus.SpectroscopySystem
|
|
614
|
+
pulsus.GaussianPulse
|
|
615
|
+
|
|
616
|
+
pulsus.finite_pulse_spectrum
|
|
617
|
+
pulsus.impulsive_spectrum
|
|
618
|
+
pulsus.short_pulse_rwa_spectrum
|
|
619
|
+
pulsus.impulsive_rwa_spectrum
|
|
620
|
+
|
|
621
|
+
pulsus.finite_pulse_linear_spectrum
|
|
622
|
+
pulsus.impulsive_linear_spectrum
|
|
623
|
+
pulsus.short_pulse_linear_rwa_spectrum
|
|
624
|
+
pulsus.impulsive_linear_rwa_spectrum
|
|
625
|
+
|
|
626
|
+
pulsus.impulsive_linear_time_signal
|
|
627
|
+
pulsus.impulsive_third_order_rwa_time_signal
|
|
628
|
+
pulsus.impulsive_pathway_polarization
|
|
629
|
+
|
|
630
|
+
pulsus.plot_spectrum
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
Additional lower-level response, Liouville-space, resolvent, and pulse-dressing functions remain available for advanced calculations and validation.
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
## Repository structure
|
|
637
|
+
|
|
638
|
+
```text
|
|
639
|
+
.
|
|
640
|
+
├── src/
|
|
641
|
+
│ └── pulsus/ PULSUS source code
|
|
642
|
+
├── tests/ unit and regression tests
|
|
643
|
+
├── examples/ usage and validation examples
|
|
644
|
+
├── notebooks/ numerical validation notebooks
|
|
645
|
+
├── figures/ manuscript figures
|
|
646
|
+
├── results/ benchmark results
|
|
647
|
+
├── main.tex manuscript / technical development
|
|
648
|
+
├── references.bib bibliography
|
|
649
|
+
└── literature_notes.md literature notes
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
PULSUS is under active development.
|