wavepacket 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wavepacket-0.1.0/LICENSE +21 -0
- wavepacket-0.1.0/PKG-INFO +111 -0
- wavepacket-0.1.0/README.rst +83 -0
- wavepacket-0.1.0/pyproject.toml +41 -0
- wavepacket-0.1.0/src/wavepacket/__init__.py +25 -0
- wavepacket-0.1.0/src/wavepacket/builder/__init__.py +8 -0
- wavepacket-0.1.0/src/wavepacket/builder/density.py +73 -0
- wavepacket-0.1.0/src/wavepacket/builder/wave_function.py +63 -0
- wavepacket-0.1.0/src/wavepacket/exceptions.py +48 -0
- wavepacket-0.1.0/src/wavepacket/expression/__init__.py +10 -0
- wavepacket-0.1.0/src/wavepacket/expression/expressionbase.py +44 -0
- wavepacket-0.1.0/src/wavepacket/expression/liouvillian.py +64 -0
- wavepacket-0.1.0/src/wavepacket/expression/schroedingerequation.py +65 -0
- wavepacket-0.1.0/src/wavepacket/generators.py +88 -0
- wavepacket-0.1.0/src/wavepacket/grid/__init__.py +12 -0
- wavepacket-0.1.0/src/wavepacket/grid/dofbase.py +191 -0
- wavepacket-0.1.0/src/wavepacket/grid/grid.py +145 -0
- wavepacket-0.1.0/src/wavepacket/grid/planewavedof.py +102 -0
- wavepacket-0.1.0/src/wavepacket/grid/state.py +93 -0
- wavepacket-0.1.0/src/wavepacket/grid/state_utilities.py +89 -0
- wavepacket-0.1.0/src/wavepacket/logging.py +34 -0
- wavepacket-0.1.0/src/wavepacket/operator/__init__.py +12 -0
- wavepacket-0.1.0/src/wavepacket/operator/fbroperators.py +94 -0
- wavepacket-0.1.0/src/wavepacket/operator/operatorbase.py +204 -0
- wavepacket-0.1.0/src/wavepacket/operator/operatorutils.py +30 -0
- wavepacket-0.1.0/src/wavepacket/operator/potentials.py +43 -0
- wavepacket-0.1.0/src/wavepacket/solver/__init__.py +8 -0
- wavepacket-0.1.0/src/wavepacket/solver/odesolver.py +70 -0
- wavepacket-0.1.0/src/wavepacket/solver/solverbase.py +119 -0
- wavepacket-0.1.0/src/wavepacket/testing/__init__.py +11 -0
- wavepacket-0.1.0/src/wavepacket/testing/assertions.py +20 -0
- wavepacket-0.1.0/src/wavepacket/testing/dummydof.py +22 -0
- wavepacket-0.1.0/src/wavepacket/testing/dummyoperator.py +26 -0
- wavepacket-0.1.0/src/wavepacket/testing/random.py +16 -0
- wavepacket-0.1.0/src/wavepacket/typing/__init__.py +7 -0
- wavepacket-0.1.0/src/wavepacket/typing/data_types.py +32 -0
wavepacket-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Ulf Lorenz
|
|
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,111 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wavepacket
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A package for the propagation of quantum-mechanical wave functions.
|
|
5
|
+
Author: Ulf Lorenz
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Description-Content-Type: text/x-rst
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: numpy >= 2.1.3
|
|
15
|
+
Requires-Dist: scipy >= 1.14.1
|
|
16
|
+
Requires-Dist: matplotlib >= 3.10 ; extra == "demos"
|
|
17
|
+
Requires-Dist: sphinx >= 8.1.3 ; extra == "doc"
|
|
18
|
+
Requires-Dist: sphinx-autoapi >= 3.4.0 ; extra == "doc"
|
|
19
|
+
Requires-Dist: numpydoc >= 1.8.0 ; extra == "doc"
|
|
20
|
+
Requires-Dist: myst-nb >= 1.2 ; extra == "doc"
|
|
21
|
+
Requires-Dist: sphinx-rtd-theme >= 3.0.2 ; extra == "doc"
|
|
22
|
+
Requires-Dist: pytest >= 8.3 ; extra == "test"
|
|
23
|
+
Project-URL: Home, https://github.com/ulflor/wavepacket
|
|
24
|
+
Provides-Extra: demos
|
|
25
|
+
Provides-Extra: doc
|
|
26
|
+
Provides-Extra: test
|
|
27
|
+
|
|
28
|
+
Description
|
|
29
|
+
-----------
|
|
30
|
+
|
|
31
|
+
Wavepacket is a Python package to define and simulate small
|
|
32
|
+
quantum systems. Or, more technically, it allows you to numerically
|
|
33
|
+
solve Schrödinger and Liouville-von-Neumann equations for
|
|
34
|
+
distinguishable particles.
|
|
35
|
+
|
|
36
|
+
The full documentation can be found under https://wavepacket.readthedocs.io.
|
|
37
|
+
|
|
38
|
+
There are many different quantum systems and consequently approaches
|
|
39
|
+
to solve them. Here we focus on a particular niche:
|
|
40
|
+
|
|
41
|
+
- Wavepacket solves the differential equations directly. This simplifies
|
|
42
|
+
the maths, but limits the system size to few degrees of freedom.
|
|
43
|
+
If you want to deal with larger systems, look out for MCTDH.
|
|
44
|
+
- Wavepacket uses the DVR approximation heavily. This allows you to
|
|
45
|
+
directly define your potentials as functions of real-space coordinates
|
|
46
|
+
instead of setting up opaque operator matrices.
|
|
47
|
+
The latter approach is simpler an more concise if you are only
|
|
48
|
+
interested in harmonic oscillators or qubits, though.
|
|
49
|
+
- Wavepacket is a Python-only package relying chiefly on numpy.
|
|
50
|
+
This is slower than natively implemented code, but you gain
|
|
51
|
+
great tooling support, for example matplotlib, Jupyter notebooks or
|
|
52
|
+
integrated documentation.
|
|
53
|
+
- Most of the code can handle both wave functions and density operators.
|
|
54
|
+
This allows you to convert a closed system into an open
|
|
55
|
+
system with minimal fuss.
|
|
56
|
+
|
|
57
|
+
For example use cases, we have been using various precursors of this
|
|
58
|
+
package for simulating small molecular systems and for teaching.
|
|
59
|
+
Besides examples shipped with this package, see
|
|
60
|
+
https://sourceforge.net/p/wavepacket/wiki/Demos.Main for more applications.
|
|
61
|
+
|
|
62
|
+
The project is currently a first iteration to flesh out everything. Once
|
|
63
|
+
0.1 is released, I plan to quickly translate the existing C++ code from
|
|
64
|
+
a precursor project and reach a stable state. More can be found on the
|
|
65
|
+
project homepage https://github.com/ulflor/wavepacket
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
Support
|
|
69
|
+
-------
|
|
70
|
+
|
|
71
|
+
If you lack a feature that you would like to have, open an issue at
|
|
72
|
+
`our issue tracker <https://github.com/ulflor/wavepacket/issues>`_.
|
|
73
|
+
Depending on the complexity of the feature, this will lead to an immediate,
|
|
74
|
+
rapid, or prioritized implementation.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
Contribution
|
|
78
|
+
------------
|
|
79
|
+
|
|
80
|
+
I currently lack a formal procedure for new contributors, but you are
|
|
81
|
+
very welcome to contribute to the project. If you do not know what to
|
|
82
|
+
do, feel free to contact one of the developers; there is enough work for
|
|
83
|
+
multiple developers, it is just not documented yet.
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
History
|
|
87
|
+
-------
|
|
88
|
+
|
|
89
|
+
The original version of Wavepacket was written in Matlab and is still
|
|
90
|
+
maintained under https://sourceforge.net/p/wavepacket/matlab. It is stable,
|
|
91
|
+
battle-tested and works.
|
|
92
|
+
|
|
93
|
+
However, Matlab is pretty expensive, so not all interested users had
|
|
94
|
+
access to it. Also, the project's architecture did not support some
|
|
95
|
+
advanced use cases without digging deep into the code. Finally,
|
|
96
|
+
C++11 had just come out and looked cool, so I started a
|
|
97
|
+
reimplementation in C++ around 2013, adding Python bindings as an
|
|
98
|
+
afterthought. The C++ project will be superseded by this Python package, but
|
|
99
|
+
can be found under https://sourceforge.net/p/wavepacket/cpp.
|
|
100
|
+
|
|
101
|
+
This worked really well. However, deploying C++ code is difficult.
|
|
102
|
+
In particular, there was no cheap route towards building a "good"
|
|
103
|
+
Python package, or towards easily building a Windows version.
|
|
104
|
+
Also, the underlying tensor library was slowly
|
|
105
|
+
getting fewer and fewer commits over the years, so I am currently
|
|
106
|
+
moving to a Python-only package.
|
|
107
|
+
The Python version is slower by a factor of two to three compared
|
|
108
|
+
to C++-backed code. This is, however, often cancelled by a
|
|
109
|
+
parallelization of the tensor operations, and the tooling is better by orders
|
|
110
|
+
of magnitude.
|
|
111
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Description
|
|
2
|
+
-----------
|
|
3
|
+
|
|
4
|
+
Wavepacket is a Python package to define and simulate small
|
|
5
|
+
quantum systems. Or, more technically, it allows you to numerically
|
|
6
|
+
solve Schrödinger and Liouville-von-Neumann equations for
|
|
7
|
+
distinguishable particles.
|
|
8
|
+
|
|
9
|
+
The full documentation can be found under https://wavepacket.readthedocs.io.
|
|
10
|
+
|
|
11
|
+
There are many different quantum systems and consequently approaches
|
|
12
|
+
to solve them. Here we focus on a particular niche:
|
|
13
|
+
|
|
14
|
+
- Wavepacket solves the differential equations directly. This simplifies
|
|
15
|
+
the maths, but limits the system size to few degrees of freedom.
|
|
16
|
+
If you want to deal with larger systems, look out for MCTDH.
|
|
17
|
+
- Wavepacket uses the DVR approximation heavily. This allows you to
|
|
18
|
+
directly define your potentials as functions of real-space coordinates
|
|
19
|
+
instead of setting up opaque operator matrices.
|
|
20
|
+
The latter approach is simpler an more concise if you are only
|
|
21
|
+
interested in harmonic oscillators or qubits, though.
|
|
22
|
+
- Wavepacket is a Python-only package relying chiefly on numpy.
|
|
23
|
+
This is slower than natively implemented code, but you gain
|
|
24
|
+
great tooling support, for example matplotlib, Jupyter notebooks or
|
|
25
|
+
integrated documentation.
|
|
26
|
+
- Most of the code can handle both wave functions and density operators.
|
|
27
|
+
This allows you to convert a closed system into an open
|
|
28
|
+
system with minimal fuss.
|
|
29
|
+
|
|
30
|
+
For example use cases, we have been using various precursors of this
|
|
31
|
+
package for simulating small molecular systems and for teaching.
|
|
32
|
+
Besides examples shipped with this package, see
|
|
33
|
+
https://sourceforge.net/p/wavepacket/wiki/Demos.Main for more applications.
|
|
34
|
+
|
|
35
|
+
The project is currently a first iteration to flesh out everything. Once
|
|
36
|
+
0.1 is released, I plan to quickly translate the existing C++ code from
|
|
37
|
+
a precursor project and reach a stable state. More can be found on the
|
|
38
|
+
project homepage https://github.com/ulflor/wavepacket
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
Support
|
|
42
|
+
-------
|
|
43
|
+
|
|
44
|
+
If you lack a feature that you would like to have, open an issue at
|
|
45
|
+
`our issue tracker <https://github.com/ulflor/wavepacket/issues>`_.
|
|
46
|
+
Depending on the complexity of the feature, this will lead to an immediate,
|
|
47
|
+
rapid, or prioritized implementation.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
Contribution
|
|
51
|
+
------------
|
|
52
|
+
|
|
53
|
+
I currently lack a formal procedure for new contributors, but you are
|
|
54
|
+
very welcome to contribute to the project. If you do not know what to
|
|
55
|
+
do, feel free to contact one of the developers; there is enough work for
|
|
56
|
+
multiple developers, it is just not documented yet.
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
History
|
|
60
|
+
-------
|
|
61
|
+
|
|
62
|
+
The original version of Wavepacket was written in Matlab and is still
|
|
63
|
+
maintained under https://sourceforge.net/p/wavepacket/matlab. It is stable,
|
|
64
|
+
battle-tested and works.
|
|
65
|
+
|
|
66
|
+
However, Matlab is pretty expensive, so not all interested users had
|
|
67
|
+
access to it. Also, the project's architecture did not support some
|
|
68
|
+
advanced use cases without digging deep into the code. Finally,
|
|
69
|
+
C++11 had just come out and looked cool, so I started a
|
|
70
|
+
reimplementation in C++ around 2013, adding Python bindings as an
|
|
71
|
+
afterthought. The C++ project will be superseded by this Python package, but
|
|
72
|
+
can be found under https://sourceforge.net/p/wavepacket/cpp.
|
|
73
|
+
|
|
74
|
+
This worked really well. However, deploying C++ code is difficult.
|
|
75
|
+
In particular, there was no cheap route towards building a "good"
|
|
76
|
+
Python package, or towards easily building a Windows version.
|
|
77
|
+
Also, the underlying tensor library was slowly
|
|
78
|
+
getting fewer and fewer commits over the years, so I am currently
|
|
79
|
+
moving to a Python-only package.
|
|
80
|
+
The Python version is slower by a factor of two to three compared
|
|
81
|
+
to C++-backed code. This is, however, often cancelled by a
|
|
82
|
+
parallelization of the tensor operations, and the tooling is better by orders
|
|
83
|
+
of magnitude.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["flit_core >=3.2,<4"]
|
|
3
|
+
build-backend = "flit_core.buildapi"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "wavepacket"
|
|
7
|
+
authors = [{ name = "Ulf Lorenz" }]
|
|
8
|
+
readme = "README.rst"
|
|
9
|
+
license = { file = "LICENSE" }
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
classifiers = [
|
|
12
|
+
"License :: OSI Approved :: MIT License",
|
|
13
|
+
"Development Status :: 3 - Alpha",
|
|
14
|
+
"Intended Audience :: Science/Research",
|
|
15
|
+
"Topic :: Scientific/Engineering :: Chemistry",
|
|
16
|
+
"Topic :: Scientific/Engineering :: Physics"
|
|
17
|
+
]
|
|
18
|
+
dynamic = ["version", "description"]
|
|
19
|
+
|
|
20
|
+
dependencies = [
|
|
21
|
+
"numpy >= 2.1.3",
|
|
22
|
+
"scipy >= 1.14.1"
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
Home = "https://github.com/ulflor/wavepacket"
|
|
27
|
+
|
|
28
|
+
[project.optional-dependencies]
|
|
29
|
+
test = [
|
|
30
|
+
"pytest >= 8.3"
|
|
31
|
+
]
|
|
32
|
+
doc = [
|
|
33
|
+
"sphinx >= 8.1.3",
|
|
34
|
+
"sphinx-autoapi >= 3.4.0",
|
|
35
|
+
"numpydoc >= 1.8.0",
|
|
36
|
+
"myst-nb >= 1.2",
|
|
37
|
+
"sphinx-rtd-theme >= 3.0.2"
|
|
38
|
+
]
|
|
39
|
+
demos = [
|
|
40
|
+
"matplotlib >= 3.10"
|
|
41
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A package for the propagation of quantum-mechanical wave functions.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
__version__ = "0.1.0"
|
|
6
|
+
|
|
7
|
+
from . import builder
|
|
8
|
+
from . import expression
|
|
9
|
+
from . import grid
|
|
10
|
+
from . import operator
|
|
11
|
+
from . import solver
|
|
12
|
+
from . import testing
|
|
13
|
+
from . import typing
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
from .exceptions import (BadFunctionCall, BadGridError, BadStateError, ExecutionError,
|
|
17
|
+
InvalidValueError)
|
|
18
|
+
from .generators import Gaussian, PlaneWave
|
|
19
|
+
from .logging import log
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
__all__ = ['__version__', 'log', 'BadFunctionCall', 'BadGridError', 'BadStateError',
|
|
23
|
+
'ExecutionError', 'InvalidValueError',
|
|
24
|
+
'Gaussian', 'PlaneWave',
|
|
25
|
+
'builder', 'expression', 'grid', 'operator', 'solver', 'testing', 'typing']
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
import wavepacket as wp
|
|
4
|
+
from ..grid import State
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def pure_density(psi: State) -> State:
|
|
8
|
+
"""
|
|
9
|
+
Given an input wave function, create the corresponding pure density operator.
|
|
10
|
+
|
|
11
|
+
This function only performs the direct product, it does not apply
|
|
12
|
+
further modifications like normalizations.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
psi : wp.grid.State
|
|
17
|
+
The input wave function
|
|
18
|
+
|
|
19
|
+
Returns
|
|
20
|
+
-------
|
|
21
|
+
wp.grid.State
|
|
22
|
+
The corresponding density operator.
|
|
23
|
+
|
|
24
|
+
Raises
|
|
25
|
+
------
|
|
26
|
+
wp.BadStateError
|
|
27
|
+
If the input is not a valid wave function.
|
|
28
|
+
|
|
29
|
+
See also
|
|
30
|
+
--------
|
|
31
|
+
direct_product : This function is identical to `direct_product(psi, psi)`
|
|
32
|
+
"""
|
|
33
|
+
return direct_product(psi, psi)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def direct_product(ket: State, bra: State) -> State:
|
|
37
|
+
"""
|
|
38
|
+
Returns the direct product of wave functions as a density operator.
|
|
39
|
+
|
|
40
|
+
Given two wave functions :math:`\psi, \phi`, this function returns the
|
|
41
|
+
density operator as :math:`| \psi \\rangle\langle \phi |`.
|
|
42
|
+
This operation can be useful to build up a
|
|
43
|
+
density operator piece by piece.
|
|
44
|
+
|
|
45
|
+
Parameters
|
|
46
|
+
----------
|
|
47
|
+
ket : wp.grid.State
|
|
48
|
+
The ket state :math:`\psi`
|
|
49
|
+
bra : wp.grid.State
|
|
50
|
+
The bra state :math:`\phi`. Note that the function performs a
|
|
51
|
+
complex conjugation of this state prior to multiplication.
|
|
52
|
+
|
|
53
|
+
Returns
|
|
54
|
+
-------
|
|
55
|
+
wp.grid.State
|
|
56
|
+
The direct product of the two states.
|
|
57
|
+
|
|
58
|
+
Raises
|
|
59
|
+
------
|
|
60
|
+
wp.BadStateError
|
|
61
|
+
If one of the input states is not a valid wave function.
|
|
62
|
+
wp.BadGridError
|
|
63
|
+
If the input states are defined on different grids.
|
|
64
|
+
"""
|
|
65
|
+
if not ket.is_wave_function() or not bra.is_wave_function():
|
|
66
|
+
raise wp.BadStateError("Density operator can only be constructed from wave functions.")
|
|
67
|
+
|
|
68
|
+
if ket.grid != bra.grid:
|
|
69
|
+
raise wp.BadGridError("Grid for bra and ket states does not match")
|
|
70
|
+
|
|
71
|
+
rho_matrix = np.outer(ket.data, np.conj(bra.data))
|
|
72
|
+
|
|
73
|
+
return State(ket.grid, np.reshape(rho_matrix, ket.grid.operator_shape))
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from collections.abc import Sequence
|
|
2
|
+
from typing import Iterable
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
import wavepacket as wp
|
|
7
|
+
import wavepacket.typing as wpt
|
|
8
|
+
from ..grid import Grid, State
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def product_wave_function(grid: Grid,
|
|
12
|
+
generators: wpt.Generator | Sequence[wpt.Generator],
|
|
13
|
+
normalize: bool = True) -> State:
|
|
14
|
+
"""
|
|
15
|
+
Builds a product wave function from a set of one-dimensional wave functions.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
grid : wp.grid.Grid
|
|
20
|
+
The grid on which the product wave function is assembled
|
|
21
|
+
generators : Sequence[wp.typing.Generator]
|
|
22
|
+
A list of callables that specifies the wave function
|
|
23
|
+
along each degree of freedom. The `generators` return
|
|
24
|
+
the one-dimensional functions in the DVR, i.e., raw function
|
|
25
|
+
values at the grid points.
|
|
26
|
+
normalize : bool, default=true
|
|
27
|
+
If the norm is non-zero and this value is set, the resulting
|
|
28
|
+
product wave function is normalized, otherwise the product
|
|
29
|
+
is returned directly.
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
wp.grid.State
|
|
34
|
+
The product wave function in the Wavepacket-default weighted DVR.
|
|
35
|
+
|
|
36
|
+
Raises
|
|
37
|
+
------
|
|
38
|
+
wp.InvalidValueError
|
|
39
|
+
If the number of generators does not match the grid dimensions.
|
|
40
|
+
"""
|
|
41
|
+
generator_list = generators
|
|
42
|
+
if not isinstance(generator_list, Iterable):
|
|
43
|
+
generator_list = [generators]
|
|
44
|
+
|
|
45
|
+
if len(generator_list) != len(grid.dofs):
|
|
46
|
+
raise wp.InvalidValueError(
|
|
47
|
+
"To build a wave function, you need as many generators as degrees of freedoms."
|
|
48
|
+
f"Given {len(generator_list)} generators for {len(grid.dofs)} DOFs.")
|
|
49
|
+
|
|
50
|
+
result_data = np.ones(grid.shape, dtype=complex)
|
|
51
|
+
for dof_index, generator in enumerate(generator_list):
|
|
52
|
+
dof = grid.dofs[dof_index]
|
|
53
|
+
array = generator(dof.dvr_points)
|
|
54
|
+
array = dof.from_dvr(array, 0)
|
|
55
|
+
|
|
56
|
+
result_data *= grid.broadcast(array, dof_index)
|
|
57
|
+
|
|
58
|
+
result = State(grid, result_data)
|
|
59
|
+
norm = np.sqrt(wp.grid.trace(result))
|
|
60
|
+
if normalize and norm > 0:
|
|
61
|
+
return result / norm
|
|
62
|
+
else:
|
|
63
|
+
return result
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
class BadFunctionCall(Exception):
|
|
2
|
+
"""
|
|
3
|
+
Signals that a function was called incorrectly.
|
|
4
|
+
|
|
5
|
+
A typical but rare use-case would be a function that was
|
|
6
|
+
called with incorrect parameters.
|
|
7
|
+
"""
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BadGridError(Exception):
|
|
12
|
+
"""
|
|
13
|
+
An invalid grid was supplied.
|
|
14
|
+
|
|
15
|
+
Most often, you attempt an operation between objects that must be defined on the
|
|
16
|
+
same grid. For example, the addition of two operators defined on different grids
|
|
17
|
+
is not a useful operation. The grid may also miss required properties, for example
|
|
18
|
+
an operation may expect a specific degree of freedom type along some index.
|
|
19
|
+
"""
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class BadStateError(Exception):
|
|
24
|
+
"""
|
|
25
|
+
An invalid state was supplied.
|
|
26
|
+
|
|
27
|
+
Either the state is completely invalid (neither wave function nor density operator),
|
|
28
|
+
or you supplied the wrong type of state to a function, for example passing a
|
|
29
|
+
density operator where a wave function was required.
|
|
30
|
+
"""
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ExecutionError(Exception):
|
|
35
|
+
"""
|
|
36
|
+
An unrecoverable problem was encountered in foreign code.
|
|
37
|
+
|
|
38
|
+
The main example is the :py:class:`wavepacket.solver.odesolver` getting
|
|
39
|
+
an error back while integrating.
|
|
40
|
+
"""
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class InvalidValueError(Exception):
|
|
45
|
+
"""
|
|
46
|
+
A function argument was incorrect, for example out of bounds.
|
|
47
|
+
"""
|
|
48
|
+
pass
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Classes that wrap operators into expressions for use in partial differential equations.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
__all__ = ['CommutatorLiouvillian',
|
|
6
|
+
'ExpressionBase', 'SchroedingerEquation']
|
|
7
|
+
|
|
8
|
+
from .expressionbase import ExpressionBase
|
|
9
|
+
from .liouvillian import CommutatorLiouvillian
|
|
10
|
+
from .schroedingerequation import SchroedingerEquation
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from ..grid import State
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ExpressionBase(ABC):
|
|
8
|
+
"""
|
|
9
|
+
Base class for expressions.
|
|
10
|
+
|
|
11
|
+
By deriving from this class and implementing the method
|
|
12
|
+
:py:meth:`ExpressionBase.apply`, you can add custom expressions.
|
|
13
|
+
|
|
14
|
+
Notes
|
|
15
|
+
-----
|
|
16
|
+
All differential equations have the form
|
|
17
|
+
:math:`\dot \\rho = \mathcal{L}(\\rho)` (or equivalently
|
|
18
|
+
:math:`\dot \psi = \hat H \psi`), that is, the left-hand side
|
|
19
|
+
is just the time derivative. This matches the common convention for the
|
|
20
|
+
Liouville von-Neumann equation, but differs from the usual
|
|
21
|
+
form of the Schrödinger equation, where the imaginary factor
|
|
22
|
+
is on the left-hand side of the equation.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
@abstractmethod
|
|
26
|
+
def apply(self, state: State, t: Optional[float] = None) -> State:
|
|
27
|
+
"""
|
|
28
|
+
Applies the expression to the input state and returns the result.
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
state : wp.grid.State
|
|
33
|
+
The state on which the expression is applied.
|
|
34
|
+
t : float, optional
|
|
35
|
+
The time at which the expression is evaluated. Default is None,
|
|
36
|
+
which will raise an exception if the contained expression is time-dependent.
|
|
37
|
+
|
|
38
|
+
Raises
|
|
39
|
+
------
|
|
40
|
+
wp.BadStateError
|
|
41
|
+
If the state is invalid or has the wrong time. For example, a Schroedinger equaiton
|
|
42
|
+
makes little sense for a density operator.
|
|
43
|
+
"""
|
|
44
|
+
pass
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
import wavepacket as wp
|
|
4
|
+
from .expressionbase import ExpressionBase
|
|
5
|
+
from ..grid import State
|
|
6
|
+
from ..operator import OperatorBase
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CommutatorLiouvillian(ExpressionBase):
|
|
10
|
+
"""
|
|
11
|
+
Represents a commutator expression in a Liouville von-Neumann equation.
|
|
12
|
+
|
|
13
|
+
Given an operator `H`, this commutator expression is given by
|
|
14
|
+
:math:`\mathcal{L}(\hat \\rho) = -\imath (\hat H \hat \\rho - \hat \\rho \hat H)`.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
op : wp.operator.OperatorBase
|
|
19
|
+
The operator to commute with the density operator.
|
|
20
|
+
|
|
21
|
+
Notes
|
|
22
|
+
-----
|
|
23
|
+
The extra factor of -i is added to ensure that the commutator can be directly
|
|
24
|
+
plugged into a Liouville von-Neumann equation. defined as
|
|
25
|
+
:math:`\\frac{\partial \hat \\rho}{\partial t} = \mathcal{L}(\hat \\rho)`.
|
|
26
|
+
If you need the raw commutator, you have to multiply the result with
|
|
27
|
+
the imaginary number.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, op: OperatorBase):
|
|
31
|
+
self._op = op
|
|
32
|
+
|
|
33
|
+
def apply(self, rho: State, t: Optional[float] = None) -> State:
|
|
34
|
+
"""
|
|
35
|
+
Evaluates the commutator for the given density operator and time.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
rho : wp.grid.State
|
|
40
|
+
The density operator to commute with
|
|
41
|
+
t : float, optional
|
|
42
|
+
The time at which the operator is evaluated. By default it is None,
|
|
43
|
+
which will throw if the contained operator is time-dependent.
|
|
44
|
+
|
|
45
|
+
Returns
|
|
46
|
+
-------
|
|
47
|
+
wp.grid.State
|
|
48
|
+
The result of the commutator.
|
|
49
|
+
|
|
50
|
+
Raises
|
|
51
|
+
------
|
|
52
|
+
wp.BadGridError
|
|
53
|
+
If the grids of the density operator and the wrapped operator do not match.
|
|
54
|
+
wp.BadStateError
|
|
55
|
+
If the input state is not a valid density operator.
|
|
56
|
+
"""
|
|
57
|
+
if rho.grid != self._op.grid:
|
|
58
|
+
raise wp.BadGridError("Input state is defined on the wrong grid.")
|
|
59
|
+
|
|
60
|
+
if not rho.is_density_operator():
|
|
61
|
+
raise wp.BadStateError("CommutatorLiouvillian requires a density operator.")
|
|
62
|
+
|
|
63
|
+
return State(rho.grid,
|
|
64
|
+
-1j * (self._op.apply_from_left(rho.data, t) - self._op.apply_from_right(rho.data, t)))
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
import wavepacket as wp
|
|
4
|
+
from .expressionbase import ExpressionBase
|
|
5
|
+
from ..grid import State
|
|
6
|
+
from ..operator import OperatorBase
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SchroedingerEquation(ExpressionBase):
|
|
10
|
+
"""
|
|
11
|
+
Expression wrapper for a Schrödinger equation.
|
|
12
|
+
|
|
13
|
+
You should wrap a Hamiltonian in an object of this type
|
|
14
|
+
so that the solvers can subsequently solve the resulting
|
|
15
|
+
equation.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
hamiltonian : wp.operator.OperatorBase
|
|
20
|
+
The Hamiltonian that is wrapped by this class.
|
|
21
|
+
|
|
22
|
+
Notes
|
|
23
|
+
-----
|
|
24
|
+
The Schrödinger equation is given by
|
|
25
|
+
:math:`\dot \psi = -\imath \hat H \psi`,
|
|
26
|
+
so this class only multiplies the wave function with the
|
|
27
|
+
negative imaginary number, and wraps the input Hamiltonian
|
|
28
|
+
into an expression so that solvers can work with it.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(self, hamiltonian: OperatorBase):
|
|
32
|
+
self._hamiltonian = hamiltonian
|
|
33
|
+
|
|
34
|
+
def apply(self, psi: State, t: Optional[float] = None) -> State:
|
|
35
|
+
"""
|
|
36
|
+
Evaluates the right-hand side of the Schrödinger equation
|
|
37
|
+
for the given input state and time.
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
psi : wp.grid.State
|
|
42
|
+
The input state that is evaluated.
|
|
43
|
+
t : float, optional
|
|
44
|
+
The time at which the Schrödinger equation is evaluated.
|
|
45
|
+
The default `None` throws if the wrapped operator is time-dependent.
|
|
46
|
+
|
|
47
|
+
Returns
|
|
48
|
+
-------
|
|
49
|
+
wp.grid.State
|
|
50
|
+
The result of the evaluation.
|
|
51
|
+
|
|
52
|
+
Raises
|
|
53
|
+
------
|
|
54
|
+
wp.grid.BadGridError
|
|
55
|
+
If the state's grid differs from that of the Hamiltonian.
|
|
56
|
+
wp.grid.BadStateError
|
|
57
|
+
If the input state is not a wave function.
|
|
58
|
+
"""
|
|
59
|
+
if psi.grid != self._hamiltonian.grid:
|
|
60
|
+
raise wp.BadGridError("Input state has wrong grid.")
|
|
61
|
+
|
|
62
|
+
if not psi.is_wave_function():
|
|
63
|
+
raise wp.BadStateError("SchroedingerEquation requires a wave function.")
|
|
64
|
+
|
|
65
|
+
return State(psi.grid, -1j * self._hamiltonian.apply_to_wave_function(psi.data, t))
|