Coverage for /usr/share/miniconda3/envs/dolfin/lib/python3.8/site-packages/block/block_scheme.py: 44%
73 statements
« prev ^ index » next coverage.py v7.2.1, created at 2023-03-20 13:03 +0000
« prev ^ index » next coverage.py v7.2.1, created at 2023-03-20 13:03 +0000
1from __future__ import division
3from builtins import range
4"""These classes are typically not used directly, but returned by a call to
5block_mat.scheme().
6"""
8from .block_base import block_base
10def block_jacobi(op):
11 from .block_mat import block_mat
12 m,n = op.blocks.shape
13 assert m==n
14 mat = block_mat(m,n)
15 for i in range(m):
16 mat[i,i] = op[i,i]
17 return mat
19class block_gs(block_base):
20 def __init__(self, op, reverse=False, truncated=False, symmetric=False, w=1.0):
21 self.op = op
22 self.range = list(range(len(op)))
23 if reverse: 23 ↛ 24line 23 didn't jump to line 24, because the condition on line 23 was never true
24 self.range.reverse()
25 if symmetric: 25 ↛ 27line 25 didn't jump to line 27, because the condition on line 25 was never false
26 self.matvec = self.matvec_symmetric
27 elif truncated:
28 self.matvec = self.matvec_truncated
29 else:
30 self.matvec = self.matvec_full
31 self.weight = w
33 def sor_weighting(self, b, x):
34 if self.weight != 1: 34 ↛ 35line 34 didn't jump to line 35, because the condition on line 34 was never true
35 for i in self.range:
36 x[i] *= self.weight
37 x[i] += (1-self.weight) * b[i]
39 def matvec_full(self, b):
40 x = b.copy()
41 for i in self.range:
42 for j in self.range:
43 if j==i:
44 continue
45 if self.op[i,j]:
46 x[i] -= self.op[i,j]*x[j]
47 x[i] = self.op[i,i]*x[i]
48 self.sor_weighting(b, x)
49 return x
51 def matvec_truncated(self, b):
52 x = b.copy()
53 for k,i in enumerate(self.range):
54 for j in self.range[:k]:
55 if self.op[i,j]:
56 x[i] -= self.op[i,j]*x[j]
57 x[i] = self.op[i,i]*x[i]
58 self.sor_weighting(b, x)
59 return x
61 def matvec_symmetric(self, b):
62 x = b.copy()
63 for k,i in enumerate(self.range):
64 for j in self.range[:k]:
65 if self.op[i,j]: 65 ↛ 64line 65 didn't jump to line 64, because the condition on line 65 was never false
66 x[i] -= self.op[i,j]*x[j]
67 x[i] = self.op[i,i]*x[i]
68 rev_range = list(reversed(self.range))
69 for k,i in enumerate(rev_range):
70 for j in rev_range[:k]:
71 if self.op[i,j]: 71 ↛ 70line 71 didn't jump to line 70, because the condition on line 71 was never false
72 x[i] -= self.op[i,i]*self.op[i,j]*x[j]
73 self.sor_weighting(b, x)
74 return x
76def blockscheme(op, scheme='jacobi', **kwargs):
77 scheme = scheme.lower()
78 if scheme == 'jacobi' or scheme == 'jac': 78 ↛ 79line 78 didn't jump to line 79, because the condition on line 78 was never true
79 return block_jacobi(op)
81 if scheme in ('gauss-seidel', 'gs', 'sor'): 81 ↛ 82line 81 didn't jump to line 82, because the condition on line 81 was never true
82 return block_gs(op, **kwargs)
84 if scheme in ('symmetric gauss-seidel', 'sgs', 'ssor'): 84 ↛ 87line 84 didn't jump to line 87, because the condition on line 84 was never false
85 return block_gs(op, symmetric=True, **kwargs)
87 if scheme in ('truncated gauss-seidel', 'tgs', 'tsor'):
88 return block_gs(op, truncated=True, **kwargs)
90 raise TypeError('unknown scheme "%s"'%scheme)