Coverage for /usr/share/miniconda3/envs/dolfin/lib/python3.8/site-packages/block/iterative/minres2.py: 8%

64 statements  

« prev     ^ index     » next       coverage.py v7.2.1, created at 2023-03-20 13:03 +0000

1 

2""" 

3@license: Copyright (C) 2006 

4Author: Gunnar Staff 

5 

6Simula Research Laboratory AS 

7 

8This file is part of PyCC. 

9 

10PyCC free software; you can redistribute it and/or modify 

11it under the terms of the GNU General Public License as published by 

12the Free Software Foundation; either version 2 of the License, or 

13(at your option) any later version. 

14 

15PyCC is distributed in the hope that it will be useful, 

16but WITHOUT ANY WARRANTY; without even the implied warranty of 

17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

18GNU General Public License for more details. 

19 

20You should have received a copy of the GNU General Public License 

21along with PyFDM; if not, write to the Free Software 

22Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

23 

24 

25MinRes: A generic implementation of the Minimum Residual method. 

26""" 

27 

28 

29MinResError = "Error in MinRes" 

30 

31import numpy as _n #/numarray 

32#from Utils import _n,inner 

33from math import sqrt,fabs 

34 

35def inner(u,v): 

36 """Compute innerproduct of u and v. 

37 It is not computed here, we just check type of operands and 

38 call a suitable innerproduct method""" 

39 

40 if isinstance(u,_n.ndarray): 

41 # assume both are numarrays: 

42 return _n.dot(u,v) 

43 else: 

44 # assume that left operand implements inner 

45 return u.inner(v) 

46 

47 

48def minres(B, A, x, b, tolerance, maxiter, progress, relativeconv=False, rit_=1, callback=None): 

49 """ 

50 precondMinRes(B,A,x,b): Solve Ax = b with the preconditioned minimum 

51 residual method. 

52 

53 @param B: Preconditioner supporting the __mul__ operator for operating on 

54 x. B must be symmetric positive definite 

55 

56 @param A: Matrix or discrete operator. Must support A*x to operate on x. 

57 A must be symmetric, but may be indefinite. 

58 

59 @param x: Anything that A can operate on, as well as support inner product 

60 and multiplication/addition/subtraction with scalar and something of the 

61 same type 

62 

63 @param b: Right-hand side, probably the same type as x. 

64 

65 @param tolerance: Convergence criterion 

66 @type tolerance: float 

67 

68 @param relativeconv: Control relative vs. absolute convergence criterion. 

69 That is, if relativeconv is True, ||r||_2/||r_init||_2 is used as 

70 convergence criterion, else just ||r||_2 is used. Actually ||r||_2^2 is 

71 used, since that save a few cycles. 

72 

73 @type relativeconv: bool 

74 

75 @return: the solution x. 

76 

77 DESCRIPTION: 

78 

79 The method implements a left preconditioned Minimum residual method 

80 for symmetric indefinite linear systems. The preconditioning 

81 operator has to be symmetric and positive definite. 

82 

83 The minimum residual method solves systems of the form BAx=Bb, 

84 where A is symmetric indefinite and B is symmetric positive 

85 definite. The linear system is symmetric with respect to the inner 

86 product $ \((\cdot,\cdot)_B = (B^{-1}\cdot,\cdot)\). The iterate 

87 x_k is determined by minimization of the norm of the residual $ \[ 

88 \|B(b - A y)\|_B \] over the Krylov space $ \(span\{Bb, BABb, 

89 \ldots, (BA)^{k-1}Bb\}\). $ Here the norm is defined by the inner 

90 product \((\cdot,\cdot)_B\). 

91 

92 The default convergence monitor is $ \[ \rho_k = \|B(b - A x_k)\|_B 

93 = (B(b - A x_k), b - A x_k).\] $ The residual \(b - A x_k\) is not 

94 computed during the iteration, hence a direct computation of this 

95 quantity reqire an additional matrix vector product. In the 

96 algorithm it is computed recursively. Unfortunately this 

97 computations accumulates error and it may be necessary to compute 

98 the exact residual every update frequency iteration. 

99 

100 

101 

102 """ 

103 

104 callback_converged = False 

105 

106 residuals = [] 

107 

108 rit = rit_ 

109 d = A*x 

110 r = b - d 

111 s = B*r 

112 rho = inner(r,s) 

113 

114 

115 po = s.copy() 

116 qo = A*po 

117 

118 p = r.copy() 

119 p *= 0.0 

120 q = p.copy() 

121 u = p.copy() 

122 

123 if relativeconv: 

124 tolerance *= sqrt(rho) 

125 

126 residuals.append(sqrt(rho)) 

127 iter = 0 

128 #print "tolerance ", tolerance 

129 # Alloc w 

130 #while sqrt(inner(r,r)) > tolerance:# and iter<maxiter: 

131 while (sqrt(rho) > tolerance and not callback_converged) and iter < maxiter: 

132 #print "iter, sqrt(inner(r,r))", iter, sqrt(inner(r,r)) 

133 uo = B*qo 

134 gamma = sqrt(inner(qo,uo)) 

135 gammai= 1.0/gamma 

136 

137 # Do a swap 

138 tmp = po 

139 po = p 

140 p = tmp 

141 p *= gammai 

142 

143 tmp = qo 

144 qo = q 

145 q = tmp 

146 q *= gammai 

147 

148 tmp = uo 

149 uo = u 

150 u = tmp 

151 u *= gammai 

152 

153 alpha = inner(s,q) 

154 x += alpha*p 

155 s -= alpha*u 

156 

157 if iter%rit==0: 

158 r = b - A*x 

159 rho = inner(r,s) 

160 else: 

161 rho -= alpha*alpha 

162 rho = fabs(rho) 

163 

164 t = A*u 

165 alpha = inner(t,u) 

166 beta = inner(t,uo) 

167 

168 po *= -beta 

169 po -= alpha*p 

170 po += u 

171 

172 # update qo 

173 #po-=beta*po 

174 qo *= -beta 

175 qo -= alpha*q 

176 qo += t 

177 

178 

179 residuals.append(sqrt(rho)) 

180 #print "sqrt(rho) ", sqrt(rho) 

181 

182 # Call user provided callback with solution 

183 if callable(callback): 

184 callback_converged = callback(k=iter, x=x, r=sqrt(rho)) #r=r) 

185 

186 iter += 1 

187 #print "r",iter,"=",sqrt(inner(r,r)) 

188 #print "precondMinRes finished, iter: %d, ||e||=%e" % (iter,sqrt(inner(r,r))) 

189 return x,residuals, [], [] 

190