Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/scipy/sparse/linalg/_isolve/utils.py: 14%
56 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-12 06:31 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-12 06:31 +0000
1__docformat__ = "restructuredtext en"
3__all__ = []
6from numpy import asanyarray, asarray, array, zeros
8from scipy.sparse.linalg._interface import aslinearoperator, LinearOperator, \
9 IdentityOperator
11_coerce_rules = {('f','f'):'f', ('f','d'):'d', ('f','F'):'F',
12 ('f','D'):'D', ('d','f'):'d', ('d','d'):'d',
13 ('d','F'):'D', ('d','D'):'D', ('F','f'):'F',
14 ('F','d'):'D', ('F','F'):'F', ('F','D'):'D',
15 ('D','f'):'D', ('D','d'):'D', ('D','F'):'D',
16 ('D','D'):'D'}
19def coerce(x,y):
20 if x not in 'fdFD':
21 x = 'd'
22 if y not in 'fdFD':
23 y = 'd'
24 return _coerce_rules[x,y]
27def id(x):
28 return x
31def make_system(A, M, x0, b):
32 """Make a linear system Ax=b
34 Parameters
35 ----------
36 A : LinearOperator
37 sparse or dense matrix (or any valid input to aslinearoperator)
38 M : {LinearOperator, Nones}
39 preconditioner
40 sparse or dense matrix (or any valid input to aslinearoperator)
41 x0 : {array_like, str, None}
42 initial guess to iterative method.
43 ``x0 = 'Mb'`` means using the nonzero initial guess ``M @ b``.
44 Default is `None`, which means using the zero initial guess.
45 b : array_like
46 right hand side
48 Returns
49 -------
50 (A, M, x, b, postprocess)
51 A : LinearOperator
52 matrix of the linear system
53 M : LinearOperator
54 preconditioner
55 x : rank 1 ndarray
56 initial guess
57 b : rank 1 ndarray
58 right hand side
59 postprocess : function
60 converts the solution vector to the appropriate
61 type and dimensions (e.g. (N,1) matrix)
63 """
64 A_ = A
65 A = aslinearoperator(A)
67 if A.shape[0] != A.shape[1]:
68 raise ValueError(f'expected square matrix, but got shape={(A.shape,)}')
70 N = A.shape[0]
72 b = asanyarray(b)
74 if not (b.shape == (N,1) or b.shape == (N,)):
75 raise ValueError(f'shapes of A {A.shape} and b {b.shape} are '
76 'incompatible')
78 if b.dtype.char not in 'fdFD':
79 b = b.astype('d') # upcast non-FP types to double
81 def postprocess(x):
82 return x
84 if hasattr(A,'dtype'):
85 xtype = A.dtype.char
86 else:
87 xtype = A.matvec(b).dtype.char
88 xtype = coerce(xtype, b.dtype.char)
90 b = asarray(b,dtype=xtype) # make b the same type as x
91 b = b.ravel()
93 # process preconditioner
94 if M is None:
95 if hasattr(A_,'psolve'):
96 psolve = A_.psolve
97 else:
98 psolve = id
99 if hasattr(A_,'rpsolve'):
100 rpsolve = A_.rpsolve
101 else:
102 rpsolve = id
103 if psolve is id and rpsolve is id:
104 M = IdentityOperator(shape=A.shape, dtype=A.dtype)
105 else:
106 M = LinearOperator(A.shape, matvec=psolve, rmatvec=rpsolve,
107 dtype=A.dtype)
108 else:
109 M = aslinearoperator(M)
110 if A.shape != M.shape:
111 raise ValueError('matrix and preconditioner have different shapes')
113 # set initial guess
114 if x0 is None:
115 x = zeros(N, dtype=xtype)
116 elif isinstance(x0, str):
117 if x0 == 'Mb': # use nonzero initial guess ``M @ b``
118 bCopy = b.copy()
119 x = M.matvec(bCopy)
120 else:
121 x = array(x0, dtype=xtype)
122 if not (x.shape == (N, 1) or x.shape == (N,)):
123 raise ValueError(f'shapes of A {A.shape} and '
124 f'x0 {x.shape} are incompatible')
125 x = x.ravel()
127 return A, M, x, b, postprocess