Metadata-Version: 2.4
Name: openseespy-solvers
Version: 0.1.1
Summary: SciPy-style PythonSparse solvers for OpenSeesPy
Project-URL: Documentation, https://openseespy-solvers.readthedocs.io/
Project-URL: Homepage, https://github.com/gaaraujo/openseespy-solvers
Project-URL: Issues, https://github.com/gaaraujo/openseespy-solvers/issues
Project-URL: Source, https://github.com/gaaraujo/openseespy-solvers
Author: openseespy-solvers contributors
License: BSD 3-Clause License
        
        Copyright (c) 2026, openseespy-solvers contributors
        All rights reserved.
        
        Redistribution and use in source and binary forms, with or without
        modification, are permitted provided that the following conditions are met:
        
        1. Redistributions of source code must retain the above copyright notice, this
           list of conditions and the following disclaimer.
        
        2. Redistributions in binary form must reproduce the above copyright notice,
           this list of conditions and the following disclaimer in the documentation
           and/or other materials provided with the distribution.
        
        3. Neither the name of the copyright holder nor the names of its
           contributors may be used to endorse or promote products derived from
           this software without specific prior written permission.
        
        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
        AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
        FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
        CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
        OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
        OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License-File: LICENSE
Keywords: eigen,finite-element,opensees,openseespy,scipy,solver,sparse
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.12
Requires-Dist: numpy>=1.26
Requires-Dist: scipy>=1.12
Provides-Extra: cuda12
Requires-Dist: cupy-cuda12x>=13.0; extra == 'cuda12'
Requires-Dist: nvmath-python[cu12]>=0.9.0; extra == 'cuda12'
Provides-Extra: cuda13
Requires-Dist: cupy-cuda13x>=13.0; extra == 'cuda13'
Requires-Dist: nvmath-python[cu13]>=0.9.0; extra == 'cuda13'
Provides-Extra: cupy
Requires-Dist: cupy>=13.0; extra == 'cupy'
Provides-Extra: dev
Requires-Dist: build; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.24; extra == 'docs'
Provides-Extra: opensees
Requires-Dist: openseespy; extra == 'opensees'
Provides-Extra: umfpack
Requires-Dist: scikit-umfpack>=0.3.3; extra == 'umfpack'
Description-Content-Type: text/markdown

# openseespy-solvers

SciPy-style sparse linear and eigen solvers for OpenSeesPy
[`PythonSparse`](https://opensees.github.io/OpenSeesDocumentation/user/manual/analysis/system/PythonSparse.html).

`openseespy-solvers` wraps familiar numerical backends such as SciPy, CuPy, and
NVIDIA nvMath as solver objects that OpenSeesPy can call directly. OpenSeesPy
assembles the stiffness, mass, and right-hand-side arrays; the solver object performs
the sparse solve and writes the result back to OpenSeesPy.

Documentation: [openseespy-solvers.readthedocs.io](https://openseespy-solvers.readthedocs.io/)

## Installation

```bash
python -m pip install openseespy-solvers
```

The base install provides NumPy/SciPy CPU solvers. It requires Python 3.12 or newer.

OpenSeesPy is optional so the package can be used and tested without forcing an OpenSees
install. If OpenSeesPy is not already in your environment, install the extra:

```bash
python -m pip install "openseespy-solvers[opensees]"
```

Optional backends:

```bash
# CPU UMFPACK direct solver
python -m pip install "openseespy-solvers[umfpack]"

# NVIDIA GPU backends: choose the CUDA generation reported by nvidia-smi
python -m pip install "openseespy-solvers[cuda13]"   # or [cuda12]
```

On Windows, install UMFPACK with conda-forge instead of pip:

```bash
conda install -c conda-forge scikit-umfpack
```

See the [installation guide](https://openseespy-solvers.readthedocs.io/en/latest/installation/)
for platform notes, CUDA 12.x alternatives, and verification steps.

## Quick Example

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

solver = spsolve()

# after defining the OpenSeesPy model:
ops.system("PythonSparse", solver.to_openseespy())
ops.numberer("RCM")
ops.constraints("Plain")
ops.integrator("LoadControl", 1.0)
ops.algorithm("Linear")
ops.analysis("Static")
ops.analyze(1)
```

For eigen analysis:

```python
from openseespy_solvers.scipy import eigsh

eigsolver = eigsh(tol=1e-8)
eigenvalues = ops.eigen("PythonSparse", 5, eigsolver.to_openseespy())
```

## Recommended Solvers

These are good first choices for typical OpenSeesPy analyses:

| Analysis | CPU | NVIDIA GPU |
|----------|-----|-------------|
| Static or transient linear solve | `scipy.spsolve`; `scipy.umfpack` for larger CPU systems | `nvmath.direct_solver` |
| Generalized eigen solve | `scipy.eigsh` | `cupy.eigsh` |

Iterative solvers (`cg`, `gmres`, `lobpcg`) and preconditioners are also available when a
direct factorization is too expensive or a model benefits from a custom strategy.

More detail: [Recommended solvers](https://openseespy-solvers.readthedocs.io/en/latest/recommended-solvers/).

## Modules

| Module | Provides |
|--------|----------|
| `openseespy_solvers.scipy` | CPU solvers: `spsolve`, `umfpack`, `cg`, `gmres`, `eigsh`, `lobpcg` |
| `openseespy_solvers.scipy.precond` | CPU preconditioners: `jacobi`, `ilu`, `direct` |
| `openseespy_solvers.cupy` | GPU solvers: `spsolve`, `cg`, `gmres`, `eigsh`, `lobpcg` |
| `openseespy_solvers.cupy.precond` | GPU preconditioners: `jacobi`, `ilu`, `direct` |
| `openseespy_solvers.nvmath` | GPU direct sparse solver: `direct_solver` |
| `openseespy_solvers.hybrid` | Direct factorization reused as a GMRES preconditioner |

Factory signatures follow the corresponding SciPy/CuPy functions where possible. The
matrix and right-hand side are supplied by OpenSeesPy at solve time.

## Examples and Development

The pip wheel contains the library. Examples, benchmarks, and tests live in the source
repository:

```bash
git clone https://github.com/gaaraujo/openseespy-solvers.git
cd openseespy-solvers
python -m pip install -e ".[dev,opensees]"
pytest
```

Then run a smoke example:

```bash
cd examples
python solvers/scipy_spsolve.py
python solvers/scipy_eigsh.py
```

## Project Links

- Documentation: [openseespy-solvers.readthedocs.io](https://openseespy-solvers.readthedocs.io/)
- Source: [github.com/gaaraujo/openseespy-solvers](https://github.com/gaaraujo/openseespy-solvers)
- Issues: [github.com/gaaraujo/openseespy-solvers/issues](https://github.com/gaaraujo/openseespy-solvers/issues)

## License

BSD 3-Clause. See [LICENSE](LICENSE).
