4
4
def block_kronecker(A, B):
5
5
"""Create the Kronecker (tensor) product of two matrices. The result is
6
returned as a product of two block matrices, (A x Ib) * (Ia x B), because
7
this will often limit the number of repeated applications of the inner
8
operators. However, it also means that A and B must be square since
9
otherwise the identities Ia and Ib are not defined.
6
returned as a product of two block matrices, (A x Ib) * (Ia x B), where Ia
7
and Ib are the appropriate identities (A=A*Ia, B=Ib*B). This will often
8
limit the number of repeated applications of the inner operators.
11
Note: If none of the parameters are of type block_mat, the composition A*B
12
is returned instead of two block matrices.
10
Note: If the A operator is a DOLFIN matrix and B is not a block_mat, A will
11
be expanded into a block_mat (one block per matrix entry). This will not
12
work in parallel. Apart from that, no blocks are expanded, i.e., only the
13
block matrices are expanded in the Kronecker product.
14
15
To form the Kronecker sum, you can extract (A x Ib) and (Ia x B) like this:
15
16
C,D = block_kronecker(A,B); sum=C+D
17
18
C,D = block_kronecker(A,B); inverse = some_invert(D)*ConjGrad(C)
19
20
from block_util import isscalar
23
if isinstance(A, dolfin.GenericMatrix) and not isinstance(B, block_mat):
24
A = block_mat(A.array())
25
assert isinstance(A, block_mat) or isinstance(B, block_mat)
21
27
if isinstance(B, block_mat):
23
C = block_mat.diag(A, n=n)
29
C = block_mat.diag(A, n=p)
27
33
if isinstance(A, block_mat):
29
35
if isinstance(B, block_mat):
36
print "Note: block_kronecker with two block matrices is probably buggy"
33
40
# A scalar can represent the scaled identity of any
34
41
# dimension, so no need to diagonal-expand it here. We
35
42
# don't do this check on the outer diagonal expansions,