Esempio n. 1
0
def collapse_mul(bmat):
    '''A*B*C to single matrix'''
    # A0 * A1 * ...
    A, B = bmat.chain[0], bmat.chain[1:]

    if len(B) == 1:
        B = B[0]
        # Two matrices
        if is_petsc_mat(A) and is_petsc_mat(B):
            A_ = as_petsc(A)
            B_ = as_petsc(B)
            assert A_.size[1] == B_.size[0]
            C_ = PETSc.Mat()
            A_.matMult(B_, C_)

            return PETScMatrix(C_)
        # One of them is a number
        elif is_petsc_mat(A) and is_number(B):
            A_ = as_petsc(A)
            C_ = A_.copy()
            C_.scale(B)
            return PETScMatrix(C_)

        elif is_petsc_mat(B) and is_number(A):
            B_ = as_petsc(B)
            C_ = B_.copy()
            C_.scale(A)
            return PETScMatrix(C_)
        # Some compositions
        else:
            return collapse(collapse(A)*collapse(B))
    # Recurse
    else:
        return collapse_mul(collapse(A)*collapse(reduce(operator.mul, B)))                                    
Esempio n. 2
0
def collapse_mul(bmat):
    '''A*B*C to single matrix'''
    # A0 * A1 * ...
    A, B = bmat.chain[0], bmat.chain[1:]

    if len(B) == 1:
        B = B[0]
        # Two matrices
        if is_petsc_mat(A) and is_petsc_mat(B):
            A_ = as_petsc(A)
            B_ = as_petsc(B)
            assert A_.size[1] == B_.size[0]
            C_ = PETSc.Mat()
            A_.matMult(B_, C_)

            return PETScMatrix(C_)
        # One of them is a number
        elif is_petsc_mat(A) and is_number(B):
            A_ = as_petsc(A)
            C_ = A_.copy()
            C_.scale(B)
            return PETScMatrix(C_)

        elif is_petsc_mat(B) and is_number(A):
            B_ = as_petsc(B)
            C_ = B_.copy()
            C_.scale(A)
            return PETScMatrix(C_)
        # Some compositions
        else:
            return collapse(collapse(A) * collapse(B))
    # Recurse
    else:
        return collapse_mul(collapse(A) * collapse(reduce(operator.mul, B)))
Esempio n. 3
0
def collapse_sub(bmat):
    '''A - B to single matrix'''
    A, B = bmat.A, bmat.B
    # Base case
    if is_petsc_mat(A) and is_petsc_mat(B):
        A_ = as_petsc(A)
        B_ = as_petsc(B)
        assert A_.size == B_.size
        C_ = A_.copy()
        # C = A - B
        C_.axpy(-1., B_, PETSc.Mat.Structure.DIFFERENT)
        return PETScMatrix(C_)
    # Recurse
    return collapse_sub(collapse(A) - collapse(B))
Esempio n. 4
0
def collapse_sub(bmat):
    '''A - B to single matrix'''
    A, B = bmat.A, bmat.B
    # Base case
    if is_petsc_mat(A) and is_petsc_mat(B):
        A_ = as_petsc(A)
        B_ = as_petsc(B)
        assert A_.size == B_.size
        C_ = A_.copy()
        # C = A - B
        C_.axpy(-1., B_, PETSc.Mat.Structure.DIFFERENT)
        return PETScMatrix(C_)
    # Recurse
    return collapse_sub(collapse(A) - collapse(B))
Esempio n. 5
0
            def multTranspose(self, mat, x, y):
                '''y = A.T*x'''
                AT = block_transpose(self.A)

                y *= 0
                x_bvec = PETScVector(x)
                y_bvec = AT * x_bvec
                y.axpy(1., as_petsc(y_bvec))
Esempio n. 6
0
def collapse_tr(bmat):
    '''to Transpose'''
    # Base
    A = bmat.A
    if is_petsc_mat(A):
        A_ = as_petsc(A)
        C_ = PETSc.Mat()
        A_.transpose(C_)
        return PETScMatrix(C_)
    # Recurse
    return collapse_tr(collapse(bmat))
Esempio n. 7
0
def collapse_tr(bmat):
    '''to Transpose'''
    # Base
    A = bmat.A
    if is_petsc_mat(A):
        A_ = as_petsc(A)
        C_ = PETSc.Mat()
        A_.transpose(C_)
        return PETScMatrix(C_)
    # Recurse
    return collapse_tr(collapse(bmat))
