qutip-cuquantum 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.
- qutip_cuquantum-0.1.0/LICENSE +28 -0
- qutip_cuquantum-0.1.0/MANIFEST.in +5 -0
- qutip_cuquantum-0.1.0/PKG-INFO +101 -0
- qutip_cuquantum-0.1.0/README.md +43 -0
- qutip_cuquantum-0.1.0/VERSION +1 -0
- qutip_cuquantum-0.1.0/pyproject.toml +57 -0
- qutip_cuquantum-0.1.0/setup.cfg +4 -0
- qutip_cuquantum-0.1.0/setup.py +122 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum/__init__.py +108 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum/callable.py +118 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum/family.py +8 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum/ode.py +92 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum/operator.py +761 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum/qobjevo.cpp +37193 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum/state.py +279 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum/utils.py +119 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum/version.py +4 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum.egg-info/PKG-INFO +101 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum.egg-info/SOURCES.txt +25 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum.egg-info/dependency_links.txt +1 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum.egg-info/entry_points.txt +2 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum.egg-info/requires.txt +12 -0
- qutip_cuquantum-0.1.0/src/qutip_cuquantum.egg-info/top_level.txt +1 -0
- qutip_cuquantum-0.1.0/tests/test_family.py +12 -0
- qutip_cuquantum-0.1.0/tests/test_operator.py +359 -0
- qutip_cuquantum-0.1.0/tests/test_solver.py +155 -0
- qutip_cuquantum-0.1.0/tests/test_state.py +184 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, QuTiP
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qutip-cuquantum
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: cuQuantum backend for QuTiP
|
|
5
|
+
Author-email: Eric Giguère <qutip-admin@googlegroups.com>
|
|
6
|
+
License: BSD 3-Clause License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025, QuTiP
|
|
9
|
+
|
|
10
|
+
Redistribution and use in source and binary forms, with or without
|
|
11
|
+
modification, are permitted provided that the following conditions are met:
|
|
12
|
+
|
|
13
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
14
|
+
list of conditions and the following disclaimer.
|
|
15
|
+
|
|
16
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
17
|
+
this list of conditions and the following disclaimer in the documentation
|
|
18
|
+
and/or other materials provided with the distribution.
|
|
19
|
+
|
|
20
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
21
|
+
contributors may be used to endorse or promote products derived from
|
|
22
|
+
this software without specific prior written permission.
|
|
23
|
+
|
|
24
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
25
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
26
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
27
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
28
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
29
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
30
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
31
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
32
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
33
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
34
|
+
|
|
35
|
+
Project-URL: Homepage, https://qutip.org
|
|
36
|
+
Project-URL: Bug Tracker, https://github.com/qutip/qutip-cuquantum/issues
|
|
37
|
+
Project-URL: Documentation, https://qutip-cuquantum.readthedocs.io/en/latest/
|
|
38
|
+
Keywords: quantum,physics,dynamics,gpu,linear-algebra
|
|
39
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
40
|
+
Classifier: Intended Audience :: Science/Research
|
|
41
|
+
Classifier: Programming Language :: Python
|
|
42
|
+
Classifier: Programming Language :: Python :: 3
|
|
43
|
+
Classifier: Topic :: Scientific/Engineering
|
|
44
|
+
Classifier: Operating System :: Unix
|
|
45
|
+
Requires-Python: >=3.11
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
47
|
+
License-File: LICENSE
|
|
48
|
+
Requires-Dist: qutip>=5.2.1
|
|
49
|
+
Provides-Extra: cuda11
|
|
50
|
+
Requires-Dist: cupy-cuda11x; extra == "cuda11"
|
|
51
|
+
Requires-Dist: cuquantum-python-cu11; extra == "cuda11"
|
|
52
|
+
Provides-Extra: cuda12
|
|
53
|
+
Requires-Dist: cupy-cuda12x; extra == "cuda12"
|
|
54
|
+
Requires-Dist: cuquantum-python-cu12; extra == "cuda12"
|
|
55
|
+
Provides-Extra: tests
|
|
56
|
+
Requires-Dist: pytest>=6.0; extra == "tests"
|
|
57
|
+
Dynamic: license-file
|
|
58
|
+
|
|
59
|
+
# qutip-cuquantum
|
|
60
|
+
|
|
61
|
+
Provide cuQuantum's cuDensityMat as a backend for QuTiP.
|
|
62
|
+
|
|
63
|
+
This backend is specifically designed for simulating **large, composite quantum systems** by performing tensor network contractions on the GPU.
|
|
64
|
+
|
|
65
|
+
## Installation
|
|
66
|
+
|
|
67
|
+
qutip-cuquantum is available on pypi.
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
pip install -U qutip>=5.2.1
|
|
71
|
+
pip install qutip-cuquantum
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
It require cuquantum to be installed at runtime.
|
|
76
|
+
If you have cuda already installed, you can install dependencies with:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
pip install qutip-cuquantum[cuda11]
|
|
80
|
+
```
|
|
81
|
+
or
|
|
82
|
+
```
|
|
83
|
+
pip install qutip-cuquantum[cuda12]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
If it does not work, you may need to install cuQuantum yourself,
|
|
87
|
+
see [nvidia's documentation](https://docs.nvidia.com/cuda/cuquantum/latest/getting-started/index.html#installing-cuquantum) for installation instruction.
|
|
88
|
+
|
|
89
|
+
## Usage
|
|
90
|
+
|
|
91
|
+
In simple case, simply calling `set_as_default` before a qutip script should be sufficient to use the backend common solver:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
import qutip_cuquantum
|
|
95
|
+
from cuquantum.densitymat import WorkStream
|
|
96
|
+
|
|
97
|
+
qutip_cuquantum.set_as_default(WorkStream())
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
qutip-cuquantum work well to speed-up large simulation using `mesolve` or `sesolve`.
|
|
101
|
+
However this backend is not compatible with advanced qutip solvers (brmesolve, HEOM) and other various feature.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# qutip-cuquantum
|
|
2
|
+
|
|
3
|
+
Provide cuQuantum's cuDensityMat as a backend for QuTiP.
|
|
4
|
+
|
|
5
|
+
This backend is specifically designed for simulating **large, composite quantum systems** by performing tensor network contractions on the GPU.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
qutip-cuquantum is available on pypi.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
pip install -U qutip>=5.2.1
|
|
13
|
+
pip install qutip-cuquantum
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
It require cuquantum to be installed at runtime.
|
|
18
|
+
If you have cuda already installed, you can install dependencies with:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
pip install qutip-cuquantum[cuda11]
|
|
22
|
+
```
|
|
23
|
+
or
|
|
24
|
+
```
|
|
25
|
+
pip install qutip-cuquantum[cuda12]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
If it does not work, you may need to install cuQuantum yourself,
|
|
29
|
+
see [nvidia's documentation](https://docs.nvidia.com/cuda/cuquantum/latest/getting-started/index.html#installing-cuquantum) for installation instruction.
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
In simple case, simply calling `set_as_default` before a qutip script should be sufficient to use the backend common solver:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
import qutip_cuquantum
|
|
37
|
+
from cuquantum.densitymat import WorkStream
|
|
38
|
+
|
|
39
|
+
qutip_cuquantum.set_as_default(WorkStream())
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
qutip-cuquantum work well to speed-up large simulation using `mesolve` or `sesolve`.
|
|
43
|
+
However this backend is not compatible with advanced qutip solvers (brmesolve, HEOM) and other various feature.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.0
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools",
|
|
4
|
+
"packaging",
|
|
5
|
+
"wheel",
|
|
6
|
+
"Cython",
|
|
7
|
+
"qutip>=5.2.1",
|
|
8
|
+
"numpy",
|
|
9
|
+
]
|
|
10
|
+
build-backend = "setuptools.build_meta"
|
|
11
|
+
|
|
12
|
+
[project]
|
|
13
|
+
name = "qutip-cuquantum"
|
|
14
|
+
dynamic = ["version"]
|
|
15
|
+
description = "cuQuantum backend for QuTiP"
|
|
16
|
+
readme = "README.md"
|
|
17
|
+
requires-python = ">=3.11"
|
|
18
|
+
license = { file = "LICENSE" }
|
|
19
|
+
keywords = ["quantum", "physics", "dynamics", "gpu", "linear-algebra"]
|
|
20
|
+
authors = [
|
|
21
|
+
{name = "Eric Giguère", email = "qutip-admin@googlegroups.com"}
|
|
22
|
+
]
|
|
23
|
+
classifiers = [
|
|
24
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
25
|
+
"Intended Audience :: Science/Research",
|
|
26
|
+
"Programming Language :: Python",
|
|
27
|
+
"Programming Language :: Python :: 3",
|
|
28
|
+
"Topic :: Scientific/Engineering",
|
|
29
|
+
"Operating System :: Unix",
|
|
30
|
+
]
|
|
31
|
+
dependencies = [
|
|
32
|
+
"qutip>=5.2.1",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
# URLs for your project
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://qutip.org"
|
|
38
|
+
"Bug Tracker" = "https://github.com/qutip/qutip-cuquantum/issues"
|
|
39
|
+
Documentation = "https://qutip-cuquantum.readthedocs.io/en/latest/"
|
|
40
|
+
|
|
41
|
+
[project.optional-dependencies]
|
|
42
|
+
cuda11 = ["cupy-cuda11x", "cuquantum-python-cu11"]
|
|
43
|
+
cuda12 = ["cupy-cuda12x", "cuquantum-python-cu12"]
|
|
44
|
+
tests = ["pytest>=6.0"]
|
|
45
|
+
|
|
46
|
+
[project.entry-points."qutip.family"]
|
|
47
|
+
qutip_cuquantum = "qutip_cuquantum.family"
|
|
48
|
+
|
|
49
|
+
[tool.setuptools]
|
|
50
|
+
packages = { find = { where = ["src"] } }
|
|
51
|
+
package-dir = { "" = "src" }
|
|
52
|
+
|
|
53
|
+
[tool.pytest.ini_options]
|
|
54
|
+
addopts = "-Werror --strict-config --strict-markers -W ignore::DeprecationWarning"
|
|
55
|
+
testpaths = [
|
|
56
|
+
"tests",
|
|
57
|
+
]
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
# Required third-party imports, must be specified in pyproject.toml.
|
|
8
|
+
import packaging.version
|
|
9
|
+
import setuptools
|
|
10
|
+
from Cython.Build import cythonize
|
|
11
|
+
import qutip
|
|
12
|
+
import numpy
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def process_options():
|
|
16
|
+
"""
|
|
17
|
+
Determine all runtime options, returning a dictionary of the results. The
|
|
18
|
+
keys are:
|
|
19
|
+
'rootdir': str
|
|
20
|
+
The root directory of the setup. Almost certainly the directory
|
|
21
|
+
that this setup.py file is contained in.
|
|
22
|
+
'release': bool
|
|
23
|
+
Is this a release build (True) or a local development build (False)
|
|
24
|
+
"""
|
|
25
|
+
options = {}
|
|
26
|
+
options["rootdir"] = os.path.dirname(os.path.abspath(__file__))
|
|
27
|
+
options = _determine_version(options)
|
|
28
|
+
return options
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _determine_version(options):
|
|
32
|
+
"""
|
|
33
|
+
Adds the 'short_version', 'version' and 'release' options.
|
|
34
|
+
|
|
35
|
+
Read from the VERSION file to discover the version. This should be a
|
|
36
|
+
single line file containing valid Python package public identifier (see PEP
|
|
37
|
+
440), for example
|
|
38
|
+
4.5.2rc2
|
|
39
|
+
5.0.0
|
|
40
|
+
5.1.1a1
|
|
41
|
+
We do that here rather than in setup.cfg so we can apply the local
|
|
42
|
+
versioning number as well.
|
|
43
|
+
"""
|
|
44
|
+
version_filename = os.path.join(options["rootdir"], "VERSION")
|
|
45
|
+
with open(version_filename, "r") as version_file:
|
|
46
|
+
version_string = version_file.read().strip()
|
|
47
|
+
version = packaging.version.Version(version_string)
|
|
48
|
+
options["short_version"] = str(version.public)
|
|
49
|
+
options["release"] = not version.is_devrelease
|
|
50
|
+
if not options["release"]:
|
|
51
|
+
# Put the version string into canonical form, if it wasn't already.
|
|
52
|
+
version_string = str(version)
|
|
53
|
+
version_string += "+"
|
|
54
|
+
try:
|
|
55
|
+
git_out = subprocess.run(
|
|
56
|
+
("git", "rev-parse", "--verify", "--short=7", "HEAD"),
|
|
57
|
+
check=True,
|
|
58
|
+
stdout=subprocess.PIPE,
|
|
59
|
+
stderr=subprocess.PIPE,
|
|
60
|
+
)
|
|
61
|
+
git_hash = git_out.stdout.decode(sys.stdout.encoding).strip()
|
|
62
|
+
version_string += git_hash or "nogit"
|
|
63
|
+
# CalledProcessError is for if the git command fails for internal
|
|
64
|
+
# reasons (e.g. we're not in a git repository), OSError is for if
|
|
65
|
+
# something goes wrong when trying to run git (e.g. it's not installed,
|
|
66
|
+
# or a permission error).
|
|
67
|
+
except (subprocess.CalledProcessError, OSError):
|
|
68
|
+
version_string += "nogit"
|
|
69
|
+
options["version"] = version_string
|
|
70
|
+
return options
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def create_version_py_file(options):
|
|
74
|
+
"""
|
|
75
|
+
Generate and write out the file version.py, which is used to produce the
|
|
76
|
+
'__version__' information for the module. This function will overwrite an
|
|
77
|
+
existing file at that location.
|
|
78
|
+
"""
|
|
79
|
+
filename = os.path.join(options["rootdir"], "src", "qutip_cuquantum", "version.py")
|
|
80
|
+
content = "\n".join(
|
|
81
|
+
[
|
|
82
|
+
"# This file is automatically generated during package setup.",
|
|
83
|
+
f"short_version = '{options['short_version']}'",
|
|
84
|
+
f"version = '{options['version']}'",
|
|
85
|
+
f"release = {options['release']}",
|
|
86
|
+
]
|
|
87
|
+
)
|
|
88
|
+
with open(filename, "w") as file:
|
|
89
|
+
print(content, file=file)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def get_ext_modules(options):
|
|
94
|
+
pyx_file = os.path.join("src", "qutip_cuquantum", "qobjevo.pyx")
|
|
95
|
+
include_dirs = [
|
|
96
|
+
numpy.get_include(),
|
|
97
|
+
os.path.abspath(os.path.join(qutip.core.data.__file__, os.pardir))
|
|
98
|
+
]
|
|
99
|
+
print("*********************************************************************************")
|
|
100
|
+
print(include_dirs)
|
|
101
|
+
print(pyx_file)
|
|
102
|
+
print("*********************************************************************************")
|
|
103
|
+
ext = setuptools.Extension(
|
|
104
|
+
name="qutip_cuquantum.qobjevo",
|
|
105
|
+
sources=[pyx_file],
|
|
106
|
+
include_dirs=include_dirs,
|
|
107
|
+
language="c++",
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
return cythonize(ext)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
if __name__ == "__main__":
|
|
114
|
+
options = process_options()
|
|
115
|
+
create_version_py_file(options)
|
|
116
|
+
# Most of the kwargs to setup are defined in setup.cfg; the only ones we
|
|
117
|
+
# keep here are ones that we have done some compile-time processing on.
|
|
118
|
+
|
|
119
|
+
setuptools.setup(
|
|
120
|
+
version = options["version"],
|
|
121
|
+
ext_modules = get_ext_modules(options),
|
|
122
|
+
)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
try:
|
|
2
|
+
import cupy
|
|
3
|
+
except ImportError as err:
|
|
4
|
+
raise ImportError("\n".join([
|
|
5
|
+
"CuPy is not installed or could not be imported.",
|
|
6
|
+
"Please install the appropriate version for your CUDA toolkit manually.",
|
|
7
|
+
"For example, for CUDA 12.x, run:",
|
|
8
|
+
" pip install cupy-cuda12x",
|
|
9
|
+
"For other versions, please see the CuPy installation guide",
|
|
10
|
+
"https://docs.cupy.dev/en/stable/install.html",
|
|
11
|
+
])) from err
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
import cuquantum.densitymat
|
|
15
|
+
except ImportError as err:
|
|
16
|
+
raise ImportError("\n".join([
|
|
17
|
+
"cuQuantum.densitymat is not installed or could not be imported.",
|
|
18
|
+
"Please install the appropriate version for your CUDA toolkit manually.",
|
|
19
|
+
"For example, for CUDA 12.x, run:",
|
|
20
|
+
" pip install cuquantum-python-cu12",
|
|
21
|
+
"For other versions, please see the cuQuantum installation guide:",
|
|
22
|
+
"https://docs.nvidia.com/cuda/cuquantum/latest/getting-started/index.html",
|
|
23
|
+
])) from err
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
import qutip
|
|
27
|
+
from qutip.core.options import QutipOptions
|
|
28
|
+
from .operator import CuOperator
|
|
29
|
+
from .state import CuState
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# TODO: The split per density is not great
|
|
33
|
+
# Add an operator / state split in qutip?
|
|
34
|
+
qutip.core.data.to.register_group(
|
|
35
|
+
['cuDensity'],
|
|
36
|
+
dense=qutip.core.data.Dense,
|
|
37
|
+
sparse=CuOperator,
|
|
38
|
+
diagonal=CuOperator
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
from qutip_cupy import CuPyDense
|
|
43
|
+
|
|
44
|
+
def CuOperator_from_CuDense(mat):
|
|
45
|
+
return CuOperator(mat)
|
|
46
|
+
|
|
47
|
+
def CuPyDense_from_CuState(mat):
|
|
48
|
+
return CuPyDense(mat.to_cupy())
|
|
49
|
+
|
|
50
|
+
def CuState_from_CuPyDense(mat):
|
|
51
|
+
return CuState(mat)
|
|
52
|
+
|
|
53
|
+
qutip.core.data.to.add_conversions([
|
|
54
|
+
(CuState, CuPyDense, CuState_from_CuPyDense),
|
|
55
|
+
(CuPyDense, CuState, CuPyDense_from_CuState),
|
|
56
|
+
(CuOperator, CuPyDense, CuOperator_from_CuDense),
|
|
57
|
+
])
|
|
58
|
+
|
|
59
|
+
except ImportError:
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
from .qobjevo import CuQobjEvo
|
|
64
|
+
from .ode import Result, CuMCIntegrator
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class cuDensityOption(QutipOptions):
|
|
68
|
+
_options = {"ctx": None}
|
|
69
|
+
_settings_name = "cuDensity"
|
|
70
|
+
_properties = {}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
cuDensityOption_instance = cuDensityOption()
|
|
74
|
+
cuDensityOption_instance._set_as_global_default()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def set_as_default(ctx: cuquantum.densitymat.WorkStream):
|
|
78
|
+
"""
|
|
79
|
+
Update qutip's default to use cuQuantum as a backend.
|
|
80
|
+
|
|
81
|
+
Parameters
|
|
82
|
+
----------
|
|
83
|
+
ctx: WorkStream
|
|
84
|
+
A WorkStream instance from cuquantum.density.
|
|
85
|
+
It can be set with mpi support for multi-gpu simulations.
|
|
86
|
+
"""
|
|
87
|
+
qutip.settings.cuDensity["ctx"] = ctx
|
|
88
|
+
qutip.settings.core["default_dtype"] = "cuDensity"
|
|
89
|
+
qutip.settings.core['numpy_backend'] = cupy
|
|
90
|
+
|
|
91
|
+
if True: # if mpi, how to check from ctx?
|
|
92
|
+
qutip.settings.core["auto_real_casting"] = False
|
|
93
|
+
|
|
94
|
+
qutip.SESolver.solver_options['method'] = "CuVern7"
|
|
95
|
+
qutip.MESolver.solver_options['method'] = "CuVern7"
|
|
96
|
+
qutip.MCSolver.solver_options['method'] = "CuVern7"
|
|
97
|
+
|
|
98
|
+
qutip.SESolver._resultclass = Result
|
|
99
|
+
qutip.MESolver._resultclass = Result
|
|
100
|
+
qutip.MCSolver._trajectory_resultclass = Result
|
|
101
|
+
qutip.MCSolver._mc_integrator_class = CuMCIntegrator
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# Cleaning the namespace
|
|
106
|
+
# del Result
|
|
107
|
+
# del QutipOptions
|
|
108
|
+
# del qutip
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
from functools import partial
|
|
2
|
+
from cuquantum.densitymat import CPUCallback, DenseOperator
|
|
3
|
+
|
|
4
|
+
from qutip.core.tensor import _reverse_partial_tensor, tensor
|
|
5
|
+
from qutip.core.superoperator import spre, spost
|
|
6
|
+
from qutip.core.cy._element import _BaseElement, _FuncElement, _MapElement, _ProdElement, _EvoElement, _ConstantElement
|
|
7
|
+
from qutip.core.data import Dia
|
|
8
|
+
from qutip.core import coefficient, Qobj
|
|
9
|
+
|
|
10
|
+
from . import CuOperator
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _hilbert_from_dims(dims):
|
|
14
|
+
if isinstance(dims[0], list):
|
|
15
|
+
return dims[0]
|
|
16
|
+
return dims
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def wrap_coeff(coeff):
|
|
20
|
+
return CPUCallback(lambda t, _: coeff(t))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _wrap_callable(func):
|
|
24
|
+
sample = func(0)
|
|
25
|
+
shape = sample._dims._get_tensor_shape()
|
|
26
|
+
perm = sample._dims._get_tensor_perm()
|
|
27
|
+
num_mode = len(shape) // 2
|
|
28
|
+
|
|
29
|
+
if sample.dtype is Dia and num_mode == 1:
|
|
30
|
+
dia_matrix = sample.as_scipy()
|
|
31
|
+
offsets = list(dia_matrix.offsets)
|
|
32
|
+
|
|
33
|
+
def wrapped(t, _=None):
|
|
34
|
+
# TODO: Should we make this a class for pickling?
|
|
35
|
+
dia_matrix = func(t).as_scipy()
|
|
36
|
+
arr_shape = (dia_matrix.shape[0], len(offsets))
|
|
37
|
+
data = np.zeros(arr_shape, dtype=complex)
|
|
38
|
+
|
|
39
|
+
for i, offset in enumerate(offsets):
|
|
40
|
+
end = None if offset == 0 else -abs(offset)
|
|
41
|
+
data[:end, i] = dia_matrix.diagonal(offset)
|
|
42
|
+
|
|
43
|
+
return data
|
|
44
|
+
|
|
45
|
+
out = MultidiagonalOperator(wrapped(0), offsets, callback=CPUCallback(wrapped))
|
|
46
|
+
|
|
47
|
+
else:
|
|
48
|
+
if sample.dtype is Dia:
|
|
49
|
+
print("Callable QobjEvo converted to dense!")
|
|
50
|
+
|
|
51
|
+
def wrapped(t, _=None):
|
|
52
|
+
# TODO: Should we make this a class for pickling?
|
|
53
|
+
arr = func(t).full()
|
|
54
|
+
arr = arr.reshape(*shape)
|
|
55
|
+
return arr.transpose(*perm)
|
|
56
|
+
|
|
57
|
+
out = DenseOperator(wrapped(0), CPUCallback(wrapped))
|
|
58
|
+
|
|
59
|
+
return out, num_mode
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def wrap_funcelement(element, args, dual, hilbert_dims, anti=False):
|
|
63
|
+
if not isinstance(element, _BaseElement):
|
|
64
|
+
element = _FuncElement(element, args)
|
|
65
|
+
|
|
66
|
+
if isinstance(element, _FuncElement):
|
|
67
|
+
oper, num_mode = _wrap_callable(element.qobj)
|
|
68
|
+
out = tensor_product((oper, tuple(range(num_mode)) ), dtype="complex128")
|
|
69
|
+
|
|
70
|
+
elif isinstance(element, _MapElement):
|
|
71
|
+
oper, num_mode = _wrap_callable(element._base.qobj)
|
|
72
|
+
as_qobj = Qobj( CuOperator(oper), dims=element._base.qobj(0)._dims )
|
|
73
|
+
for transform in element._transform:
|
|
74
|
+
as_qobj = transform(as_qobj)
|
|
75
|
+
if as_qobj.dtype is not CuOperator:
|
|
76
|
+
oper, num_mode = _wrap_callable(element.qobj)
|
|
77
|
+
out = tensor_product((oper, tuple(range(num_mode)) ), dtype="complex128")
|
|
78
|
+
else:
|
|
79
|
+
coeff = conj(element._coeff) if anti else element._coeff
|
|
80
|
+
out = as_qobj.data.to_OperatorTerm(dual, hilbert_dims=hilbert_dims) * coeff
|
|
81
|
+
|
|
82
|
+
elif isinstance(element, _ProdElement):
|
|
83
|
+
dims_left = element._left.qobj(0).dims
|
|
84
|
+
hilbert_left = _hilbert_from_dims(dims_left)
|
|
85
|
+
left = CuOperator(
|
|
86
|
+
wrap_funcelement(element._left, None, dual, hilbert_left, element._conj != anti),
|
|
87
|
+
hilbert_dims=hilbert_left,
|
|
88
|
+
)
|
|
89
|
+
dims_right = element._right.qobj(0).dims
|
|
90
|
+
hilbert_right = _hilbert_from_dims(dims_right)
|
|
91
|
+
right = CuOperator(
|
|
92
|
+
wrap_funcelement(element._right, None, dual, hilbert_right, element._conj != anti),
|
|
93
|
+
hilbert_dims=hilbert_right,
|
|
94
|
+
)
|
|
95
|
+
as_qobj = Qobj(left @ right, [dims_left[0], dims_right[1]])
|
|
96
|
+
for transform in element._transform:
|
|
97
|
+
as_qobj = transform(as_qobj)
|
|
98
|
+
|
|
99
|
+
if as_qobj.dtype is not CuOperator:
|
|
100
|
+
oper, num_mode = _wrap_callable(element.qobj)
|
|
101
|
+
coeff = make_CPUcall( coefficient(element.coeff).conj() ) if anti else make_CPUcall(element.coeff)
|
|
102
|
+
out = tensor_product((oper, tuple(range(num_mode)) ), dtype="complex128") * coeff
|
|
103
|
+
else:
|
|
104
|
+
out = as_qobj.data.to_OperatorTerm(dual, hilbert_dims=hilbert_dims)
|
|
105
|
+
|
|
106
|
+
elif isinstance(element, _EvoElement):
|
|
107
|
+
qobj = element._qobj
|
|
108
|
+
coeff = make_CPUcall(element._coefficient.conj()) if anti else make_CPUcall(element._coefficient)
|
|
109
|
+
out = qobj.data.to_OperatorTerm(dual, hilbert_dims=hilbert_dims) * coeff
|
|
110
|
+
|
|
111
|
+
elif isinstance(element, _ConstantElement):
|
|
112
|
+
qobj = element._qobj
|
|
113
|
+
out = qobj.data.to_OperatorTerm(dual, hilbert_dims=hilbert_dims)
|
|
114
|
+
|
|
115
|
+
else:
|
|
116
|
+
raise NotImplementedError(type(element))
|
|
117
|
+
|
|
118
|
+
return out
|