Skip to content

API Reference

This section documents the public Python API for openseespy-solvers.

The public modules are:

Module Purpose
openseespy_solvers.scipy CPU linear and eigen solver constructors
openseespy_solvers.scipy.precond CPU built-in preconditioners
openseespy_solvers.cupy CUDA linear and eigen solver constructors
openseespy_solvers.cupy.precond CUDA built-in preconditioners
openseespy_solvers.nvmath NVIDIA nvmath.sparse direct solver constructor
openseespy_solvers.hybrid Hybrid direct-factorization/GMRES solver constructor
openseespy_solvers.exceptions Public exception types

Private modules and names beginning with _ are implementation details.

Importing

Use the backend namespace that matches the solver you want:

from openseespy_solvers.scipy import spsolve, eigsh
from openseespy_solvers.scipy import precond

For optional GPU backends:

from openseespy_solvers.cupy import eigsh
from openseespy_solvers.nvmath import direct_solver

All solver constructors return solver objects. Register those objects with OpenSeesPy by passing solver.to_openseespy() to ops.system("PythonSparse", ...) or ops.eigen("PythonSparse", ...).

Linear Solvers

Constructor Backend Purpose
scipy.spsolve scipy.sparse.linalg / SuperLU CPU sparse direct solve
scipy.umfpack scikit-umfpack CPU sparse direct solve using UMFPACK
scipy.cg scipy.sparse.linalg CPU Conjugate Gradient
scipy.gmres scipy.sparse.linalg CPU GMRES
cupy.spsolve cupyx.scipy.sparse.linalg CUDA sparse direct solve
cupy.cg cupyx.scipy.sparse.linalg CUDA Conjugate Gradient
cupy.gmres cupyx.scipy.sparse.linalg CUDA GMRES
nvmath.direct_solver NVIDIA nvmath.sparse CUDA sparse direct solve
hybrid scipy-compatible direct solver + GMRES Reuse a direct factorization as a GMRES preconditioner

Eigen Solvers

Constructor Backend Purpose
scipy.eigsh scipy.sparse.linalg / ARPACK CPU generalized symmetric eigen solve
scipy.lobpcg scipy.sparse.linalg CPU LOBPCG eigen solve
cupy.eigsh cupyx.scipy.sparse.linalg + scipy.sparse.linalg CUDA-assisted generalized symmetric eigen solve
cupy.lobpcg cupyx.scipy.sparse.linalg CUDA LOBPCG eigen solve

Preconditioners

Preconditioner Backend Purpose
scipy.precond.jacobi scipy.sparse Diagonal/Jacobi preconditioner
scipy.precond.ilu scipy.sparse.linalg Incomplete LU preconditioner
scipy.precond.direct scipy.sparse.linalg Direct-solver preconditioner
cupy.precond.jacobi cupyx.scipy.sparse Diagonal/Jacobi preconditioner
cupy.precond.ilu cupyx.scipy.sparse.linalg Incomplete LU preconditioner
cupy.precond.direct cupyx.scipy.sparse.linalg Direct-solver preconditioner

API compatibility with scipy, cupy, and nvmath

If you already use scipy.sparse.linalg or cupyx.scipy.sparse.linalg, the solver constructors in openseespy_solvers.scipy and openseespy_solvers.cupy follow the same names and keyword arguments. The only routine change is that you do not pass A and b (or K and M) — OpenSees assembles those during analysis — and you register the solver with OpenSeesPy instead of calling the solve function yourself.

Direct solve

scipy.sparse.linalg:

import scipy.sparse.linalg as spla

x = spla.spsolve(A, b)

spsolve() in openseespy_solvers.scipy — same solver options, no matrix or RHS at construction:

import openseespy.opensees as ops
from openseespy_solvers.scipy import spsolve

solver = spsolve()  # e.g. permc_spec=... like splu
ops.system("PythonSparse", solver.to_openseespy())
ops.analyze(num_steps)

Iterative solve

scipy.sparse.linalg:

import scipy.sparse.linalg as spla

x, info = spla.cg(A, b, rtol=1e-8, M=M, maxiter=1000)

cg() in openseespy_solvers.scipy — same rtol, atol, maxiter, M, and related keywords:

import openseespy.opensees as ops
from openseespy_solvers.scipy import cg, precond

solver = cg(rtol=1e-8, M=precond.jacobi, maxiter=1000)
ops.system("PythonSparse", solver.to_openseespy())
ops.analyze(num_steps)

openseespy_solvers.cupy mirrors the same pattern (spsolve(), cg(), …) for GPU backends.

nvmath direct solve

nvmath.sparse.advanced.DirectSolver takes the sparse matrix a, dense RHS b, and optional options, execution, and stream keyword arguments:

import nvmath

solver = nvmath.sparse.advanced.DirectSolver(a, b, execution=execution)
with solver:
    solver.plan()
    solver.factorize()
    x = solver.solve()

direct_solver() in openseespy_solvers.nvmath — pass the nvmath keywords you need at construction; OpenSees supplies a and b on each solve and runs the plan / factorize / solve workflow for you:

import openseespy.opensees as ops
from openseespy_solvers.nvmath import direct_solver

solver = direct_solver(execution=execution, plan_algorithm=plan_algorithm)
ops.system("PythonSparse", solver.to_openseespy())
ops.analyze(num_steps)

direct_solver() exposes execution=, multithreading_lib=, and plan_algorithm=; stream and other DirectSolverOptions fields are not. See nvmath for details.

See Solver objects and PythonSparse interface for lifecycle details.