Verify Install¶
A self-contained smoke test that confirms TensorMesh, torch-sla, and
your PyTorch build are wired up correctly. The script:
prints the core versions (TensorMesh, PyTorch, torch-sla, CUDA),
solves a tiny Poisson problem on the CPU (always),
repeats the solve on the GPU if CUDA is available, and
reports the
torch-slasparse-solver backends available on your machine.
The checker ships with the package, so after installing just run
python -m tensormesh.verify_install — there is no file to save. Total
runtime is a couple of seconds; the full source is reproduced below for
reference.
The script¶
"""Verify a TensorMesh install: print the core versions, solve a tiny
Poisson problem on CPU (and on GPU if available), and report the
torch-sla sparse-solver backends available on this machine."""
import math
import time
import torch
import torch_sla
import tensormesh
def solve_poisson(device):
from tensormesh import ElementAssembler, NodeAssembler, Mesh, Condenser
mesh = Mesh.gen_rectangle(chara_length=0.1).to(device)
class Laplace(ElementAssembler):
def forward(self, gradu, gradv):
return gradu @ gradv
class Source(NodeAssembler):
def forward(self, v, f):
return f * v
x, y = mesh.points[:, 0], mesh.points[:, 1]
f_vals = 2 * math.pi**2 * torch.sin(math.pi * x) * torch.sin(math.pi * y)
K = Laplace.from_mesh(mesh)()
b = Source.from_mesh(mesh)(point_data={"f": f_vals})
cond = Condenser(mesh.boundary_mask)
K_, b_ = cond(K, b)
u = cond.recover(K_.solve(b_))
u_exact = torch.sin(math.pi * x) * torch.sin(math.pi * y)
return float((u - u_exact).norm() / u_exact.norm())
def main():
print("TensorMesh smoke test")
print("=" * 40)
print(f"tensormesh : {tensormesh.__version__}")
print(f"torch : {torch.__version__}")
print(f"torch-sla : {torch_sla.__version__}")
print(f"cuda : {torch.version.cuda or 'not available'}")
print()
t0 = time.perf_counter()
err = solve_poisson("cpu")
print(f"[CPU ] Poisson 2D ... OK L2 error = {err:.3e} {time.perf_counter() - t0:.2f} s")
if torch.cuda.is_available():
t0 = time.perf_counter()
err = solve_poisson("cuda")
print(f"[CUDA] Poisson 2D ... OK L2 error = {err:.3e} {time.perf_counter() - t0:.2f} s")
else:
print("[CUDA] not available, skipping GPU test")
print()
# Every sparse-solver backend is provided by torch-sla; let it report them.
torch_sla.show_backends()
print()
print("All required checks passed.")
if __name__ == "__main__":
main()
Expected output¶
On a CUDA machine (a Linux box with an NVIDIA GPU and a CUDA-enabled PyTorch build), you should see something close to:
TensorMesh smoke test
========================================
tensormesh : 0.1.0
torch : 2.10.0+cu128
torch-sla : 0.2.1
cuda : 12.8
[CPU ] Poisson 2D ... OK L2 error = 1.185e-02 0.05 s
[CUDA] Poisson 2D ... OK L2 error = 1.185e-02 0.88 s
torch-sla backend status (CUDA: available)
scipy [CPU] available
eigen [CPU] not available — JIT-compiled C++ extension (requires a C++ compiler)
pytorch [CPU/CUDA] available
cupy [CUDA] available
cudss [CUDA] available
All required checks passed.
On a CPU-only machine (e.g. a macOS / Linux laptop) the cuda line
reads not available, the [CUDA] solve is skipped, and the
backend-table header reads (CUDA: not available) with cupy /
cudss listed as optional extras to install.
The exact L2 error depends on the mesh, but should be on the order of \(10^{-2}\) — anything more than a few percent indicates a numerical problem.
Note
Why is the GPU run sometimes *slower* than the CPU run?
The smoke-test mesh is intentionally tiny (\(\sim\) 100 DOFs). At
this scale, the CUDA solve is dominated by one-time overheads —
context creation, JIT kernel compilation, host↔device transfers, and
cuSPARSE/cuSOLVER workspace allocation — rather than by
actual floating-point work. The first GPU call also pays for CUDA
driver initialization. Run a real-sized problem
(\(\geq 10^4\)–\(10^5\) DOFs) to see the GPU pull ahead;
see Performance for benchmarks.
Note
Which solver does ``A.solve(b)`` actually use by default?
SparseMatrix.solve is inherited from torch_sla.SparseTensor
and called with backend="auto", method="auto". torch-sla’s
auto-selector then picks, based on device and problem size:
CPU → SciPy / SuperLU (
backend="scipy",method="lu") — a direct factorization, fast and machine-precision for the sizes reachable on CPU.CUDA, DOF < 2M → cuDSS if available (
method="cholesky"when SPD, elseldlt/lu); falls back to CuPy, and finally to the PyTorch-native iterative CG.CUDA, DOF ≥ 2M → PyTorch-native iterative solver (
backend="pytorch",method="cg"for SPD orbicgstabotherwise) with Jacobi preconditioning, to stay within GPU memory.
So the smoke test above runs SuperLU on CPU and cuDSS Cholesky
on GPU (Poisson is SPD), not an iterative solver. To pick a
different solver explicitly, pass backend=... / method=...
to solve — see Sparse Solvers.
Every sparse-solver backend is provided by torch-sla — TensorMesh
adds none of its own. Backends reported as not available are not a
failure; they are optional torch-sla extras you can install when you
need them:
scipy
[CPU]— SciPy / SuperLU direct and iterative solvers; the default CPU path, always available.pytorch
[CPU/CUDA]— torch-native iterative solvers (CG / BiCGSTAB), always available and fully autograd-friendly.eigen
[CPU]— a JIT-compiled C++ direct solver; needs a C++ compiler on the machine.cupy
[CUDA]/ cudss[CUDA]— GPU sparse-direct solvers (pip install torch-sla[cupy]/pip install torch-sla[cudss]).
Run torch_sla.show_backends() at any time to re-check status. See
Sparse Solvers for guidance on choosing among them.
Troubleshooting¶
``ModuleNotFoundError: No module named ‘tensormesh’`` — the package isn’t installed in the active Python environment. Re-check Installation.
``ModuleNotFoundError: No module named ‘torch_sla’`` — install it
with pip install "torch-sla>=0.2.1". torch-sla is a hard,
import-time dependency: tensormesh.sparse refuses to import
without it, and every sparse-solver backend is provided through it.
Stuck on ``[CPU ] Poisson 2D`` — your PyTorch build may be downloading
gmsh cache files on first use; subsequent runs are instant.
``L2 error`` ≫ ``1e-2`` — likely an issue with the mesh or PyTorch build. Open an issue at github.com/camlab-ethz/TensorMesh/issues with the full output of this script.