pymatsolver 0.2.0__tar.gz → 0.3.0__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.
- pymatsolver-0.3.0/PKG-INFO +139 -0
- pymatsolver-0.3.0/README.rst +76 -0
- pymatsolver-0.3.0/pymatsolver/__init__.py +117 -0
- pymatsolver-0.3.0/pymatsolver/direct/__init__.py +10 -0
- pymatsolver-0.3.0/pymatsolver/direct/mumps.py +122 -0
- pymatsolver-0.3.0/pymatsolver/direct/pardiso.py +138 -0
- pymatsolver-0.3.0/pymatsolver/iterative.py +127 -0
- pymatsolver-0.3.0/pymatsolver/solvers.py +605 -0
- pymatsolver-0.3.0/pymatsolver/wrappers.py +260 -0
- pymatsolver-0.3.0/pymatsolver.egg-info/PKG-INFO +139 -0
- {pymatsolver-0.2.0 → pymatsolver-0.3.0}/pymatsolver.egg-info/SOURCES.txt +4 -9
- pymatsolver-0.3.0/pymatsolver.egg-info/requires.txt +21 -0
- {pymatsolver-0.2.0 → pymatsolver-0.3.0}/pymatsolver.egg-info/top_level.txt +0 -1
- pymatsolver-0.3.0/pyproject.toml +97 -0
- pymatsolver-0.2.0/PKG-INFO +0 -138
- pymatsolver-0.2.0/README.rst +0 -106
- pymatsolver-0.2.0/pymatsolver/__init__.py +0 -103
- pymatsolver-0.2.0/pymatsolver/direct.py +0 -95
- pymatsolver-0.2.0/pymatsolver/iterative.py +0 -52
- pymatsolver-0.2.0/pymatsolver/solvers.py +0 -205
- pymatsolver-0.2.0/pymatsolver/wrappers.py +0 -118
- pymatsolver-0.2.0/pymatsolver.egg-info/PKG-INFO +0 -138
- pymatsolver-0.2.0/pymatsolver.egg-info/requires.txt +0 -2
- pymatsolver-0.2.0/setup.py +0 -49
- pymatsolver-0.2.0/tests/__init__.py +0 -11
- pymatsolver-0.2.0/tests/test_Basic.py +0 -30
- pymatsolver-0.2.0/tests/test_BicgJacobi.py +0 -90
- pymatsolver-0.2.0/tests/test_Mumps.py +0 -86
- pymatsolver-0.2.0/tests/test_Pardiso.py +0 -180
- pymatsolver-0.2.0/tests/test_Scipy.py +0 -87
- pymatsolver-0.2.0/tests/test_Triangle.py +0 -34
- {pymatsolver-0.2.0 → pymatsolver-0.3.0}/LICENSE +0 -0
- {pymatsolver-0.2.0 → pymatsolver-0.3.0}/pymatsolver.egg-info/dependency_links.txt +0 -0
- {pymatsolver-0.2.0 → pymatsolver-0.3.0}/setup.cfg +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pymatsolver
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: pymatsolver: Matrix Solvers for Python
|
|
5
|
+
Author-email: SimPEG developers <rowanc1@gmail.com>
|
|
6
|
+
License: The MIT License (MIT)
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2013-2016 Rowan Cockett
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
11
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
12
|
+
the Software without restriction, including without limitation the rights to
|
|
13
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
14
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
15
|
+
subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
22
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
23
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
24
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
25
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
26
|
+
|
|
27
|
+
Project-URL: Homepage, https://simpeg.xyz
|
|
28
|
+
Project-URL: Documentation, https://simpeg.xyz/pymatsolver/
|
|
29
|
+
Project-URL: Repository, https://github.com/simpeg/pymatsolver
|
|
30
|
+
Keywords: matrix solver
|
|
31
|
+
Classifier: Development Status :: 4 - Beta
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: Intended Audience :: Science/Research
|
|
34
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
35
|
+
Classifier: Programming Language :: Python
|
|
36
|
+
Classifier: Topic :: Scientific/Engineering
|
|
37
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
38
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
39
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
40
|
+
Classifier: Operating System :: POSIX
|
|
41
|
+
Classifier: Operating System :: Unix
|
|
42
|
+
Classifier: Operating System :: MacOS
|
|
43
|
+
Classifier: Natural Language :: English
|
|
44
|
+
Requires-Python: >=3.10
|
|
45
|
+
Description-Content-Type: text/x-rst
|
|
46
|
+
License-File: LICENSE
|
|
47
|
+
Requires-Dist: numpy>=1.21
|
|
48
|
+
Requires-Dist: scipy>=1.8
|
|
49
|
+
Provides-Extra: pardiso
|
|
50
|
+
Requires-Dist: pydiso; extra == "pardiso"
|
|
51
|
+
Provides-Extra: mumps
|
|
52
|
+
Requires-Dist: python-mumps; extra == "mumps"
|
|
53
|
+
Provides-Extra: docs
|
|
54
|
+
Requires-Dist: sphinx; extra == "docs"
|
|
55
|
+
Requires-Dist: numpydoc; extra == "docs"
|
|
56
|
+
Requires-Dist: pydata-sphinx-theme; extra == "docs"
|
|
57
|
+
Provides-Extra: tests
|
|
58
|
+
Requires-Dist: pytest; extra == "tests"
|
|
59
|
+
Requires-Dist: pytest-cov; extra == "tests"
|
|
60
|
+
Provides-Extra: build
|
|
61
|
+
Requires-Dist: setuptools_scm>=8; extra == "build"
|
|
62
|
+
Requires-Dist: setuptools>=64; extra == "build"
|
|
63
|
+
|
|
64
|
+
pymatsolver
|
|
65
|
+
***********
|
|
66
|
+
|
|
67
|
+
.. image:: https://img.shields.io/pypi/v/pymatsolver.svg
|
|
68
|
+
:target: https://pypi.python.org/pypi/pymatsolver
|
|
69
|
+
:alt: Latest PyPI version
|
|
70
|
+
|
|
71
|
+
.. image:: https://img.shields.io/badge/license-MIT-blue.svg
|
|
72
|
+
:target: https://github.com/simpeg/pymatsolver/blob/master/LICENSE
|
|
73
|
+
:alt: MIT license.
|
|
74
|
+
|
|
75
|
+
.. image:: https://codecov.io/gh/simpeg/pymatsolver/branch/main/graph/badge.svg?token=8uQoxzxf3r
|
|
76
|
+
:target: https://codecov.io/gh/simpeg/pymatsolver
|
|
77
|
+
:alt: Coverage status
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
A (sparse) matrix solver for python.
|
|
81
|
+
|
|
82
|
+
Solving Ax = b should be as easy as:
|
|
83
|
+
|
|
84
|
+
.. code-block:: python
|
|
85
|
+
|
|
86
|
+
Ainv = Solver(A)
|
|
87
|
+
x = Ainv * b
|
|
88
|
+
|
|
89
|
+
In pymatsolver we provide a number of wrappers to existing numerical packages. Nothing fancy here.
|
|
90
|
+
|
|
91
|
+
Solvers Available
|
|
92
|
+
=================
|
|
93
|
+
|
|
94
|
+
All solvers work with :code:`scipy.sparse` matricies, and a single or multiple right hand sides using :code:`numpy`:
|
|
95
|
+
|
|
96
|
+
* L/U Triangular Solves
|
|
97
|
+
* Wrapping of SciPy matrix solvers (direct and indirect)
|
|
98
|
+
* Pardiso solvers
|
|
99
|
+
* Mumps solvers
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
Installing Solvers
|
|
103
|
+
==================
|
|
104
|
+
Often, there are faster solvers available for your system than the default scipy factorizations available.
|
|
105
|
+
pymatsolver provides a consistent interface to both MKL's ``Pardiso`` routines and the ``MUMPS`` solver package. To
|
|
106
|
+
make use of these we use intermediate wrappers for the libraries that must be installed separately.
|
|
107
|
+
|
|
108
|
+
Pardiso
|
|
109
|
+
-------
|
|
110
|
+
The Pardiso interface is recommended for Intel processor based systems. The interface is enabled by
|
|
111
|
+
the ``pydiso`` python package, which can be installed through conda-forge as:
|
|
112
|
+
|
|
113
|
+
.. code::
|
|
114
|
+
|
|
115
|
+
conda install -c conda-forge pydiso
|
|
116
|
+
|
|
117
|
+
Mumps
|
|
118
|
+
-----
|
|
119
|
+
Mumps is available for all platforms. The mumps interface is enabled by installing the ``python-mumps``
|
|
120
|
+
wrapper package. This can easily be installed through conda-forge with:
|
|
121
|
+
|
|
122
|
+
.. code::
|
|
123
|
+
|
|
124
|
+
conda install -c conda-forge python-mumps
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
Code:
|
|
129
|
+
https://github.com/simpeg/pymatsolver
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
Tests:
|
|
133
|
+
https://github.com/simpeg/pymatsolver/actions
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
Bugs & Issues:
|
|
137
|
+
https://github.com/simpeg/pymatsolver/issues
|
|
138
|
+
|
|
139
|
+
License: MIT
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
pymatsolver
|
|
2
|
+
***********
|
|
3
|
+
|
|
4
|
+
.. image:: https://img.shields.io/pypi/v/pymatsolver.svg
|
|
5
|
+
:target: https://pypi.python.org/pypi/pymatsolver
|
|
6
|
+
:alt: Latest PyPI version
|
|
7
|
+
|
|
8
|
+
.. image:: https://img.shields.io/badge/license-MIT-blue.svg
|
|
9
|
+
:target: https://github.com/simpeg/pymatsolver/blob/master/LICENSE
|
|
10
|
+
:alt: MIT license.
|
|
11
|
+
|
|
12
|
+
.. image:: https://codecov.io/gh/simpeg/pymatsolver/branch/main/graph/badge.svg?token=8uQoxzxf3r
|
|
13
|
+
:target: https://codecov.io/gh/simpeg/pymatsolver
|
|
14
|
+
:alt: Coverage status
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
A (sparse) matrix solver for python.
|
|
18
|
+
|
|
19
|
+
Solving Ax = b should be as easy as:
|
|
20
|
+
|
|
21
|
+
.. code-block:: python
|
|
22
|
+
|
|
23
|
+
Ainv = Solver(A)
|
|
24
|
+
x = Ainv * b
|
|
25
|
+
|
|
26
|
+
In pymatsolver we provide a number of wrappers to existing numerical packages. Nothing fancy here.
|
|
27
|
+
|
|
28
|
+
Solvers Available
|
|
29
|
+
=================
|
|
30
|
+
|
|
31
|
+
All solvers work with :code:`scipy.sparse` matricies, and a single or multiple right hand sides using :code:`numpy`:
|
|
32
|
+
|
|
33
|
+
* L/U Triangular Solves
|
|
34
|
+
* Wrapping of SciPy matrix solvers (direct and indirect)
|
|
35
|
+
* Pardiso solvers
|
|
36
|
+
* Mumps solvers
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
Installing Solvers
|
|
40
|
+
==================
|
|
41
|
+
Often, there are faster solvers available for your system than the default scipy factorizations available.
|
|
42
|
+
pymatsolver provides a consistent interface to both MKL's ``Pardiso`` routines and the ``MUMPS`` solver package. To
|
|
43
|
+
make use of these we use intermediate wrappers for the libraries that must be installed separately.
|
|
44
|
+
|
|
45
|
+
Pardiso
|
|
46
|
+
-------
|
|
47
|
+
The Pardiso interface is recommended for Intel processor based systems. The interface is enabled by
|
|
48
|
+
the ``pydiso`` python package, which can be installed through conda-forge as:
|
|
49
|
+
|
|
50
|
+
.. code::
|
|
51
|
+
|
|
52
|
+
conda install -c conda-forge pydiso
|
|
53
|
+
|
|
54
|
+
Mumps
|
|
55
|
+
-----
|
|
56
|
+
Mumps is available for all platforms. The mumps interface is enabled by installing the ``python-mumps``
|
|
57
|
+
wrapper package. This can easily be installed through conda-forge with:
|
|
58
|
+
|
|
59
|
+
.. code::
|
|
60
|
+
|
|
61
|
+
conda install -c conda-forge python-mumps
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
Code:
|
|
66
|
+
https://github.com/simpeg/pymatsolver
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
Tests:
|
|
70
|
+
https://github.com/simpeg/pymatsolver/actions
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
Bugs & Issues:
|
|
74
|
+
https://github.com/simpeg/pymatsolver/issues
|
|
75
|
+
|
|
76
|
+
License: MIT
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""
|
|
2
|
+
===
|
|
3
|
+
API
|
|
4
|
+
===
|
|
5
|
+
.. currentmodule:: pymatsolver
|
|
6
|
+
|
|
7
|
+
.. autosummary::
|
|
8
|
+
:toctree: generated/
|
|
9
|
+
|
|
10
|
+
solvers.Base
|
|
11
|
+
|
|
12
|
+
Basic Solvers
|
|
13
|
+
=============
|
|
14
|
+
|
|
15
|
+
Diagonal
|
|
16
|
+
--------
|
|
17
|
+
.. autosummary::
|
|
18
|
+
:toctree: generated/
|
|
19
|
+
|
|
20
|
+
Diagonal
|
|
21
|
+
|
|
22
|
+
Triangular
|
|
23
|
+
----------
|
|
24
|
+
.. autosummary::
|
|
25
|
+
:toctree: generated/
|
|
26
|
+
|
|
27
|
+
Triangle
|
|
28
|
+
Forward
|
|
29
|
+
Backward
|
|
30
|
+
|
|
31
|
+
Iterative Solvers
|
|
32
|
+
=================
|
|
33
|
+
|
|
34
|
+
.. autosummary::
|
|
35
|
+
:toctree: generated/
|
|
36
|
+
|
|
37
|
+
SolverCG
|
|
38
|
+
BiCGJacobi
|
|
39
|
+
|
|
40
|
+
Direct Solvers
|
|
41
|
+
==============
|
|
42
|
+
|
|
43
|
+
.. autosummary::
|
|
44
|
+
:toctree: generated/
|
|
45
|
+
|
|
46
|
+
Solver
|
|
47
|
+
SolverLU
|
|
48
|
+
Pardiso
|
|
49
|
+
Mumps
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
# Simple solvers
|
|
53
|
+
from .solvers import Diagonal, Triangle, Forward, Backward
|
|
54
|
+
from .wrappers import wrap_direct, WrapDirect
|
|
55
|
+
from .wrappers import wrap_iterative, WrapIterative
|
|
56
|
+
|
|
57
|
+
# Scipy Iterative solvers
|
|
58
|
+
from .iterative import SolverCG
|
|
59
|
+
from .iterative import SolverBiCG
|
|
60
|
+
from .iterative import BiCGJacobi
|
|
61
|
+
|
|
62
|
+
# Scipy direct solvers
|
|
63
|
+
from .direct import Solver, pardiso
|
|
64
|
+
from .direct import SolverLU
|
|
65
|
+
|
|
66
|
+
from .solvers import SolverAccuracyError
|
|
67
|
+
from .direct import Pardiso, Mumps
|
|
68
|
+
from .direct.pardiso import _available as _pardiso_available
|
|
69
|
+
from .direct.mumps import _available as _mumps_available
|
|
70
|
+
|
|
71
|
+
SolverHelp = {}
|
|
72
|
+
AvailableSolvers = {
|
|
73
|
+
"Diagonal": True,
|
|
74
|
+
"Solver": True,
|
|
75
|
+
"SolverLU": True,
|
|
76
|
+
"SolverCG": True,
|
|
77
|
+
"Triangle": True,
|
|
78
|
+
"Pardiso": _pardiso_available,
|
|
79
|
+
"Mumps": _mumps_available,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
BicgJacobi = BiCGJacobi # backwards compatibility
|
|
83
|
+
PardisoSolver = Pardiso # backwards compatibility
|
|
84
|
+
|
|
85
|
+
if not AvailableSolvers["Pardiso"]:
|
|
86
|
+
SolverHelp['Pardiso'] = """Pardiso is not working
|
|
87
|
+
|
|
88
|
+
Ensure that you have pydiso installed, which may also require Python
|
|
89
|
+
to be installed through conda.
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
if not AvailableSolvers["Mumps"]:
|
|
93
|
+
SolverHelp['Mumps'] = """Mumps is not working.
|
|
94
|
+
|
|
95
|
+
Ensure that you have python-mumps installed, which may also require Python
|
|
96
|
+
to be installed through conda.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
__author__ = 'SimPEG Team'
|
|
100
|
+
__license__ = 'MIT'
|
|
101
|
+
__copyright__ = '2013 - 2024, SimPEG Team, https://simpeg.xyz'
|
|
102
|
+
|
|
103
|
+
from importlib.metadata import version, PackageNotFoundError
|
|
104
|
+
|
|
105
|
+
# Version
|
|
106
|
+
try:
|
|
107
|
+
# - Released versions just tags: 0.8.0
|
|
108
|
+
# - GitHub commits add .dev#+hash: 0.8.1.dev4+g2785721
|
|
109
|
+
# - Uncommitted changes add timestamp: 0.8.1.dev4+g2785721.d20191022
|
|
110
|
+
__version__ = version("pymatsolver")
|
|
111
|
+
except PackageNotFoundError:
|
|
112
|
+
# If it was not installed, then we don't know the version. We could throw a
|
|
113
|
+
# warning here, but this case *should* be rare. discretize should be
|
|
114
|
+
# installed properly!
|
|
115
|
+
from datetime import datetime
|
|
116
|
+
|
|
117
|
+
__version__ = "unknown-" + datetime.today().strftime("%Y%m%d")
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from scipy.sparse.linalg import spsolve, splu
|
|
2
|
+
|
|
3
|
+
from ..wrappers import WrapDirect
|
|
4
|
+
from .pardiso import Pardiso
|
|
5
|
+
from .mumps import Mumps
|
|
6
|
+
|
|
7
|
+
Solver = WrapDirect(spsolve, factorize=False, name="Solver")
|
|
8
|
+
SolverLU = WrapDirect(splu, factorize=True, name="SolverLU")
|
|
9
|
+
|
|
10
|
+
__all__ = ["Solver", "SolverLU", "Pardiso", "Mumps"]
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
from pymatsolver.solvers import Base
|
|
2
|
+
try:
|
|
3
|
+
from mumps import Context
|
|
4
|
+
_available = True
|
|
5
|
+
except ImportError:
|
|
6
|
+
Context = None
|
|
7
|
+
_available = False
|
|
8
|
+
|
|
9
|
+
class Mumps(Base):
|
|
10
|
+
"""The MUMPS direct solver.
|
|
11
|
+
|
|
12
|
+
This solver uses the python-mumps wrappers to factorize a sparse matrix, and use that factorization for solving.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
A
|
|
17
|
+
Matrix to solve with.
|
|
18
|
+
ordering : str, default 'metis'
|
|
19
|
+
Which ordering algorithm to use. See the `python-mumps` documentation for more details.
|
|
20
|
+
is_symmetric : bool, optional
|
|
21
|
+
Whether the matrix is symmetric. By default, it will perform some simple tests to check for symmetry, and
|
|
22
|
+
default to ``False`` if those fail.
|
|
23
|
+
is_positive_definite : bool, optional
|
|
24
|
+
Whether the matrix is positive definite.
|
|
25
|
+
check_accuracy : bool, optional
|
|
26
|
+
Whether to check the accuracy of the solution.
|
|
27
|
+
check_rtol : float, optional
|
|
28
|
+
The relative tolerance to check against for accuracy.
|
|
29
|
+
check_atol : float, optional
|
|
30
|
+
The absolute tolerance to check against for accuracy.
|
|
31
|
+
accuracy_tol : float, optional
|
|
32
|
+
Relative accuracy tolerance.
|
|
33
|
+
.. deprecated:: 0.3.0
|
|
34
|
+
`accuracy_tol` will be removed in pymatsolver 0.4.0. Use `check_rtol` and `check_atol` instead.
|
|
35
|
+
**kwargs
|
|
36
|
+
Extra keyword arguments. If there are any left here a warning will be raised.
|
|
37
|
+
"""
|
|
38
|
+
_transposed = False
|
|
39
|
+
|
|
40
|
+
def __init__(self, A, ordering=None, is_symmetric=None, is_positive_definite=False, check_accuracy=False, check_rtol=1e-6, check_atol=0, accuracy_tol=None, **kwargs):
|
|
41
|
+
if not _available:
|
|
42
|
+
raise ImportError(
|
|
43
|
+
"The Mumps solver requires the python-mumps package to be installed."
|
|
44
|
+
)
|
|
45
|
+
is_hermitian = kwargs.pop('is_hermitian', False)
|
|
46
|
+
super().__init__(A, is_symmetric=is_symmetric, is_positive_definite=is_positive_definite, is_hermitian=is_hermitian, check_accuracy=check_accuracy, check_rtol=check_rtol, check_atol=check_atol, accuracy_tol=accuracy_tol, **kwargs)
|
|
47
|
+
if ordering is None:
|
|
48
|
+
ordering = "metis"
|
|
49
|
+
self.ordering = ordering
|
|
50
|
+
self.solver = Context()
|
|
51
|
+
self._set_A(self.A)
|
|
52
|
+
|
|
53
|
+
def _set_A(self, A):
|
|
54
|
+
self.solver.set_matrix(
|
|
55
|
+
A,
|
|
56
|
+
symmetric=self.is_symmetric,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def ordering(self):
|
|
61
|
+
"""The ordering algorithm to use.
|
|
62
|
+
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
65
|
+
str
|
|
66
|
+
"""
|
|
67
|
+
return self._ordering
|
|
68
|
+
|
|
69
|
+
@ordering.setter
|
|
70
|
+
def ordering(self, value):
|
|
71
|
+
self._ordering = str(value)
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def _factored(self):
|
|
75
|
+
return self.solver.factored
|
|
76
|
+
|
|
77
|
+
def get_attributes(self):
|
|
78
|
+
attrs = super().get_attributes()
|
|
79
|
+
attrs['ordering'] = self.ordering
|
|
80
|
+
return attrs
|
|
81
|
+
|
|
82
|
+
def transpose(self):
|
|
83
|
+
trans_obj = Mumps.__new__(Mumps)
|
|
84
|
+
trans_obj._A = self.A
|
|
85
|
+
for attr, value in self.get_attributes().items():
|
|
86
|
+
setattr(trans_obj, attr, value)
|
|
87
|
+
trans_obj.solver = self.solver
|
|
88
|
+
trans_obj._transposed = not self._transposed
|
|
89
|
+
return trans_obj
|
|
90
|
+
|
|
91
|
+
def factor(self, A=None):
|
|
92
|
+
"""(Re)factor the A matrix.
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
A : scipy.sparse.spmatrix
|
|
97
|
+
The matrix to be factorized. If a previous factorization has been performed, this will
|
|
98
|
+
reuse the previous factorization's analysis.
|
|
99
|
+
"""
|
|
100
|
+
reuse_analysis = self._factored
|
|
101
|
+
do_factor = not self._factored
|
|
102
|
+
if A is not None and A is not self.A:
|
|
103
|
+
# if it was previously factored then re-use the analysis.
|
|
104
|
+
self._set_A(A)
|
|
105
|
+
self._A = A
|
|
106
|
+
do_factor = True
|
|
107
|
+
if do_factor:
|
|
108
|
+
pivot_tol = 0.0 if self.is_positive_definite else 0.01
|
|
109
|
+
self.solver.factor(
|
|
110
|
+
ordering=self.ordering, reuse_analysis=reuse_analysis, pivot_tol=pivot_tol
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
def _solve_multiple(self, rhs):
|
|
114
|
+
self.factor()
|
|
115
|
+
if self._transposed:
|
|
116
|
+
self.solver.mumps_instance.icntl[9] = 0
|
|
117
|
+
else:
|
|
118
|
+
self.solver.mumps_instance.icntl[9] = 1
|
|
119
|
+
sol = self.solver.solve(rhs)
|
|
120
|
+
return sol
|
|
121
|
+
|
|
122
|
+
_solve_single = _solve_multiple
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
from pymatsolver.solvers import Base
|
|
2
|
+
try:
|
|
3
|
+
from pydiso.mkl_solver import MKLPardisoSolver
|
|
4
|
+
from pydiso.mkl_solver import set_mkl_pardiso_threads, get_mkl_pardiso_max_threads
|
|
5
|
+
_available = True
|
|
6
|
+
except ImportError:
|
|
7
|
+
_available = False
|
|
8
|
+
|
|
9
|
+
class Pardiso(Base):
|
|
10
|
+
"""The Pardiso direct solver.
|
|
11
|
+
|
|
12
|
+
This solver uses the `pydiso` Intel MKL wrapper to factorize a sparse matrix, and use that
|
|
13
|
+
factorization for solving.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
A : scipy.sparse.spmatrix
|
|
18
|
+
Matrix to solve with.
|
|
19
|
+
n_threads : int, optional
|
|
20
|
+
Number of threads to use for the `Pardiso` routine in Intel's MKL.
|
|
21
|
+
is_symmetric : bool, optional
|
|
22
|
+
Whether the matrix is symmetric. By default, it will perform some simple tests to check for symmetry, and
|
|
23
|
+
default to ``False`` if those fail.
|
|
24
|
+
is_positive_definite : bool, optional
|
|
25
|
+
Whether the matrix is positive definite.
|
|
26
|
+
is_hermitian : bool, optional
|
|
27
|
+
Whether the matrix is hermitian. By default, it will perform some simple tests to check, and default to
|
|
28
|
+
``False`` if those fail.
|
|
29
|
+
check_accuracy : bool, optional
|
|
30
|
+
Whether to check the accuracy of the solution.
|
|
31
|
+
check_rtol : float, optional
|
|
32
|
+
The relative tolerance to check against for accuracy.
|
|
33
|
+
check_atol : float, optional
|
|
34
|
+
The absolute tolerance to check against for accuracy.
|
|
35
|
+
accuracy_tol : float, optional
|
|
36
|
+
Relative accuracy tolerance.
|
|
37
|
+
.. deprecated:: 0.3.0
|
|
38
|
+
`accuracy_tol` will be removed in pymatsolver 0.4.0. Use `check_rtol` and `check_atol` instead.
|
|
39
|
+
**kwargs
|
|
40
|
+
Extra keyword arguments. If there are any left here a warning will be raised.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
_transposed = False
|
|
44
|
+
|
|
45
|
+
def __init__(self, A, n_threads=None, is_symmetric=None, is_positive_definite=False, is_hermitian=None, check_accuracy=False, check_rtol=1e-6, check_atol=0, accuracy_tol=None, **kwargs):
|
|
46
|
+
if not _available:
|
|
47
|
+
raise ImportError("Pardiso solver requires the pydiso package to be installed.")
|
|
48
|
+
super().__init__(A, is_symmetric=is_symmetric, is_positive_definite=is_positive_definite, is_hermitian=is_hermitian, check_accuracy=check_accuracy, check_rtol=check_rtol, check_atol=check_atol, accuracy_tol=accuracy_tol, **kwargs)
|
|
49
|
+
self.solver = MKLPardisoSolver(
|
|
50
|
+
self.A,
|
|
51
|
+
matrix_type=self._matrixType(),
|
|
52
|
+
factor=False
|
|
53
|
+
)
|
|
54
|
+
if n_threads is not None:
|
|
55
|
+
self.n_threads = n_threads
|
|
56
|
+
|
|
57
|
+
def _matrixType(self):
|
|
58
|
+
"""
|
|
59
|
+
Set basic matrix type:
|
|
60
|
+
|
|
61
|
+
Real::
|
|
62
|
+
|
|
63
|
+
1: structurally symmetric
|
|
64
|
+
2: symmetric positive definite
|
|
65
|
+
-2: symmetric indefinite
|
|
66
|
+
11: nonsymmetric
|
|
67
|
+
|
|
68
|
+
Complex::
|
|
69
|
+
|
|
70
|
+
6: symmetric
|
|
71
|
+
4: hermitian positive definite
|
|
72
|
+
-4: hermitian indefinite
|
|
73
|
+
3: structurally symmetric
|
|
74
|
+
13: nonsymmetric
|
|
75
|
+
|
|
76
|
+
"""
|
|
77
|
+
if self.is_real:
|
|
78
|
+
if self.is_symmetric:
|
|
79
|
+
if self.is_positive_definite:
|
|
80
|
+
return 2
|
|
81
|
+
else:
|
|
82
|
+
return -2
|
|
83
|
+
else:
|
|
84
|
+
return 11
|
|
85
|
+
else:
|
|
86
|
+
if self.is_symmetric:
|
|
87
|
+
return 6
|
|
88
|
+
elif self.is_hermitian:
|
|
89
|
+
if self.is_positive_definite:
|
|
90
|
+
return 4
|
|
91
|
+
else:
|
|
92
|
+
return -4
|
|
93
|
+
else:
|
|
94
|
+
return 13
|
|
95
|
+
|
|
96
|
+
def factor(self, A=None):
|
|
97
|
+
"""(Re)factor the A matrix.
|
|
98
|
+
|
|
99
|
+
Parameters
|
|
100
|
+
----------
|
|
101
|
+
A : scipy.sparse.spmatrix
|
|
102
|
+
The matrix to be factorized. If a previous factorization has been performed, this will
|
|
103
|
+
reuse the previous factorization's analysis.
|
|
104
|
+
"""
|
|
105
|
+
if A is not None and self.A is not A:
|
|
106
|
+
self._A = A
|
|
107
|
+
self.solver.refactor(self.A)
|
|
108
|
+
|
|
109
|
+
def _solve_multiple(self, rhs):
|
|
110
|
+
sol = self.solver.solve(rhs, transpose=self._transposed)
|
|
111
|
+
return sol
|
|
112
|
+
|
|
113
|
+
def transpose(self):
|
|
114
|
+
trans_obj = Pardiso.__new__(Pardiso)
|
|
115
|
+
trans_obj._A = self.A
|
|
116
|
+
for attr, value in self.get_attributes().items():
|
|
117
|
+
setattr(trans_obj, attr, value)
|
|
118
|
+
trans_obj.solver = self.solver
|
|
119
|
+
trans_obj._transposed = not self._transposed
|
|
120
|
+
return trans_obj
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def n_threads(self):
|
|
124
|
+
"""Number of threads to use for the Pardiso solver routine.
|
|
125
|
+
|
|
126
|
+
This property is global to all Pardiso solver objects for a single python process.
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
int
|
|
131
|
+
"""
|
|
132
|
+
return get_mkl_pardiso_max_threads()
|
|
133
|
+
|
|
134
|
+
@n_threads.setter
|
|
135
|
+
def n_threads(self, n_threads):
|
|
136
|
+
set_mkl_pardiso_threads(n_threads)
|
|
137
|
+
|
|
138
|
+
_solve_single = _solve_multiple
|