cuquantum-python-jax-cu12 0.0.6__tar.gz → 0.0.8__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.
Files changed (50) hide show
  1. {cuquantum_python_jax_cu12-0.0.6/cuquantum_python_jax_cu12.egg-info → cuquantum_python_jax_cu12-0.0.8}/PKG-INFO +11 -8
  2. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/README.md +9 -6
  3. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/__init__.py +2 -9
  4. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/cppsrc/cudensitymat.h +169 -27
  5. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/cppsrc/cudensitymat_jax.cpp +20 -20
  6. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/operator_action.py +61 -30
  7. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/pysrc/__init__.py +1 -0
  8. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/pysrc/base.py +0 -8
  9. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/pysrc/context.py +44 -35
  10. cuquantum_python_jax_cu12-0.0.8/cuquantum/densitymat/jax/pysrc/elementary_operator.py +474 -0
  11. cuquantum_python_jax_cu12-0.0.8/cuquantum/densitymat/jax/pysrc/matrix_operator.py +387 -0
  12. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/pysrc/operator.py +156 -66
  13. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/pysrc/operator_action_prim.py +134 -46
  14. cuquantum_python_jax_cu12-0.0.8/cuquantum/densitymat/jax/pysrc/operator_term.py +1138 -0
  15. cuquantum_python_jax_cu12-0.0.8/cuquantum/densitymat/jax/pysrc/simplifier_config.py +112 -0
  16. cuquantum_python_jax_cu12-0.0.8/cuquantum/densitymat/jax/utils.py +858 -0
  17. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/stabilizer/jax/__init__.py +0 -10
  18. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/stabilizer/jax/cppsrc/CMakeLists.txt +0 -1
  19. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/stabilizer/jax/cppsrc/custabilizer.h +229 -8
  20. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/stabilizer/jax/pysrc/_ffi.py +30 -4
  21. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8/cuquantum_python_jax_cu12.egg-info}/PKG-INFO +11 -8
  22. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum_python_jax_cu12.egg-info/SOURCES.txt +1 -0
  23. cuquantum_python_jax_cu12-0.0.8/cuquantum_python_jax_cu12.egg-info/requires.txt +2 -0
  24. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/pyproject.toml +2 -2
  25. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/pyproject.toml.template +2 -2
  26. cuquantum_python_jax_cu12-0.0.6/cuquantum/densitymat/jax/pysrc/elementary_operator.py +0 -259
  27. cuquantum_python_jax_cu12-0.0.6/cuquantum/densitymat/jax/pysrc/matrix_operator.py +0 -200
  28. cuquantum_python_jax_cu12-0.0.6/cuquantum/densitymat/jax/pysrc/operator_term.py +0 -487
  29. cuquantum_python_jax_cu12-0.0.6/cuquantum/densitymat/jax/utils.py +0 -399
  30. cuquantum_python_jax_cu12-0.0.6/cuquantum_python_jax_cu12.egg-info/requires.txt +0 -2
  31. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/LICENSE +0 -0
  32. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/MANIFEST.in +0 -0
  33. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/NV.LICENSE +0 -0
  34. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/configure.sh +0 -0
  35. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/_build_info.py +0 -0
  36. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/cppsrc/CMakeLists.txt +0 -0
  37. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/cppsrc/cudensitymat_jax.h +0 -0
  38. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/cppsrc/pybind.cpp +0 -0
  39. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/densitymat/jax/cppsrc/utils.h +0 -0
  40. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/stabilizer/jax/_build_info.py +0 -0
  41. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/stabilizer/jax/cppsrc/custabilizer_jax.cpp +0 -0
  42. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/stabilizer/jax/cppsrc/custabilizer_jax.h +0 -0
  43. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/stabilizer/jax/cppsrc/pybind.cpp +0 -0
  44. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/stabilizer/jax/pysrc/__init__.py +0 -0
  45. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum/stabilizer/jax/pysrc/_backend.py +0 -0
  46. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum_python_jax_cu12.egg-info/dependency_links.txt +0 -0
  47. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum_python_jax_cu12.egg-info/not-zip-safe +0 -0
  48. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/cuquantum_python_jax_cu12.egg-info/top_level.txt +0 -0
  49. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/setup.cfg +0 -0
  50. {cuquantum_python_jax_cu12-0.0.6 → cuquantum_python_jax_cu12-0.0.8}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cuquantum-python-jax-cu12
3
- Version: 0.0.6
3
+ Version: 0.0.8
4
4
  Summary: NVIDIA cuQuantum Python JAX
5
5
  Author-email: NVIDIA Corporation <cuquantum-python@nvidia.com>
6
6
  License-Expression: BSD-3-Clause
@@ -21,13 +21,13 @@ Requires-Python: >=3.11.0
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
23
  License-File: NV.LICENSE
24
- Requires-Dist: cuquantum-python-cu12~=26.6.0
24
+ Requires-Dist: cuquantum-python-cu12~=26.11.0
25
25
  Requires-Dist: jax[cuda12-local]>=0.8
26
26
  Dynamic: license-file
27
27
 
28
28
  # cuQuantum Python JAX
29
29
 
30
- cuQuantum Python JAX provides a JAX extension for cuQuantum Python. It exposes selected functionality of cuQuantum SDK in a JAX-compatible way that enables JAX frameworks to directly interface with the exposed cuQuantum API. In the current release, cuQuantum JAX exposes a JAX interface to the Operator Action API from the cuDensityMat library and the GF(2) sparse-dense matrix multiply from the cuStabilizer library.
30
+ cuQuantum Python JAX provides a JAX extension for cuQuantum Python. It exposes selected functionalities of cuQuantum SDK in a JAX-compatible way that enables JAX frameworks to directly interface with the exposed cuQuantum API. In the current release, cuQuantum JAX exposes JAX interfaces to the Operator Action API from the cuDensityMat library and the GF(2) sparse-dense matrix multiplication from the cuStabilizer library.
31
31
 
32
32
  ## Documentation
33
33
 