Esempio n. 8
0
def setup_preconditioner(W, which, eps=None):
    '''
    This is a block diagonal preconditioner based on H1 x H^{-0.5}
    '''
    from xii.linalg.matrix_utils import as_petsc
    from numpy import hstack
    from petsc4py import PETSc
    from hsmg import HsNorm

    assert len(eps) == 2
    mu_value, lmbda_value = eps

    V, Q = W

    # H1
    u, v = TrialFunction(V), TestFunction(V)
    b00 = inner(grad(u), grad(v)) * dx + inner(u, v) * dx
    A = as_backend_type(assemble(b00))

    # Attach rigid deformations to A
    # Functions
    Z = [
        interpolate(Constant((1, 0)), V),
        interpolate(Constant((0, 1)), V),
        interpolate(Expression(('x[1]', '-x[0]'), degree=1), V)
    ]
    # The basis
    Z = VectorSpaceBasis([z.vector() for z in Z])
    Z.orthonormalize()
    A.set_nullspace(Z)
    A.set_near_nullspace(Z)

    A = as_petsc(A)
    # Setup the preconditioner in petsc
    pc = PETSc.PC().create()
    pc.setType(PETSc.PC.Type.HYPRE)
    pc.setOperators(A)
    # Other options
    opts = PETSc.Options()
    opts.setValue('pc_hypre_boomeramg_cycle_type', 'V')
    opts.setValue('pc_hypre_boomeramg_relax_type_all', 'symmetric-SOR/Jacobi')
    opts.setValue('pc_hypre_boomeramg_coarsen_type', 'Falgout')
    pc.setFromOptions()

    # Wrap for cbc.block
    B00 = BlockPC(pc)
    # The Q norm via spectral
    Qi = Q.sub(0).collapse()
    B11 = inverse(VectorizedOperator(HsNorm(Qi, s=-0.5), Q))

    return block_diag_mat([B00, B11])
Esempio n. 9
0
def block_mat_to_numpy(bmat):
    '''Collapsing block mat of matrices to scipy's bmat'''
    # A single matrix
    if is_petsc_mat(bmat):
        bmat = as_petsc(bmat)
        return csr_matrix(bmat.getValuesCSR()[::-1], shape=bmat.size)
    # 0
    if is_number(bmat):
        return None  # What bmat accepts
    # Recurse on blocks
    blocks = np.array(map(block_mat_to_numpy, bmat.blocks.flatten()))
    blocks = blocks.reshape(bmat.blocks.shape)
    # The bmat
    return numpy_block_mat(blocks).tocsr()
Esempio n. 10
0
def set_lg_map(mat):
    '''Set local-to-global-map on the matrix'''
    # NOTE; serial only - so we own everything but still sometimes we need
    # to tell that to petsc (especiialy when bcs are to be applied)

    if is_number(mat): return mat

    assert is_petsc_mat(mat) or isinstance(mat, block_mat), (type(mat))

    if isinstance(mat, block_mat):
        blocks = np.array(map(set_lg_map, mat.blocks.flatten())).reshape(mat.blocks.shape)
        return block_mat(blocks)

    comm = mpi_comm_world().tompi4py()
    # Work with matrix
    rowmap, colmap = range(mat.size(0)), range(mat.size(1))

    row_lgmap = PETSc.LGMap().create(rowmap, comm=comm)
    col_lgmap = PETSc.LGMap().create(colmap, comm=comm)

    as_petsc(mat).setLGMap(row_lgmap, col_lgmap)

    return mat
Esempio n. 11
0
def set_lg_map(mat):
    '''Set local-to-global-map on the matrix'''
    # NOTE; serial only - so we own everything but still sometimes we need
    # to tell that to petsc (especiialy when bcs are to be applied)

    if is_number(mat): return mat

    assert is_petsc_mat(mat) or isinstance(mat, block_mat), (type(mat))

    if isinstance(mat, block_mat):
        blocks = np.array(map(set_lg_map, mat.blocks.flatten())).reshape(mat.blocks.shape)
        return block_mat(blocks)

    comm = mpi_comm_world().tompi4py()
    # Work with matrix
    rowmap, colmap = range(mat.size(0)), range(mat.size(1))

    row_lgmap = PETSc.LGMap().create(rowmap, comm=comm)
    col_lgmap = PETSc.LGMap().create(colmap, comm=comm)

    as_petsc(mat).setLGMap(row_lgmap, col_lgmap)

    return mat
