def convert(bmat, algorithm='numpy'): ''' Attempt to convert bmat to a PETSc(Matrix/Vector) object. If succed this is at worst a number. ''' # Block vec conversion if isinstance(bmat, block_vec): array = block_vec_to_numpy(bmat) vec = PETSc.Vec().createWithArray(array) vec.assemble() return PETScVector(vec) # Conversion of bmat is bit more involved because of the possibility # that some of the blocks are numbers or composition of matrix operations if isinstance(bmat, block_mat): # Create collpsed bmat row_sizes, col_sizes = bmat_sizes(bmat) nrows, ncols = len(row_sizes), len(col_sizes) indices = itertools.product(list(range(nrows)), list(range(ncols))) blocks = np.zeros((nrows, ncols), dtype='object') for block, (i, j) in zip(bmat.blocks.flatten(), indices): # This might is guaranteed to be matrix or number A = collapse(block) if is_number(A): # Diagonal matrices can be anything provided square if i == j and row_sizes[i] == col_sizes[j]: A = diagonal_matrix(row_sizes[i], A) else: # Offdiagonal can only be zero A = zero_matrix(row_sizes[i], col_sizes[j]) #else: # A = 0 # The converted block blocks[i, j] = A # Now every block is a matrix/number and we can make a monolithic thing bmat = block_mat(blocks) assert all(is_petsc_mat(block) or is_number(block) for block in bmat.blocks.flatten()) # Opt out of monolithic if not algorithm: set_lg_map(bmat) return bmat # Monolithic via numpy (fast) # Convert to numpy array = block_mat_to_numpy(bmat) # Constuct from numpy bmat = numpy_to_petsc(array) set_lg_map(bmat) return bmat # Try with a composite return collapse(bmat)
def collapse(self): '''Explicit matrix representation of the operator''' from xii.linalg.matrix_utils import diagonal_matrix, row_matrix from xii import ii_convert D = row_matrix(self.dual_basis) B = row_matrix(self.primal_basis) I = diagonal_matrix(B.size(1), 1.) return ii_convert(I - B.T * D)
def convert(bmat, algorithm='numpy'): ''' Attempt to convert bmat to a PETSc(Matrix/Vector) object. If succed this is at worst a number. ''' # Block vec conversion if isinstance(bmat, block_vec): array = block_vec_to_numpy(bmat) vec = PETSc.Vec().createWithArray(array) vec.assemble() return PETScVector(vec) # Conversion of bmat is bit more involved because of the possibility # that some of the blocks are numbers or composition of matrix operations if isinstance(bmat, block_mat): # Create collpsed bmat row_sizes, col_sizes = bmat_sizes(bmat) nrows, ncols = len(row_sizes), len(col_sizes) indices = itertools.product(range(nrows), range(ncols)) blocks = np.zeros((nrows, ncols), dtype='object') for block, (i, j) in zip(bmat.blocks.flatten(), indices): # This might is guaranteed to be matrix or number A = collapse(block) if is_number(A): # Diagonal matrices can be anything provided square if i == j and row_sizes[i] == col_sizes[j]: A = diagonal_matrix(row_sizes[i], A) else: # Offdiagonal can only be zero A = zero_matrix(row_sizes[i], col_sizes[j]) #else: # A = 0 # The converted block blocks[i, j] = A # Now every block is a matrix/number and we can make a monolithic thing bmat = block_mat(blocks) assert all(is_petsc_mat(block) or is_number(block) for block in bmat.blocks.flatten()) # Opt out of monolithic if not algorithm: return bmat # Monolithic via numpy (fast) # Convert to numpy array = block_mat_to_numpy(bmat) # Constuct from numpy return numpy_to_petsc(array) # Try with a composite return collapse(bmat)
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)