Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed
- The tutorial's vectorized-integrand example crashed with `RuntimeError: Expected
all tensors to be on the same device` on any CUDA machine. It built its helper
tensors with the legacy `torch.Tensor(...)` constructor, which — unlike
`torch.tensor(...)` — ignores the `torch.set_default_device("cuda")` that
`set_up_backend` performs, so the helpers stayed on the CPU while the sample
points were on the GPU. A note now explains the distinction, since it bites in
user code as readily as in the docs.
- The tutorial's import block used `matplotlib`, which is not a torchquad runtime
dependency, so it failed after the installation the README documents. Called out
as a prerequisite rather than added as a dependency.
- The README logo and five file links used repository-relative paths, which PyPI
resolves against `pypi.org`, so the logo did not render and the links 404ed on
the project page. All are now absolute URLs, matching the performance figures.

## [0.6.0] - 2026-08-23

The 0.6 line is a modernization and credibility release: modern tooling, honest
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<br />
<p align="center">
<a href="https://github.com/esa/torchquad">
<img src="logos/torchquad_white_background_PNG.png" alt="Logo" width="280" height="120">
<img src="https://github.com/esa/torchquad/blob/main/logos/torchquad_white_background_PNG.png?raw=true" alt="Logo" width="280" height="120">
</a>
<p align="center">
High-performance numerical integration on the GPU with PyTorch, JAX and Tensorflow
Expand Down Expand Up @@ -98,7 +98,7 @@ torchquad has no backend pinned as a hard dependency — install the numerical b
Note that torchquad also works on the CPU; however, it is optimized for GPU usage. GPU support is tested only on NVIDIA cards with CUDA. For GPU installs, follow each framework's own install guide — the CPU-only convenience extras below cannot select GPU wheels, and JAX/TensorFlow GPU builds are Linux/WSL2-only.

For a detailed list of required packages and packages for numerical backends,
please refer to the conda environment files [environment.yml](/environment.yml) and [environment_all_backends.yml](/environment_all_backends.yml).
please refer to the conda environment files [environment.yml](https://github.com/esa/torchquad/blob/main/environment.yml) and [environment_all_backends.yml](https://github.com/esa/torchquad/blob/main/environment_all_backends.yml).
torchquad requires Python 3.10 or newer. Its CI suite runs on Python 3.12 with JAX 0.4.35, NumPy 2.3, PyTorch 2.5 and TensorFlow 2.18 on Linux; other versions of the backends should work as well but some may require additional setup on other platforms such as Windows.


Expand Down Expand Up @@ -136,7 +136,7 @@ GPU support install the backend from its own guide, then `pip install torchquad`
- TensorFlow (Linux/WSL2 only): <https://www.tensorflow.org/install/gpu>

For a full multi-backend setup, the conda file
[environment_all_backends.yml](/environment_all_backends.yml) installs every
[environment_all_backends.yml](https://github.com/esa/torchquad/blob/main/environment_all_backends.yml) installs every
backend (CPU) in one step:
```sh
conda env create -f environment_all_backends.yml
Expand Down Expand Up @@ -279,7 +279,7 @@ See the [open issues](https://github.com/esa/torchquad/issues) for a list of pro

All figures below were measured on an RTX 4060 Ti / i5-13400F. Accuracy is
measured against closed-form integrals from the
[Genz test-function family](benchmarking/genz_functions.py) in float64; runtimes
[Genz test-function family](https://github.com/esa/torchquad/blob/main/benchmarking/genz_functions.py) in float64; runtimes
are float32 and synchronize the GPU before the clock stops.

### Convergence
Expand Down Expand Up @@ -411,7 +411,7 @@ float64, timings in float32.

The project is open to community contributions. Feel free to open an [issue](https://github.com/esa/torchquad/issues) or write us an email if you would like to discuss a problem or idea first.

See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide — how to set up a
See [CONTRIBUTING.md](https://github.com/esa/torchquad/blob/main/CONTRIBUTING.md) for the full guide — how to set up a
development environment, the checks CI runs, and the review process. In short:
fork the repo, branch off `develop`, and open your pull request against
`develop` (not `main`). Documentation fixes for the *current release* are the
Expand Down
36 changes: 32 additions & 4 deletions docs/source/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ Imports

Now let's get started! First, the general imports:

.. note::

This tutorial uses ``matplotlib`` for its plots and ``scipy`` for benchmark
comparisons. ``scipy`` is a torchquad dependency and is already present, but
``matplotlib`` is not — install it with ``pip install matplotlib`` if you are
following along in your own environment.

.. code:: python

import scipy
Expand Down Expand Up @@ -149,6 +156,14 @@ Now let's get started! First, the general imports:
# Use this to enable GPU support and set the floating point precision
set_up_backend("torch", data_type="float32")

.. note::

On a GPU machine this also makes CUDA the default device for newly created
tensors. If you build your own tensors alongside torchquad's, use
``torch.tensor(...)`` rather than the legacy ``torch.Tensor(...)``, which
ignores that default and allocates on the CPU — see
:ref:`this note <tensor_vs_Tensor>`.




Expand Down Expand Up @@ -792,7 +807,7 @@ sample points for both functions:

# The integration domain, dimensionality and number of evaluations
# For the calculate_grid method we need a Tensor and not a list.
integration_domain = torch.Tensor([[0.0, 1.0], [-1.0, 1.0]])
integration_domain = torch.tensor([[0.0, 1.0], [-1.0, 1.0]])
dim = 2
N = 9409

Expand Down Expand Up @@ -884,15 +899,15 @@ As an example, here we evaluate a similar integrand many times for different val

a_params = torch.arange(40)
b_params = torch.arange(10, 20)
integration_domain = torch.Tensor([[0, 1]])
integration_domain = torch.tensor([[0.0, 1.0]])
simp = Simpson()
result = torch.stack([torch.Tensor([simp.integrate(lambda x: parametrized_integrand(x, a, b), dim=1, N=101, integration_domain=integration_domain) for a in a_params]) for b in b_params])
result = torch.stack([torch.stack([simp.integrate(lambda x: parametrized_integrand(x, a, b), dim=1, N=101, integration_domain=integration_domain) for a in a_params]) for b in b_params])

Now let's see how to do this a bit more simply, and in a way that provides signficant speedup as the size of the integrand's ``grid`` grows:

.. code:: python

grid = torch.stack([torch.Tensor([a + b for a in a_params]) for b in b_params])
grid = (b_params[:, None] + a_params[None, :]).to(torch.get_default_dtype())

def integrand(x):
return torch.sqrt(torch.cos(torch.sin(torch.einsum("i,jk->ijk", x.flatten(), grid))))
Expand All @@ -904,6 +919,19 @@ Now let's see how to do this a bit more simply, and in a way that provides signf
.. note::
VEGAS does not support multi-dimensional integrands. If you would like this, please consider opening an issue or PR.

.. _tensor_vs_Tensor:

.. note::
Build helper tensors with ``torch.tensor(...)``, not the legacy
``torch.Tensor(...)`` constructor. On a GPU machine
:func:`torchquad.set_up_backend` calls ``torch.set_default_device("cuda")``,
which ``torch.tensor`` honours and ``torch.Tensor`` ignores — the latter
always allocates on the CPU. Mixing the two gives ``RuntimeError: Expected all
tensors to be on the same device`` as soon as the helper meets the sample
points. The same applies to combining per-integration results:
``torch.stack`` keeps them on their original device, while wrapping them in
``torch.Tensor([...])`` moves them to the CPU.

Parametric Integration with Variable Domains
--------------------------------------------

Expand Down
Loading