Esempio n. 12
0
def block_mat_to_numpy(bmat):
    '''Collapsing block mat of matrices to scipy's bmat'''
    # A single matrix
    if is_petsc_mat(bmat):
        bmat = as_petsc(bmat)
        return csr_matrix(bmat.getValuesCSR()[::-1], shape=bmat.size)
    # 0
    if is_number(bmat):
        return None  # What bmat accepts
    # Recurse on blocks
    blocks = np.array(map(block_mat_to_numpy, bmat.blocks.flatten()))
    blocks = blocks.reshape(bmat.blocks.shape)
    # The bmat
    return numpy_block_mat(blocks).tocsr()
Esempio n. 13
0
def nest(tensor, elim_zeros_tol=1E-15, W=None):
    '''Block mat/vec -> PETSc.Nest mat/vec'''
    # Convert block-vector
    if isinstance(tensor, block_vec):
        vecs = [as_petsc(bi) for bi in tensor]
        # FIXME: handle numbers
        vec = PETSc.Vec().createNest(vecs)
        vec.assemble()
        return vec

    # Convert block-matrix
    if isinstance(tensor, block_mat):
        # Maybe we have preconditioner
        if any(
                isinstance(block, precond)
                for block in tensor.blocks.flatten()):
            return

        nrows, ncols = tensor.blocks.shape
        A = [[None for j in range(ncols)] for i in range(nrows)]
        for i in range(nrows):
            for j in range(ncols):

                if isinstance(tensor[i][j], (int, float)):
                    # assert i != j, (i, j, tensor[i][j])
                    block = None
                else:
                    # Optimize for zeros and insert None
                    block = as_petsc(convert(tensor[i][j]))
                    if block.norm(2) < elim_zeros_tol:
                        block = None
                A[i][j] = block

        mat = PETSc.Mat().createNest(A)
        mat.assemble()
        return mat
Esempio n. 14
0
def pc_mat(pc, block):
    '''Set pc for (non-block) operator'''
    if isinstance(block, LU):
        pc.setType('lu')
        pc.setFactorPivot(1E-18)
        return block.A

    if isinstance(block, SUPERLU_LU):
        pc.setType('lu')
        pc.setFactorPivot(1E-18)
        pc.setFactorSolverType('superlu')
        return block.A

    if isinstance(block, AMG):
        pc.setType('hypre')
        return block.A

    if isinstance(block, Elasticity):
        pc.setType('gamg')
        return block.A

    # FIXME: Very add hoc support for sum, this should recursive
    if isinstance(block, block_add):
        this, that = block.A, block.B
        assert isinstance(this, precond) and isinstance(that, precond)

        pc.setType('composite')
        pc.setCompositeType(PETSc.PC.CompositeType.ADDITIVE)

        for sub, op in enumerate((this, that)):
            # Fake it
            pc_ = PETSc.PC().create()
            A = pc_mat(pc_, op)

            pc.addCompositePC(pc_.getType())

            pc_sub = pc.getCompositePC(sub)
            # Make it
            pc_mat(pc_sub, op)
            pc_sub.setOperators(as_petsc(A))

        mat = diagonal_matrix(op.A.size(0), 1)

        return mat

    assert False, type(block)
Esempio n. 15
0
def setup_preconditioner(W, which, eps=None):
    '''
    This is a block diagonal preconditioner based on H1 x L2 x H^{-0.5}
    '''
    from block.algebraic.petsc import LumpedInvDiag
    from xii.linalg.matrix_utils import as_petsc
    from numpy import hstack
    from petsc4py import PETSc
    from hsmg import HsNorm

    V, Q, Y = W

    # H1
    u, v = TrialFunction(V), TestFunction(V)
    b00 = inner(grad(u), grad(v)) * dx + inner(u, v) * dx
    # NOTE: since interpolation is broken with MINI I don't interpolate
    # here the RM basis to attach the vectros to matrix
    A = assemble(b00)

    A = as_petsc(A)
    # Setup the preconditioner in petsc
    pc = PETSc.PC().create()
    pc.setType(PETSc.PC.Type.HYPRE)
    pc.setOperators(A)
    # Other options
    opts = PETSc.Options()
    opts.setValue('pc_hypre_boomeramg_cycle_type', 'V')
    opts.setValue('pc_hypre_boomeramg_relax_type_all', 'symmetric-SOR/Jacobi')
    opts.setValue('pc_hypre_boomeramg_coarsen_type', 'Falgout')
    pc.setFromOptions()
    # Wrap for cbc.block
    B00 = BlockPC(pc)

    p, q = TrialFunction(Q), TestFunction(Q)
    B11 = LumpedInvDiag(assemble(inner(p, q) * dx))

    # The Y norm via spectral
    Yi = Y.sub(0).collapse()
    B22 = inverse(VectorizedOperator(HsNorm(Yi, s=-0.5), Y))

    return block_diag_mat([B00, B11, B22])