@@ -39,15 +39,17 @@ Please visit the [NVIDIA cuQuantum Python documentation](https://docs.nvidia.com
39
39
 
40
40
  The build-time dependencies of the cuQuantum Python JAX package include:
41
41
 
42
+ * Python 3.11+
42
43
  * CUDA Toolkit 12.x or 13.x
43
- * jax[cuda12-local]>=0.5,<0.7 for CUDA 12 or jax[cuda13-local]>=0.8,<0.9 for CUDA 13
44
+ * cmake>=3.22
45
+ * jax[cuda12-local]>=0.8 for CUDA 12 or jax[cuda13-local]>=0.8 for CUDA 13
44
46
  * pybind11
45
47
  * wheel
46
48
  * setuptools>=77.0.3
47
49
 
48
50
  Note:
49
- - cuQuantum Python JAX is only supported with CUDA 12 and CUDA 13.
50
- - cuQuantum Python JAX wheels are CUDA-versioned: `cuquantum-python-jax-cu12` for CUDA 12 and `cuquantum-python-jax-cu13` for CUDA 13.
51
+ - cuQuantum Python JAX is only supported with CUDA 12 and CUDA 13 and the distributions are CUDA-versioned: `cuquantum-python-jax-cu12` for CUDA 12 and `cuquantum-python-jax-cu13` for CUDA 13.
52
+ - **Build isolation note:** When installing with build isolation (`pip`'s default mode), the JAX version used at build time is determined by the build dependency specification in `pyproject.toml` and may differ from the JAX version pre-installed in the environment. Mismatched build-time and runtime JAX versions can lead to errors when importing cuQuantum's JAX extension. We recommend passing `--no-build-isolation` to `pip install` and pre-installing all build dependencies manually.
51
53
 
52
54
  #### Installation using `jax[cudaXX-local]`
53
55
 
@@ -101,10 +103,11 @@ The CUDA version is detected automatically from `$CUDA_PATH` and the wheel will
101
103
 
102
104
  Runtime dependencies of the cuQuantum Python JAX package include:
103
105
 
106
+ * Python 3.11+
104
107
  * An NVIDIA GPU with compute capability 7.5+
105
108
  * CUDA Toolkit 12.x or 13.x
106
- * cuquantum-python-cu12~=26.3.0 for CUDA 12 or cuquantum-python-cu13~=26.3.0 for CUDA 13
107
- * jax[cuda12-local]>=0.5,<0.7 for CUDA 12 or jax[cuda13-local]>=0.8,<0.9 for CUDA 13
109
+ * cuquantum-python-cu12~=26.11.0 for CUDA 12 or cuquantum-python-cu13~=26.11.0 for CUDA 13
110
+ * jax[cuda12-local]>=0.8 for CUDA 12 or jax[cuda13-local]>=0.8 for CUDA 13
108
111
 
109
112
  ## Developer Notes
110
113
 
@@ -1,6 +1,6 @@
1
1
  # cuQuantum Python JAX
2
2
 
3
- cuQuantum Python JAX provides a JAX extension for cuQuantum Python. It exposes selected functionality of cuQuantum SDK in a JAX-compatible way that enables JAX frameworks to directly interface with the exposed cuQuantum API. In the current release, cuQuantum JAX exposes a JAX interface to the Operator Action API from the cuDensityMat library and the GF(2) sparse-dense matrix multiply from the cuStabilizer library.
3
+ cuQuantum Python JAX provides a JAX extension for cuQuantum Python. It exposes selected functionalities of cuQuantum SDK in a JAX-compatible way that enables JAX frameworks to directly interface with the exposed cuQuantum API. In the current release, cuQuantum JAX exposes JAX interfaces to the Operator Action API from the cuDensityMat library and the GF(2) sparse-dense matrix multiplication from the cuStabilizer library.
4
4
 
5
5
  ## Documentation
6
6
 
@@ -12,15 +12,17 @@ Please visit the [NVIDIA cuQuantum Python documentation](https://docs.nvidia.com
12
12
 
13
13
  The build-time dependencies of the cuQuantum Python JAX package include:
14
14
 
15
+ * Python 3.11+
15
16
  * CUDA Toolkit 12.x or 13.x
16
- * jax[cuda12-local]>=0.5,<0.7 for CUDA 12 or jax[cuda13-local]>=0.8,<0.9 for CUDA 13
17
+ * cmake>=3.22
18
+ * jax[cuda12-local]>=0.8 for CUDA 12 or jax[cuda13-local]>=0.8 for CUDA 13
17
19
  * pybind11
18
20
  * wheel
19
21
  * setuptools>=77.0.3
20
22
 
21
23
  Note:
22
- - cuQuantum Python JAX is only supported with CUDA 12 and CUDA 13.
23
- - cuQuantum Python JAX wheels are CUDA-versioned: `cuquantum-python-jax-cu12` for CUDA 12 and `cuquantum-python-jax-cu13` for CUDA 13.
24
+ - cuQuantum Python JAX is only supported with CUDA 12 and CUDA 13 and the distributions are CUDA-versioned: `cuquantum-python-jax-cu12` for CUDA 12 and `cuquantum-python-jax-cu13` for CUDA 13.
25
+ - **Build isolation note:** When installing with build isolation (`pip`'s default mode), the JAX version used at build time is determined by the build dependency specification in `pyproject.toml` and may differ from the JAX version pre-installed in the environment. Mismatched build-time and runtime JAX versions can lead to errors when importing cuQuantum's JAX extension. We recommend passing `--no-build-isolation` to `pip install` and pre-installing all build dependencies manually.
24
26
 
25
27
  #### Installation using `jax[cudaXX-local]`
26
28
 
@@ -74,10 +76,11 @@ The CUDA version is detected automatically from `$CUDA_PATH` and the wheel will
74
76
 
75
77
  Runtime dependencies of the cuQuantum Python JAX package include:
76
78
 
79
+ * Python 3.11+
77
80
  * An NVIDIA GPU with compute capability 7.5+
78
81
  * CUDA Toolkit 12.x or 13.x
79
- * cuquantum-python-cu12~=26.3.0 for CUDA 12 or cuquantum-python-cu13~=26.3.0 for CUDA 13
80
- * jax[cuda12-local]>=0.5,<0.7 for CUDA 12 or jax[cuda13-local]>=0.8,<0.9 for CUDA 13
82
+ * cuquantum-python-cu12~=26.11.0 for CUDA 12 or cuquantum-python-cu13~=26.11.0 for CUDA 13
83
+ * jax[cuda12-local]>=0.8 for CUDA 12 or jax[cuda13-local]>=0.8 for CUDA 13
81
84
 
82
85
  ## Developer Notes
83
86
 
@@ -2,11 +2,6 @@
2
2
  #
3
3
  # SPDX-License-Identifier: BSD-3-Clause
4
4
 
5
- from cuquantum.bindings._internal import cudensitymat as _cudm
6
- _cudm._inspect_function_pointers() # for loading libcudensitymat.so
7
-
8
- import jax
9
-
10
5
  try:
11
6
  from ._build_info import check_jax_abi as _check_jax_abi
12
7
  except ImportError:
@@ -15,13 +10,11 @@ else:
15
10
  _check_jax_abi()
16
11
  del _check_jax_abi
17
12
 
18
- if not jax.config.jax_enable_x64:
19
- raise RuntimeError("jax_enable_x64 must be set to True to use cuQuantum Python JAX")
20
-
21
13
  from .operator_action import operator_action
22
14
  from .pysrc import (
23
15
  ElementaryOperator,
24
16
  MatrixOperator,
25
17
  OperatorTerm,
26
- Operator
18
+ Operator,
19
+ SimplifierConfig
27
20
  )
@@ -63,8 +63,8 @@
63
63
  // LIBRARY VERSION
64
64
 
65
65
  #define CUDENSITYMAT_MAJOR 0 //!< cuDensityMat major version.
66
- #define CUDENSITYMAT_MINOR 6 //!< cuDensityMat minor version.
67
- #define CUDENSITYMAT_PATCH 0 //!< cuDensityMat patch version.
66
+ #define CUDENSITYMAT_MINOR 7 //!< cuDensityMat minor version.
67
+ #define CUDENSITYMAT_PATCH 1 //!< cuDensityMat patch version.
68
68
  #define CUDENSITYMAT_VERSION (CUDENSITYMAT_MAJOR * 10000 + CUDENSITYMAT_MINOR * 100 + CUDENSITYMAT_PATCH)
69
69
 
70
70
 
@@ -282,7 +282,8 @@ typedef enum
282
282
  */
283
283
  typedef enum
284
284
  {
285
- CUDENSITYMAT_EIGEN_SCOPE_SPLIT_DMRG = 0, ///< DMRG-based split decomposition (default)
285
+ CUDENSITYMAT_EIGEN_SCOPE_SPLIT_DMRG = 0, ///< DMRG-based split decomposition (default)
286
+ CUDENSITYMAT_EIGEN_SCOPE_SPLIT_SHIFT_INVERT_DMRG = 1, ///< Shift-invert DMRG split decomposition (eigenpair nearest a target energy)
286
287
  } cudensitymatEigenDecompositionScopeSplitKind_t;
287
288
 
288
289
  /**
@@ -298,8 +299,9 @@ typedef enum
298
299
  */
299
300
  typedef enum
300
301
  {
301
- CUDENSITYMAT_EIGEN_APPROACH_KRYLOV = 0, ///< Krylov subspace method
302
- //CUDENSITYMAT_EIGEN_APPROACH_DAVIDSON = 1, ///< Davidson method
302
+ CUDENSITYMAT_EIGEN_APPROACH_KRYLOV = 0, ///< Krylov subspace (block-Lanczos) eigensolver
303
+ CUDENSITYMAT_EIGEN_APPROACH_LINEAR = 1, ///< Iterative linear solver (currently MINRES)
304
+ //CUDENSITYMAT_EIGEN_APPROACH_DAVIDSON = 2, ///< Davidson method
303
305
  } cudensitymatEigenDecompositionApproachKind_t;
304
306
 
305
307
  /**
@@ -322,8 +324,9 @@ typedef enum
322
324
  CUDENSITYMAT_EIGEN_SPLIT_SCOPE_KIND = 0, ///< int32_t (cudensitymatEigenDecompositionScopeSplitKind_t): Split kind
323
325
  //CUDENSITYMAT_EIGEN_FULL_SCOPE_KIND = 1, ///< int32_t (cudensitymatEigenDecompositionScopeFullKind_t): Full-scope kind
324
326
  //CUDENSITYMAT_EIGEN_FULL_SCOPE_EXACT_CONFIG = 2, ///< cudensitymatEigenDecompositionScopeFullExactConfig_t: Full exact-scope configuration
325
- CUDENSITYMAT_EIGEN_SPLIT_SCOPE_DMRG_CONFIG = 3, ///< cudensitymatEigenDecompositionScopeSplitDMRGConfig_t: DMRG split configuration
327
+ CUDENSITYMAT_EIGEN_SPLIT_SCOPE_DMRG_CONFIG = 3, ///< cudensitymatEigenDecompositionScopeSplitDMRGConfig_t: DMRG split configuration (shared by the DMRG and shift-invert DMRG split kinds)
326
328
  CUDENSITYMAT_EIGEN_APPROACH_KRYLOV_CONFIG = 10, ///< cudensitymatEigenDecompositionApproachKrylovConfig_t: Krylov approach configuration
329
+ CUDENSITYMAT_EIGEN_APPROACH_LINEAR_CONFIG = 11, ///< cudensitymatEigenDecompositionApproachLinearConfig_t: Linear-solver approach configuration
327
330
  } cudensitymatEigenDecompositionAttribute_t;
328
331
 
329
332
  // /**
@@ -378,12 +381,21 @@ typedef enum
378
381
  */
379
382
  typedef enum
380
383
  {
381
- CUDENSITYMAT_EIGEN_SPLIT_SCOPE_DMRG_NUM_SITES = 0, ///< int32_t: Number of sites in the DMRG chain (default: 1)
382
- CUDENSITYMAT_EIGEN_SPLIT_SCOPE_DMRG_SVD_CONFIG = 1, ///< cudensitymatSVDConfig_t: SVD truncation configuration
383
- CUDENSITYMAT_EIGEN_SPLIT_SCOPE_DMRG_MAX_SWEEPS = 2, ///< int32_t: Maximum number of full L-R-L sweeps (default: 20)
384
- CUDENSITYMAT_EIGEN_SPLIT_SCOPE_DMRG_ENERGY_TOLERANCE = 3, ///< double: Convergence threshold on the change in variational energy between consecutive sweeps; the sweep loop terminates when |E_k - E_{k-1}| falls below this value (default: 1e-10)
384
+ CUDENSITYMAT_EIGEN_SPLIT_SCOPE_DMRG_NUM_SITES = 0, ///< int32_t: Number of neighboring MPS sites updated in each local solve (1 or 2; default: 1). SetAttribute returns CUDENSITYMAT_STATUS_INVALID_VALUE for values <= 0 and CUDENSITYMAT_STATUS_NOT_SUPPORTED for values > 2.
385
+ CUDENSITYMAT_EIGEN_SPLIT_SCOPE_DMRG_SVD_CONFIG = 1, ///< cudensitymatSVDConfig_t: SVD truncation configuration for 2-site updates
386
+ CUDENSITYMAT_EIGEN_SPLIT_SCOPE_DMRG_MAX_SWEEPS = 2, ///< int32_t: Maximum number of full L-R-L sweeps (default: 20); for shift-invert, the fitting-sweep cap for each inverse application
387
+ CUDENSITYMAT_EIGEN_SPLIT_SCOPE_DMRG_ENERGY_TOLERANCE = 3, ///< double: Convergence threshold on the change in energy between consecutive sweeps for ground-state DMRG or outer power iterations for shift-invert DMRG (default: 1e-10)
388
+ CUDENSITYMAT_EIGEN_SPLIT_SCOPE_DMRG_MAX_POWER_ITERATIONS = 4, ///< int32_t: Maximum number of outer power iterations on (H - sigma)^{-1} for the shift-invert DMRG split kind; ignored by the ground-state DMRG split kind (default: 10)
385
389
  } cudensitymatEigenDecompositionScopeSplitDMRGConfigAttribute_t;
386
390
 
391
+ /**
392
+ * \brief Configuration attributes for the iterative linear solver (currently MINRES).
393
+ */
394
+ typedef enum
395
+ {
396
+ CUDENSITYMAT_EIGEN_APPROACH_LINEAR_MAX_ITERATIONS = 0, ///< int32_t: Maximum number of iterations for the local linear solve (default: 200). The per-site solve convergence tolerance is supplied at Compute time via the in/out tolerances[] argument, not as a config attribute.
397
+ } cudensitymatEigenDecompositionApproachLinearConfigAttribute_t;
398
+
387
399
  /**
388
400
  * \brief State-fitting scope (full vs split fitting).
389
401
  */
@@ -500,7 +512,7 @@ typedef enum
500
512
  typedef enum
501
513
  {
502
514
  CUDENSITYMAT_EIGEN_SPECTRUM_LARGEST = 0, ///< Compute the largest by magnitude eigen-values of the operator
503
- CUDENSITYMAT_EIGEN_SPECTRUM_SMALLEST = 1, ///< Compute the smallest by magnitude eigen-values of the operator
515
+ CUDENSITYMAT_EIGEN_SPECTRUM_SMALLEST = 1, ///< Compute the smallest by magnitude eigenvalues; for shift-invert DMRG, select the smallest |E - sigma| using the Compute target
504
516
  CUDENSITYMAT_EIGEN_SPECTRUM_LARGEST_REAL = 2, ///< Compute the largest by the real part eigen-values of the operator
505
517
  CUDENSITYMAT_EIGEN_SPECTRUM_SMALLEST_REAL = 3, ///< Compute the smallest by the real part eigen-values of the operator
506
518
  } cudensitymatEigenDecompositionSpectrumKind_t;
@@ -685,6 +697,14 @@ typedef void * cudensitymatTimePropagationScopeSplitTDVPConfig_t;
685
697
  */
686
698
  typedef void * cudensitymatEigenDecompositionScopeSplitDMRGConfig_t;
687
699
 
700
+ /**
701
+ * \brief Opaque data structure holding the iterative linear-solver configuration.
702
+ *
703
+ * \details This configuration object stores the iteration cap for the iterative
704
+ * linear solver; the solve tolerance is supplied to Compute.
705
+ */
706
+ typedef void * cudensitymatEigenDecompositionApproachLinearConfig_t;
707
+
688
708
  /**
689
709
  * \brief Opaque data structure holding variational ALS configuration
690
710
  * for split-scope state fitting on a factorized (e.g., MPS) quantum state.
@@ -1631,7 +1651,8 @@ cudensitymatStatus_t cudensitymatStateComputeInnerProduct(
1631
1651
  * The full non-zero diagonals are stored in a concatenated form,
1632
1652
  * following the order how they appear in the `diagonalOffsets` argument.
1633
1653
  * The length of each stored diagonal is equal to the full matrix dimension,
1634
- * padded with trailing zeros for non-main diagonals.
1654
+ * padded with trailing zeros for non-main diagonals. Each non-zero diagonal
1655
+ * is stored exactly once, hence all diagonal offsets must be unique.
1635
1656
  *
1636
1657
  * \note Currently the multi-diagonal storage format is only supported
1637
1658
  * by 1-body elementary tensor operators (restriction subject to lifting in future).
@@ -1648,7 +1669,9 @@ cudensitymatStatus_t cudensitymatStateComputeInnerProduct(
1648
1669
  * \param[in] diagonalOffsets For multi-diagonal tensor operator matrices, these are
1649
1670
  * the offsets of the non-zero diagonals (for example, the main diagonal has offset 0,
1650
1671
  * the diagonal right above the main diagonal has offset +1, the diagonal right below
1651
- * the main diagonal has offset -1, and so on).
1672
+ * the main diagonal has offset -1, and so on). The diagonal offsets must be unique
1673
+ * (each non-zero diagonal is specified and stored exactly once); repeated offsets
1674
+ * are rejected.
1652
1675
  * \param[in] dataType Tensor operator data type.
1653
1676
  * \param[in] tensorData GPU-accessible pointer to the tensor operator elements storage.
1654
1677
  * \param[in] tensorCallback Optional user-defined tensor callback function
@@ -1703,7 +1726,8 @@ cudensitymatStatus_t cudensitymatCreateElementaryOperator(
1703
1726
  * The full non-zero diagonals are stored in a concatenated form,
1704
1727
  * following the order how they appear in the `diagonalOffsets` argument.
1705
1728
  * The length of each stored diagonal is equal to the full matrix dimension,
1706
- * padded with trailing zeros for non-main diagonals.
1729
+ * padded with trailing zeros for non-main diagonals. Each non-zero diagonal
1730
+ * is stored exactly once, hence all diagonal offsets must be unique.
1707
1731
  *
1708
1732
  * \note Currently the multi-diagonal storage format is only supported
1709
1733
  * by 1-body elementary tensor operators (restriction subject to lifting in future).
@@ -1724,6 +1748,8 @@ cudensitymatStatus_t cudensitymatCreateElementaryOperator(
1724
1748
  * \param[in] diagonalOffsets Offsets of the non-zero diagonals (for example,
1725
1749
  * the main diagonal has offset 0, the diagonal right above the main diagonal
1726
1750
  * has offset +1, the diagonal right below the main diagonal has offset -1, and so on).
1751
+ * The diagonal offsets must be unique (each non-zero diagonal is specified and
1752
+ * stored exactly once); repeated offsets are rejected.
1727
1753
  * \param[in] dataType Tensor operator data type.
1728
1754
  * \param[in] tensorData GPU-accessible pointer to the tensor operator elements storage,
1729
1755
  * where all elementary tensor operators within the batch are stored contiguously in memory.
@@ -3011,9 +3037,13 @@ cudensitymatStatus_t cudensitymatOperatorSpectrumPrepare(
3011
3037
  * of shape [numEigenStates, batchSize]) in GPU-accessible RAM (same data type
3012
3038
  * as used by the quantum state and operator).
3013
3039
  * \param[inout] tolerances Pointer to an F-order array of shape [numEigenStates, batchSize]
3014
- * in CPU-accessible RAM. The initial values represent the desirable convergence tolerances
3015
- * for all eigen-states. The returned values represent the actually achieved residual norms
3016
- * for all eigen-states.
3040
+ * in CPU-accessible RAM. On input, the desired solver convergence tolerances for all
3041
+ * eigen-states; on output, the actually achieved solver convergence residual norms (which
3042
+ * may differ from the requested values in either direction). These characterize solver
3043
+ * convergence, not the representation error of the returned state. For the full-state solver
3044
+ * they coincide with the eigenpair residual ||H x - E x||; for split (DMRG / shift-invert)
3045
+ * solvers the returned value is the local per-site solver residual, NOT the global
3046
+ * ||H|psi> - E|psi>||. The representation error is a separate quantity (dedicated query, when available).
3017
3047
  * \param[in] workspace Allocated workspace descriptor.
3018
3048
  * \param[in] stream CUDA stream.
3019
3049
  * \return cudensitymatStatus_t
@@ -3572,6 +3602,71 @@ cudensitymatStatus_t cudensitymatEigenDecompositionApproachKrylovConfigGetAttrib
3572
3602
  void * attributeValue,
3573
3603
  size_t attributeSize);
3574
3604
 
3605
+ // ============================================================================
3606
+ // Linear-Solver Configuration API (eigensolver)
3607
+ // ============================================================================
3608
+
3609
+ /**
3610
+ * \brief Creates an eigen-decomposition iterative linear-solver approach
3611
+ * configuration object with default settings.
3612
+ *
3613
+ * \param[in] handle Library handle.
3614
+ * \param[out] config Linear-solver configuration object.
3615
+ * \return cudensitymatStatus_t
3616
+ */
3617
+ cudensitymatStatus_t cudensitymatCreateEigenDecompositionApproachLinearConfig(
3618
+ const cudensitymatHandle_t handle,
3619
+ cudensitymatEigenDecompositionApproachLinearConfig_t * config);
3620
+
3621
+ /**
3622
+ * \brief Destroys an eigen-decomposition iterative linear-solver approach
3623
+ * configuration object.
3624
+ *
3625
+ * \param[in] config Linear-solver configuration object.
3626
+ * \return cudensitymatStatus_t
3627
+ */
3628
+ cudensitymatStatus_t cudensitymatDestroyEigenDecompositionApproachLinearConfig(cudensitymatEigenDecompositionApproachLinearConfig_t config);
3629
+
3630
+ /**
3631
+ * \brief Sets an attribute of the eigen-decomposition iterative linear-solver
3632
+ * approach configuration.
3633
+ *
3634
+ * \param[in] handle Library handle.
3635
+ * \param[in] config Linear-solver configuration object.
3636
+ * \param[in] attribute Attribute to set.
3637
+ * \param[in] attributeValue Pointer to the attribute value.
3638
+ * \param[in] attributeSize Size of the attribute value in bytes.
3639
+ * \return cudensitymatStatus_t
3640
+ *
3641
+ * \note The library captures the attribute by value at this call; the caller
3642
+ * retains ownership of `attributeValue` and may destroy the source as soon as
3643
+ * the call returns.
3644
+ */
3645
+ cudensitymatStatus_t cudensitymatEigenDecompositionApproachLinearConfigSetAttribute(
3646
+ const cudensitymatHandle_t handle,
3647
+ cudensitymatEigenDecompositionApproachLinearConfig_t config,
3648
+ cudensitymatEigenDecompositionApproachLinearConfigAttribute_t attribute,
3649
+ const void * attributeValue,
3650
+ size_t attributeSize);
3651
+
3652
+ /**
3653
+ * \brief Gets an attribute of the eigen-decomposition iterative linear-solver
3654
+ * approach configuration.
3655
+ *
3656
+ * \param[in] handle Library handle.
3657
+ * \param[in] config Linear-solver configuration object.
3658
+ * \param[in] attribute Attribute to get.
3659
+ * \param[out] attributeValue Pointer to store the attribute value.
3660
+ * \param[in] attributeSize Size of the buffer in bytes.
3661
+ * \return cudensitymatStatus_t
3662
+ */
3663
+ cudensitymatStatus_t cudensitymatEigenDecompositionApproachLinearConfigGetAttribute(
3664
+ const cudensitymatHandle_t handle,
3665
+ const cudensitymatEigenDecompositionApproachLinearConfig_t config,
3666
+ cudensitymatEigenDecompositionApproachLinearConfigAttribute_t attribute,
3667
+ void * attributeValue,
3668
+ size_t attributeSize);
3669
+
3575
3670
  // ============================================================================
3576
3671
  // Eigen Decomposition API
3577
3672
  // ============================================================================
@@ -3584,7 +3679,8 @@ cudensitymatStatus_t cudensitymatEigenDecompositionApproachKrylovConfigGetAttrib
3584
3679
  * \param[in] isHermitian Specifies whether the operator is Hermitian (!=0) or not (0).
3585
3680
  * \param[in] spectrumKind Requested kind of the eigen-spectrum computation.
3586
3681
  * \param[in] scopeKind Requested decomposition scope (full vs split).
3587
- * \param[in] approachKind Requested decomposition approach (e.g., Krylov).
3682
+ * \param[in] approachKind Requested decomposition approach (e.g., Krylov or
3683
+ * iterative linear solve).
3588
3684
  * \param[out] eigenDecomposition Eigen-decomposition computation object.
3589
3685
  * \return cudensitymatStatus_t
3590
3686
  *
@@ -3595,6 +3691,10 @@ cudensitymatStatus_t cudensitymatEigenDecompositionApproachKrylovConfigGetAttrib
3595
3691
  * `CUDENSITYMAT_STATUS_NOT_SUPPORTED`; only Hermitian operators are
3596
3692
  * supported in this release. The library trusts the caller's flag and does
3597
3693
  * not verify Hermiticity of the operator.
3694
+ *
3695
+ * \note In this release, an operator containing more than one MPO product,
3696
+ * or an MPO product containing more than one MPO, is rejected at Create with
3697
+ * `CUDENSITYMAT_STATUS_NOT_SUPPORTED`.
3598
3698
  */
3599
3699
  cudensitymatStatus_t cudensitymatCreateEigenDecomposition(
3600
3700
  const cudensitymatHandle_t handle,
@@ -3655,17 +3755,26 @@ cudensitymatStatus_t cudensitymatEigenDecompositionConfigure(
3655
3755
  * \param[in] stream CUDA stream.
3656
3756
  * \return cudensitymatStatus_t
3657
3757
  *
3758
+ * \note Prepare is transactional with respect to the cached eigen plan and
3759
+ * workspace requirements. If Prepare fails without an intervening successful
3760
+ * Configure, the last successfully prepared plan and workspace requirements
3761
+ * remain valid provided the generator, state geometry, and Context distribution
3762
+ * are unchanged. A successful Configure invalidates the prepared lifecycle, so
3763
+ * a subsequent failed Prepare leaves the object unprepared.
3764
+ *
3658
3765
  * \note In this release, Prepare returns `CUDENSITYMAT_STATUS_NOT_SUPPORTED`
3659
3766
  * when any of the following conditions is met:
3660
3767
  * (a) the `scopeKind` provided at Create is `CUDENSITYMAT_EIGEN_SCOPE_FULL`;
3661
3768
  * (b) the bound DMRG configuration has `CUDENSITYMAT_EIGEN_SPLIT_SCOPE_DMRG_NUM_SITES`
3662
3769
  * not in `{1, 2}` (only 1-site and 2-site DMRG are supported in this release);
3663
3770
  * (c) `maxEigenStates != 1` (only a single eigen-pair is supported in this release);
3664
- * (d) the `spectrumKind` provided at Create is not
3665
- * `CUDENSITYMAT_EIGEN_SPECTRUM_SMALLEST_REAL` (only the smallest-real
3666
- * eigenvalue is supported by the DMRG engine in this release);
3771
+ * (d) the selected split/approach/spectrum combination is neither
3772
+ * `SPLIT_DMRG + KRYLOV + SMALLEST_REAL` nor
3773
+ * `SPLIT_SHIFT_INVERT_DMRG + LINEAR + SMALLEST`;
3667
3774
  * (e) the representative `state` is a single-site (1-mode) MPS (an MPS
3668
- * with at least two sites is required by the DMRG engine).
3775
+ * with at least two sites is required by the DMRG engine);
3776
+ * (f) the state data type is not `CUDA_R_64F` or `CUDA_C_64F`, or
3777
+ * `computeType` is not `CUDENSITYMAT_COMPUTE_64F`.
3669
3778
  */
3670
3779
  cudensitymatStatus_t cudensitymatEigenDecompositionPrepare(
3671
3780
  const cudensitymatHandle_t handle,
@@ -3697,13 +3806,25 @@ cudensitymatStatus_t cudensitymatEigenDecompositionPrepare(
3697
3806
  * \param[inout] eigenstates Quantum eigenstates.
3698
3807
  * The initial values of the provided quantum states will be used as the
3699
3808
  * initial guesses for the iterative solver.
3700
- * \param[out] eigenvalues Pointer to the eigenvalues storage (F-order array
3809
+ * \param[inout] eigenvalues Pointer to the eigenvalues storage (F-order array
3701
3810
  * of shape [numEigenStates, batchSize]) in GPU-accessible RAM (same data type
3702
- * as used by the quantum state and operator).
3811
+ * as used by the quantum state and operator). For the shift-invert DMRG split kind,
3812
+ * the input value is the target energy sigma (the returned eigenpair is the one whose
3813
+ * eigenvalue is nearest sigma); it is ignored on input by other split kinds/approaches.
3814
+ * On output, holds the computed eigenvalue(s).
3703
3815
  * \param[inout] tolerances Pointer to an F-order array of shape [numEigenStates, batchSize]
3704
- * in CPU-accessible RAM. The initial values represent the desirable convergence tolerances
3705
- * for all eigen-states. The returned values represent the actually achieved residual norms
3706
- * for all eigen-states.
3816
+ * in CPU-accessible RAM. On input, the desired solver convergence tolerances for all
3817
+ * eigen-states; on output, the actually achieved solver convergence residual norms (which
3818
+ * may differ from the requested values in either direction). These characterize solver
3819
+ * convergence, not the representation error of the returned state. For the full-state solver
3820
+ * they coincide with the eigenpair residual ||H x - E x||; for split (DMRG / shift-invert)
3821
+ * solvers the returned value is the local per-site solver residual, NOT the global
3822
+ * ||H|psi> - E|psi>||. The representation error is a separate quantity (dedicated query, when available).
3823
+ * For shift-invert DMRG specifically, the input value is the requested per-site
3824
+ * relative normal-equation tolerance. On output it is the maximum achieved absolute
3825
+ * post-insertion (and, for 2-site updates, post-truncation) local normal-equation
3826
+ * residual over every region in the final complete fitting sweep of the final outer
3827
+ * iteration. It is not the achieved outer energy-difference metric.
3707
3828
  * \param[in] workspace Allocated workspace descriptor.
3708
3829
  * \param[in] stream CUDA stream.
3709
3830
  * \return cudensitymatStatus_t
@@ -3714,10 +3835,25 @@ cudensitymatStatus_t cudensitymatEigenDecompositionPrepare(
3714
3835
  * \note `numEigenStates != 1` returns `CUDENSITYMAT_STATUS_NOT_SUPPORTED`
3715
3836
  * in this release; only a single eigen-pair is supported.
3716
3837
  *
3838
+ * \note `batchSize < 1` returns `CUDENSITYMAT_STATUS_INVALID_VALUE`;
3839
+ * `batchSize > 1` returns `CUDENSITYMAT_STATUS_NOT_SUPPORTED`.
3840
+ *
3841
+ * \note `handle` and its distributed configuration must match the last
3842
+ * successful Prepare. After changing either, call Prepare again before Compute.
3843
+ *
3717
3844
  * \note The eigenvalue data type matches the state's data type (i.e., the
3718
3845
  * complex type used for the input `eigenstates`). For Hermitian operators
3719
3846
  * the real eigenvalue is written into the complex slot with `imag = 0`.
3720
3847
  *
3848
+ * \note Shift-invert convergence requires finite real sigma, d1 > 0, and
3849
+ * d1 < d2, where d1 and d2 are the nearest distinct-eigenvalue distances.
3850
+ * A degenerate nearest eigenspace is allowed; exact and equidistant targets
3851
+ * are not detected or detuned.
3852
+ *
3853
+ * \note Cap exhaustion returns `CUDENSITYMAT_STATUS_SUCCESS` with the final
3854
+ * normalized approximation, Rayleigh quotient, and final-sweep local residual;
3855
+ * these outputs do not certify outer or global convergence.
3856
+ *
3721
3857
  * \note The input `eigenstates` are used as initial guesses for the iterative
3722
3858
  * solver. The library does not canonicalize them; the caller is responsible
3723
3859
  * for providing a linearly-independent (and ideally well-conditioned) set.
@@ -3788,6 +3924,12 @@ cudensitymatStatus_t cudensitymatDestroyWorkspace(
3788
3924
  /**
3789
3925
  * \brief Queries the required workspace buffer size.
3790
3926
  *
3927
+ * \note Two-site MPS operations can execute without caller-provided host
3928
+ * scratch even when a nonzero host workspace size is reported. If host
3929
+ * scratch is provided, its size must be at least the reported value.
3930
+ * Providing the reported host workspace is recommended for performance.
3931
+ * Device scratch requirements remain mandatory.
3932
+ *
3791
3933
  * \param[in] handle Library handle.
3792
3934
  * \param[in] workspaceDescr Workspace descriptor.
3793
3935
  * \param[in] memSpace Memory space.
@@ -56,7 +56,7 @@ xla::ffi::Error OperatorActionImpl(cudaStream_t stream,
56
56
  FFI_CUDA_ERROR_CHECK(cudaStreamSynchronize(stream));
57
57
  }
58
58
 
59
- // Attach storage to input state.
59
+ // Process buffers for all inputs, including input state, elementary/matrix operators and coefficients.
60
60
  std::vector<void*> stateInComponentBufs;
61
61
  std::vector<size_t> stateInComponentSizes;
62
62
  for (int i = 0; i < inBufs.size(); ++i) {
@@ -103,6 +103,7 @@ xla::ffi::Error OperatorActionImpl(cudaStream_t stream,
103
103
  FFI_CUDA_ERROR_CHECK(cudaStreamSynchronize(stream));
104
104
  }
105
105
 
106
+ // Attach storage to input state.
106
107
  FFI_CUDM_ERROR_CHECK(cudensitymatStateAttachComponentStorage(handle,
107
108
  stateIn,
108
109
  numStateComponents,
@@ -147,9 +148,6 @@ xla::ffi::Error OperatorActionImpl(cudaStream_t stream,
147
148
  stateOutComponentSizes.data())
148
149
  );
149
150
 
150
-
151
- // Execute operator action.
152
-
153
151
  // Attach batched coefficients if needed.
154
152
  if (operatorTermBatchedCoeffsPtrs.size() > 0 || operatorProductBatchedCoeffsPtrs.size() > 0) {
155
153
  FFI_CUDM_ERROR_CHECK(cudensitymatAttachBatchedCoefficients(
@@ -166,8 +164,7 @@ xla::ffi::Error OperatorActionImpl(cudaStream_t stream,
166
164
  // Initialize output state to zero.
167
165
  FFI_CUDM_ERROR_CHECK(cudensitymatStateInitializeZero(handle, stateOut, stream));
168
166
 
169
- FFI_CUDA_ERROR_CHECK(cudaStreamSynchronize(stream));
170
-
167
+ // Execute operator action.
171
168
  FFI_CUDM_ERROR_CHECK(cudensitymatOperatorComputeAction(handle,
172
169
  superoperator,
173
170
  0.0, // time
@@ -193,8 +190,8 @@ XLA_FFI_DEFINE_HANDLER_SYMBOL(
193
190
  OperatorActionImpl,
194
191
  xla::ffi::Ffi::Bind()
195
192
  .Ctx<xla::ffi::PlatformStream<cudaStream_t>>()
196
- .RemainingArgs() // all input buffers
197
- .RemainingRets() // all output buffers (workspace first, then state out components)
193
+ .RemainingArgs() // all input buffers (state_in components, elementary/matrix operators, coefficients)
194
+ .RemainingRets() // all output buffers (workspace first, then state_out components)
198
195
  .Attr<xla::ffi::Span<const int64_t>>("other_in_types")
199
196
  .Attr<xla::ffi::Span<const int64_t>>("other_in_ptrs")
200
197
  .Attr<int64_t>("batch_size")
@@ -316,7 +313,6 @@ xla::ffi::Error OperatorActionBackwardDiffImpl(cudaStream_t stream,
316
313
  stateOutAdjComponentSizes.data()));
317
314
 
318
315
  // Attach storage to output state.
319
- // outBufs layout: [workspace, state in adj components..., grad bufs...]
320
316
  std::vector<void*> stateInAdjComponentBufs;
321
317
  std::vector<size_t> stateInAdjComponentSizes;
322
318
 
@@ -353,10 +349,18 @@ xla::ffi::Error OperatorActionBackwardDiffImpl(cudaStream_t stream,
353
349
  workspacePtrAligned,
354
350
  workspaceSizeAligned));
355
351
 
356
- // Initialize output state to zero.
352
+ // Initialize state_in_adj to zero.
357
353
  FFI_CUDM_ERROR_CHECK(cudensitymatStateInitializeZero(handle, stateInAdj, stream));
358
354
 
359
- // Execute operator action backward differentiation.
355
+ // Zero out the persistent gradient buffers.
356
+ for (int i = 0; i < otherOutPtrs.size(); ++i) {
357
+ xla::ffi::Result<xla::ffi::AnyBuffer> resBuf =
358
+ outBufs.get<xla::ffi::AnyBuffer>(i + numStateComponents + 1).value();
359
+ FFI_CUDA_ERROR_CHECK(cudaMemsetAsync(reinterpret_cast<void*>(otherOutPtrs[i]),
360
+ 0,
361
+ resBuf->size_bytes(),
362
+ stream));
363
+ }
360
364
 
361
365
  // Attach batched coefficients if needed.
362
366
  if (operatorTermBatchedCoeffsPtrs.size() > 0 || operatorProductBatchedCoeffsPtrs.size() > 0) {
@@ -371,6 +375,7 @@ xla::ffi::Error OperatorActionBackwardDiffImpl(cudaStream_t stream,
371
375
  operatorProductBatchedCoeffs.data()));
372
376
  }
373
377
 
378
+ // Execute operator action backward differentiation.
374
379
  FFI_CUDM_ERROR_CHECK(cudensitymatOperatorComputeActionBackwardDiff(handle,
375
380
  superoperator,
376
381
  0.0, // time
@@ -384,13 +389,7 @@ xla::ffi::Error OperatorActionBackwardDiffImpl(cudaStream_t stream,
384
389
  workspaceDesc,
385
390
  stream));
386
391
 
387
- // The Python gradient callbacks (for both scalar and tensor operators) dispatch
388
- // their += accumulation operations on CuPy's default CUDA stream, which may differ
389
- // from the XLA FFI stream used here. Synchronize the default stream before copying
390
- // so that all callback writes are guaranteed to be visible to the memcpy below.
391
- FFI_CUDA_ERROR_CHECK(cudaStreamSynchronize(cudaStreamDefault));
392
-
393
- // outBufs layout (after workspace and numStateComponents state adj bufs): [grad bufs].
392
+ // Copy gradient buffers from CuPy arrays to XLA buffers.
394
393
  for (int i = 0; i < otherOutPtrs.size(); ++i) {
395
394
  xla::ffi::Result<xla::ffi::AnyBuffer> resBuf =
396
395
  outBufs.get<xla::ffi::AnyBuffer>(i + numStateComponents + 1).value();
@@ -418,8 +417,9 @@ XLA_FFI_DEFINE_HANDLER_SYMBOL(
418
417
  OperatorActionBackwardDiffImpl,
419
418
  xla::ffi::Ffi::Bind()
420
419
  .Ctx<xla::ffi::PlatformStream<cudaStream_t>>()
421
- .RemainingArgs() // all input buffers
422
- .RemainingRets() // all output buffers (workspace first, then state in adj components, then grad bufs)
420
+ .RemainingArgs() // all input buffers (state_in components, state_out_adj components,
421
+ // elementary/matrix operators, coefficients)
422
+ .RemainingRets() // all output buffers (workspace first, then state_in_adj components, then grad bufs)
423
423
  .Attr<xla::ffi::Span<const int64_t>>("other_in_types")
424
424
  .Attr<xla::ffi::Span<const int64_t>>("other_in_ptrs")
425
425
  .Attr<xla::ffi::Span<const int64_t>>("other_out_ptrs")