Esempio n. 16
0
def setup_preconditioner(W, which, eps=None):
    '''
    This is a block diagonal preconditioner based on H1 x L2 x H^{-0.5}
    '''
    from block.algebraic.petsc import LumpedInvDiag
    from xii.linalg.matrix_utils import as_petsc
    from numpy import hstack
    from petsc4py import PETSc
    from hsmg import HsNorm
    
    V, Q, Y = W
    
    # H1
    u, v = TrialFunction(V), TestFunction(V)
    b00 = inner(grad(u), grad(v))*dx + inner(u, v)*dx
    # NOTE: since interpolation is broken with MINI I don't interpolate
    # here the RM basis to attach the vectros to matrix
    A = assemble(b00)

    A = as_petsc(A)
    # Setup the preconditioner in petsc
    pc = PETSc.PC().create()
    pc.setType(PETSc.PC.Type.HYPRE)
    pc.setOperators(A)
    # Other options
    opts = PETSc.Options()
    opts.setValue('pc_hypre_boomeramg_cycle_type', 'V')
    opts.setValue('pc_hypre_boomeramg_relax_type_all',  'symmetric-SOR/Jacobi')
    opts.setValue('pc_hypre_boomeramg_coarsen_type', 'Falgout')  
    pc.setFromOptions()         
    # Wrap for cbc.block
    B00 = BlockPC(pc)

    p, q = TrialFunction(Q), TestFunction(Q)
    B11 = LumpedInvDiag(assemble(inner(p, q)*dx))
    
    # The Y norm via spectral
    Yi = Y.sub(0).collapse()
    B22 = inverse(VectorizedOperator(HsNorm(Yi, s=-0.5), Y))

    return block_diag_mat([B00, B11, B22])
Esempio n. 17
0
 def mult(self, mat, x, y):
     '''y = A*x'''
     y *= 0
     x_bvec = PETScVector(x)
     y_bvec = self.A * x_bvec
     y.axpy(1., as_petsc(y_bvec))
Esempio n. 18
0
 def matvec(self, x):
     y = self.create_vec(0)
     self.pc.apply(as_petsc(x), as_petsc(y))
     return y
Esempio n. 19
0
def pc_nest(pc, block_pc, Amat):
    '''Setup field split and its operators'''
    isets, jsets = Amat.getNestISs()
    # Sanity
    assert len(isets) == len(jsets)
    assert all(i.equal(j) for i, j in zip(isets, jsets)), [
        (i.array[[0, -1]], j.array[[0, -1]]) for i, j in zip(isets, jsets)
    ]

    # We target block matrices
    if len(isets) == 1:
        A = pc_mat(pc, block_pc[0][0])
        return as_petsc(A)

    grouped_isets = []
    # It may be that block_pc requires different grouping if indinces.
    # This is signaled by presence of RestrictionOperator
    if isinstance(block_pc, block_mul):
        Rt, block_pc, R = block_pc.chain
        assert Rt.A == R

        offsets = R.offsets

        for first, last in zip(R.offsets[:-1], R.offsets[1:]):
            if last - first == 1:
                grouped_isets.append(isets[first])
            else:
                group = isets[first]
                for i in range(first + 1, last):
                    group = group.union(isets[i])
                grouped_isets.append(group)
    else:
        grouped_isets = isets

    assert not isinstance(block_pc, block_mat) or set(
        block_pc.blocks.shape) == set((len(grouped_isets), ))

    pc.setFieldSplitIS(*[(str(i), iset)
                         for i, iset in enumerate(grouped_isets)])

    # The preconditioner will always be fieldsplit
    assert pc.getType() == 'fieldsplit'

    pc_ksps = pc.getFieldSplitSubKSP()

    nblocks, = set(block_pc.blocks.shape)

    # For now we can only do pure block_mats
    assert isinstance(block_pc, block_mat)
    # Consistency
    assert len(grouped_isets) == nblocks
    # ... and the have to be diagonal
    assert all(i == j or block_pc[i][j] == 0 for i in range(nblocks)
               for j in range(nblocks))

    Bmat = block_mat([[0 for i in range(nblocks)] for j in range(nblocks)])
    for i, pc_ksp in enumerate(pc_ksps):
        pc_ksp.setType('preonly')
        pci = pc_ksp.getPC()
        # Set individual preconds for blocks
        block = block_pc[i][i]
        mat = pc_mat(pci, block)

        Bmat[i][i] = mat
    # Return out for setOperators
    return nest(Bmat)